nomen-lang 0.0.19 → 0.2.0
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/NOMEN_AGENTS.md +57 -12
- package/core/System/Array.nm +11 -11
- package/core/System/Buffer.nm +2 -2
- package/core/System/Channel.nm +146 -12
- package/core/System/ClassBuffer.nm +2 -2
- package/core/System/Console.nm +28 -17
- package/core/System/Controls/Button.nm +96 -8
- package/core/System/Controls/CheckBox.nm +117 -12
- package/core/System/Controls/Container.nm +114 -8
- package/core/System/Controls/Text.nm +98 -8
- package/core/System/Controls/TextBox.nm +120 -10
- package/core/System/Controls/Window.nm +231 -23
- package/core/System/Graph.nm +1 -1
- package/core/System/Init.nm +4 -8
- package/core/System/LinkedList.nm +1 -1
- package/core/System/List.nm +3 -3
- package/core/System/Map.nm +5 -5
- package/core/System/Math.nm +10 -32
- package/core/System/Result.nm +1 -1
- package/core/System/Set.nm +4 -4
- package/core/System/Stream/Directory.nm +189 -63
- package/core/System/Stream/DirectoryError.nm +21 -0
- package/core/System/Stream/File.nm +339 -141
- package/core/System/Stream/FileError.nm +21 -0
- package/core/System/Stream/Http.nm +109 -44
- package/core/System/Stream/HttpError.nm +20 -0
- package/core/System/String.nm +83 -69
- package/core/System/StringBuilder.nm +11 -13
- package/core/System/Task.nm +46 -12
- package/core/System/Test.nm +1 -1
- package/core/System/Text/Json.nm +5 -3
- package/core/System/Text/JsonTree.nm +23 -14
- package/core/System/Text/Regex.nm +124 -64
- package/core/System/Tree.nm +1 -1
- package/core/System/bool.nm +4 -9
- package/core/System/char.nm +3 -9
- package/core/System/float.nm +2 -1
- package/core/System/float32.nm +44 -0
- package/core/System/float64.nm +44 -0
- package/core/System/int.nm +3 -9
- package/core/System/int16.nm +47 -0
- package/core/System/int32.nm +47 -0
- package/core/System/int64.nm +3 -9
- package/core/System/int8.nm +3 -9
- package/core/System/ufloat.nm +44 -0
- package/core/System/ufloat32.nm +44 -0
- package/core/System/ufloat64.nm +44 -0
- package/core/System/uint.nm +3 -9
- package/core/System/uint16.nm +47 -0
- package/core/System/uint32.nm +47 -0
- package/core/System/uint64.nm +3 -9
- package/core/System/uint8.nm +3 -9
- package/core/docs/System/Channel.md +2 -0
- package/core/docs/System/Result.md +5 -1
- package/core/docs/System/Task.md +1 -1
- package/dist/index.mjs +38794 -21299
- package/package.json +38 -34
- package/src/args.ts +11 -0
- package/src/index.ts +21 -3
- package/src/init.ts +1 -1
- package/src/test.ts +48 -4
- package/src/types/Config.ts +2 -0
package/core/System/Task.nm
CHANGED
|
@@ -64,11 +64,15 @@ pub class Task<T> : Sendable {
|
|
|
64
64
|
```
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
// Block until the task finishes, then return its result as T.
|
|
68
|
-
//
|
|
69
|
-
// the
|
|
70
|
-
//
|
|
71
|
-
|
|
67
|
+
// Block until the task finishes, then return its result as T. The spawn
|
|
68
|
+
// build phase allocates a heap slot (owned by the future) sized to hold
|
|
69
|
+
// the full return value — including the 16-byte fat-string pair — and the
|
|
70
|
+
// trampoline writes the function's return value there before exiting.
|
|
71
|
+
// The result is MOVED OUT: the slot is zeroed as the value leaves, and
|
|
72
|
+
// `move out T` marks the caller as the owner. Call it once; a second call
|
|
73
|
+
// returns the zero value. For tasks with no return value (void
|
|
74
|
+
// functions), returns the zero value.
|
|
75
|
+
pub func result = (ref self, move out T) {
|
|
72
76
|
```
|
|
73
77
|
#arch: c
|
|
74
78
|
if (self->future) {
|
|
@@ -79,7 +83,9 @@ pub class Task<T> : Sendable {
|
|
|
79
83
|
self->handle = 0;
|
|
80
84
|
self->done = 1;
|
|
81
85
|
}
|
|
82
|
-
|
|
86
|
+
T _r = *(T *)self->result_slot;
|
|
87
|
+
memset((void *)self->result_slot, 0, sizeof(T));
|
|
88
|
+
return _r;
|
|
83
89
|
```
|
|
84
90
|
```
|
|
85
91
|
#arch: aarch64
|
|
@@ -101,9 +107,14 @@ pub class Task<T> : Sendable {
|
|
|
101
107
|
mov w0, #1
|
|
102
108
|
strb w0, [x19, #16]
|
|
103
109
|
.Lresult_read:
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
// The result cell is always 16 bytes (see the spawn build phase):
|
|
111
|
+
// load the full pair — a fat string returns (ptr, len) in x0/x1, a
|
|
112
|
+
// scalar returns its word in x0 — then zero the cell (the value is
|
|
113
|
+
// moved out; a second call observes the zero).
|
|
114
|
+
ldr x8, [x19, #24]
|
|
115
|
+
ldr x0, [x8]
|
|
116
|
+
ldr x1, [x8, #8]
|
|
117
|
+
stp xzr, xzr, [x8]
|
|
107
118
|
```
|
|
108
119
|
}
|
|
109
120
|
|
|
@@ -236,12 +247,22 @@ pub class Task<T> : Sendable {
|
|
|
236
247
|
// Release this handle's reference to the future. The future owns the
|
|
237
248
|
// result slot and cancel flag; it (and they) are freed only when the
|
|
238
249
|
// last reference — this handle, the running trampoline, or a tracking
|
|
239
|
-
// nursery — is released.
|
|
240
|
-
//
|
|
250
|
+
// nursery — is released. A string result that was never consumed
|
|
251
|
+
// (`result()` zeroes the slot when it moves the value out) is freed
|
|
252
|
+
// here, before the future releases the cell. The Task instance itself
|
|
253
|
+
// is freed by the auto-free pass after #destroy returns.
|
|
241
254
|
pub func #destroy = () {
|
|
242
255
|
```
|
|
243
256
|
#arch: c
|
|
244
257
|
if (self->future) {
|
|
258
|
+
#if T_NEEDS_STRDUP
|
|
259
|
+
// T is the fat nomen_string here (the guard is 0 for every other
|
|
260
|
+
// T, and the preprocessor removes this region before parsing).
|
|
261
|
+
if (self->result_slot) {
|
|
262
|
+
T _s = *(T *)self->result_slot;
|
|
263
|
+
if (_s.ptr) free(_s.ptr);
|
|
264
|
+
}
|
|
265
|
+
#endif
|
|
245
266
|
__nomen_future_release((struct nomen_future *)self->future);
|
|
246
267
|
self->future = 0;
|
|
247
268
|
self->result_slot = 0;
|
|
@@ -250,9 +271,22 @@ pub class Task<T> : Sendable {
|
|
|
250
271
|
```
|
|
251
272
|
```
|
|
252
273
|
#arch: aarch64
|
|
253
|
-
// if (self->future) { release; zero fields }
|
|
274
|
+
// if (self->future) { free an unconsumed string result; release; zero fields }
|
|
254
275
|
ldr x0, [x19, #40]
|
|
255
276
|
cbz x0, .Ldestroy_done
|
|
277
|
+
// An unconsumed string result: the cell still holds (ptr, len) —
|
|
278
|
+
// result() zeroes it when it moves the value out. The T_FAT dispatch
|
|
279
|
+
// folds to a constant branch after monomorphization.
|
|
280
|
+
ldr x8, [x19, #24]
|
|
281
|
+
mov x0, #T_FAT
|
|
282
|
+
cmp x0, #0
|
|
283
|
+
b.eq .Ldestroy_nofree
|
|
284
|
+
cbz x8, .Ldestroy_nofree
|
|
285
|
+
ldr x0, [x8]
|
|
286
|
+
cbz x0, .Ldestroy_nofree
|
|
287
|
+
bl _free
|
|
288
|
+
.Ldestroy_nofree:
|
|
289
|
+
ldr x0, [x19, #40]
|
|
256
290
|
bl ___nomen_future_release
|
|
257
291
|
str xzr, [x19, #40]
|
|
258
292
|
str xzr, [x19, #24]
|
package/core/System/Test.nm
CHANGED
package/core/System/Text/Json.nm
CHANGED
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
**/
|
|
15
15
|
pub struct Json {
|
|
16
16
|
// Serialize a string to a JSON string literal, escaping the special
|
|
17
|
-
// characters ", \, newline, tab and carriage return.
|
|
18
|
-
|
|
17
|
+
// characters ", \, newline, tab and carriage return. `move out string`:
|
|
18
|
+
// returns the StringBuilder's owned heap copy.
|
|
19
|
+
pub func serialize = (string value, move out string) {
|
|
19
20
|
var sb = StringBuilder()
|
|
20
21
|
sb.append_char('"')
|
|
21
22
|
var i = 0
|
|
@@ -49,7 +50,8 @@ pub struct Json {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
// Deserialize a JSON string literal to the raw, unescaped value.
|
|
52
|
-
|
|
53
|
+
// `move out string`: returns the StringBuilder's owned heap copy.
|
|
54
|
+
pub func deserialize = (string json, move out string) {
|
|
53
55
|
var sb = StringBuilder()
|
|
54
56
|
var int len = json.length
|
|
55
57
|
var i = 0
|
|
@@ -40,22 +40,25 @@ pub struct JsonTree {
|
|
|
40
40
|
```
|
|
41
41
|
#arch: c
|
|
42
42
|
JsonNode *nodes = (JsonNode*)(unsigned long long)self->nodes.data;
|
|
43
|
-
free(nodes[idx].text);
|
|
44
|
-
nodes[idx].text = 0;
|
|
43
|
+
free(nodes[idx].text.ptr);
|
|
44
|
+
nodes[idx].text.ptr = 0;
|
|
45
|
+
nodes[idx].text.len = 0;
|
|
45
46
|
```
|
|
46
47
|
```
|
|
47
48
|
#arch: aarch64
|
|
48
49
|
// x19 = self. count is at self+32 and already equals idx+1 here, so
|
|
49
|
-
// idx = count - 1. nodes.data at self+16, JsonNode size
|
|
50
|
+
// idx = count - 1. nodes.data at self+16, JsonNode size 56 (fat text),
|
|
51
|
+
// text at +16 (ptr) / +24 (len).
|
|
50
52
|
ldr x0, [x19, #16]
|
|
51
53
|
ldr x1, [x19, #32]
|
|
52
54
|
sub x1, x1, #1
|
|
53
|
-
mov x3, #
|
|
55
|
+
mov x3, #56
|
|
54
56
|
madd x1, x1, x3, xzr
|
|
55
57
|
add x0, x0, x1
|
|
56
58
|
add x0, x0, #16
|
|
57
59
|
ldr x1, [x0]
|
|
58
60
|
str xzr, [x0]
|
|
61
|
+
str xzr, [x0, #8]
|
|
59
62
|
cbz x1, .Lalloc_node_text_skip
|
|
60
63
|
mov x0, x1
|
|
61
64
|
bl _free
|
|
@@ -70,13 +73,13 @@ pub struct JsonTree {
|
|
|
70
73
|
```
|
|
71
74
|
#arch: c
|
|
72
75
|
JsonNode *nodes = (JsonNode*)(unsigned long long)self->nodes.data;
|
|
73
|
-
if (nodes[idx].text) { free(nodes[idx].text); nodes[idx].text = 0; }
|
|
76
|
+
if (nodes[idx].text.ptr) { free(nodes[idx].text.ptr); nodes[idx].text.ptr = 0; nodes[idx].text.len = 0; }
|
|
74
77
|
```
|
|
75
78
|
```
|
|
76
79
|
#arch: aarch64
|
|
77
|
-
// x19 = self, x1 = idx. Compute &nodes[idx].text.
|
|
80
|
+
// x19 = self, x1 = idx. Compute &nodes[idx].text (JsonNode size 56).
|
|
78
81
|
ldr x0, [x19, #16]
|
|
79
|
-
mov x3, #
|
|
82
|
+
mov x3, #56
|
|
80
83
|
madd x1, x1, x3, xzr
|
|
81
84
|
add x0, x0, x1
|
|
82
85
|
add x0, x0, #16
|
|
@@ -87,6 +90,7 @@ pub struct JsonTree {
|
|
|
87
90
|
bl _free
|
|
88
91
|
ldr x0, [sp], #16
|
|
89
92
|
str xzr, [x0]
|
|
93
|
+
str xzr, [x0, #8]
|
|
90
94
|
.Ljsontree_free_text_skip:
|
|
91
95
|
```
|
|
92
96
|
}
|
|
@@ -113,33 +117,38 @@ pub struct JsonTree {
|
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
// strdup directly into the slab — see file header for why this can't
|
|
116
|
-
// go through load_T/store_T.
|
|
120
|
+
// go through load_T/store_T. (Under the fat-string ABI the C body is
|
|
121
|
+
// emitted behind the _raw_ adapter, so `text` arrives as a thin char*;
|
|
122
|
+
// aarch64 receives the pair x2 = ptr, x3 = len.)
|
|
117
123
|
func set_text = (ref self, int idx, string text) {
|
|
118
124
|
```
|
|
119
125
|
#arch: c
|
|
120
126
|
JsonNode *nodes = (JsonNode*)(unsigned long long)self->nodes.data;
|
|
121
|
-
nodes[idx].text = strdup(text);
|
|
127
|
+
nodes[idx].text.ptr = strdup(text);
|
|
128
|
+
nodes[idx].text.len = (long)strlen(text);
|
|
122
129
|
```
|
|
123
130
|
```
|
|
124
131
|
#arch: aarch64
|
|
125
|
-
// x19 = self, x1 = idx, x2 = text
|
|
132
|
+
// x19 = self, x1 = idx, x2 = text.ptr, x3 = text.len
|
|
126
133
|
// nodes.data is at self+16 (JsonTree.vt[0] + Buffer.vt[8])
|
|
127
|
-
// text field is at offset 16 in JsonNode (vt[0] + kind[8])
|
|
128
|
-
// sizeof(JsonNode) =
|
|
134
|
+
// text field is at offset 16 in JsonNode (vt[0] + kind[8]); the fat
|
|
135
|
+
// field is ptr@+16, len@+24; sizeof(JsonNode) = 56.
|
|
129
136
|
sub sp, sp, #32
|
|
130
137
|
str x1, [sp, #0]
|
|
131
|
-
str
|
|
138
|
+
str x3, [sp, #8]
|
|
132
139
|
mov x0, x2
|
|
133
140
|
bl _strdup
|
|
134
141
|
str x0, [sp, #16]
|
|
135
142
|
ldr x0, [x19, #16]
|
|
136
143
|
ldr x1, [sp, #0]
|
|
137
|
-
mov x3, #
|
|
144
|
+
mov x3, #56
|
|
138
145
|
madd x1, x1, x3, xzr
|
|
139
146
|
add x0, x0, x1
|
|
140
147
|
add x0, x0, #16
|
|
141
148
|
ldr x1, [sp, #16]
|
|
142
149
|
str x1, [x0]
|
|
150
|
+
ldr x1, [sp, #8]
|
|
151
|
+
str x1, [x0, #8]
|
|
143
152
|
add sp, sp, #32
|
|
144
153
|
```
|
|
145
154
|
}
|
|
@@ -30,7 +30,9 @@ pub struct Regex {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Return the first substring of input matching pattern, or "" if none.
|
|
33
|
-
|
|
33
|
+
// `move out string`: the built match (or the copied empty literal) is
|
|
34
|
+
// handed to the caller as an owned value.
|
|
35
|
+
pub func match = (string pattern, string input, move out string) {
|
|
34
36
|
var match_result = ""
|
|
35
37
|
var int pat_len = pattern.length
|
|
36
38
|
var int len = input.length
|
|
@@ -124,101 +126,159 @@ pub struct Regex {
|
|
|
124
126
|
}
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
// Scan input[pos..len) for the next byte that appears in charset
|
|
129
|
+
// Scan input[pos..len) for the next byte that appears in charset.
|
|
128
130
|
// Returns the index of the match, or len if none found / charset is empty.
|
|
129
131
|
func find_next_byte = (string input, int pos, int len, string charset, out int) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
cbz w9, .Lfnb_default
|
|
147
|
-
add x0, x0, x1 // x0 = input + pos
|
|
148
|
-
mov x1, x3 // x1 = charset
|
|
149
|
-
bl _strpbrk
|
|
150
|
-
cbz x0, .Lfnb_default
|
|
151
|
-
ldr x9, [sp, #0] // input
|
|
152
|
-
sub x0, x0, x9 // result = found - input
|
|
153
|
-
b .Lfnb_end
|
|
154
|
-
.Lfnb_default:
|
|
155
|
-
ldr x0, [sp, #8] // return len
|
|
156
|
-
.Lfnb_end:
|
|
157
|
-
add sp, sp, #32
|
|
158
|
-
```
|
|
132
|
+
if pos >= len {
|
|
133
|
+
return len
|
|
134
|
+
}
|
|
135
|
+
if charset.length == 0 {
|
|
136
|
+
return len
|
|
137
|
+
}
|
|
138
|
+
var i = pos
|
|
139
|
+
while i < len && i < input.length; i += 1 {
|
|
140
|
+
var j = 0
|
|
141
|
+
while j < charset.length; j += 1 {
|
|
142
|
+
if input.at(i) == charset.at(j) {
|
|
143
|
+
return i
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return len
|
|
159
148
|
}
|
|
160
149
|
|
|
161
150
|
// Extract the set of possible first bytes from a pattern into a charset string.
|
|
162
|
-
// Returns "" if every byte is possible (e.g. pattern starts with '.', '
|
|
151
|
+
// Returns "" if every byte is possible (e.g. pattern starts with '.', '(' with
|
|
152
|
+
// an unbounded repeat, or an alternative whose first set can't be determined).
|
|
163
153
|
func first_byte_set = (string pattern, int pat_len, out string) {
|
|
164
154
|
if pat_len == 0 {
|
|
165
155
|
return ""
|
|
166
156
|
}
|
|
167
157
|
var sb = StringBuilder()
|
|
168
|
-
collect_first_bytes(pattern, 0, pat_len, ref sb)
|
|
158
|
+
if collect_first_bytes(pattern, 0, pat_len, ref sb) < 0 {
|
|
159
|
+
// Some alternative's first-byte set is indeterminable — a wildcard
|
|
160
|
+
// '.', an empty alternative, or similar. The charset is a PREFILTER
|
|
161
|
+
// (candidate positions via strpbrk): under-approximating it would
|
|
162
|
+
// skip positions where a match can start, so disable it entirely.
|
|
163
|
+
return ""
|
|
164
|
+
}
|
|
169
165
|
return sb.to_string()
|
|
170
166
|
}
|
|
171
167
|
|
|
172
168
|
// Walk top-level alternatives of pattern[pat_pos..pat_end), appending the first
|
|
173
169
|
// byte(s) of each alternative to sb. Alternations at depth 0 are split on '|'.
|
|
174
|
-
|
|
170
|
+
// Returns -1 when any alternative's first-byte set can't be determined (the
|
|
171
|
+
// caller must then disable the prefilter), 0 otherwise.
|
|
172
|
+
func collect_first_bytes = (string pattern, int pat_pos, int pat_end, ref StringBuilder sb, out int) {
|
|
175
173
|
var depth = 0
|
|
176
174
|
var int i = pat_pos
|
|
177
175
|
var int alt_start = pat_pos
|
|
178
176
|
while i < pat_end {
|
|
179
177
|
var char c = pattern.at(i)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
178
|
+
if (c as int) == 92 {
|
|
179
|
+
i += 2
|
|
180
|
+
} else {
|
|
181
|
+
if c == '[' {
|
|
182
|
+
i = atom_end_pos(pattern, i, pat_end)
|
|
183
|
+
} else {
|
|
184
|
+
if c == '(' {
|
|
185
|
+
depth = depth + 1
|
|
186
|
+
}
|
|
187
|
+
if c == ')' {
|
|
188
|
+
if depth > 0 {
|
|
189
|
+
depth -= 1
|
|
186
190
|
}
|
|
187
191
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
if (c as int) == 124 {
|
|
193
|
+
if depth == 0 {
|
|
194
|
+
if alt_first_bytes(pattern, alt_start, i, ref sb) < 0 {
|
|
195
|
+
return -1
|
|
196
|
+
}
|
|
197
|
+
alt_start = i + 1
|
|
198
|
+
}
|
|
194
199
|
}
|
|
195
|
-
i = atom_end_pos(pattern, i, pat_end)
|
|
196
|
-
}
|
|
197
|
-
case c == '(' {
|
|
198
|
-
depth = depth + 1
|
|
199
200
|
i += 1
|
|
200
201
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return alt_first_bytes(pattern, alt_start, pat_end, ref sb)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Append the set of bytes that can start a match of the alternative occupying
|
|
208
|
+
// pattern[start..end) to sb. Returns -1 when the set can't be determined (the
|
|
209
|
+
// caller must disable the prefilter), 0 when it was appended.
|
|
210
|
+
//
|
|
211
|
+
// Handles the shapes the engine's matcher can produce: a leading anchor is
|
|
212
|
+
// zero-width (skipped), a leading group contributes its CONTENT's first bytes
|
|
213
|
+
// (recursively over the group's own top-level alternatives), and a group
|
|
214
|
+
// quantified with '?'/'*' is nullable — what FOLLOWS it can also be first, so
|
|
215
|
+
// the scan continues past it. A wildcard '.' or an empty alternative makes the
|
|
216
|
+
// set indeterminable.
|
|
217
|
+
func alt_first_bytes = (string pattern, int start, int end, ref StringBuilder sb, out int) {
|
|
218
|
+
var int i = start
|
|
219
|
+
while i < end {
|
|
220
|
+
var char c = pattern.at(i)
|
|
221
|
+
if (c as int) == 92 {
|
|
222
|
+
// escaped literal: first byte is the escaped char
|
|
223
|
+
if i + 1 < end {
|
|
224
|
+
sb.append_char(pattern.at(i + 1))
|
|
206
225
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
226
|
+
return 0
|
|
227
|
+
}
|
|
228
|
+
if c == '[' {
|
|
229
|
+
var int a_end = atom_end_pos(pattern, i, end)
|
|
230
|
+
// A NEGATED class can match any byte outside its member set —
|
|
231
|
+
// not expressible as an inclusion charset, and under-approximating
|
|
232
|
+
// (the member bytes alone) would make strpbrk skip valid match
|
|
233
|
+
// positions. Disable the prefilter instead.
|
|
234
|
+
var int cs = i + 1
|
|
235
|
+
if cs < a_end - 1 {
|
|
236
|
+
if pattern.at(cs) == '^' {
|
|
237
|
+
return -1
|
|
210
238
|
}
|
|
211
|
-
i += 1
|
|
212
239
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
240
|
+
add_class_chars(pattern, i + 1, a_end - 1, ref sb)
|
|
241
|
+
return 0
|
|
242
|
+
}
|
|
243
|
+
if c == '(' {
|
|
244
|
+
var int a_end = atom_end_pos(pattern, i, end)
|
|
245
|
+
// The group's first bytes are the union of its content's
|
|
246
|
+
// top-level alternatives' first bytes.
|
|
247
|
+
if collect_first_bytes(pattern, i + 1, a_end - 1, ref sb) < 0 {
|
|
248
|
+
return -1
|
|
216
249
|
}
|
|
217
|
-
|
|
218
|
-
|
|
250
|
+
// A '?'/'*' quantifier makes the group nullable — the first byte
|
|
251
|
+
// can also come from whatever follows it.
|
|
252
|
+
var int after = a_end
|
|
253
|
+
var int nullable = 0
|
|
254
|
+
if after < end {
|
|
255
|
+
var char q = pattern.at(after)
|
|
256
|
+
if q == '?' || q == '*' {
|
|
257
|
+
nullable = 1
|
|
258
|
+
after += 1
|
|
259
|
+
}
|
|
219
260
|
}
|
|
261
|
+
if nullable == 0 {
|
|
262
|
+
return 0
|
|
263
|
+
}
|
|
264
|
+
i = after
|
|
265
|
+
continue
|
|
266
|
+
}
|
|
267
|
+
if c == '^' || c == '$' {
|
|
268
|
+
// zero-width assertions never consume a byte
|
|
269
|
+
i += 1
|
|
270
|
+
continue
|
|
220
271
|
}
|
|
272
|
+
if c == '.' {
|
|
273
|
+
// wildcard (any byte except '\n') — not expressible as an
|
|
274
|
+
// inclusion set; the prefilter must be disabled.
|
|
275
|
+
return -1
|
|
276
|
+
}
|
|
277
|
+
sb.append_char(c)
|
|
278
|
+
return 0
|
|
221
279
|
}
|
|
280
|
+
// An empty alternative can match at any position — indeterminable.
|
|
281
|
+
return -1
|
|
222
282
|
}
|
|
223
283
|
|
|
224
284
|
// Append the members of character class [start..end) to sb. Ranges (a-z) are
|
package/core/System/Tree.nm
CHANGED
package/core/System/bool.nm
CHANGED
|
@@ -3,14 +3,7 @@
|
|
|
3
3
|
**/
|
|
4
4
|
pub struct bool: Stringable, Hashable, Equatable {
|
|
5
5
|
pub func hash = (self, out uint) {
|
|
6
|
-
|
|
7
|
-
#arch: c
|
|
8
|
-
return (unsigned long)self;
|
|
9
|
-
```
|
|
10
|
-
```
|
|
11
|
-
#arch: aarch64
|
|
12
|
-
mov x0, x19
|
|
13
|
-
```
|
|
6
|
+
return self as uint
|
|
14
7
|
}
|
|
15
8
|
|
|
16
9
|
/**
|
|
@@ -19,7 +12,7 @@ pub struct bool: Stringable, Hashable, Equatable {
|
|
|
19
12
|
* @param self: the boolean
|
|
20
13
|
* @out string: the boolean as a string value (`"true"` or `"false"`)
|
|
21
14
|
**/
|
|
22
|
-
pub func to_string = (self, out string) {
|
|
15
|
+
pub func to_string = (self, move out string) {
|
|
23
16
|
```
|
|
24
17
|
#arch: c
|
|
25
18
|
int length = snprintf(NULL, 0, "%s", self ? "true" : "false");
|
|
@@ -49,6 +42,7 @@ pub struct bool: Stringable, Hashable, Equatable {
|
|
|
49
42
|
adr x2, .Lfmt_bool_true
|
|
50
43
|
mov x3, x19
|
|
51
44
|
bl _snprintf
|
|
45
|
+
mov x1, x0
|
|
52
46
|
ldr x0, [sp, #72]
|
|
53
47
|
add sp, sp, #128
|
|
54
48
|
b .Lend_bool_to_string
|
|
@@ -65,6 +59,7 @@ pub struct bool: Stringable, Hashable, Equatable {
|
|
|
65
59
|
adr x2, .Lfmt_bool_false
|
|
66
60
|
mov x3, x19
|
|
67
61
|
bl _snprintf
|
|
62
|
+
mov x1, x0
|
|
68
63
|
ldr x0, [sp, #72]
|
|
69
64
|
add sp, sp, #128
|
|
70
65
|
b .Lend_bool_to_string
|
package/core/System/char.nm
CHANGED
|
@@ -3,17 +3,10 @@
|
|
|
3
3
|
**/
|
|
4
4
|
pub struct char: Stringable, Hashable, Equatable {
|
|
5
5
|
pub func hash = (self, out uint) {
|
|
6
|
-
|
|
7
|
-
#arch: c
|
|
8
|
-
return (unsigned long)self;
|
|
9
|
-
```
|
|
10
|
-
```
|
|
11
|
-
#arch: aarch64
|
|
12
|
-
mov x0, x19
|
|
13
|
-
```
|
|
6
|
+
return self as uint
|
|
14
7
|
}
|
|
15
8
|
|
|
16
|
-
pub func to_string = (self, out string) {
|
|
9
|
+
pub func to_string = (self, move out string) {
|
|
17
10
|
```
|
|
18
11
|
#arch: c
|
|
19
12
|
int length = snprintf(NULL, 0, "%c", self);
|
|
@@ -42,6 +35,7 @@ pub struct char: Stringable, Hashable, Equatable {
|
|
|
42
35
|
adr x2, .Lfmt_char_c
|
|
43
36
|
mov x3, x19
|
|
44
37
|
bl _snprintf
|
|
38
|
+
mov x1, x0
|
|
45
39
|
ldr x0, [sp, #72]
|
|
46
40
|
add sp, sp, #128
|
|
47
41
|
b .Lend_char_to_string
|
package/core/System/float.nm
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* A double-precision (64-bit) floating-point number
|
|
3
3
|
**/
|
|
4
4
|
pub struct float: Stringable {
|
|
5
|
-
pub func to_string = (self, out string) {
|
|
5
|
+
pub func to_string = (self, move out string) {
|
|
6
6
|
```
|
|
7
7
|
#arch: c
|
|
8
8
|
int length = snprintf(NULL, 0, "%f", self);
|
|
@@ -32,6 +32,7 @@ pub struct float: Stringable {
|
|
|
32
32
|
adr x2, .Lfmt_float_f
|
|
33
33
|
fmov d0, x19
|
|
34
34
|
bl _snprintf
|
|
35
|
+
mov x1, x0
|
|
35
36
|
ldr x0, [sp, #72]
|
|
36
37
|
add sp, sp, #128
|
|
37
38
|
b .Lend_float_to_string
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signed double-precision (64-bit) floating-point number
|
|
3
|
+
**/
|
|
4
|
+
pub struct float32: Stringable {
|
|
5
|
+
pub func to_string = (self, move out string) {
|
|
6
|
+
```
|
|
7
|
+
#arch: c
|
|
8
|
+
int length = snprintf(NULL, 0, "%f", self);
|
|
9
|
+
char* str = malloc(length + 1);
|
|
10
|
+
snprintf(str, length + 1, "%f", self);
|
|
11
|
+
return str;
|
|
12
|
+
```
|
|
13
|
+
```
|
|
14
|
+
#arch: aarch64
|
|
15
|
+
sub sp, sp, #128
|
|
16
|
+
str x0, [sp, #0]
|
|
17
|
+
str x1, [sp, #8]
|
|
18
|
+
str x2, [sp, #16]
|
|
19
|
+
str x3, [sp, #24]
|
|
20
|
+
str d0, [sp, #64]
|
|
21
|
+
mov x0, xzr
|
|
22
|
+
mov x1, xzr
|
|
23
|
+
adr x2, .Lfmt_float32_f
|
|
24
|
+
fmov d0, x19
|
|
25
|
+
bl _snprintf
|
|
26
|
+
add x0, x0, #1
|
|
27
|
+
str x0, [sp, #64]
|
|
28
|
+
bl _malloc
|
|
29
|
+
str x0, [sp, #72]
|
|
30
|
+
ldr x0, [sp, #72]
|
|
31
|
+
ldr x1, [sp, #64]
|
|
32
|
+
adr x2, .Lfmt_float32_f
|
|
33
|
+
fmov d0, x19
|
|
34
|
+
bl _snprintf
|
|
35
|
+
mov x1, x0
|
|
36
|
+
ldr x0, [sp, #72]
|
|
37
|
+
add sp, sp, #128
|
|
38
|
+
b .Lend_float32_to_string
|
|
39
|
+
.Lfmt_float32_f: .asciz "%f"
|
|
40
|
+
.p2align 2
|
|
41
|
+
.Lend_float32_to_string:
|
|
42
|
+
```
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signed double-precision (64-bit) floating-point number
|
|
3
|
+
**/
|
|
4
|
+
pub struct float64: Stringable {
|
|
5
|
+
pub func to_string = (self, move out string) {
|
|
6
|
+
```
|
|
7
|
+
#arch: c
|
|
8
|
+
int length = snprintf(NULL, 0, "%f", self);
|
|
9
|
+
char* str = malloc(length + 1);
|
|
10
|
+
snprintf(str, length + 1, "%f", self);
|
|
11
|
+
return str;
|
|
12
|
+
```
|
|
13
|
+
```
|
|
14
|
+
#arch: aarch64
|
|
15
|
+
sub sp, sp, #128
|
|
16
|
+
str x0, [sp, #0]
|
|
17
|
+
str x1, [sp, #8]
|
|
18
|
+
str x2, [sp, #16]
|
|
19
|
+
str x3, [sp, #24]
|
|
20
|
+
str d0, [sp, #64]
|
|
21
|
+
mov x0, xzr
|
|
22
|
+
mov x1, xzr
|
|
23
|
+
adr x2, .Lfmt_float64_f
|
|
24
|
+
fmov d0, x19
|
|
25
|
+
bl _snprintf
|
|
26
|
+
add x0, x0, #1
|
|
27
|
+
str x0, [sp, #64]
|
|
28
|
+
bl _malloc
|
|
29
|
+
str x0, [sp, #72]
|
|
30
|
+
ldr x0, [sp, #72]
|
|
31
|
+
ldr x1, [sp, #64]
|
|
32
|
+
adr x2, .Lfmt_float64_f
|
|
33
|
+
fmov d0, x19
|
|
34
|
+
bl _snprintf
|
|
35
|
+
mov x1, x0
|
|
36
|
+
ldr x0, [sp, #72]
|
|
37
|
+
add sp, sp, #128
|
|
38
|
+
b .Lend_float64_to_string
|
|
39
|
+
.Lfmt_float64_f: .asciz "%f"
|
|
40
|
+
.p2align 2
|
|
41
|
+
.Lend_float64_to_string:
|
|
42
|
+
```
|
|
43
|
+
}
|
|
44
|
+
}
|
package/core/System/int.nm
CHANGED
|
@@ -3,17 +3,10 @@
|
|
|
3
3
|
**/
|
|
4
4
|
pub struct int: Stringable, Hashable, Equatable {
|
|
5
5
|
pub func hash = (self, out uint) {
|
|
6
|
-
|
|
7
|
-
#arch: c
|
|
8
|
-
return (unsigned long)self;
|
|
9
|
-
```
|
|
10
|
-
```
|
|
11
|
-
#arch: aarch64
|
|
12
|
-
mov x0, x19
|
|
13
|
-
```
|
|
6
|
+
return self as uint
|
|
14
7
|
}
|
|
15
8
|
|
|
16
|
-
pub func to_string = (self, out string) {
|
|
9
|
+
pub func to_string = (self, move out string) {
|
|
17
10
|
```
|
|
18
11
|
#arch: c
|
|
19
12
|
int length = snprintf(NULL, 0, "%ld", self);
|
|
@@ -42,6 +35,7 @@ pub struct int: Stringable, Hashable, Equatable {
|
|
|
42
35
|
adr x2, .Lfmt_int_ld
|
|
43
36
|
mov x3, x19
|
|
44
37
|
bl _snprintf
|
|
38
|
+
mov x1, x0
|
|
45
39
|
ldr x0, [sp, #72]
|
|
46
40
|
add sp, sp, #128
|
|
47
41
|
b .Lend_int_to_string
|