compiler/ lib/ examples/ std/ arch/ rv64/ tests/ abi.sizes.rad 3.4 KiB aggregate.return.rad 4.0 KiB arith.assignment.rad 580 B arith.basic.rad 176 B arith.modulo.rad 96 B arith.subword.rad 3.8 KiB arith.sum.rad 177 B arith.w64.rad 4.1 KiB array.assign.rad 221 B array.bounds.check.rad 321 B array.index.assign.rad 367 B array.index.rad 249 B array.length.rad 262 B array.math.rad 1.2 KiB array.nested.assign.rad 319 B array.nested.rad 325 B array.record.elements.rad 1.7 KiB array.repeat.edge.rad 548 B array.repeat.rad 828 B array.return.rad 330 B array.slice.empty.rad 108 B array.slice.gen.end.rad 126 B array.slice.gen.index.rad 139 B array.slice.gen.open.rad 125 B array.slice.gen.start.end.rad 127 B array.slice.gen.start.rad 126 B array.slice.rad 759 B as.precedence.rad 212 B assert.basic.rad 387 B assert.fail.rad 138 B assert.false.rad 140 B assert.true.rad 100 B assign.mutable.rad 6.1 KiB assign.rad 129 B assign.shadow.mutable.rad 461 B binop.bitwise.rad 1.2 KiB binop.cmp.rad 426 B bool.comparison.array.rad 688 B bool.comparison.nested.gen.rad 1.0 KiB bool.comparison.opt.rad 905 B bool.comparison.record.gen.rad 1.0 KiB bool.comparison.record.rad 1.1 KiB bool.comparison.slice.gen.rad 157 B bool.comparison.slice.rad 4.1 KiB bool.comparison.slice.record.gen.rad 2.0 KiB bool.comparison.slice.union.gen.rad 2.5 KiB bool.comparison.union.ctor.rad 690 B bool.comparison.union.gen.rad 1.2 KiB bool.comparison.union.record.gen.rad 1.5 KiB bool.comparison.union.simple.gen.rad 281 B bool.operators.complex.rad 384 B bool.operators.rad 831 B bool.short.circuit.rad 2.3 KiB bool.simple.rad 194 B bool.values.rad 772 B builtin.size.align.rad 1.3 KiB builtin.sliceof.mut.rad 606 B builtin.sliceof.rad 505 B call.arg.clobber.rad 717 B call.basic.rad 241 B call.clobber.rad 462 B cast.same.size.rad 1.0 KiB casting.numbers.rad 1.5 KiB char.literal.rad 165 B compound.assign.field.rad 285 B compound.assign.rad 1.1 KiB cond.assign.rad 723 B cond.expr.aggregate.rad 1.1 KiB cond.expr.rad 1.8 KiB cond.for.else.break.rad 326 B cond.for.indexed.rad 238 B cond.for.rad 165 B cond.for.range.indexed.rad 526 B cond.for.range.rad 171 B cond.for.unsigned.range.rad 644 B cond.forever.break.continue.rad 182 B cond.forever.break.rad 232 B cond.fused.rad 926 B cond.if.case.rad 2.2 KiB cond.if.else.min.rad 143 B cond.if.else.rad 225 B cond.if.elseif.rad 420 B cond.if.noelse.rad 120 B cond.if.rad 865 B cond.match.fallthrough.rad 369 B cond.match.guard.rad 1.4 KiB cond.match.guard.regalloc.rad 1.3 KiB cond.while.else.break.rad 282 B cond.while.rad 119 B const.array.copy.mutate.rad 386 B const.array.rad 195 B const.basic.rad 325 B const.char.rad 159 B const.fn.array.rad 664 B const.record.array.rad 1.2 KiB const.record.array.simple.rad 523 B const.record.ctor.rad 170 B const.record.fn.rad 353 B const.record.rad 182 B const.slice.param.rad 333 B const.union.payload.ctor.rad 349 B const.union.record.literal.rad 359 B data.array.rad 767 B data.bool.rad 216 B data.i16.rad 261 B data.i32.rad 281 B data.i8.rad 248 B data.record.rad 561 B data.simple.rad 436 B data.u16.rad 220 B data.u32.rad 240 B data.u8.rad 208 B data.union.rad 886 B debug.tag.rad 557 B edge.cases.2.rad 337 B edge.cases.3.rad 594 B edge.cases.4.rad 1.2 KiB edge.cases.5.rad 1.0 KiB edge.cases.6.rad 2.6 KiB edge.cases.7.addr.bug.rad 224 B edge.cases.8.bug.rad 508 B edge.cases.rad 223 B error.basic.rad 159 B error.catch.rad 1.6 KiB error.division.zero.rad 164 B error.modulo.zero.rad 162 B error.multi.basic.rad 672 B error.multi.catch.rad 772 B error.multi.catch.typed.binding.rad 791 B error.multi.catch.typed.catchall.rad 1.0 KiB error.multi.catch.typed.rad 1.1 KiB error.multi.propagate.multi.rad 953 B error.multi.propagate.rad 825 B error.multi.try.optional.rad 507 B error.slice.bounds.rad 219 B error.try.bang.success.rad 370 B error.try.catch.binding.rad 2.0 KiB error.try.optional.rad 1.8 KiB error.try.rad 4.0 KiB fn.block.scope.rad 508 B fn.callback.nested.rad 1.2 KiB fn.default.rad 131 B fn.local.rad 140 B fn.recursion.2.rad 239 B fn.void.rad 150 B for.else.continue.rad 1.1 KiB frame.large.rad 567 B if-let-mut.rad 1.1 KiB iflet.shadow.leak.rad 317 B integer.bitwise.basic.rad 693 B integer.overflow.rad 1.8 KiB large.blit.store.rad 2.1 KiB let.guard.rad 1.9 KiB literal.w64.rad 1.7 KiB loc.addr.offset.bug.rad 410 B loc.addr.opt.to.opt.rad 433 B loc.addr.optional.assign.rad 408 B loc.addr.record.assign.rad 443 B loop.complex.flow.rad 1007 B loop.sealblock.rad 911 B match.array.rad 3.4 KiB match.char.rad 1.6 KiB match.multi.seal.rad 987 B match.multi.survive.rad 1.6 KiB match.mutref.push.rad 1.0 KiB match.mutref.union.rad 662 B match.nested.call.rad 1.7 KiB match.nested.deep.rad 2.2 KiB match.nested.deref.rad 3.7 KiB match.nested.guard.rad 1.6 KiB match.nested.iflet.guard.rad 1.6 KiB match.nested.iflet.rad 1.4 KiB match.nested.letelse.rad 813 B match.nested.letelse.union.rad 1.3 KiB match.nested.literal.rad 3.1 KiB match.nested.multi.rad 2.4 KiB match.nested.pattern.rad 5.2 KiB match.nested.record.rad 2.0 KiB match.nested.union.rad 2.3 KiB match.nested.whilelet.rad 2.4 KiB match.string.rad 1.8 KiB match.value.copy.rad 2.0 KiB match.void.then.or.rad 1.6 KiB memzero.result.bug.rad 806 B memzero.union.bug.rad 576 B mutref.loop.bug.rad 1.8 KiB opt.assignment.bug.rad 1.3 KiB opt.bug.test.rad 1.4 KiB opt.if.let.complex.rad 6.2 KiB opt.if.let.guard.rad 809 B opt.if.let.rad 956 B opt.nil.check.rad 1.5 KiB opt.record.eq.rad 842 B opt.record.rad 655 B opt.return.array.rad 289 B opt.return.nested.rad 797 B opt.return.record.rad 344 B opt.slice.npo.rad 2.8 KiB opt.type.rad 200 B opt.while.let.complex.rad 404 B panic.rad 111 B placeholder.basic.rad 133 B placeholder.comprehensive.rad 562 B pointer.copy.edge.case.rad 1.3 KiB pointer.slice.index.rad 269 B pointer.slice.store.rad 881 B prog.ackermann.rad 5.0 KiB prog.bignum.rad 9.4 KiB prog.binsearch.rad 2.4 KiB prog.bubblesort.rad 2.0 KiB prog.cordic.rad 6.9 KiB prog.crc32.rad 2.7 KiB prog.dijkstra.rad 7.7 KiB prog.eval.rad 6.2 KiB prog.hanoi.rad 3.8 KiB prog.huffman.rad 9.3 KiB prog.hybridsort.rad 3.0 KiB prog.linkedlist.rad 5.8 KiB prog.lzw.rad 6.7 KiB prog.matmul.rad 2.9 KiB prog.mersenne.rad 5.2 KiB prog.nqueens.rad 3.4 KiB prog.rbtree.rad 8.2 KiB prog.regex.rad 10.2 KiB prog.sha256.rad 7.0 KiB prog.sieve.rad 2.8 KiB prog.symtab.rad 10.1 KiB prog.tokenizer.rad 13.8 KiB prog.vm.rad 17.4 KiB ptr.assign.rad 137 B ptr.deref.rad 622 B ptr.eq.rad 966 B ptr.mutate.rad 244 B ptr.opaque.rad 1.4 KiB record.access.rad 285 B record.alignment.rad 179 B record.array.elements.rad 1.7 KiB record.copy.rad 2.0 KiB record.field.assign.rad 184 B record.nested.calls.2.rad 612 B record.nested.calls.3.rad 734 B record.param.lit.rad 353 B record.ptr.access.rad 227 B record.ptr.mutate.rad 243 B record.shorthand.rad 1.5 KiB record.unlabeled.rad 407 B ref.if.bug.rad 519 B ref.immut.loop.bug.rad 670 B ref.mut.ptr.rad 261 B regalloc.callee.save.rad 1.5 KiB regalloc.spill.reuse.rad 473 B reserve.loop.rad 392 B result.void.success.rad 716 B slice.alloc.loop.rad 788 B slice.append.rad 3.3 KiB slice.cap.rad 941 B slice.delete.rad 971 B slice.of.rad 460 B slice.subslice.rad 1.4 KiB spill.blockarg.clobber.rad 3.5 KiB spill.loop.rad 1.6 KiB stack.local.corrupt.rad 320 B static.array.mutate.rad 387 B static.basic.rad 327 B static.fn.array.rad 628 B static.record.array.rad 503 B static.slice.index.assign.rad 408 B static.slice.offset.rad 668 B string.basic.rad 149 B string.escape.rad 349 B string.index.rad 116 B switch.blockargs.clobber.rad 1.3 KiB trait.aggregate.ret.rad 1.5 KiB trait.array.optional.rad 1.7 KiB trait.basic.rad 565 B trait.control.flow.rad 1.1 KiB trait.fn.param.rad 1.6 KiB trait.multiple.methods.rad 1.2 KiB trait.multiple.traits.rad 1.2 KiB trait.multiple.types.rad 1.3 KiB trait.supertrait.rad 2.5 KiB trait.throws.rad 1.0 KiB trait.writer.rad 2.6 KiB type.unify.rad 4.5 KiB undefined.rad 417 B union-tag.rad 911 B union.bitfield.rad 1.2 KiB union.discriminant.cast.rad 389 B union.edge.case.2.rad 679 B union.edge.case.3.rad 608 B union.mixed.assign.rad 977 B union.payload.mutref.rad 1.4 KiB union.payload.rad 580 B union.record.forward.rad 1.3 KiB union.void.match.rad 403 B union.void.rad 824 B unsigned.compare.rad 1.9 KiB var.align.rad 1013 B var.infer.rad 549 B decode.rad 14.6 KiB emit.rad 24.4 KiB encode.rad 19.9 KiB isel.rad 41.1 KiB printer.rad 13.0 KiB tests.rad 15.7 KiB rv64.rad 13.0 KiB collections/ lang/ sys/ arch.rad 65 B collections.rad 36 B fmt.rad 3.8 KiB intrinsics.rad 206 B io.rad 1.2 KiB lang.rad 222 B mem.rad 2.2 KiB sys.rad 167 B testing.rad 2.4 KiB tests.rad 11.6 KiB vec.rad 3.1 KiB std.rad 231 B scripts/ seed/ test/ vim/ .gitignore 353 B .gitsigners 112 B LICENSE 1.1 KiB Makefile 3.1 KiB README 2.5 KiB std.lib 987 B std.lib.test 252 B
lib/std/arch/rv64/tests/prog.linkedlist.rad 5.8 KiB raw
1
//! Linked list via array pool.
2
//! Implement a singly-linked list using an array of node records
3
//! (pool allocator pattern). Operations: push, pop, find, reverse, length.
4
5
6
/// A node in the linked list.
7
record Node {
8
    value: i32,
9
    next: ?u32,
10
}
11
12
/// A linked list backed by a pool of pre-allocated nodes.
13
record List {
14
    pool: [Node; 64],
15
    free: u32,
16
    head: ?u32,
17
}
18
19
/// Allocate a node from the pool. Returns its index.
20
fn alloc(list: *mut List, value: i32) -> u32 {
21
    let idx = list.free;
22
    list.free += 1;
23
    list.pool[idx] = Node { value, next: nil };
24
    return idx;
25
}
26
27
/// Push a value onto the front of the list.
28
fn push(list: *mut List, value: i32) {
29
    let idx = alloc(list, value);
30
    list.pool[idx].next = list.head;
31
    list.head = idx;
32
}
33
34
/// Pop a value from the front of the list. Returns nil if empty.
35
fn pop(list: *mut List) -> ?i32 {
36
    let idx = list.head else {
37
        return nil;
38
    };
39
    let value = list.pool[idx].value;
40
    list.head = list.pool[idx].next;
41
    return value;
42
}
43
44
/// Get the length of the list.
45
fn length(list: *List) -> u32 {
46
    let mut count: u32 = 0;
47
    let mut cur = list.head;
48
    while let idx = cur {
49
        count += 1;
50
        cur = list.pool[idx].next;
51
    }
52
    return count;
53
}
54
55
/// Find a value in the list. Returns the node index if found, or nil.
56
fn find(list: *List, value: i32) -> ?u32 {
57
    let mut cur = list.head;
58
    while let idx = cur {
59
        if list.pool[idx].value == value {
60
            return idx;
61
        }
62
        cur = list.pool[idx].next;
63
    }
64
    return nil;
65
}
66
67
/// Get the value at a given index (0-based from head).
68
fn valueAt(list: *List, index: u32) -> ?i32 {
69
    let mut cur = list.head;
70
    let mut i: u32 = 0;
71
    while let idx = cur {
72
        if i == index {
73
            return list.pool[idx].value;
74
        }
75
        cur = list.pool[idx].next;
76
        i += 1;
77
    }
78
    return nil;
79
}
80
81
/// Reverse the linked list in-place.
82
fn reverse(list: *mut List) {
83
    let mut prev: ?u32 = nil;
84
    let mut cur = list.head;
85
    while let idx = cur {
86
        let next = list.pool[idx].next;
87
        list.pool[idx].next = prev;
88
        prev = idx;
89
        cur = next;
90
    }
91
    list.head = prev;
92
}
93
94
/// Compute the sum of all values in the list.
95
fn sum(list: *List) -> i32 {
96
    let mut total: i32 = 0;
97
    let mut cur = list.head;
98
    while let idx = cur {
99
        total += list.pool[idx].value;
100
        cur = list.pool[idx].next;
101
    }
102
    return total;
103
}
104
105
/// Reset the list to empty.
106
fn reset(list: *mut List) {
107
    list.head = nil;
108
    list.free = 0;
109
}
110
111
/// Test basic push and length.
112
fn testPushLength(list: *mut List) -> i32 {
113
    push(list, 10);
114
    push(list, 20);
115
    push(list, 30);
116
117
    assert length(list) == 3;
118
    // Head should be most recently pushed.
119
    let v0 = valueAt(list, 0) else {
120
        return 2;
121
    };
122
    assert v0 == 30;
123
    let v1 = valueAt(list, 1) else {
124
        return 3;
125
    };
126
    assert v1 == 20;
127
    let v2 = valueAt(list, 2) else {
128
        return 4;
129
    };
130
    assert v2 == 10;
131
    return 0;
132
}
133
134
/// Test pop.
135
fn testPop(list: *mut List) -> i32 {
136
    let v = pop(list) else {
137
        return 1;
138
    };
139
    assert v == 30;
140
    assert length(list) == 2;
141
    let v0 = valueAt(list, 0) else {
142
        return 3;
143
    };
144
    assert v0 == 20;
145
    return 0;
146
}
147
148
/// Test find.
149
fn testFind(list: *mut List) -> i32 {
150
    // 20 should be found.
151
    assert find(list, 20) != nil;
152
    // 10 should be found.
153
    assert find(list, 10) != nil;
154
    // 30 was popped, should not be found.
155
    assert find(list, 30) == nil;
156
    // 99 never inserted.
157
    assert find(list, 99) == nil;
158
    return 0;
159
}
160
161
/// Test reverse.
162
fn testReverse(list: *mut List) -> i32 {
163
    // Current list: 20 -> 10
164
    // Add more elements.
165
    push(list, 40);
166
    push(list, 50);
167
    // List: 50 -> 40 -> 20 -> 10
168
169
    let sumBefore = sum(list);
170
171
    reverse(list);
172
    // List should be: 10 -> 20 -> 40 -> 50
173
174
    assert length(list) == 4;
175
176
    let v0 = valueAt(list, 0) else {
177
        return 2;
178
    };
179
    assert v0 == 10;
180
    let v1 = valueAt(list, 1) else {
181
        return 3;
182
    };
183
    assert v1 == 20;
184
    let v2 = valueAt(list, 2) else {
185
        return 4;
186
    };
187
    assert v2 == 40;
188
    let v3 = valueAt(list, 3) else {
189
        return 5;
190
    };
191
    assert v3 == 50;
192
193
    assert sum(list) == sumBefore;
194
    return 0;
195
}
196
197
/// Test building a larger list.
198
fn testLargerList(list: *mut List) -> i32 {
199
    reset(list);
200
201
    // Push 32 elements.
202
    let mut i: u32 = 0;
203
    while i < 32 {
204
        push(list, i as i32 * 3);
205
        i += 1;
206
    }
207
208
    assert length(list) == 32;
209
210
    // Sum should be 3 * (0 + 1 + ... + 31) = 3 * 496 = 1488
211
    assert sum(list) == 1488;
212
213
    // Reverse and verify sum is preserved.
214
    reverse(list);
215
    assert sum(list) == 1488;
216
217
    // After reverse, head should be 0 (first pushed), tail should be 93 (last pushed).
218
    let head = valueAt(list, 0) else {
219
        return 4;
220
    };
221
    assert head == 0;
222
    let tail = valueAt(list, 31) else {
223
        return 5;
224
    };
225
    assert tail == 93;
226
227
    // Pop all and verify decreasing original order.
228
    let mut j: u32 = 0;
229
    while j < 32 {
230
        let v = pop(list) else {
231
            return 6;
232
        };
233
        let expected = j as i32 * 3;
234
        assert v == expected;
235
        j += 1;
236
    }
237
238
    assert length(list) == 0;
239
240
    // Pop from empty list should return nil.
241
    assert pop(list) == nil;
242
    return 0;
243
}
244
245
@default fn main() -> i32 {
246
    let mut list: List = List {
247
        pool: [Node { value: 0, next: nil }; 64],
248
        free: 0,
249
        head: nil,
250
    };
251
252
    let r1 = testPushLength(&mut list);
253
    if r1 != 0 {
254
        return 10 + r1;
255
    }
256
257
    let r2 = testPop(&mut list);
258
    if r2 != 0 {
259
        return 20 + r2;
260
    }
261
262
    let r3 = testFind(&mut list);
263
    if r3 != 0 {
264
        return 30 + r3;
265
    }
266
267
    let r4 = testReverse(&mut list);
268
    if r4 != 0 {
269
        return 40 + r4;
270
    }
271
272
    let r5 = testLargerList(&mut list);
273
    if r5 != 0 {
274
        return 50 + r5;
275
    }
276
    return 0;
277
}