compiler: Check qualified name byte construction

72388a52f94cc49a52c049e5c80e62ee7d6c760588bdf8c43c8e83bce85f66fc
Alexis Sellier committed ago 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 {