@graffiticode/basis 1.5.19 → 1.5.20
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/src/compiler.js +133 -10
- package/src/lexicon.js +28 -0
package/package.json
CHANGED
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,62 @@ 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
|
+
}
|
|
428
484
|
}
|
|
429
485
|
|
|
430
486
|
function enterEnv(ctx, name, paramc) {
|
|
@@ -724,7 +780,6 @@ export class Transformer extends Visitor {
|
|
|
724
780
|
}
|
|
725
781
|
BINDING(node, options, resume) {
|
|
726
782
|
const err = [];
|
|
727
|
-
const val = node;
|
|
728
783
|
this.visit(node.elts[0], options, (err1, val1) => {
|
|
729
784
|
this.visit(node.elts[1], options, (err2, val2) => {
|
|
730
785
|
resume([].concat(err1).concat(err2), {key: val1, val: val2});
|
|
@@ -825,9 +880,11 @@ export class Transformer extends Visitor {
|
|
|
825
880
|
resume(err, val);
|
|
826
881
|
}
|
|
827
882
|
LEN(node, options, resume) {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
883
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
884
|
+
const err = e0;
|
|
885
|
+
const val = Array.isArray(v0) && v0.length;
|
|
886
|
+
resume(err, val);
|
|
887
|
+
});
|
|
831
888
|
}
|
|
832
889
|
ARG(node, options, resume) {
|
|
833
890
|
const err = [];
|
|
@@ -869,11 +926,8 @@ export class Transformer extends Visitor {
|
|
|
869
926
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
870
927
|
let err = [];
|
|
871
928
|
let val = [];
|
|
872
|
-
console.log(
|
|
873
|
-
"MAP()",
|
|
874
|
-
"v1=" + JSON.stringify(v1),
|
|
875
|
-
);
|
|
876
929
|
v1.forEach(args => {
|
|
930
|
+
options.SYNC = true;
|
|
877
931
|
options.args = args;
|
|
878
932
|
options = JSON.parse(JSON.stringify(options)); // Copy option arg support async.
|
|
879
933
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
@@ -921,6 +975,7 @@ export class Transformer extends Visitor {
|
|
|
921
975
|
let err = [];
|
|
922
976
|
let val = v1;
|
|
923
977
|
v2.forEach((args, index) => {
|
|
978
|
+
options.SYNC = true;
|
|
924
979
|
options.args = [val, args];
|
|
925
980
|
options = JSON.parse(JSON.stringify(options)); // Copy option arg support async.
|
|
926
981
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
@@ -1150,7 +1205,6 @@ export class Transformer extends Visitor {
|
|
|
1150
1205
|
const start = new Decimal(v0);
|
|
1151
1206
|
const end = new Decimal(v1);
|
|
1152
1207
|
const step = new Decimal(v2);
|
|
1153
|
-
|
|
1154
1208
|
if (step.isZero()) {
|
|
1155
1209
|
resume([...err, 'Error in RANGE operation: step cannot be zero'], []);
|
|
1156
1210
|
return;
|
|
@@ -1176,6 +1230,75 @@ export class Transformer extends Visitor {
|
|
|
1176
1230
|
});
|
|
1177
1231
|
});
|
|
1178
1232
|
}
|
|
1233
|
+
NOT(node, options, resume) {
|
|
1234
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1235
|
+
const err = [].concat(e0);
|
|
1236
|
+
try {
|
|
1237
|
+
// Handle various falsy values explicitly
|
|
1238
|
+
if (v0 === null || v0 === undefined || v0 === 0 || v0 === "" || v0 === false) {
|
|
1239
|
+
resume(err, true);
|
|
1240
|
+
} else {
|
|
1241
|
+
resume(err, !v0);
|
|
1242
|
+
}
|
|
1243
|
+
} catch (e) {
|
|
1244
|
+
resume([...err, `Error in NOT operation: ${e.message}`], false);
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
EQUIV(node, options, resume) {
|
|
1249
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1250
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1251
|
+
const err = [].concat(e0).concat(e1);
|
|
1252
|
+
try {
|
|
1253
|
+
// Use strict equality for primitive comparison
|
|
1254
|
+
const val = v0 === v1;
|
|
1255
|
+
resume(err, val);
|
|
1256
|
+
} catch (e) {
|
|
1257
|
+
resume([...err, `Error in EQUIV operation: ${e.message}`], false);
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
OR(node, options, resume) {
|
|
1263
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1264
|
+
// Short-circuit evaluation - if first argument is truthy, return true immediately
|
|
1265
|
+
if (v0) {
|
|
1266
|
+
resume(e0, true);
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1271
|
+
const err = [].concat(e0).concat(e1);
|
|
1272
|
+
try {
|
|
1273
|
+
// Standard boolean OR operation
|
|
1274
|
+
const val = Boolean(v0) || Boolean(v1);
|
|
1275
|
+
resume(err, val);
|
|
1276
|
+
} catch (e) {
|
|
1277
|
+
resume([...err, `Error in OR operation: ${e.message}`], false);
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
AND(node, options, resume) {
|
|
1283
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1284
|
+
// Short-circuit evaluation - if first argument is falsy, return false immediately
|
|
1285
|
+
if (!v0) {
|
|
1286
|
+
resume(e0, false);
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1291
|
+
const err = [].concat(e0).concat(e1);
|
|
1292
|
+
try {
|
|
1293
|
+
// Standard boolean AND operation
|
|
1294
|
+
const val = Boolean(v0) && Boolean(v1);
|
|
1295
|
+
resume(err, val);
|
|
1296
|
+
} catch (e) {
|
|
1297
|
+
resume([...err, `Error in AND operation: ${e.message}`], false);
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1179
1302
|
}
|
|
1180
1303
|
|
|
1181
1304
|
export class Renderer {
|
package/src/lexicon.js
CHANGED
|
@@ -189,5 +189,33 @@ export const lexicon = {
|
|
|
189
189
|
"cls": "function",
|
|
190
190
|
"length": 3,
|
|
191
191
|
"arity": 3
|
|
192
|
+
},
|
|
193
|
+
"not" : {
|
|
194
|
+
"tk": 1,
|
|
195
|
+
"name": "NOT",
|
|
196
|
+
"cls": "function",
|
|
197
|
+
"length": 1,
|
|
198
|
+
"arity": 1
|
|
199
|
+
},
|
|
200
|
+
"equiv" : {
|
|
201
|
+
"tk": 1,
|
|
202
|
+
"name": "EQUIV",
|
|
203
|
+
"cls": "function",
|
|
204
|
+
"length": 2,
|
|
205
|
+
"arity": 2
|
|
206
|
+
},
|
|
207
|
+
"or" : {
|
|
208
|
+
"tk": 1,
|
|
209
|
+
"name": "OR",
|
|
210
|
+
"cls": "function",
|
|
211
|
+
"length": 2,
|
|
212
|
+
"arity": 2
|
|
213
|
+
},
|
|
214
|
+
"and" : {
|
|
215
|
+
"tk": 1,
|
|
216
|
+
"name": "AND",
|
|
217
|
+
"cls": "function",
|
|
218
|
+
"length": 2,
|
|
219
|
+
"arity": 2
|
|
192
220
|
}
|
|
193
221
|
}
|