nomen-lang 0.0.11 → 0.0.13
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/core/System/Array.nm +104 -9
- package/core/System/Buffer.nm +144 -0
- package/core/System/ClassBuffer.nm +143 -0
- package/core/System/Graph.nm +4 -5
- package/core/System/Init.nm +3 -1
- package/core/System/LinkedList.nm +4 -5
- package/core/System/List.nm +25 -7
- package/core/System/Map.nm +29 -19
- package/core/System/Option.nm +4 -0
- package/core/System/Result.nm +4 -0
- package/core/System/Set.nm +59 -13
- package/core/System/String.nm +27 -1
- package/core/System/Test.nm +1 -3
- package/core/System/Text/JsonTree.nm +11 -3
- package/core/System/Text/Regex.nm +4 -1
- package/core/System/bool.nm +12 -1
- package/core/System/char.nm +12 -1
- package/core/System/int.nm +12 -1
- package/core/System/int64.nm +12 -1
- package/core/System/int8.nm +12 -1
- package/core/System/uint.nm +12 -1
- package/core/System/uint64.nm +12 -1
- package/core/System/uint8.nm +12 -1
- package/core/docs/System/Init.md +2 -1
- package/core/docs/System/Option.md +23 -0
- package/core/docs/System/Result.md +19 -0
- package/dist/index.mjs +7252 -5266
- package/package.json +34 -33
- package/src/args.ts +11 -9
- package/src/index.ts +22 -16
package/core/System/Map.nm
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* An ordered key-value map with `set`/`get`/`has`/`remove
|
|
2
|
+
* An ordered key-value map with `set`/`get`/`has`/`remove`. Keys must be
|
|
3
|
+
* `Hashable` (hashed to a `uint` via `key.hash()`) and `Equatable` (compared
|
|
4
|
+
* with `==`); values may be any type.
|
|
3
5
|
**/
|
|
4
|
-
pub struct Map<TK, TV> {
|
|
6
|
+
pub struct Map<TK: Hashable + Equatable, TV> {
|
|
5
7
|
var length = 0
|
|
6
8
|
var Buffer<TK> keys = Buffer<TK>()
|
|
7
9
|
var Buffer<TV> values = Buffer<TV>()
|
|
@@ -20,8 +22,8 @@ pub struct Map<TK, TV> {
|
|
|
20
22
|
pub func set = (ref self, mov TK key, mov TV value) {
|
|
21
23
|
var int cap = self.keys.cap
|
|
22
24
|
if cap == 0 {
|
|
23
|
-
cap = self.keys.
|
|
24
|
-
self.values.
|
|
25
|
+
cap = self.keys.alloc_T(8)
|
|
26
|
+
self.values.alloc_T(8)
|
|
25
27
|
self.used.alloc(8)
|
|
26
28
|
}
|
|
27
29
|
if self.length * 4 >= cap * 3 {
|
|
@@ -31,11 +33,11 @@ pub struct Map<TK, TV> {
|
|
|
31
33
|
var int idx = self.find_slot(key, cap)
|
|
32
34
|
if self.used.load(idx) == 0 {
|
|
33
35
|
self.used.store(idx, 1)
|
|
34
|
-
self.keys.
|
|
35
|
-
self.values.
|
|
36
|
+
self.keys.store_T(idx, key)
|
|
37
|
+
self.values.store_T(idx, value)
|
|
36
38
|
self.length += 1
|
|
37
39
|
} else {
|
|
38
|
-
self.values.
|
|
40
|
+
self.values.replace_T(idx, value)
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -48,7 +50,7 @@ pub struct Map<TK, TV> {
|
|
|
48
50
|
if self.used.load(idx) == 0 {
|
|
49
51
|
return 0
|
|
50
52
|
}
|
|
51
|
-
return self.values.
|
|
53
|
+
return self.values.load_T(idx)
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
pub func has = (self, TK key, out bool) {
|
|
@@ -89,7 +91,7 @@ pub struct Map<TK, TV> {
|
|
|
89
91
|
if self.used.load(k) == 0 {
|
|
90
92
|
break
|
|
91
93
|
}
|
|
92
|
-
var int home = self.keys.
|
|
94
|
+
var int home = (self.keys.load_T(k).hash() as int) % cap
|
|
93
95
|
if home < 0 {
|
|
94
96
|
home = home + cap
|
|
95
97
|
}
|
|
@@ -102,26 +104,23 @@ pub struct Map<TK, TV> {
|
|
|
102
104
|
dk = dk + cap
|
|
103
105
|
}
|
|
104
106
|
if dgap < dk {
|
|
105
|
-
self.keys.
|
|
106
|
-
self.values.
|
|
107
|
+
self.keys.store_T(gap, self.keys.load_T(k))
|
|
108
|
+
self.values.store_T(gap, self.values.load_T(k))
|
|
107
109
|
self.used.store(gap, 1)
|
|
108
110
|
gap = k
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
113
|
self.used.store(gap, 0)
|
|
112
|
-
self.keys.store_int(gap, 0)
|
|
113
|
-
self.values.store_int(gap, 0)
|
|
114
114
|
self.length = self.length - 1
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
func find_slot = (self, TK key, int cap, out int: out >= 0 && out < cap) {
|
|
118
|
-
var int
|
|
119
|
-
var int idx = k % cap
|
|
118
|
+
var int idx = (key.hash() as int) % cap
|
|
120
119
|
if idx < 0 {
|
|
121
120
|
idx = idx + cap
|
|
122
121
|
}
|
|
123
122
|
while self.used.load(idx) != 0 {
|
|
124
|
-
if self.keys.
|
|
123
|
+
if self.keys.load_T(idx) == key {
|
|
125
124
|
return idx
|
|
126
125
|
}
|
|
127
126
|
idx += 1
|
|
@@ -138,15 +137,26 @@ pub struct Map<TK, TV> {
|
|
|
138
137
|
var Buffer<int> old_used = mov self.used swap Buffer<int>()
|
|
139
138
|
var int old_cap = old_keys.cap
|
|
140
139
|
|
|
141
|
-
self.keys.
|
|
142
|
-
self.values.
|
|
140
|
+
self.keys.alloc_T(new_cap)
|
|
141
|
+
self.values.alloc_T(new_cap)
|
|
143
142
|
self.used.alloc(new_cap)
|
|
144
143
|
self.length = 0
|
|
145
144
|
|
|
146
145
|
var i = 0
|
|
147
146
|
while i < old_cap; i += 1 {
|
|
148
147
|
if old_used.load(i) != 0 {
|
|
149
|
-
|
|
148
|
+
// move_T (not load_T) relinquishes the old slot, so each
|
|
149
|
+
// key/value is owned by exactly one buffer (the new self)
|
|
150
|
+
// afterwards. load_T would leave the old slot referencing
|
|
151
|
+
// the same class pointer — a double-free when old_keys is
|
|
152
|
+
// destroyed. The results are bound to locals so an
|
|
153
|
+
// owning-element copy (e.g. a `Buffer<string>` slot, which
|
|
154
|
+
// store_T strdup's) is freed here once the new buffer has
|
|
155
|
+
// made its own copy — passing them inline would orphan the
|
|
156
|
+
// move_T results.
|
|
157
|
+
var TK k = old_keys.move_T(i)
|
|
158
|
+
var TV v = old_values.move_T(i)
|
|
159
|
+
self.set(mov k, mov v)
|
|
150
160
|
}
|
|
151
161
|
}
|
|
152
162
|
}
|
package/core/System/Set.nm
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* An ordered set of unique values (`add`/`has`/`get`/`remove`)
|
|
2
|
+
* An ordered set of unique values (`add`/`has`/`get`/`remove`). Elements must
|
|
3
|
+
* be `Hashable` (hashed to a `uint` via `value.hash()`) and `Equatable`
|
|
4
|
+
* (compared with `==`).
|
|
3
5
|
**/
|
|
4
|
-
pub struct Set<T> {
|
|
6
|
+
pub struct Set<T: Hashable + Equatable> {
|
|
5
7
|
var length = 0
|
|
6
8
|
var Buffer<T> slots = Buffer<T>()
|
|
7
9
|
var used = Buffer<int>()
|
|
@@ -9,7 +11,7 @@ pub struct Set<T> {
|
|
|
9
11
|
pub func add = (ref self, mov T value) {
|
|
10
12
|
var int cap = self.slots.cap
|
|
11
13
|
if cap == 0 {
|
|
12
|
-
cap = self.slots.
|
|
14
|
+
cap = self.slots.alloc_T(8)
|
|
13
15
|
self.used.alloc(8)
|
|
14
16
|
}
|
|
15
17
|
if self.length * 4 >= cap * 3 {
|
|
@@ -19,7 +21,7 @@ pub struct Set<T> {
|
|
|
19
21
|
var int idx = self.find_slot(value, cap)
|
|
20
22
|
if self.used.load(idx) == 0 {
|
|
21
23
|
self.used.store(idx, 1)
|
|
22
|
-
self.slots.
|
|
24
|
+
self.slots.store_T(idx, value)
|
|
23
25
|
self.length += 1
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -42,7 +44,7 @@ pub struct Set<T> {
|
|
|
42
44
|
if self.used.load(idx) == 0 {
|
|
43
45
|
return 0
|
|
44
46
|
}
|
|
45
|
-
return self.slots.
|
|
47
|
+
return self.slots.load_T(idx)
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
pub func remove = (ref self, T value) {
|
|
@@ -54,20 +56,55 @@ pub struct Set<T> {
|
|
|
54
56
|
if self.used.load(idx) == 0 {
|
|
55
57
|
return
|
|
56
58
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
// Backward-shift deletion for linear probing. `gap` is the empty slot
|
|
60
|
+
// walking forward through the cluster; `k` scans ahead of it. An entry
|
|
61
|
+
// at k shifts into the gap only if the gap still lies within its valid
|
|
62
|
+
// probe range ([home, k) cyclically); otherwise the entry stays put and
|
|
63
|
+
// we keep scanning, because a later entry may still belong behind the
|
|
64
|
+
// gap. This is the subtle point: k advances independently of the gap,
|
|
65
|
+
// so entries past a non-moveable one are not stranded behind an empty
|
|
66
|
+
// slot (which would make find_slot miss them). No tombstones, so
|
|
67
|
+
// find_slot/get/has/add are unchanged, and the cost is the local cluster
|
|
68
|
+
// length — not a full O(cap) rehash on every delete.
|
|
69
|
+
var int gap = idx
|
|
70
|
+
var int k = idx
|
|
71
|
+
while true {
|
|
72
|
+
k += 1
|
|
73
|
+
if k >= cap {
|
|
74
|
+
k = 0
|
|
75
|
+
}
|
|
76
|
+
if self.used.load(k) == 0 {
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
var int home = (self.slots.load_T(k).hash() as int) % cap
|
|
80
|
+
if home < 0 {
|
|
81
|
+
home = home + cap
|
|
82
|
+
}
|
|
83
|
+
var int dgap = gap - home
|
|
84
|
+
if dgap < 0 {
|
|
85
|
+
dgap = dgap + cap
|
|
86
|
+
}
|
|
87
|
+
var int dk = k - home
|
|
88
|
+
if dk < 0 {
|
|
89
|
+
dk = dk + cap
|
|
90
|
+
}
|
|
91
|
+
if dgap < dk {
|
|
92
|
+
self.slots.store_T(gap, self.slots.load_T(k))
|
|
93
|
+
self.used.store(gap, 1)
|
|
94
|
+
gap = k
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
self.used.store(gap, 0)
|
|
59
98
|
self.length = self.length - 1
|
|
60
|
-
self.rehash(cap)
|
|
61
99
|
}
|
|
62
100
|
|
|
63
101
|
func find_slot = (self, T value, int cap, out int: out >= 0 && out < cap) {
|
|
64
|
-
var int
|
|
65
|
-
var int idx = v % cap
|
|
102
|
+
var int idx = (value.hash() as int) % cap
|
|
66
103
|
if idx < 0 {
|
|
67
104
|
idx = idx + cap
|
|
68
105
|
}
|
|
69
106
|
while self.used.load(idx) != 0 {
|
|
70
|
-
if self.slots.
|
|
107
|
+
if self.slots.load_T(idx) == value {
|
|
71
108
|
return idx
|
|
72
109
|
}
|
|
73
110
|
idx += 1
|
|
@@ -83,14 +120,23 @@ pub struct Set<T> {
|
|
|
83
120
|
var Buffer<int> old_used = mov self.used swap Buffer<int>()
|
|
84
121
|
var int old_cap = old_slots.cap
|
|
85
122
|
|
|
86
|
-
self.slots.
|
|
123
|
+
self.slots.alloc_T(new_cap)
|
|
87
124
|
self.used.alloc(new_cap)
|
|
88
125
|
self.length = 0
|
|
89
126
|
|
|
90
127
|
var i = 0
|
|
91
128
|
while i < old_cap; i += 1 {
|
|
92
129
|
if old_used.load(i) != 0 {
|
|
93
|
-
|
|
130
|
+
// move_T (not load_T) relinquishes the old slot, so each value
|
|
131
|
+
// is owned by exactly one buffer (the new self) afterwards.
|
|
132
|
+
// load_T would leave the old slot referencing the same class
|
|
133
|
+
// pointer — a double-free when old_slots is destroyed. The
|
|
134
|
+
// result is bound to a local so an owning-element copy (e.g. a
|
|
135
|
+
// `Buffer<string>` slot, which store_T strdup's) is freed here
|
|
136
|
+
// once the new buffer has made its own copy — passing it inline
|
|
137
|
+
// would orphan the move_T result.
|
|
138
|
+
var T v = old_slots.move_T(i)
|
|
139
|
+
self.add(mov v)
|
|
94
140
|
}
|
|
95
141
|
}
|
|
96
142
|
}
|
package/core/System/String.nm
CHANGED
|
@@ -1,7 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A UTF-8 text string — a heap-owned, length-tracked sequence of bytes
|
|
3
3
|
**/
|
|
4
|
-
pub struct string: Stringable {
|
|
4
|
+
pub struct string: Stringable, Hashable, Equatable {
|
|
5
|
+
pub func hash = (self, out uint) {
|
|
6
|
+
```
|
|
7
|
+
#arch: c
|
|
8
|
+
unsigned long h = 5381;
|
|
9
|
+
for (const char* p = self; *p; p++) {
|
|
10
|
+
h = h * 33 + (unsigned long)(unsigned char)*p;
|
|
11
|
+
}
|
|
12
|
+
return h;
|
|
13
|
+
```
|
|
14
|
+
```
|
|
15
|
+
#arch: aarch64
|
|
16
|
+
// x19 = self (char*), result in x0 (djb2 hash)
|
|
17
|
+
mov x0, #5381
|
|
18
|
+
mov x3, x19
|
|
19
|
+
.Lstring_hash_loop:
|
|
20
|
+
ldrb w1, [x3]
|
|
21
|
+
cbz w1, .Lstring_hash_done
|
|
22
|
+
mov x2, #33
|
|
23
|
+
mul x0, x0, x2
|
|
24
|
+
add x0, x0, x1
|
|
25
|
+
add x3, x3, #1
|
|
26
|
+
b .Lstring_hash_loop
|
|
27
|
+
.Lstring_hash_done:
|
|
28
|
+
```
|
|
29
|
+
}
|
|
30
|
+
|
|
5
31
|
pub func to_string = (self, out string) {
|
|
6
32
|
```
|
|
7
33
|
#arch: c
|
package/core/System/Test.nm
CHANGED
|
@@ -129,9 +129,7 @@ pub class Tester {
|
|
|
129
129
|
// Assert that a nullable value holds a value.
|
|
130
130
|
//
|
|
131
131
|
// Nomen has no generic methods, so there is one overload per nullable
|
|
132
|
-
// type the compiler can compare against `null`.
|
|
133
|
-
// (`Point?`) are not supported by the backend yet — use
|
|
134
|
-
// `t.expect(p != null, "...")` once that gap closes.
|
|
132
|
+
// type the compiler can compare against `null`.
|
|
135
133
|
pub func assert = (ref self, int? value, string message) {
|
|
136
134
|
self.expect(value != null, message)
|
|
137
135
|
}
|
|
@@ -32,12 +32,15 @@ pub struct JsonTree {
|
|
|
32
32
|
self.count = idx + 1
|
|
33
33
|
var default = JsonNode()
|
|
34
34
|
self.nodes.store_T(idx, default)
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// (set_text
|
|
35
|
+
// store_T deep-copies the owning `text` field (strdup of the shared
|
|
36
|
+
// empty-string literal) into the slot. JsonTree manages node texts
|
|
37
|
+
// manually (set_text strdup's into the slab; free_text/release frees
|
|
38
|
+
// them; NULL means "no text"), so the slot must start NULL — free the
|
|
39
|
+
// strdup'd default and NULL it, or reset() would leak it. idx is x1.
|
|
38
40
|
```
|
|
39
41
|
#arch: c
|
|
40
42
|
JsonNode *nodes = (JsonNode*)(unsigned long long)self->nodes.data;
|
|
43
|
+
free(nodes[idx].text);
|
|
41
44
|
nodes[idx].text = 0;
|
|
42
45
|
```
|
|
43
46
|
```
|
|
@@ -51,7 +54,12 @@ pub struct JsonTree {
|
|
|
51
54
|
madd x1, x1, x3, xzr
|
|
52
55
|
add x0, x0, x1
|
|
53
56
|
add x0, x0, #16
|
|
57
|
+
ldr x1, [x0]
|
|
54
58
|
str xzr, [x0]
|
|
59
|
+
cbz x1, .Lalloc_node_text_skip
|
|
60
|
+
mov x0, x1
|
|
61
|
+
bl _free
|
|
62
|
+
.Lalloc_node_text_skip:
|
|
55
63
|
```
|
|
56
64
|
return idx
|
|
57
65
|
}
|
|
@@ -254,6 +254,9 @@ func add_class_chars = (string pattern, int start, int end, ref StringBuilder sb
|
|
|
254
254
|
|
|
255
255
|
// Match pattern[pat_pos..pat_end) against input starting at in_pos.
|
|
256
256
|
// Returns the end position in input after a successful match, or -1.
|
|
257
|
+
// Return contract: a successful match never reads past in_len, so the result
|
|
258
|
+
// is always <= in_len (and -1 on failure). This lets callers prove an index
|
|
259
|
+
// bounded by the result is also bounded by the input length.
|
|
257
260
|
func match_here = (
|
|
258
261
|
string pattern,
|
|
259
262
|
int pat_pos,
|
|
@@ -261,7 +264,7 @@ func match_here = (
|
|
|
261
264
|
string input,
|
|
262
265
|
int in_pos,
|
|
263
266
|
int in_len,
|
|
264
|
-
out int
|
|
267
|
+
out int: out <= in_len
|
|
265
268
|
) {
|
|
266
269
|
// Handle top-level alternation: a '|' at bracket/paren depth 0 splits the
|
|
267
270
|
// range into alternatives. Char classes and escapes are skipped so a '|' or
|
package/core/System/bool.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A boolean value (`true` or `false`)
|
|
3
3
|
**/
|
|
4
|
-
pub struct bool: Stringable {
|
|
4
|
+
pub struct bool: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
/**
|
|
6
17
|
* Converts this boolean to a string value (`"true"` or `"false"`)
|
|
7
18
|
*
|
package/core/System/char.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A single character
|
|
3
3
|
**/
|
|
4
|
-
pub struct char: Stringable {
|
|
4
|
+
pub struct char: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/System/int.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A signed integer — the default integer type
|
|
3
3
|
**/
|
|
4
|
-
pub struct int: Stringable {
|
|
4
|
+
pub struct int: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/System/int64.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A 64-bit signed integer
|
|
3
3
|
**/
|
|
4
|
-
pub struct int64: Stringable {
|
|
4
|
+
pub struct int64: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/System/int8.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* An 8-bit signed integer
|
|
3
3
|
**/
|
|
4
|
-
pub struct int8: Stringable {
|
|
4
|
+
pub struct int8: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/System/uint.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* An unsigned integer
|
|
3
3
|
**/
|
|
4
|
-
pub struct uint: Stringable {
|
|
4
|
+
pub struct uint: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/System/uint64.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A 64-bit unsigned integer
|
|
3
3
|
**/
|
|
4
|
-
pub struct uint64: Stringable {
|
|
4
|
+
pub struct uint64: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/System/uint8.nm
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* An 8-bit unsigned integer
|
|
3
3
|
**/
|
|
4
|
-
pub struct uint8: Stringable {
|
|
4
|
+
pub struct uint8: Stringable, Hashable, Equatable {
|
|
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
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
pub func to_string = (self, out string) {
|
|
6
17
|
```
|
|
7
18
|
#arch: c
|
package/core/docs/System/Init.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## `struct Init`
|
|
4
4
|
|
|
5
|
-
Program startup state — the argument count and argument list passed to `main
|
|
5
|
+
Program startup state — the argument count and argument list passed to `main`,
|
|
6
|
+
plus `is_tty` (whether stdout is a terminal, for renderer selection).
|
|
6
7
|
|
|
7
8
|
## `func parse_intparse_int(string s) -> int`
|
|
8
9
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Option
|
|
2
|
+
|
|
3
|
+
## `enum Option<T>`
|
|
4
|
+
|
|
5
|
+
A generic optional type with a `some(T value)` case and a `none` case.
|
|
6
|
+
Monomorphized per concrete type argument (e.g. `Option<int>`).
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
func find_first_even = (int[] xs, out Option<int>) {
|
|
10
|
+
for x of xs {
|
|
11
|
+
if x % 2 == 0 {
|
|
12
|
+
return .some(x)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return .none
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const found = find_first_even([1, 3, 4])
|
|
19
|
+
match found {
|
|
20
|
+
case .some(v) -> Console.write("\\{v}")
|
|
21
|
+
case .none -> Console.write("none")
|
|
22
|
+
}
|
|
23
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Result
|
|
2
|
+
|
|
3
|
+
## `enum Result<T, E>`
|
|
4
|
+
|
|
5
|
+
A generic result type with an `ok(T value)` success case and an
|
|
6
|
+
`error(E error)` failure case. Monomorphized per concrete type-argument pair
|
|
7
|
+
(e.g. `Result<int, string>`).
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
func parse_age = (string s, out Result<int, string>) {
|
|
11
|
+
return .error("not a number")
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result = parse_age("x")
|
|
15
|
+
match result {
|
|
16
|
+
case .ok(age) -> Console.write("\\{age}")
|
|
17
|
+
case .error(msg) -> Console.write("error: \\{msg}")
|
|
18
|
+
}
|
|
19
|
+
```
|