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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
import Struct, Op, PureOp, Constant, Error, const, any, sig from require 'alv.base'
key_type = const.str / const.sym
get = Constant.meta
meta:
name: 'get'
summary: "Index into a struct."
examples: { '(get struct key)' }
description: "Get the value at `key`.
`key` has to be a constant expression."
value: class extends PureOp
pattern: any! + key_type
type: (inputs) =>
{ struct, key } = inputs
struct\type!\get key.result!
tick: =>
{ struct, key } = @unwrap_all!
@out\set struct[key]
getdef = Constant.meta
meta:
name: 'getdef'
summary: "Index into a struct, with a default fallback."
examples: { '(get struct key default)' }
description: "Get the value at `key`, or fall back to `default`.
`key` has to be a constant expression."
value: class extends PureOp
pattern: any! + key_type + sig!
type: (inputs) =>
{ struct, key, default } = inputs
itype = struct\type!.types[key.result!]
dtype = default\type!
if itype
assert itype == dtype, Error 'argument', "default needs to be of same type as indexed"
dtype
tick: =>
{ struct, key, default } = @unwrap_all!
@out\set struct[key] or default
set = Constant.meta
meta:
name: 'set'
summary: "Update values in a struct."
examples: { '(set struct key val)' }
description: "Set the value for `key` to `val`.
`key` has to be a constant expression. This is a pure op, so at most one of
`struct` and `val` may be a !-stream."
value: class extends PureOp
pattern: any! + key_type + any!
type: (inputs) =>
{ struct, key, val } = inputs
type = struct\type!
expected = type\get key.result!
if expected ~= val\type!
msg = string.format "expected value for key '%s' to be %s, not %s",
key.result!, expected, val\type!
error Error 'argument', msg
type
tick: =>
{ struct, key, val } = @unwrap_all!
struct = {k,v for k,v in pairs struct}
struct[key] = val
@out\set struct
insert = Constant.meta
meta:
name: 'insert'
summary: "Insert a new value into a struct."
examples: { '(insert struct key val)' }
description: "Insert `val` into `struct` at `key`.
`key` has to be a constant expression. This is a pure op, so at most one of
`struct` and `val` may be a !-stream."
value: class extends PureOp
pattern: any! + key_type + any!
type: (inputs) =>
{ struct, key, val } = inputs
type = struct\type!
key = key.result!
if type.types[key]
msg = string.format "key '%s' already exists in value of type %s",
key, type
error Error 'argument', msg
types = {k,v for k,v in pairs type.types}
types[key] = val\type!
Struct types
tick: =>
{ struct, key, val } = @unwrap_all!
struct = {k,v for k,v in pairs struct}
struct[key] = val
@out\set struct
remove = Constant.meta
meta:
name: 'remove'
summary: "Remove values from a struct."
examples: { '(remove struct key)' }
description: "Removes the value at index `key` from `struct`.
`key` has to be a constant expression."
value: class extends PureOp
pattern: any! + key_type
type: (inputs) =>
{ struct, key } = inputs
type = struct\type!
key = key.result!
-- check key exists
type\get key
types = {k,v for k,v in pairs type.types}
types[key] = nil
Struct types
tick: =>
{ struct, key, val } = @unwrap_all!
struct = {k,v for k,v in pairs struct}
struct[key] = nil
@out\set struct
Constant.meta
meta:
name: 'struct'
summary: "Utilities for dealing with structs."
value:
:get, :getdef, :set
:insert, :remove
|