git.s-ol.nu alive / 4fc94b1
rename array/struct modules to avoid name conflict s-ol 1 year, 14 days ago
6 changed file(s) with 428 addition(s) and 428 deletion(s). Raw diff Collapse all Expand all
0 import Array, Op, PureOp, Builtin, Constant, Error, const, sig, evt, T from require 'alv.base'
1 import Cell from require 'alv.cell'
2 import Tag from require 'alv.tag'
3 builtins = require 'alv.builtins'
4
5 unpack or= table.unpack
6 any = sig! / evt!
7
8 get = Constant.meta
9 meta:
10 name: 'get'
11 summary: "Index into an array."
12 examples: { '(get array i)' }
13 description: "Get the value at index `i` (starting at 0).
14
15 `i` has to be a constant expression."
16
17 value: class extends PureOp
18 pattern: any + const.num
19 type: (inputs) =>
20 { array, i } = inputs
21 array\type!\get i.result!
22
23 tick: =>
24 { array, i } = @unwrap_all!
25 @out\set array[i + 1]
26
27 set = Constant.meta
28 meta:
29 name: 'set'
30 summary: "Update a value in an array."
31 examples: { '(set array i val)' }
32 description: "Set the value for `i` to `val`.
33
34 `i` has to be a constant expression. This is a pure op, so at most one of
35 `array` and `val` may be a !-stream."
36
37 value: class extends PureOp
38 pattern: any + const.num + any
39 type: (inputs) =>
40 { array, i, val } = inputs
41 type = array\type!
42 expected = type\get i.result!
43
44 if expected ~= val\type!
45 msg = string.format "expected value of type %s, not %s",
46 expected, val\type!
47 error Error 'argument', msg
48
49 type
50
51 tick: =>
52 { array, key, val } = @unwrap_all!
53
54 array = [v for v in *array]
55 array[key + 1] = val
56
57 @out\set array
58
59 head = Constant.meta
60 meta:
61 name: 'head'
62 summary: "Get the first element from an array."
63 examples: { '(head array)' }
64
65 value: class extends PureOp
66 pattern: any*1
67 type: (inputs) =>
68 type = inputs[1]\type!
69
70 assert type.__class == Array, Error 'argument', "expected an Array"
71 assert type.size > 0, Error 'argument', "cannot get head of empty Array"
72
73 type.type
74
75 tick: =>
76 { array } = @unwrap_all!
77 @out\set array[1]
78
79 tail = Constant.meta
80 meta:
81 name: 'tail'
82 summary: "Get everything except the first element from an array."
83 examples: { '(tail array)' }
84
85 value: class extends PureOp
86 pattern: any*1
87 type: (inputs) =>
88 type = inputs[1]\type!
89
90 assert type.__class == Array, Error 'argument', "expected an Array"
91 assert type.size > 0, Error 'argument', "cannot get tail of empty Array"
92
93 Array type.size - 1, type.type
94
95 tick: =>
96 { array } = @unwrap_all!
97 @out\set [v for v in *array[2,]]
98
99 prepend = Constant.meta
100 meta:
101 name: 'prepend'
102 summary: "Prepend a new value at the start of an array."
103 examples: { '(prepend array val)' }
104 description: "Prepend `val` to `array` at index `0`, moving other values back.
105
106 This is a pure op, so at most one of `array` and `val` may be a !-stream."
107
108 value: class extends PureOp
109 pattern: any + any
110 type: (inputs) =>
111 { array, val } = inputs
112 type = array\type!
113
114 if val\type! ~= type.type
115 msg = string.format "expected value of type %s, not %s",
116 type.type, val\type!
117 error Error 'argument', msg
118
119 Array type.size + 1, type.type
120
121 tick: =>
122 { array, val } = @unwrap_all!
123
124 array = [v for v in *array]
125 table.insert array, 1, val
126
127 @out\set array
128
129 insert = Constant.meta
130 meta:
131 name: 'insert'
132 summary: "Insert a new value into an array."
133 examples: { '(insert array i val)' }
134 description: "Insert `val` into `array` at `i`, moving other values back if
135 necessary.
136
137 `i` has to be a constant expression. This is a pure op, so at most one of
138 `array` and `val` may be a !-stream."
139
140 value: class extends PureOp
141 pattern: any + const.num + any
142 type: (inputs) =>
143 { array, i, val } = inputs
144 type = array\type!
145 i = i.result!
146
147 if i > type.size or i < 0
148 error Error 'argument', "index '#{i}' out of range!"
149 if val\type! ~= type.type
150 msg = string.format "expected value of type %s, not %s",
151 type.type, val\type!
152 error Error 'argument', msg
153
154 Array type.size + 1, type.type
155
156 tick: =>
157 { array, i, val } = @unwrap_all!
158
159 array = [v for v in *array]
160 table.insert array, i + 1, val
161
162 @out\set array
163
164 remove = Constant.meta
165 meta:
166 name: 'remove'
167 summary: "Remove a value from an Array."
168 examples: { '(remove array i)' }
169 description: "Removes the value at index `i` from `array`.
170
171 `i` has to be a constant expression."
172
173 value: class extends PureOp
174 pattern: any + const.num
175 type: (inputs) =>
176 { array, i } = inputs
177 type = array\type!
178
179 -- check index range
180 type\get i.result!
181
182 Array type.size - 1, type.type
183
184 tick: =>
185 { array, i, val } = @unwrap_all!
186
187 array = [v for v in *array]
188 table.remove array, i + 1
189
190 @out\set array
191
192 size = Constant.meta
193 meta:
194 name: 'size'
195 summary: "Get the size of an array."
196 examples: { '(size array)' }
197
198 value: class extends Op
199 setup: (inputs) =>
200 super {}
201
202 assert #inputs == 1, Error 'argument', "expected exactly one argument"
203 type = inputs[1]\type!
204 assert type.__class == Array, Error 'argument', "expected an Array"
205
206 @out = Constant.num type.size
207
208 concat = Constant.meta
209 meta:
210 name: 'concat'
211 summary: "Concatenate Arrays."
212 examples: { '(concat arr1 arr2 [arr3…])' }
213
214 value: class extends PureOp
215 pattern: any\rep 2
216 type: (inputs) =>
217 size = 0
218 type = inputs[1]\type!.type
219
220 for input in *inputs
221 array = input\type!
222
223 if array.type ~= type
224 msg = string.format "Cannot concatenate different arrays %s, %s",
225 inputs[1]\type!, array
226 error Error 'argument', msg
227
228 size += array.size
229
230 Array size, type
231
232 tick: =>
233 arrays = @unwrap_all!
234 out = {}
235
236 for array in *arrays
237 for val in *array
238 table.insert out, val
239
240 @out\set out
241
242 array_constr = builtins!\get('array').result
243 map = Constant.meta
244 meta:
245 name: 'map'
246 summary: "Apply an function to each value in an array."
247 examples: { '(map array fn)' }
248 description: "
249 Invokes `fn` once for each element in `array` and returns an array of the results.
250 `fn` must take one argument and return the same type consistently."
251
252 value: class extends Builtin
253 eval: (scope, tail) =>
254 L\trace "evaling #{@}"
255 assert #tail == 2, "'map' takes exactly two arguments"
256 tail = [L\push t\eval, scope for t in *tail]
257 { array, fn } = tail
258
259 fndef = fn.result
260 assert fn\type! == T.fndef, "fn has to be a fndef"
261 array_type = array\type!
262 assert array_type.__class == Array, Error 'argument', "expected an Array"
263
264 invocations = for i=1, array_type.size
265 tag_o = @tag\clone Tag.parse tostring i
266 tag_i = @tag\clone tag_o
267 Cell tag_o, {
268 with Constant.literal T.fndef, fndef!, 'fn'
269 .meta = fndef.meta
270 Cell tag_i, {
271 Constant.literal T.opdef, get!, 'get'
272 Constant.literal array_type, array.result!, 'array'
273 Constant.num i-1
274 }
275 }
276
277 tag = @tag\clone Tag.parse '-1'
278 inner = Cell tag, {
279 Constant.literal T.opdef, array_constr, 'array'
280 unpack invocations
281 }
282 super inner\eval scope
283
284
285 Constant.meta
286 meta:
287 name: 'array'
288 summary: "Utilities for dealing with arrays."
289
290 value:
291 :get, :set
292 :head, :tail, :prepend
293 :insert, :remove
294 :map
295
296 :size, :concat
+0
-297
alv-lib/array.moon less more
0 import Array, Op, PureOp, Builtin, Constant, Error, const, sig, evt, T from require 'alv.base'
1 import Cell from require 'alv.cell'
2 import Tag from require 'alv.tag'
3 builtins = require 'alv.builtins'
4
5 unpack or= table.unpack
6 any = sig! / evt!
7
8 get = Constant.meta
9 meta:
10 name: 'get'
11 summary: "Index into an array."
12 examples: { '(get array i)' }
13 description: "Get the value at index `i` (starting at 0).
14
15 `i` has to be a constant expression."
16
17 value: class extends PureOp
18 pattern: any + const.num
19 type: (inputs) =>
20 { array, i } = inputs
21 array\type!\get i.result!
22
23 tick: =>
24 { array, i } = @unwrap_all!
25 @out\set array[i + 1]
26
27 set = Constant.meta
28 meta:
29 name: 'set'
30 summary: "Update a value in an array."
31 examples: { '(set array i val)' }
32 description: "Set the value for `i` to `val`.
33
34 `i` has to be a constant expression. This is a pure op, so at most one of
35 `array` and `val` may be a !-stream."
36
37 value: class extends PureOp
38 pattern: any + const.num + any
39 type: (inputs) =>
40 { array, i, val } = inputs
41 type = array\type!
42 expected = type\get i.result!
43
44 if expected ~= val\type!
45 msg = string.format "expected value of type %s, not %s",
46 expected, val\type!
47 error Error 'argument', msg
48
49 type
50
51 tick: =>
52 { array, key, val } = @unwrap_all!
53
54 array = [v for v in *array]
55 array[key + 1] = val
56
57 @out\set array
58
59 head = Constant.meta
60 meta:
61 name: 'head'
62 summary: "Get the first element from an array."
63 examples: { '(head array)' }
64
65 value: class extends PureOp
66 pattern: any*1
67 type: (inputs) =>
68 type = inputs[1]\type!
69
70 assert type.__class == Array, Error 'argument', "expected an Array"
71 assert type.size > 0, Error 'argument', "cannot get head of empty Array"
72
73 type.type
74
75 tick: =>
76 { array } = @unwrap_all!
77 @out\set array[1]
78
79 tail = Constant.meta
80 meta:
81 name: 'tail'
82 summary: "Get everything except the first element from an array."
83 examples: { '(tail array)' }
84
85 value: class extends PureOp
86 pattern: any*1
87 type: (inputs) =>
88 type = inputs[1]\type!
89
90 assert type.__class == Array, Error 'argument', "expected an Array"
91 assert type.size > 0, Error 'argument', "cannot get tail of empty Array"
92
93 Array type.size - 1, type.type
94
95 tick: =>
96 { array } = @unwrap_all!
97 @out\set [v for v in *array[2,]]
98
99 prepend = Constant.meta
100 meta:
101 name: 'prepend'
102 summary: "Prepend a new value at the start of an array."
103 examples: { '(prepend array val)' }
104 description: "Prepend `val` to `array` at index `0`, moving other values back.
105
106 This is a pure op, so at most one of `array` and `val` may be a !-stream."
107
108 value: class extends PureOp
109 pattern: any + any
110 type: (inputs) =>
111 { array, val } = inputs
112 type = array\type!
113
114 if val\type! ~= type.type
115 msg = string.format "expected value of type %s, not %s",
116 type.type, val\type!
117 error Error 'argument', msg
118
119 Array type.size + 1, type.type
120
121 tick: =>
122 { array, val } = @unwrap_all!
123
124 array = [v for v in *array]
125 table.insert array, 1, val
126
127 @out\set array
128
129 insert = Constant.meta
130 meta:
131 name: 'insert'
132 summary: "Insert a new value into an array."
133 examples: { '(insert array i val)' }
134 description: "Insert `val` into `array` at `i`, moving other values back if
135 necessary.
136
137 `i` has to be a constant expression. This is a pure op, so at most one of
138 `array` and `val` may be a !-stream."
139
140 value: class extends PureOp
141 pattern: any + const.num + any
142 type: (inputs) =>
143 { array, i, val } = inputs
144 type = array\type!
145 i = i.result!
146
147 if i > type.size or i < 0
148 error Error 'argument', "index '#{i}' out of range!"
149 if val\type! ~= type.type
150 msg = string.format "expected value of type %s, not %s",
151 type.type, val\type!
152 error Error 'argument', msg
153
154 Array type.size + 1, type.type
155
156 tick: =>
157 { array, i, val } = @unwrap_all!
158
159 array = [v for v in *array]
160 table.insert array, i + 1, val
161
162 @out\set array
163
164 remove = Constant.meta
165 meta:
166 name: 'remove'
167 summary: "Remove a value from an Array."
168 examples: { '(remove array i)' }
169 description: "Removes the value at index `i` from `array`.
170
171 `i` has to be a constant expression."
172
173 value: class extends PureOp
174 pattern: any + const.num
175 type: (inputs) =>
176 { array, i } = inputs
177 type = array\type!
178
179 -- check index range
180 type\get i.result!
181
182 Array type.size - 1, type.type
183
184 tick: =>
185 { array, i, val } = @unwrap_all!
186
187 array = [v for v in *array]
188 table.remove array, i + 1
189
190 @out\set array
191
192 size = Constant.meta
193 meta:
194 name: 'size'
195 summary: "Get the size of an array."
196 examples: { '(size array)' }
197
198 value: class extends Op
199 setup: (inputs) =>
200 super {}
201
202 assert #inputs == 1, Error 'argument', "expected exactly one argument"
203 type = inputs[1]\type!
204 assert type.__class == Array, Error 'argument', "expected an Array"
205
206 @out = Constant.num type.size
207
208 concat = Constant.meta
209 meta:
210 name: 'concat'
211 summary: "Concatenate Arrays."
212 examples: { '(concat arr1 arr2 [arr3…])' }
213
214 value: class extends PureOp
215 pattern: any\rep 2
216 type: (inputs) =>
217 size = 0
218 type = inputs[1]\type!.type
219
220 for input in *inputs
221 array = input\type!
222
223 if array.type ~= type
224 msg = string.format "Cannot concatenate different arrays %s, %s",
225 inputs[1]\type!, array
226 error Error 'argument', msg
227
228 size += array.size
229
230 Array size, type
231
232 tick: =>
233 arrays = @unwrap_all!
234 out = {}
235
236 for array in *arrays
237 for val in *array
238 table.insert out, val
239
240 @out\set out
241
242 array_constr = builtins!\get('array').result
243 map = Constant.meta
244 meta:
245 name: 'map'
246 summary: "Apply an function to each value in an array."
247 examples: { '(map array fn)' }
248 description: "
249 Invokes `fn` once for each element in `array` and returns an array of the results.
250 `fn` must take one argument and return the same type consistently."
251
252 value: class extends Builtin
253 eval: (scope, tail) =>
254 L\trace "evaling #{@}"
255 assert #tail == 2, "'map' takes exactly two arguments"
256 tail = [L\push t\eval, scope for t in *tail]
257 { array, fn } = tail
258
259 fndef = fn.result
260 assert fn\type! == T.fndef, "fn has to be a fndef"
261 array_type = array\type!
262 assert array_type.__class == Array, Error 'argument', "expected an Array"
263
264 invocations = for i=1, array_type.size
265 tag_o = @tag\clone Tag.parse tostring i
266 tag_i = @tag\clone tag_o
267 Cell tag_o, {
268 with Constant.literal T.fndef, fndef!, 'fn'
269 .meta = fndef.meta
270 Cell tag_i, {
271 Constant.literal T.opdef, get!, 'get'
272 Constant.literal array_type, array.result!, 'array'
273 Constant.num i-1
274 }
275 }
276
277 tag = @tag\clone Tag.parse '-1'
278 inner = Cell tag, {
279 Constant.literal T.opdef, array_constr, 'array'
280 unpack invocations
281 }
282 super inner\eval scope
283
284
285 Constant.meta
286 meta:
287 name: 'array'
288 summary: "Utilities for dealing with arrays."
289
290 value:
291 :get, :set
292 :head, :tail, :prepend
293 :insert, :remove
294 :map
295
296 :size, :concat
0 import Struct, Op, PureOp, Constant, Error, const, sig, evt from require 'alv.base'
1
2 any = sig! / evt!
3 key_type = const.str / const.sym
4
5 get = Constant.meta
6 meta:
7 name: 'get'
8 summary: "Index into a struct."
9 examples: { '(get struct key)' }
10 description: "Get the value at `key`.
11
12 `key` has to be a constant expression."
13
14 value: class extends PureOp
15 pattern: any + key_type
16 type: (inputs) =>
17 { struct, key } = inputs
18 struct\type!\get key.result!
19
20 tick: =>
21 { struct, key } = @unwrap_all!
22 @out\set struct[key]
23
24 set = Constant.meta
25 meta:
26 name: 'set'
27 summary: "Update values in a struct."
28 examples: { '(set struct key val)' }
29 description: "Set the value for `key` to `val`.
30
31 `key` has to be a constant expression. This is a pure op, so at most one of
32 `struct` and `val` may be a !-stream."
33
34 value: class extends PureOp
35 pattern: any + key_type + any
36 type: (inputs) =>
37 { struct, key, val } = inputs
38 type = struct\type!
39 expected = type\get key.result!
40
41 if expected ~= val\type!
42 msg = string.format "expected value for key '%s' to be %s, not %s",
43 key.result!, expected, val\type!
44 error Error 'argument', msg
45
46 type
47
48 tick: =>
49 { struct, key, val } = @unwrap_all!
50
51 struct = {k,v for k,v in pairs struct}
52 struct[key] = val
53
54 @out\set struct
55
56 insert = Constant.meta
57 meta:
58 name: 'insert'
59 summary: "Insert a new value into a struct."
60 examples: { '(insert struct key val)' }
61 description: "Insert `val` into `struct` at `key`.
62
63 `key` has to be a constant expression. This is a pure op, so at most one of
64 `struct` and `val` may be a !-stream."
65
66 value: class extends PureOp
67 pattern: any + key_type + any
68 type: (inputs) =>
69 { struct, key, val } = inputs
70 type = struct\type!
71 key = key.result!
72
73 if type.types[key]
74 msg = string.format "key '%s' already exists in value of type %s",
75 key, type
76 error Error 'argument', msg
77
78 types = {k,v for k,v in pairs type.types}
79 types[key] = val\type!
80 Struct types
81
82 tick: =>
83 { struct, key, val } = @unwrap_all!
84
85 struct = {k,v for k,v in pairs struct}
86 struct[key] = val
87
88 @out\set struct
89
90 remove = Constant.meta
91 meta:
92 name: 'remove'
93 summary: "Remove values from a struct."
94 examples: { '(remove struct key)' }
95 description: "Removes the value at index `key` from `struct`.
96
97 `key` has to be a constant expression."
98
99 value: class extends PureOp
100 pattern: any + key_type
101 type: (inputs) =>
102 { struct, key } = inputs
103 type = struct\type!
104 key = key.result!
105
106 -- check key exists
107 type\get key
108
109 types = {k,v for k,v in pairs type.types}
110 types[key] = nil
111 Struct types
112
113 tick: =>
114 { struct, key, val } = @unwrap_all!
115
116 struct = {k,v for k,v in pairs struct}
117 struct[key] = nil
118
119 @out\set struct
120
121 Constant.meta
122 meta:
123 name: 'struct'
124 summary: "Utilities for dealing with structs."
125
126 value:
127 :get, :set
128 :insert, :remove
+0
-129
alv-lib/struct.moon less more
0 import Struct, Op, PureOp, Constant, Error, const, sig, evt from require 'alv.base'
1
2 any = sig! / evt!
3 key_type = const.str / const.sym
4
5 get = Constant.meta
6 meta:
7 name: 'get'
8 summary: "Index into a struct."
9 examples: { '(get struct key)' }
10 description: "Get the value at `key`.
11
12 `key` has to be a constant expression."
13
14 value: class extends PureOp
15 pattern: any + key_type
16 type: (inputs) =>
17 { struct, key } = inputs
18 struct\type!\get key.result!
19
20 tick: =>
21 { struct, key } = @unwrap_all!
22 @out\set struct[key]
23
24 set = Constant.meta
25 meta:
26 name: 'set'
27 summary: "Update values in a struct."
28 examples: { '(set struct key val)' }
29 description: "Set the value for `key` to `val`.
30
31 `key` has to be a constant expression. This is a pure op, so at most one of
32 `struct` and `val` may be a !-stream."
33
34 value: class extends PureOp
35 pattern: any + key_type + any
36 type: (inputs) =>
37 { struct, key, val } = inputs
38 type = struct\type!
39 expected = type\get key.result!
40
41 if expected ~= val\type!
42 msg = string.format "expected value for key '%s' to be %s, not %s",
43 key.result!, expected, val\type!
44 error Error 'argument', msg
45
46 type
47
48 tick: =>
49 { struct, key, val } = @unwrap_all!
50
51 struct = {k,v for k,v in pairs struct}
52 struct[key] = val
53
54 @out\set struct
55
56 insert = Constant.meta
57 meta:
58 name: 'insert'
59 summary: "Insert a new value into a struct."
60 examples: { '(insert struct key val)' }
61 description: "Insert `val` into `struct` at `key`.
62
63 `key` has to be a constant expression. This is a pure op, so at most one of
64 `struct` and `val` may be a !-stream."
65
66 value: class extends PureOp
67 pattern: any + key_type + any
68 type: (inputs) =>
69 { struct, key, val } = inputs
70 type = struct\type!
71 key = key.result!
72
73 if type.types[key]
74 msg = string.format "key '%s' already exists in value of type %s",
75 key, type
76 error Error 'argument', msg
77
78 types = {k,v for k,v in pairs type.types}
79 types[key] = val\type!
80 Struct types
81
82 tick: =>
83 { struct, key, val } = @unwrap_all!
84
85 struct = {k,v for k,v in pairs struct}
86 struct[key] = val
87
88 @out\set struct
89
90 remove = Constant.meta
91 meta:
92 name: 'remove'
93 summary: "Remove values from a struct."
94 examples: { '(remove struct key)' }
95 description: "Removes the value at index `key` from `struct`.
96
97 `key` has to be a constant expression."
98
99 value: class extends PureOp
100 pattern: any + key_type
101 type: (inputs) =>
102 { struct, key } = inputs
103 type = struct\type!
104 key = key.result!
105
106 -- check key exists
107 type\get key
108
109 types = {k,v for k,v in pairs type.types}
110 types[key] = nil
111 Struct types
112
113 tick: =>
114 { struct, key, val } = @unwrap_all!
115
116 struct = {k,v for k,v in pairs struct}
117 struct[key] = nil
118
119 @out\set struct
120
121 Constant.meta
122 meta:
123 name: 'struct'
124 summary: "Utilities for dealing with structs."
125
126 value:
127 :get, :set
128 :insert, :remove
11 import T, Array, Constant from require 'alv'
22
33 describe "array", ->
4 test = TestPilot '', '(import* array)\n'
4 test = TestPilot '', '(import* array-)\n'
55
66 svec3 = Array 3, T.str
77
11 import T, Struct, Constant from require 'alv'
22
33 describe "struct", ->
4 test = TestPilot '', '(import* struct)\n'
4 test = TestPilot '', '(import* struct-)\n'
55
66 ab = Struct { a: T.num, b: T.bool }
77