@graffiticode/basis 1.5.20 → 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 +64 -0
- package/src/lexicon.js +14 -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
|
@@ -481,6 +481,30 @@ export class Checker extends Visitor {
|
|
|
481
481
|
});
|
|
482
482
|
});
|
|
483
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
|
+
}
|
|
484
508
|
}
|
|
485
509
|
|
|
486
510
|
function enterEnv(ctx, name, paramc) {
|
|
@@ -1299,6 +1323,46 @@ export class Transformer extends Visitor {
|
|
|
1299
1323
|
});
|
|
1300
1324
|
});
|
|
1301
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
|
+
}
|
|
1302
1366
|
}
|
|
1303
1367
|
|
|
1304
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,
|
|
@@ -217,5 +215,19 @@ export const lexicon = {
|
|
|
217
215
|
"cls": "function",
|
|
218
216
|
"length": 2,
|
|
219
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
|
|
220
232
|
}
|
|
221
233
|
}
|