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.
Files changed (62) hide show
  1. package/NOMEN_AGENTS.md +57 -12
  2. package/core/System/Array.nm +11 -11
  3. package/core/System/Buffer.nm +2 -2
  4. package/core/System/Channel.nm +146 -12
  5. package/core/System/ClassBuffer.nm +2 -2
  6. package/core/System/Console.nm +28 -17
  7. package/core/System/Controls/Button.nm +96 -8
  8. package/core/System/Controls/CheckBox.nm +117 -12
  9. package/core/System/Controls/Container.nm +114 -8
  10. package/core/System/Controls/Text.nm +98 -8
  11. package/core/System/Controls/TextBox.nm +120 -10
  12. package/core/System/Controls/Window.nm +231 -23
  13. package/core/System/Graph.nm +1 -1
  14. package/core/System/Init.nm +4 -8
  15. package/core/System/LinkedList.nm +1 -1
  16. package/core/System/List.nm +3 -3
  17. package/core/System/Map.nm +5 -5
  18. package/core/System/Math.nm +10 -32
  19. package/core/System/Result.nm +1 -1
  20. package/core/System/Set.nm +4 -4
  21. package/core/System/Stream/Directory.nm +189 -63
  22. package/core/System/Stream/DirectoryError.nm +21 -0
  23. package/core/System/Stream/File.nm +339 -141
  24. package/core/System/Stream/FileError.nm +21 -0
  25. package/core/System/Stream/Http.nm +109 -44
  26. package/core/System/Stream/HttpError.nm +20 -0
  27. package/core/System/String.nm +83 -69
  28. package/core/System/StringBuilder.nm +11 -13
  29. package/core/System/Task.nm +46 -12
  30. package/core/System/Test.nm +1 -1
  31. package/core/System/Text/Json.nm +5 -3
  32. package/core/System/Text/JsonTree.nm +23 -14
  33. package/core/System/Text/Regex.nm +124 -64
  34. package/core/System/Tree.nm +1 -1
  35. package/core/System/bool.nm +4 -9
  36. package/core/System/char.nm +3 -9
  37. package/core/System/float.nm +2 -1
  38. package/core/System/float32.nm +44 -0
  39. package/core/System/float64.nm +44 -0
  40. package/core/System/int.nm +3 -9
  41. package/core/System/int16.nm +47 -0
  42. package/core/System/int32.nm +47 -0
  43. package/core/System/int64.nm +3 -9
  44. package/core/System/int8.nm +3 -9
  45. package/core/System/ufloat.nm +44 -0
  46. package/core/System/ufloat32.nm +44 -0
  47. package/core/System/ufloat64.nm +44 -0
  48. package/core/System/uint.nm +3 -9
  49. package/core/System/uint16.nm +47 -0
  50. package/core/System/uint32.nm +47 -0
  51. package/core/System/uint64.nm +3 -9
  52. package/core/System/uint8.nm +3 -9
  53. package/core/docs/System/Channel.md +2 -0
  54. package/core/docs/System/Result.md +5 -1
  55. package/core/docs/System/Task.md +1 -1
  56. package/dist/index.mjs +38794 -21299
  57. package/package.json +38 -34
  58. package/src/args.ts +11 -0
  59. package/src/index.ts +21 -3
  60. package/src/init.ts +1 -1
  61. package/src/test.ts +48 -4
  62. package/src/types/Config.ts +2 -0
@@ -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
- // The spawn build phase allocates a heap slot (owned by the future) and
69
- // the trampoline writes the function's return value there before exiting.
70
- // For tasks with no return value (void functions), returns the zero value.
71
- pub func result = (ref self, out T) {
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
- return *(T *)self->result_slot;
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
- // return *(T *)self->result_slot
105
- ldr x0, [x19, #24]
106
- ldr x0, [x0]
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. The Task instance itself is freed by the
240
- // auto-free pass after #destroy returns.
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]
@@ -36,7 +36,7 @@
36
36
  *
37
37
  * A test function receives the tester by mutable reference:
38
38
  *
39
- * import System/Test
39
+ * import System::Test
40
40
  *
41
41
  * pub func test_add = (ref Tester t) {
42
42
  * t.expect(add(1, 1) == 2, "1 + 1 should be 2")
@@ -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
- pub func serialize = (string value, out string) {
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
- pub func deserialize = (string json, out string) {
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 48, text at +16.
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, #48
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, #48
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) = 48 (vt + 5 fields * 8)
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 x2, [sp, #8]
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, #48
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
- pub func match = (string pattern, string input, out string) {
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 (null-terminated).
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
- #arch: c
132
- if (pos >= len || charset[0] == 0) return len;
133
- char* found = strpbrk(input + pos, charset);
134
- if (found == NULL) return len;
135
- return (int)(found - input);
136
- ```
137
- ```
138
- #arch: aarch64
139
- // Free function: x0 = input, x1 = pos, x2 = len, x3 = charset
140
- sub sp, sp, #32
141
- str x0, [sp, #0] // input
142
- str x2, [sp, #8] // len (default return)
143
- cmp x1, x2
144
- b.ge .Lfnb_default
145
- ldrb w9, [x3]
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
- func collect_first_bytes = (string pattern, int pat_pos, int pat_end, ref StringBuilder sb) {
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
- switch {
181
- case (c as int) == 92 {
182
- // escaped literal: '\x' → first byte is x
183
- if i == alt_start {
184
- if i + 1 < pat_end {
185
- sb.append_char(pattern.at(i + 1))
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
- i += 2
189
- }
190
- case c == '[' {
191
- if i == alt_start {
192
- var int a_end = atom_end_pos(pattern, i, pat_end)
193
- add_class_chars(pattern, i + 1, a_end - 1, ref sb)
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
- case c == ')' {
202
- if depth > 0 {
203
- depth -= 1
204
- }
205
- i += 1
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
- case (c as int) == 124 {
208
- if depth == 0 {
209
- alt_start = i + 1
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
- case i == alt_start && depth == 0 && c != '^' && c != '$' && c != '.' {
214
- sb.append_char(c)
215
- i += 1
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
- else {
218
- i += 1
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
@@ -13,7 +13,7 @@ pub struct Tree<T>: Enumerable {
13
13
  var parents = Buffer<int>()
14
14
  var count = 0
15
15
 
16
- pub func add = (ref self, mov T value) {
16
+ pub func add = (ref self, move T value) {
17
17
  const int idx = self.count
18
18
  self.values.grow_int(idx + 1)
19
19
  const int v = value
@@ -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
@@ -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
@@ -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
+ }
@@ -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