Require `&` for re-slicing
18a8980798c23a67d02435bc2473205eacabc41dff188e5f28be3be9965c1732
Like arrays, slicing a slice now requires an explicit address-of operator. This enables taking an immutable slice from a mutable one.
1 parent
9aad4c31
compiler/radiance.rad
+5 -5
| 534 | 534 | /// Synthesize a `testing::test("mod", "name", mod::fn)` call for one test. |
|
| 535 | 535 | fn synthTestCall(arena: *mut ast::NodeArena, desc: *TestDesc) -> *ast::Node { |
|
| 536 | 536 | let callee = synthScopeAccess(arena, &["testing", "test"]); |
|
| 537 | 537 | let modStr = il::formatQualifiedName( |
|
| 538 | 538 | &mut arena.arena, |
|
| 539 | - | desc.modPath[..desc.modPath.len - 1], |
|
| 539 | + | &desc.modPath[..desc.modPath.len - 1], |
|
| 540 | 540 | desc.modPath[desc.modPath.len - 1] |
|
| 541 | 541 | ); |
|
| 542 | 542 | let modArg = ast::synthNode(arena, ast::NodeValue::String(modStr)); |
|
| 543 | 543 | let nameArg = ast::synthNode(arena, ast::NodeValue::String(desc.fnName)); |
|
| 544 | 544 |
| 721 | 721 | for i in 0..entries.len { |
|
| 722 | 722 | let entry = &entries[i]; |
|
| 723 | 723 | let modEntry = module::get(graph, entry.moduleId) else { |
|
| 724 | 724 | panic "writeDebugInfo: module not found for debug entry"; |
|
| 725 | 725 | }; |
|
| 726 | - | pos = pos + try! mem::copy(buf[pos..], @sliceOf(&entry.pc as *u8, 4)); |
|
| 727 | - | pos = pos + try! mem::copy(buf[pos..], @sliceOf(&entry.offset as *u8, 4)); |
|
| 728 | - | pos = pos + try! mem::copy(buf[pos..], modEntry.filePath); |
|
| 726 | + | pos = pos + try! mem::copy(&mut buf[pos..], @sliceOf(&entry.pc as *u8, 4)); |
|
| 727 | + | pos = pos + try! mem::copy(&mut buf[pos..], @sliceOf(&entry.offset as *u8, 4)); |
|
| 728 | + | pos = pos + try! mem::copy(&mut buf[pos..], modEntry.filePath); |
|
| 729 | 729 | ||
| 730 | 730 | buf[pos] = 0; |
|
| 731 | 731 | pos = pos + 1; |
|
| 732 | 732 | } |
|
| 733 | - | try writeDataWithExt(buf[..pos], basePath, DEBUG_EXT); |
|
| 733 | + | try writeDataWithExt(&buf[..pos], basePath, DEBUG_EXT); |
|
| 734 | 734 | } |
|
| 735 | 735 | ||
| 736 | 736 | /// Run the resolver on the parsed modules. |
|
| 737 | 737 | fn runResolver(ctx: *mut CompileContext, nodeCount: u32) -> resolver::Resolver throws (Error) { |
|
| 738 | 738 | let mut mainArena = alloc::new(&mut MAIN_ARENA[..]); |
lib/std/arch/rv64.rad
+7 -7
| 241 | 241 | for _ in 0..v.count { |
|
| 242 | 242 | match v.item { |
|
| 243 | 243 | case il::DataItem::Val { typ, val } => { |
|
| 244 | 244 | let size = il::typeSize(typ); |
|
| 245 | 245 | let valPtr = &val as *u8; |
|
| 246 | - | try! mem::copy(buf[offset..], @sliceOf(valPtr, size)); |
|
| 246 | + | try! mem::copy(&mut buf[offset..], @sliceOf(valPtr, size)); |
|
| 247 | 247 | offset = offset + size; |
|
| 248 | 248 | }, |
|
| 249 | 249 | case il::DataItem::Sym(name) => { |
|
| 250 | 250 | let addr = lookupDataSymAddr(dataSyms, name) else { |
|
| 251 | 251 | panic "emitSection: data symbol not found"; |
| 256 | 256 | let lo: u32 = addr; |
|
| 257 | 257 | let hi: u32 = 0; |
|
| 258 | 258 | let loPtr = &lo as *u8; |
|
| 259 | 259 | let hiPtr = &hi as *u8; |
|
| 260 | 260 | ||
| 261 | - | try! mem::copy(buf[offset..], @sliceOf(loPtr, 4)); |
|
| 262 | - | try! mem::copy(buf[(offset + 4)..], @sliceOf(hiPtr, 4)); |
|
| 261 | + | try! mem::copy(&mut buf[offset..], @sliceOf(loPtr, 4)); |
|
| 262 | + | try! mem::copy(&mut buf[(offset + 4)..], @sliceOf(hiPtr, 4)); |
|
| 263 | 263 | ||
| 264 | 264 | offset = offset + 8; |
|
| 265 | 265 | }, |
|
| 266 | 266 | case il::DataItem::Fn(name) => { |
|
| 267 | 267 | let addr = codeBase + labels::funcOffset(fnLabels, name) as u32; |
|
| 268 | 268 | let lo: u32 = addr; |
|
| 269 | 269 | let hi: u32 = 0; |
|
| 270 | 270 | let loPtr = &lo as *u8; |
|
| 271 | 271 | let hiPtr = &hi as *u8; |
|
| 272 | 272 | ||
| 273 | - | try! mem::copy(buf[offset..], @sliceOf(loPtr, 4)); |
|
| 274 | - | try! mem::copy(buf[(offset + 4)..], @sliceOf(hiPtr, 4)); |
|
| 273 | + | try! mem::copy(&mut buf[offset..], @sliceOf(loPtr, 4)); |
|
| 274 | + | try! mem::copy(&mut buf[(offset + 4)..], @sliceOf(hiPtr, 4)); |
|
| 275 | 275 | ||
| 276 | 276 | offset = offset + 8; |
|
| 277 | 277 | }, |
|
| 278 | 278 | case il::DataItem::Str(s) => { |
|
| 279 | - | try! mem::copy(buf[offset..], s); |
|
| 279 | + | try! mem::copy(&mut buf[offset..], s); |
|
| 280 | 280 | offset = offset + s.len; |
|
| 281 | 281 | }, |
|
| 282 | 282 | case il::DataItem::Undef => { |
|
| 283 | 283 | buf[offset] = 0; |
|
| 284 | 284 | offset = offset + 1; |
| 331 | 331 | emit::emit(&mut e, encode::nop()); // Placeholder for two-instruction jump. |
|
| 332 | 332 | emit::emit(&mut e, encode::nop()); // |
|
| 333 | 333 | } |
|
| 334 | 334 | ||
| 335 | 335 | // Generate code for all functions. |
|
| 336 | - | let dataSyms = storage.dataSyms[..dataSymCount]; |
|
| 336 | + | let dataSyms = &storage.dataSyms[..dataSymCount]; |
|
| 337 | 337 | ||
| 338 | 338 | for i in 0..program.fns.len { |
|
| 339 | 339 | let func = program.fns[i]; |
|
| 340 | 340 | if not func.isExtern { |
|
| 341 | 341 | let checkpoint = alloc::save(arena); |
lib/std/arch/rv64/emit.rad
+3 -3
| 657 | 657 | // Code Access // |
|
| 658 | 658 | ////////////////// |
|
| 659 | 659 | ||
| 660 | 660 | /// Get emitted code as a slice. |
|
| 661 | 661 | pub fn getCode(e: *Emitter) -> *[u32] { |
|
| 662 | - | return e.code[..e.codeLen]; |
|
| 662 | + | return &e.code[..e.codeLen]; |
|
| 663 | 663 | } |
|
| 664 | 664 | ||
| 665 | 665 | /// Get function addresses for printing. |
|
| 666 | 666 | pub fn getFuncs(e: *Emitter) -> *[FuncAddr] { |
|
| 667 | - | return e.funcs[..e.funcsLen]; |
|
| 667 | + | return &e.funcs[..e.funcsLen]; |
|
| 668 | 668 | } |
|
| 669 | 669 | ||
| 670 | 670 | /// Record a debug entry mapping the current PC to a source location. |
|
| 671 | 671 | /// Deduplicates consecutive entries with the same location. |
|
| 672 | 672 | pub fn recordSrcLoc(e: *mut Emitter, loc: il::SrcLoc) { |
| 690 | 690 | e.debugEntriesLen = e.debugEntriesLen + 1; |
|
| 691 | 691 | } |
|
| 692 | 692 | ||
| 693 | 693 | /// Get debug entries as a slice. |
|
| 694 | 694 | pub fn getDebugEntries(e: *Emitter) -> *[DebugEntry] { |
|
| 695 | - | return e.debugEntries[..e.debugEntriesLen]; |
|
| 695 | + | return &e.debugEntries[..e.debugEntriesLen]; |
|
| 696 | 696 | } |
lib/std/arch/rv64/printer.rad
+1 -1
| 343 | 343 | pub fn printCode(pkgName: *[u8], code: *[u32], funcs: *[emit::FuncAddr], arena: *mut alloc::Arena, buf: *mut [u8]) -> *[u8] { |
|
| 344 | 344 | let mut pos: u32 = 0; |
|
| 345 | 345 | let mut out = sexpr::Output::Buffer { buf, pos: &mut pos }; |
|
| 346 | 346 | printCodeTo(&mut out, pkgName, code, funcs, arena); |
|
| 347 | 347 | ||
| 348 | - | return buf[..pos]; |
|
| 348 | + | return &buf[..pos]; |
|
| 349 | 349 | } |
lib/std/arch/rv64/tests/cond.match.guard.regalloc.rad
+2 -2
| 23 | 23 | let mut out: *[*[u8]] = &[]; |
|
| 24 | 24 | ||
| 25 | 25 | match node.kind { |
|
| 26 | 26 | case Kind::Name(name) if name.len > 0 => { |
|
| 27 | 27 | buf[0] = name; |
|
| 28 | - | out = buf[..1]; |
|
| 28 | + | out = &buf[..1]; |
|
| 29 | 29 | } |
|
| 30 | 30 | case Kind::Pair { a, b } => { |
|
| 31 | - | out = buf[..1]; |
|
| 31 | + | out = &buf[..1]; |
|
| 32 | 32 | } |
|
| 33 | 33 | else => {} |
|
| 34 | 34 | } |
|
| 35 | 35 | return out; |
|
| 36 | 36 | } |
lib/std/arch/rv64/tests/const.slice.param.rad
+2 -2
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | 9 | @default fn main() -> i32 { |
|
| 10 | 10 | let all: *[i32] = &DATA[..]; |
|
| 11 | 11 | let head: i32 = sumPair(all); |
|
| 12 | - | let tail: i32 = sumPair(all[2..]); |
|
| 13 | - | let mid: i32 = sumPair(all[1..3]); |
|
| 12 | + | let tail: i32 = sumPair(&all[2..]); |
|
| 13 | + | let mid: i32 = sumPair(&all[1..3]); |
|
| 14 | 14 | ||
| 15 | 15 | return head + tail + mid; |
|
| 16 | 16 | } |
lib/std/arch/rv64/tests/prog.tokenizer.rad
+1 -1
| 457 | 457 | return 2; |
|
| 458 | 458 | } |
|
| 459 | 459 | ||
| 460 | 460 | // Count number tokens using for-in. |
|
| 461 | 461 | let mut numCount: u32 = 0; |
|
| 462 | - | let slice = tokenBuf[0..list.count]; |
|
| 462 | + | let slice = &tokenBuf[0..list.count]; |
|
| 463 | 463 | for tok in slice { |
|
| 464 | 464 | match tok { |
|
| 465 | 465 | case Token::Number(_) => { |
|
| 466 | 466 | numCount = numCount + 1; |
|
| 467 | 467 | } |
lib/std/arch/rv64/tests/slice.subslice.rad
+6 -6
| 1 | 1 | //! returns: 42 |
|
| 2 | 2 | ||
| 3 | 3 | fn testBasicSubslice() -> bool { |
|
| 4 | 4 | let arr: [i32; 5] = [10, 20, 30, 40, 50]; |
|
| 5 | 5 | let slice: *[i32] = &arr[..]; // Full slice [10, 20, 30, 40, 50] |
|
| 6 | - | let subslice: *[i32] = slice[1..4]; // Sub-slice [20, 30, 40] |
|
| 6 | + | let subslice: *[i32] = &slice[1..4]; // Sub-slice [20, 30, 40] |
|
| 7 | 7 | ||
| 8 | 8 | return subslice[0] == 20 and subslice[1] == 30 and subslice[2] == 40; |
|
| 9 | 9 | } |
|
| 10 | 10 | ||
| 11 | 11 | fn testNestedSubslice() -> bool { |
|
| 12 | 12 | let arr: [i32; 6] = [100, 200, 300, 400, 500, 600]; |
|
| 13 | 13 | let slice1: *[i32] = &arr[1..5]; // [200, 300, 400, 500] |
|
| 14 | - | let slice2: *[i32] = slice1[1..3]; // [300, 400] |
|
| 15 | - | let slice3: *[i32] = slice2[0..1]; // [300] |
|
| 14 | + | let slice2: *[i32] = &slice1[1..3]; // [300, 400] |
|
| 15 | + | let slice3: *[i32] = &slice2[0..1]; // [300] |
|
| 16 | 16 | ||
| 17 | 17 | return slice3[0] == 300; |
|
| 18 | 18 | } |
|
| 19 | 19 | ||
| 20 | 20 | fn testSubsliceLength() -> bool { |
|
| 21 | 21 | let arr: [i32; 4] = [1, 2, 3, 4]; |
|
| 22 | 22 | let slice: *[i32] = &arr[..]; |
|
| 23 | - | let subslice: *[i32] = slice[1..3]; |
|
| 23 | + | let subslice: *[i32] = &slice[1..3]; |
|
| 24 | 24 | ||
| 25 | 25 | return subslice.len == 2; |
|
| 26 | 26 | } |
|
| 27 | 27 | ||
| 28 | 28 | fn testEdgeCases() -> bool { |
|
| 29 | 29 | let arr: [i32; 3] = [7, 8, 9]; |
|
| 30 | 30 | let slice: *[i32] = &arr[..]; |
|
| 31 | 31 | ||
| 32 | 32 | // Test single element subslice |
|
| 33 | - | let single: *[i32] = slice[1..2]; |
|
| 33 | + | let single: *[i32] = &slice[1..2]; |
|
| 34 | 34 | if (single[0] != 8 or single.len != 1) { |
|
| 35 | 35 | return false; |
|
| 36 | 36 | } |
|
| 37 | 37 | ||
| 38 | 38 | // Test empty subslice |
|
| 39 | - | let empty: *[i32] = slice[2..2]; |
|
| 39 | + | let empty: *[i32] = &slice[2..2]; |
|
| 40 | 40 | if (empty.len != 0) { |
|
| 41 | 41 | return false; |
|
| 42 | 42 | } |
|
| 43 | 43 | return true; |
|
| 44 | 44 | } |
lib/std/fmt.rad
+6 -6
| 32 | 32 | x = x / 10; |
|
| 33 | 33 | } |
|
| 34 | 34 | } |
|
| 35 | 35 | // Return the slice from the start of the written number to |
|
| 36 | 36 | // the end of the buffer. |
|
| 37 | - | return buffer[i..]; |
|
| 37 | + | return &buffer[i..]; |
|
| 38 | 38 | } |
|
| 39 | 39 | ||
| 40 | 40 | /// Format a i32 by writing it to the provided buffer. |
|
| 41 | 41 | pub fn formatI32(val: i32, buffer: *mut [u8]) -> *[u8] { |
|
| 42 | 42 | debug::assert(buffer.len >= I32_STR_LEN); |
| 65 | 65 | if neg { |
|
| 66 | 66 | i = i - 1; |
|
| 67 | 67 | buffer[i] = '-'; |
|
| 68 | 68 | } |
|
| 69 | 69 | } |
|
| 70 | - | return buffer[i..]; |
|
| 70 | + | return &buffer[i..]; |
|
| 71 | 71 | } |
|
| 72 | 72 | ||
| 73 | 73 | /// Format a u64 by writing it to the provided buffer. |
|
| 74 | 74 | pub fn formatU64(val: u64, buffer: *mut [u8]) -> *[u8] { |
|
| 75 | 75 | debug::assert(buffer.len >= U64_STR_LEN); |
| 85 | 85 | i = i - 1; |
|
| 86 | 86 | buffer[i] = ('0' + (x % 10) as u8); |
|
| 87 | 87 | x = x / 10; |
|
| 88 | 88 | } |
|
| 89 | 89 | } |
|
| 90 | - | return buffer[i..]; |
|
| 90 | + | return &buffer[i..]; |
|
| 91 | 91 | } |
|
| 92 | 92 | ||
| 93 | 93 | /// Format a i64 by writing it to the provided buffer. |
|
| 94 | 94 | pub fn formatI64(val: i64, buffer: *mut [u8]) -> *[u8] { |
|
| 95 | 95 | debug::assert(buffer.len >= I64_STR_LEN); |
| 115 | 115 | if neg { |
|
| 116 | 116 | i = i - 1; |
|
| 117 | 117 | buffer[i] = '-'; |
|
| 118 | 118 | } |
|
| 119 | 119 | } |
|
| 120 | - | return buffer[i..]; |
|
| 120 | + | return &buffer[i..]; |
|
| 121 | 121 | } |
|
| 122 | 122 | ||
| 123 | 123 | /// Format a i8 by writing it to the provided buffer. |
|
| 124 | 124 | pub fn formatI8(val: i8, buffer: *mut [u8]) -> *[u8] { |
|
| 125 | 125 | return formatI32(val as i32, buffer); |
| 142 | 142 | ||
| 143 | 143 | /// Format a bool by writing it to the provided buffer. |
|
| 144 | 144 | pub fn formatBool(val: bool, buffer: *mut [u8]) -> *[u8] { |
|
| 145 | 145 | if val { |
|
| 146 | 146 | try! mem::copy(buffer, "true"); |
|
| 147 | - | return buffer[..4]; |
|
| 147 | + | return &buffer[..4]; |
|
| 148 | 148 | } else { |
|
| 149 | 149 | try! mem::copy(buffer, "false"); |
|
| 150 | - | return buffer[..5]; |
|
| 150 | + | return &buffer[..5]; |
|
| 151 | 151 | } |
|
| 152 | 152 | } |
lib/std/io.rad
+2 -2
| 39 | 39 | ||
| 40 | 40 | pub fn readToEnd(buf: *mut [u8]) -> *[u8] { |
|
| 41 | 41 | let mut total: u32 = 0; |
|
| 42 | 42 | ||
| 43 | 43 | while total < buf.len { |
|
| 44 | - | let chunk: *mut [u8] = buf[total..]; |
|
| 44 | + | let chunk: *mut [u8] = &mut buf[total..]; |
|
| 45 | 45 | let n: u32 = read(chunk); |
|
| 46 | 46 | ||
| 47 | 47 | if n == 0 { |
|
| 48 | 48 | break; |
|
| 49 | 49 | } |
| 51 | 51 | total = buf.len; |
|
| 52 | 52 | break; |
|
| 53 | 53 | } |
|
| 54 | 54 | total = total + n; |
|
| 55 | 55 | } |
|
| 56 | - | return buf[..total]; |
|
| 56 | + | return &buf[..total]; |
|
| 57 | 57 | } |
lib/std/lang/alloc.rad
+1 -1
| 80 | 80 | return arena.data.len as u32 - arena.offset; |
|
| 81 | 81 | } |
|
| 82 | 82 | ||
| 83 | 83 | /// Returns the remaining buffer as a mutable slice. |
|
| 84 | 84 | pub fn remainingBuf(arena: *mut Arena) -> *mut [u8] { |
|
| 85 | - | return arena.data[arena.offset..]; |
|
| 85 | + | return &mut arena.data[arena.offset..]; |
|
| 86 | 86 | } |
|
| 87 | 87 | ||
| 88 | 88 | /// Commits `size` bytes of allocation, advancing the offset. |
|
| 89 | 89 | /// Use after writing to the buffer returned by [`remainingBuf`]. |
|
| 90 | 90 | pub fn commit(arena: *mut Arena, size: u32) { |
lib/std/lang/il.rad
+4 -4
| 89 | 89 | } |
|
| 90 | 90 | let buf = try! alloc::allocSlice(arena, 1, 1, totalLen) as *mut [u8]; |
|
| 91 | 91 | let mut pos: u32 = 0; |
|
| 92 | 92 | ||
| 93 | 93 | for segment in path { |
|
| 94 | - | pos = pos + try! mem::copy(buf[pos..], segment); |
|
| 95 | - | pos = pos + try! mem::copy(buf[pos..], PATH_SEPARATOR); |
|
| 94 | + | pos = pos + try! mem::copy(&mut buf[pos..], segment); |
|
| 95 | + | pos = pos + try! mem::copy(&mut buf[pos..], PATH_SEPARATOR); |
|
| 96 | 96 | } |
|
| 97 | - | try! mem::copy(buf[pos..], name); |
|
| 97 | + | try! mem::copy(&mut buf[pos..], name); |
|
| 98 | 98 | ||
| 99 | - | return buf[..totalLen]; |
|
| 99 | + | return &buf[..totalLen]; |
|
| 100 | 100 | } |
|
| 101 | 101 | ||
| 102 | 102 | /////////// |
|
| 103 | 103 | // Types // |
|
| 104 | 104 | /////////// |
lib/std/lang/il/printer.rad
+3 -3
| 46 | 46 | fn prefixStr(a: *mut alloc::Arena, prefix: u8, str: *[u8]) -> *[u8] { |
|
| 47 | 47 | let len = str.len + 1; |
|
| 48 | 48 | let ptr = try! alloc::allocSlice(a, 1, 1, len); |
|
| 49 | 49 | let slice = ptr as *mut [u8]; |
|
| 50 | 50 | slice[0] = prefix; |
|
| 51 | - | try! mem::copy(slice[1..], str); |
|
| 51 | + | try! mem::copy(&mut slice[1..], str); |
|
| 52 | 52 | ||
| 53 | 53 | return slice; |
|
| 54 | 54 | } |
|
| 55 | 55 | ||
| 56 | 56 | /// Format a register reference (`%n`). |
| 433 | 433 | write(out, ")"); |
|
| 434 | 434 | } |
|
| 435 | 435 | write(out, "\n"); |
|
| 436 | 436 | ||
| 437 | 437 | // Instructions. |
|
| 438 | - | let instrs = block.instrs.list[0..block.instrs.len]; |
|
| 438 | + | let instrs = &block.instrs.list[0..block.instrs.len]; |
|
| 439 | 439 | for i in 0..instrs.len { |
|
| 440 | 440 | indent(out, 1); |
|
| 441 | 441 | writeInstr(out, a, blocks, instrs[i]); |
|
| 442 | 442 | write(out, ";\n"); |
|
| 443 | 443 | } |
| 565 | 565 | ) -> *[u8] { |
|
| 566 | 566 | let mut pos: u32 = 0; |
|
| 567 | 567 | let mut out = sexpr::Output::Buffer { buf, pos: &mut pos }; |
|
| 568 | 568 | printProgram(&mut out, arena, program); |
|
| 569 | 569 | ||
| 570 | - | return buf[..pos]; |
|
| 570 | + | return &buf[..pos]; |
|
| 571 | 571 | } |
lib/std/lang/lower.rad
+20 -20
| 389 | 389 | } |
|
| 390 | 390 | ||
| 391 | 391 | /// Return the accumulated values. |
|
| 392 | 392 | fn dataBuilderFinish(b: *DataValueBuilder) -> ConstDataResult { |
|
| 393 | 393 | return ConstDataResult { |
|
| 394 | - | values: b.values[..b.len], |
|
| 394 | + | values: &b.values[..b.len], |
|
| 395 | 395 | isUndefined: b.allUndef, |
|
| 396 | 396 | }; |
|
| 397 | 397 | } |
|
| 398 | 398 | ||
| 399 | 399 | /////////////////////////// |
| 755 | 755 | options: LowerOptions { debug: false, buildTest: false }, |
|
| 756 | 756 | }; |
|
| 757 | 757 | let defaultFnIdx = try lowerDecls(&mut low, root, true); |
|
| 758 | 758 | ||
| 759 | 759 | return il::Program { |
|
| 760 | - | data: low.data[..low.dataCount], |
|
| 761 | - | fns: low.fns[..low.fnCount], |
|
| 760 | + | data: &low.data[..low.dataCount], |
|
| 761 | + | fns: &low.fns[..low.fnCount], |
|
| 762 | 762 | defaultFnIdx, |
|
| 763 | 763 | }; |
|
| 764 | 764 | } |
|
| 765 | 765 | ||
| 766 | 766 | ///////////////////////////////// |
| 855 | 855 | } |
|
| 856 | 856 | ||
| 857 | 857 | /// Finalize lowering and return the unified IL program. |
|
| 858 | 858 | pub fn finalize(low: *Lowerer, defaultFnIdx: ?u32) -> il::Program { |
|
| 859 | 859 | return il::Program { |
|
| 860 | - | data: low.data[..low.dataCount], |
|
| 861 | - | fns: low.fns[..low.fnCount], |
|
| 860 | + | data: &low.data[..low.dataCount], |
|
| 861 | + | fns: &low.fns[..low.fnCount], |
|
| 862 | 862 | defaultFnIdx, |
|
| 863 | 863 | }; |
|
| 864 | 864 | } |
|
| 865 | 865 | ||
| 866 | 866 | ///////////////////////////////// |
| 1049 | 1049 | let mut digits: [u8; fmt::U32_STR_LEN] = undefined; |
|
| 1050 | 1050 | let suffixText = fmt::formatU32(suffix, &mut digits[..]); |
|
| 1051 | 1051 | let totalLen = base.len + suffixText.len; |
|
| 1052 | 1052 | let buf = try! alloc::allocSlice(self.low.arena, 1, 1, totalLen) as *mut [u8]; |
|
| 1053 | 1053 | ||
| 1054 | - | try! mem::copy(buf[..base.len], base); |
|
| 1055 | - | try! mem::copy(buf[base.len..totalLen], suffixText); |
|
| 1054 | + | try! mem::copy(&mut buf[..base.len], base); |
|
| 1055 | + | try! mem::copy(&mut buf[base.len..totalLen], suffixText); |
|
| 1056 | 1056 | ||
| 1057 | - | return buf[..totalLen]; |
|
| 1057 | + | return &buf[..totalLen]; |
|
| 1058 | 1058 | } |
|
| 1059 | 1059 | ||
| 1060 | 1060 | /// Generate a unique label by appending the global counter to the base. |
|
| 1061 | 1061 | fn nextLabel(self: *mut FnLowerer, base: *[u8]) -> *[u8] throws (LowerError) { |
|
| 1062 | 1062 | let idx = self.labelCounter; |
| 1519 | 1519 | let suffix = fmt::formatU32(count, &mut digits[..]); |
|
| 1520 | 1520 | let suffixStart = prefix.len + 1; |
|
| 1521 | 1521 | let totalLen = suffixStart + suffix.len; |
|
| 1522 | 1522 | let buf = try! alloc::allocSlice(self.arena, 1, 1, totalLen) as *mut [u8]; |
|
| 1523 | 1523 | ||
| 1524 | - | try! mem::copy(buf[..prefix.len], prefix); |
|
| 1524 | + | try! mem::copy(&mut buf[..prefix.len], prefix); |
|
| 1525 | 1525 | buf[prefix.len] = '$'; |
|
| 1526 | - | try! mem::copy(buf[suffixStart..], suffix); |
|
| 1526 | + | try! mem::copy(&mut buf[suffixStart..], suffix); |
|
| 1527 | 1527 | ||
| 1528 | - | return buf[..totalLen]; |
|
| 1528 | + | return &buf[..totalLen]; |
|
| 1529 | 1529 | } |
|
| 1530 | 1530 | ||
| 1531 | 1531 | /// Append a data entry using a declaration-scoped name (`prefix$N`). |
|
| 1532 | 1532 | fn pushDeclData( |
|
| 1533 | 1533 | self: *mut Lowerer, |
| 1558 | 1558 | ||
| 1559 | 1559 | values[0] = il::DataValue { |
|
| 1560 | 1560 | item: il::DataItem::Str(s), |
|
| 1561 | 1561 | count: 1 |
|
| 1562 | 1562 | }; |
|
| 1563 | - | return try pushDeclData(self, s.len, 1, true, values[..1], dataPrefix); |
|
| 1563 | + | return try pushDeclData(self, s.len, 1, true, &values[..1], dataPrefix); |
|
| 1564 | 1564 | } |
|
| 1565 | 1565 | ||
| 1566 | 1566 | /// Compare two data items for structural equality. |
|
| 1567 | 1567 | /// Unlike raw byte comparison, this correctly ignores padding bytes in unions. |
|
| 1568 | 1568 | fn dataItemEq(a: il::DataItem, b: il::DataItem) -> bool { |
| 2389 | 2389 | let mut count: u32 = 0; |
|
| 2390 | 2390 | ||
| 2391 | 2391 | for i in 0..self.blockCount { |
|
| 2392 | 2392 | let data = &self.blockData[i]; |
|
| 2393 | 2393 | ||
| 2394 | - | let params = data.params.list[..data.params.len]; |
|
| 2395 | - | let preds = data.preds.list[..data.preds.len]; |
|
| 2394 | + | let params = &data.params.list[..data.params.len]; |
|
| 2395 | + | let preds = &data.preds.list[..data.preds.len]; |
|
| 2396 | 2396 | blocks[count] = il::Block { |
|
| 2397 | 2397 | label: data.label, |
|
| 2398 | 2398 | params, |
|
| 2399 | 2399 | instrs: data.instrs, |
|
| 2400 | - | locs: data.locs[..data.locsLen], |
|
| 2400 | + | locs: &data.locs[..data.locsLen], |
|
| 2401 | 2401 | preds, |
|
| 2402 | 2402 | loopDepth: data.loopDepth, |
|
| 2403 | 2403 | }; |
|
| 2404 | 2404 | count = count + 1; |
|
| 2405 | 2405 | } |
|
| 2406 | - | return blocks[..count]; |
|
| 2406 | + | return &blocks[..count]; |
|
| 2407 | 2407 | } |
|
| 2408 | 2408 | ||
| 2409 | 2409 | ///////////////////// |
|
| 2410 | 2410 | // Loop Management // |
|
| 2411 | 2411 | ///////////////////// |
| 3253 | 3253 | } |
|
| 3254 | 3254 | emit(self, il::Instr::Switch { |
|
| 3255 | 3255 | val: subject.val, |
|
| 3256 | 3256 | defaultTarget: blocks[defaultIdx].n, |
|
| 3257 | 3257 | defaultArgs: &mut [], |
|
| 3258 | - | cases: cases[..caseIdx] |
|
| 3258 | + | cases: &mut cases[..caseIdx] |
|
| 3259 | 3259 | }); |
|
| 3260 | 3260 | ||
| 3261 | 3261 | for i in 0..prongs.len { |
|
| 3262 | 3262 | let p = prongs.list[i]; |
|
| 3263 | 3263 | let case ast::NodeValue::MatchProng(prong) = p.value |
| 4790 | 4790 | ||
| 4791 | 4791 | /// Lower a subscript expression. |
|
| 4792 | 4792 | fn lowerSubscript(self: *mut FnLowerer, node: *ast::Node, container: *ast::Node, index: *ast::Node) -> il::Val |
|
| 4793 | 4793 | throws (LowerError) |
|
| 4794 | 4794 | { |
|
| 4795 | - | if let case ast::NodeValue::Range(range) = index.value { |
|
| 4796 | - | return try lowerSliceRange(self, container, range, node); |
|
| 4795 | + | if let case ast::NodeValue::Range(_) = index.value { |
|
| 4796 | + | panic "lowerSubscript: range subscript must use address-of (&)"; |
|
| 4797 | 4797 | } |
|
| 4798 | 4798 | let result = try lowerElemPtr(self, container, index); |
|
| 4799 | 4799 | ||
| 4800 | 4800 | return emitRead(self, result.elemReg, 0, result.elemType); |
|
| 4801 | 4801 | } |
| 5940 | 5940 | } |
|
| 5941 | 5941 | emit(self, il::Instr::Switch { |
|
| 5942 | 5942 | val: il::Val::Reg(tagReg), |
|
| 5943 | 5943 | defaultTarget: defaultTarget.n, |
|
| 5944 | 5944 | defaultArgs: &mut [], |
|
| 5945 | - | cases: cases[..caseIdx] |
|
| 5945 | + | cases: &mut cases[..caseIdx] |
|
| 5946 | 5946 | }); |
|
| 5947 | 5947 | ||
| 5948 | 5948 | // Second pass: emit each catch clause body. |
|
| 5949 | 5949 | for i in 0..catches.len { |
|
| 5950 | 5950 | let clauseNode = catches.list[i]; |
lib/std/lang/lower/tests/slice.range.rad
+4 -4
| 1 | 1 | /// Returns a subslice with explicit bounds. |
|
| 2 | 2 | fn sliceRange(s: *[i32], start: u32, end: u32) -> *[i32] { |
|
| 3 | - | return s[start..end]; |
|
| 3 | + | return &s[start..end]; |
|
| 4 | 4 | } |
|
| 5 | 5 | ||
| 6 | 6 | /// Returns a subslice with an open end bound. |
|
| 7 | 7 | fn sliceRangeOpenEnd(s: *[i32], start: u32) -> *[i32] { |
|
| 8 | - | return s[start..]; |
|
| 8 | + | return &s[start..]; |
|
| 9 | 9 | } |
|
| 10 | 10 | ||
| 11 | 11 | /// Returns a subslice with an open start bound. |
|
| 12 | 12 | fn sliceRangeOpenStart(s: *[i32], end: u32) -> *[i32] { |
|
| 13 | - | return s[..end]; |
|
| 13 | + | return &s[..end]; |
|
| 14 | 14 | } |
|
| 15 | 15 | ||
| 16 | 16 | /// Returns a full reslice of a slice. |
|
| 17 | 17 | fn sliceRangeFull(s: *[i32]) -> *[i32] { |
|
| 18 | - | return s[..]; |
|
| 18 | + | return &s[..]; |
|
| 19 | 19 | } |
|
| 20 | 20 | ||
| 21 | 21 | /// Returns a subslice from an array parameter. |
|
| 22 | 22 | fn sliceArray(a: [i32; 4]) -> *[i32] { |
|
| 23 | 23 | return &a[1..3]; |
lib/std/lang/module.rad
+7 -7
| 199 | 199 | return m.children[index]; |
|
| 200 | 200 | } |
|
| 201 | 201 | ||
| 202 | 202 | /// Public accessor for a module's directory prefix. |
|
| 203 | 203 | pub fn moduleDir(m: *ModuleEntry) -> *[u8] { |
|
| 204 | - | return m.filePath[..m.dirLen]; |
|
| 204 | + | return &m.filePath[..m.dirLen]; |
|
| 205 | 205 | } |
|
| 206 | 206 | ||
| 207 | 207 | /// Public accessor to the logical module path segments. |
|
| 208 | 208 | pub fn moduleQualifiedPath(m: *ModuleEntry) -> *[*[u8]] { |
|
| 209 | 209 | debug::assertMsg(m.pathDepth > 0, "moduleQualifiedPath: path must not be empty"); |
| 262 | 262 | // Split on '/' to extract all but the last component. |
|
| 263 | 263 | for i in 0..filePath.len { |
|
| 264 | 264 | if filePath[i] == PATH_SEP { |
|
| 265 | 265 | if i > last { |
|
| 266 | 266 | debug::assertMsg(count < components.len, "parsePath: output slice is large enough"); |
|
| 267 | - | components[count] = filePath[last..i]; |
|
| 267 | + | components[count] = &filePath[last..i]; |
|
| 268 | 268 | count = count + 1; |
|
| 269 | 269 | } |
|
| 270 | 270 | last = i + 1; |
|
| 271 | 271 | } |
|
| 272 | 272 | } |
| 274 | 274 | return nil; // Path ends with separator or is empty. |
|
| 275 | 275 | } |
|
| 276 | 276 | ||
| 277 | 277 | // Handle the last component by removing extension. |
|
| 278 | 278 | debug::assertMsg(count < components.len, "parsePath: output slice is large enough"); |
|
| 279 | - | if let name = trimExtension(filePath[last..]) { |
|
| 279 | + | if let name = trimExtension(&filePath[last..]) { |
|
| 280 | 280 | components[count] = name; |
|
| 281 | 281 | } else { |
|
| 282 | 282 | return nil; |
|
| 283 | 283 | }; |
|
| 284 | 284 | count = count + 1; |
| 323 | 323 | } |
|
| 324 | 324 | let childName = childPath[childPath.len - 1]; |
|
| 325 | 325 | ||
| 326 | 326 | // Navigate through all but the last segment to find the parent. |
|
| 327 | 327 | let mut parentId = root; |
|
| 328 | - | for part in childPath[..(childPath.len - 1)] { |
|
| 328 | + | for part in &childPath[..(childPath.len - 1)] { |
|
| 329 | 329 | let child = findChild(graph, part, parentId) else { |
|
| 330 | 330 | throw ModuleError::MissingParent; |
|
| 331 | 331 | }; |
|
| 332 | 332 | parentId = child.id; |
|
| 333 | 333 | } |
| 410 | 410 | fn basenameSlice(path: *[u8]) -> *[u8] throws (ModuleError) { |
|
| 411 | 411 | let start = basenameStart(path); |
|
| 412 | 412 | let withoutExt = trimExtension(path) else { |
|
| 413 | 413 | throw ModuleError::InvalidPath; |
|
| 414 | 414 | }; |
|
| 415 | - | return withoutExt[start..]; |
|
| 415 | + | return &withoutExt[start..]; |
|
| 416 | 416 | } |
|
| 417 | 417 | ||
| 418 | 418 | /// Find the byte offset immediately following the last separator. |
|
| 419 | 419 | fn basenameStart(path: *[u8]) -> u32 { |
|
| 420 | 420 | let mut start: u32 = 0; |
| 436 | 436 | for i in 0..SOURCE_EXT.len { |
|
| 437 | 437 | if path[extStart + i] != SOURCE_EXT[i] { |
|
| 438 | 438 | return nil; |
|
| 439 | 439 | } |
|
| 440 | 440 | } |
|
| 441 | - | return path[..extStart]; |
|
| 441 | + | return &path[..extStart]; |
|
| 442 | 442 | } |
|
| 443 | 443 | ||
| 444 | 444 | /// Strip prefix from path, and return the suffix. |
|
| 445 | 445 | fn stripPathPrefix(prefix: *[*[u8]], path: *[*[u8]]) -> ?*[*[u8]] { |
|
| 446 | 446 | if prefix.len == 0 { |
| 452 | 452 | for segment, i in prefix { |
|
| 453 | 453 | if not mem::eq(segment, path[i]) { |
|
| 454 | 454 | return nil; |
|
| 455 | 455 | } |
|
| 456 | 456 | } |
|
| 457 | - | return path[prefix.len..]; |
|
| 457 | + | return &path[prefix.len..]; |
|
| 458 | 458 | } |
lib/std/lang/parser.rad
+3 -3
| 738 | 738 | return nodeChar(p, ch); |
|
| 739 | 739 | } |
|
| 740 | 740 | case scanner::TokenKind::String => { |
|
| 741 | 741 | advance(p); |
|
| 742 | 742 | let src = p.previous.source; |
|
| 743 | - | let raw = src[1..src.len - 1]; // Strip quotes. |
|
| 743 | + | let raw = &src[1..src.len - 1]; // Strip quotes. |
|
| 744 | 744 | ||
| 745 | 745 | // Process escape sequences into arena buffer. |
|
| 746 | 746 | let buf = alloc::remainingBuf(&mut p.arena.arena); |
|
| 747 | 747 | let len = unescapeString(raw, buf); |
|
| 748 | 748 | alloc::commit(&mut p.arena.arena, len); |
|
| 749 | 749 | ||
| 750 | - | return nodeString(p, buf[..len]); |
|
| 750 | + | return nodeString(p, &buf[..len]); |
|
| 751 | 751 | } |
|
| 752 | 752 | case scanner::TokenKind::Underscore => { |
|
| 753 | 753 | advance(p); |
|
| 754 | 754 | return node(p, ast::NodeValue::Placeholder); |
|
| 755 | 755 | } |
| 921 | 921 | fn tryParseAnnotation(p: *mut Parser) -> ?*ast::Node { |
|
| 922 | 922 | if not check(p, scanner::TokenKind::AtIdent) { |
|
| 923 | 923 | return nil; |
|
| 924 | 924 | } |
|
| 925 | 925 | // Token is @identifier, skip the '@' to get the name. |
|
| 926 | - | let ident = p.current.source[..]; |
|
| 926 | + | let ident = &p.current.source[..]; |
|
| 927 | 927 | if ident == "@default" { |
|
| 928 | 928 | advance(p); // Consume `@default`. |
|
| 929 | 929 | return nodeAttribute(p, ast::Attribute::Default); |
|
| 930 | 930 | } |
|
| 931 | 931 | if ident == "@test" { |
lib/std/lang/resolver.rad
+43 -69
| 2063 | 2063 | case ast::NodeValue::Ident(name) if name.len > 0 => { |
|
| 2064 | 2064 | if buf.len < 1 { |
|
| 2065 | 2065 | panic "flattenPath: invalid output buffer size"; |
|
| 2066 | 2066 | } |
|
| 2067 | 2067 | buf[0] = name; |
|
| 2068 | - | out = buf[..1]; |
|
| 2068 | + | out = &buf[..1]; |
|
| 2069 | 2069 | } |
|
| 2070 | 2070 | case ast::NodeValue::ScopeAccess(access) => { |
|
| 2071 | 2071 | // Recursively flatten parent path. |
|
| 2072 | 2072 | let parent = try flattenPath(self, access.parent, buf); |
|
| 2073 | 2073 | if parent.len >= buf.len { |
|
| 2074 | 2074 | panic "flattenPath: invalid output buffer size"; |
|
| 2075 | 2075 | } |
|
| 2076 | 2076 | let child = try nodeName(self, access.child); |
|
| 2077 | 2077 | buf[parent.len] = child; |
|
| 2078 | - | out = buf[..parent.len + 1]; |
|
| 2078 | + | out = &buf[..parent.len + 1]; |
|
| 2079 | 2079 | } |
|
| 2080 | 2080 | case ast::NodeValue::Super => { |
|
| 2081 | 2081 | // `super` is handled by scope adjustment in `checkSuperAccess`. |
|
| 2082 | 2082 | // Return empty prefix so the path continues from the next segment. |
|
| 2083 | - | out = buf[..0]; |
|
| 2083 | + | out = &buf[..0]; |
|
| 2084 | 2084 | return out; |
|
| 2085 | 2085 | } |
|
| 2086 | 2086 | else => { |
|
| 2087 | 2087 | // Fallthrough to error. |
|
| 2088 | 2088 | } |
| 2202 | 2202 | } |
|
| 2203 | 2203 | // Start by finding the root of the path. |
|
| 2204 | 2204 | let root = path[0]; |
|
| 2205 | 2205 | let sym = findInScopeRecursive(scope, root, isAnySymbol) else |
|
| 2206 | 2206 | throw emitError(self, node, ErrorKind::UnresolvedSymbol(root)); |
|
| 2207 | - | let suffix = path[1..]; |
|
| 2207 | + | let suffix = &path[1..]; |
|
| 2208 | 2208 | ||
| 2209 | 2209 | // Check visibility for symbol. |
|
| 2210 | 2210 | if not isSymbolVisible(sym, scope, self.scope) { |
|
| 2211 | 2211 | throw emitError(self, node, ErrorKind::UnresolvedSymbol(root)); |
|
| 2212 | 2212 | } |
| 2263 | 2263 | } |
|
| 2264 | 2264 | let parentName = path[0]; |
|
| 2265 | 2265 | ||
| 2266 | 2266 | // First, check if this is a sub-module of the start scope. |
|
| 2267 | 2267 | if let sym = findSymbolInScope(startScope, parentName) { |
|
| 2268 | - | return try resolveModulePathRecursive(self, module, path[1..], sym); |
|
| 2268 | + | return try resolveModulePathRecursive(self, module, &path[1..], sym); |
|
| 2269 | 2269 | } |
|
| 2270 | 2270 | // Not a sub-module, so look in the global scope for a package root. |
|
| 2271 | 2271 | let sym = findSymbolInScope(self.pkgScope, parentName) |
|
| 2272 | 2272 | else throw emitError(self, module, ErrorKind::UnresolvedSymbol(parentName)); |
|
| 2273 | 2273 | ||
| 2274 | - | return try resolveModulePathRecursive(self, module, path[1..], sym); |
|
| 2274 | + | return try resolveModulePathRecursive(self, module, &path[1..], sym); |
|
| 2275 | 2275 | } |
|
| 2276 | 2276 | ||
| 2277 | 2277 | /// Recursively resolve the remaining path segments by traversing child modules. |
|
| 2278 | 2278 | fn resolveModulePathRecursive( |
|
| 2279 | 2279 | self: *mut Resolver, |
| 2295 | 2295 | throw emitError(self, node, ErrorKind::UnresolvedSymbol(childName)); |
|
| 2296 | 2296 | } |
|
| 2297 | 2297 | return try resolveModulePathRecursive( |
|
| 2298 | 2298 | self, |
|
| 2299 | 2299 | node, |
|
| 2300 | - | path[1..], |
|
| 2300 | + | &path[1..], |
|
| 2301 | 2301 | childSym |
|
| 2302 | 2302 | ); |
|
| 2303 | 2303 | } |
|
| 2304 | 2304 | ||
| 2305 | 2305 | /// Resolve a type name, which could be an identifier or scoped path. |
| 4228 | 4228 | ||
| 4229 | 4229 | /// Analyze an array or slice subscript expression. |
|
| 4230 | 4230 | fn resolveSubscript(self: *mut Resolver, node: *ast::Node, container: *ast::Node, indexNode: *ast::Node) -> Type |
|
| 4231 | 4231 | throws (ResolveError) |
|
| 4232 | 4232 | { |
|
| 4233 | - | let containerTy = try infer(self, container); |
|
| 4234 | - | let mut indexTy: Type = undefined; |
|
| 4235 | - | let mut rangeExpr: ?ast::Range = nil; |
|
| 4236 | - | ||
| 4237 | - | match indexNode.value { |
|
| 4238 | - | case ast::NodeValue::Range(range) => { |
|
| 4239 | - | indexTy = try infer(self, indexNode); |
|
| 4240 | - | rangeExpr = range; |
|
| 4241 | - | } |
|
| 4242 | - | else => { |
|
| 4243 | - | indexTy = try checkAssignable(self, indexNode, Type::U32); |
|
| 4244 | - | } |
|
| 4233 | + | // Range subscripts always require `&` to form a slice. |
|
| 4234 | + | if let case ast::NodeValue::Range(range) = indexNode.value { |
|
| 4235 | + | let _ = try infer(self, indexNode); |
|
| 4236 | + | let _ = try infer(self, container); |
|
| 4237 | + | try checkSliceRangeIndices(self, range); |
|
| 4238 | + | throw emitError(self, node, ErrorKind::SliceRequiresAddress); |
|
| 4245 | 4239 | } |
|
| 4240 | + | let containerTy = try infer(self, container); |
|
| 4241 | + | let _ = try checkAssignable(self, indexNode, Type::U32); |
|
| 4246 | 4242 | let subjectTy = autoDeref(containerTy); |
|
| 4247 | 4243 | ||
| 4248 | 4244 | match subjectTy { |
|
| 4249 | 4245 | case Type::Array(arrayInfo) => { |
|
| 4250 | - | if let range = rangeExpr { |
|
| 4251 | - | try checkSliceRangeIndices(self, range); |
|
| 4252 | - | throw emitError(self, node, ErrorKind::SliceRequiresAddress); |
|
| 4253 | - | } |
|
| 4254 | 4246 | return try setNodeType(self, node, *arrayInfo.item); |
|
| 4255 | 4247 | } |
|
| 4256 | - | case Type::Slice { item, mutable } => { |
|
| 4257 | - | if let range = rangeExpr { |
|
| 4258 | - | try checkSliceRangeIndices(self, range); |
|
| 4259 | - | try setSliceRangeInfo(self, node, SliceRangeInfo { |
|
| 4260 | - | itemType: item, |
|
| 4261 | - | mutable, |
|
| 4262 | - | capacity: nil, |
|
| 4263 | - | }); |
|
| 4264 | - | return try setNodeType(self, node, *allocType(self, Type::Slice { |
|
| 4265 | - | item, |
|
| 4266 | - | mutable, |
|
| 4267 | - | })); |
|
| 4268 | - | } |
|
| 4248 | + | case Type::Slice { item, .. } => { |
|
| 4269 | 4249 | return try setNodeType(self, node, *item); |
|
| 4270 | 4250 | } |
|
| 4271 | 4251 | else => { |
|
| 4272 | 4252 | throw emitError(self, container, ErrorKind::ExpectedIndexable); |
|
| 4273 | 4253 | } |
| 4739 | 4719 | if let case ast::NodeValue::Subscript { container, index } = addr.target.value { |
|
| 4740 | 4720 | if let case ast::NodeValue::Range(range) = index.value { |
|
| 4741 | 4721 | let containerTy = try infer(self, container); |
|
| 4742 | 4722 | let subjectTy = autoDeref(containerTy); |
|
| 4743 | 4723 | ||
| 4744 | - | if let case Type::Array(arrayInfo) = subjectTy { |
|
| 4745 | - | try checkSliceRangeIndices(self, range); |
|
| 4746 | - | try validateArraySliceBounds(self, range, arrayInfo.length, node); |
|
| 4747 | - | let sliceTy = Type::Slice { |
|
| 4748 | - | item: arrayInfo.item, |
|
| 4749 | - | mutable: addr.mutable, |
|
| 4750 | - | }; |
|
| 4751 | - | let alloc = allocType(self, sliceTy); |
|
| 4752 | - | try setSliceRangeInfo(self, node, SliceRangeInfo { |
|
| 4753 | - | itemType: arrayInfo.item, |
|
| 4754 | - | mutable: addr.mutable, |
|
| 4755 | - | capacity: arrayInfo.length, |
|
| 4756 | - | }); |
|
| 4757 | - | try setNodeType(self, addr.target, *alloc); |
|
| 4724 | + | try checkSliceRangeIndices(self, range); |
|
| 4758 | 4725 | ||
| 4759 | - | return try setNodeType(self, node, *alloc); |
|
| 4760 | - | } |
|
| 4761 | - | if let case Type::Slice { item, mutable } = subjectTy { |
|
| 4762 | - | if addr.mutable and not mutable { |
|
| 4763 | - | throw emitError(self, addr.target, ErrorKind::ImmutableBinding); |
|
| 4764 | - | } |
|
| 4765 | - | try checkSliceRangeIndices(self, range); |
|
| 4766 | - | let sliceTy = Type::Slice { |
|
| 4767 | - | item, |
|
| 4768 | - | mutable: addr.mutable, |
|
| 4769 | - | }; |
|
| 4770 | - | let alloc = allocType(self, sliceTy); |
|
| 4771 | - | try setSliceRangeInfo(self, node, SliceRangeInfo { |
|
| 4772 | - | itemType: item, |
|
| 4773 | - | mutable: addr.mutable, |
|
| 4774 | - | capacity: nil, |
|
| 4775 | - | }); |
|
| 4776 | - | try setNodeType(self, addr.target, *alloc); |
|
| 4726 | + | let mut item: *Type = undefined; |
|
| 4727 | + | let mut capacity: ?u32 = nil; |
|
| 4777 | 4728 | ||
| 4778 | - | return try setNodeType(self, node, *alloc); |
|
| 4729 | + | match subjectTy { |
|
| 4730 | + | case Type::Array(arrayInfo) => { |
|
| 4731 | + | try validateArraySliceBounds(self, range, arrayInfo.length, node); |
|
| 4732 | + | item = arrayInfo.item; |
|
| 4733 | + | capacity = arrayInfo.length; |
|
| 4734 | + | } |
|
| 4735 | + | case Type::Slice { item: sliceItem, mutable } => { |
|
| 4736 | + | if addr.mutable and not mutable { |
|
| 4737 | + | throw emitError(self, addr.target, ErrorKind::ImmutableBinding); |
|
| 4738 | + | } |
|
| 4739 | + | item = sliceItem; |
|
| 4740 | + | } |
|
| 4741 | + | else => { |
|
| 4742 | + | throw emitError(self, container, ErrorKind::ExpectedIndexable); |
|
| 4743 | + | } |
|
| 4779 | 4744 | } |
|
| 4745 | + | let sliceTy = Type::Slice { item, mutable: addr.mutable }; |
|
| 4746 | + | let alloc = allocType(self, sliceTy); |
|
| 4747 | + | try setSliceRangeInfo(self, node, SliceRangeInfo { |
|
| 4748 | + | itemType: item, |
|
| 4749 | + | mutable: addr.mutable, |
|
| 4750 | + | capacity, |
|
| 4751 | + | }); |
|
| 4752 | + | try setNodeType(self, addr.target, *alloc); |
|
| 4753 | + | return try setNodeType(self, node, *alloc); |
|
| 4780 | 4754 | } |
|
| 4781 | 4755 | } |
|
| 4782 | 4756 | // Derive a hint for the target type from the slice hint. |
|
| 4783 | 4757 | let mut targetHint: Type = Type::Unknown; |
|
| 4784 | 4758 | if let case Type::Slice { item, .. } = hint { |
lib/std/lang/resolver/tests.rad
+7 -0
| 933 | 933 | let program = "let xs: [u8; 2] = [1, 2]; xs[..];"; |
|
| 934 | 934 | let result = try resolveProgramStr(&mut a, program); |
|
| 935 | 935 | try expectErrorKind(&result, super::ErrorKind::SliceRequiresAddress); |
|
| 936 | 936 | } |
|
| 937 | 937 | ||
| 938 | + | @test fn testResolveSliceResliceRequiresAddressOf() throws (testing::TestError) { |
|
| 939 | + | let mut a = testResolver(); |
|
| 940 | + | let program = "fn f(s: *[u8]) -> *[u8] { return s[..]; }"; |
|
| 941 | + | let result = try resolveProgramStr(&mut a, program); |
|
| 942 | + | try expectErrorKind(&result, super::ErrorKind::SliceRequiresAddress); |
|
| 943 | + | } |
|
| 944 | + | ||
| 938 | 945 | @test fn testResolveSliceRangeOutOfBounds() throws (testing::TestError) { |
|
| 939 | 946 | { |
|
| 940 | 947 | let mut a = testResolver(); |
|
| 941 | 948 | let program = "let xs: [u8; 2] = [1, 2]; let slice = &xs[..3];"; |
|
| 942 | 949 | let result = try resolveProgramStr(&mut a, program); |
lib/std/lang/scanner.rad
+4 -4
| 367 | 367 | return false; |
|
| 368 | 368 | } |
|
| 369 | 369 | ||
| 370 | 370 | /// Create a token from the current scanner state. |
|
| 371 | 371 | fn tok(s: *Scanner, kind: TokenKind) -> Token { |
|
| 372 | - | return Token { kind, source: s.source[s.token..s.cursor], offset: s.token }; |
|
| 372 | + | return Token { kind, source: &s.source[s.token..s.cursor], offset: s.token }; |
|
| 373 | 373 | } |
|
| 374 | 374 | ||
| 375 | 375 | /// Create an invalid token with the given message. |
|
| 376 | 376 | pub fn invalid(offset: u32, message: *[u8]) -> Token { |
|
| 377 | 377 | return Token { kind: TokenKind::Invalid, source: message, offset }; |
| 526 | 526 | /// Scan an identifier, keyword, or label. |
|
| 527 | 527 | fn scanIdentifier(s: *mut Scanner) -> Token { |
|
| 528 | 528 | while let ch = current(s); isAlpha(ch) or isDigit(ch) or ch == '_' or ch == '#' { |
|
| 529 | 529 | advance(s); |
|
| 530 | 530 | } |
|
| 531 | - | let ident = s.source[s.token..s.cursor]; |
|
| 531 | + | let ident = &s.source[s.token..s.cursor]; |
|
| 532 | 532 | let kind = keywordOrIdent(ident); |
|
| 533 | 533 | ||
| 534 | 534 | // Only intern actual identifiers, not keywords. |
|
| 535 | 535 | if kind == TokenKind::Ident { |
|
| 536 | 536 | return Token { kind, source: strings::intern(s.pool, ident), offset: s.token }; |
| 683 | 683 | } |
|
| 684 | 684 | // Must have at least one character after `@`. |
|
| 685 | 685 | if s.cursor - s.token <= 1 { |
|
| 686 | 686 | return invalid(s.token, "expected identifier after `@`"); |
|
| 687 | 687 | } |
|
| 688 | - | let name = s.source[s.token..s.cursor]; |
|
| 688 | + | let name = &s.source[s.token..s.cursor]; |
|
| 689 | 689 | return Token { |
|
| 690 | 690 | kind: TokenKind::AtIdent, |
|
| 691 | 691 | source: strings::intern(s.pool, name), |
|
| 692 | 692 | offset: s.token, |
|
| 693 | 693 | }; |
| 709 | 709 | let mut c: u16 = 1; |
|
| 710 | 710 | ||
| 711 | 711 | if offset >= source.len { |
|
| 712 | 712 | return nil; |
|
| 713 | 713 | } |
|
| 714 | - | for ch in source[..offset] { |
|
| 714 | + | for ch in &source[..offset] { |
|
| 715 | 715 | if ch == '\n' { |
|
| 716 | 716 | c = 1; |
|
| 717 | 717 | l = l + 1; |
|
| 718 | 718 | } else { |
|
| 719 | 719 | c = c + 1; |
lib/std/mem.rad
+1 -1
| 29 | 29 | for i in 0..prefix.len { |
|
| 30 | 30 | if prefix[i] != input[i] { |
|
| 31 | 31 | return nil; |
|
| 32 | 32 | } |
|
| 33 | 33 | } |
|
| 34 | - | return input[prefix.len..]; |
|
| 34 | + | return &input[prefix.len..]; |
|
| 35 | 35 | } |
|
| 36 | 36 | ||
| 37 | 37 | /// Align value up to alignment boundary. |
|
| 38 | 38 | pub fn alignUp(value: u32, alignment: u32) -> u32 { |
|
| 39 | 39 | return (value + alignment - 1) & ~(alignment - 1); |
lib/std/sys/unix.rad
+3 -3
| 54 | 54 | /// Reads from a file descriptor until EOF or buffer is full. |
|
| 55 | 55 | /// Returns the total number of bytes read, or a negative value on error. |
|
| 56 | 56 | pub fn readToEnd(fd: i32, buf: *mut [u8]) -> i32 { |
|
| 57 | 57 | let mut total: u32 = 0; |
|
| 58 | 58 | while total < buf.len { |
|
| 59 | - | let chunk = buf[total..]; |
|
| 59 | + | let chunk = &mut buf[total..]; |
|
| 60 | 60 | let n = read(fd, chunk); |
|
| 61 | 61 | ||
| 62 | 62 | if n < 0 { |
|
| 63 | 63 | return n; |
|
| 64 | 64 | } |
| 96 | 96 | return nil; |
|
| 97 | 97 | } |
|
| 98 | 98 | if n < 0 { |
|
| 99 | 99 | return nil; |
|
| 100 | 100 | } |
|
| 101 | - | return buf[..(n as u32)]; |
|
| 101 | + | return &buf[..(n as u32)]; |
|
| 102 | 102 | } |
|
| 103 | 103 | ||
| 104 | 104 | /// Exit the current process with the given status code. |
|
| 105 | 105 | pub fn exit(status: i32) { |
|
| 106 | 106 | intrinsics::ecall(93, status, 0, 0, 0); |
| 117 | 117 | if fd < 0 { |
|
| 118 | 118 | return false; |
|
| 119 | 119 | } |
|
| 120 | 120 | let mut written: u32 = 0; |
|
| 121 | 121 | while written < data.len { |
|
| 122 | - | let chunk = data[written..]; |
|
| 122 | + | let chunk = &data[written..]; |
|
| 123 | 123 | let n = write(fd, chunk); |
|
| 124 | 124 | if n <= 0 { |
|
| 125 | 125 | close(fd); |
|
| 126 | 126 | return false; |
|
| 127 | 127 | } |
test/lower/lower-test.rad
+4 -4
| 41 | 41 | if line[i] != ' ' and line[i] != '\t' { |
|
| 42 | 42 | end = i + 1; |
|
| 43 | 43 | } |
|
| 44 | 44 | i = i + 1; |
|
| 45 | 45 | } |
|
| 46 | - | return line[..end]; |
|
| 46 | + | return &line[..end]; |
|
| 47 | 47 | } |
|
| 48 | 48 | ||
| 49 | 49 | /// Get next line from string at offset. Returns the line and updates offset past newline. |
|
| 50 | 50 | fn nextLine(s: *[u8], offset: *mut u32) -> *[u8] { |
|
| 51 | 51 | let start = *offset; |
|
| 52 | 52 | let mut i = start; |
|
| 53 | 53 | ||
| 54 | 54 | while i < s.len and s[i] != '\n' { |
|
| 55 | 55 | i = i + 1; |
|
| 56 | 56 | } |
|
| 57 | - | let line = s[start..i]; |
|
| 57 | + | let line = &s[start..i]; |
|
| 58 | 58 | if i < s.len { |
|
| 59 | 59 | *offset = i + 1; |
|
| 60 | 60 | } else { |
|
| 61 | 61 | *offset = i; |
|
| 62 | 62 | } |
| 102 | 102 | if len < 4 { |
|
| 103 | 103 | return nil; |
|
| 104 | 104 | } |
|
| 105 | 105 | // Check for .rad extension. |
|
| 106 | 106 | let extStart = len - 4; // TODO: language support for additions in ranges. |
|
| 107 | - | if not mem::eq(sourcePath[extStart..len], ".rad") { |
|
| 107 | + | if not mem::eq(&sourcePath[extStart..len], ".rad") { |
|
| 108 | 108 | return nil; |
|
| 109 | 109 | } |
|
| 110 | 110 | if len + 1 > buf.len { |
|
| 111 | 111 | return nil; |
|
| 112 | 112 | } |
| 119 | 119 | buf[len - 3] = 'r'; |
|
| 120 | 120 | buf[len - 2] = 'i'; |
|
| 121 | 121 | buf[len - 1] = 'l'; |
|
| 122 | 122 | buf[len] = 0; |
|
| 123 | 123 | ||
| 124 | - | return buf[..len]; |
|
| 124 | + | return &buf[..len]; |
|
| 125 | 125 | } |
|
| 126 | 126 | ||
| 127 | 127 | /// Run a single lowering test case. Returns `true` on success. |
|
| 128 | 128 | fn runTest(sourcePath: *[u8]) -> bool { |
|
| 129 | 129 | // Buffers for file I/O. |