-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmodule.ae
More file actions
105 lines (97 loc) · 3.64 KB
/
Copy pathmodule.ae
File metadata and controls
105 lines (97 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// std.map - HashMap Operations (alias for std.collections)
//
// API shape:
// - Raw externs end in `_raw` and return ptr/int in the old C-style
// convention. They are the escape hatch for advanced callers.
// - Aether-native wrappers (below) use Go-style `(value, err)` / `err`
// returns.
exports(
map_new, map_put_raw, map_put_string_owned, map_get_raw, map_has, map_remove,
map_size, map_clear, map_free, map_keys_raw, map_keys_free,
map_keys_size_raw, map_keys_get_raw,
put, get, keys, keys_size, keys_get
)
extern map_new() -> ptr
extern map_put_raw(map: ptr, key: string, value: ptr) -> int
// Heap-string-aware put. The map acquires its OWN reference: a
// refcounted string is retained, a plain pointer (a literal, a
// borrowed char*) is copied. The caller keeps and independently frees
// theirs, so the same value can live in several containers. map_free
// releases each owned value. Codegen auto-routes
// `map.put(m, k, heap_string_expr)` to the adopting sibling instead,
// where the value is escaping into the map.
extern map_put_string_owned(map: ptr, key: string, value: ptr) -> int
extern map_get_raw(map: ptr, key: string) -> ptr
extern map_has(map: ptr, key: string) -> int
extern map_remove(map: ptr, key: string)
extern map_size(map: ptr) -> int
extern map_clear(map: ptr)
extern map_free(map: ptr)
extern map_keys_raw(map: ptr) -> ptr
extern map_keys_free(keys: ptr)
extern map_keys_size_raw(keys: ptr) -> int
extern map_keys_get_raw(keys: ptr, index: int) -> string
// Insert or update a key-value pair. Returns "" on success, error on
// failure (null map/key or OOM).
put(map: ptr, key: string, value: ptr) -> {
ok = map_put_raw(map, key, value)
if ok == 0 {
return "map.put failed"
}
return ""
}
// Look up a key.
// - (value, "") : key present
// - (null, "") : key absent (not an error — use map.has)
// - (null, "null map") : `map` is null
get(map: ptr, key: string) -> {
if map == null {
return null, "null map"
}
v = map_get_raw(map, key)
return v, ""
}
// Snapshot a map's keys. Returns (MapKeys ptr, "") on success, (null,
// error) on allocation failure. Caller must free with map.keys_free.
keys(map: ptr) -> {
if map == null {
return null, "null map"
}
k = map_keys_raw(map)
if k == null {
return null, "allocation failed"
}
return k, ""
}
// ---- reading a keys snapshot (#1724) --------------------------------------
//
// `keys` hands back a snapshot; these read it. Before this pair the snapshot
// could only be allocated and freed, so a map's key set was unreachable from
// Aether and callers kept a parallel array of keys purely to have something
// iterable.
//
// The strings are BORROWED from the live map: valid until `keys_free`, and
// only while the map still holds that entry. The snapshot does not track
// later mutation -- a key removed from the map leaves a dangling entry here.
// Retain or copy anything that must outlive either.
//
// Iteration order is bucket order and is UNSPECIFIED. Callers who need a
// deterministic order sort the keys (std.sort.strings).
keys_size(keys: ptr) -> int {
if keys == null {
return 0
}
return map_keys_size_raw(keys)
}
// Out of range or null returns "" rather than trapping, so a bad index is a
// visible empty string instead of a wild read. An empty string is also a
// legitimate key, so callers who must distinguish check keys_size first.
keys_get(keys: ptr, index: int) -> string {
if keys == null {
return ""
}
if index < 0 || index >= map_keys_size_raw(keys) {
return ""
}
return map_keys_get_raw(keys, index)
}