@graffiticode/basis 1.5.11 → 1.5.13
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 +4 -1
- package/src/compiler.js +157 -21
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graffiticode/basis",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.13",
|
|
5
5
|
"description": "The basis library for creating Graffiticode languages",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
@@ -26,5 +26,8 @@
|
|
|
26
26
|
"https": "^1.0.0",
|
|
27
27
|
"jest": "^27.0.1",
|
|
28
28
|
"react": "^17.0.2"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"decimal.js": "^10.5.0"
|
|
29
32
|
}
|
|
30
33
|
}
|
package/src/compiler.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright (c) 2021, ARTCOMPILER INC */
|
|
2
2
|
import {assert, message, messages, reserveCodeRange} from "./share.js";
|
|
3
|
+
import Decimal from 'decimal.js';
|
|
3
4
|
reserveCodeRange(1000, 1999, "compile");
|
|
4
5
|
messages[1001] = "Node ID %1 not found in pool.";
|
|
5
6
|
messages[1002] = "Invalid tag in node with Node ID %1.";
|
|
@@ -308,6 +309,35 @@ export class Checker extends Visitor {
|
|
|
308
309
|
const val = node;
|
|
309
310
|
resume(err, val);
|
|
310
311
|
}
|
|
312
|
+
RANGE(node, options, resume) {
|
|
313
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
314
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
315
|
+
this.visit(node.elts[2], options, (err3, val3) => {
|
|
316
|
+
const err = [].concat(err1).concat(err2).concat(err3);
|
|
317
|
+
const val = node;
|
|
318
|
+
resume(err, val);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
EQ(node, options, resume) {
|
|
324
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
325
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
326
|
+
const err = [].concat(err1).concat(err2);
|
|
327
|
+
const val = node;
|
|
328
|
+
resume(err, val);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
MOD(node, options, resume) {
|
|
333
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
334
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
335
|
+
const err = [].concat(err1).concat(err2);
|
|
336
|
+
const val = node;
|
|
337
|
+
resume(err, val);
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
}
|
|
311
341
|
}
|
|
312
342
|
|
|
313
343
|
function enterEnv(ctx, name, paramc) {
|
|
@@ -556,8 +586,12 @@ export class Transformer extends Visitor {
|
|
|
556
586
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
557
587
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
558
588
|
const err = [].concat(e0).concat(e1);
|
|
559
|
-
|
|
560
|
-
|
|
589
|
+
try {
|
|
590
|
+
const val = new Decimal(v0).plus(new Decimal(v1)).toNumber();
|
|
591
|
+
resume(err, val);
|
|
592
|
+
} catch (e) {
|
|
593
|
+
resume([...err, `Error in ADD operation: ${e.message}`], NaN);
|
|
594
|
+
}
|
|
561
595
|
});
|
|
562
596
|
});
|
|
563
597
|
}
|
|
@@ -565,8 +599,12 @@ export class Transformer extends Visitor {
|
|
|
565
599
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
566
600
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
567
601
|
const err = [].concat(e0).concat(e1);
|
|
568
|
-
|
|
569
|
-
|
|
602
|
+
try {
|
|
603
|
+
const val = new Decimal(v0).minus(new Decimal(v1)).toNumber();
|
|
604
|
+
resume(err, val);
|
|
605
|
+
} catch (e) {
|
|
606
|
+
resume([...err, `Error in SUB operation: ${e.message}`], NaN);
|
|
607
|
+
}
|
|
570
608
|
});
|
|
571
609
|
});
|
|
572
610
|
}
|
|
@@ -574,8 +612,12 @@ export class Transformer extends Visitor {
|
|
|
574
612
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
575
613
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
576
614
|
const err = [].concat(e0).concat(e1);
|
|
577
|
-
|
|
578
|
-
|
|
615
|
+
try {
|
|
616
|
+
const val = new Decimal(v0).lessThan(new Decimal(v1));
|
|
617
|
+
resume(err, val);
|
|
618
|
+
} catch (e) {
|
|
619
|
+
resume([...err, `Error in LT operation: ${e.message}`], false);
|
|
620
|
+
}
|
|
579
621
|
});
|
|
580
622
|
});
|
|
581
623
|
}
|
|
@@ -623,30 +665,57 @@ export class Transformer extends Visitor {
|
|
|
623
665
|
MUL(node, options, resume) {
|
|
624
666
|
this.visit(node.elts[0], options, (err1, val1) => {
|
|
625
667
|
this.visit(node.elts[1], options, (err2, val2) => {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
668
|
+
let err = [].concat(err1).concat(err2);
|
|
669
|
+
try {
|
|
670
|
+
const val = new Decimal(val1).times(new Decimal(val2)).toNumber();
|
|
671
|
+
resume(err, val);
|
|
672
|
+
} catch (e) {
|
|
673
|
+
if (isNaN(+val1)) {
|
|
674
|
+
err = err.concat(error("MUL first argument must be a number: ", JSON.stringify(node, null, 2)));
|
|
675
|
+
}
|
|
676
|
+
if (isNaN(+val2)) {
|
|
677
|
+
err = err.concat(error("MUL second argument must be a number: ", JSON.stringify(node, null, 2)));
|
|
678
|
+
}
|
|
679
|
+
resume([...err, `Error in MUL operation: ${e.message}`], NaN);
|
|
631
680
|
}
|
|
632
|
-
const err = [].concat(err1).concat(err2);
|
|
633
|
-
const val = +val1 * +val2;
|
|
634
|
-
resume(err, val);
|
|
635
681
|
});
|
|
636
682
|
});
|
|
637
683
|
}
|
|
638
684
|
POW(node, options, resume) {
|
|
639
685
|
this.visit(node.elts[0], options, (err1, val1) => {
|
|
640
686
|
this.visit(node.elts[1], options, (err2, val2) => {
|
|
641
|
-
|
|
642
|
-
|
|
687
|
+
let err = [].concat(err1).concat(err2);
|
|
688
|
+
try {
|
|
689
|
+
const val = new Decimal(val1).pow(new Decimal(val2)).toNumber();
|
|
690
|
+
resume(err, val);
|
|
691
|
+
} catch (e) {
|
|
692
|
+
if (isNaN(+val1)) {
|
|
693
|
+
err = err.concat(error("POW first argument must be a number: ", JSON.stringify(node, null, 2)));
|
|
694
|
+
}
|
|
695
|
+
if (isNaN(+val2)) {
|
|
696
|
+
err = err.concat(error("POW second argument must be a number: ", JSON.stringify(node, null, 2)));
|
|
697
|
+
}
|
|
698
|
+
resume([...err, `Error in POW operation: ${e.message}`], NaN);
|
|
643
699
|
}
|
|
644
|
-
|
|
645
|
-
|
|
700
|
+
});
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
MOD(node, options, resume) {
|
|
704
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
705
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
706
|
+
let err = [].concat(err1).concat(err2);
|
|
707
|
+
try {
|
|
708
|
+
const val = new Decimal(val1).mod(new Decimal(val2)).toNumber();
|
|
709
|
+
resume(err, val);
|
|
710
|
+
} catch (e) {
|
|
711
|
+
if (isNaN(+val1)) {
|
|
712
|
+
err = err.concat(error("MOD first argument must be a number: ", JSON.stringify(node, null, 2)));
|
|
713
|
+
}
|
|
714
|
+
if (isNaN(+val2)) {
|
|
715
|
+
err = err.concat(error("MOD second argument must be a number: ", JSON.stringify(node, null, 2)));
|
|
716
|
+
}
|
|
717
|
+
resume([...err, `Error in MOD operation: ${e.message}`], NaN);
|
|
646
718
|
}
|
|
647
|
-
const err = [].concat(err1).concat(err2);
|
|
648
|
-
const val = node;
|
|
649
|
-
resume(err, val);
|
|
650
719
|
});
|
|
651
720
|
});
|
|
652
721
|
}
|
|
@@ -848,6 +917,22 @@ export class Transformer extends Visitor {
|
|
|
848
917
|
});
|
|
849
918
|
});
|
|
850
919
|
}
|
|
920
|
+
SET(node, options, resume) {
|
|
921
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
922
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
923
|
+
this.visit(node.elts[2], options, (e2, v2) => {
|
|
924
|
+
const err = [...e0, ...e1];
|
|
925
|
+
assert(typeof v0 === "object", "Type Error: expected v0 to be an object.");
|
|
926
|
+
assert(typeof v1 === "string", "Type Error: expected v1 to be a string.");
|
|
927
|
+
const val = {
|
|
928
|
+
...v0,
|
|
929
|
+
[v1]: v2,
|
|
930
|
+
};
|
|
931
|
+
resume(err, val);
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
});
|
|
935
|
+
}
|
|
851
936
|
NTH(node, options, resume) {
|
|
852
937
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
853
938
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
@@ -868,6 +953,57 @@ export class Transformer extends Visitor {
|
|
|
868
953
|
resume(err, val);
|
|
869
954
|
})
|
|
870
955
|
}
|
|
956
|
+
EQ(node, options, resume) {
|
|
957
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
958
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
959
|
+
const err = [].concat(e0).concat(e1);
|
|
960
|
+
try {
|
|
961
|
+
const val = new Decimal(v0).equals(new Decimal(v1));
|
|
962
|
+
resume(err, val);
|
|
963
|
+
} catch (e) {
|
|
964
|
+
resume([...err, `Error in EQ operation: ${e.message}`], false);
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
RANGE(node, options, resume) {
|
|
970
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
971
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
972
|
+
this.visit(node.elts[2], options, (e2, v2) => {
|
|
973
|
+
const err = [].concat(e0).concat(e1).concat(e2);
|
|
974
|
+
try {
|
|
975
|
+
const start = new Decimal(v0);
|
|
976
|
+
const end = new Decimal(v1);
|
|
977
|
+
const step = new Decimal(v2);
|
|
978
|
+
|
|
979
|
+
if (step.isZero()) {
|
|
980
|
+
resume([...err, 'Error in RANGE operation: step cannot be zero'], []);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
const result = [];
|
|
985
|
+
let current = start;
|
|
986
|
+
|
|
987
|
+
if (step.isPositive()) {
|
|
988
|
+
while (current.lessThan(end)) {
|
|
989
|
+
result.push(current.toNumber());
|
|
990
|
+
current = current.plus(step);
|
|
991
|
+
}
|
|
992
|
+
} else {
|
|
993
|
+
while (current.greaterThan(end)) {
|
|
994
|
+
result.push(current.toNumber());
|
|
995
|
+
current = current.plus(step);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
resume(err, result);
|
|
1000
|
+
} catch (e) {
|
|
1001
|
+
resume([...err, `Error in RANGE operation: ${e.message}`], []);
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
});
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
871
1007
|
}
|
|
872
1008
|
|
|
873
1009
|
export class Renderer {
|