@graffiticode/basis 1.5.19 → 1.5.21
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/package.json +1 -1
- package/spec/spec.html +65 -2
- package/spec/spec.md +48 -1
- package/src/compiler.js +197 -10
- package/src/lexicon.js +42 -2
package/package.json
CHANGED
package/spec/spec.html
CHANGED
|
@@ -64,6 +64,10 @@
|
|
|
64
64
|
<li><a href="#sec-isEmpty"><span class="spec-secid">5.2.16</span>isEmpty</a></li>
|
|
65
65
|
<li><a href="#sec-get"><span class="spec-secid">5.2.17</span>get</a></li>
|
|
66
66
|
<li><a href="#sec-set"><span class="spec-secid">5.2.18</span>set</a></li>
|
|
67
|
+
<li><a href="#sec-not"><span class="spec-secid">5.2.19</span>not</a></li>
|
|
68
|
+
<li><a href="#sec-equiv"><span class="spec-secid">5.2.20</span>equiv</a></li>
|
|
69
|
+
<li><a href="#sec-or"><span class="spec-secid">5.2.21</span>or</a></li>
|
|
70
|
+
<li><a href="#sec-and"><span class="spec-secid">5.2.22</span>and</a></li>
|
|
67
71
|
</ol>
|
|
68
72
|
</li>
|
|
69
73
|
</ol>
|
|
@@ -278,8 +282,8 @@ end
|
|
|
278
282
|
</tr>
|
|
279
283
|
<tr>
|
|
280
284
|
<td align="left"><code>reduce</code></td>
|
|
281
|
-
<td align="left"><code><function list: any></code></td>
|
|
282
|
-
<td align="left">Combines list using a reducer</td>
|
|
285
|
+
<td align="left"><code><function any list: any></code></td>
|
|
286
|
+
<td align="left">Combines list using a reducer with initial value</td>
|
|
283
287
|
</tr>
|
|
284
288
|
<tr>
|
|
285
289
|
<td align="left"><code>hd</code></td>
|
|
@@ -316,6 +320,26 @@ end
|
|
|
316
320
|
<td align="left"><code><string any record: record></code></td>
|
|
317
321
|
<td align="left">Returns a new record with a key set to a value</td>
|
|
318
322
|
</tr>
|
|
323
|
+
<tr>
|
|
324
|
+
<td align="left"><code>not</code></td>
|
|
325
|
+
<td align="left"><code><bool: bool></code></td>
|
|
326
|
+
<td align="left">Logical NOT operation, inverts a boolean value</td>
|
|
327
|
+
</tr>
|
|
328
|
+
<tr>
|
|
329
|
+
<td align="left"><code>equiv</code></td>
|
|
330
|
+
<td align="left"><code><any any: bool></code></td>
|
|
331
|
+
<td align="left">Tests if two values are strictly equivalent</td>
|
|
332
|
+
</tr>
|
|
333
|
+
<tr>
|
|
334
|
+
<td align="left"><code>or</code></td>
|
|
335
|
+
<td align="left"><code><bool bool: bool></code></td>
|
|
336
|
+
<td align="left">Logical OR operation</td>
|
|
337
|
+
</tr>
|
|
338
|
+
<tr>
|
|
339
|
+
<td align="left"><code>and</code></td>
|
|
340
|
+
<td align="left"><code><bool bool: bool></code></td>
|
|
341
|
+
<td align="left">Logical AND operation</td>
|
|
342
|
+
</tr>
|
|
319
343
|
</tbody>
|
|
320
344
|
</table>
|
|
321
345
|
<section id="sec-add" secid="5.2.1">
|
|
@@ -426,6 +450,41 @@ end
|
|
|
426
450
|
<pre><code>set "a" 2 {a: 1} | returns {a: 2}
|
|
427
451
|
</code></pre>
|
|
428
452
|
</section>
|
|
453
|
+
<section id="sec-not" secid="5.2.19">
|
|
454
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-not">5.2.19</a></span>not</h3>
|
|
455
|
+
<p>Logical NOT that inverts a boolean value</p>
|
|
456
|
+
<pre><code>not true | returns false
|
|
457
|
+
not false | returns true
|
|
458
|
+
</code></pre>
|
|
459
|
+
</section>
|
|
460
|
+
<section id="sec-equiv" secid="5.2.20">
|
|
461
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-equiv">5.2.20</a></span>equiv</h3>
|
|
462
|
+
<p>Tests if two values are strictly equivalent</p>
|
|
463
|
+
<pre><code>equiv 1 1 | returns true
|
|
464
|
+
equiv "a" "a" | returns true
|
|
465
|
+
equiv true true | returns true
|
|
466
|
+
equiv 1 2 | returns false
|
|
467
|
+
equiv "a" "b" | returns false
|
|
468
|
+
</code></pre>
|
|
469
|
+
</section>
|
|
470
|
+
<section id="sec-or" secid="5.2.21">
|
|
471
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-or">5.2.21</a></span>or</h3>
|
|
472
|
+
<p>Logical OR operation</p>
|
|
473
|
+
<pre><code>or false false | returns false
|
|
474
|
+
or false true | returns true
|
|
475
|
+
or true false | returns true
|
|
476
|
+
or true true | returns true
|
|
477
|
+
</code></pre>
|
|
478
|
+
</section>
|
|
479
|
+
<section id="sec-and" secid="5.2.22">
|
|
480
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-and">5.2.22</a></span>and</h3>
|
|
481
|
+
<p>Logical AND operation</p>
|
|
482
|
+
<pre><code>and false false | returns false
|
|
483
|
+
and false true | returns false
|
|
484
|
+
and true false | returns false
|
|
485
|
+
and true true | returns true
|
|
486
|
+
</code></pre>
|
|
487
|
+
</section>
|
|
429
488
|
</section>
|
|
430
489
|
</section>
|
|
431
490
|
<section id="sec-Program-Examples" secid="6">
|
|
@@ -518,6 +577,10 @@ Written in <a href="https://spec-md.com" target="_blank">Spec Markdown</a>.</foo
|
|
|
518
577
|
<li id="_sidebar_5.2.16"><a href="#sec-isEmpty"><span class="spec-secid">5.2.16</span>isEmpty</a></li>
|
|
519
578
|
<li id="_sidebar_5.2.17"><a href="#sec-get"><span class="spec-secid">5.2.17</span>get</a></li>
|
|
520
579
|
<li id="_sidebar_5.2.18"><a href="#sec-set"><span class="spec-secid">5.2.18</span>set</a></li>
|
|
580
|
+
<li id="_sidebar_5.2.19"><a href="#sec-not"><span class="spec-secid">5.2.19</span>not</a></li>
|
|
581
|
+
<li id="_sidebar_5.2.20"><a href="#sec-equiv"><span class="spec-secid">5.2.20</span>equiv</a></li>
|
|
582
|
+
<li id="_sidebar_5.2.21"><a href="#sec-or"><span class="spec-secid">5.2.21</span>or</a></li>
|
|
583
|
+
<li id="_sidebar_5.2.22"><a href="#sec-and"><span class="spec-secid">5.2.22</span>and</a></li>
|
|
521
584
|
</ol>
|
|
522
585
|
</li>
|
|
523
586
|
</ol>
|
package/spec/spec.md
CHANGED
|
@@ -169,7 +169,7 @@ This approach draws inspiration from **Model-View-Update** (MVU) architectures,
|
|
|
169
169
|
| `range` | `<number number number: list>` | Generates a range list |
|
|
170
170
|
| `map` | `<function list: list>` | Applies function to each item |
|
|
171
171
|
| `filter` | `<function list: list>` | Keeps items matching predicate |
|
|
172
|
-
| `reduce` | `<function list: any>` | Combines list using a reducer |
|
|
172
|
+
| `reduce` | `<function any list: any>` | Combines list using a reducer with initial value |
|
|
173
173
|
| `hd` | `<list: any>` | First item of list |
|
|
174
174
|
| `tl` | `<list: list>` | All items except first |
|
|
175
175
|
| `nth` | `<number list: any>` | Nth element of list |
|
|
@@ -177,6 +177,10 @@ This approach draws inspiration from **Model-View-Update** (MVU) architectures,
|
|
|
177
177
|
| `isEmpty` | `<list: bool>` | Returns true if the list is empty |
|
|
178
178
|
| `get` | `<string record: any>` | Retrieves a value from a record by key |
|
|
179
179
|
| `set` | `<string any record: record>` | Returns a new record with a key set to a value |
|
|
180
|
+
| `not` | `<bool: bool>` | Logical NOT operation, inverts a boolean value |
|
|
181
|
+
| `equiv` | `<any any: bool>` | Tests if two values are strictly equivalent |
|
|
182
|
+
| `or` | `<bool bool: bool>` | Logical OR operation |
|
|
183
|
+
| `and` | `<bool bool: bool>` | Logical AND operation |
|
|
180
184
|
|
|
181
185
|
### add
|
|
182
186
|
|
|
@@ -322,6 +326,49 @@ Return a new record with an updated field
|
|
|
322
326
|
set "a" 2 {a: 1} | returns {a: 2}
|
|
323
327
|
```
|
|
324
328
|
|
|
329
|
+
### not
|
|
330
|
+
|
|
331
|
+
Logical NOT that inverts a boolean value
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
not true | returns false
|
|
335
|
+
not false | returns true
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### equiv
|
|
339
|
+
|
|
340
|
+
Tests if two values are strictly equivalent
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
equiv 1 1 | returns true
|
|
344
|
+
equiv "a" "a" | returns true
|
|
345
|
+
equiv true true | returns true
|
|
346
|
+
equiv 1 2 | returns false
|
|
347
|
+
equiv "a" "b" | returns false
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### or
|
|
351
|
+
|
|
352
|
+
Logical OR operation
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
or false false | returns false
|
|
356
|
+
or false true | returns true
|
|
357
|
+
or true false | returns true
|
|
358
|
+
or true true | returns true
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### and
|
|
362
|
+
|
|
363
|
+
Logical AND operation
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
and false false | returns false
|
|
367
|
+
and false true | returns false
|
|
368
|
+
and true false | returns false
|
|
369
|
+
and true true | returns true
|
|
370
|
+
```
|
|
371
|
+
|
|
325
372
|
# Program Examples
|
|
326
373
|
|
|
327
374
|
```
|
package/src/compiler.js
CHANGED
|
@@ -27,7 +27,7 @@ class Visitor {
|
|
|
27
27
|
}
|
|
28
28
|
visit(nid, options, resume) {
|
|
29
29
|
try {
|
|
30
|
-
assert(nid);
|
|
30
|
+
assert(nid, "Invalid nid=" + nid);
|
|
31
31
|
let node;
|
|
32
32
|
if (typeof nid === "object") {
|
|
33
33
|
node = nid;
|
|
@@ -425,6 +425,86 @@ export class Checker extends Visitor {
|
|
|
425
425
|
});
|
|
426
426
|
});
|
|
427
427
|
}
|
|
428
|
+
NOT(node, options, resume) {
|
|
429
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
430
|
+
let err = [].concat(err1);
|
|
431
|
+
if (typeof val1 !== "boolean" && val1 !== null && val1 !== undefined && val1 !== 0 && val1 !== "" && val1 !== false) {
|
|
432
|
+
err.push(`NOT operation requires a boolean argument, got ${typeof val1}`);
|
|
433
|
+
}
|
|
434
|
+
const val = node;
|
|
435
|
+
resume(err, val);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
EQUIV(node, options, resume) {
|
|
439
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
440
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
441
|
+
let err = [].concat(err1).concat(err2);
|
|
442
|
+
const validTypes = ["boolean", "string", "number"];
|
|
443
|
+
if (!validTypes.includes(typeof val1) && val1 !== null) {
|
|
444
|
+
err.push(`EQUIV operation requires primitive arguments, got ${typeof val1} for first argument`);
|
|
445
|
+
}
|
|
446
|
+
if (!validTypes.includes(typeof val2) && val2 !== null) {
|
|
447
|
+
err.push(`EQUIV operation requires primitive arguments, got ${typeof val2} for second argument`);
|
|
448
|
+
}
|
|
449
|
+
const val = node;
|
|
450
|
+
resume(err, val);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
OR(node, options, resume) {
|
|
455
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
456
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
457
|
+
let err = [].concat(err1).concat(err2);
|
|
458
|
+
if (typeof val1 !== "boolean" && val1 !== null && val1 !== undefined && val1 !== 0 && val1 !== "" && val1 !== false) {
|
|
459
|
+
err.push(`OR operation requires boolean arguments, got ${typeof val1} for first argument`);
|
|
460
|
+
}
|
|
461
|
+
if (typeof val2 !== "boolean" && val2 !== null && val2 !== undefined && val2 !== 0 && val2 !== "" && val2 !== false) {
|
|
462
|
+
err.push(`OR operation requires boolean arguments, got ${typeof val2} for second argument`);
|
|
463
|
+
}
|
|
464
|
+
const val = node;
|
|
465
|
+
resume(err, val);
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
AND(node, options, resume) {
|
|
470
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
471
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
472
|
+
let err = [].concat(err1).concat(err2);
|
|
473
|
+
if (typeof val1 !== "boolean" && val1 !== null && val1 !== undefined && val1 !== 0 && val1 !== "" && val1 !== false) {
|
|
474
|
+
err.push(`AND operation requires boolean arguments, got ${typeof val1} for first argument`);
|
|
475
|
+
}
|
|
476
|
+
if (typeof val2 !== "boolean" && val2 !== null && val2 !== undefined && val2 !== 0 && val2 !== "" && val2 !== false) {
|
|
477
|
+
err.push(`AND operation requires boolean arguments, got ${typeof val2} for second argument`);
|
|
478
|
+
}
|
|
479
|
+
const val = node;
|
|
480
|
+
resume(err, val);
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
HD(node, options, resume) {
|
|
485
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
486
|
+
let err = [].concat(err1);
|
|
487
|
+
// if (!Array.isArray(val1)) {
|
|
488
|
+
// err.push(`HD operation requires a list argument, got ${typeof val1}`);
|
|
489
|
+
// } else if (val1.length === 0) {
|
|
490
|
+
// err.push(`HD operation called on an empty list`);
|
|
491
|
+
// }
|
|
492
|
+
const val = node;
|
|
493
|
+
resume(err, val);
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
TL(node, options, resume) {
|
|
497
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
498
|
+
let err = [].concat(err1);
|
|
499
|
+
// if (!Array.isArray(val1)) {
|
|
500
|
+
// err.push(`TL operation requires a list argument, got ${typeof val1}`);
|
|
501
|
+
// } else if (val1.length === 0) {
|
|
502
|
+
// err.push(`TL operation called on an empty list`);
|
|
503
|
+
// }
|
|
504
|
+
const val = node;
|
|
505
|
+
resume(err, val);
|
|
506
|
+
});
|
|
507
|
+
}
|
|
428
508
|
}
|
|
429
509
|
|
|
430
510
|
function enterEnv(ctx, name, paramc) {
|
|
@@ -724,7 +804,6 @@ export class Transformer extends Visitor {
|
|
|
724
804
|
}
|
|
725
805
|
BINDING(node, options, resume) {
|
|
726
806
|
const err = [];
|
|
727
|
-
const val = node;
|
|
728
807
|
this.visit(node.elts[0], options, (err1, val1) => {
|
|
729
808
|
this.visit(node.elts[1], options, (err2, val2) => {
|
|
730
809
|
resume([].concat(err1).concat(err2), {key: val1, val: val2});
|
|
@@ -825,9 +904,11 @@ export class Transformer extends Visitor {
|
|
|
825
904
|
resume(err, val);
|
|
826
905
|
}
|
|
827
906
|
LEN(node, options, resume) {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
907
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
908
|
+
const err = e0;
|
|
909
|
+
const val = Array.isArray(v0) && v0.length;
|
|
910
|
+
resume(err, val);
|
|
911
|
+
});
|
|
831
912
|
}
|
|
832
913
|
ARG(node, options, resume) {
|
|
833
914
|
const err = [];
|
|
@@ -869,11 +950,8 @@ export class Transformer extends Visitor {
|
|
|
869
950
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
870
951
|
let err = [];
|
|
871
952
|
let val = [];
|
|
872
|
-
console.log(
|
|
873
|
-
"MAP()",
|
|
874
|
-
"v1=" + JSON.stringify(v1),
|
|
875
|
-
);
|
|
876
953
|
v1.forEach(args => {
|
|
954
|
+
options.SYNC = true;
|
|
877
955
|
options.args = args;
|
|
878
956
|
options = JSON.parse(JSON.stringify(options)); // Copy option arg support async.
|
|
879
957
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
@@ -921,6 +999,7 @@ export class Transformer extends Visitor {
|
|
|
921
999
|
let err = [];
|
|
922
1000
|
let val = v1;
|
|
923
1001
|
v2.forEach((args, index) => {
|
|
1002
|
+
options.SYNC = true;
|
|
924
1003
|
options.args = [val, args];
|
|
925
1004
|
options = JSON.parse(JSON.stringify(options)); // Copy option arg support async.
|
|
926
1005
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
@@ -1150,7 +1229,6 @@ export class Transformer extends Visitor {
|
|
|
1150
1229
|
const start = new Decimal(v0);
|
|
1151
1230
|
const end = new Decimal(v1);
|
|
1152
1231
|
const step = new Decimal(v2);
|
|
1153
|
-
|
|
1154
1232
|
if (step.isZero()) {
|
|
1155
1233
|
resume([...err, 'Error in RANGE operation: step cannot be zero'], []);
|
|
1156
1234
|
return;
|
|
@@ -1176,6 +1254,115 @@ export class Transformer extends Visitor {
|
|
|
1176
1254
|
});
|
|
1177
1255
|
});
|
|
1178
1256
|
}
|
|
1257
|
+
NOT(node, options, resume) {
|
|
1258
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1259
|
+
const err = [].concat(e0);
|
|
1260
|
+
try {
|
|
1261
|
+
// Handle various falsy values explicitly
|
|
1262
|
+
if (v0 === null || v0 === undefined || v0 === 0 || v0 === "" || v0 === false) {
|
|
1263
|
+
resume(err, true);
|
|
1264
|
+
} else {
|
|
1265
|
+
resume(err, !v0);
|
|
1266
|
+
}
|
|
1267
|
+
} catch (e) {
|
|
1268
|
+
resume([...err, `Error in NOT operation: ${e.message}`], false);
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
EQUIV(node, options, resume) {
|
|
1273
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1274
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1275
|
+
const err = [].concat(e0).concat(e1);
|
|
1276
|
+
try {
|
|
1277
|
+
// Use strict equality for primitive comparison
|
|
1278
|
+
const val = v0 === v1;
|
|
1279
|
+
resume(err, val);
|
|
1280
|
+
} catch (e) {
|
|
1281
|
+
resume([...err, `Error in EQUIV operation: ${e.message}`], false);
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
OR(node, options, resume) {
|
|
1287
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1288
|
+
// Short-circuit evaluation - if first argument is truthy, return true immediately
|
|
1289
|
+
if (v0) {
|
|
1290
|
+
resume(e0, true);
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1295
|
+
const err = [].concat(e0).concat(e1);
|
|
1296
|
+
try {
|
|
1297
|
+
// Standard boolean OR operation
|
|
1298
|
+
const val = Boolean(v0) || Boolean(v1);
|
|
1299
|
+
resume(err, val);
|
|
1300
|
+
} catch (e) {
|
|
1301
|
+
resume([...err, `Error in OR operation: ${e.message}`], false);
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
AND(node, options, resume) {
|
|
1307
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1308
|
+
// Short-circuit evaluation - if first argument is falsy, return false immediately
|
|
1309
|
+
if (!v0) {
|
|
1310
|
+
resume(e0, false);
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1315
|
+
const err = [].concat(e0).concat(e1);
|
|
1316
|
+
try {
|
|
1317
|
+
// Standard boolean AND operation
|
|
1318
|
+
const val = Boolean(v0) && Boolean(v1);
|
|
1319
|
+
resume(err, val);
|
|
1320
|
+
} catch (e) {
|
|
1321
|
+
resume([...err, `Error in AND operation: ${e.message}`], false);
|
|
1322
|
+
}
|
|
1323
|
+
});
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
HD(node, options, resume) {
|
|
1327
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1328
|
+
const err = [].concat(e0);
|
|
1329
|
+
try {
|
|
1330
|
+
if (!Array.isArray(v0)) {
|
|
1331
|
+
resume([...err, `Error in HD operation: expected an array, got ${typeof v0}`], null);
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
if (v0.length === 0) {
|
|
1335
|
+
resume([...err, `Error in HD operation: empty array has no head`], null);
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
// Return the first element of the array
|
|
1339
|
+
const val = v0[0];
|
|
1340
|
+
resume(err, val);
|
|
1341
|
+
} catch (e) {
|
|
1342
|
+
resume([...err, `Error in HD operation: ${e.message}`], null);
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
TL(node, options, resume) {
|
|
1347
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1348
|
+
const err = [].concat(e0);
|
|
1349
|
+
try {
|
|
1350
|
+
if (!Array.isArray(v0)) {
|
|
1351
|
+
resume([...err, `Error in TL operation: expected an array, got ${typeof v0}`], []);
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
if (v0.length === 0) {
|
|
1355
|
+
resume([...err, `Error in TL operation: empty array has no tail`], []);
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
// Return all elements except the first
|
|
1359
|
+
const val = v0.slice(1);
|
|
1360
|
+
resume(err, val);
|
|
1361
|
+
} catch (e) {
|
|
1362
|
+
resume([...err, `Error in TL operation: ${e.message}`], []);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1179
1366
|
}
|
|
1180
1367
|
|
|
1181
1368
|
export class Renderer {
|
package/src/lexicon.js
CHANGED
|
@@ -12,7 +12,6 @@ export const lexicon = {
|
|
|
12
12
|
"cls": "function",
|
|
13
13
|
"length": 2,
|
|
14
14
|
"arity": 2,
|
|
15
|
-
"args": ["key", "record"]
|
|
16
15
|
},
|
|
17
16
|
"set" : {
|
|
18
17
|
"tk": 1,
|
|
@@ -20,7 +19,6 @@ export const lexicon = {
|
|
|
20
19
|
"cls": "function",
|
|
21
20
|
"length": 3,
|
|
22
21
|
"arity": 3,
|
|
23
|
-
"args": ["key", "value", "record"]
|
|
24
22
|
},
|
|
25
23
|
"nth" : {
|
|
26
24
|
"tk": 1,
|
|
@@ -189,5 +187,47 @@ export const lexicon = {
|
|
|
189
187
|
"cls": "function",
|
|
190
188
|
"length": 3,
|
|
191
189
|
"arity": 3
|
|
190
|
+
},
|
|
191
|
+
"not" : {
|
|
192
|
+
"tk": 1,
|
|
193
|
+
"name": "NOT",
|
|
194
|
+
"cls": "function",
|
|
195
|
+
"length": 1,
|
|
196
|
+
"arity": 1
|
|
197
|
+
},
|
|
198
|
+
"equiv" : {
|
|
199
|
+
"tk": 1,
|
|
200
|
+
"name": "EQUIV",
|
|
201
|
+
"cls": "function",
|
|
202
|
+
"length": 2,
|
|
203
|
+
"arity": 2
|
|
204
|
+
},
|
|
205
|
+
"or" : {
|
|
206
|
+
"tk": 1,
|
|
207
|
+
"name": "OR",
|
|
208
|
+
"cls": "function",
|
|
209
|
+
"length": 2,
|
|
210
|
+
"arity": 2
|
|
211
|
+
},
|
|
212
|
+
"and" : {
|
|
213
|
+
"tk": 1,
|
|
214
|
+
"name": "AND",
|
|
215
|
+
"cls": "function",
|
|
216
|
+
"length": 2,
|
|
217
|
+
"arity": 2
|
|
218
|
+
},
|
|
219
|
+
"hd" : {
|
|
220
|
+
"tk": 1,
|
|
221
|
+
"name": "HD",
|
|
222
|
+
"cls": "function",
|
|
223
|
+
"length": 1,
|
|
224
|
+
"arity": 1
|
|
225
|
+
},
|
|
226
|
+
"tl" : {
|
|
227
|
+
"tk": 1,
|
|
228
|
+
"name": "TL",
|
|
229
|
+
"cls": "function",
|
|
230
|
+
"length": 1,
|
|
231
|
+
"arity": 1
|
|
192
232
|
}
|
|
193
233
|
}
|