@shd101wyy/yo 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/skills/yo-async-effects/SKILL.md +4 -4
- package/.github/skills/yo-async-effects/async-effects-recipes.md +40 -40
- package/.github/skills/yo-core-patterns/SKILL.md +1 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +30 -26
- package/.github/skills/yo-project-workflow/SKILL.md +6 -3
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
- package/.github/skills/yo-syntax/SKILL.md +7 -6
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +78 -60
- package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
- package/README.md +10 -8
- package/out/cjs/index.cjs +583 -567
- package/out/cjs/yo-cli.cjs +664 -632
- package/out/cjs/yo-lsp.cjs +510 -485
- package/out/esm/index.mjs +538 -522
- package/out/types/src/codegen/codegen-c.d.ts +2 -2
- package/out/types/src/codegen/functions/collection.d.ts +2 -2
- package/out/types/src/codegen/functions/context.d.ts +3 -2
- package/out/types/src/codegen/types/collection.d.ts +2 -2
- package/out/types/src/codegen/utils/index.d.ts +3 -1
- package/out/types/src/doc/builder.d.ts +2 -2
- package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
- package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
- package/out/types/src/evaluator/context.d.ts +8 -9
- package/out/types/src/evaluator/index.d.ts +3 -3
- package/out/types/src/evaluator/types/record.d.ts +14 -0
- package/out/types/src/evaluator/types/validation.d.ts +2 -2
- package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
- package/out/types/src/evaluator/values/impl.d.ts +1 -1
- package/out/types/src/expr.d.ts +1 -4
- package/out/types/src/formatter.d.ts +11 -0
- package/out/types/src/function-value.d.ts +1 -1
- package/out/types/src/lsp/document-manager.d.ts +1 -1
- package/out/types/src/lsp/formatting.d.ts +2 -0
- package/out/types/src/module-manager.d.ts +3 -3
- package/out/types/src/tests/formatter.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +3 -4
- package/out/types/src/types/definitions.d.ts +8 -19
- package/out/types/src/types/guards.d.ts +3 -3
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/types/utils.d.ts +1 -1
- package/out/types/src/value-tag.d.ts +0 -1
- package/out/types/src/value.d.ts +6 -13
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/alg/hash.yo +13 -21
- package/std/allocator.yo +25 -40
- package/std/async.yo +3 -7
- package/std/build.yo +105 -151
- package/std/cli/arg_parser.yo +184 -169
- package/std/collections/array_list.yo +350 -314
- package/std/collections/btree_map.yo +142 -131
- package/std/collections/deque.yo +132 -128
- package/std/collections/hash_map.yo +542 -566
- package/std/collections/hash_set.yo +623 -687
- package/std/collections/linked_list.yo +275 -293
- package/std/collections/ordered_map.yo +113 -85
- package/std/collections/priority_queue.yo +73 -73
- package/std/crypto/md5.yo +191 -95
- package/std/crypto/random.yo +56 -64
- package/std/crypto/sha256.yo +151 -107
- package/std/encoding/base64.yo +87 -81
- package/std/encoding/hex.yo +43 -50
- package/std/encoding/html.yo +56 -81
- package/std/encoding/html_char_utils.yo +7 -13
- package/std/encoding/html_entities.yo +2248 -2253
- package/std/encoding/json.yo +316 -224
- package/std/encoding/punycode.yo +86 -116
- package/std/encoding/toml.yo +67 -66
- package/std/encoding/utf16.yo +37 -44
- package/std/env.yo +62 -91
- package/std/error.yo +12 -20
- package/std/fmt/display.yo +5 -9
- package/std/fmt/index.yo +8 -14
- package/std/fmt/to_string.yo +330 -315
- package/std/fmt/writer.yo +58 -87
- package/std/fs/dir.yo +83 -102
- package/std/fs/file.yo +147 -180
- package/std/fs/metadata.yo +45 -78
- package/std/fs/temp.yo +55 -65
- package/std/fs/types.yo +27 -40
- package/std/fs/walker.yo +53 -68
- package/std/gc.yo +5 -8
- package/std/glob.yo +30 -43
- package/std/http/client.yo +107 -120
- package/std/http/http.yo +106 -96
- package/std/http/index.yo +4 -6
- package/std/imm/list.yo +88 -93
- package/std/imm/map.yo +528 -464
- package/std/imm/set.yo +52 -57
- package/std/imm/sorted_map.yo +340 -286
- package/std/imm/sorted_set.yo +57 -63
- package/std/imm/string.yo +404 -345
- package/std/imm/vec.yo +173 -181
- package/std/io/reader.yo +3 -6
- package/std/io/writer.yo +4 -8
- package/std/libc/assert.yo +5 -9
- package/std/libc/ctype.yo +32 -22
- package/std/libc/dirent.yo +26 -25
- package/std/libc/errno.yo +164 -90
- package/std/libc/fcntl.yo +52 -45
- package/std/libc/float.yo +66 -44
- package/std/libc/limits.yo +42 -33
- package/std/libc/math.yo +53 -82
- package/std/libc/signal.yo +72 -47
- package/std/libc/stdatomic.yo +217 -188
- package/std/libc/stdint.yo +5 -29
- package/std/libc/stdio.yo +5 -29
- package/std/libc/stdlib.yo +32 -39
- package/std/libc/string.yo +5 -23
- package/std/libc/sys/stat.yo +58 -56
- package/std/libc/time.yo +5 -19
- package/std/libc/unistd.yo +5 -20
- package/std/libc/wctype.yo +6 -9
- package/std/libc/windows.yo +26 -30
- package/std/log.yo +41 -55
- package/std/net/addr.yo +102 -97
- package/std/net/dns.yo +27 -28
- package/std/net/errors.yo +50 -49
- package/std/net/tcp.yo +113 -124
- package/std/net/udp.yo +55 -66
- package/std/os/env.yo +35 -33
- package/std/os/signal.yo +15 -25
- package/std/path.yo +276 -311
- package/std/prelude.yo +6316 -4333
- package/std/process/command.yo +87 -103
- package/std/process/index.yo +12 -31
- package/std/regex/compiler.yo +196 -95
- package/std/regex/flags.yo +58 -39
- package/std/regex/index.yo +157 -173
- package/std/regex/match.yo +20 -31
- package/std/regex/node.yo +134 -152
- package/std/regex/parser.yo +283 -259
- package/std/regex/unicode.yo +172 -202
- package/std/regex/vm.yo +155 -171
- package/std/string/index.yo +5 -7
- package/std/string/rune.yo +45 -55
- package/std/string/string.yo +937 -964
- package/std/string/string_builder.yo +94 -104
- package/std/string/unicode.yo +46 -64
- package/std/sync/channel.yo +72 -73
- package/std/sync/cond.yo +31 -36
- package/std/sync/mutex.yo +30 -32
- package/std/sync/once.yo +13 -16
- package/std/sync/rwlock.yo +26 -31
- package/std/sync/waitgroup.yo +20 -25
- package/std/sys/advise.yo +16 -24
- package/std/sys/bufio/buf_reader.yo +77 -93
- package/std/sys/bufio/buf_writer.yo +52 -65
- package/std/sys/clock.yo +4 -9
- package/std/sys/constants.yo +77 -61
- package/std/sys/copy.yo +4 -10
- package/std/sys/dir.yo +26 -43
- package/std/sys/dns.yo +41 -61
- package/std/sys/errors.yo +95 -103
- package/std/sys/events.yo +45 -57
- package/std/sys/externs.yo +319 -267
- package/std/sys/fallocate.yo +7 -11
- package/std/sys/fcntl.yo +14 -22
- package/std/sys/file.yo +26 -40
- package/std/sys/future.yo +5 -8
- package/std/sys/iov.yo +12 -25
- package/std/sys/lock.yo +12 -13
- package/std/sys/mmap.yo +38 -43
- package/std/sys/path.yo +3 -8
- package/std/sys/perm.yo +7 -21
- package/std/sys/pipe.yo +5 -12
- package/std/sys/process.yo +23 -29
- package/std/sys/seek.yo +10 -12
- package/std/sys/signal.yo +7 -13
- package/std/sys/signals.yo +52 -35
- package/std/sys/socket.yo +63 -58
- package/std/sys/socketpair.yo +3 -6
- package/std/sys/sockinfo.yo +11 -20
- package/std/sys/statfs.yo +11 -34
- package/std/sys/statx.yo +25 -52
- package/std/sys/sysinfo.yo +15 -20
- package/std/sys/tcp.yo +62 -92
- package/std/sys/temp.yo +5 -9
- package/std/sys/time.yo +5 -15
- package/std/sys/timer.yo +6 -11
- package/std/sys/tty.yo +10 -18
- package/std/sys/udp.yo +22 -39
- package/std/sys/umask.yo +3 -6
- package/std/sys/unix.yo +33 -52
- package/std/testing/bench.yo +49 -52
- package/std/thread.yo +10 -15
- package/std/time/datetime.yo +105 -89
- package/std/time/duration.yo +43 -56
- package/std/time/instant.yo +13 -18
- package/std/time/sleep.yo +5 -9
- package/std/url/index.yo +184 -209
- package/std/worker.yo +6 -10
- package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
- package/out/types/src/evaluator/types/module.d.ts +0 -19
|
@@ -1,63 +1,59 @@
|
|
|
1
1
|
//! Dynamic array (vector) with amortized O(1) push and O(1) indexed access.
|
|
2
|
-
|
|
3
|
-
{
|
|
4
|
-
{ memmove, memcpy, memset } :: import "../libc/string.yo";
|
|
2
|
+
{ GlobalAllocator, AllocError } :: import("../allocator.yo");
|
|
3
|
+
{ memmove, memcpy, memset } :: import("../libc/string.yo");
|
|
5
4
|
{ malloc, calloc, realloc, free, aligned_alloc } :: GlobalAllocator;
|
|
6
|
-
|
|
7
5
|
/// Error variants for ArrayList operations.
|
|
8
6
|
ArrayListError :: enum(
|
|
9
7
|
/// Memory allocation failed.
|
|
10
8
|
AllocError(error : AllocError),
|
|
11
9
|
/// Index is out of bounds for the current length.
|
|
12
|
-
IndexOutOfBounds(index: usize, length: usize),
|
|
10
|
+
IndexOutOfBounds(index : usize, length : usize),
|
|
13
11
|
/// Attempted to access an element from an empty list.
|
|
14
12
|
EmptyList
|
|
15
13
|
);
|
|
16
|
-
|
|
17
14
|
/// Generic growable array similar to Rust's `Vec<T>`.
|
|
18
15
|
/// Heap-allocated with automatic resizing and reference-counted cleanup.
|
|
19
|
-
ArrayList :: (fn(comptime(T): Type) -> comptime(Type))(
|
|
16
|
+
ArrayList :: (fn(comptime(T) : Type) -> comptime(Type))(
|
|
20
17
|
object(
|
|
21
18
|
_ptr : ?*(T),
|
|
22
19
|
_length : usize,
|
|
23
20
|
_capacity : usize
|
|
24
21
|
)
|
|
25
22
|
);
|
|
26
|
-
impl(
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
impl(
|
|
24
|
+
forall(T : Type),
|
|
25
|
+
ArrayList(T),
|
|
26
|
+
len : (fn(self : Self) -> usize)({
|
|
27
|
+
return(self._length);
|
|
29
28
|
}),
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return self._capacity;
|
|
29
|
+
capacity : (fn(self : Self) -> usize)({
|
|
30
|
+
return(self._capacity);
|
|
33
31
|
}),
|
|
34
|
-
|
|
35
32
|
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
ptr : (fn(self: Self) -> ?*(T))(
|
|
33
|
+
* Get a pointer to the underlying data buffer
|
|
34
|
+
* Returns .None if the list is empty or has no allocated buffer
|
|
35
|
+
*/
|
|
36
|
+
ptr : (fn(self : Self) -> ?*(T))(
|
|
40
37
|
self._ptr
|
|
41
38
|
),
|
|
42
|
-
|
|
43
39
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
as_slice : (fn(self: Self) -> Option(Slice(T)))(
|
|
50
|
-
match(
|
|
51
|
-
|
|
52
|
-
.
|
|
40
|
+
* Get a slice view of the ArrayList
|
|
41
|
+
* Returns a fat pointer Slice(T) with data pointer and length
|
|
42
|
+
* This allows passing ArrayList to functions expecting slices
|
|
43
|
+
* Returns .None for an empty ArrayList with no allocated buffer
|
|
44
|
+
*/
|
|
45
|
+
as_slice : (fn(self : Self) -> Option(Slice(T)))(
|
|
46
|
+
match(
|
|
47
|
+
self._ptr,
|
|
48
|
+
.Some(p) =>.Some(Slice(T).from_raw_parts(p, self._length)),
|
|
49
|
+
.None =>.None
|
|
53
50
|
)
|
|
54
51
|
),
|
|
55
|
-
|
|
56
52
|
/** * Directly set the length of the ArrayList
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
set_len : (fn(self: Self, new_len: usize) -> unit)({
|
|
53
|
+
* UNSAFE: This does not initialize new elements or free removed elements
|
|
54
|
+
* Only use when you've manually populated the buffer (e.g., via direct memory writes)
|
|
55
|
+
*/
|
|
56
|
+
set_len : (fn(self : Self, new_len : usize) -> unit)({
|
|
61
57
|
cond(
|
|
62
58
|
(new_len <= self._capacity) => {
|
|
63
59
|
self._length = new_len;
|
|
@@ -65,63 +61,64 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
65
61
|
true => panic("set_len: new length exceeds capacity")
|
|
66
62
|
);
|
|
67
63
|
}),
|
|
68
|
-
|
|
69
64
|
/**
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
* Create a new empty ArrayList
|
|
66
|
+
*/
|
|
72
67
|
new : (fn() -> Self)(
|
|
73
68
|
Self(
|
|
74
|
-
_ptr
|
|
75
|
-
_length: usize(0),
|
|
76
|
-
_capacity: usize(0)
|
|
77
|
-
)
|
|
78
|
-
|
|
69
|
+
_ptr :.None,
|
|
70
|
+
_length : usize(0),
|
|
71
|
+
_capacity : usize(0)
|
|
72
|
+
)
|
|
73
|
+
),
|
|
79
74
|
/**
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
with_capacity : (fn(cap: usize) -> Self)(
|
|
75
|
+
* Create an ArrayList with a specific initial cap
|
|
76
|
+
*/
|
|
77
|
+
with_capacity : (fn(cap : usize) -> Self)(
|
|
83
78
|
cond(
|
|
84
|
-
(cap == usize(0)) =>
|
|
79
|
+
(cap == usize(0)) =>
|
|
85
80
|
Self.new(),
|
|
86
81
|
true => {
|
|
87
82
|
ptr_result := malloc(sizeof(T) * cap);
|
|
88
|
-
match(
|
|
83
|
+
match(
|
|
84
|
+
ptr_result,
|
|
89
85
|
.Some(_ptr) =>
|
|
90
86
|
Self(
|
|
91
|
-
_ptr
|
|
92
|
-
_length: usize(0),
|
|
93
|
-
_capacity: cap
|
|
87
|
+
_ptr :.Some((*(T))(_ptr)),
|
|
88
|
+
_length : usize(0),
|
|
89
|
+
_capacity : cap
|
|
94
90
|
),
|
|
95
91
|
.None => panic("malloc returned None")
|
|
96
92
|
)
|
|
97
93
|
}
|
|
98
94
|
)
|
|
99
95
|
),
|
|
100
|
-
|
|
101
96
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
push : (fn(self: Self, value: T) -> Result(unit, ArrayListError))(
|
|
97
|
+
* Add an element to the end of the ArrayList
|
|
98
|
+
*/
|
|
99
|
+
push : (fn(self : Self, value : T) -> Result(unit, ArrayListError))(
|
|
105
100
|
// Check if we need to grow
|
|
106
101
|
cond(
|
|
107
102
|
(self._length >= self._capacity) => {
|
|
108
103
|
// Need to grow - calculate new capacity
|
|
109
|
-
new_capacity := cond
|
|
104
|
+
new_capacity := cond(
|
|
110
105
|
(self._capacity == usize(0)) => usize(4),
|
|
111
|
-
true => (self._capacity * usize(2))
|
|
112
|
-
|
|
106
|
+
true => (self._capacity * usize(2))
|
|
107
|
+
);
|
|
113
108
|
// Allocate or reallocate
|
|
114
|
-
new_some_ptr := match
|
|
109
|
+
new_some_ptr := match(
|
|
110
|
+
self._ptr,
|
|
115
111
|
.None => GlobalAllocator.malloc(sizeof(T) * new_capacity),
|
|
116
112
|
.Some(old_ptr) => GlobalAllocator.realloc(
|
|
117
|
-
.Some((*(void))(old_ptr)),
|
|
113
|
+
.Some((*(void))(old_ptr)),
|
|
118
114
|
sizeof(T) * new_capacity
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
match(
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
match(
|
|
118
|
+
new_some_ptr,
|
|
122
119
|
.Some(new_ptr) => {
|
|
123
120
|
typed_ptr := *(T)(new_ptr);
|
|
124
|
-
self._ptr
|
|
121
|
+
self._ptr =.Some(typed_ptr);
|
|
125
122
|
self._capacity = new_capacity;
|
|
126
123
|
// Now add the element at position length
|
|
127
124
|
target_ptr := (typed_ptr &+ self._length);
|
|
@@ -129,12 +126,13 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
129
126
|
self._length = (self._length + usize(1));
|
|
130
127
|
.Ok(())
|
|
131
128
|
},
|
|
132
|
-
.None
|
|
129
|
+
.None =>.Err(.AllocError(.OutOfMemory))
|
|
133
130
|
)
|
|
134
131
|
},
|
|
135
132
|
true =>
|
|
136
133
|
// Have capacity - just add the element
|
|
137
|
-
match(
|
|
134
|
+
match(
|
|
135
|
+
self._ptr,
|
|
138
136
|
.Some(_ptr) => {
|
|
139
137
|
target_ptr := (_ptr &+ self._length);
|
|
140
138
|
consume(target_ptr.* = value);
|
|
@@ -145,17 +143,17 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
145
143
|
)
|
|
146
144
|
)
|
|
147
145
|
),
|
|
148
|
-
|
|
149
146
|
/**
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
pop : (fn(self: Self) -> Option(T))(
|
|
147
|
+
* Remove and return the last element
|
|
148
|
+
*/
|
|
149
|
+
pop : (fn(self : Self) -> Option(T))(
|
|
153
150
|
cond(
|
|
154
|
-
(self._length == usize(0))
|
|
151
|
+
(self._length == usize(0)) =>.None,
|
|
155
152
|
true => {
|
|
156
153
|
self._length = (self._length - usize(1));
|
|
157
|
-
match(
|
|
158
|
-
.
|
|
154
|
+
match(
|
|
155
|
+
self._ptr,
|
|
156
|
+
.None =>.None,
|
|
159
157
|
.Some(_ptr) => {
|
|
160
158
|
last_element_ptr := (_ptr &+ self._length);
|
|
161
159
|
last_element := last_element_ptr.*;
|
|
@@ -168,69 +166,71 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
168
166
|
}
|
|
169
167
|
)
|
|
170
168
|
),
|
|
171
|
-
|
|
172
169
|
/**
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
get : (fn(self: Self, index: usize) -> Option(T))(
|
|
170
|
+
* Get an element by index (bounds checked)
|
|
171
|
+
*/
|
|
172
|
+
get : (fn(self : Self, index : usize) -> Option(T))(
|
|
176
173
|
cond(
|
|
177
|
-
(index >= self._length)
|
|
174
|
+
(index >= self._length) =>.None,
|
|
178
175
|
true =>
|
|
179
|
-
match(
|
|
180
|
-
.
|
|
181
|
-
.
|
|
176
|
+
match(
|
|
177
|
+
self._ptr,
|
|
178
|
+
.None =>.None,
|
|
179
|
+
.Some(_ptr) =>.Some((_ptr &+ index).*)
|
|
182
180
|
)
|
|
183
181
|
)
|
|
184
182
|
),
|
|
185
|
-
|
|
186
183
|
/**
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
shrink_to_fit : (fn(self: Self) -> Result(unit, ArrayListError))(
|
|
184
|
+
* Shrink the capacity to match the current length
|
|
185
|
+
* This reduces memory usage but may cause reallocation on next push
|
|
186
|
+
*/
|
|
187
|
+
shrink_to_fit : (fn(self : Self) -> Result(unit, ArrayListError))(
|
|
191
188
|
// If length equals capacity or both are zero, nothing to do
|
|
192
189
|
cond(
|
|
193
|
-
((self._length == self._capacity) || (self._capacity == usize(0)))
|
|
190
|
+
((self._length == self._capacity) || (self._capacity == usize(0))) =>.Ok(()),
|
|
194
191
|
true =>
|
|
195
192
|
// If length is zero, free the buffer
|
|
196
193
|
cond(
|
|
197
194
|
(self._length == usize(0)) => {
|
|
198
|
-
match(
|
|
195
|
+
match(
|
|
196
|
+
self._ptr,
|
|
199
197
|
.Some(_ptr) => {
|
|
200
198
|
GlobalAllocator.free(.Some(*(void)(_ptr)));
|
|
201
|
-
self._ptr
|
|
199
|
+
self._ptr =.None;
|
|
202
200
|
self._capacity = usize(0);
|
|
203
201
|
},
|
|
204
|
-
.None => ()
|
|
202
|
+
.None => ()
|
|
203
|
+
);
|
|
205
204
|
.Ok(())
|
|
206
205
|
},
|
|
207
206
|
true =>
|
|
208
207
|
// Otherwise, reallocate to exact size
|
|
209
|
-
match(
|
|
208
|
+
match(
|
|
209
|
+
self._ptr,
|
|
210
210
|
.None => panic("ArrayList has capacity but no ptr"),
|
|
211
211
|
.Some(old_ptr) => {
|
|
212
212
|
new_some_ptr := GlobalAllocator.realloc(
|
|
213
213
|
.Some(*(void)(old_ptr)),
|
|
214
214
|
sizeof(T) * self._length
|
|
215
215
|
);
|
|
216
|
-
match(
|
|
216
|
+
match(
|
|
217
|
+
new_some_ptr,
|
|
217
218
|
.Some(new_ptr) => {
|
|
218
|
-
self._ptr
|
|
219
|
+
self._ptr =.Some(*(T)(new_ptr));
|
|
219
220
|
self._capacity = self._length;
|
|
220
221
|
.Ok(())
|
|
221
222
|
},
|
|
222
|
-
.None
|
|
223
|
+
.None =>.Err(.AllocError(.OutOfMemory))
|
|
223
224
|
)
|
|
224
225
|
}
|
|
225
226
|
)
|
|
226
227
|
)
|
|
227
228
|
)
|
|
228
229
|
),
|
|
229
|
-
|
|
230
230
|
_free_elements : (fn(self : Self) -> unit)(
|
|
231
231
|
cond(
|
|
232
232
|
Type.contains_rc_type(T) => {
|
|
233
|
-
if(
|
|
233
|
+
if(self._length > usize(0), {
|
|
234
234
|
i := usize(0);
|
|
235
235
|
base_ptr := self._ptr.unwrap();
|
|
236
236
|
while(i < self._length, i = (i + usize(1)), {
|
|
@@ -242,16 +242,15 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
242
242
|
true => ()
|
|
243
243
|
)
|
|
244
244
|
),
|
|
245
|
-
|
|
246
245
|
/**
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
remove : (fn(self: Self, start: usize, (count : usize) ?= 1) -> Result(usize, ArrayListError))(
|
|
246
|
+
* Remove elements from the ArrayList starting at index, removing count elements
|
|
247
|
+
* Returns the number of elements actually removed
|
|
248
|
+
*/
|
|
249
|
+
remove : (fn(self : Self, start : usize, (count : usize) ?= 1) -> Result(usize, ArrayListError))(
|
|
251
250
|
// Check if start index is valid
|
|
252
251
|
cond(
|
|
253
|
-
(start >= self._length) =>
|
|
254
|
-
.Err(.IndexOutOfBounds(index: start, length: self._length)),
|
|
252
|
+
(start >= self._length) =>
|
|
253
|
+
.Err(.IndexOutOfBounds(index : start, length : self._length)),
|
|
255
254
|
true => {
|
|
256
255
|
// Calculate actual number of elements to remove
|
|
257
256
|
// (can't remove more than what's available)
|
|
@@ -260,12 +259,12 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
260
259
|
(count > available) => available,
|
|
261
260
|
true => count
|
|
262
261
|
);
|
|
263
|
-
|
|
264
262
|
// If removing 0 elements, just return success
|
|
265
263
|
cond(
|
|
266
|
-
(actual_count == usize(0))
|
|
264
|
+
(actual_count == usize(0)) =>.Ok(usize(0)),
|
|
267
265
|
true =>
|
|
268
|
-
match(
|
|
266
|
+
match(
|
|
267
|
+
self._ptr,
|
|
269
268
|
.None => panic("ArrayList has length but no ptr"),
|
|
270
269
|
.Some(_ptr) => {
|
|
271
270
|
// Shift remaining elements left to fill the gap
|
|
@@ -276,7 +275,6 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
276
275
|
(elements_after > usize(0)) => {
|
|
277
276
|
src_ptr := (_ptr &+ (start + actual_count));
|
|
278
277
|
dst_ptr := (_ptr &+ start);
|
|
279
|
-
|
|
280
278
|
cond(
|
|
281
279
|
Type.contains_rc_type(T) => {
|
|
282
280
|
// For RC types, iterate and properly manage RC
|
|
@@ -323,7 +321,6 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
323
321
|
);
|
|
324
322
|
}
|
|
325
323
|
);
|
|
326
|
-
|
|
327
324
|
// Update length
|
|
328
325
|
self._length = new_length;
|
|
329
326
|
.Ok(actual_count)
|
|
@@ -333,37 +330,36 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
333
330
|
}
|
|
334
331
|
)
|
|
335
332
|
),
|
|
336
|
-
|
|
337
333
|
/**
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
slice : (fn(self: Self, start: usize, end: usize) -> Result(Self, ArrayListError))(
|
|
334
|
+
* Create a new ArrayList containing a slice of elements from start to end (exclusive)
|
|
335
|
+
* Similar to array slicing in many languages: array[start:end]
|
|
336
|
+
* Returns a new ArrayList with copied elements
|
|
337
|
+
*/
|
|
338
|
+
slice : (fn(self : Self, start : usize, end : usize) -> Result(Self, ArrayListError))(
|
|
343
339
|
// Validate indices
|
|
344
340
|
cond(
|
|
345
341
|
(start > self._length) =>
|
|
346
|
-
.Err(.IndexOutOfBounds(index: start, length: self._length)),
|
|
342
|
+
.Err(.IndexOutOfBounds(index : start, length : self._length)),
|
|
347
343
|
(end > self._length) =>
|
|
348
|
-
.Err(.IndexOutOfBounds(index: end, length: self._length)),
|
|
344
|
+
.Err(.IndexOutOfBounds(index : end, length : self._length)),
|
|
349
345
|
(start > end) =>
|
|
350
|
-
.Err(.IndexOutOfBounds(index: start, length: end)),
|
|
346
|
+
.Err(.IndexOutOfBounds(index : start, length : end)),
|
|
351
347
|
true => {
|
|
352
348
|
slice_length := (end - start);
|
|
353
|
-
|
|
354
349
|
// If slice is empty, return empty ArrayList
|
|
355
350
|
cond(
|
|
356
351
|
(slice_length == usize(0)) =>
|
|
357
352
|
.Ok(Self.new()),
|
|
358
353
|
true =>
|
|
359
|
-
match(
|
|
354
|
+
match(
|
|
355
|
+
self._ptr,
|
|
360
356
|
.None => panic("ArrayList has length but no ptr"),
|
|
361
357
|
.Some(src_ptr) => {
|
|
362
358
|
// Create new ArrayList with exact capacity
|
|
363
359
|
new_list := Self.with_capacity(slice_length);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
.None
|
|
360
|
+
match(
|
|
361
|
+
new_list._ptr,
|
|
362
|
+
.None =>.Err(.AllocError(.OutOfMemory)),
|
|
367
363
|
.Some(dst_ptr) => {
|
|
368
364
|
// Copy elements
|
|
369
365
|
i := usize(0);
|
|
@@ -372,7 +368,6 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
372
368
|
dst := (dst_ptr &+ i);
|
|
373
369
|
consume(dst.* = src.*);
|
|
374
370
|
});
|
|
375
|
-
|
|
376
371
|
// Set the length of the new list
|
|
377
372
|
new_list._length = slice_length;
|
|
378
373
|
.Ok(new_list)
|
|
@@ -384,12 +379,11 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
384
379
|
}
|
|
385
380
|
)
|
|
386
381
|
),
|
|
387
|
-
|
|
388
382
|
/**
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
ensure_total_capacity : (fn(self: Self, min_cap: usize) -> unit)({
|
|
383
|
+
* Ensure the ArrayList can hold at least `min_cap` total elements
|
|
384
|
+
* without further reallocation.
|
|
385
|
+
*/
|
|
386
|
+
ensure_total_capacity : (fn(self : Self, min_cap : usize) -> unit)({
|
|
393
387
|
cond(
|
|
394
388
|
(min_cap <= self._capacity) => (),
|
|
395
389
|
true => {
|
|
@@ -397,22 +391,24 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
397
391
|
(self._capacity == usize(0)) => min_cap,
|
|
398
392
|
true => {
|
|
399
393
|
cap := self._capacity;
|
|
400
|
-
while
|
|
394
|
+
while(cap < min_cap, {
|
|
401
395
|
cap = (cap * usize(2));
|
|
402
|
-
};
|
|
396
|
+
});
|
|
403
397
|
cap
|
|
404
398
|
}
|
|
405
399
|
);
|
|
406
|
-
new_some_ptr := match(
|
|
407
|
-
.
|
|
400
|
+
new_some_ptr := match(
|
|
401
|
+
self._ptr,
|
|
402
|
+
.None => GlobalAllocator.malloc(sizeof(T) * new_capacity),
|
|
408
403
|
.Some(old_ptr) => GlobalAllocator.realloc(
|
|
409
404
|
.Some((*(void))(old_ptr)),
|
|
410
|
-
|
|
405
|
+
sizeof(T) * new_capacity
|
|
411
406
|
)
|
|
412
407
|
);
|
|
413
|
-
match(
|
|
408
|
+
match(
|
|
409
|
+
new_some_ptr,
|
|
414
410
|
.Some(new_ptr) => {
|
|
415
|
-
self._ptr
|
|
411
|
+
self._ptr =.Some((*(T))(new_ptr));
|
|
416
412
|
self._capacity = new_capacity;
|
|
417
413
|
},
|
|
418
414
|
.None => panic("ArrayList.ensure_total_capacity: allocation failed")
|
|
@@ -420,20 +416,20 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
420
416
|
}
|
|
421
417
|
);
|
|
422
418
|
}),
|
|
423
|
-
|
|
424
419
|
/**
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
extend_from_ptr : (fn(self: Self, src: *(T), count: usize) -> unit)({
|
|
420
|
+
* Append `count` elements from a raw pointer using memcpy.
|
|
421
|
+
* The caller must ensure `src` points to at least `count` valid elements.
|
|
422
|
+
*/
|
|
423
|
+
extend_from_ptr : (fn(self : Self, src : *(T), count : usize) -> unit)({
|
|
429
424
|
cond(
|
|
430
425
|
(count == usize(0)) => (),
|
|
431
426
|
true => {
|
|
432
|
-
self.ensure_total_capacity(
|
|
433
|
-
match(
|
|
427
|
+
self.ensure_total_capacity(self._length + count);
|
|
428
|
+
match(
|
|
429
|
+
self._ptr,
|
|
434
430
|
.Some(dst_base) => {
|
|
435
|
-
dst := (*(void))(
|
|
436
|
-
_ := memcpy(dst, (*(void))(src),
|
|
431
|
+
dst := (*(void))(dst_base &+ self._length);
|
|
432
|
+
_ := memcpy(dst, (*(void))(src), count * sizeof(T));
|
|
437
433
|
self._length = (self._length + count);
|
|
438
434
|
},
|
|
439
435
|
.None => panic("ArrayList.extend_from_ptr: no ptr after ensure_total_capacity")
|
|
@@ -441,44 +437,43 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
441
437
|
}
|
|
442
438
|
);
|
|
443
439
|
}),
|
|
444
|
-
|
|
445
440
|
/**
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
clear : (fn(self: Self) -> unit)({
|
|
441
|
+
* Clear all elements but keep capacity
|
|
442
|
+
*/
|
|
443
|
+
clear : (fn(self : Self) -> unit)({
|
|
449
444
|
Self._free_elements(self);
|
|
450
445
|
self._length = usize(0);
|
|
451
446
|
}),
|
|
452
|
-
|
|
453
447
|
/**
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
fill_with_byte : (fn(self: Self, byte_val: int) -> unit)(
|
|
459
|
-
match(
|
|
448
|
+
* Fill all elements with a byte pattern using memset.
|
|
449
|
+
* Useful for zeroing bool/integer arrays in O(1).
|
|
450
|
+
* Only safe for types without RC (e.g., bool, u8, usize).
|
|
451
|
+
*/
|
|
452
|
+
fill_with_byte : (fn(self : Self, byte_val : int) -> unit)(
|
|
453
|
+
match(
|
|
454
|
+
self._ptr,
|
|
460
455
|
.None => (),
|
|
461
456
|
.Some(_ptr) => {
|
|
462
|
-
_ := memset((*(void))(_ptr), byte_val,
|
|
457
|
+
_ := memset((*(void))(_ptr), byte_val, self._length * sizeof(T));
|
|
463
458
|
}
|
|
464
459
|
)
|
|
465
460
|
),
|
|
466
|
-
|
|
467
461
|
/**
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
resize_with_byte : (fn(self: Self, new_len: usize, byte_val: int) -> unit)({
|
|
462
|
+
* Resize ArrayList to exactly `new_len` elements, filling new slots with
|
|
463
|
+
* a byte pattern via memset. Does not call destructors on removed elements.
|
|
464
|
+
* Only safe for trivial types (bool, u8, usize, etc.).
|
|
465
|
+
*/
|
|
466
|
+
resize_with_byte : (fn(self : Self, new_len : usize, byte_val : int) -> unit)({
|
|
473
467
|
cond(
|
|
474
468
|
(new_len <= self._length) => {
|
|
475
469
|
self._length = new_len;
|
|
476
470
|
},
|
|
477
471
|
true => {
|
|
478
472
|
self.ensure_total_capacity(new_len);
|
|
479
|
-
match(
|
|
473
|
+
match(
|
|
474
|
+
self._ptr,
|
|
480
475
|
.Some(_ptr) => {
|
|
481
|
-
start := (*(void))(
|
|
476
|
+
start := (*(void))(_ptr &+ self._length);
|
|
482
477
|
fill_count := ((new_len - self._length) * sizeof(T));
|
|
483
478
|
_ := memset(start, byte_val, fill_count);
|
|
484
479
|
self._length = new_len;
|
|
@@ -489,115 +484,133 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
489
484
|
);
|
|
490
485
|
})
|
|
491
486
|
);
|
|
492
|
-
impl(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
)
|
|
505
|
-
|
|
506
|
-
|
|
487
|
+
impl(
|
|
488
|
+
forall(T : Type),
|
|
489
|
+
ArrayList(T),
|
|
490
|
+
Index(usize)(
|
|
491
|
+
/// The output type is the element type `T`.
|
|
492
|
+
Output : T,
|
|
493
|
+
/// Returns a pointer to the element at the given index. Panics if the index is out of bounds.
|
|
494
|
+
index : (fn(self : *(Self), idx : usize) -> *(Self.Output))({
|
|
495
|
+
assert(idx < self.*._length, "ArrayList: index out of bounds");
|
|
496
|
+
match(
|
|
497
|
+
self.*._ptr,
|
|
498
|
+
.Some(_ptr) => (_ptr &+ idx),
|
|
499
|
+
.None => panic("ArrayList: index on empty list")
|
|
500
|
+
)
|
|
501
|
+
})
|
|
502
|
+
)
|
|
503
|
+
);
|
|
504
|
+
impl(
|
|
505
|
+
forall(T : Type),
|
|
506
|
+
ArrayList(T),
|
|
507
|
+
Dispose(
|
|
508
|
+
/**
|
|
507
509
|
* RAII destructor - automatically called when ArrayList goes out of scope
|
|
508
510
|
* For `object`, this is called when the reference count drops to zero
|
|
509
511
|
*/
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
)
|
|
522
|
-
|
|
512
|
+
dispose : (fn(self : Self) -> unit)({
|
|
513
|
+
match(
|
|
514
|
+
self._ptr,
|
|
515
|
+
.Some(_ptr) => {
|
|
516
|
+
Self._free_elements(self);
|
|
517
|
+
self._length = usize(0);
|
|
518
|
+
GlobalAllocator.free(.Some(*(void)(_ptr)));
|
|
519
|
+
self._ptr =.None;
|
|
520
|
+
},
|
|
521
|
+
.None => ()
|
|
522
|
+
);
|
|
523
|
+
})
|
|
524
|
+
)
|
|
525
|
+
);
|
|
523
526
|
// === Iterator support ===
|
|
524
|
-
|
|
525
527
|
/**
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
528
|
+
* Value iterator for ArrayList - yields elements by value (T)
|
|
529
|
+
* Used by into_iter() / IntoIterator trait
|
|
530
|
+
*/
|
|
529
531
|
ArrayListIter :: (fn(comptime(T) : Type) -> comptime(Type))(
|
|
530
532
|
struct(
|
|
531
|
-
_list
|
|
533
|
+
_list : ArrayList(T),
|
|
532
534
|
_index : usize
|
|
533
535
|
)
|
|
534
536
|
);
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
537
|
+
impl(
|
|
538
|
+
forall(T : Type),
|
|
539
|
+
ArrayListIter(T),
|
|
540
|
+
Iterator(
|
|
541
|
+
Item : T,
|
|
542
|
+
next : (fn(self : *(Self)) -> Option(T))(
|
|
543
|
+
cond(
|
|
544
|
+
(self._index >= self._list._length) =>.None,
|
|
545
|
+
true => {
|
|
546
|
+
value := self._list.get(self._index);
|
|
547
|
+
self._index = (self._index + usize(1));
|
|
548
|
+
value
|
|
549
|
+
}
|
|
550
|
+
)
|
|
546
551
|
)
|
|
547
552
|
)
|
|
548
|
-
)
|
|
549
|
-
|
|
550
|
-
|
|
553
|
+
);
|
|
554
|
+
impl(
|
|
555
|
+
forall(T : Type),
|
|
556
|
+
ArrayList(T),
|
|
551
557
|
into_iter : (fn(self : Self) -> ArrayListIter(T))(
|
|
552
|
-
ArrayListIter(T)(_list: self, _index: usize(0))
|
|
558
|
+
ArrayListIter(T)(_list : self, _index : usize(0))
|
|
553
559
|
)
|
|
554
560
|
);
|
|
555
|
-
|
|
556
561
|
/**
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
562
|
+
* Pointer iterator for ArrayList - yields pointers to elements (*(T))
|
|
563
|
+
* Used by iter() method
|
|
564
|
+
*/
|
|
560
565
|
ArrayListIterPtr :: (fn(comptime(T) : Type) -> comptime(Type))(
|
|
561
566
|
struct(
|
|
562
|
-
_list
|
|
567
|
+
_list : ArrayList(T),
|
|
563
568
|
_index : usize
|
|
564
569
|
)
|
|
565
570
|
);
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
self.
|
|
577
|
-
.Some(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
571
|
+
impl(
|
|
572
|
+
forall(T : Type),
|
|
573
|
+
ArrayListIterPtr(T),
|
|
574
|
+
Iterator(
|
|
575
|
+
Item : *(T),
|
|
576
|
+
next : (fn(self : *(Self)) -> Option(*(T)))(
|
|
577
|
+
cond(
|
|
578
|
+
(self._index >= self._list._length) =>.None,
|
|
579
|
+
true =>
|
|
580
|
+
match(
|
|
581
|
+
self._list._ptr,
|
|
582
|
+
.Some(ptr) => {
|
|
583
|
+
element_ptr := (ptr &+ self._index);
|
|
584
|
+
self._index = (self._index + usize(1));
|
|
585
|
+
.Some(element_ptr)
|
|
586
|
+
},
|
|
587
|
+
.None =>.None
|
|
588
|
+
)
|
|
589
|
+
)
|
|
581
590
|
)
|
|
582
591
|
)
|
|
583
|
-
)
|
|
584
|
-
|
|
585
|
-
|
|
592
|
+
);
|
|
593
|
+
impl(
|
|
594
|
+
forall(T : Type),
|
|
595
|
+
ArrayList(T),
|
|
586
596
|
iter : (fn(self : *(Self)) -> ArrayListIterPtr(T))(
|
|
587
|
-
ArrayListIterPtr(T)(_list: self.*, _index: usize(0))
|
|
597
|
+
ArrayListIterPtr(T)(_list : self.*, _index : usize(0))
|
|
588
598
|
)
|
|
589
599
|
);
|
|
590
|
-
|
|
591
|
-
|
|
600
|
+
impl(
|
|
601
|
+
forall(T : Type),
|
|
602
|
+
where(T <: Eq(T)),
|
|
603
|
+
ArrayList(T),
|
|
592
604
|
/**
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
contains : (fn(self: Self, value: T) -> bool)({
|
|
605
|
+
* Check if the list contains a value
|
|
606
|
+
*/
|
|
607
|
+
contains : (fn(self : Self, value : T) -> bool)({
|
|
596
608
|
found := false;
|
|
597
|
-
match(
|
|
609
|
+
match(
|
|
610
|
+
self._ptr,
|
|
598
611
|
.Some(_ptr) => {
|
|
599
612
|
i := usize(0);
|
|
600
|
-
while((
|
|
613
|
+
while((i < self._length) && !(found), i = (i + usize(1)), {
|
|
601
614
|
cond(
|
|
602
615
|
((_ptr &+ i).* == value) => {
|
|
603
616
|
found = true;
|
|
@@ -608,23 +621,23 @@ impl(forall(T : Type), where(T <: Eq(T)), ArrayList(T),
|
|
|
608
621
|
},
|
|
609
622
|
.None => ()
|
|
610
623
|
);
|
|
611
|
-
return
|
|
624
|
+
return(found);
|
|
612
625
|
}),
|
|
613
|
-
|
|
614
626
|
/**
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
index_of : (fn(self: Self, value: T) -> Option(usize))({
|
|
619
|
-
(result : Option(usize))
|
|
627
|
+
* Find the first index of a matching value
|
|
628
|
+
* Returns .Some(index) if found, .None otherwise
|
|
629
|
+
*/
|
|
630
|
+
index_of : (fn(self : Self, value : T) -> Option(usize))({
|
|
631
|
+
(result : Option(usize)) =.None;
|
|
620
632
|
found := false;
|
|
621
|
-
match(
|
|
633
|
+
match(
|
|
634
|
+
self._ptr,
|
|
622
635
|
.Some(_ptr) => {
|
|
623
636
|
i := usize(0);
|
|
624
|
-
while((
|
|
637
|
+
while((i < self._length) && !(found), i = (i + usize(1)), {
|
|
625
638
|
cond(
|
|
626
639
|
((_ptr &+ i).* == value) => {
|
|
627
|
-
result
|
|
640
|
+
result =.Some(i);
|
|
628
641
|
found = true;
|
|
629
642
|
},
|
|
630
643
|
true => ()
|
|
@@ -633,23 +646,28 @@ impl(forall(T : Type), where(T <: Eq(T)), ArrayList(T),
|
|
|
633
646
|
},
|
|
634
647
|
.None => ()
|
|
635
648
|
);
|
|
636
|
-
return
|
|
649
|
+
return(result);
|
|
637
650
|
})
|
|
638
651
|
);
|
|
639
|
-
|
|
640
|
-
|
|
652
|
+
impl(
|
|
653
|
+
forall(T : Type),
|
|
654
|
+
ArrayList(T),
|
|
641
655
|
/**
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
reverse : (fn(self: Self) -> unit)({
|
|
656
|
+
* Reverse elements in place
|
|
657
|
+
*/
|
|
658
|
+
reverse : (fn(self : Self) -> unit)({
|
|
645
659
|
cond(
|
|
646
660
|
(self._length <= usize(1)) => (),
|
|
647
661
|
true =>
|
|
648
|
-
match(
|
|
662
|
+
match(
|
|
663
|
+
self._ptr,
|
|
649
664
|
.Some(_ptr) => {
|
|
650
665
|
i := usize(0);
|
|
651
666
|
j := (self._length - usize(1));
|
|
652
|
-
while(
|
|
667
|
+
while(i < j, {
|
|
668
|
+
i = (i + usize(1));
|
|
669
|
+
j = (j - usize(1));
|
|
670
|
+
}, {
|
|
653
671
|
tmp := (_ptr &+ i).*;
|
|
654
672
|
(_ptr &+ i).* = (_ptr &+ j).*;
|
|
655
673
|
(_ptr &+ j).* = tmp;
|
|
@@ -660,19 +678,22 @@ impl(forall(T : Type), ArrayList(T),
|
|
|
660
678
|
);
|
|
661
679
|
})
|
|
662
680
|
);
|
|
663
|
-
|
|
664
|
-
|
|
681
|
+
impl(
|
|
682
|
+
forall(T : Type),
|
|
683
|
+
where(T <: Ord(T)),
|
|
684
|
+
ArrayList(T),
|
|
665
685
|
/**
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
sort : (fn(self: Self) -> unit)({
|
|
686
|
+
* Sort elements in ascending order using insertion sort
|
|
687
|
+
*/
|
|
688
|
+
sort : (fn(self : Self) -> unit)({
|
|
669
689
|
cond(
|
|
670
690
|
(self._length <= usize(1)) => (),
|
|
671
691
|
true =>
|
|
672
|
-
match(
|
|
692
|
+
match(
|
|
693
|
+
self._ptr,
|
|
673
694
|
.Some(_ptr) => {
|
|
674
695
|
i := usize(1);
|
|
675
|
-
while(
|
|
696
|
+
while(i < self._length, i = (i + usize(1)), {
|
|
676
697
|
key := (_ptr &+ i).*;
|
|
677
698
|
j := i;
|
|
678
699
|
shifting := cond(
|
|
@@ -695,64 +716,78 @@ impl(forall(T : Type), where(T <: Ord(T)), ArrayList(T),
|
|
|
695
716
|
);
|
|
696
717
|
})
|
|
697
718
|
);
|
|
698
|
-
|
|
699
719
|
/// Equality for ArrayList — two lists are equal if they have the same length
|
|
700
720
|
/// and every pair of elements at corresponding indices is equal.
|
|
701
|
-
impl(
|
|
702
|
-
(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
721
|
+
impl(
|
|
722
|
+
forall(T : Type),
|
|
723
|
+
where(T <: Eq(T)),
|
|
724
|
+
ArrayList(T),
|
|
725
|
+
Eq(ArrayList(T))(
|
|
726
|
+
(==) : (fn(lhs : Self, rhs : Self) -> bool)({
|
|
727
|
+
n := lhs.len();
|
|
728
|
+
cond(
|
|
729
|
+
(!(n == rhs.len())) => false,
|
|
730
|
+
true => {
|
|
731
|
+
(i : usize) = usize(0);
|
|
732
|
+
(equal : bool) = true;
|
|
733
|
+
while(runtime((i < n) && equal), {
|
|
734
|
+
match(
|
|
735
|
+
lhs.get(i),
|
|
736
|
+
.Some(a) => match(
|
|
737
|
+
rhs.get(i),
|
|
738
|
+
.Some(b) => {
|
|
739
|
+
equal = (a == b);
|
|
740
|
+
},
|
|
741
|
+
.None => {
|
|
742
|
+
equal = false;
|
|
743
|
+
}
|
|
744
|
+
),
|
|
745
|
+
.None => {
|
|
746
|
+
equal = false;
|
|
747
|
+
}
|
|
748
|
+
);
|
|
749
|
+
i = (i + usize(1));
|
|
750
|
+
});
|
|
751
|
+
equal
|
|
752
|
+
}
|
|
753
|
+
)
|
|
754
|
+
})
|
|
755
|
+
)
|
|
756
|
+
);
|
|
725
757
|
/// Clone implementation for ArrayList — deep-clones each element.
|
|
726
|
-
impl(
|
|
727
|
-
|
|
728
|
-
|
|
758
|
+
impl(
|
|
759
|
+
forall(T : Type),
|
|
760
|
+
where(T <: Clone),
|
|
761
|
+
ArrayList(T),
|
|
762
|
+
Clone(
|
|
763
|
+
clone : (fn(self : *(Self)) -> Self)({
|
|
729
764
|
n := self.*.len();
|
|
730
765
|
result := Self.with_capacity(n);
|
|
731
766
|
i := usize(0);
|
|
732
|
-
while
|
|
767
|
+
while(i < n, {
|
|
733
768
|
item_opt := self.*.get(i);
|
|
734
|
-
match(
|
|
735
|
-
|
|
769
|
+
match(
|
|
770
|
+
item_opt,
|
|
771
|
+
.Some(item) => {
|
|
772
|
+
result.push((&(item)).clone());
|
|
773
|
+
},
|
|
736
774
|
.None => ()
|
|
737
775
|
);
|
|
738
776
|
i = (i + usize(1));
|
|
739
|
-
};
|
|
777
|
+
});
|
|
740
778
|
result
|
|
741
|
-
}
|
|
779
|
+
})
|
|
742
780
|
)
|
|
743
|
-
)
|
|
744
|
-
|
|
745
|
-
export
|
|
781
|
+
);
|
|
782
|
+
export(
|
|
746
783
|
ArrayList,
|
|
747
784
|
ArrayListError,
|
|
748
785
|
ArrayListIter,
|
|
749
786
|
ArrayListIterPtr
|
|
750
|
-
;
|
|
751
|
-
|
|
787
|
+
);
|
|
752
788
|
// =============================================================================
|
|
753
789
|
// array_list! literal macro
|
|
754
790
|
// =============================================================================
|
|
755
|
-
|
|
756
791
|
/// Internal helper: build a list of `tmp.push(elem)` statements from `elems`.
|
|
757
792
|
__array_list_build_pushes :: (fn(comptime(tmp) : Expr, comptime(elems) : ExprList) -> comptime(ExprList))(
|
|
758
793
|
cond(
|
|
@@ -760,12 +795,11 @@ __array_list_build_pushes :: (fn(comptime(tmp) : Expr, comptime(elems) : ExprLis
|
|
|
760
795
|
true => {
|
|
761
796
|
first :: elems.car();
|
|
762
797
|
rest :: elems.cdr();
|
|
763
|
-
stmt :: quote(
|
|
798
|
+
stmt :: quote(unquote(tmp).push(unquote(first)));
|
|
764
799
|
stmt.cons(recur(tmp, rest))
|
|
765
800
|
}
|
|
766
801
|
)
|
|
767
802
|
);
|
|
768
|
-
|
|
769
803
|
/// `array_list` macro — construct an `ArrayList(T)` literal.
|
|
770
804
|
///
|
|
771
805
|
/// The element type `T` is inferred from the first element via `typeof`, so
|
|
@@ -788,20 +822,22 @@ __array_list_build_pushes :: (fn(comptime(tmp) : Expr, comptime(elems) : ExprLis
|
|
|
788
822
|
/// __tmp
|
|
789
823
|
/// }
|
|
790
824
|
/// ```
|
|
791
|
-
array_list :: (fn(...(quote(elems))) -> unquote(Expr))
|
|
792
|
-
__ :: comptime_assert(
|
|
793
|
-
|
|
825
|
+
array_list :: (fn(...(quote(elems))) -> unquote(Expr))({
|
|
826
|
+
__ :: comptime_assert(
|
|
827
|
+
elems.len() > usize(0),
|
|
828
|
+
"array_list requires at least one element to infer the element type"
|
|
829
|
+
);
|
|
794
830
|
first :: elems.car();
|
|
795
831
|
rest :: elems.cdr();
|
|
796
832
|
tmp :: gensym("array_list");
|
|
797
833
|
first_tmp :: gensym("array_list_first");
|
|
798
834
|
rest_pushes :: __array_list_build_pushes(tmp, rest);
|
|
799
|
-
quote
|
|
835
|
+
quote({
|
|
800
836
|
unquote(first_tmp) := unquote(first);
|
|
801
837
|
unquote(tmp) := ArrayList(typeof(unquote(first_tmp))).new();
|
|
802
838
|
unquote(tmp).push(unquote(first_tmp));
|
|
803
839
|
unquote_splicing(rest_pushes);
|
|
804
840
|
unquote(tmp)
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
export
|
|
841
|
+
})
|
|
842
|
+
});
|
|
843
|
+
export(array_list);
|