@adapt-toolkit/mufl 0.8.0
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/LICENSE +172 -0
- package/LICENSE.fsl +105 -0
- package/NOTICE +25 -0
- package/README.md +70 -0
- package/bin/mufl-compile.js +4 -0
- package/bin/mufl.js +4 -0
- package/lib/launcher.js +60 -0
- package/lib/paths.js +26 -0
- package/meta/meta.mm +2666 -0
- package/mufl_stdlib/config.mufl +86 -0
- package/mufl_stdlib/continuation.mm +51 -0
- package/mufl_stdlib/control_packet.mu +184 -0
- package/mufl_stdlib/cryptography/address_document.mm +333 -0
- package/mufl_stdlib/cryptography/address_document_types.mm +16 -0
- package/mufl_stdlib/cryptography/attestation/attestation_document.mm +68 -0
- package/mufl_stdlib/cryptography/attestation/config.mufl +12 -0
- package/mufl_stdlib/cryptography/attestation/container_associated_data.mm +12 -0
- package/mufl_stdlib/cryptography/attestation/control_packet_identity_proof_document.mm +36 -0
- package/mufl_stdlib/cryptography/attestation/identity_proof_document_impl.mm +57 -0
- package/mufl_stdlib/cryptography/attestation/identity_proof_document_types.mm +45 -0
- package/mufl_stdlib/cryptography/attestation/node_description.mm +9 -0
- package/mufl_stdlib/cryptography/attestation/platform_dependent_attestation_document/browser/browser_attestation_document.mm +25 -0
- package/mufl_stdlib/cryptography/attestation/platform_dependent_attestation_document/browser/config.mufl +12 -0
- package/mufl_stdlib/cryptography/attestation/platform_dependent_attestation_document/config.mufl +12 -0
- package/mufl_stdlib/cryptography/attestation/platform_dependent_attestation_document/native/config.mufl +12 -0
- package/mufl_stdlib/cryptography/attestation/platform_dependent_attestation_document/native/native_attestation_document.mm +25 -0
- package/mufl_stdlib/cryptography/attestation/platform_dependent_attestation_document/platform_dependent_attestation_document.mm +57 -0
- package/mufl_stdlib/cryptography/authorizing_container.mm +21 -0
- package/mufl_stdlib/cryptography/config.mufl +12 -0
- package/mufl_stdlib/cryptography/encrypted_channel.mm +95 -0
- package/mufl_stdlib/cryptography/key_storage.mm +391 -0
- package/mufl_stdlib/cryptography/key_storage_api.mm +17 -0
- package/mufl_stdlib/cryptography/key_utils.mm +20 -0
- package/mufl_stdlib/cryptography/peer_container.mu +17 -0
- package/mufl_stdlib/cryptography/registration_proof.mm +40 -0
- package/mufl_stdlib/current_transaction_info.mm +78 -0
- package/mufl_stdlib/identity_proof_document.mm +21 -0
- package/mufl_stdlib/integration_test_api.mm +39 -0
- package/mufl_stdlib/lists.mm +84 -0
- package/mufl_stdlib/permissions.mm +219 -0
- package/mufl_stdlib/platform_type_id.mm +20 -0
- package/mufl_stdlib/random.mm +50 -0
- package/mufl_stdlib/rslt.mm +32 -0
- package/mufl_stdlib/transaction_message_decoder.mm +22 -0
- package/mufl_stdlib/transaction_queue.mm +60 -0
- package/mufl_stdlib/vector.mm +115 -0
- package/mufl_stdlib/verification.mm +35 -0
- package/package.json +43 -0
- package/prebuilds/linux-x64/mufl +0 -0
- package/prebuilds/linux-x64/mufl-compile +0 -0
- package/transactions/__t_wrapper.mm +169 -0
- package/transactions/config.mufl +22 -0
- package/transactions/transaction.mm +200 -0
package/meta/meta.mm
ADDED
|
@@ -0,0 +1,2666 @@
|
|
|
1
|
+
PRAGMA LANGSERVER meta = 0
|
|
2
|
+
library meta {
|
|
3
|
+
// TODO: tests for present cast
|
|
4
|
+
// TODO: tests for function and mutable type compatibility (tricky with arg/return)
|
|
5
|
+
|
|
6
|
+
// "rtype" const
|
|
7
|
+
// "ptype" const
|
|
8
|
+
// "ptype_detailed" func( rtype )
|
|
9
|
+
// "description" const str
|
|
10
|
+
// "verify_reduction" func( rtype )
|
|
11
|
+
// "verify_reference_extention" func( rtype )
|
|
12
|
+
// "safe_cast"
|
|
13
|
+
// "iteration" -> true/false
|
|
14
|
+
// "reduction" -> true/false
|
|
15
|
+
// "reference_extention" -> true/false
|
|
16
|
+
// "check_compatibility"
|
|
17
|
+
|
|
18
|
+
// "base_type"
|
|
19
|
+
// "const_value"
|
|
20
|
+
|
|
21
|
+
// LOC_REF file line col line col <NODE>
|
|
22
|
+
|
|
23
|
+
names_root=(,).
|
|
24
|
+
lookup_root=(,).
|
|
25
|
+
|
|
26
|
+
__global_meta_runtime = (,).
|
|
27
|
+
__eval_tree_type_info = (,).
|
|
28
|
+
__eval_tree_info = (,).
|
|
29
|
+
|
|
30
|
+
module internal {
|
|
31
|
+
set_eval_tree_type_info = fn (id, type) {
|
|
32
|
+
__eval_tree_type_info id -> type.
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pass_info = fn (id, val) {
|
|
36
|
+
__eval_tree_info id -> val.
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get_info = fn (id) = (__eval_tree_info id).
|
|
40
|
+
|
|
41
|
+
print_deep = fn (val) {
|
|
42
|
+
if _typeof val != "IMMUTABLE_DICTIONARY" {
|
|
43
|
+
_print val.
|
|
44
|
+
} else {
|
|
45
|
+
counter = 0.
|
|
46
|
+
_print "(".
|
|
47
|
+
sc val -- (elem->value) {
|
|
48
|
+
if counter > 0 {
|
|
49
|
+
_print ",".
|
|
50
|
+
}
|
|
51
|
+
counter->counter + 1.
|
|
52
|
+
print_deep elem "->" value.
|
|
53
|
+
}
|
|
54
|
+
if counter == 0 {
|
|
55
|
+
_print ",".
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_print ")".
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
RETURN print_deep.
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
de_const = fn (t) {
|
|
65
|
+
if t "base_type_of_const" {
|
|
66
|
+
RETURN t "base_type_of_const".
|
|
67
|
+
} else {
|
|
68
|
+
RETURN t.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module forwards {
|
|
74
|
+
module conversions {
|
|
75
|
+
safe_cast = NIL.
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
disjunction = NIL.
|
|
79
|
+
conjunction = NIL.
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module domain {
|
|
83
|
+
any = 0.
|
|
84
|
+
nil = 1.
|
|
85
|
+
true = 2.
|
|
86
|
+
false = 3.
|
|
87
|
+
primitives = 4.
|
|
88
|
+
integer = 5.
|
|
89
|
+
string = 6.
|
|
90
|
+
code = 7.
|
|
91
|
+
dictionary = 8.
|
|
92
|
+
int_seq = 9.
|
|
93
|
+
packet = 10.
|
|
94
|
+
saferef = 11.
|
|
95
|
+
binary = 12.
|
|
96
|
+
crypto = 13.
|
|
97
|
+
time = 14.
|
|
98
|
+
hash_code = 15.
|
|
99
|
+
utf8 = 16.
|
|
100
|
+
|
|
101
|
+
name = (
|
|
102
|
+
any -> "any",
|
|
103
|
+
nil -> "nil",
|
|
104
|
+
true -> "true",
|
|
105
|
+
primitives -> "primitives",
|
|
106
|
+
integer -> "integer",
|
|
107
|
+
string -> "string",
|
|
108
|
+
code -> "code",
|
|
109
|
+
dictionary -> "dictionary",
|
|
110
|
+
int_seq -> "int_seq",
|
|
111
|
+
packet -> "packet",
|
|
112
|
+
saferef -> "saferef",
|
|
113
|
+
binary -> "binary",
|
|
114
|
+
crypto -> "crypto",
|
|
115
|
+
time -> "time",
|
|
116
|
+
hash_code -> "hash_code",
|
|
117
|
+
utf8 -> "utf8"
|
|
118
|
+
|
|
119
|
+
).
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
domain_conversions_tmp = (
|
|
123
|
+
_str nil -> "NIL",
|
|
124
|
+
_str true -> "TRUE",
|
|
125
|
+
_str integer -> "INTEGER",
|
|
126
|
+
_str string -> "STRING",
|
|
127
|
+
_str int_seq -> "INTEGER_SEQUENCE",
|
|
128
|
+
_str saferef -> "SAFEREF",
|
|
129
|
+
_str packet -> "PACKET",
|
|
130
|
+
_str binary -> "BINARY",
|
|
131
|
+
_str crypto -> "CRYPTO_ELEMENT",
|
|
132
|
+
_str time -> "TIME",
|
|
133
|
+
_str hash_code -> "HASH_CODE",
|
|
134
|
+
_str utf8 -> "UTF8"
|
|
135
|
+
).
|
|
136
|
+
|
|
137
|
+
__global_meta_runtime "domain_conversions" -> domain_conversions_tmp.
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module test_mode {
|
|
141
|
+
on = NIL.
|
|
142
|
+
err = NIL.
|
|
143
|
+
set_test_mode = fn (_) { on -> TRUE. }
|
|
144
|
+
clear_error = fn (_) { err -> NIL. }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
hidden {
|
|
148
|
+
error_state = NIL.
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
error_state_reset = fn (_) { error_state->NIL. }
|
|
152
|
+
error_state_finalize = fn (_) {
|
|
153
|
+
if( error_state != NIL ) {
|
|
154
|
+
_e_print "Evaluation aborted due to meta-stage error\n".
|
|
155
|
+
RETURN NIL.
|
|
156
|
+
} else {
|
|
157
|
+
RETURN TRUE.
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
signal_error = fn (message, err) {
|
|
162
|
+
if test_mode::on {
|
|
163
|
+
test_mode::err -> (err + ": " + message).
|
|
164
|
+
_print "TEST MODE: " test_mode::err "\n".
|
|
165
|
+
} else {
|
|
166
|
+
error_state->TRUE.
|
|
167
|
+
_e_print (err + ": " + message + "\n").
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
hidden {
|
|
172
|
+
any_type = (
|
|
173
|
+
"is_any_type" -> TRUE,
|
|
174
|
+
"describe" -> fn (_) = "any",
|
|
175
|
+
"verify_reduction" -> fn (_) = [ any_type, NIL ],
|
|
176
|
+
"reference_extention" -> fn (_) = any_type,
|
|
177
|
+
"iteration" -> fn (_) = ("ptype"->any_type, "rtype"->any_type),
|
|
178
|
+
"check_compatibility" -> fn (_) = TRUE,
|
|
179
|
+
"safe_cast" -> fn (_type_from, _error) {
|
|
180
|
+
RETURN fn (value) = value.
|
|
181
|
+
}
|
|
182
|
+
).
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
no_safe_cast = fn (description) {
|
|
186
|
+
RETURN fn (_type_from, err) {
|
|
187
|
+
signal_error ( "Type " + description + ") not support SAFE cast") err.
|
|
188
|
+
}.
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
mutation_forbidden = fn (description) {
|
|
192
|
+
RETURN fn (err, reducer, product) {
|
|
193
|
+
err_msg = "Invalid mutation for " + description +
|
|
194
|
+
" (Observed reducer as " + (reducer "describe" NIL) +
|
|
195
|
+
", product as " + (product "describe" NIL) + ")".
|
|
196
|
+
|
|
197
|
+
::meta::signal_error err_msg err.
|
|
198
|
+
RETURN any_type.
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
iteration_forbidden = fn (description) {
|
|
203
|
+
RETURN fn (err) {
|
|
204
|
+
err_msg = "Invalid iteration for " + description.
|
|
205
|
+
::meta::signal_error err_msg err.
|
|
206
|
+
RETURN ("ptype"->any_type, "rtype"->any_type).
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
reduction_forbidden = fn (description) {
|
|
211
|
+
RETURN fn (reducer) {
|
|
212
|
+
err = "Invalid reduction for " + description +
|
|
213
|
+
" (Observed reducer as " + (reducer "describe" NIL) + ")".
|
|
214
|
+
|
|
215
|
+
RETURN [ any_type, err ].
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
reference_extention_forbidden = fn (description) {
|
|
220
|
+
RETURN fn (_reducer) {
|
|
221
|
+
err = "Invalid reference extention for " + description.
|
|
222
|
+
|
|
223
|
+
RETURN [ any_type, err ].
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module basics {
|
|
228
|
+
|
|
229
|
+
nothing = fn (description)
|
|
230
|
+
{
|
|
231
|
+
ret = (
|
|
232
|
+
"describe" -> fn (_) = description,
|
|
233
|
+
"check_compatibility" -> fn (_actual) = NIL,
|
|
234
|
+
"verify_reduction" -> reduction_forbidden description,
|
|
235
|
+
"iteration" -> iteration_forbidden description,
|
|
236
|
+
"safe_cast" -> no_safe_cast description,
|
|
237
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
238
|
+
).
|
|
239
|
+
|
|
240
|
+
RETURN ret.
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
none = nothing "meta::basics::none".
|
|
244
|
+
|
|
245
|
+
nil = (
|
|
246
|
+
"is_domain" -> TRUE,
|
|
247
|
+
"is_const" -> TRUE,
|
|
248
|
+
"const_value" -> NIL,
|
|
249
|
+
"describe" -> fn (_) = $nil,
|
|
250
|
+
"domain" -> domain::nil,
|
|
251
|
+
"verify_reduction" -> reduction_forbidden $nil,
|
|
252
|
+
"iteration" -> iteration_forbidden $nil,
|
|
253
|
+
"check_compatibility" -> fn (actual) = (actual "domain" == domain::nil),
|
|
254
|
+
"reference_extention" -> reference_extention_forbidden $nil,
|
|
255
|
+
).
|
|
256
|
+
|
|
257
|
+
true = (
|
|
258
|
+
"is_domain" -> TRUE,
|
|
259
|
+
"is_const" -> TRUE,
|
|
260
|
+
"const_value" -> TRUE,
|
|
261
|
+
"describe" -> fn (_) = $true,
|
|
262
|
+
"domain" -> domain::true,
|
|
263
|
+
"verify_reduction" -> reduction_forbidden $true,
|
|
264
|
+
"iteration" -> iteration_forbidden $true,
|
|
265
|
+
"check_compatibility" -> fn (actual) = (actual "domain" == domain::true),
|
|
266
|
+
"reference_extention" -> reference_extention_forbidden $true,
|
|
267
|
+
).
|
|
268
|
+
|
|
269
|
+
false = (
|
|
270
|
+
"is_domain" -> TRUE,
|
|
271
|
+
"is_const" -> TRUE,
|
|
272
|
+
"const_value" -> FALSE,
|
|
273
|
+
"describe" -> fn (_) = $false,
|
|
274
|
+
"domain" -> domain::false,
|
|
275
|
+
"verify_reduction" -> reduction_forbidden $false,
|
|
276
|
+
"iteration" -> iteration_forbidden $false,
|
|
277
|
+
"check_compatibility" -> fn (actual) = (actual "domain" == domain::false),
|
|
278
|
+
"reference_extention" -> reference_extention_forbidden $false,
|
|
279
|
+
).
|
|
280
|
+
|
|
281
|
+
packet = (
|
|
282
|
+
"is_domain" -> TRUE,
|
|
283
|
+
"domain" -> domain::packet,
|
|
284
|
+
"describe" -> fn (_) = $db,
|
|
285
|
+
"verify_reduction" -> reduction_forbidden $db,
|
|
286
|
+
"iteration" -> iteration_forbidden $db,
|
|
287
|
+
"check_compatibility" -> fn (actual) = (actual "domain" == domain::packet),
|
|
288
|
+
"reference_extention" -> reference_extention_forbidden $db,
|
|
289
|
+
).
|
|
290
|
+
|
|
291
|
+
saferef = (
|
|
292
|
+
"is_domain" -> TRUE,
|
|
293
|
+
"domain" -> domain::saferef,
|
|
294
|
+
"describe" -> fn (_) = $sr,
|
|
295
|
+
"verify_reduction" -> reduction_forbidden $sr,
|
|
296
|
+
"iteration" -> iteration_forbidden $sr,
|
|
297
|
+
"check_compatibility" -> fn (actual) = (actual "domain" == domain::saferef),
|
|
298
|
+
"reference_extention" -> reference_extention_forbidden $sr,
|
|
299
|
+
).
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
integer = (
|
|
303
|
+
"is_domain" -> TRUE,
|
|
304
|
+
"domain" -> domain::integer,
|
|
305
|
+
"describe" -> fn (_) = $int,
|
|
306
|
+
"verify_reduction" -> reduction_forbidden $int,
|
|
307
|
+
"iteration" -> iteration_forbidden $int,
|
|
308
|
+
"check_compatibility" -> fn (actual) { return domain::integer == actual "domain". },
|
|
309
|
+
"reference_extention" -> reference_extention_forbidden $int,
|
|
310
|
+
).
|
|
311
|
+
|
|
312
|
+
string = (
|
|
313
|
+
"is_domain"->TRUE,
|
|
314
|
+
"is_iterable" -> TRUE,
|
|
315
|
+
"domain"->domain::string,
|
|
316
|
+
"describe" -> fn (_) = $str,
|
|
317
|
+
"rtype" -> basics::integer,
|
|
318
|
+
"verify_reduction" -> fn (arg) {
|
|
319
|
+
if arg "domain" != domain::integer {
|
|
320
|
+
RETURN [ any_type, "String reduction requires integer argument " ].
|
|
321
|
+
} else {
|
|
322
|
+
RETURN [ string, NIL ].
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
"iteration" -> fn (_err) = ("rtype"->basics::integer, "ptype"->basics::string),
|
|
326
|
+
"check_compatibility" -> fn (actual) {
|
|
327
|
+
RETURN domain::string == actual "domain".
|
|
328
|
+
},
|
|
329
|
+
"reference_extention" -> reference_extention_forbidden $str,
|
|
330
|
+
).
|
|
331
|
+
|
|
332
|
+
binary = (
|
|
333
|
+
"is_domain"->TRUE,
|
|
334
|
+
"is_iterable" -> TRUE,
|
|
335
|
+
"domain"->domain::binary,
|
|
336
|
+
"describe" -> fn (_) = $bin,
|
|
337
|
+
"rtype" -> basics::integer,
|
|
338
|
+
"ptype" -> basics::integer,
|
|
339
|
+
"verify_reduction" -> fn (arg) {
|
|
340
|
+
if arg "domain" != domain::integer {
|
|
341
|
+
RETURN [ any_type, "Binary reduction requires integer argument " ].
|
|
342
|
+
} else {
|
|
343
|
+
RETURN [ integer, NIL ].
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
"iteration" -> fn (_err) = ("rtype"->basics::integer, "ptype"->basics::integer),
|
|
347
|
+
"check_compatibility" -> fn (actual) {
|
|
348
|
+
RETURN domain::binary == actual "domain".
|
|
349
|
+
},
|
|
350
|
+
"reference_extention" -> reference_extention_forbidden $bin,
|
|
351
|
+
).
|
|
352
|
+
|
|
353
|
+
utf8 = (
|
|
354
|
+
"is_domain"->TRUE,
|
|
355
|
+
"is_iterable"->TRUE,
|
|
356
|
+
"domain"->domain::utf8,
|
|
357
|
+
"describe" -> fn (_) = $utf8,
|
|
358
|
+
"rtype" -> basics::integer,
|
|
359
|
+
"ptype" -> basics::utf8,
|
|
360
|
+
"verify_reduction" -> fn (arg) {
|
|
361
|
+
if arg "domain" != domain::integer {
|
|
362
|
+
RETURN [ any_type, "UTF-8 reduction requires integer argument " ].
|
|
363
|
+
} else {
|
|
364
|
+
RETURN [ integer, NIL ].
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
"iteration" -> fn (_err) = ("rtype"->basics::integer, "ptype" -> basics::utf8),
|
|
368
|
+
"check_compatibility" -> fn (actual) {
|
|
369
|
+
RETURN domain::utf8 == actual "domain".
|
|
370
|
+
},
|
|
371
|
+
"reference_extention" -> reference_extention_forbidden $utf8
|
|
372
|
+
).
|
|
373
|
+
|
|
374
|
+
boolean = (
|
|
375
|
+
"describe" -> fn (_) = $bool,
|
|
376
|
+
"verify_reduction" -> reduction_forbidden $bool,
|
|
377
|
+
"iteration" -> iteration_forbidden $bool,
|
|
378
|
+
"check_compatibility" -> fn (_actual) { return TRUE. },
|
|
379
|
+
"safe_cast" -> fn (_type_from, _err) {
|
|
380
|
+
RETURN fn (value) {
|
|
381
|
+
abort provisional "Value not boolean" WHEN value != TRUE && value != FALSE.
|
|
382
|
+
RETURN value.
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
"reference_extention" -> reference_extention_forbidden $bool,
|
|
386
|
+
).
|
|
387
|
+
|
|
388
|
+
time = (
|
|
389
|
+
"is_domain" -> TRUE,
|
|
390
|
+
"domain" -> domain::time,
|
|
391
|
+
"describe" -> fn (_) = $time,
|
|
392
|
+
"verify_reduction" -> reduction_forbidden $time,
|
|
393
|
+
"iteration" -> iteration_forbidden $time,
|
|
394
|
+
"check_compatibility" -> fn (actual) {
|
|
395
|
+
RETURN domain::time == actual "domain".
|
|
396
|
+
},
|
|
397
|
+
"reference_extention" -> reference_extention_forbidden $time
|
|
398
|
+
).
|
|
399
|
+
|
|
400
|
+
hash_code = (
|
|
401
|
+
"is_domain" -> TRUE,
|
|
402
|
+
"domain" -> domain::hash_code,
|
|
403
|
+
"describe" -> fn (_) = $hash_code,
|
|
404
|
+
"verify_reduction" -> reduction_forbidden $hash_code,
|
|
405
|
+
"iteration" -> iteration_forbidden $hash_code,
|
|
406
|
+
"check_compatibility" -> fn (actual) {
|
|
407
|
+
RETURN domain::hash_code == actual $domain.
|
|
408
|
+
},
|
|
409
|
+
"reference_extention" -> reference_extention_forbidden $hash_code
|
|
410
|
+
).
|
|
411
|
+
|
|
412
|
+
any = any_type.
|
|
413
|
+
|
|
414
|
+
constant = fn (type, value) {
|
|
415
|
+
RETURN type'($is_const->TRUE, $const_value->value, $base_type_of_const->type).
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
module compatibility {
|
|
421
|
+
check = fn (needed, actual) {
|
|
422
|
+
if actual == basics::none {
|
|
423
|
+
RETURN TRUE.
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if actual $is_opaque && check needed (actual $base_type) {
|
|
427
|
+
RETURN TRUE.
|
|
428
|
+
} elif actual $is_conjunction {
|
|
429
|
+
sc actual $types -- (t->) {
|
|
430
|
+
if check needed t {
|
|
431
|
+
RETURN TRUE.
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
RETURN NIL.
|
|
435
|
+
} elif actual $is_disjunction {
|
|
436
|
+
sc actual $types -- (t -> ) {
|
|
437
|
+
if !(check needed t) {
|
|
438
|
+
RETURN NIL.
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
RETURN TRUE.
|
|
442
|
+
} else {
|
|
443
|
+
RETURN (needed "check_compatibility" actual).
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
check_or_error = fn (err, needed, actual) {
|
|
448
|
+
if !(check needed actual) {
|
|
449
|
+
message = "Incompatible type detected. Required " + (needed "describe" NIL) + ", but observing " + (actual "describe" NIL).
|
|
450
|
+
signal_error message err.
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
combine_types = fn (err, type_a, type_b) {
|
|
455
|
+
if check type_a type_b {
|
|
456
|
+
RETURN type_a.
|
|
457
|
+
} else {
|
|
458
|
+
if check type_b type_a {
|
|
459
|
+
RETURN type_b.
|
|
460
|
+
} else {
|
|
461
|
+
message = "Incompatible types in conditional expression, " + (type_a "describe" NIL) + " can not be combined with " + (type_b "describe" NIL).
|
|
462
|
+
signal_error message err.
|
|
463
|
+
RETURN basics::any.
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
module opaque {
|
|
470
|
+
type = fn (name, base_type, check_func)
|
|
471
|
+
{
|
|
472
|
+
description = "(::meta::opaque::type \"" + name + "\" " + (base_type "describe" NIL) + ")".
|
|
473
|
+
res = (
|
|
474
|
+
$is_opaque -> TRUE,
|
|
475
|
+
$domain -> base_type $domain,
|
|
476
|
+
$name -> name,
|
|
477
|
+
$base_type -> base_type,
|
|
478
|
+
$describe -> fn (_) = description,
|
|
479
|
+
$verify_reduction -> reduction_forbidden description,
|
|
480
|
+
$iteration -> iteration_forbidden description,
|
|
481
|
+
$check_compatibility -> fn (actual) {
|
|
482
|
+
if !( actual $is_opaque) {
|
|
483
|
+
RETURN NIL.
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
RETURN actual $name == name && actual $base_type == base_type.
|
|
487
|
+
},
|
|
488
|
+
$safe_cast -> fn (_type_from, _err) = check_func,
|
|
489
|
+
$reference_extention -> reference_extention_forbidden description,
|
|
490
|
+
).
|
|
491
|
+
|
|
492
|
+
RETURN res.
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
module crypto_element {
|
|
497
|
+
hidden {
|
|
498
|
+
crypto_scheme_sc = fn (x) {
|
|
499
|
+
if (x != 1) {
|
|
500
|
+
_abort_transaction ("Invalid schema id, allowed 1 but got " + (_str x)).
|
|
501
|
+
RETURN NIL.
|
|
502
|
+
} else {
|
|
503
|
+
RETURN x.
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
encrypt__secretkey_check = fn (x) {
|
|
508
|
+
if !(_crypto_element_validate x 1 $SECKEY_ENCRYPT) {
|
|
509
|
+
_abort_transaction "Invalid encrypt-private key, verification failed".
|
|
510
|
+
} else {
|
|
511
|
+
RETURN x.
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
RETURN NIL.
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
sign__secretkey_check = fn (x) {
|
|
518
|
+
if !(_crypto_element_validate x 1 $SECKEY_SIGN) {
|
|
519
|
+
_abort_transaction "Invalid sign-private key, verification failed".
|
|
520
|
+
} else {
|
|
521
|
+
RETURN x.
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
RETURN NIL.
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
encrypt__publickey_check = fn (x) {
|
|
528
|
+
if !(_crypto_element_validate x 1 $PUBKEY_ENCRYPT) {
|
|
529
|
+
_abort_transaction "Invalid encrypt-public key, verification failed".
|
|
530
|
+
} else {
|
|
531
|
+
RETURN x.
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
RETURN NIL.
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
sign__publickey_check = fn (x) {
|
|
539
|
+
if !(_crypto_element_validate x 1 $PUBKEY_SIGN) {
|
|
540
|
+
_abort_transaction "Invalid sign-public key, verification failed".
|
|
541
|
+
} else {
|
|
542
|
+
RETURN x.
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
RETURN NIL.
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
signature_check = fn (x) {
|
|
549
|
+
if !(_crypto_element_validate x 1 $SIGNATURE) {
|
|
550
|
+
_abort_transaction "Invalid signature, verification failed".
|
|
551
|
+
} else {
|
|
552
|
+
RETURN x.
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
RETURN NIL.
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
encrypted_data_check = fn (x) {
|
|
559
|
+
if !(_crypto_element_validate x 1 $ENCRYPTED_DATA) {
|
|
560
|
+
_abort_transaction "Invalid encrypted message, verification failed".
|
|
561
|
+
} else {
|
|
562
|
+
RETURN x.
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
RETURN NIL.
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
type = fn (kind) {
|
|
570
|
+
if( kind != $ANY && !(_crypto_validate_kind kind) ) {
|
|
571
|
+
signal_error ("Invalid crypto element kind "+kind) "".
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
validator = fn (id, kind, value)
|
|
575
|
+
{
|
|
576
|
+
if _typeof value != "CRYPTO_ELEMENT" {
|
|
577
|
+
_abort_transaction_provisional ("Invalid value for crypto element: required CRYPTO_ELEMENT domain but found " + (_typeof value)).
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if kind == $ANY {
|
|
581
|
+
kind->_crypto_get_element_kind value.
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if !(_crypto_element_validate value id kind) {
|
|
585
|
+
_abort_transaction_provisional ("Invalid crypto element -- validation failed for kind " + kind + " id " + (_str id)).
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
RETURN value.
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
RETURN (
|
|
592
|
+
"is_domain"->TRUE,
|
|
593
|
+
"domain"->domain::crypto,
|
|
594
|
+
"kind"->kind,
|
|
595
|
+
"describe" -> fn (_) = ("(crypto " + kind + ")"),
|
|
596
|
+
"verify_reduction" -> reduction_forbidden $crypto,
|
|
597
|
+
"check_compatibility" -> fn (actual) {
|
|
598
|
+
if domain::crypto != actual "domain" {
|
|
599
|
+
RETURN NIL.
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
if kind == "ANY" {
|
|
603
|
+
RETURN TRUE.
|
|
604
|
+
} else {
|
|
605
|
+
RETURN kind == actual "kind".
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
"safe_cast" -> fn (_type_from, _err) {
|
|
609
|
+
RETURN validator 0 kind.
|
|
610
|
+
},
|
|
611
|
+
"reference_extention" -> reference_extention_forbidden $crypto,
|
|
612
|
+
).
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
global_id_check = fn (x) {
|
|
616
|
+
if _typeof x != "STRING" {
|
|
617
|
+
_abort_transaction_provisional "Global id check failed".
|
|
618
|
+
}
|
|
619
|
+
_validate_global_id_string x.
|
|
620
|
+
RETURN x.
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
module nullable {
|
|
625
|
+
allows_null_values = fn (t)
|
|
626
|
+
{
|
|
627
|
+
RETURN ( t "domain" == domain::nil ) || ( t "is_nullable" ) || ( t "is_any_type" ).
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
type = fn (t)
|
|
631
|
+
{
|
|
632
|
+
if allows_null_values t {
|
|
633
|
+
RETURN t.
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
description = (t "describe" NIL) + "+".
|
|
637
|
+
res = (
|
|
638
|
+
"is_nullable" -> TRUE,
|
|
639
|
+
"non_null_type" -> t,
|
|
640
|
+
"describe" -> fn (_)
|
|
641
|
+
{
|
|
642
|
+
RETURN description.
|
|
643
|
+
},
|
|
644
|
+
"verify_reduction" -> fn (arg) = (t "verify_reduction" arg),
|
|
645
|
+
"iteration" -> iteration_forbidden description,
|
|
646
|
+
"check_compatibility" -> fn (actual) {
|
|
647
|
+
if actual "is_domain" && actual "domain" == domain::nil {
|
|
648
|
+
RETURN TRUE.
|
|
649
|
+
} elif actual "is_nullable" {
|
|
650
|
+
RETURN t "check_compatibility" (actual "non_null_type").
|
|
651
|
+
} else {
|
|
652
|
+
RETURN t "check_compatibility" actual.
|
|
653
|
+
}.
|
|
654
|
+
},
|
|
655
|
+
"safe_cast" -> fn (type_from, err) {
|
|
656
|
+
base_type_cast = forwards::conversions::safe_cast type_from t err.
|
|
657
|
+
RETURN fn (value)
|
|
658
|
+
{
|
|
659
|
+
if value == NIL { RETURN NIL. } else { RETURN base_type_cast value. }
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
663
|
+
).
|
|
664
|
+
|
|
665
|
+
RETURN res.
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
get_product_type_no_err = fn (f)
|
|
669
|
+
{
|
|
670
|
+
if f "is_function" {
|
|
671
|
+
RETURN f "ptype".
|
|
672
|
+
} elif f "iterable" || f "is_immutable" {
|
|
673
|
+
RETURN f "ptype".
|
|
674
|
+
} elif f "is_record" || f "is_tuple" {
|
|
675
|
+
RETURN basics::any. // TODO
|
|
676
|
+
} elif f "is_any_type" {
|
|
677
|
+
RETURN basics::any.
|
|
678
|
+
} elif f "is_conjunction" || f "is_disjunction" {
|
|
679
|
+
RETURN f "product".
|
|
680
|
+
} else {
|
|
681
|
+
RETURN basics::none.
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
is_product_nullable_by_id = fn (id)
|
|
686
|
+
{
|
|
687
|
+
type_definition = __eval_tree_type_info id.
|
|
688
|
+
if type_definition $is_tuple || type_definition $is_record {
|
|
689
|
+
RETURN TRUE.
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
product_type = get_product_type_no_err type_definition.
|
|
693
|
+
if product_type $is_immutable || product_type $is_tuple || product_type $is_record {
|
|
694
|
+
RETURN TRUE.
|
|
695
|
+
} else {
|
|
696
|
+
RETURN allows_null_values product_type.
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
remove = fn (t)
|
|
701
|
+
{
|
|
702
|
+
if t $is_nullable {
|
|
703
|
+
RETURN t $non_null_type.
|
|
704
|
+
} else {
|
|
705
|
+
RETURN t.
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
remove_maybe = fn (t, def)
|
|
710
|
+
{
|
|
711
|
+
if allows_null_values def {
|
|
712
|
+
RETURN t.
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
RETURN remove t.
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
module conversions {
|
|
720
|
+
safe_cast = fn (type_from, type_to, err)
|
|
721
|
+
{
|
|
722
|
+
if type_to "safe_cast" != NIL {
|
|
723
|
+
RETURN type_to "safe_cast" type_from err.
|
|
724
|
+
} elif type_to "is_domain" {
|
|
725
|
+
dom = type_to "domain".
|
|
726
|
+
required_domain = domain::name dom.
|
|
727
|
+
RETURN fn (value)
|
|
728
|
+
{
|
|
729
|
+
abort provisional err + ": Runtime mismatch for SAFE cast: Invalid value domain. Required: " + required_domain + " but observing " + (_typeof value)
|
|
730
|
+
WHEN _typeof value != __global_meta_runtime "domain_conversions" (_str dom).
|
|
731
|
+
|
|
732
|
+
RETURN value.
|
|
733
|
+
}
|
|
734
|
+
} else {
|
|
735
|
+
signal_error ("Safe cast not available for type " + (type_to "describe" NIL)) err.
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
forwards::conversions::safe_cast -> safe_cast.
|
|
740
|
+
|
|
741
|
+
present_cast = fn (type_from, err)
|
|
742
|
+
{
|
|
743
|
+
if !(nullable::allows_null_values type_from) {
|
|
744
|
+
RETURN fn (value) = value.
|
|
745
|
+
} else {
|
|
746
|
+
RETURN fn (value) {
|
|
747
|
+
abort provisional err + ": Runtime mismatch for PRESENT cast: value is NIL" WHEN value == NIL.
|
|
748
|
+
RETURN value.
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
module iterable {
|
|
755
|
+
type = fn (rtype, ptype)
|
|
756
|
+
{
|
|
757
|
+
description = "(" + (rtype "describe" NIL) + "*>" + (ptype "describe" NIL) + ")".
|
|
758
|
+
|
|
759
|
+
RETURN (
|
|
760
|
+
"is_iterable" -> TRUE,
|
|
761
|
+
"describe" -> fn (_) = description,
|
|
762
|
+
"rtype" -> rtype,
|
|
763
|
+
"ptype" -> ptype,
|
|
764
|
+
"check_compatibility" -> fn (actual) {
|
|
765
|
+
RETURN
|
|
766
|
+
(
|
|
767
|
+
(actual "is_iterable") &&
|
|
768
|
+
(rtype "check_compatibility" (actual "rtype")) &&
|
|
769
|
+
(ptype "check_compatibility" (actual "ptype"))
|
|
770
|
+
).
|
|
771
|
+
},
|
|
772
|
+
"iteration" -> fn (_err) = ("rtype"->rtype, "ptype"->ptype),
|
|
773
|
+
"verify_reduction" -> reduction_forbidden description,
|
|
774
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
775
|
+
).
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
integer_sequence = type basics::integer basics::integer.
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
module enumerated_sets {
|
|
783
|
+
sets_by_hash = (,).
|
|
784
|
+
|
|
785
|
+
type = fn (base_type, value_list) {
|
|
786
|
+
if base_type != basics::string && base_type != basics::integer {
|
|
787
|
+
signal_error ("Base type must be vanilla integer or string but found " + (base_type "describe" NIL)) "".
|
|
788
|
+
RETURN basics::string.
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
sc value_list -- (value -> ) {
|
|
792
|
+
if (base_type == basics::string && _typeof value != "STRING" ) ||
|
|
793
|
+
(base_type == basics::integer && _typeof value != "INTEGER" )
|
|
794
|
+
{
|
|
795
|
+
signal_error "invalid value list element, not compatible with base type" "".
|
|
796
|
+
RETURN basics::any.
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
type_hash = _value_id value_list abort "Unable to generate value hash" WHEN IS NIL.
|
|
801
|
+
__global_meta_runtime type_hash -> value_list.
|
|
802
|
+
|
|
803
|
+
type = sets_by_hash type_hash.
|
|
804
|
+
if type != NIL { RETURN type. }
|
|
805
|
+
|
|
806
|
+
SafeCast = fn (_type_from, _err)
|
|
807
|
+
{
|
|
808
|
+
RETURN fn (value)
|
|
809
|
+
{
|
|
810
|
+
if _typeof value != "STRING" {
|
|
811
|
+
_abort_transaction_provisional "Value) not match this value set: it is not a string".
|
|
812
|
+
} elif __global_meta_runtime type_hash value {
|
|
813
|
+
RETURN value.
|
|
814
|
+
} else {
|
|
815
|
+
_abort_transaction_provisional ("String value \"" + value + "\" does not match this value set").
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
Describe = fn (_)
|
|
821
|
+
{
|
|
822
|
+
Ret = (,).
|
|
823
|
+
Ret() -> "<".
|
|
824
|
+
sc value_list -- (value -> ) {
|
|
825
|
+
if base_type == basics::string {
|
|
826
|
+
Ret() -> Ret() + (_code_str value).
|
|
827
|
+
} else {
|
|
828
|
+
Ret() -> Ret() + (_str value).
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
Ret() -> Ret() + ",".
|
|
832
|
+
}
|
|
833
|
+
Ret() -> Ret() + ">".
|
|
834
|
+
RETURN Ret().
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
description = Describe().
|
|
838
|
+
|
|
839
|
+
CheckCompatibility = fn (actual) {
|
|
840
|
+
|
|
841
|
+
if actual "is_const" && value_list (actual "const_value") {
|
|
842
|
+
RETURN TRUE.
|
|
843
|
+
} elif actual "is_enumerated_set" {
|
|
844
|
+
if actual "type_hash" == type_hash {
|
|
845
|
+
RETURN TRUE.
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
if actual "base_type" != base_type {
|
|
849
|
+
RETURN NIL.
|
|
850
|
+
}
|
|
851
|
+
sc actual "value_list" -- (v -> ) {
|
|
852
|
+
if !(value_list v) {
|
|
853
|
+
RETURN NIL.
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
RETURN TRUE.
|
|
858
|
+
} else {
|
|
859
|
+
RETURN NIL.
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
ret = (
|
|
864
|
+
"is_enumerated_set" -> TRUE,
|
|
865
|
+
"base_type" -> base_type,
|
|
866
|
+
"value_list" -> value_list,
|
|
867
|
+
"type_hash" -> type_hash,
|
|
868
|
+
"describe" -> fn (_) = description,
|
|
869
|
+
"check_compatibility" -> CheckCompatibility,
|
|
870
|
+
"iteration" -> iteration_forbidden description,
|
|
871
|
+
"verify_reduction" -> reduction_forbidden description,
|
|
872
|
+
"safe_cast" -> SafeCast,
|
|
873
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
874
|
+
).
|
|
875
|
+
|
|
876
|
+
sets_by_hash type_hash -> ret.
|
|
877
|
+
RETURN ret.
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
module combinations {
|
|
883
|
+
Conjunction_SafeCast_ex = fn (type_from, err, index, array_of_types, description) {
|
|
884
|
+
check_cur = conversions::safe_cast basics::any (array_of_types index) err.
|
|
885
|
+
if index < (_count array_of_types) - 1 {
|
|
886
|
+
check_tail = Conjunction_SafeCast_ex type_from err (index+1) array_of_types description.
|
|
887
|
+
RETURN fn (value) {
|
|
888
|
+
WHEN provisional abort e {
|
|
889
|
+
ret = check_cur value.
|
|
890
|
+
ret -> check_tail value.
|
|
891
|
+
RETURN ret.
|
|
892
|
+
}
|
|
893
|
+
abort provisional "Safe cast for conjunction" + description + " failed: " + e WHEN e != NIL.
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
} else {
|
|
897
|
+
RETURN fn (value) = (check_cur value).
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
conjunction = fn (set_of_types)
|
|
901
|
+
{
|
|
902
|
+
type_set_description = "(".
|
|
903
|
+
allows_null_values = TRUE.
|
|
904
|
+
non_null_type_set = (,).
|
|
905
|
+
product_type_set = (,).
|
|
906
|
+
has_types = NIL.
|
|
907
|
+
|
|
908
|
+
sc set_of_types -- (elem -> ) {
|
|
909
|
+
if elem $is_conjunction {
|
|
910
|
+
set_of_types->set_of_types'(elem->delete).
|
|
911
|
+
set_of_types->set_of_types'(elem $types).
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
sc set_of_types -- (elem -> ) {
|
|
916
|
+
set_of_types->set_of_types'(elem->delete, internal::de_const elem).
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
first IS true+ = TRUE.
|
|
920
|
+
sc set_of_types -- (elem -> ) {
|
|
921
|
+
if elem == any_type {
|
|
922
|
+
continue.
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
if elem == basics::none {
|
|
926
|
+
RETURN basics::none.
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
has_types -> TRUE.
|
|
930
|
+
if nullable::allows_null_values elem {
|
|
931
|
+
non_null_type_set (nullable::remove elem) -> TRUE.
|
|
932
|
+
} else {
|
|
933
|
+
non_null_type_set elem -> TRUE.
|
|
934
|
+
allows_null_values -> NIL.
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
product_type_set -> product_type_set'(nullable::get_product_type_no_err elem,).
|
|
938
|
+
if first {
|
|
939
|
+
type_set_description -> "(" + ( elem "describe" NIL ).
|
|
940
|
+
first->NIL.
|
|
941
|
+
} else {
|
|
942
|
+
type_set_description -> type_set_description + " && " + ( elem "describe" NIL ).
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
if !has_types {
|
|
947
|
+
RETURN basics::any.
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
if (_count set_of_types) == 1 {
|
|
951
|
+
sc set_of_types -- (ret -> ) {
|
|
952
|
+
RETURN ret.
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
type_set_description -> type_set_description + ")".
|
|
957
|
+
|
|
958
|
+
description = type_set_description.
|
|
959
|
+
|
|
960
|
+
SafeCast = fn (type_from, err) {
|
|
961
|
+
array_of_types = [].
|
|
962
|
+
sc set_of_types -- (type -> ) {
|
|
963
|
+
array_of_types (_count array_of_types) -> type.
|
|
964
|
+
}
|
|
965
|
+
RETURN Conjunction_SafeCast_ex type_from err 0 array_of_types description.
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
ret = (
|
|
969
|
+
"is_conjunction" -> TRUE,
|
|
970
|
+
"is_nullable" -> allows_null_values,
|
|
971
|
+
"non_null_type" -> (allows_null_values ?? conjunction non_null_type_set ; NIL ),
|
|
972
|
+
"product" -> conjunction product_type_set,
|
|
973
|
+
"describe" -> fn (_) = description,
|
|
974
|
+
"types" -> set_of_types,
|
|
975
|
+
"check_compatibility" -> fn (actual) {
|
|
976
|
+
sc set_of_types -- (t -> ) {
|
|
977
|
+
if !(t "check_compatibility" actual) {
|
|
978
|
+
RETURN NIL.
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
RETURN TRUE.
|
|
983
|
+
},
|
|
984
|
+
"iteration" -> iteration_forbidden description,
|
|
985
|
+
"verify_reduction" -> fn (arg) {
|
|
986
|
+
result_type_set = (,).
|
|
987
|
+
message = "Invalid reduction for type " + description.
|
|
988
|
+
has_error = NIL.
|
|
989
|
+
sc set_of_types -- (t -> ) {
|
|
990
|
+
t "verify_reduction" arg => [result_type, result_error].
|
|
991
|
+
if result_error {
|
|
992
|
+
message -> message + "\n\t Invalid reduction for type " + (t "describe" NIL) + ": " + result_error.
|
|
993
|
+
has_error -> TRUE.
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
result_type_set-> result_type_set'(result_type,).
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
RETURN [ conjunction result_type_set, (has_error ?? message ; NIL) ].
|
|
1000
|
+
},
|
|
1001
|
+
"safe_cast" -> SafeCast,
|
|
1002
|
+
"reference_extention" -> reference_extention_forbidden description
|
|
1003
|
+
).
|
|
1004
|
+
|
|
1005
|
+
RETURN ret.
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
conjunction_pair = fn (left, right)
|
|
1009
|
+
{
|
|
1010
|
+
set = (,).
|
|
1011
|
+
if left "is_conjunction" {
|
|
1012
|
+
set -> left "types".
|
|
1013
|
+
} else {
|
|
1014
|
+
set -> (left,).
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
if right "is_conjunction" {
|
|
1018
|
+
set -> set'(right "types").
|
|
1019
|
+
} else {
|
|
1020
|
+
set -> set'(right,).
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
RETURN conjunction set.
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
forwards::conjunction->conjunction.
|
|
1027
|
+
|
|
1028
|
+
CheckCompatibility_ex = fn (set_of_types, actual) {
|
|
1029
|
+
if actual $is_disjunction {
|
|
1030
|
+
sc actual $types -- (one_possible_type -> ) {
|
|
1031
|
+
if !(CheckCompatibility_ex set_of_types one_possible_type) {
|
|
1032
|
+
RETURN NIL.
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
RETURN TRUE.
|
|
1036
|
+
}
|
|
1037
|
+
sc set_of_types -- (t -> ) {
|
|
1038
|
+
if (t "check_compatibility" actual) {
|
|
1039
|
+
RETURN TRUE.
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
RETURN NIL.
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
Disjunction_SafeCast_ex = fn (_type_from, err, index, array_of_types, type_dsc) {
|
|
1047
|
+
check_cur = conversions::safe_cast basics::any (array_of_types index) err.
|
|
1048
|
+
if index < (_count array_of_types) - 1 {
|
|
1049
|
+
check_tail = combinations::Disjunction_SafeCast_ex _type_from err (index+1) array_of_types type_dsc.
|
|
1050
|
+
RETURN fn (value) {
|
|
1051
|
+
WHEN provisional abort _e {
|
|
1052
|
+
RETURN (check_cur value).
|
|
1053
|
+
}
|
|
1054
|
+
// current type is invalid, check remaining types
|
|
1055
|
+
WHEN provisional abort e {
|
|
1056
|
+
RETURN (check_tail value).
|
|
1057
|
+
}
|
|
1058
|
+
abort provisional "Runtime mismatch for disjunction SAFE cast: Expected " + type_dsc WHEN e != NIL.
|
|
1059
|
+
}
|
|
1060
|
+
} else {
|
|
1061
|
+
RETURN fn (value) = (check_cur value).
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
disjunction = fn (set_of_types)
|
|
1065
|
+
{
|
|
1066
|
+
type_set_description = "(".
|
|
1067
|
+
allows_null_values = NIL.
|
|
1068
|
+
non_null_type_set = (,).
|
|
1069
|
+
product_type_set = (,).
|
|
1070
|
+
has_types = NIL.
|
|
1071
|
+
|
|
1072
|
+
sc set_of_types -- (elem -> ) {
|
|
1073
|
+
if elem $is_disjunction {
|
|
1074
|
+
set_of_types->set_of_types'(elem->delete).
|
|
1075
|
+
set_of_types->set_of_types'(elem $types).
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// strings and string-enumerated types get all folded into one.
|
|
1080
|
+
string_consumer = enumerated_sets::type basics::string (,).
|
|
1081
|
+
sc set_of_types -- (elem -> ) {
|
|
1082
|
+
if elem == basics::string {
|
|
1083
|
+
string_consumer -> basics::string.
|
|
1084
|
+
set_of_types->set_of_types'(elem->delete).
|
|
1085
|
+
} elif elem "is_const" && elem "base_type_of_const" == basics::string {
|
|
1086
|
+
set_of_types->set_of_types'(elem->delete).
|
|
1087
|
+
if string_consumer != basics::string {
|
|
1088
|
+
string_consumer -> enumerated_sets::type basics::string (string_consumer "value_list")'(elem "const_value",).
|
|
1089
|
+
}
|
|
1090
|
+
} elif elem "is_enumerated_set" && elem "base_type" == basics::string {
|
|
1091
|
+
set_of_types->set_of_types'(elem->delete).
|
|
1092
|
+
if string_consumer != basics::string {
|
|
1093
|
+
string_consumer -> enumerated_sets::type basics::string (string_consumer "value_list")'(elem "value_list").
|
|
1094
|
+
}
|
|
1095
|
+
} else {
|
|
1096
|
+
set_of_types->set_of_types'(elem->delete, internal::de_const elem).
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
if string_consumer == basics::string || string_consumer "value_list" != (,) {
|
|
1101
|
+
set_of_types->set_of_types'(string_consumer,).
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// TODO: outer scope protect feature for IFs and SCANs
|
|
1105
|
+
// ensuring it's not possible to create a new name that shadows
|
|
1106
|
+
// an outer name in this context.
|
|
1107
|
+
descriptions = (,).
|
|
1108
|
+
sc set_of_types -- (elem -> ) {
|
|
1109
|
+
if elem == any_type {
|
|
1110
|
+
RETURN any_type.
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
if elem == basics::none {
|
|
1114
|
+
continue.
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
has_types -> TRUE.
|
|
1118
|
+
if nullable::allows_null_values elem {
|
|
1119
|
+
allows_null_values -> TRUE.
|
|
1120
|
+
if elem != basics::nil {
|
|
1121
|
+
non_null_type_set (nullable::remove elem) -> TRUE.
|
|
1122
|
+
}
|
|
1123
|
+
} else {
|
|
1124
|
+
non_null_type_set elem -> TRUE.
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
this_product = nullable::get_product_type_no_err elem.
|
|
1128
|
+
|
|
1129
|
+
product_type_set -> product_type_set'(this_product,).
|
|
1130
|
+
descriptions (elem "describe" NIL) -> TRUE.
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
first IS true+ = TRUE.
|
|
1134
|
+
sc descriptions -- (one_description -> ) {
|
|
1135
|
+
if first {
|
|
1136
|
+
type_set_description -> "(" + one_description.
|
|
1137
|
+
first->NIL.
|
|
1138
|
+
} else {
|
|
1139
|
+
type_set_description -> type_set_description + " || " + one_description.
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
if !has_types {
|
|
1144
|
+
RETURN basics::none.
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (_count set_of_types) == 1 {
|
|
1148
|
+
sc set_of_types -- (ret -> ) {
|
|
1149
|
+
RETURN ret.
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
type_set_description -> type_set_description + ")".
|
|
1154
|
+
|
|
1155
|
+
description = type_set_description.
|
|
1156
|
+
|
|
1157
|
+
SafeCast = fn (_type_from, _err) {
|
|
1158
|
+
array_of_types IS any[] = [].
|
|
1159
|
+
sc set_of_types -- (t -> ) { array_of_types (_count array_of_types) -> t. }
|
|
1160
|
+
RETURN Disjunction_SafeCast_ex _type_from _err 0 array_of_types description.
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
ret = (
|
|
1164
|
+
"is_disjunction" -> TRUE,
|
|
1165
|
+
"is_nullable" -> allows_null_values,
|
|
1166
|
+
"non_null_type" -> (allows_null_values ?? disjunction non_null_type_set ; NIL ),
|
|
1167
|
+
"describe" -> fn (_) = description,
|
|
1168
|
+
"types" -> set_of_types,
|
|
1169
|
+
"check_compatibility" -> CheckCompatibility_ex set_of_types,
|
|
1170
|
+
"product" -> disjunction product_type_set,
|
|
1171
|
+
"iteration" -> iteration_forbidden description,
|
|
1172
|
+
"verify_reduction" -> fn (arg) {
|
|
1173
|
+
result_type_set = (,).
|
|
1174
|
+
message = "Invalid reduction for type " + description.
|
|
1175
|
+
has_error = NIL.
|
|
1176
|
+
sc set_of_types -- (t -> ) {
|
|
1177
|
+
t "verify_reduction" arg => [result_type, result_error].
|
|
1178
|
+
if result_error {
|
|
1179
|
+
message -> message + "\n\t Invalid reduction for type " + (t "describe" NIL) + ": " + result_error.
|
|
1180
|
+
has_error -> TRUE.
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
result_type_set-> result_type_set'(result_type,).
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
RETURN [ disjunction result_type_set, (has_error ?? message ; NIL) ].
|
|
1187
|
+
},
|
|
1188
|
+
"safe_cast" -> SafeCast,
|
|
1189
|
+
"reference_extention" -> reference_extention_forbidden description
|
|
1190
|
+
).
|
|
1191
|
+
|
|
1192
|
+
RETURN ret.
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
forwards::disjunction->disjunction.
|
|
1196
|
+
|
|
1197
|
+
disjunction_pair = fn (left, right)
|
|
1198
|
+
{
|
|
1199
|
+
set = (,).
|
|
1200
|
+
if left "is_disjunction" {
|
|
1201
|
+
set -> left "types".
|
|
1202
|
+
} else {
|
|
1203
|
+
set -> (left,).
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
if right "is_disjunction" {
|
|
1207
|
+
set -> set'(right "types").
|
|
1208
|
+
} else {
|
|
1209
|
+
set -> set'(right,).
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
ret = disjunction set.
|
|
1213
|
+
RETURN ret.
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
module immutable {
|
|
1218
|
+
type = fn (rtype, ptype) {
|
|
1219
|
+
description = "(" + (rtype "describe" NIL) + "->>" + (ptype "describe" NIL) + ")".
|
|
1220
|
+
|
|
1221
|
+
Combinator = fn (err, _this, type_r)
|
|
1222
|
+
{
|
|
1223
|
+
if type_r "is_immutable" {
|
|
1224
|
+
RETURN immutable::type (forwards::disjunction (rtype, type_r $rtype)) (forwards::disjunction (ptype, type_r $ptype)).
|
|
1225
|
+
} elif type_r "is_tuple" {
|
|
1226
|
+
RETURN immutable::type (forwards::disjunction (rtype, basics::integer)) (forwards::disjunction (type_r $type_set)'(ptype,)).
|
|
1227
|
+
} elif type_r "is_record" {
|
|
1228
|
+
RETURN immutable::type (forwards::disjunction (rtype, basics::string)) (forwards::disjunction (type_r $type_set)'(ptype,)).
|
|
1229
|
+
} else {
|
|
1230
|
+
message = "Type " + (type_r "describe" NIL) + " can not be used on the right side of the combinator".
|
|
1231
|
+
signal_error message err.
|
|
1232
|
+
RETURN basics::any.
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
RETURN (
|
|
1237
|
+
"is_immutable" -> TRUE,
|
|
1238
|
+
"is_iterable" -> TRUE,
|
|
1239
|
+
"describe" -> fn (_) = description,
|
|
1240
|
+
"rtype" -> rtype,
|
|
1241
|
+
"ptype" -> ptype,
|
|
1242
|
+
"combinator" -> Combinator,
|
|
1243
|
+
"check_compatibility" -> fn (actual) {
|
|
1244
|
+
if actual "is_immutable" {
|
|
1245
|
+
RETURN (rtype "check_compatibility" (actual "rtype")) &&
|
|
1246
|
+
(ptype "check_compatibility" (actual "ptype")).
|
|
1247
|
+
} elif actual "is_record" {
|
|
1248
|
+
if _count (actual $field_list) == 0 {
|
|
1249
|
+
RETURN TRUE.
|
|
1250
|
+
} elif !(rtype "check_compatibility" meta::basics::string) {
|
|
1251
|
+
RETURN NIL.
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
sc actual "field_list" -- (_ -> tp) {
|
|
1255
|
+
if !(ptype "check_compatibility" tp) {
|
|
1256
|
+
RETURN NIL.
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
RETURN TRUE.
|
|
1261
|
+
} elif actual "is_tuple" {
|
|
1262
|
+
if _count (actual $type_list) == 0 {
|
|
1263
|
+
RETURN TRUE.
|
|
1264
|
+
} elif !(rtype "check_compatibility" basics::integer) { RETURN NIL. }
|
|
1265
|
+
|
|
1266
|
+
sc actual $type_list -- (_ -> tp) {
|
|
1267
|
+
if !(ptype "check_compatibility" tp ) {
|
|
1268
|
+
RETURN NIL.
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
RETURN TRUE.
|
|
1272
|
+
} else {
|
|
1273
|
+
RETURN NIL.
|
|
1274
|
+
}
|
|
1275
|
+
},
|
|
1276
|
+
"iteration" -> fn (_err) = ("rtype"->rtype, "ptype"->ptype),
|
|
1277
|
+
"verify_reduction" -> fn (param)
|
|
1278
|
+
{
|
|
1279
|
+
if !(rtype "check_compatibility" param) {
|
|
1280
|
+
message = "In a reduction: invalid reducer type. Required " + (rtype "describe" NIL) + " but observing " + (param "describe" NIL).
|
|
1281
|
+
RETURN [any_type, message].
|
|
1282
|
+
} else {
|
|
1283
|
+
RETURN [(meta::nullable::type ptype), NIL].
|
|
1284
|
+
}
|
|
1285
|
+
},
|
|
1286
|
+
"safe_cast" -> fn (_type_from, err)
|
|
1287
|
+
{
|
|
1288
|
+
reducer_cast = conversions::safe_cast basics::any rtype err.
|
|
1289
|
+
product_cast = conversions::safe_cast basics::any ptype err.
|
|
1290
|
+
RETURN fn (value)
|
|
1291
|
+
{
|
|
1292
|
+
abort provisional "Safe cast failed, required dictionary value" WHEN _typeof value != "IMMUTABLE_DICTIONARY".
|
|
1293
|
+
|
|
1294
|
+
sc value -- (i -> v) {
|
|
1295
|
+
reducer_cast i.
|
|
1296
|
+
product_cast v.
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
RETURN value.
|
|
1300
|
+
}
|
|
1301
|
+
},
|
|
1302
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
1303
|
+
).
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
array = fn (result_type) = (type basics::integer result_type).
|
|
1308
|
+
set = fn (elem_type) = (type elem_type (nullable::type basics::true)).
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
module tuple {
|
|
1313
|
+
hidden {
|
|
1314
|
+
SafeCast_ex = fn (_type_from, err, index, rlist)
|
|
1315
|
+
{
|
|
1316
|
+
check_at_index = conversions::safe_cast basics::any (rlist index) err.
|
|
1317
|
+
if index < (_count rlist) - 1 {
|
|
1318
|
+
check_tail = tuple::SafeCast_ex basics::any err (index + 1) rlist.
|
|
1319
|
+
RETURN fn (value)
|
|
1320
|
+
{
|
|
1321
|
+
ret = check_tail value.
|
|
1322
|
+
ret index -> check_at_index (value index).
|
|
1323
|
+
RETURN ret.
|
|
1324
|
+
}
|
|
1325
|
+
} else {
|
|
1326
|
+
RETURN fn (value)
|
|
1327
|
+
{
|
|
1328
|
+
if _typeof value != "DICTIONARY" && _typeof value != "IMMUTABLE_DICTIONARY" {
|
|
1329
|
+
_abort_transaction_provisional "SAFE cast to tuple failed: value is not a dictionary".
|
|
1330
|
+
} else {
|
|
1331
|
+
ret = (,).
|
|
1332
|
+
ret index -> check_at_index (value index).
|
|
1333
|
+
RETURN ret.
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
type = fn (tlist) {
|
|
1341
|
+
rlist = (,).
|
|
1342
|
+
type_set = (,).
|
|
1343
|
+
valid_subscript_set = (,).
|
|
1344
|
+
sc tlist -- (index -> t) {
|
|
1345
|
+
valid_subscript_set index->TRUE.
|
|
1346
|
+
rlist->rlist'(index -> internal::de_const t,).
|
|
1347
|
+
type_set->type_set'(internal::de_const t,).
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
Describe = fn (_)
|
|
1351
|
+
{
|
|
1352
|
+
Ret = "[".
|
|
1353
|
+
counter = 0.
|
|
1354
|
+
sc rlist -- (index -> rtype) {
|
|
1355
|
+
if (counter > 0) {
|
|
1356
|
+
Ret -> Ret + ",".
|
|
1357
|
+
}
|
|
1358
|
+
counter -> counter + 1.
|
|
1359
|
+
Ret -> Ret + (_str index) + "->" + (rtype "describe" NIL).
|
|
1360
|
+
}
|
|
1361
|
+
Ret -> Ret + "]".
|
|
1362
|
+
RETURN Ret.
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
description = Describe().
|
|
1366
|
+
tuple_size = _count rlist.
|
|
1367
|
+
|
|
1368
|
+
CheckCompatibility = fn (actual) {
|
|
1369
|
+
if !( actual "is_tuple" ) { RETURN NIL. }
|
|
1370
|
+
sc rlist -- (index -> expected_rtype) {
|
|
1371
|
+
actual_type = actual $type_list index.
|
|
1372
|
+
if actual_type == NIL { actual_type->basics::nil. }
|
|
1373
|
+
if !(expected_rtype "check_compatibility" actual_type) {
|
|
1374
|
+
RETURN NIL.
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
RETURN TRUE.
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
Combinator = fn (err, this, type_r)
|
|
1382
|
+
{
|
|
1383
|
+
if _count tlist == 0 {
|
|
1384
|
+
RETURN type_r.
|
|
1385
|
+
} elif type_r "is_immutable" {
|
|
1386
|
+
RETURN immutable::type (forwards::disjunction (type_r $rtype, basics::integer)) (forwards::disjunction (type_r $ptype,)'type_set).
|
|
1387
|
+
} elif type_r "is_tuple" {
|
|
1388
|
+
RETURN tuple::type rlist'(type_r $type_list).
|
|
1389
|
+
} elif type_r "is_record" {
|
|
1390
|
+
if _count (type_r "field_list") == 0 {
|
|
1391
|
+
RETURN this.
|
|
1392
|
+
} else {
|
|
1393
|
+
RETURN immutable::type (forwards::disjunction (basics::integer, basics::string)) (forwards::disjunction (type_r $type_set)'type_set).
|
|
1394
|
+
}
|
|
1395
|
+
} else {
|
|
1396
|
+
message = "Type " + (type_r "describe" NIL) + " can not be used on the right side of the combinator".
|
|
1397
|
+
signal_error message err.
|
|
1398
|
+
RETURN basics::any.
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
VerifyReduction = fn (reducer)
|
|
1403
|
+
{
|
|
1404
|
+
message = NIL.
|
|
1405
|
+
if !(compatibility::check meta::basics::integer reducer) {
|
|
1406
|
+
message -> "In a reduction: invalid reducer type for tuple, integer required but observing " + (reducer "describe" NIL).
|
|
1407
|
+
} elif !(reducer "is_const") {
|
|
1408
|
+
message -> "In a reduction: tuple subscript must be constant".
|
|
1409
|
+
} elif !(valid_subscript_set (reducer "const_value")) || (reducer "const_value" < 0) {
|
|
1410
|
+
message -> "In a reduction: tuple subscript out of bounds".
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
if message {
|
|
1414
|
+
RETURN [any_type, message].
|
|
1415
|
+
} else {
|
|
1416
|
+
RETURN [rlist (reducer "const_value"), NIL].
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
SafeCast = fn (type_from, err)
|
|
1421
|
+
{
|
|
1422
|
+
RETURN tuple::SafeCast_ex type_from err 0 rlist.
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
DeleteElement = fn (err, index_type) {
|
|
1426
|
+
if index_type "base_type_of_const" != basics::integer {
|
|
1427
|
+
message = "Invalid deletion of a tuple element: index must be constant. To force this operation cast to an array."
|
|
1428
|
+
signal_error message err.
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
index = index_type "const_value".
|
|
1432
|
+
new_field_list = rlist'(index->delete).
|
|
1433
|
+
RETURN tuple::type new_field_list.
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
ret_val = (
|
|
1437
|
+
"is_tuple" -> TRUE,
|
|
1438
|
+
"is_iterable" -> TRUE,
|
|
1439
|
+
"rtype" -> basics::integer,
|
|
1440
|
+
"ptype" -> forwards::disjunction type_set,
|
|
1441
|
+
"type_list" -> rlist,
|
|
1442
|
+
"type_set" -> type_set,
|
|
1443
|
+
"tuple_size" -> tuple_size,
|
|
1444
|
+
"describe"-> fn (_) = description,
|
|
1445
|
+
"check_compatibility" -> CheckCompatibility,
|
|
1446
|
+
"combinator" -> Combinator,
|
|
1447
|
+
"delete" -> DeleteElement,
|
|
1448
|
+
"iteration" -> fn (_err) = ( "rtype"->basics::integer, "ptype"->forwards::disjunction type_set ),
|
|
1449
|
+
"verify_reduction" -> VerifyReduction,
|
|
1450
|
+
"safe_cast" -> SafeCast,
|
|
1451
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
1452
|
+
).
|
|
1453
|
+
|
|
1454
|
+
RETURN ret_val.
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
empty = type [].
|
|
1458
|
+
member_type = fn (t, i, err)
|
|
1459
|
+
{
|
|
1460
|
+
if !(t "is_tuple") {
|
|
1461
|
+
signal_error "Type is not a tuple" err.
|
|
1462
|
+
RETURN ::meta::basics::any.
|
|
1463
|
+
} elif !(t "type_list" i) {
|
|
1464
|
+
signal_error << "Tuple) not have element " + (_str i) << err.
|
|
1465
|
+
RETURN ::meta::basics::any.
|
|
1466
|
+
} else {
|
|
1467
|
+
RETURN t "type_list" i.
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
module reference {
|
|
1473
|
+
type = fn (base_type) {
|
|
1474
|
+
Describe = fn (_)
|
|
1475
|
+
{
|
|
1476
|
+
RETURN "&" + (base_type "describe" NIL).
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
description = Describe().
|
|
1480
|
+
|
|
1481
|
+
CheckCompatibility = fn (actual) {
|
|
1482
|
+
if !(actual "is_reference" ) {
|
|
1483
|
+
RETURN NIL.
|
|
1484
|
+
} else {
|
|
1485
|
+
RETURN compatibility::check base_type (actual "base_type").
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
ret = (
|
|
1490
|
+
"is_reference" -> TRUE,
|
|
1491
|
+
"base_type" -> base_type,
|
|
1492
|
+
"describe" -> fn (_) = description,
|
|
1493
|
+
"check_compatibility" -> CheckCompatibility,
|
|
1494
|
+
"iteration" -> iteration_forbidden description,
|
|
1495
|
+
"verify_reduction" -> reduction_forbidden description,
|
|
1496
|
+
"safe_cast" -> no_safe_cast description,
|
|
1497
|
+
"reference_extention" -> fn (reducer)
|
|
1498
|
+
{
|
|
1499
|
+
BIND [result_type, result_error] TO base_type "verify_reduction" reducer.
|
|
1500
|
+
RETURN [ reference::type result_type, result_error ].
|
|
1501
|
+
},
|
|
1502
|
+
).
|
|
1503
|
+
|
|
1504
|
+
RETURN ret.
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
dereference = fn (type, err) {
|
|
1508
|
+
if !(type "is_reference") {
|
|
1509
|
+
message = "Reference was expected but found " + (type "describe" NIL).
|
|
1510
|
+
signal_error message err.
|
|
1511
|
+
RETURN basics::any.
|
|
1512
|
+
} else {
|
|
1513
|
+
RETURN type "base_type".
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
remove_null = fn (t) {
|
|
1518
|
+
if t $is_reference {
|
|
1519
|
+
RETURN reference::type (meta::nullable::remove (t $base_type)).
|
|
1520
|
+
} else {
|
|
1521
|
+
RETURN meta::nullable::remove t.
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
module record {
|
|
1527
|
+
hidden {
|
|
1528
|
+
SafeCast_ex = fn (_type_from, err, index, fnames_array, flist)
|
|
1529
|
+
{
|
|
1530
|
+
field_name = fnames_array index.
|
|
1531
|
+
count_fields = _count fnames_array.
|
|
1532
|
+
field_type = flist field_name.
|
|
1533
|
+
field_count = _count fnames_array.
|
|
1534
|
+
check_field = conversions::safe_cast basics::any field_type err.
|
|
1535
|
+
|
|
1536
|
+
if index < field_count - 1 {
|
|
1537
|
+
check_tail = SafeCast_ex basics::any err (index + 1) fnames_array flist.
|
|
1538
|
+
RETURN fn (value)
|
|
1539
|
+
{
|
|
1540
|
+
ret = check_tail value.
|
|
1541
|
+
ret field_name -> check_field (value field_name).
|
|
1542
|
+
RETURN ret.
|
|
1543
|
+
}
|
|
1544
|
+
} else {
|
|
1545
|
+
RETURN fn (value)
|
|
1546
|
+
{
|
|
1547
|
+
// TODO: Find and eliminate "DICTIONARY"
|
|
1548
|
+
if _typeof value != "DICTIONARY" && _typeof value != "IMMUTABLE_DICTIONARY" {
|
|
1549
|
+
_abort_transaction_provisional "SAFE cast to record failed: value is not a dictionary".
|
|
1550
|
+
} else {
|
|
1551
|
+
ret = (,).
|
|
1552
|
+
ret field_name -> check_field (value field_name).
|
|
1553
|
+
RETURN ret.
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
type = fn (flist) { // name->type
|
|
1561
|
+
// construct an enumerated set of field names
|
|
1562
|
+
field_names = (,).
|
|
1563
|
+
product_type_set = (,).
|
|
1564
|
+
index = 0.
|
|
1565
|
+
fnames_array = [].
|
|
1566
|
+
sc flist -- (name -> ptype) {
|
|
1567
|
+
fnames_array index -> name.
|
|
1568
|
+
index -> index + 1.
|
|
1569
|
+
field_names name->TRUE.
|
|
1570
|
+
product_type_set->product_type_set'(ptype,).
|
|
1571
|
+
flist name->/*internal::de_const*/ ptype.
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
subscript_type = enumerated_sets::type basics::string field_names.
|
|
1575
|
+
|
|
1576
|
+
Describe = fn (_)
|
|
1577
|
+
{
|
|
1578
|
+
Ret = "(/*empty_record*/,".
|
|
1579
|
+
is_not_first = NIL.
|
|
1580
|
+
sc flist -- (name -> rtype) {
|
|
1581
|
+
if is_not_first {
|
|
1582
|
+
Ret -> Ret + ",".
|
|
1583
|
+
} else {
|
|
1584
|
+
Ret->"(".
|
|
1585
|
+
is_not_first->TRUE.
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
Ret -> Ret + "\"" + name + "\"->" + (rtype "describe" NIL).
|
|
1589
|
+
}
|
|
1590
|
+
Ret -> Ret + ")".
|
|
1591
|
+
RETURN Ret.
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
description = Describe().
|
|
1595
|
+
|
|
1596
|
+
CheckCompatibility = fn (actual) {
|
|
1597
|
+
if !(actual "is_record") { RETURN NIL. }
|
|
1598
|
+
|
|
1599
|
+
sc flist -- (name -> rtype) {
|
|
1600
|
+
actual_field = actual "field_list" name.
|
|
1601
|
+
if( actual_field == NIL ) {
|
|
1602
|
+
actual_field->basics::nil.
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
if actual "field_list" name == NIL && !(nullable::allows_null_values rtype) {
|
|
1606
|
+
RETURN NIL.
|
|
1607
|
+
} elif !(rtype "check_compatibility" actual_field) {
|
|
1608
|
+
RETURN NIL.
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
RETURN TRUE.
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
Combinator = fn (err, this, type_r)
|
|
1615
|
+
{
|
|
1616
|
+
if _count flist == 0 {
|
|
1617
|
+
RETURN type_r.
|
|
1618
|
+
} elif type_r "is_immutable" {
|
|
1619
|
+
RETURN immutable::type (forwards::disjunction (type_r $rtype, basics::string)) (forwards::disjunction (type_r $ptype,)'product_type_set).
|
|
1620
|
+
} elif type_r "is_tuple" {
|
|
1621
|
+
if _count (type_r $type_list) == 0 {
|
|
1622
|
+
RETURN this.
|
|
1623
|
+
} else {
|
|
1624
|
+
RETURN immutable::type (forwards::disjunction (basics::integer, basics::string)) (forwards::disjunction (type_r $type_set)'product_type_set).
|
|
1625
|
+
}
|
|
1626
|
+
} elif type_r "is_record" {
|
|
1627
|
+
RETURN record::type flist'(type_r $field_list).
|
|
1628
|
+
} else {
|
|
1629
|
+
message = "Type " + (type_r "describe" NIL) + " can not be used on the right side of the combinator".
|
|
1630
|
+
signal_error message err.
|
|
1631
|
+
RETURN basics::any.
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
VerifyReduction = fn (reducer)
|
|
1636
|
+
{
|
|
1637
|
+
if !(compatibility::check subscript_type reducer) {
|
|
1638
|
+
message = "In a reduction: invalid reducer type for record, field name required but observing " + (reducer "describe" NIL).
|
|
1639
|
+
RETURN [ basics::any, message ].
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
RETURN [flist (reducer "const_value"), NIL].
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
DeleteElement = fn (err, index_type) {
|
|
1646
|
+
if index_type "base_type_of_const" != basics::string {
|
|
1647
|
+
message = "Invalid deletion of a record element: index must be constant. To force this operation cast to a dictionary."
|
|
1648
|
+
signal_error message err.
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
index = index_type "const_value".
|
|
1652
|
+
new_field_list = flist'(index->delete).
|
|
1653
|
+
RETURN record::type new_field_list.
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
SafeCast = fn (type_from, err)
|
|
1657
|
+
{
|
|
1658
|
+
RETURN SafeCast_ex type_from err 0 fnames_array flist.
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
res = (
|
|
1662
|
+
"is_record" -> TRUE,
|
|
1663
|
+
"is_iterable" -> TRUE,
|
|
1664
|
+
"field_list" -> flist,
|
|
1665
|
+
"rtype" -> subscript_type,
|
|
1666
|
+
"ptype" -> basics::any, // forwards::disjunction product_type_set,
|
|
1667
|
+
"type_set" -> product_type_set,
|
|
1668
|
+
"describe" -> fn (_) = description,
|
|
1669
|
+
"check_compatibility" -> CheckCompatibility,
|
|
1670
|
+
"combinator" -> Combinator,
|
|
1671
|
+
"delete" -> DeleteElement,
|
|
1672
|
+
"iteration" -> fn (_err) = ( "rtype"->basics::string, "ptype"->forwards::disjunction product_type_set ),
|
|
1673
|
+
"verify_reduction" -> VerifyReduction,
|
|
1674
|
+
"safe_cast" -> SafeCast,
|
|
1675
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
1676
|
+
).
|
|
1677
|
+
|
|
1678
|
+
RETURN res.
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
empty = type (,).
|
|
1682
|
+
field_type = fn (t, f, err)
|
|
1683
|
+
{
|
|
1684
|
+
if !(t "is_record") {
|
|
1685
|
+
signal_error "Type is not a record" err.
|
|
1686
|
+
RETURN ::meta::basics::any.
|
|
1687
|
+
} elif !(t "field_list" f) {
|
|
1688
|
+
signal_error << "Record) not have element " + f << err.
|
|
1689
|
+
RETURN ::meta::basics::any.
|
|
1690
|
+
} else {
|
|
1691
|
+
RETURN t "field_list" f.
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
module ops
|
|
1697
|
+
{
|
|
1698
|
+
config_result = meta::nullable::type
|
|
1699
|
+
(record::type
|
|
1700
|
+
(
|
|
1701
|
+
$imports->record::type (
|
|
1702
|
+
$libraries->immutable::type basics::string basics::string,
|
|
1703
|
+
$applications->immutable::type basics::string basics::string
|
|
1704
|
+
),
|
|
1705
|
+
$exports->record::type (
|
|
1706
|
+
$libraries->immutable::type basics::string basics::string,
|
|
1707
|
+
$applications->immutable::type basics::string basics::string
|
|
1708
|
+
),
|
|
1709
|
+
)
|
|
1710
|
+
).
|
|
1711
|
+
|
|
1712
|
+
implied_declared_type = fn (t) {
|
|
1713
|
+
if t == basics::true || t == basics::false {
|
|
1714
|
+
return basics::boolean.
|
|
1715
|
+
} else {
|
|
1716
|
+
return t.
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
describe = fn (t) {
|
|
1721
|
+
RETURN t "describe" NIL.
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
arith = fn (err, op, type_l, type_r) {
|
|
1725
|
+
if op != "+" {
|
|
1726
|
+
if type_l "domain" != domain::integer || type_r "domain" != domain::integer {
|
|
1727
|
+
message = "Arithmetic operation '" + op + "' requires integer operands, but observing " +
|
|
1728
|
+
(type_l "describe" NIL) + " and " + (type_r "describe" NIL) + " instead.".
|
|
1729
|
+
|
|
1730
|
+
meta::signal_error message err.
|
|
1731
|
+
RETURN basics::any.
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
|
|
1735
|
+
if type_l "is_const" && type_r "is_const" {
|
|
1736
|
+
RETURN (basics::constant basics::integer ((type_l "const_value") + (type_r "const_value"))). // TODO: This is a bug
|
|
1737
|
+
} else {
|
|
1738
|
+
RETURN basics::integer.
|
|
1739
|
+
}
|
|
1740
|
+
} elif type_l "domain" == type_r "domain" // op == "+"
|
|
1741
|
+
&& ( type_l "domain" == domain::integer || type_l "domain" == domain::string || type_l "domain" == domain::binary || type_l "domain" == domain::utf8 )
|
|
1742
|
+
{
|
|
1743
|
+
if type_l "is_const" && type_r "is_const" {
|
|
1744
|
+
RETURN (basics::constant type_l ((type_l "const_value") + (type_r "const_value"))).
|
|
1745
|
+
} elif( type_l "domain" == domain::integer ) {
|
|
1746
|
+
RETURN basics::integer.
|
|
1747
|
+
} elif( type_l "domain" == domain::binary ) {
|
|
1748
|
+
RETURN basics::binary.
|
|
1749
|
+
} elif( type_l "domain" == domain::utf8 ) {
|
|
1750
|
+
RETURN basics::utf8.
|
|
1751
|
+
} else {
|
|
1752
|
+
RETURN basics::string.
|
|
1753
|
+
}
|
|
1754
|
+
} else {
|
|
1755
|
+
message = "Plus requires arguments to either both be integer, string, binary or UTF-8, but observing " +
|
|
1756
|
+
(type_l "describe" NIL) + " and " + (type_r "describe" NIL) + " instead.".
|
|
1757
|
+
signal_error message err.
|
|
1758
|
+
RETURN basics::any.
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
eq = fn (_err, _type_l, _type_r) {
|
|
1763
|
+
RETURN basics::boolean.
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
negate = fn (_err, _arg) {
|
|
1767
|
+
RETURN basics::boolean.
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
unary_minus = fn (err, arg) {
|
|
1771
|
+
if (arg "domain" != domain::integer ) {
|
|
1772
|
+
signal_error ("Unary minus requires integer argument, got " + (arg "describe" NIL) + " instead") err.
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
RETURN basics::integer.
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
predicate = fn (_err, _op, _type_l, _type_r) {
|
|
1779
|
+
RETURN basics::boolean.
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
comparison = fn (_err, _op, _type_l, _type_r) {
|
|
1783
|
+
RETURN basics::boolean. // TODO
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
combinator = fn (err, type_l, type_r) {
|
|
1787
|
+
if !(type_l "combinator") {
|
|
1788
|
+
message = "Type) not support combinator: " + (type_r "describe" NIL).
|
|
1789
|
+
meta::signal_error message err.
|
|
1790
|
+
RETURN meta::basics::any.
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
RETURN type_l "combinator" err type_l type_r.
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
immutable_deletion = fn (producer, type_l, err) {
|
|
1797
|
+
if producer "is_immutable" {
|
|
1798
|
+
BIND [ _, result_error ] TO producer "verify_reduction" type_l.
|
|
1799
|
+
if result_error {
|
|
1800
|
+
signal_error result_error err.
|
|
1801
|
+
}
|
|
1802
|
+
RETURN producer.
|
|
1803
|
+
} elif producer "is_record" || producer "is_tuple" {
|
|
1804
|
+
RETURN producer "delete" err type_l.
|
|
1805
|
+
} else {
|
|
1806
|
+
signal_error ("Unable to delete elements for type " + (producer "describe" NIL)) err.
|
|
1807
|
+
RETURN basics::any.
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
verify_reduction = fn (ptype, rtype, err)
|
|
1812
|
+
{
|
|
1813
|
+
BIND [result_type, result_error] TO ptype "verify_reduction" rtype.
|
|
1814
|
+
if result_error != NIL {
|
|
1815
|
+
signal_error result_error err.
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
RETURN result_type.
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
// PTYPE DEFAULT(default) RTYPE
|
|
1822
|
+
verify_reduction_with_default = fn (ptype, rtype, def, err)
|
|
1823
|
+
{
|
|
1824
|
+
BIND [result_type, result_error] TO ptype "verify_reduction" rtype.
|
|
1825
|
+
if result_error != NIL {
|
|
1826
|
+
signal_error result_error err.
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
meta::compatibility::check_or_error err ptype def.
|
|
1830
|
+
RETURN result_type.
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
verify_reference_extention = fn (ptype, rtype, err)
|
|
1834
|
+
{
|
|
1835
|
+
BIND [ result_type, result_error ] TO ptype "reference_extention" rtype.
|
|
1836
|
+
if result_error != NIL {
|
|
1837
|
+
signal_error result_error err.
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
RETURN result_type.
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
// PTYPE-ref DEFAULT(default) RTYPE
|
|
1844
|
+
verify_reference_extention_with_default = fn (ptype, rtype, def, err)
|
|
1845
|
+
{
|
|
1846
|
+
BIND [ result_type, result_error ] TO ptype "reference_extention" rtype.
|
|
1847
|
+
if result_error != NIL {
|
|
1848
|
+
signal_error result_error err.
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
meta::compatibility::check_or_error err (meta::reference::dereference ptype err) def.
|
|
1852
|
+
RETURN result_type.
|
|
1853
|
+
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
retrieve_reducer_type = fn (f)
|
|
1857
|
+
{
|
|
1858
|
+
if f "iterable" || f "is_record" || f "is_tuple" || f "is_immutable" || f "is_function" {
|
|
1859
|
+
RETURN f "rtype".
|
|
1860
|
+
} elif f "domain" == domain::string || f "domain" == domain::binary || f "domain" == domain::utf8 {
|
|
1861
|
+
RETURN f "rtype".
|
|
1862
|
+
} elif f "is_any_type" {
|
|
1863
|
+
RETURN meta::basics::any.
|
|
1864
|
+
} else {
|
|
1865
|
+
RETURN NIL.
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
retrieve_product_type = fn (f)
|
|
1870
|
+
{
|
|
1871
|
+
if f "iterable" || f "is_immutable" || f "is_function" || f "is_record" || f "is_tuple" {
|
|
1872
|
+
RETURN f "ptype".
|
|
1873
|
+
} elif f "domain" == domain::binary {
|
|
1874
|
+
RETURN f "ptype".
|
|
1875
|
+
} elif f "domain" == domain::string {
|
|
1876
|
+
RETURN basics::string.
|
|
1877
|
+
} elif f "domain" == domain::utf8 {
|
|
1878
|
+
RETURN basics::utf8.
|
|
1879
|
+
} elif f "is_any_type" {
|
|
1880
|
+
RETURN meta::basics::any.
|
|
1881
|
+
} else {
|
|
1882
|
+
RETURN NIL.
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
slice = fn (value_type, slice_type, _is_soft, err)
|
|
1887
|
+
{
|
|
1888
|
+
BIND ( "rtype"->slice_type_reducer, "ptype"->slice_type_product ) TO slice_type "iteration" err.
|
|
1889
|
+
|
|
1890
|
+
value_type_reducer = retrieve_reducer_type value_type.
|
|
1891
|
+
value_type_product = retrieve_product_type value_type.
|
|
1892
|
+
|
|
1893
|
+
if value_type "is_record" {
|
|
1894
|
+
value_type_reducer->basics::string.
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
if value_type_reducer == NIL || value_type_product == NIL {
|
|
1898
|
+
message = "Value being sliced is not reduceable".
|
|
1899
|
+
signal_error message err.
|
|
1900
|
+
RETURN basics::any.
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
if !( compatibility::check value_type_reducer slice_type_product ) {
|
|
1904
|
+
message = "Slice parameter not compatible: has product type " + (slice_type_product "describe" NIL) + " but expecting " + (value_type_reducer "describe" NIL).
|
|
1905
|
+
signal_error message err.
|
|
1906
|
+
RETURN meta::basics::any.
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
if value_type "domain" == domain::string {
|
|
1910
|
+
if !(compatibility::check basics::integer slice_type_reducer) {
|
|
1911
|
+
message = "Slice parameter not compatible with string type: has reducer type " + (slice_type_reducer "describe" NIL ) + " but expecting integer".
|
|
1912
|
+
signal_error message err.
|
|
1913
|
+
RETURN meta::basics::any.
|
|
1914
|
+
}
|
|
1915
|
+
RETURN basics::string.
|
|
1916
|
+
} elif value_type "domain" == domain::binary {
|
|
1917
|
+
if !(compatibility::check basics::integer slice_type_reducer) {
|
|
1918
|
+
message = "Slice parameter not compatible with binary type: has reducer type " + (slice_type_reducer "describe" NIL ) + " but expecting integer".
|
|
1919
|
+
signal_error message err.
|
|
1920
|
+
RETURN meta::basics::any.
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
RETURN basics::binary.
|
|
1924
|
+
} elif value_type "is_tuple" || value_type "is_record" || value_type "is_immutable" || value_type "is_function" {
|
|
1925
|
+
RETURN immutable::type slice_type_reducer value_type_product.
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
module database_checks {
|
|
1931
|
+
// init_arg is intentionally unused here just to run metachecks for this argument
|
|
1932
|
+
create_database = fn (err, arg, _init_arg) {
|
|
1933
|
+
if (arg "domain" != domain::string) {
|
|
1934
|
+
signal_error ("Create database requires string argument for seed, got " + (arg "describe" NIL) + " instead") err.
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
RETURN ::meta::basics::packet.
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
execute_transaction = fn (err, db, message, is_encrypted) {
|
|
1941
|
+
if (db "domain" != domain::packet ) {
|
|
1942
|
+
signal_error ("Execute transaction requires database, got " + (db "describe" NIL) + " instead") err.
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
if is_encrypted && (message "domain" != domain::binary) {
|
|
1946
|
+
signal_error ("Encrypted message passed to a transaction must be a binary object, but got " + (db "describe" NIL) + " instead" ) err.
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
RETURN tuple::type [nullable::type basics::packet, basics::any, basics::string].
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
module stack {
|
|
1954
|
+
stack_collection = (,).
|
|
1955
|
+
init = fn (_)
|
|
1956
|
+
{
|
|
1957
|
+
id = _new_id().
|
|
1958
|
+
stack_collection id -> (($count->0)).
|
|
1959
|
+
RETURN &(stack_collection id).
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
push = fn (st, val) {
|
|
1963
|
+
#st (#st "count") -> val.
|
|
1964
|
+
#st "count" -> (#st "count") + 1.
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
pop = fn (st) {
|
|
1968
|
+
if #st "count" == 0 {
|
|
1969
|
+
RETURN NIL.
|
|
1970
|
+
} else {
|
|
1971
|
+
#st "count" -> (#st "count") - 1.
|
|
1972
|
+
ret = #st (#st "count").
|
|
1973
|
+
delete #st (#st "count").
|
|
1974
|
+
RETURN ret.
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
peek = fn (st) = (#st ((#st "count") - 1)).
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
|
|
1982
|
+
module ret {
|
|
1983
|
+
// return_statck tracks the return type
|
|
1984
|
+
return_stack = stack::init().
|
|
1985
|
+
|
|
1986
|
+
push = fn (rt)
|
|
1987
|
+
{
|
|
1988
|
+
stack::push return_stack rt.
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
pop = fn (_) { stack::pop return_stack. }
|
|
1992
|
+
current = fn (_) = ( stack::peek return_stack ).
|
|
1993
|
+
|
|
1994
|
+
// return_state tracks whether the return statement is present or not.
|
|
1995
|
+
return_state = stack::init().
|
|
1996
|
+
push_state = fn (state)
|
|
1997
|
+
{
|
|
1998
|
+
stack::push return_state (TRUE->state).
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
pop_state = fn (_)
|
|
2002
|
+
{
|
|
2003
|
+
state = stack::pop return_state TRUE.
|
|
2004
|
+
RETURN state.
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
current_state = fn (_)
|
|
2008
|
+
{
|
|
2009
|
+
state_var = stack::peek return_state.
|
|
2010
|
+
if state_var { RETURN state_var TRUE. } else { RETURN NIL. }
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
set_state = fn (state)
|
|
2014
|
+
{
|
|
2015
|
+
state_var = stack::pop return_state.
|
|
2016
|
+
if state_var {
|
|
2017
|
+
stack::push return_state (TRUE->state).
|
|
2018
|
+
}.
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
// this is used at the end of the 'else' clause of the 'if' statement
|
|
2022
|
+
// it assumes that both 'then' and 'else' pushed their own state onto the state stack
|
|
2023
|
+
merge_state = fn (_)
|
|
2024
|
+
{
|
|
2025
|
+
state1 = pop_state().
|
|
2026
|
+
state2 = pop_state().
|
|
2027
|
+
state = ( current_state() || (state1 && state2) ).
|
|
2028
|
+
set_state state.
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
check_and_pop_state = fn (err)
|
|
2032
|
+
{
|
|
2033
|
+
return_type = current().
|
|
2034
|
+
current_return_state = current_state().
|
|
2035
|
+
|
|
2036
|
+
null_allowed = nullable::allows_null_values return_type.
|
|
2037
|
+
if !null_allowed && !current_return_state {
|
|
2038
|
+
signal_error "Function return does not allow NIL but there are some code paths that do not produce a valid return" err.
|
|
2039
|
+
}
|
|
2040
|
+
pop_state().
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
module locals {
|
|
2045
|
+
hidden {
|
|
2046
|
+
current_scope = NIL.
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
push = fn (name) {
|
|
2050
|
+
new_scope = (
|
|
2051
|
+
"name" -> name,
|
|
2052
|
+
"parent" -> current_scope,
|
|
2053
|
+
"vars" -> (,)
|
|
2054
|
+
).
|
|
2055
|
+
current_scope -> new_scope.
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
pop = fn (_) {
|
|
2059
|
+
current_scope->current_scope "parent".
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
set = fn (nm, tp) {
|
|
2063
|
+
current_scope "vars" nm -> tp.
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
get_current_scope = fn (_) {
|
|
2067
|
+
RETURN current_scope.
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
set_current_scope = fn (s) {
|
|
2071
|
+
current_scope->s.
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
hidden {
|
|
2075
|
+
get_ex = fn (scope, layer, nm) {
|
|
2076
|
+
if (layer > 0) {
|
|
2077
|
+
if (scope "parent") == NIL {
|
|
2078
|
+
RETURN NIL.
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
RETURN (get_ex (scope "parent") (layer - 1) nm).
|
|
2082
|
+
} else {
|
|
2083
|
+
RETURN (scope "vars" nm).
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
find_ex = fn (scope, nm) {
|
|
2088
|
+
ret = scope "vars" nm.
|
|
2089
|
+
if( ret != NIL) {
|
|
2090
|
+
RETURN ret.
|
|
2091
|
+
} else {
|
|
2092
|
+
if (scope "parent") == NIL {
|
|
2093
|
+
RETURN NIL.
|
|
2094
|
+
}
|
|
2095
|
+
RETURN (find_ex (scope "parent") nm).
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
get = fn (layer, nm) {
|
|
2101
|
+
ret = (get_ex current_scope layer nm).
|
|
2102
|
+
if (ret == NIL) {
|
|
2103
|
+
signal_error ("Internal error, local value " + nm + " was not found") "".
|
|
2104
|
+
RETURN meta::basics::any.
|
|
2105
|
+
}
|
|
2106
|
+
RETURN ret.
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
find = fn (nm) {
|
|
2110
|
+
RETURN (find_ex current_scope nm).
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
module functions {
|
|
2116
|
+
hidden {
|
|
2117
|
+
get_arg_list_and_return = fn (args, ret, n) {
|
|
2118
|
+
if !(ret "is_function") {
|
|
2119
|
+
RETURN ($args->args, $return->ret).
|
|
2120
|
+
} else {
|
|
2121
|
+
RETURN (get_arg_list_and_return (args'(n->(ret "rtype"))) (ret "ptype") (n + 1)).
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
get_arg_count = fn (f) {
|
|
2126
|
+
if !(f "is_function") {
|
|
2127
|
+
RETURN 0.
|
|
2128
|
+
} else {
|
|
2129
|
+
RETURN (get_arg_count (f "ptype")) + 1.
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
// TODO_TODO: Test this carefully
|
|
2135
|
+
f_simple = fn (arg, ret) {
|
|
2136
|
+
Describe = fn (_)
|
|
2137
|
+
{
|
|
2138
|
+
RETURN ("(" + (arg "describe" NIL) + "->" + (ret "describe" NIL) + ")").
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
description = Describe().
|
|
2142
|
+
|
|
2143
|
+
res = (
|
|
2144
|
+
"is_function" -> TRUE,
|
|
2145
|
+
"rtype" -> arg,
|
|
2146
|
+
"ptype" -> ret,
|
|
2147
|
+
"describe" -> fn (_) = description,
|
|
2148
|
+
"verify_reduction" -> fn (actual) {
|
|
2149
|
+
if !(compatibility::check arg actual) {
|
|
2150
|
+
RETURN [ ret,
|
|
2151
|
+
"Incompatible argument type, expecting " + (arg "describe" NIL) + " but observed " + (actual "describe" NIL)
|
|
2152
|
+
].
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
RETURN [ ret, NIL ].
|
|
2156
|
+
},
|
|
2157
|
+
"iteration" -> iteration_forbidden description,
|
|
2158
|
+
"check_compatibility" -> fn (actual) {
|
|
2159
|
+
if !( actual "is_function" ) {
|
|
2160
|
+
RETURN NIL.
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
if !( compatibility::check (actual "rtype") arg) {
|
|
2164
|
+
RETURN NIL.
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
if !( compatibility::check ret (actual "ptype")) {
|
|
2168
|
+
RETURN NIL.
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
RETURN TRUE.
|
|
2172
|
+
},
|
|
2173
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
2174
|
+
).
|
|
2175
|
+
|
|
2176
|
+
RETURN res.
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
hidden {
|
|
2180
|
+
f_ex = fn (args_list, start, ret) {
|
|
2181
|
+
if (args_list 0) == NIL {
|
|
2182
|
+
_meta_stage_error "Invalid function type, argument list is invalid\n".
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
if (args_list (start + 1) == NIL) {
|
|
2186
|
+
RETURN (f_simple (args_list start) ret).
|
|
2187
|
+
} else {
|
|
2188
|
+
RETURN (f_simple (args_list start) (f_ex args_list (start + 1) ret)).
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
get_last_arg = fn (f) {
|
|
2193
|
+
if !(f "is_function") { RETURN NIL. }
|
|
2194
|
+
if (f "ptype" "is_function") {
|
|
2195
|
+
RETURN (get_last_arg (f "ptype")).
|
|
2196
|
+
} else {
|
|
2197
|
+
RETURN (f "rtype").
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
|
|
2203
|
+
f = fn (args, ret)
|
|
2204
|
+
{
|
|
2205
|
+
// Backward compatibility as we are switching to type expressions:
|
|
2206
|
+
// args could be an array [t1,t2,...] or a tuple meta::tuple::type [t1, t2, ...]
|
|
2207
|
+
|
|
2208
|
+
// tuple type is generated by type expression logic when it sees [t1, t2, ...]
|
|
2209
|
+
// whereas an expression that is not a type expression will generate an array
|
|
2210
|
+
|
|
2211
|
+
// TODO: Remove this code when we fully switch to type expressions
|
|
2212
|
+
// and only expect a tuple type descriptor as parameter, not an array
|
|
2213
|
+
tuple = args.
|
|
2214
|
+
if args "is_tuple" {
|
|
2215
|
+
tuple->args "type_list".
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
RETURN ( f_ex tuple 0 ret ).
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
cp_unary_f = fn (arg, ret, cp) { // const_propagating function, used for some primitives
|
|
2222
|
+
description = "(" + (arg "describe" NIL) + "->/*const_propagating*/" + (ret "describe" NIL) + ")".
|
|
2223
|
+
|
|
2224
|
+
res = (
|
|
2225
|
+
"rtype" -> arg,
|
|
2226
|
+
"ptype" -> ret,
|
|
2227
|
+
"describe" -> fn (_) = description,
|
|
2228
|
+
"iteration" -> iteration_forbidden description,
|
|
2229
|
+
"verify_reduction" -> fn (a) {
|
|
2230
|
+
message = NIL.
|
|
2231
|
+
if !(compatibility::check arg a) {
|
|
2232
|
+
message -> "Incompatible argument type for function, expected " + (arg "describe" NIL) + " but observing " + (a "describe" NIL) + " instead".
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
if !(a "is_const") {
|
|
2236
|
+
RETURN [ ret, message ].
|
|
2237
|
+
} else {
|
|
2238
|
+
RETURN [ (basics::constant ret (cp (a "const_value"))), message ].
|
|
2239
|
+
}
|
|
2240
|
+
},
|
|
2241
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
2242
|
+
).
|
|
2243
|
+
|
|
2244
|
+
RETURN res.
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
all_ellipses = (,).
|
|
2248
|
+
|
|
2249
|
+
ellipsis = fn (type)
|
|
2250
|
+
{
|
|
2251
|
+
description = (type "describe" NIL) + "->...".
|
|
2252
|
+
res = (
|
|
2253
|
+
"rtype" -> type,
|
|
2254
|
+
"describe" -> fn (_) = description,
|
|
2255
|
+
"iteration" -> iteration_forbidden res,
|
|
2256
|
+
"verify_reduction" -> fn (arg)
|
|
2257
|
+
{
|
|
2258
|
+
message = NIL.
|
|
2259
|
+
if !(compatibility::check type arg) {
|
|
2260
|
+
message -> "Incompatible argument type".
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
RETURN [ all_ellipses type, message ].
|
|
2264
|
+
},
|
|
2265
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
2266
|
+
).
|
|
2267
|
+
|
|
2268
|
+
all_ellipses type -> res.
|
|
2269
|
+
RETURN res.
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
module debug {
|
|
2274
|
+
list_names = fn (_)
|
|
2275
|
+
{
|
|
2276
|
+
sc ::meta::names_root -- (name -> type) {
|
|
2277
|
+
_print name "-->".
|
|
2278
|
+
_print (type "describe" NIL) "\n".
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
module blinded {
|
|
2284
|
+
type = fn (rtype, ptype) {
|
|
2285
|
+
description = "#(" + (rtype "describe" NIL) + "->>" + (ptype "describe" NIL) + ")".
|
|
2286
|
+
|
|
2287
|
+
RETURN (
|
|
2288
|
+
"is_blinded" -> TRUE,
|
|
2289
|
+
"describe" -> fn (_) = description,
|
|
2290
|
+
"rtype" -> rtype,
|
|
2291
|
+
"ptype" -> ptype,
|
|
2292
|
+
"check_compatibility" -> fn (actual) {
|
|
2293
|
+
if actual "is_blinded" {
|
|
2294
|
+
RETURN (rtype "check_compatibility" (actual "rtype")) &&
|
|
2295
|
+
(ptype "check_compatibility" (actual "ptype")).
|
|
2296
|
+
} else {
|
|
2297
|
+
RETURN NIL.
|
|
2298
|
+
}
|
|
2299
|
+
},
|
|
2300
|
+
"iteration" -> iteration_forbidden description,
|
|
2301
|
+
"verify_reduction" -> fn (param)
|
|
2302
|
+
{
|
|
2303
|
+
if !(rtype "check_compatibility" param) {
|
|
2304
|
+
message = "In a reduction: invalid reducer type. Required " + (rtype "describe" NIL) + " but observing " + (param "describe" NIL).
|
|
2305
|
+
RETURN [any_type, message].
|
|
2306
|
+
} else {
|
|
2307
|
+
RETURN [(meta::nullable::type ptype), NIL].
|
|
2308
|
+
}
|
|
2309
|
+
},
|
|
2310
|
+
"safe_cast" -> fn (_type_from, err)
|
|
2311
|
+
{
|
|
2312
|
+
reducer_cast = conversions::safe_cast basics::any rtype err.
|
|
2313
|
+
product_cast = conversions::safe_cast basics::any ptype err.
|
|
2314
|
+
RETURN fn (value)
|
|
2315
|
+
{
|
|
2316
|
+
abort provisional "Safe cast failed, required dictionary value" WHEN _typeof value != "BLINDED_DICTIONARY".
|
|
2317
|
+
|
|
2318
|
+
sc value -- (i -> v) {
|
|
2319
|
+
reducer_cast i.
|
|
2320
|
+
product_cast v.
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
RETURN value.
|
|
2324
|
+
}
|
|
2325
|
+
},
|
|
2326
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
2327
|
+
).
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
make = fn (unblinded_type) {
|
|
2331
|
+
if( unblinded_type "is_immutable" ) {
|
|
2332
|
+
return type (unblinded_type $rtype) (make (unblinded_type $ptype)).
|
|
2333
|
+
} elif( unblinded_type "is_record" ) {
|
|
2334
|
+
return type basics::string basics::any.
|
|
2335
|
+
} elif( unblinded_type "is_tuple" ) {
|
|
2336
|
+
return type basics::integer basics::any.
|
|
2337
|
+
} else {
|
|
2338
|
+
return unblinded_type.
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
module functor {
|
|
2344
|
+
array_append = fn (arr, val) {
|
|
2345
|
+
return arr'(_count arr->val).
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
simple = fn (
|
|
2349
|
+
in_func /*type,type[]->($check->type,$ts->type[]) */,
|
|
2350
|
+
out_func /* type[]->type */
|
|
2351
|
+
) {
|
|
2352
|
+
RETURN fn (typeset /* type[] */) {
|
|
2353
|
+
description = "(::meta::functor::functor ***)".
|
|
2354
|
+
RETURN (
|
|
2355
|
+
"is_functor" -> TRUE,
|
|
2356
|
+
"in_typeset" -> typeset,
|
|
2357
|
+
"in_func" -> in_func,
|
|
2358
|
+
"out_func" -> out_func,
|
|
2359
|
+
"describe" -> fn (_) = description,
|
|
2360
|
+
"check_compatibility" -> fn (actual) = (
|
|
2361
|
+
actual $in_typeset == typeset &&
|
|
2362
|
+
actual $in_func == in_func &&
|
|
2363
|
+
actual $out_func == out_func ),
|
|
2364
|
+
"iteration" -> iteration_forbidden description,
|
|
2365
|
+
"safe_cast" -> no_safe_cast description,
|
|
2366
|
+
"reference_extention" -> reference_extention_forbidden description,
|
|
2367
|
+
"verify_reduction" -> fn (param) {
|
|
2368
|
+
BIND ($check->check_type, $ts->out_typeset) TO in_func param typeset.
|
|
2369
|
+
if !(compatibility::check check_type param) {
|
|
2370
|
+
RETURN [ basics::any, "functor compatibility check failed, needed: " + (check_type "describe" NIL) + " actual:" + (param "describe" NIL) ].
|
|
2371
|
+
} else {
|
|
2372
|
+
RETURN [ out_func out_typeset, NIL ].
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
).
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
functor_ex = fn (index, args, ret) {
|
|
2380
|
+
if args (index + 1) == NIL {
|
|
2381
|
+
return simple (args index) ret.
|
|
2382
|
+
} else {
|
|
2383
|
+
return simple (args index) (functor_ex (index + 1) args ret).
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
make = fn (args, ret) = (functor_ex 0 args ret).
|
|
2388
|
+
|
|
2389
|
+
save = fn (param, typeset) = ($check->param, $ts->array_append typeset param).
|
|
2390
|
+
|
|
2391
|
+
check = fn (t) {
|
|
2392
|
+
RETURN fn (param, typeset) = ($check->t, $ts->array_append typeset param).
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
return_index_blinded = fn (index) {
|
|
2396
|
+
RETURN fn (typeset) = (blinded::make (typeset index)).
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
make_any_x_ret_blinded_0 = fn (t) = ((make [ save, check t ] (return_index_blinded 0)) []).
|
|
2400
|
+
make_any_x_y_ret_blinded_0 = fn (t1, t2) = ((make [ save, check t1, check t2 ] (return_index_blinded 0)) []).
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
none = basics::none.
|
|
2404
|
+
arr = immutable::array.
|
|
2405
|
+
int = basics::integer.
|
|
2406
|
+
str = basics::string.
|
|
2407
|
+
bin = basics::binary.
|
|
2408
|
+
bool = basics::boolean.
|
|
2409
|
+
nil = basics::nil.
|
|
2410
|
+
true = basics::true.
|
|
2411
|
+
false = basics::false.
|
|
2412
|
+
time = basics::time.
|
|
2413
|
+
utf8 = basics::utf8.
|
|
2414
|
+
hash_code = basics::hash_code.
|
|
2415
|
+
truenil = meta::nullable::type true.
|
|
2416
|
+
function = functions::f.
|
|
2417
|
+
set = immutable::set.
|
|
2418
|
+
immutable_map = immutable::type.
|
|
2419
|
+
map = immutable::type.
|
|
2420
|
+
db = basics::packet.
|
|
2421
|
+
any = basics::any.
|
|
2422
|
+
saferef = basics::saferef.
|
|
2423
|
+
jsonlimits = record::type($ws->int,$depth->int,$strlen->int,$keylen->int,$items->int).
|
|
2424
|
+
plug = meta::nullable::type true.
|
|
2425
|
+
secretkey_sign = meta::crypto_element::type $SECKEY_SIGN.
|
|
2426
|
+
publickey_sign = meta::crypto_element::type $PUBKEY_SIGN.
|
|
2427
|
+
secretkey_encrypt = meta::crypto_element::type $SECKEY_ENCRYPT.
|
|
2428
|
+
publickey_encrypt = meta::crypto_element::type $PUBKEY_ENCRYPT.
|
|
2429
|
+
crypto_signature = meta::crypto_element::type $SIGNATURE.
|
|
2430
|
+
crypto_message = meta::crypto_element::type $ENCRYPTED_DATA.
|
|
2431
|
+
crypto = meta::crypto_element::type $ANY.
|
|
2432
|
+
global_id = meta::opaque::type $global_id str crypto_element::global_id_check.
|
|
2433
|
+
|
|
2434
|
+
eth_transaction = record::type ($nonce->bin, $gasPrice->bin, $gasLimit->bin, $data->bin, $value->bin, $to->bin).
|
|
2435
|
+
eth_transaction_signed = record::type ($nonce->bin, $gasPrice->bin, $gasLimit->bin, $data->bin, $value->bin, $to->bin, $v->bin, $r->bin, $s->bin, $signer->bin, $chain->(meta::nullable::type str)).
|
|
2436
|
+
|
|
2437
|
+
totp_key = record::type ($seckey->bin, $digits->int, $period->int, $algorithm -> enumerated_sets::type str ($SHA1, $SHA256, $SHA512,)).
|
|
2438
|
+
totp_input_configuration = meta::nullable::type (record::type ($digits -> meta::nullable::type int, $period -> meta::nullable::type int, $key_length -> meta::nullable::type int, $algorithm -> meta::nullable::type (enumerated_sets::type str ($SHA1, $SHA256, $SHA512)))).
|
|
2439
|
+
|
|
2440
|
+
hidden {
|
|
2441
|
+
crypto_scheme_sc = fn (x) {
|
|
2442
|
+
if (x != 1) {
|
|
2443
|
+
_abort_transaction ("Invalid schema id, allowed 1 but got " + (_str x)).
|
|
2444
|
+
RETURN NIL.
|
|
2445
|
+
} else {
|
|
2446
|
+
RETURN x.
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
crypto_scheme = meta::opaque::type $crypto_scheme int crypto_scheme_sc.
|
|
2451
|
+
|
|
2452
|
+
module primitives {
|
|
2453
|
+
names_root "::_print" -> functions::ellipsis any.
|
|
2454
|
+
names_root "::_strlen" -> functions::cp_unary_f str int (fn (str) = (_strlen str)).
|
|
2455
|
+
names_root "::_binlen" -> functions::cp_unary_f bin int (fn (v) = (_binlen v)).
|
|
2456
|
+
names_root "::NIL" -> nil.
|
|
2457
|
+
names_root "::TRUE" -> true.
|
|
2458
|
+
names_root "::FALSE" -> false.
|
|
2459
|
+
names_root "::__LINE__" -> int.
|
|
2460
|
+
names_root "::_to_json_with_limits" -> function [map str int,any] any.
|
|
2461
|
+
names_root "::_from_json_with_limits" -> function [map str int,str] any.
|
|
2462
|
+
names_root "::_rsa_generate_cipher_params" -> function [bin] (record::type ($N->bin, $Phi->bin)).
|
|
2463
|
+
names_root "::_rsa_create_key_by_params" -> function [bin, bin, bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2464
|
+
names_root "::_rsa_create_key" -> function [bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2465
|
+
names_root "::_rsa_encrypt" -> function [bin, bin, bin] bin.
|
|
2466
|
+
names_root "::_rsa_decrypt" -> function [bin, bin, bin] bin.
|
|
2467
|
+
names_root "::_rsa1024_generate_cipher_params" -> function [bin] (record::type ($N->bin, $Phi->bin)).
|
|
2468
|
+
names_root "::_rsa1024_create_key_by_params" -> function [bin, bin, bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2469
|
+
names_root "::_rsa1024_create_key" -> function [bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2470
|
+
names_root "::_rsa1024_encrypt" -> function [bin, bin, bin] bin.
|
|
2471
|
+
names_root "::_rsa1024_decrypt" -> function [bin, bin, bin] bin.
|
|
2472
|
+
names_root "::_rsa2048_generate_cipher_params" -> function [bin] (record::type ($N->bin, $Phi->bin)).
|
|
2473
|
+
names_root "::_rsa2048_create_key_by_params" -> function [bin, bin, bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2474
|
+
names_root "::_rsa2048_create_key" -> function [bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2475
|
+
names_root "::_rsa2048_encrypt" -> function [bin, bin, bin] bin.
|
|
2476
|
+
names_root "::_rsa2048_decrypt" -> function [bin, bin, bin] bin.
|
|
2477
|
+
names_root "::_rsa4096_generate_cipher_params" -> function [bin] (record::type ($N->bin, $Phi->bin)).
|
|
2478
|
+
names_root "::_rsa4096_create_key_by_params" -> function [bin, bin, bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2479
|
+
names_root "::_rsa4096_create_key" -> function [bin] (record::type ($N-> bin, $E->bin, $D->bin)).
|
|
2480
|
+
names_root "::_rsa4096_encrypt" -> function [bin, bin, bin] bin.
|
|
2481
|
+
names_root "::_rsa4096_decrypt" -> function [bin, bin, bin] bin.
|
|
2482
|
+
names_root "::_shamir_generate_shares" -> function [bin, int, int, bin] (record::type ($K->int, $N->int, $Prime->bin, $Shares->(immutable::array (record::type ($i->int, $share->bin))))).
|
|
2483
|
+
names_root "::_shamir_reconstruct_secret" -> function [int, bin, (immutable::array bin)] bin.
|
|
2484
|
+
names_root "::_ecc_c25519_create_key" -> function [str] (meta::tuple::type [str,str]).
|
|
2485
|
+
names_root "::_crypto_get_scheme_id" -> function [crypto] int.
|
|
2486
|
+
names_root "::_crypto_get_element_kind" -> function [crypto] str.
|
|
2487
|
+
names_root "::_crypto_construct_signing_keypair" -> function [int] (record::type ($public_key->publickey_sign, $secret_key->secretkey_sign)).
|
|
2488
|
+
names_root "::_crypto_signing_keypair_from_secret" -> function [int, secretkey_sign] (record::type ($public_key->publickey_sign, $secret_key->secretkey_sign)).
|
|
2489
|
+
names_root "::_crypto_construct_encryption_keypair" -> function [int] (record::type ($public_key->publickey_encrypt, $secret_key->secretkey_encrypt)).
|
|
2490
|
+
names_root "::_crypto_construct_encryption_keypair_from_seed" -> function [int, bin] (record::type ($public_key->publickey_encrypt, $secret_key->secretkey_encrypt)).
|
|
2491
|
+
names_root "::_crypto_default_scheme_id" -> function [plug] int.
|
|
2492
|
+
names_root "::_crypto_scheme_id_valid_range" -> function [plug] (record::type ($min->int, $max->int)).
|
|
2493
|
+
names_root "::_crypto_element_validate" -> function [crypto, int, str] truenil.
|
|
2494
|
+
names_root "::_crypto_validate_kind" -> function [str] truenil.
|
|
2495
|
+
names_root "::_crypto_sign_hash" -> function [hash_code,secretkey_sign] crypto_signature.
|
|
2496
|
+
names_root "::_crypto_verify_hash_signature" -> function [hash_code,crypto_signature,publickey_sign] truenil.
|
|
2497
|
+
names_root "::_crypto_encrypt_message" -> function [secretkey_encrypt,publickey_encrypt,bin] crypto_message.
|
|
2498
|
+
names_root "::_crypto_decrypt_message" -> function [secretkey_encrypt,publickey_encrypt,crypto_message] bin.
|
|
2499
|
+
names_root "::_crypto_get_key_id" -> function [ crypto ] bin.
|
|
2500
|
+
names_root "::_crypto_get_key_id_target" -> function [ crypto_message ] bin.
|
|
2501
|
+
names_root "::_construct_blinded_dictionary" -> functor::make_any_x_ret_blinded_0 (immutable::set (immutable::array basics::any) ).
|
|
2502
|
+
names_root "::_construct_blinded_dictionary_custom" -> functor::make_any_x_y_ret_blinded_0 (immutable::set (immutable::array basics::any) ) (immutable::type str any).
|
|
2503
|
+
names_root "::_construct_blinded_with_absence" -> functor::make_any_x_y_ret_blinded_0 (immutable::set (immutable::array basics::any) ) (immutable::set (immutable::array basics::any) ).
|
|
2504
|
+
names_root "::_examine_blinded" -> function [any, (immutable::array basics::any)] (immutable::array basics::any).
|
|
2505
|
+
names_root "::_examine_blinded_many" -> function [any, (immutable::array (immutable::array basics::any))] (immutable::array (immutable::array basics::any)).
|
|
2506
|
+
names_root "::_examine_blinded_strict" -> function [any, (immutable::array basics::any)] (immutable::array basics::any).
|
|
2507
|
+
names_root "::_examine_blinded_many_strict" -> function [any, (immutable::array (immutable::array basics::any))] (immutable::array (immutable::array basics::any)).
|
|
2508
|
+
names_root "::_get_hash_code_metadata" -> function [hash_code] (record::type ($hash_type->str, $hash_shape_version->int)).
|
|
2509
|
+
names_root "::_eth_sign" -> function [bin, eth_transaction, meta::nullable::type int] bin.
|
|
2510
|
+
names_root "::_eth_parse_signature" -> function [bin] eth_transaction_signed.
|
|
2511
|
+
names_root "::_eth_validate_and_parse_signature" -> function [bin, bin] eth_transaction_signed.
|
|
2512
|
+
names_root "::_eth_public_from_private" -> function [bin] bin.
|
|
2513
|
+
names_root "::_eth_address_from_public" -> function [bin] bin.
|
|
2514
|
+
names_root "::_eth_compress_public" -> function [bin] bin.
|
|
2515
|
+
names_root "::_eth_decompress_public" -> function [bin] bin.
|
|
2516
|
+
names_root "::_rlp_decode" -> function [bin] any.
|
|
2517
|
+
names_root "::_crypto_keccak256" -> function [bin] bin.
|
|
2518
|
+
names_root "::_crypto_sha256" -> function [bin] bin.
|
|
2519
|
+
names_root "::_crypto_sha256d" -> function [bin] bin.
|
|
2520
|
+
names_root "::_crypto_ripemd160" -> function [bin] bin.
|
|
2521
|
+
names_root "::_crypto_hash160" -> function [bin] bin.
|
|
2522
|
+
names_root "::_crypto_hmac_sha256" -> function [bin, bin] bin.
|
|
2523
|
+
names_root "::_crypto_hmac_sha512" -> function [bin, bin] bin.
|
|
2524
|
+
names_root "::_base58_encode" -> function [bin] str.
|
|
2525
|
+
names_root "::_base58_decode" -> function [str] bin.
|
|
2526
|
+
names_root "::_base58check_encode" -> function [bin] str.
|
|
2527
|
+
names_root "::_base58check_decode" -> function [str] bin.
|
|
2528
|
+
names_root "::_crypto_secp256k1_sign_recoverable" -> function [bin, bin] bin.
|
|
2529
|
+
names_root "::_crypto_secp256k1_ecrecover" -> function [bin, bin] bin.
|
|
2530
|
+
names_root "::_crypto_secp256k1_verify" -> function [bin, bin, bin] truenil.
|
|
2531
|
+
names_root "::_rlp_encode" -> function [any] bin.
|
|
2532
|
+
names_root "::_bech32_encode" -> function [str, bin] str.
|
|
2533
|
+
names_root "::_bech32_decode" -> function [str] (record::type ($hrp->str, $data->bin)).
|
|
2534
|
+
names_root "::_bech32m_encode" -> function [str, bin] str.
|
|
2535
|
+
names_root "::_bech32m_decode" -> function [str] (record::type ($hrp->str, $data->bin)).
|
|
2536
|
+
names_root "::_read" -> function [bin] (forwards::disjunction ((record::type ($kind -> enumerated_sets::type str ($ok,), $value -> any)), (record::type ($kind -> enumerated_sets::type str ($err,), $value -> str)))).
|
|
2537
|
+
names_root "::_generate_totp_key" -> function [totp_input_configuration] totp_key.
|
|
2538
|
+
names_root "::_generate_totp_code" -> function [totp_key, time] str.
|
|
2539
|
+
|
|
2540
|
+
ret_spec = basics::nothing "primitives::retspec".
|
|
2541
|
+
ret_spec->ret_spec'(
|
|
2542
|
+
"verify_reduction" -> fn (arg) {
|
|
2543
|
+
message = NIL.
|
|
2544
|
+
expected = ret::current().
|
|
2545
|
+
if expected == NIL {
|
|
2546
|
+
message -> "Return without a function (ret_spec)".
|
|
2547
|
+
} elif !(compatibility::check expected arg) {
|
|
2548
|
+
// TODO TODO: prevent creation of duplicate names inside temporary scopes of if and SCAN
|
|
2549
|
+
message -> ("Invalid return type, expected " + (expected "describe" NIL) + " but observing " + (arg "describe" NIL)).
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
ret::set_state().
|
|
2553
|
+
RETURN [ arg, message ].
|
|
2554
|
+
}
|
|
2555
|
+
).
|
|
2556
|
+
names_root "::_return" -> ret_spec.
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
type_of_global = fn (name) = (names_root name "describe" NIL).
|
|
2560
|
+
type_of_local = fn (name) {
|
|
2561
|
+
t = locals::find name.
|
|
2562
|
+
if t {
|
|
2563
|
+
RETURN (locals::find name "describe" NIL).
|
|
2564
|
+
} else {
|
|
2565
|
+
RETURN "".
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
domain_of = fn (name) = (domain::name (names_root name "domain")).
|
|
2570
|
+
is_constant = fn (name) = (names_root name "is_const").
|
|
2571
|
+
constant_value = fn (name) = (names_root name "const_value").
|
|
2572
|
+
|
|
2573
|
+
module checks {
|
|
2574
|
+
verify_is_type_expression = fn (err, expr)
|
|
2575
|
+
{
|
|
2576
|
+
if (_typeof expr) != "IMMUTABLE_DICTIONARY" {
|
|
2577
|
+
signal_error "Invalid type expression" err.
|
|
2578
|
+
RETURN int.
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
if (expr "describe") == NIL {
|
|
2582
|
+
signal_error "Invalid type expression" err.
|
|
2583
|
+
RETURN int.
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
RETURN expr.
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
global_name_get = fn (name, err)
|
|
2591
|
+
{
|
|
2592
|
+
ret = names_root name.
|
|
2593
|
+
if ret == NIL {
|
|
2594
|
+
signal_error ("Internal error: global name " + name + " was not found") err.
|
|
2595
|
+
RETURN any.
|
|
2596
|
+
}
|
|
2597
|
+
RETURN ret.
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
|
|
2601
|
+
get_reducer_type = fn (f, err)
|
|
2602
|
+
{
|
|
2603
|
+
if f "iterable" || f "is_record" || f "is_immutable" || f "is_function" || f "is_tuple" || f "is_record" {
|
|
2604
|
+
RETURN f "rtype".
|
|
2605
|
+
} elif f "is_any_type" {
|
|
2606
|
+
RETURN meta::basics::any.
|
|
2607
|
+
} else {
|
|
2608
|
+
signal_error ("Cannot deduce reducer type for " + ( f "describe" NIL ) ) err.
|
|
2609
|
+
RETURN meta::basics::any.
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
get_product_type = fn (f, err)
|
|
2614
|
+
{
|
|
2615
|
+
if f "iterable" || f "is_immutable" || f "is_function" || f "is_tuple" || f "is_record" {
|
|
2616
|
+
RETURN f "ptype".
|
|
2617
|
+
} elif f "is_any_type" {
|
|
2618
|
+
RETURN meta::basics::any.
|
|
2619
|
+
} else {
|
|
2620
|
+
message = "Cannot deduce product type for " + (f "describe" NIL).
|
|
2621
|
+
signal_error message err.
|
|
2622
|
+
RETURN basics::any.
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
|
|
2627
|
+
get_product_type_detailed = fn (f, reducer, err)
|
|
2628
|
+
{
|
|
2629
|
+
if f "iterable" || f "is_immutable" || f "is_function" {
|
|
2630
|
+
RETURN f "ptype".
|
|
2631
|
+
} elif f "is_record" {
|
|
2632
|
+
if reducer "is_const" && _typeof (reducer "const_value") == "STRING" {
|
|
2633
|
+
ret = f "field_list" (reducer "const_value").
|
|
2634
|
+
if NIL != ret {
|
|
2635
|
+
RETURN ret.
|
|
2636
|
+
} else {
|
|
2637
|
+
RETURN basics::any.
|
|
2638
|
+
}
|
|
2639
|
+
} else {
|
|
2640
|
+
RETURN basics::any.
|
|
2641
|
+
}
|
|
2642
|
+
} elif f "is_tuple" {
|
|
2643
|
+
if reducer "is_const" && _typeof (reducer "const_value") == "INTEGER" {
|
|
2644
|
+
ret = f "type_list" (reducer "const_value").
|
|
2645
|
+
if NIL != ret {
|
|
2646
|
+
RETURN ret.
|
|
2647
|
+
} else {
|
|
2648
|
+
RETURN basics::any.
|
|
2649
|
+
}
|
|
2650
|
+
} else {
|
|
2651
|
+
RETURN basics::any.
|
|
2652
|
+
}
|
|
2653
|
+
} elif f "is_any_type" {
|
|
2654
|
+
RETURN basics::any.
|
|
2655
|
+
} elif f "is_nullable" {
|
|
2656
|
+
RETURN get_product_type_detailed (f "non_null_type") reducer err.
|
|
2657
|
+
} else {
|
|
2658
|
+
signal_error ("Type " + (f "describe" NIL) + " is not reduce-able: no product") err.
|
|
2659
|
+
RETURN basics::any.
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
finalize = fn (_)
|
|
2664
|
+
{
|
|
2665
|
+
}
|
|
2666
|
+
}
|