Repository navigation
Expand file tree
/
Copy pathmodule.ae
More file actions
95 lines (90 loc) · 3.9 KB
/
Copy pathmodule.ae
File metadata and controls
95 lines (90 loc) · 3.9 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
// std.list - ArrayList 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(
list_new, list_new_in, list_add, list_add_raw, list_add_string_owned, list_get_raw, list_set,
list_size, list_remove, list_clear, list_free,
get, get_string, at
)
extern list_new() -> ptr @fresh
extern list_new_in(alloc: ptr) -> ptr @fresh
// The stores keep their item past the call (#3086): a `ptr` stays the
// list's, so a function that adds a borrowed `ptr` parameter declares it
// `@keep`, and a string or a closure is handed a reference of its own
// (`@retain`, R4).
extern list_add_raw(list: @holds ptr, item: @aether @retain ptr) -> int
// Append an item to a list. Returns "" on success, error on failure.
extern list_add(list: @holds ptr, item: @aether @retain ptr) -> string
// String-aware add, for C and `ptr` callers. The list takes a
// reference of its own: a counted string is retained, a plain C
// pointer is copied. The caller keeps and releases its own, so the
// same value can live in several containers. list_free releases each
// owned element before freeing the backing array. `list.add(l, s)` of
// a `string` in Aether code is a store into the list (R3): the
// compiler hands the list a reference, moving a fresh value in.
extern list_add_string_owned(list: @holds ptr, item: @aether ptr) -> int
extern list_get_raw(list: ptr, index: int) -> ptr
extern list_set(list: @holds ptr, index: int, item: @aether @retain ptr)
extern list_size(list: ptr) -> int
extern list_remove(list: ptr, index: int)
extern list_clear(list: ptr)
extern list_free(list: @frees ptr)
extern aether_string_is_string(p: @aether ptr) -> int
// Index into a list.
// - (item, "") : index in range
// - (null, "index out of range") : index < 0 or index >= size
// - (null, "null list") : `list` is null
// An empty error means the value is good, as everywhere else in std (#2439).
// list_get_raw stays the unchecked form for callers that have already
// bounded the index.
get(list: ptr, index: int) -> {
if list == null {
return null, "null list"
}
if index < 0 || index >= list_size(list) {
return null, "index out of range"
}
return list_get_raw(list, index), ""
}
// The item at `index`, for a caller that has bounded the index (a loop over
// 0 ..< list_size). An index out of range, or a null list, is a panic that
// names the index and the size, as a slice index is (#3107): the unchecked
// read handed back a null there, which a caller took for a stored null.
at(list: ptr, index: int) -> ptr {
if list == null {
panic("list.at: the list is null")
}
n = list_size(list)
if index < 0 || index >= n {
panic("list index ${index} out of range for length ${n}")
}
return list_get_raw(list, index)
}
// Index into a list whose element is a string. `get` hands back a `ptr`,
// which a `string` local would read as text whatever it points at (refused,
// E0202); this says the element is a string, and checks it is one:
// - (item, "") : index in range, the element a string
// - (null, "") : the element is null
// - (null, "not a string") : the element is some other pointer
// - (null, "index out of range") : index < 0 or index >= size
// - (null, "null list") : `list` is null
get_string(list: ptr, index: int) -> (string, string) {
if list == null {
return null, "null list"
}
if index < 0 || index >= list_size(list) {
return null, "index out of range"
}
v = list_get_raw(list, index)
if v == null {
return null, ""
}
if aether_string_is_string(v) == 0 {
return null, "not a string"
}
return v, ""
}