mlogjs 0.5.0 → 0.5.2
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/dist/Compiler.d.ts +2 -0
- package/dist/index.cjs +96 -51
- package/dist/index.mjs +96 -51
- package/dist/macros/DynamicArray.d.ts +3 -0
- package/dist/macros/Function.d.ts +3 -1
- package/dist/types.d.ts +5 -0
- package/dist/utils/value.d.ts +1 -0
- package/dist/values/AssignmentValue.d.ts +1 -0
- package/dist/values/VoidValue.d.ts +1 -0
- package/lib/commands.d.ts +2 -0
- package/lib/helpers.d.ts +3 -3
- package/package.json +1 -1
package/dist/Compiler.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare class Compiler {
|
|
|
22
22
|
protected parse(script: string): import("@babel/parser").ParseResult<es.File>;
|
|
23
23
|
protected mapSources(valueInst: TValueInstructions<IValue | null>): es.SourceLocation[];
|
|
24
24
|
handle(scope: IScope, node: es.Node, handler?: THandler<IValue | null> | undefined, out?: TEOutput): TValueInstructions<IValue | null>;
|
|
25
|
+
/** Handles the node and asserts that it resolves to a value. */
|
|
26
|
+
handleValue(scope: IScope, node: es.Node, handler?: THandler<IValue | null> | undefined, out?: TEOutput): TValueInstructions;
|
|
25
27
|
handleEval(scope: IScope, node: es.Node, out?: TEOutput): TValueInstructions;
|
|
26
28
|
/**
|
|
27
29
|
* Handles many nodes in order.
|
package/dist/index.cjs
CHANGED
|
@@ -230,6 +230,9 @@ class VoidValue {
|
|
|
230
230
|
return;
|
|
231
231
|
}
|
|
232
232
|
postCall(_scope) { }
|
|
233
|
+
toOut() {
|
|
234
|
+
return this;
|
|
235
|
+
}
|
|
233
236
|
debugString() {
|
|
234
237
|
return "VoidValue";
|
|
235
238
|
}
|
|
@@ -403,8 +406,8 @@ function extractOutName(out) {
|
|
|
403
406
|
return out.name;
|
|
404
407
|
}
|
|
405
408
|
function extractDestrucuringOut(out, field) {
|
|
406
|
-
if (out
|
|
407
|
-
return
|
|
409
|
+
if (isDiscardedOut(out))
|
|
410
|
+
return discardedName;
|
|
408
411
|
if (!(out instanceof DestructuringValue))
|
|
409
412
|
return;
|
|
410
413
|
return out.fields[field] ?? discardedName;
|
|
@@ -459,6 +462,13 @@ function assertObjectFields(value, fields) {
|
|
|
459
462
|
}
|
|
460
463
|
return result;
|
|
461
464
|
}
|
|
465
|
+
function isDiscardedOut(out) {
|
|
466
|
+
if (!out)
|
|
467
|
+
return false;
|
|
468
|
+
if (typeof out === "string")
|
|
469
|
+
return out === discardedName;
|
|
470
|
+
return out.name === discardedName;
|
|
471
|
+
}
|
|
462
472
|
|
|
463
473
|
class SetInstruction extends InstructionBase {
|
|
464
474
|
constructor(store, value) {
|
|
@@ -540,7 +550,7 @@ class JumpInstruction extends InstructionBase {
|
|
|
540
550
|
if (test === out)
|
|
541
551
|
return [];
|
|
542
552
|
return [
|
|
543
|
-
new JumpInstruction(out.address, EJumpKind.Equal, test, new LiteralValue(
|
|
553
|
+
new JumpInstruction(out.address, out.whenTrue ? EJumpKind.NotEqual : EJumpKind.Equal, test, new LiteralValue(0)),
|
|
544
554
|
];
|
|
545
555
|
}
|
|
546
556
|
}
|
|
@@ -642,8 +652,11 @@ class BaseValue extends VoidValue {
|
|
|
642
652
|
];
|
|
643
653
|
}
|
|
644
654
|
"u+"(scope, out) {
|
|
645
|
-
|
|
646
|
-
|
|
655
|
+
const inst = [];
|
|
656
|
+
const value = pipeInsts(this.eval(scope), inst);
|
|
657
|
+
const zero = new LiteralValue(0);
|
|
658
|
+
const result = pipeInsts(zero["+"](scope, value, out), inst);
|
|
659
|
+
return [result, inst];
|
|
647
660
|
}
|
|
648
661
|
"!"(scope, out) {
|
|
649
662
|
const inst = [];
|
|
@@ -665,7 +678,7 @@ class BaseValue extends VoidValue {
|
|
|
665
678
|
const endAdress = new LiteralValue(null);
|
|
666
679
|
const [left, leftInst] = this.eval(scope, result);
|
|
667
680
|
const [right, rightInst] = other.eval(scope, result);
|
|
668
|
-
const [test, testInst] =
|
|
681
|
+
const [test, testInst] = left["==="](scope, nullLiteral);
|
|
669
682
|
return [
|
|
670
683
|
result,
|
|
671
684
|
[
|
|
@@ -730,7 +743,7 @@ const assignmentToBinary = {
|
|
|
730
743
|
for (const k in assignmentToBinary) {
|
|
731
744
|
const op = k;
|
|
732
745
|
BaseValue.prototype[op] = function (scope, value) {
|
|
733
|
-
const [opValue, opInst] = this[assignmentToBinary[op]](scope, value, this);
|
|
746
|
+
const [opValue, opInst] = this[assignmentToBinary[op]](scope, value, this.toOut());
|
|
734
747
|
const [retValue, retInst] = this["="](scope, opValue);
|
|
735
748
|
return [retValue, [...opInst, ...retInst]];
|
|
736
749
|
};
|
|
@@ -738,9 +751,10 @@ for (const k in assignmentToBinary) {
|
|
|
738
751
|
for (const key of updateOperators) {
|
|
739
752
|
BaseValue.prototype[key] = function (scope, prefix, out) {
|
|
740
753
|
let [ret, inst] = this.eval(scope);
|
|
741
|
-
if (!prefix && out
|
|
754
|
+
if (!prefix && !isDiscardedOut(out)) {
|
|
742
755
|
const temp = StoreValue.from(scope, out);
|
|
743
|
-
|
|
756
|
+
pipeInsts(temp["="](scope, ret), inst);
|
|
757
|
+
ret = temp;
|
|
744
758
|
}
|
|
745
759
|
const kind = key === "++" ? "+=" : "-=";
|
|
746
760
|
pipeInsts(this[kind](scope, new LiteralValue(1)), inst);
|
|
@@ -897,7 +911,7 @@ class StoreValue extends BaseValue {
|
|
|
897
911
|
const [evalValue, evalInst] = value.eval(scope, this);
|
|
898
912
|
if (evalValue.macro)
|
|
899
913
|
throw new CompilerError(`Cannot assign a macro to a store (attempted to assign [${evalValue.debugString()}] to [${this.debugString()}])`);
|
|
900
|
-
return [
|
|
914
|
+
return [evalValue, [...evalInst, new SetInstruction(this, evalValue)]];
|
|
901
915
|
}
|
|
902
916
|
"=="(scope, value, out) {
|
|
903
917
|
if (compareStores(this, value))
|
|
@@ -1160,10 +1174,13 @@ class AssignmentValue extends VoidValue {
|
|
|
1160
1174
|
}
|
|
1161
1175
|
"="(scope, value, out) {
|
|
1162
1176
|
const inst = [];
|
|
1163
|
-
const input = pipeInsts(value["??"](scope, this.right, this.left), inst);
|
|
1177
|
+
const input = pipeInsts(value["??"](scope, this.right, this.left.toOut()), inst);
|
|
1164
1178
|
const output = pipeInsts(this.left["="](scope, input, out), inst);
|
|
1165
1179
|
return [output, inst];
|
|
1166
1180
|
}
|
|
1181
|
+
toOut() {
|
|
1182
|
+
return this.left.toOut();
|
|
1183
|
+
}
|
|
1167
1184
|
debugString() {
|
|
1168
1185
|
return "AssignmentValue";
|
|
1169
1186
|
}
|
|
@@ -1495,22 +1512,22 @@ const LogicalExpression = (c, scope, node, out) => {
|
|
|
1495
1512
|
if (node.operator !== "??")
|
|
1496
1513
|
return LRExpression(c, scope, node, out);
|
|
1497
1514
|
const other = new LazyValue((scope, out) => c.handleEval(scope, node.right, out));
|
|
1498
|
-
const [left, leftInst] = c.
|
|
1515
|
+
const [left, leftInst] = c.handleValue(scope, node.left);
|
|
1499
1516
|
const [result, resultInst] = left["??"](scope, other, out);
|
|
1500
1517
|
return [result, [...leftInst, ...resultInst]];
|
|
1501
1518
|
};
|
|
1502
1519
|
const AssignmentExpression = (c, scope, node) => {
|
|
1503
|
-
const [left, leftInst] = c.
|
|
1520
|
+
const [left, leftInst] = c.handleValue(scope, node.left);
|
|
1521
|
+
const leftOutput = left.toOut();
|
|
1504
1522
|
const [right, rightInst] = node.operator !== "??="
|
|
1505
|
-
? c.handleEval(scope, node.right, node.operator === "="
|
|
1523
|
+
? c.handleEval(scope, node.right, node.operator === "=" ? leftOutput : undefined)
|
|
1506
1524
|
: [
|
|
1507
1525
|
new LazyValue((scope, out) => c.handleEval(scope, node.right, out)),
|
|
1508
1526
|
[],
|
|
1509
1527
|
];
|
|
1510
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1511
1528
|
const [op, opInst] = left[node.operator](scope, right);
|
|
1512
|
-
|
|
1513
|
-
|
|
1529
|
+
scope.clearDependentCache(left);
|
|
1530
|
+
scope.clearDependentCache(leftOutput);
|
|
1514
1531
|
return [op, [...leftInst, ...rightInst, ...opInst]];
|
|
1515
1532
|
};
|
|
1516
1533
|
const UnaryExpression = (c, scope, { argument, operator }, out) => {
|
|
@@ -1526,10 +1543,8 @@ const UnaryExpression = (c, scope, { argument, operator }, out) => {
|
|
|
1526
1543
|
return [op, [...argInst, ...opInst]];
|
|
1527
1544
|
};
|
|
1528
1545
|
const UpdateExpression = (c, scope, { argument, operator, prefix }, out) => {
|
|
1529
|
-
const [arg, argInst] = c.
|
|
1530
|
-
|
|
1531
|
-
scope.clearDependentCache(arg);
|
|
1532
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1546
|
+
const [arg, argInst] = c.handleValue(scope, argument);
|
|
1547
|
+
scope.clearDependentCache(arg);
|
|
1533
1548
|
const [op, opInst] = arg[operator](scope, prefix, out);
|
|
1534
1549
|
return [op, [...argInst, ...opInst]];
|
|
1535
1550
|
};
|
|
@@ -1679,7 +1694,9 @@ function asMergeableJumpNode(body) {
|
|
|
1679
1694
|
if (body.type === "ContinueStatement" || body.type === "BreakStatement")
|
|
1680
1695
|
return body;
|
|
1681
1696
|
if (body.type !== "BlockStatement")
|
|
1682
|
-
return
|
|
1697
|
+
return;
|
|
1698
|
+
if (body.body.length == 0)
|
|
1699
|
+
return;
|
|
1683
1700
|
return asMergeableJumpNode(body.body[0]);
|
|
1684
1701
|
}
|
|
1685
1702
|
|
|
@@ -1961,7 +1978,7 @@ class FunctionValue extends VoidValue {
|
|
|
1961
1978
|
for (let i = 0; i < this.params.length; i++) {
|
|
1962
1979
|
const value = this.unwrapParameter(this.params[i]);
|
|
1963
1980
|
this.paramValues.push(value);
|
|
1964
|
-
this.paramOuts.push(value
|
|
1981
|
+
this.paramOuts.push(value.toOut());
|
|
1965
1982
|
if (!(value instanceof AssignmentValue))
|
|
1966
1983
|
this.minimumArgumentCount = i + 1;
|
|
1967
1984
|
}
|
|
@@ -2133,7 +2150,7 @@ class FunctionValue extends VoidValue {
|
|
|
2133
2150
|
const hasDefault = value instanceof AssignmentValue;
|
|
2134
2151
|
this.destructuringKeyData.set(key, { inst: propInst, value });
|
|
2135
2152
|
members.set(key, {
|
|
2136
|
-
value:
|
|
2153
|
+
value: value.toOut(),
|
|
2137
2154
|
handler: (get, propExists, scope) => {
|
|
2138
2155
|
return this.c.handle(scope, prop, () => {
|
|
2139
2156
|
const inst = [...propInst];
|
|
@@ -2164,7 +2181,7 @@ class FunctionValue extends VoidValue {
|
|
|
2164
2181
|
const key = new LiteralValue(i);
|
|
2165
2182
|
this.destructuringKeyData.set(key, { inst: [], value });
|
|
2166
2183
|
members.set(key, {
|
|
2167
|
-
value:
|
|
2184
|
+
value: value.toOut(),
|
|
2168
2185
|
handler: (get, propExists, scope) => {
|
|
2169
2186
|
return this.c.handle(scope, element, () => {
|
|
2170
2187
|
if (propExists() || !hasDefault) {
|
|
@@ -2379,12 +2396,10 @@ const ArrayPattern = (c, scope, node) => {
|
|
|
2379
2396
|
const element = node.elements[i];
|
|
2380
2397
|
if (!element)
|
|
2381
2398
|
continue;
|
|
2382
|
-
const value = pipeInsts(c.
|
|
2399
|
+
const value = pipeInsts(c.handleValue(scope, element), inst);
|
|
2383
2400
|
const hasDefault = value instanceof AssignmentValue;
|
|
2384
|
-
if (!value)
|
|
2385
|
-
throw new CompilerError("Destructuring element must resolve to a value", element);
|
|
2386
2401
|
members.set(new LiteralValue(i), {
|
|
2387
|
-
value:
|
|
2402
|
+
value: value.toOut(),
|
|
2388
2403
|
handler(get, propExists, scope) {
|
|
2389
2404
|
return c.handle(scope, element, () => {
|
|
2390
2405
|
if (propExists() || !hasDefault) {
|
|
@@ -2412,12 +2427,10 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
2412
2427
|
const [key, keyInst] = propKey.type === "Identifier" && !prop.computed
|
|
2413
2428
|
? [new LiteralValue(propKey.name), []]
|
|
2414
2429
|
: c.handleEval(scope, propKey);
|
|
2415
|
-
const value = pipeInsts(c.
|
|
2430
|
+
const value = pipeInsts(c.handleValue(scope, prop.value), inst);
|
|
2416
2431
|
const hasDefault = value instanceof AssignmentValue;
|
|
2417
|
-
if (!value)
|
|
2418
|
-
throw new CompilerError("Destructuring member must resolve to a value", prop.value);
|
|
2419
2432
|
members.set(key, {
|
|
2420
|
-
value:
|
|
2433
|
+
value: value.toOut(),
|
|
2421
2434
|
handler(get, propExists, scope) {
|
|
2422
2435
|
return c.handle(scope, prop, () => {
|
|
2423
2436
|
const inst = keyInst;
|
|
@@ -2438,9 +2451,7 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
2438
2451
|
// the mlog runtime already does this check for us
|
|
2439
2452
|
const OptionalMemberExpression = (c, scope, node, out) => MemberExpression(c, scope, node, out, true);
|
|
2440
2453
|
const AssignmentPattern = (c, scope, node) => {
|
|
2441
|
-
const [left, inst] = c.
|
|
2442
|
-
if (!left)
|
|
2443
|
-
throw new CompilerError("Left side of assignment pattern could not be resolved", node.left);
|
|
2454
|
+
const [left, inst] = c.handleValue(scope, node.left);
|
|
2444
2455
|
const right = new LazyValue((_, out) => c.handleEval(scope, node.right, out));
|
|
2445
2456
|
return [new AssignmentValue(left, right), inst];
|
|
2446
2457
|
};
|
|
@@ -2555,8 +2566,9 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
2555
2566
|
});
|
|
2556
2567
|
|
|
2557
2568
|
class MacroFunction extends VoidValue {
|
|
2558
|
-
constructor(fn) {
|
|
2569
|
+
constructor(fn, paramOuts) {
|
|
2559
2570
|
super();
|
|
2571
|
+
this.paramOuts = paramOuts;
|
|
2560
2572
|
this.macro = true;
|
|
2561
2573
|
this.mutability = EMutability.constant;
|
|
2562
2574
|
this.fn = fn;
|
|
@@ -2567,6 +2579,9 @@ class MacroFunction extends VoidValue {
|
|
|
2567
2579
|
eval(_scope) {
|
|
2568
2580
|
return [this, []];
|
|
2569
2581
|
}
|
|
2582
|
+
preCall(_scope, _out) {
|
|
2583
|
+
return this.paramOuts;
|
|
2584
|
+
}
|
|
2570
2585
|
debugString() {
|
|
2571
2586
|
return "MacroFunction";
|
|
2572
2587
|
}
|
|
@@ -2676,7 +2691,10 @@ class Concat extends MacroFunction {
|
|
|
2676
2691
|
const [first] = values;
|
|
2677
2692
|
if (!isTemplateObjectArray(first)) {
|
|
2678
2693
|
assertLiterals(values, "Concat arguments must be all literal values");
|
|
2679
|
-
|
|
2694
|
+
let text = "";
|
|
2695
|
+
for (const value of values)
|
|
2696
|
+
text += value.data;
|
|
2697
|
+
return [new LiteralValue(text), []];
|
|
2680
2698
|
}
|
|
2681
2699
|
let text = "";
|
|
2682
2700
|
const [, ...interpolated] = values;
|
|
@@ -3594,24 +3612,28 @@ class VarsNamespace extends NamespaceMacro {
|
|
|
3594
3612
|
const itemSize = 2;
|
|
3595
3613
|
class DynamicArray extends ObjectValue {
|
|
3596
3614
|
constructor(scope, name, values, dynamic) {
|
|
3597
|
-
const getterName = `${name}.&
|
|
3598
|
-
const setterName = `${name}.&
|
|
3615
|
+
const getterName = `${name}.&read`;
|
|
3616
|
+
const setterName = `${name}.&write`;
|
|
3599
3617
|
const returnName = `${name}.&rt`;
|
|
3600
3618
|
const lengthName = getLengthName(name);
|
|
3601
3619
|
const lengthStore = new StoreValue(lengthName);
|
|
3602
3620
|
const sizeValue = new LiteralValue(values.length);
|
|
3603
3621
|
super({
|
|
3604
|
-
// array[index]
|
|
3605
3622
|
fill: new MacroFunction((scope, out, value) => {
|
|
3623
|
+
if (!value)
|
|
3624
|
+
throw new CompilerError("Missing argument: value");
|
|
3625
|
+
this.initFill();
|
|
3606
3626
|
const inst = [];
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3627
|
+
const returnAddress = new LiteralValue(null);
|
|
3628
|
+
pipeInsts(values[0]["="](scope, value), inst);
|
|
3629
|
+
pipeInsts(this.returnTemp["="](scope, returnAddress), inst);
|
|
3630
|
+
inst.push(new JumpInstruction(this.fillAddr, EJumpKind.Always));
|
|
3631
|
+
inst.push(new AddressResolver(returnAddress));
|
|
3610
3632
|
if (this.lengthStore) {
|
|
3611
3633
|
pipeInsts(this.lengthStore["="](scope, new LiteralValue(values.length)), inst);
|
|
3612
3634
|
}
|
|
3613
3635
|
return [null, inst];
|
|
3614
|
-
}),
|
|
3636
|
+
}, [values[0]]),
|
|
3615
3637
|
at: new MacroFunction((scope, out, index) => {
|
|
3616
3638
|
const inst = [];
|
|
3617
3639
|
const isLiteral = index instanceof LiteralValue;
|
|
@@ -3652,7 +3674,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3652
3674
|
});
|
|
3653
3675
|
const [, inst] = entry["="](scope, item);
|
|
3654
3676
|
return [new LiteralValue(null), inst];
|
|
3655
|
-
}),
|
|
3677
|
+
}, [setterName]),
|
|
3656
3678
|
pop: new MacroFunction((scope, out) => {
|
|
3657
3679
|
const checked = scope.checkIndexes;
|
|
3658
3680
|
const inst = [];
|
|
@@ -3667,7 +3689,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3667
3689
|
failAddress,
|
|
3668
3690
|
});
|
|
3669
3691
|
const nullLiteral = new LiteralValue(null);
|
|
3670
|
-
const hasOut = out
|
|
3692
|
+
const hasOut = !isDiscardedOut(out);
|
|
3671
3693
|
const result = hasOut
|
|
3672
3694
|
? pipeInsts(entry.eval(scope, out), inst)
|
|
3673
3695
|
: nullLiteral;
|
|
@@ -3686,7 +3708,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3686
3708
|
assertBounds(index, 0, values.length - 1);
|
|
3687
3709
|
}
|
|
3688
3710
|
const checked = scope.checkIndexes;
|
|
3689
|
-
const hasOut = out
|
|
3711
|
+
const hasOut = !isDiscardedOut(out);
|
|
3690
3712
|
const { returnTemp } = this;
|
|
3691
3713
|
const inst = [];
|
|
3692
3714
|
let result = new LiteralValue(null);
|
|
@@ -3736,6 +3758,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3736
3758
|
this.bundledSetter = false;
|
|
3737
3759
|
this.bundledGetter = false;
|
|
3738
3760
|
this.bundledRemoveAt = false;
|
|
3761
|
+
this.bundledFill = false;
|
|
3739
3762
|
this.scope = scope;
|
|
3740
3763
|
this.name = name;
|
|
3741
3764
|
this.values = values;
|
|
@@ -3747,6 +3770,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3747
3770
|
this.getterAddr = new LiteralValue(null);
|
|
3748
3771
|
this.setterAddr = new LiteralValue(null);
|
|
3749
3772
|
this.removeAtAddr = new LiteralValue(null);
|
|
3773
|
+
this.fillAddr = new LiteralValue(null);
|
|
3750
3774
|
}
|
|
3751
3775
|
get(scope, index, out) {
|
|
3752
3776
|
if (super.hasProperty(scope, index))
|
|
@@ -3806,6 +3830,19 @@ class DynamicArray extends ObjectValue {
|
|
|
3806
3830
|
pipeInsts(last["="](this.scope, new LiteralValue(null)), inst);
|
|
3807
3831
|
inst.push(new SetCounterInstruction(this.returnTemp));
|
|
3808
3832
|
}
|
|
3833
|
+
initFill() {
|
|
3834
|
+
if (this.bundledFill)
|
|
3835
|
+
return;
|
|
3836
|
+
this.bundledFill = true;
|
|
3837
|
+
const { inst } = this.scope;
|
|
3838
|
+
inst.push(new AddressResolver(this.fillAddr));
|
|
3839
|
+
const firstValue = this.values[0];
|
|
3840
|
+
for (let i = 1; i < this.values.length; i++) {
|
|
3841
|
+
const value = this.values[i];
|
|
3842
|
+
pipeInsts(value["="](this.scope, firstValue), inst);
|
|
3843
|
+
}
|
|
3844
|
+
inst.push(new SetCounterInstruction(this.returnTemp));
|
|
3845
|
+
}
|
|
3809
3846
|
debugString() {
|
|
3810
3847
|
const id = this.dynamic ? "DynamicArray" : "MutableArray";
|
|
3811
3848
|
return `${id}("${this.name}")`;
|
|
@@ -3905,6 +3942,9 @@ class DynamicArrayEntry extends BaseValue {
|
|
|
3905
3942
|
inst.push(new AddressResolver(failAddress));
|
|
3906
3943
|
return [value, inst];
|
|
3907
3944
|
}
|
|
3945
|
+
toOut() {
|
|
3946
|
+
return this.array.setterTemp;
|
|
3947
|
+
}
|
|
3908
3948
|
debugString() {
|
|
3909
3949
|
const name = this.array.dynamic ? "DynamicArray" : "MutableArray";
|
|
3910
3950
|
return `${name}Entry`;
|
|
@@ -4191,10 +4231,15 @@ class Compiler {
|
|
|
4191
4231
|
throw error;
|
|
4192
4232
|
}
|
|
4193
4233
|
}
|
|
4234
|
+
/** Handles the node and asserts that it resolves to a value. */
|
|
4235
|
+
handleValue(scope, node, handler = this.handlers[node.type], out) {
|
|
4236
|
+
const result = this.handle(scope, node, handler, out);
|
|
4237
|
+
if (!result[0])
|
|
4238
|
+
throw new CompilerError(`This node (${node.type}) did not return a value`, node);
|
|
4239
|
+
return result;
|
|
4240
|
+
}
|
|
4194
4241
|
handleEval(scope, node, out) {
|
|
4195
|
-
const [res, inst] = this.
|
|
4196
|
-
if (!res)
|
|
4197
|
-
throw new CompilerError(`This node (${node.type}) does not return a value`, node);
|
|
4242
|
+
const [res, inst] = this.handleValue(scope, node, undefined, out);
|
|
4198
4243
|
const [evaluated, evaluatedInst] = res.eval(scope, out);
|
|
4199
4244
|
const result = [evaluated, [...inst, ...evaluatedInst]];
|
|
4200
4245
|
if (this.sourcemap)
|
package/dist/index.mjs
CHANGED
|
@@ -209,6 +209,9 @@ class VoidValue {
|
|
|
209
209
|
return;
|
|
210
210
|
}
|
|
211
211
|
postCall(_scope) { }
|
|
212
|
+
toOut() {
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
212
215
|
debugString() {
|
|
213
216
|
return "VoidValue";
|
|
214
217
|
}
|
|
@@ -382,8 +385,8 @@ function extractOutName(out) {
|
|
|
382
385
|
return out.name;
|
|
383
386
|
}
|
|
384
387
|
function extractDestrucuringOut(out, field) {
|
|
385
|
-
if (out
|
|
386
|
-
return
|
|
388
|
+
if (isDiscardedOut(out))
|
|
389
|
+
return discardedName;
|
|
387
390
|
if (!(out instanceof DestructuringValue))
|
|
388
391
|
return;
|
|
389
392
|
return out.fields[field] ?? discardedName;
|
|
@@ -438,6 +441,13 @@ function assertObjectFields(value, fields) {
|
|
|
438
441
|
}
|
|
439
442
|
return result;
|
|
440
443
|
}
|
|
444
|
+
function isDiscardedOut(out) {
|
|
445
|
+
if (!out)
|
|
446
|
+
return false;
|
|
447
|
+
if (typeof out === "string")
|
|
448
|
+
return out === discardedName;
|
|
449
|
+
return out.name === discardedName;
|
|
450
|
+
}
|
|
441
451
|
|
|
442
452
|
class SetInstruction extends InstructionBase {
|
|
443
453
|
constructor(store, value) {
|
|
@@ -519,7 +529,7 @@ class JumpInstruction extends InstructionBase {
|
|
|
519
529
|
if (test === out)
|
|
520
530
|
return [];
|
|
521
531
|
return [
|
|
522
|
-
new JumpInstruction(out.address, EJumpKind.Equal, test, new LiteralValue(
|
|
532
|
+
new JumpInstruction(out.address, out.whenTrue ? EJumpKind.NotEqual : EJumpKind.Equal, test, new LiteralValue(0)),
|
|
523
533
|
];
|
|
524
534
|
}
|
|
525
535
|
}
|
|
@@ -621,8 +631,11 @@ class BaseValue extends VoidValue {
|
|
|
621
631
|
];
|
|
622
632
|
}
|
|
623
633
|
"u+"(scope, out) {
|
|
624
|
-
|
|
625
|
-
|
|
634
|
+
const inst = [];
|
|
635
|
+
const value = pipeInsts(this.eval(scope), inst);
|
|
636
|
+
const zero = new LiteralValue(0);
|
|
637
|
+
const result = pipeInsts(zero["+"](scope, value, out), inst);
|
|
638
|
+
return [result, inst];
|
|
626
639
|
}
|
|
627
640
|
"!"(scope, out) {
|
|
628
641
|
const inst = [];
|
|
@@ -644,7 +657,7 @@ class BaseValue extends VoidValue {
|
|
|
644
657
|
const endAdress = new LiteralValue(null);
|
|
645
658
|
const [left, leftInst] = this.eval(scope, result);
|
|
646
659
|
const [right, rightInst] = other.eval(scope, result);
|
|
647
|
-
const [test, testInst] =
|
|
660
|
+
const [test, testInst] = left["==="](scope, nullLiteral);
|
|
648
661
|
return [
|
|
649
662
|
result,
|
|
650
663
|
[
|
|
@@ -709,7 +722,7 @@ const assignmentToBinary = {
|
|
|
709
722
|
for (const k in assignmentToBinary) {
|
|
710
723
|
const op = k;
|
|
711
724
|
BaseValue.prototype[op] = function (scope, value) {
|
|
712
|
-
const [opValue, opInst] = this[assignmentToBinary[op]](scope, value, this);
|
|
725
|
+
const [opValue, opInst] = this[assignmentToBinary[op]](scope, value, this.toOut());
|
|
713
726
|
const [retValue, retInst] = this["="](scope, opValue);
|
|
714
727
|
return [retValue, [...opInst, ...retInst]];
|
|
715
728
|
};
|
|
@@ -717,9 +730,10 @@ for (const k in assignmentToBinary) {
|
|
|
717
730
|
for (const key of updateOperators) {
|
|
718
731
|
BaseValue.prototype[key] = function (scope, prefix, out) {
|
|
719
732
|
let [ret, inst] = this.eval(scope);
|
|
720
|
-
if (!prefix && out
|
|
733
|
+
if (!prefix && !isDiscardedOut(out)) {
|
|
721
734
|
const temp = StoreValue.from(scope, out);
|
|
722
|
-
|
|
735
|
+
pipeInsts(temp["="](scope, ret), inst);
|
|
736
|
+
ret = temp;
|
|
723
737
|
}
|
|
724
738
|
const kind = key === "++" ? "+=" : "-=";
|
|
725
739
|
pipeInsts(this[kind](scope, new LiteralValue(1)), inst);
|
|
@@ -876,7 +890,7 @@ class StoreValue extends BaseValue {
|
|
|
876
890
|
const [evalValue, evalInst] = value.eval(scope, this);
|
|
877
891
|
if (evalValue.macro)
|
|
878
892
|
throw new CompilerError(`Cannot assign a macro to a store (attempted to assign [${evalValue.debugString()}] to [${this.debugString()}])`);
|
|
879
|
-
return [
|
|
893
|
+
return [evalValue, [...evalInst, new SetInstruction(this, evalValue)]];
|
|
880
894
|
}
|
|
881
895
|
"=="(scope, value, out) {
|
|
882
896
|
if (compareStores(this, value))
|
|
@@ -1139,10 +1153,13 @@ class AssignmentValue extends VoidValue {
|
|
|
1139
1153
|
}
|
|
1140
1154
|
"="(scope, value, out) {
|
|
1141
1155
|
const inst = [];
|
|
1142
|
-
const input = pipeInsts(value["??"](scope, this.right, this.left), inst);
|
|
1156
|
+
const input = pipeInsts(value["??"](scope, this.right, this.left.toOut()), inst);
|
|
1143
1157
|
const output = pipeInsts(this.left["="](scope, input, out), inst);
|
|
1144
1158
|
return [output, inst];
|
|
1145
1159
|
}
|
|
1160
|
+
toOut() {
|
|
1161
|
+
return this.left.toOut();
|
|
1162
|
+
}
|
|
1146
1163
|
debugString() {
|
|
1147
1164
|
return "AssignmentValue";
|
|
1148
1165
|
}
|
|
@@ -1474,22 +1491,22 @@ const LogicalExpression = (c, scope, node, out) => {
|
|
|
1474
1491
|
if (node.operator !== "??")
|
|
1475
1492
|
return LRExpression(c, scope, node, out);
|
|
1476
1493
|
const other = new LazyValue((scope, out) => c.handleEval(scope, node.right, out));
|
|
1477
|
-
const [left, leftInst] = c.
|
|
1494
|
+
const [left, leftInst] = c.handleValue(scope, node.left);
|
|
1478
1495
|
const [result, resultInst] = left["??"](scope, other, out);
|
|
1479
1496
|
return [result, [...leftInst, ...resultInst]];
|
|
1480
1497
|
};
|
|
1481
1498
|
const AssignmentExpression = (c, scope, node) => {
|
|
1482
|
-
const [left, leftInst] = c.
|
|
1499
|
+
const [left, leftInst] = c.handleValue(scope, node.left);
|
|
1500
|
+
const leftOutput = left.toOut();
|
|
1483
1501
|
const [right, rightInst] = node.operator !== "??="
|
|
1484
|
-
? c.handleEval(scope, node.right, node.operator === "="
|
|
1502
|
+
? c.handleEval(scope, node.right, node.operator === "=" ? leftOutput : undefined)
|
|
1485
1503
|
: [
|
|
1486
1504
|
new LazyValue((scope, out) => c.handleEval(scope, node.right, out)),
|
|
1487
1505
|
[],
|
|
1488
1506
|
];
|
|
1489
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1490
1507
|
const [op, opInst] = left[node.operator](scope, right);
|
|
1491
|
-
|
|
1492
|
-
|
|
1508
|
+
scope.clearDependentCache(left);
|
|
1509
|
+
scope.clearDependentCache(leftOutput);
|
|
1493
1510
|
return [op, [...leftInst, ...rightInst, ...opInst]];
|
|
1494
1511
|
};
|
|
1495
1512
|
const UnaryExpression = (c, scope, { argument, operator }, out) => {
|
|
@@ -1505,10 +1522,8 @@ const UnaryExpression = (c, scope, { argument, operator }, out) => {
|
|
|
1505
1522
|
return [op, [...argInst, ...opInst]];
|
|
1506
1523
|
};
|
|
1507
1524
|
const UpdateExpression = (c, scope, { argument, operator, prefix }, out) => {
|
|
1508
|
-
const [arg, argInst] = c.
|
|
1509
|
-
|
|
1510
|
-
scope.clearDependentCache(arg);
|
|
1511
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1525
|
+
const [arg, argInst] = c.handleValue(scope, argument);
|
|
1526
|
+
scope.clearDependentCache(arg);
|
|
1512
1527
|
const [op, opInst] = arg[operator](scope, prefix, out);
|
|
1513
1528
|
return [op, [...argInst, ...opInst]];
|
|
1514
1529
|
};
|
|
@@ -1658,7 +1673,9 @@ function asMergeableJumpNode(body) {
|
|
|
1658
1673
|
if (body.type === "ContinueStatement" || body.type === "BreakStatement")
|
|
1659
1674
|
return body;
|
|
1660
1675
|
if (body.type !== "BlockStatement")
|
|
1661
|
-
return
|
|
1676
|
+
return;
|
|
1677
|
+
if (body.body.length == 0)
|
|
1678
|
+
return;
|
|
1662
1679
|
return asMergeableJumpNode(body.body[0]);
|
|
1663
1680
|
}
|
|
1664
1681
|
|
|
@@ -1940,7 +1957,7 @@ class FunctionValue extends VoidValue {
|
|
|
1940
1957
|
for (let i = 0; i < this.params.length; i++) {
|
|
1941
1958
|
const value = this.unwrapParameter(this.params[i]);
|
|
1942
1959
|
this.paramValues.push(value);
|
|
1943
|
-
this.paramOuts.push(value
|
|
1960
|
+
this.paramOuts.push(value.toOut());
|
|
1944
1961
|
if (!(value instanceof AssignmentValue))
|
|
1945
1962
|
this.minimumArgumentCount = i + 1;
|
|
1946
1963
|
}
|
|
@@ -2112,7 +2129,7 @@ class FunctionValue extends VoidValue {
|
|
|
2112
2129
|
const hasDefault = value instanceof AssignmentValue;
|
|
2113
2130
|
this.destructuringKeyData.set(key, { inst: propInst, value });
|
|
2114
2131
|
members.set(key, {
|
|
2115
|
-
value:
|
|
2132
|
+
value: value.toOut(),
|
|
2116
2133
|
handler: (get, propExists, scope) => {
|
|
2117
2134
|
return this.c.handle(scope, prop, () => {
|
|
2118
2135
|
const inst = [...propInst];
|
|
@@ -2143,7 +2160,7 @@ class FunctionValue extends VoidValue {
|
|
|
2143
2160
|
const key = new LiteralValue(i);
|
|
2144
2161
|
this.destructuringKeyData.set(key, { inst: [], value });
|
|
2145
2162
|
members.set(key, {
|
|
2146
|
-
value:
|
|
2163
|
+
value: value.toOut(),
|
|
2147
2164
|
handler: (get, propExists, scope) => {
|
|
2148
2165
|
return this.c.handle(scope, element, () => {
|
|
2149
2166
|
if (propExists() || !hasDefault) {
|
|
@@ -2358,12 +2375,10 @@ const ArrayPattern = (c, scope, node) => {
|
|
|
2358
2375
|
const element = node.elements[i];
|
|
2359
2376
|
if (!element)
|
|
2360
2377
|
continue;
|
|
2361
|
-
const value = pipeInsts(c.
|
|
2378
|
+
const value = pipeInsts(c.handleValue(scope, element), inst);
|
|
2362
2379
|
const hasDefault = value instanceof AssignmentValue;
|
|
2363
|
-
if (!value)
|
|
2364
|
-
throw new CompilerError("Destructuring element must resolve to a value", element);
|
|
2365
2380
|
members.set(new LiteralValue(i), {
|
|
2366
|
-
value:
|
|
2381
|
+
value: value.toOut(),
|
|
2367
2382
|
handler(get, propExists, scope) {
|
|
2368
2383
|
return c.handle(scope, element, () => {
|
|
2369
2384
|
if (propExists() || !hasDefault) {
|
|
@@ -2391,12 +2406,10 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
2391
2406
|
const [key, keyInst] = propKey.type === "Identifier" && !prop.computed
|
|
2392
2407
|
? [new LiteralValue(propKey.name), []]
|
|
2393
2408
|
: c.handleEval(scope, propKey);
|
|
2394
|
-
const value = pipeInsts(c.
|
|
2409
|
+
const value = pipeInsts(c.handleValue(scope, prop.value), inst);
|
|
2395
2410
|
const hasDefault = value instanceof AssignmentValue;
|
|
2396
|
-
if (!value)
|
|
2397
|
-
throw new CompilerError("Destructuring member must resolve to a value", prop.value);
|
|
2398
2411
|
members.set(key, {
|
|
2399
|
-
value:
|
|
2412
|
+
value: value.toOut(),
|
|
2400
2413
|
handler(get, propExists, scope) {
|
|
2401
2414
|
return c.handle(scope, prop, () => {
|
|
2402
2415
|
const inst = keyInst;
|
|
@@ -2417,9 +2430,7 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
2417
2430
|
// the mlog runtime already does this check for us
|
|
2418
2431
|
const OptionalMemberExpression = (c, scope, node, out) => MemberExpression(c, scope, node, out, true);
|
|
2419
2432
|
const AssignmentPattern = (c, scope, node) => {
|
|
2420
|
-
const [left, inst] = c.
|
|
2421
|
-
if (!left)
|
|
2422
|
-
throw new CompilerError("Left side of assignment pattern could not be resolved", node.left);
|
|
2433
|
+
const [left, inst] = c.handleValue(scope, node.left);
|
|
2423
2434
|
const right = new LazyValue((_, out) => c.handleEval(scope, node.right, out));
|
|
2424
2435
|
return [new AssignmentValue(left, right), inst];
|
|
2425
2436
|
};
|
|
@@ -2534,8 +2545,9 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
2534
2545
|
});
|
|
2535
2546
|
|
|
2536
2547
|
class MacroFunction extends VoidValue {
|
|
2537
|
-
constructor(fn) {
|
|
2548
|
+
constructor(fn, paramOuts) {
|
|
2538
2549
|
super();
|
|
2550
|
+
this.paramOuts = paramOuts;
|
|
2539
2551
|
this.macro = true;
|
|
2540
2552
|
this.mutability = EMutability.constant;
|
|
2541
2553
|
this.fn = fn;
|
|
@@ -2546,6 +2558,9 @@ class MacroFunction extends VoidValue {
|
|
|
2546
2558
|
eval(_scope) {
|
|
2547
2559
|
return [this, []];
|
|
2548
2560
|
}
|
|
2561
|
+
preCall(_scope, _out) {
|
|
2562
|
+
return this.paramOuts;
|
|
2563
|
+
}
|
|
2549
2564
|
debugString() {
|
|
2550
2565
|
return "MacroFunction";
|
|
2551
2566
|
}
|
|
@@ -2655,7 +2670,10 @@ class Concat extends MacroFunction {
|
|
|
2655
2670
|
const [first] = values;
|
|
2656
2671
|
if (!isTemplateObjectArray(first)) {
|
|
2657
2672
|
assertLiterals(values, "Concat arguments must be all literal values");
|
|
2658
|
-
|
|
2673
|
+
let text = "";
|
|
2674
|
+
for (const value of values)
|
|
2675
|
+
text += value.data;
|
|
2676
|
+
return [new LiteralValue(text), []];
|
|
2659
2677
|
}
|
|
2660
2678
|
let text = "";
|
|
2661
2679
|
const [, ...interpolated] = values;
|
|
@@ -3573,24 +3591,28 @@ class VarsNamespace extends NamespaceMacro {
|
|
|
3573
3591
|
const itemSize = 2;
|
|
3574
3592
|
class DynamicArray extends ObjectValue {
|
|
3575
3593
|
constructor(scope, name, values, dynamic) {
|
|
3576
|
-
const getterName = `${name}.&
|
|
3577
|
-
const setterName = `${name}.&
|
|
3594
|
+
const getterName = `${name}.&read`;
|
|
3595
|
+
const setterName = `${name}.&write`;
|
|
3578
3596
|
const returnName = `${name}.&rt`;
|
|
3579
3597
|
const lengthName = getLengthName(name);
|
|
3580
3598
|
const lengthStore = new StoreValue(lengthName);
|
|
3581
3599
|
const sizeValue = new LiteralValue(values.length);
|
|
3582
3600
|
super({
|
|
3583
|
-
// array[index]
|
|
3584
3601
|
fill: new MacroFunction((scope, out, value) => {
|
|
3602
|
+
if (!value)
|
|
3603
|
+
throw new CompilerError("Missing argument: value");
|
|
3604
|
+
this.initFill();
|
|
3585
3605
|
const inst = [];
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3606
|
+
const returnAddress = new LiteralValue(null);
|
|
3607
|
+
pipeInsts(values[0]["="](scope, value), inst);
|
|
3608
|
+
pipeInsts(this.returnTemp["="](scope, returnAddress), inst);
|
|
3609
|
+
inst.push(new JumpInstruction(this.fillAddr, EJumpKind.Always));
|
|
3610
|
+
inst.push(new AddressResolver(returnAddress));
|
|
3589
3611
|
if (this.lengthStore) {
|
|
3590
3612
|
pipeInsts(this.lengthStore["="](scope, new LiteralValue(values.length)), inst);
|
|
3591
3613
|
}
|
|
3592
3614
|
return [null, inst];
|
|
3593
|
-
}),
|
|
3615
|
+
}, [values[0]]),
|
|
3594
3616
|
at: new MacroFunction((scope, out, index) => {
|
|
3595
3617
|
const inst = [];
|
|
3596
3618
|
const isLiteral = index instanceof LiteralValue;
|
|
@@ -3631,7 +3653,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3631
3653
|
});
|
|
3632
3654
|
const [, inst] = entry["="](scope, item);
|
|
3633
3655
|
return [new LiteralValue(null), inst];
|
|
3634
|
-
}),
|
|
3656
|
+
}, [setterName]),
|
|
3635
3657
|
pop: new MacroFunction((scope, out) => {
|
|
3636
3658
|
const checked = scope.checkIndexes;
|
|
3637
3659
|
const inst = [];
|
|
@@ -3646,7 +3668,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3646
3668
|
failAddress,
|
|
3647
3669
|
});
|
|
3648
3670
|
const nullLiteral = new LiteralValue(null);
|
|
3649
|
-
const hasOut = out
|
|
3671
|
+
const hasOut = !isDiscardedOut(out);
|
|
3650
3672
|
const result = hasOut
|
|
3651
3673
|
? pipeInsts(entry.eval(scope, out), inst)
|
|
3652
3674
|
: nullLiteral;
|
|
@@ -3665,7 +3687,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3665
3687
|
assertBounds(index, 0, values.length - 1);
|
|
3666
3688
|
}
|
|
3667
3689
|
const checked = scope.checkIndexes;
|
|
3668
|
-
const hasOut = out
|
|
3690
|
+
const hasOut = !isDiscardedOut(out);
|
|
3669
3691
|
const { returnTemp } = this;
|
|
3670
3692
|
const inst = [];
|
|
3671
3693
|
let result = new LiteralValue(null);
|
|
@@ -3715,6 +3737,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3715
3737
|
this.bundledSetter = false;
|
|
3716
3738
|
this.bundledGetter = false;
|
|
3717
3739
|
this.bundledRemoveAt = false;
|
|
3740
|
+
this.bundledFill = false;
|
|
3718
3741
|
this.scope = scope;
|
|
3719
3742
|
this.name = name;
|
|
3720
3743
|
this.values = values;
|
|
@@ -3726,6 +3749,7 @@ class DynamicArray extends ObjectValue {
|
|
|
3726
3749
|
this.getterAddr = new LiteralValue(null);
|
|
3727
3750
|
this.setterAddr = new LiteralValue(null);
|
|
3728
3751
|
this.removeAtAddr = new LiteralValue(null);
|
|
3752
|
+
this.fillAddr = new LiteralValue(null);
|
|
3729
3753
|
}
|
|
3730
3754
|
get(scope, index, out) {
|
|
3731
3755
|
if (super.hasProperty(scope, index))
|
|
@@ -3785,6 +3809,19 @@ class DynamicArray extends ObjectValue {
|
|
|
3785
3809
|
pipeInsts(last["="](this.scope, new LiteralValue(null)), inst);
|
|
3786
3810
|
inst.push(new SetCounterInstruction(this.returnTemp));
|
|
3787
3811
|
}
|
|
3812
|
+
initFill() {
|
|
3813
|
+
if (this.bundledFill)
|
|
3814
|
+
return;
|
|
3815
|
+
this.bundledFill = true;
|
|
3816
|
+
const { inst } = this.scope;
|
|
3817
|
+
inst.push(new AddressResolver(this.fillAddr));
|
|
3818
|
+
const firstValue = this.values[0];
|
|
3819
|
+
for (let i = 1; i < this.values.length; i++) {
|
|
3820
|
+
const value = this.values[i];
|
|
3821
|
+
pipeInsts(value["="](this.scope, firstValue), inst);
|
|
3822
|
+
}
|
|
3823
|
+
inst.push(new SetCounterInstruction(this.returnTemp));
|
|
3824
|
+
}
|
|
3788
3825
|
debugString() {
|
|
3789
3826
|
const id = this.dynamic ? "DynamicArray" : "MutableArray";
|
|
3790
3827
|
return `${id}("${this.name}")`;
|
|
@@ -3884,6 +3921,9 @@ class DynamicArrayEntry extends BaseValue {
|
|
|
3884
3921
|
inst.push(new AddressResolver(failAddress));
|
|
3885
3922
|
return [value, inst];
|
|
3886
3923
|
}
|
|
3924
|
+
toOut() {
|
|
3925
|
+
return this.array.setterTemp;
|
|
3926
|
+
}
|
|
3887
3927
|
debugString() {
|
|
3888
3928
|
const name = this.array.dynamic ? "DynamicArray" : "MutableArray";
|
|
3889
3929
|
return `${name}Entry`;
|
|
@@ -4170,10 +4210,15 @@ class Compiler {
|
|
|
4170
4210
|
throw error;
|
|
4171
4211
|
}
|
|
4172
4212
|
}
|
|
4213
|
+
/** Handles the node and asserts that it resolves to a value. */
|
|
4214
|
+
handleValue(scope, node, handler = this.handlers[node.type], out) {
|
|
4215
|
+
const result = this.handle(scope, node, handler, out);
|
|
4216
|
+
if (!result[0])
|
|
4217
|
+
throw new CompilerError(`This node (${node.type}) did not return a value`, node);
|
|
4218
|
+
return result;
|
|
4219
|
+
}
|
|
4173
4220
|
handleEval(scope, node, out) {
|
|
4174
|
-
const [res, inst] = this.
|
|
4175
|
-
if (!res)
|
|
4176
|
-
throw new CompilerError(`This node (${node.type}) does not return a value`, node);
|
|
4221
|
+
const [res, inst] = this.handleValue(scope, node, undefined, out);
|
|
4177
4222
|
const [evaluated, evaluatedInst] = res.eval(scope, out);
|
|
4178
4223
|
const result = [evaluated, [...inst, ...evaluatedInst]];
|
|
4179
4224
|
if (this.sourcemap)
|
|
@@ -12,16 +12,19 @@ export declare class DynamicArray extends ObjectValue {
|
|
|
12
12
|
getterAddr: LiteralValue<number | null>;
|
|
13
13
|
setterAddr: LiteralValue<number | null>;
|
|
14
14
|
removeAtAddr: LiteralValue<number | null>;
|
|
15
|
+
fillAddr: LiteralValue<number | null>;
|
|
15
16
|
lengthStore?: StoreValue;
|
|
16
17
|
bundledSetter: boolean;
|
|
17
18
|
bundledGetter: boolean;
|
|
18
19
|
bundledRemoveAt: boolean;
|
|
20
|
+
bundledFill: boolean;
|
|
19
21
|
constructor(scope: IScope, name: string, values: IValue[], dynamic: boolean);
|
|
20
22
|
get(scope: IScope, index: IValue, out?: TEOutput): TValueInstructions;
|
|
21
23
|
hasProperty(scope: IScope, prop: IValue): boolean;
|
|
22
24
|
initGetter(): void;
|
|
23
25
|
initSetter(): void;
|
|
24
26
|
initRemoveAt(): void;
|
|
27
|
+
initFill(): void;
|
|
25
28
|
debugString(): string;
|
|
26
29
|
toString(): string;
|
|
27
30
|
}
|
|
@@ -2,12 +2,14 @@ import { EMutability, IScope, IValue, TEOutput, TValueInstructions } from "../ty
|
|
|
2
2
|
import { VoidValue } from "../values";
|
|
3
3
|
type TFunction<T extends IValue | null> = (scope: IScope, out: TEOutput | undefined, ...args: IValue[]) => TValueInstructions<T>;
|
|
4
4
|
export declare class MacroFunction<RT extends IValue | null = IValue> extends VoidValue {
|
|
5
|
+
paramOuts?: TEOutput[] | undefined;
|
|
5
6
|
macro: boolean;
|
|
6
7
|
mutability: EMutability;
|
|
7
8
|
fn: TFunction<RT>;
|
|
8
|
-
constructor(fn: TFunction<RT
|
|
9
|
+
constructor(fn: TFunction<RT>, paramOuts?: TEOutput[] | undefined);
|
|
9
10
|
call(scope: IScope, args: IValue[], out?: TEOutput): TValueInstructions<RT>;
|
|
10
11
|
eval(_scope: IScope): TValueInstructions;
|
|
12
|
+
preCall(_scope: IScope, _out?: TEOutput | undefined): readonly TEOutput[] | undefined;
|
|
11
13
|
debugString(): string;
|
|
12
14
|
toString(): string;
|
|
13
15
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -236,6 +236,11 @@ export interface IValue extends IValueOperators {
|
|
|
236
236
|
postCall(scope: IScope): void;
|
|
237
237
|
/** The string representation of `this` in error messages. */
|
|
238
238
|
debugString(): string;
|
|
239
|
+
/**
|
|
240
|
+
* Allows some values to choose alternative representations
|
|
241
|
+
* when they are used as operation outputs.
|
|
242
|
+
*/
|
|
243
|
+
toOut(): IValue;
|
|
239
244
|
}
|
|
240
245
|
/** Helper type that is used in some typescript assertions */
|
|
241
246
|
export interface INamedValue extends IValue {
|
package/dist/utils/value.d.ts
CHANGED
|
@@ -38,3 +38,4 @@ export interface IParameterDescriptor {
|
|
|
38
38
|
}
|
|
39
39
|
/** Asserts that all of the fields described are present on `value`*/
|
|
40
40
|
export declare function assertObjectFields(value: ObjectValue, fields: (string | IParameterDescriptor)[]): (IValue | string)[];
|
|
41
|
+
export declare function isDiscardedOut(out: TEOutput | undefined): boolean;
|
|
@@ -9,6 +9,7 @@ export declare class VoidValue implements IValue {
|
|
|
9
9
|
hasProperty(_scope: IScope, _prop: IValue): boolean;
|
|
10
10
|
preCall(_scope: IScope, _out?: TEOutput): readonly TEOutput[] | undefined;
|
|
11
11
|
postCall(_scope: IScope): void;
|
|
12
|
+
toOut(): IValue;
|
|
12
13
|
debugString(): string;
|
|
13
14
|
toString(): string;
|
|
14
15
|
}
|
package/lib/commands.d.ts
CHANGED
package/lib/helpers.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ declare function getBuilding<T extends BasicBuilding = AnyBuilding>(
|
|
|
20
20
|
name: string
|
|
21
21
|
): T;
|
|
22
22
|
|
|
23
|
+
type ConcatLiteral = string | number | boolean | undefined;
|
|
24
|
+
|
|
23
25
|
/**
|
|
24
26
|
* Concatenates a list of constant literal values.
|
|
25
27
|
*
|
|
@@ -34,9 +36,7 @@ declare function getBuilding<T extends BasicBuilding = AnyBuilding>(
|
|
|
34
36
|
* ```
|
|
35
37
|
*/
|
|
36
38
|
declare function concat(
|
|
37
|
-
...args:
|
|
38
|
-
| (string | number | undefined)[]
|
|
39
|
-
| [TemplateStringsArray, ...(string | number | undefined)[]]
|
|
39
|
+
...args: ConcatLiteral[] | [TemplateStringsArray, ...ConcatLiteral[]]
|
|
40
40
|
): string;
|
|
41
41
|
|
|
42
42
|
/**
|