compiler: Check qualified name byte construction
72388a52f94cc49a52c049e5c80e62ee7d6c760588bdf8c43c8e83bce85f66fc
1 parent
db1f48d4
lib/std/lang/il.rad
+15 -12
| 60 | 60 | ||
| 61 | 61 | export mod printer; |
|
| 62 | 62 | export mod binary; |
|
| 63 | 63 | @test mod tests; |
|
| 64 | 64 | ||
| 65 | - | use std::mem; |
|
| 66 | 65 | use std::lang::alloc; |
|
| 67 | 66 | ||
| 68 | 67 | /// Source location for debug info. |
|
| 69 | 68 | /// |
|
| 70 | 69 | /// Associates an IL instruction with its originating source module and |
| 83 | 82 | /// Separator for qualified symbol names. |
|
| 84 | 83 | export constant PATH_SEPARATOR: *[u8] = "::"; |
|
| 85 | 84 | ||
| 86 | 85 | /// Format a qualified symbol name: `pkg::mod::path::name`. |
|
| 87 | 86 | export unsafe fn formatQualifiedName(arena: &mut alloc::Arena, path: &[*[u8]], name: *[u8]) -> *[u8] { |
|
| 88 | - | let mut totalLen: u32 = name.len; |
|
| 89 | - | for segment in path { |
|
| 90 | - | set totalLen += segment.len + PATH_SEPARATOR.len; |
|
| 91 | - | } |
|
| 92 | - | let buf = try! alloc::allocSlice(arena, 1, 1, totalLen) as *mut [u8]; |
|
| 93 | - | let mut pos: u32 = 0; |
|
| 87 | + | return qualifiedName(path, name, alloc::arenaAllocator(arena)); |
|
| 88 | + | } |
|
| 94 | 89 | ||
| 90 | + | /// Assemble qualified name bytes in owned storage. |
|
| 91 | + | fn qualifiedName(path: &[*[u8]], name: &[u8], allocator: alloc::Allocator) -> *[u8] { |
|
| 92 | + | let mut buf: *mut [u8] = &mut []; |
|
| 95 | 93 | for segment in path { |
|
| 96 | - | set pos += try! mem::copy(&mut buf[pos..], segment); |
|
| 97 | - | set pos += try! mem::copy(&mut buf[pos..], PATH_SEPARATOR); |
|
| 94 | + | for byte in segment { |
|
| 95 | + | buf.append(byte, allocator); |
|
| 96 | + | } |
|
| 97 | + | for byte in PATH_SEPARATOR { |
|
| 98 | + | buf.append(byte, allocator); |
|
| 99 | + | } |
|
| 98 | 100 | } |
|
| 99 | - | try! mem::copy(&mut buf[pos..], name); |
|
| 100 | - | ||
| 101 | - | return &buf[..totalLen]; |
|
| 101 | + | for byte in name { |
|
| 102 | + | buf.append(byte, allocator); |
|
| 103 | + | } |
|
| 104 | + | return buf; |
|
| 102 | 105 | } |
|
| 103 | 106 | ||
| 104 | 107 | /////////// |
|
| 105 | 108 | // Types // |
|
| 106 | 109 | /////////// |
lib/std/lang/il/tests.rad
+15 -0
| 1 | 1 | //! Tests for RIL formatting and source register iteration. |
|
| 2 | 2 | ||
| 3 | 3 | use std::testing; |
|
| 4 | 4 | use std::lang::sexpr; |
|
| 5 | 5 | use std::lang::il::printer; |
|
| 6 | + | use std::lang::alloc; |
|
| 7 | + | ||
| 8 | + | /// Qualified names preserve empty segments and exact separator placement. |
|
| 9 | + | @test unsafe fn testQualifiedNames() throws (testing::TestError) { |
|
| 10 | + | static STORAGE: [u8; 2048] = [0; 2048]; |
|
| 11 | + | let mut arena = alloc::new(&mut STORAGE[..]); |
|
| 12 | + | try testing::expectBytesEq(super::formatQualifiedName(&mut arena, &[], ""), ""); |
|
| 13 | + | try testing::expectBytesEq(super::formatQualifiedName(&mut arena, &[], "method"), "method"); |
|
| 14 | + | let path = ["package", "module", "Type"]; |
|
| 15 | + | try testing::expectBytesEq(super::formatQualifiedName(&mut arena, &path[..], "method"), "package::module::Type::method"); |
|
| 16 | + | let empty = ["", "Type", ""]; |
|
| 17 | + | try testing::expectBytesEq(super::formatQualifiedName(&mut arena, &empty[..], ""), "::Type::::"); |
|
| 18 | + | let table = ["vtable", "Widget"]; |
|
| 19 | + | try testing::expectBytesEq(super::formatQualifiedName(&mut arena, &table[..], "Printable"), "vtable::Widget::Printable"); |
|
| 20 | + | } |
|
| 6 | 21 | ||
| 7 | 22 | /// Check one instruction between the function header and closing delimiter. |
|
| 8 | 23 | unsafe fn checkPrintedInstruction(instr: super::Instr, expected: &[u8]) throws (testing::TestError) { |
|
| 9 | 24 | let mut instructions = [instr]; |
|
| 10 | 25 | let blocks = [super::Block { |