mlogjs 0.4.0 → 0.4.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/Scope.d.ts +1 -0
- package/dist/handlers/Statements.d.ts +1 -0
- package/dist/index.cjs +500 -350
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +500 -350
- package/dist/index.mjs.map +1 -1
- package/dist/instructions/SetInstruction.d.ts +2 -0
- package/dist/macros/Asm.d.ts +1 -2
- package/dist/macros/Function.d.ts +4 -4
- package/dist/macros/GetGlobal.d.ts +2 -2
- package/dist/macros/Memory.d.ts +1 -2
- package/dist/macros/Namespace.d.ts +1 -1
- package/dist/macros/Other.d.ts +1 -2
- package/dist/macros/commands/ApplyStatus.d.ts +1 -2
- package/dist/macros/commands/Control.d.ts +1 -2
- package/dist/macros/commands/Cutscene.d.ts +1 -2
- package/dist/macros/commands/Draw.d.ts +1 -2
- package/dist/macros/commands/DrawFlush.d.ts +1 -2
- package/dist/macros/commands/End.d.ts +1 -2
- package/dist/macros/commands/Explosion.d.ts +1 -2
- package/dist/macros/commands/Fetch.d.ts +1 -2
- package/dist/macros/commands/FlushMessage.d.ts +1 -2
- package/dist/macros/commands/GetBlock.d.ts +1 -2
- package/dist/macros/commands/GetFlag.d.ts +1 -2
- package/dist/macros/commands/GetLink.d.ts +1 -2
- package/dist/macros/commands/Lookup.d.ts +1 -2
- package/dist/macros/commands/PackColor.d.ts +1 -2
- package/dist/macros/commands/Print.d.ts +1 -2
- package/dist/macros/commands/PrintFlush.d.ts +1 -2
- package/dist/macros/commands/Radar.d.ts +1 -2
- package/dist/macros/commands/Sensor.d.ts +1 -2
- package/dist/macros/commands/SetBlock.d.ts +1 -2
- package/dist/macros/commands/SetFlag.d.ts +1 -2
- package/dist/macros/commands/SetRate.d.ts +1 -2
- package/dist/macros/commands/SetRule.d.ts +1 -2
- package/dist/macros/commands/SpawnUnit.d.ts +1 -2
- package/dist/macros/commands/SpawnWave.d.ts +1 -2
- package/dist/macros/commands/Stop.d.ts +1 -2
- package/dist/macros/commands/UnitBind.d.ts +1 -2
- package/dist/macros/commands/UnitControl.d.ts +1 -2
- package/dist/macros/commands/UnitLocate.d.ts +1 -2
- package/dist/macros/commands/UnitRadar.d.ts +1 -2
- package/dist/macros/commands/Wait.d.ts +1 -2
- package/dist/macros/util.d.ts +2 -3
- package/dist/operators.d.ts +4 -4
- package/dist/types.d.ts +3 -1
- package/dist/values/BaseValue.d.ts +2 -2
- package/dist/values/DestructuringValue.d.ts +1 -1
- package/dist/values/FunctionValue.d.ts +3 -4
- package/dist/values/LiteralValue.d.ts +3 -2
- package/dist/values/ObjectValue.d.ts +3 -3
- package/dist/values/StoreValue.d.ts +4 -2
- package/dist/values/VoidValue.d.ts +0 -2
- package/lib/commands.d.ts +306 -40
- package/lib/eslib/lib.es5.d.ts +23 -0
- package/lib/globals.d.ts +2 -3
- package/lib/helpers.d.ts +2 -1
- package/lib/kinds.d.ts +5 -2
- package/lib/traits.d.ts +10 -6
- package/package.json +2 -7
- package/dist/types/Compiler.d.ts +0 -39
- package/dist/types/CompilerError.d.ts +0 -33
- package/dist/types/Scope.d.ts +0 -24
- package/dist/types/assertions.d.ts +0 -28
- package/dist/types/bin.d.ts +0 -1
- package/dist/types/handlers/BlockStatement.d.ts +0 -2
- package/dist/types/handlers/CallExpression.d.ts +0 -4
- package/dist/types/handlers/File.d.ts +0 -2
- package/dist/types/handlers/ForStatement.d.ts +0 -2
- package/dist/types/handlers/Function.d.ts +0 -5
- package/dist/types/handlers/Identifier.d.ts +0 -2
- package/dist/types/handlers/IfStatement.d.ts +0 -2
- package/dist/types/handlers/Literal.d.ts +0 -5
- package/dist/types/handlers/Object.d.ts +0 -6
- package/dist/types/handlers/OperationExpressions.d.ts +0 -8
- package/dist/types/handlers/Program.d.ts +0 -2
- package/dist/types/handlers/Statements.d.ts +0 -5
- package/dist/types/handlers/SwitchStatement.d.ts +0 -2
- package/dist/types/handlers/TemplateExpression.d.ts +0 -2
- package/dist/types/handlers/Typescript.d.ts +0 -7
- package/dist/types/handlers/VariableDeclaration.d.ts +0 -3
- package/dist/types/handlers/WhileStatement.d.ts +0 -3
- package/dist/types/handlers/index.d.ts +0 -17
- package/dist/types/index.d.ts +0 -3
- package/dist/types/initScope.d.ts +0 -5
- package/dist/types/instructions/AddressResolver.d.ts +0 -12
- package/dist/types/instructions/ControlInstructions.d.ts +0 -10
- package/dist/types/instructions/EndInstruction.d.ts +0 -4
- package/dist/types/instructions/InstructionBase.d.ts +0 -14
- package/dist/types/instructions/JumpInstruction.d.ts +0 -16
- package/dist/types/instructions/OperationInstruction.d.ts +0 -5
- package/dist/types/instructions/SetCounterInstruction.d.ts +0 -5
- package/dist/types/instructions/SetInstruction.d.ts +0 -6
- package/dist/types/instructions/ZeroSpaceInstruction.d.ts +0 -4
- package/dist/types/instructions/index.d.ts +0 -9
- package/dist/types/macros/Asm.d.ts +0 -5
- package/dist/types/macros/Function.d.ts +0 -13
- package/dist/types/macros/GetGlobal.d.ts +0 -5
- package/dist/types/macros/Math.d.ts +0 -5
- package/dist/types/macros/Memory.d.ts +0 -5
- package/dist/types/macros/Namespace.d.ts +0 -13
- package/dist/types/macros/Other.d.ts +0 -5
- package/dist/types/macros/commands/ApplyStatus.d.ts +0 -5
- package/dist/types/macros/commands/Control.d.ts +0 -5
- package/dist/types/macros/commands/Cutscene.d.ts +0 -5
- package/dist/types/macros/commands/Draw.d.ts +0 -5
- package/dist/types/macros/commands/DrawFlush.d.ts +0 -5
- package/dist/types/macros/commands/End.d.ts +0 -5
- package/dist/types/macros/commands/Explosion.d.ts +0 -5
- package/dist/types/macros/commands/Fetch.d.ts +0 -5
- package/dist/types/macros/commands/FlushMessage.d.ts +0 -5
- package/dist/types/macros/commands/GetBlock.d.ts +0 -5
- package/dist/types/macros/commands/GetFlag.d.ts +0 -5
- package/dist/types/macros/commands/GetLink.d.ts +0 -5
- package/dist/types/macros/commands/Lookup.d.ts +0 -5
- package/dist/types/macros/commands/PackColor.d.ts +0 -5
- package/dist/types/macros/commands/Print.d.ts +0 -5
- package/dist/types/macros/commands/PrintFlush.d.ts +0 -5
- package/dist/types/macros/commands/Radar.d.ts +0 -7
- package/dist/types/macros/commands/Sensor.d.ts +0 -5
- package/dist/types/macros/commands/SetBlock.d.ts +0 -5
- package/dist/types/macros/commands/SetFlag.d.ts +0 -5
- package/dist/types/macros/commands/SetRate.d.ts +0 -5
- package/dist/types/macros/commands/SetRule.d.ts +0 -5
- package/dist/types/macros/commands/SpawnUnit.d.ts +0 -5
- package/dist/types/macros/commands/SpawnWave.d.ts +0 -5
- package/dist/types/macros/commands/Stop.d.ts +0 -5
- package/dist/types/macros/commands/UnitBind.d.ts +0 -5
- package/dist/types/macros/commands/UnitControl.d.ts +0 -5
- package/dist/types/macros/commands/UnitLocate.d.ts +0 -5
- package/dist/types/macros/commands/UnitRadar.d.ts +0 -5
- package/dist/types/macros/commands/Wait.d.ts +0 -5
- package/dist/types/macros/commands/index.d.ts +0 -30
- package/dist/types/macros/index.d.ts +0 -6
- package/dist/types/macros/util.d.ts +0 -18
- package/dist/types/operators.d.ts +0 -25
- package/dist/types/types.d.ts +0 -238
- package/dist/types/utils.d.ts +0 -47
- package/dist/types/values/BaseValue.d.ts +0 -9
- package/dist/types/values/DestructuringValue.d.ts +0 -17
- package/dist/types/values/FunctionValue.d.ts +0 -47
- package/dist/types/values/LiteralValue.d.ts +0 -13
- package/dist/types/values/ObjectValue.d.ts +0 -23
- package/dist/types/values/SenseableValue.d.ts +0 -23
- package/dist/types/values/StoreValue.d.ts +0 -15
- package/dist/types/values/ValueOwner.d.ts +0 -27
- package/dist/types/values/VoidValue.d.ts +0 -16
- package/dist/types/values/index.d.ts +0 -7
package/dist/index.cjs
CHANGED
|
@@ -138,7 +138,7 @@ const arithmeticAssignmentOperators = [
|
|
|
138
138
|
"-=",
|
|
139
139
|
"/=",
|
|
140
140
|
];
|
|
141
|
-
const logicalAssignmentOperators = ["&&=", "||="];
|
|
141
|
+
const logicalAssignmentOperators = ["&&=", "||=", "??="];
|
|
142
142
|
const bitwiseAssignmentOperators = [
|
|
143
143
|
"<<=",
|
|
144
144
|
">>=",
|
|
@@ -171,11 +171,10 @@ const singleOperators = [...unaryOperators, ...updateOperators];
|
|
|
171
171
|
const operators = [...leftRightOperators, ...singleOperators];
|
|
172
172
|
|
|
173
173
|
class VoidValue {
|
|
174
|
-
constructor(
|
|
174
|
+
constructor() {
|
|
175
175
|
this.owner = null;
|
|
176
176
|
this.mutability = EMutability.mutable;
|
|
177
177
|
this.macro = false;
|
|
178
|
-
this.scope = scope;
|
|
179
178
|
}
|
|
180
179
|
eval(_scope) {
|
|
181
180
|
throw new CompilerError(`${this} cannot eval.`);
|
|
@@ -232,8 +231,22 @@ class SetInstruction extends InstructionBase {
|
|
|
232
231
|
constructor(store, value) {
|
|
233
232
|
super("set", store, value);
|
|
234
233
|
}
|
|
234
|
+
get store() {
|
|
235
|
+
return this.args[1];
|
|
236
|
+
}
|
|
237
|
+
get value() {
|
|
238
|
+
return this.args[2];
|
|
239
|
+
}
|
|
235
240
|
get hidden() {
|
|
236
|
-
|
|
241
|
+
const { store, value } = this;
|
|
242
|
+
return (this._hidden ||
|
|
243
|
+
// assignment to discarded value
|
|
244
|
+
!store.owner ||
|
|
245
|
+
// self assignment of a store
|
|
246
|
+
(!!store.owner &&
|
|
247
|
+
store instanceof StoreValue &&
|
|
248
|
+
value instanceof StoreValue &&
|
|
249
|
+
store.owner === value.owner));
|
|
237
250
|
}
|
|
238
251
|
}
|
|
239
252
|
|
|
@@ -312,38 +325,6 @@ class ContinueInstruction extends JumpInstruction {
|
|
|
312
325
|
}
|
|
313
326
|
}
|
|
314
327
|
|
|
315
|
-
class ValueOwner {
|
|
316
|
-
/**
|
|
317
|
-
* Creates a new `ValueOwner`, if `value` is already owned,
|
|
318
|
-
* `this` will be aliased to `value`, else `this` will own `value`
|
|
319
|
-
*/
|
|
320
|
-
constructor({ scope, constant = false, value, identifier, name, }) {
|
|
321
|
-
this.scope = scope;
|
|
322
|
-
this.constant = constant;
|
|
323
|
-
this.value = value;
|
|
324
|
-
this.identifier = identifier;
|
|
325
|
-
this.name = name ?? scope.makeTempName();
|
|
326
|
-
this.persistent = !!name;
|
|
327
|
-
this.owned = new Set();
|
|
328
|
-
if (!value.owner?.persistent)
|
|
329
|
-
this.own(value);
|
|
330
|
-
}
|
|
331
|
-
own(target) {
|
|
332
|
-
target.owner = this;
|
|
333
|
-
this.owned.add(target);
|
|
334
|
-
}
|
|
335
|
-
replace(target) {
|
|
336
|
-
this.value.owner = null;
|
|
337
|
-
this.owned.delete(this.value);
|
|
338
|
-
this.value = target;
|
|
339
|
-
this.own(target);
|
|
340
|
-
}
|
|
341
|
-
moveInto(owner) {
|
|
342
|
-
this.owned.forEach(value => owner.own(value));
|
|
343
|
-
this.owned.clear();
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
328
|
class BaseValue extends VoidValue {
|
|
348
329
|
"u-"(scope) {
|
|
349
330
|
const [that, inst] = this.consume(scope);
|
|
@@ -352,7 +333,7 @@ class BaseValue extends VoidValue {
|
|
|
352
333
|
temp,
|
|
353
334
|
[
|
|
354
335
|
...inst,
|
|
355
|
-
new OperationInstruction("sub", temp, new LiteralValue(
|
|
336
|
+
new OperationInstruction("sub", temp, new LiteralValue(0), that),
|
|
356
337
|
],
|
|
357
338
|
];
|
|
358
339
|
}
|
|
@@ -363,7 +344,7 @@ class BaseValue extends VoidValue {
|
|
|
363
344
|
"!"(scope) {
|
|
364
345
|
const [that, inst] = this.consume(scope);
|
|
365
346
|
const temp = new StoreValue(scope);
|
|
366
|
-
const falseLiteral = new LiteralValue(
|
|
347
|
+
const falseLiteral = new LiteralValue(0);
|
|
367
348
|
return [
|
|
368
349
|
temp,
|
|
369
350
|
[...inst, new OperationInstruction("equal", temp, that, falseLiteral)],
|
|
@@ -374,8 +355,33 @@ class BaseValue extends VoidValue {
|
|
|
374
355
|
const temp = new StoreValue(scope);
|
|
375
356
|
return [temp, [...inst, new OperationInstruction("not", temp, that, null)]];
|
|
376
357
|
}
|
|
377
|
-
|
|
378
|
-
|
|
358
|
+
// requires special handling
|
|
359
|
+
// the handler should give an object value to allow the lazy evaluation
|
|
360
|
+
"??"(scope, other) {
|
|
361
|
+
const [left, leftInst] = this.eval(scope);
|
|
362
|
+
const nullLiteral = new LiteralValue(null);
|
|
363
|
+
const endAdress = new LiteralValue(null);
|
|
364
|
+
const [nullTest] = left["=="](scope, nullLiteral);
|
|
365
|
+
if (nullTest instanceof LiteralValue) {
|
|
366
|
+
if (nullTest.data)
|
|
367
|
+
return other.eval(scope);
|
|
368
|
+
else
|
|
369
|
+
return [left, leftInst];
|
|
370
|
+
}
|
|
371
|
+
const [right, rightInst] = other.eval(scope);
|
|
372
|
+
const result = new StoreValue(scope);
|
|
373
|
+
result.ensureOwned();
|
|
374
|
+
return [
|
|
375
|
+
result,
|
|
376
|
+
[
|
|
377
|
+
...leftInst,
|
|
378
|
+
...result["="](scope, left)[1],
|
|
379
|
+
new JumpInstruction(endAdress, EJumpKind.NotEqual, result, nullLiteral),
|
|
380
|
+
...rightInst,
|
|
381
|
+
...result["="](scope, right)[1],
|
|
382
|
+
new AddressResolver(endAdress),
|
|
383
|
+
],
|
|
384
|
+
];
|
|
379
385
|
}
|
|
380
386
|
}
|
|
381
387
|
const operatorMap$1 = {
|
|
@@ -433,6 +439,7 @@ const assignmentToBinary = {
|
|
|
433
439
|
"<<=": "<<",
|
|
434
440
|
"&&=": "&&",
|
|
435
441
|
"||=": "||",
|
|
442
|
+
"??=": "??",
|
|
436
443
|
};
|
|
437
444
|
for (const op in assignmentToBinary) {
|
|
438
445
|
BaseValue.prototype[op] = function (scope, value) {
|
|
@@ -452,23 +459,20 @@ for (const key of updateOperators) {
|
|
|
452
459
|
inst.push(...tempInst);
|
|
453
460
|
}
|
|
454
461
|
const kind = key === "++" ? "+=" : "-=";
|
|
455
|
-
return [
|
|
456
|
-
ret,
|
|
457
|
-
[...inst, ...this[kind](scope, new LiteralValue(scope, 1))[1]],
|
|
458
|
-
];
|
|
462
|
+
return [ret, [...inst, ...this[kind](scope, new LiteralValue(1))[1]]];
|
|
459
463
|
};
|
|
460
464
|
}
|
|
461
465
|
|
|
462
466
|
const literalMethods = {
|
|
463
|
-
length: function (
|
|
467
|
+
length: function () {
|
|
464
468
|
if (typeof this.data !== "string")
|
|
465
469
|
throw new CompilerError("Length method only works on string literal values.");
|
|
466
|
-
return new LiteralValue(
|
|
470
|
+
return new LiteralValue(this.data.length);
|
|
467
471
|
},
|
|
468
472
|
};
|
|
469
473
|
class LiteralValue extends BaseValue {
|
|
470
|
-
constructor(
|
|
471
|
-
super(
|
|
474
|
+
constructor(data) {
|
|
475
|
+
super();
|
|
472
476
|
this.mutability = EMutability.constant;
|
|
473
477
|
this.data = data;
|
|
474
478
|
}
|
|
@@ -496,9 +500,10 @@ class LiteralValue extends BaseValue {
|
|
|
496
500
|
return 1;
|
|
497
501
|
return this.data;
|
|
498
502
|
}
|
|
499
|
-
typeof(
|
|
500
|
-
return [new LiteralValue(
|
|
503
|
+
typeof() {
|
|
504
|
+
return [new LiteralValue("literal"), []];
|
|
501
505
|
}
|
|
506
|
+
ensureOwned() { }
|
|
502
507
|
}
|
|
503
508
|
const operatorMap = {
|
|
504
509
|
"==": (a, b) => +(a == b),
|
|
@@ -530,10 +535,7 @@ for (const key in operatorMap) {
|
|
|
530
535
|
if (!(value instanceof LiteralValue)) {
|
|
531
536
|
return BaseValue.prototype[key].apply(this, [scope, value]);
|
|
532
537
|
}
|
|
533
|
-
return [
|
|
534
|
-
new LiteralValue(scope, fn(this.data, value.data)),
|
|
535
|
-
[],
|
|
536
|
-
];
|
|
538
|
+
return [new LiteralValue(fn(this.data, value.data)), []];
|
|
537
539
|
};
|
|
538
540
|
}
|
|
539
541
|
const unaryOperatorMap = {
|
|
@@ -543,9 +545,9 @@ const unaryOperatorMap = {
|
|
|
543
545
|
"u+": v => +v,
|
|
544
546
|
};
|
|
545
547
|
for (const key in unaryOperatorMap) {
|
|
546
|
-
LiteralValue.prototype[key] = function (
|
|
548
|
+
LiteralValue.prototype[key] = function () {
|
|
547
549
|
const fn = unaryOperatorMap[key];
|
|
548
|
-
return [new LiteralValue(
|
|
550
|
+
return [new LiteralValue(fn(this.data)), []];
|
|
549
551
|
};
|
|
550
552
|
}
|
|
551
553
|
|
|
@@ -624,17 +626,50 @@ function isTemplateObjectArray(value) {
|
|
|
624
626
|
typeof value.data.raw.data.length.data === "number");
|
|
625
627
|
}
|
|
626
628
|
|
|
629
|
+
class ValueOwner {
|
|
630
|
+
/**
|
|
631
|
+
* Creates a new `ValueOwner`, if `value` is already owned,
|
|
632
|
+
* `this` will be aliased to `value`, else `this` will own `value`
|
|
633
|
+
*/
|
|
634
|
+
constructor({ scope, constant = false, value, identifier, name, }) {
|
|
635
|
+
this.scope = scope;
|
|
636
|
+
this.constant = constant;
|
|
637
|
+
this.value = value;
|
|
638
|
+
this.identifier = identifier;
|
|
639
|
+
this.name = name ?? scope.makeTempName();
|
|
640
|
+
this.persistent = !!name;
|
|
641
|
+
this.owned = new Set();
|
|
642
|
+
if (!value.owner?.persistent)
|
|
643
|
+
this.own(value);
|
|
644
|
+
}
|
|
645
|
+
own(target) {
|
|
646
|
+
target.owner = this;
|
|
647
|
+
this.owned.add(target);
|
|
648
|
+
}
|
|
649
|
+
replace(target) {
|
|
650
|
+
this.value.owner = null;
|
|
651
|
+
this.owned.delete(this.value);
|
|
652
|
+
this.value = target;
|
|
653
|
+
this.own(target);
|
|
654
|
+
}
|
|
655
|
+
moveInto(owner) {
|
|
656
|
+
this.owned.forEach(value => owner.own(value));
|
|
657
|
+
this.owned.clear();
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
627
661
|
/**
|
|
628
662
|
* `StoreValue` represents values unknown at compile time,
|
|
629
663
|
* mostly used with mutable variables and temporary values
|
|
630
664
|
*/
|
|
631
665
|
class StoreValue extends BaseValue {
|
|
632
666
|
constructor(scope) {
|
|
633
|
-
super(
|
|
667
|
+
super();
|
|
668
|
+
this.scope = scope;
|
|
634
669
|
this.mutability = EMutability.mutable;
|
|
635
670
|
}
|
|
636
|
-
typeof(
|
|
637
|
-
return [new LiteralValue(
|
|
671
|
+
typeof() {
|
|
672
|
+
return [new LiteralValue("store"), []];
|
|
638
673
|
}
|
|
639
674
|
"="(scope, value) {
|
|
640
675
|
if (this.mutability !== EMutability.mutable)
|
|
@@ -661,31 +696,34 @@ class StoreValue extends BaseValue {
|
|
|
661
696
|
this.ensureOwned();
|
|
662
697
|
return [this, []];
|
|
663
698
|
}
|
|
699
|
+
ensureOwned() {
|
|
700
|
+
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
701
|
+
}
|
|
664
702
|
toString() {
|
|
665
703
|
return this.owner?.name ?? discardedName;
|
|
666
704
|
}
|
|
667
705
|
}
|
|
668
706
|
|
|
669
707
|
class ObjectValue extends VoidValue {
|
|
670
|
-
constructor(
|
|
671
|
-
super(
|
|
708
|
+
constructor(data = {}) {
|
|
709
|
+
super();
|
|
672
710
|
this.mutability = EMutability.constant;
|
|
673
711
|
this.macro = true;
|
|
674
712
|
this.data = data;
|
|
675
713
|
}
|
|
676
|
-
static fromArray(
|
|
714
|
+
static fromArray(items, intialData) {
|
|
677
715
|
const data = {
|
|
678
716
|
...intialData,
|
|
679
|
-
length: new LiteralValue(
|
|
717
|
+
length: new LiteralValue(items.length),
|
|
680
718
|
};
|
|
681
719
|
items.forEach((item, i) => {
|
|
682
720
|
if (item)
|
|
683
721
|
data[i] = item;
|
|
684
722
|
});
|
|
685
|
-
return new ObjectValue(
|
|
723
|
+
return new ObjectValue(data);
|
|
686
724
|
}
|
|
687
|
-
typeof(
|
|
688
|
-
return [new LiteralValue(
|
|
725
|
+
typeof() {
|
|
726
|
+
return [new LiteralValue("object"), []];
|
|
689
727
|
}
|
|
690
728
|
get(scope, key) {
|
|
691
729
|
// avoids naming collisions with keys like
|
|
@@ -722,9 +760,7 @@ class ObjectValue extends VoidValue {
|
|
|
722
760
|
return super.call(scope, args);
|
|
723
761
|
return $call.call(scope, args);
|
|
724
762
|
}
|
|
725
|
-
ensureOwned() {
|
|
726
|
-
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
727
|
-
}
|
|
763
|
+
ensureOwned() { }
|
|
728
764
|
}
|
|
729
765
|
for (const op of operators) {
|
|
730
766
|
ObjectValue.prototype[op] = function (...args) {
|
|
@@ -793,8 +829,8 @@ class SenseableValue extends StoreValue {
|
|
|
793
829
|
* each of them to their counterparts on the right hand value.
|
|
794
830
|
*/
|
|
795
831
|
class DestructuringValue extends VoidValue {
|
|
796
|
-
constructor(
|
|
797
|
-
super(
|
|
832
|
+
constructor(members) {
|
|
833
|
+
super();
|
|
798
834
|
this.members = members;
|
|
799
835
|
this.macro = true;
|
|
800
836
|
}
|
|
@@ -981,7 +1017,7 @@ const DeclareObjectPattern = (c, scope, node, kind, base) => {
|
|
|
981
1017
|
throw new CompilerError("The rest operator is not supported", prop);
|
|
982
1018
|
const { key, value } = prop;
|
|
983
1019
|
const keyInst = key.type === "Identifier" && !prop.computed
|
|
984
|
-
? [new LiteralValue(
|
|
1020
|
+
? [new LiteralValue(key.name), []]
|
|
985
1021
|
: c.handleConsume(scope, prop.key);
|
|
986
1022
|
const propInit = init.get(scope, keyInst[0]);
|
|
987
1023
|
const declarationInst = Declare(c, scope, value, kind, propInit[0]);
|
|
@@ -990,14 +1026,14 @@ const DeclareObjectPattern = (c, scope, node, kind, base) => {
|
|
|
990
1026
|
return [null, [...inst, ...propertiesInst[1]]];
|
|
991
1027
|
};
|
|
992
1028
|
|
|
993
|
-
const Literal = (_c, scope, node) => [new LiteralValue(
|
|
1029
|
+
const Literal = (_c, scope, node) => [new LiteralValue(node.value), []];
|
|
994
1030
|
const NumericLiteral = Literal;
|
|
995
1031
|
const StringLiteral = Literal;
|
|
996
|
-
const NullLiteral = (
|
|
997
|
-
new LiteralValue(
|
|
1032
|
+
const NullLiteral = () => [
|
|
1033
|
+
new LiteralValue(null),
|
|
998
1034
|
[],
|
|
999
1035
|
];
|
|
1000
|
-
const BooleanLiteral = (_c, scope, node) => [new LiteralValue(
|
|
1036
|
+
const BooleanLiteral = (_c, scope, node) => [new LiteralValue(+node.value), []];
|
|
1001
1037
|
|
|
1002
1038
|
const LRExpression = (c, scope, node) => {
|
|
1003
1039
|
const [left, leftInst] = c.handleConsume(scope, node.left);
|
|
@@ -1009,35 +1045,26 @@ const BinaryExpression = LRExpression;
|
|
|
1009
1045
|
const LogicalExpression = (c, scope, node) => {
|
|
1010
1046
|
if (node.operator !== "??")
|
|
1011
1047
|
return LRExpression(c, scope, node);
|
|
1012
|
-
const
|
|
1013
|
-
|
|
1048
|
+
const other = lazyValue({
|
|
1049
|
+
eval: scope => c.handleEval(scope, node.right),
|
|
1050
|
+
consume: scope => c.handleConsume(scope, node.right),
|
|
1051
|
+
});
|
|
1014
1052
|
const [left, leftInst] = c.handleEval(scope, node.left);
|
|
1015
|
-
const [
|
|
1016
|
-
|
|
1017
|
-
if (nullTest.data)
|
|
1018
|
-
return c.handleEval(scope, node.right);
|
|
1019
|
-
else
|
|
1020
|
-
return [left, leftInst];
|
|
1021
|
-
}
|
|
1022
|
-
const [right, rightInst] = c.handleEval(scope, node.right);
|
|
1023
|
-
const result = new StoreValue(scope);
|
|
1024
|
-
result.ensureOwned();
|
|
1025
|
-
return [
|
|
1026
|
-
result,
|
|
1027
|
-
[
|
|
1028
|
-
...leftInst,
|
|
1029
|
-
...result["="](scope, left)[1],
|
|
1030
|
-
new JumpInstruction(endAdress, EJumpKind.NotEqual, result, nullLiteral),
|
|
1031
|
-
...rightInst,
|
|
1032
|
-
...result["="](scope, right)[1],
|
|
1033
|
-
new AddressResolver(endAdress),
|
|
1034
|
-
],
|
|
1035
|
-
];
|
|
1053
|
+
const [result, resultInst] = left["??"](scope, other);
|
|
1054
|
+
return [result, [...leftInst, ...resultInst]];
|
|
1036
1055
|
};
|
|
1037
1056
|
const AssignmentExpression = (c, scope, node) => {
|
|
1038
1057
|
const [left, leftInst] = c.handle(scope, node.left);
|
|
1039
1058
|
// doesn't need to consume because the operators already do that
|
|
1040
|
-
const [right, rightInst] =
|
|
1059
|
+
const [right, rightInst] = node.operator !== "??="
|
|
1060
|
+
? c.handleEval(scope, node.right)
|
|
1061
|
+
: [
|
|
1062
|
+
lazyValue({
|
|
1063
|
+
eval: scope => c.handleEval(scope, node.right),
|
|
1064
|
+
consume: scope => c.handleConsume(scope, node.right),
|
|
1065
|
+
}),
|
|
1066
|
+
[],
|
|
1067
|
+
];
|
|
1041
1068
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1042
1069
|
const [op, opInst] = left[node.operator](scope, right);
|
|
1043
1070
|
return [op, [...leftInst, ...rightInst, ...opInst]];
|
|
@@ -1069,13 +1096,13 @@ const ConditionalExpression = (c, scope, node) => {
|
|
|
1069
1096
|
result.ensureOwned();
|
|
1070
1097
|
const consequent = c.handleEval(scope, node.consequent);
|
|
1071
1098
|
const alternate = c.handleEval(scope, node.alternate);
|
|
1072
|
-
const alternateStartAdress = new LiteralValue(
|
|
1073
|
-
const endExpressionAdress = new LiteralValue(
|
|
1099
|
+
const alternateStartAdress = new LiteralValue(null);
|
|
1100
|
+
const endExpressionAdress = new LiteralValue(null);
|
|
1074
1101
|
return [
|
|
1075
1102
|
result,
|
|
1076
1103
|
[
|
|
1077
1104
|
...testInst,
|
|
1078
|
-
new JumpInstruction(alternateStartAdress, EJumpKind.Equal, test, new LiteralValue(
|
|
1105
|
+
new JumpInstruction(alternateStartAdress, EJumpKind.Equal, test, new LiteralValue(0)),
|
|
1079
1106
|
...consequent[1],
|
|
1080
1107
|
...result["="](scope, consequent[0])[1],
|
|
1081
1108
|
new JumpInstruction(endExpressionAdress, EJumpKind.Always),
|
|
@@ -1085,7 +1112,13 @@ const ConditionalExpression = (c, scope, node) => {
|
|
|
1085
1112
|
new AddressResolver(endExpressionAdress),
|
|
1086
1113
|
],
|
|
1087
1114
|
];
|
|
1088
|
-
};
|
|
1115
|
+
};
|
|
1116
|
+
function lazyValue(options) {
|
|
1117
|
+
const value = new VoidValue();
|
|
1118
|
+
value.eval = options.eval;
|
|
1119
|
+
value.consume = options.consume;
|
|
1120
|
+
return value;
|
|
1121
|
+
}
|
|
1089
1122
|
|
|
1090
1123
|
const Identifier = (c, scope, node) => {
|
|
1091
1124
|
return [scope.get(node.name), []];
|
|
@@ -1094,14 +1127,18 @@ const Identifier = (c, scope, node) => {
|
|
|
1094
1127
|
const ExpressionStatement = (c, scope, node) => {
|
|
1095
1128
|
return c.handle(scope, node.expression);
|
|
1096
1129
|
};
|
|
1097
|
-
const BreakStatement = (_, scope) => {
|
|
1098
|
-
const
|
|
1099
|
-
scope
|
|
1130
|
+
const BreakStatement = (_, scope, node) => {
|
|
1131
|
+
const label = node.label?.name;
|
|
1132
|
+
const target = label ? findScopeLabel(scope, label) : scope;
|
|
1133
|
+
const addr = new LiteralValue(null);
|
|
1134
|
+
target.break.bind(addr);
|
|
1100
1135
|
return [null, [new BreakInstruction(addr)]];
|
|
1101
1136
|
};
|
|
1102
|
-
const ContinueStatement = (_, scope) => {
|
|
1103
|
-
const addr = new LiteralValue(
|
|
1104
|
-
|
|
1137
|
+
const ContinueStatement = (_, scope, node) => {
|
|
1138
|
+
const addr = new LiteralValue(null);
|
|
1139
|
+
const label = node.label?.name;
|
|
1140
|
+
const target = label ? findScopeLabel(scope, label) : scope;
|
|
1141
|
+
target.continue.bind(addr);
|
|
1105
1142
|
return [null, [new ContinueInstruction(addr)]];
|
|
1106
1143
|
};
|
|
1107
1144
|
const ReturnStatement = (c, scope, node) => {
|
|
@@ -1110,7 +1147,24 @@ const ReturnStatement = (c, scope, node) => {
|
|
|
1110
1147
|
: [null, []];
|
|
1111
1148
|
const [ret, retInst] = scope.function.return(scope, arg);
|
|
1112
1149
|
return [ret, [...argInst, ...retInst]];
|
|
1113
|
-
};
|
|
1150
|
+
};
|
|
1151
|
+
const LabeledStatement = (c, scope, node) => {
|
|
1152
|
+
const inner = scope.createScope();
|
|
1153
|
+
inner.label = node.label.name;
|
|
1154
|
+
const end = new LiteralValue(null);
|
|
1155
|
+
const endAdress = new AddressResolver(end).bindBreak(inner);
|
|
1156
|
+
const [, bodyInst] = c.handle(inner, node.body);
|
|
1157
|
+
return [null, [...bodyInst, endAdress]];
|
|
1158
|
+
};
|
|
1159
|
+
function findScopeLabel(scope, label) {
|
|
1160
|
+
let current = scope;
|
|
1161
|
+
while (current !== null) {
|
|
1162
|
+
if (current.label === label)
|
|
1163
|
+
return current;
|
|
1164
|
+
current = current.parent;
|
|
1165
|
+
}
|
|
1166
|
+
throw new CompilerError(`Could not find label "${label}"`);
|
|
1167
|
+
}
|
|
1114
1168
|
|
|
1115
1169
|
const IfStatement = (c, scope, node) => {
|
|
1116
1170
|
const inst = [];
|
|
@@ -1122,9 +1176,9 @@ const IfStatement = (c, scope, node) => {
|
|
|
1122
1176
|
inst.push(...c.handle(scope, node.alternate)[1]);
|
|
1123
1177
|
return [null, inst];
|
|
1124
1178
|
}
|
|
1125
|
-
const endIfAddr = new LiteralValue(
|
|
1126
|
-
inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1127
|
-
const endElseAddr = new LiteralValue(
|
|
1179
|
+
const endIfAddr = new LiteralValue(null);
|
|
1180
|
+
inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(0)), ...withAlwaysRuns(c.handle(scope, node.consequent), false)[1], new AddressResolver(endIfAddr));
|
|
1181
|
+
const endElseAddr = new LiteralValue(null);
|
|
1128
1182
|
if (node.alternate) {
|
|
1129
1183
|
inst.push(new JumpInstruction(endElseAddr, EJumpKind.Always), new AddressResolver(endIfAddr), ...withAlwaysRuns(c.handle(scope, node.alternate), false)[1], new AddressResolver(endElseAddr));
|
|
1130
1184
|
}
|
|
@@ -1135,13 +1189,13 @@ const SwitchStatement = (c, scope, node) => {
|
|
|
1135
1189
|
const innerScope = scope.createScope();
|
|
1136
1190
|
const [ref, refInst] = c.handleConsume(scope, node.discriminant);
|
|
1137
1191
|
const inst = [];
|
|
1138
|
-
const endAdress = new LiteralValue(
|
|
1192
|
+
const endAdress = new LiteralValue(null);
|
|
1139
1193
|
const endLine = new AddressResolver(endAdress).bindBreak(innerScope);
|
|
1140
1194
|
const caseJumps = [];
|
|
1141
1195
|
let defaultJump;
|
|
1142
1196
|
for (const scase of node.cases) {
|
|
1143
1197
|
const [, bodyInst] = c.handleMany(innerScope, scase.consequent);
|
|
1144
|
-
const bodyAdress = new LiteralValue(
|
|
1198
|
+
const bodyAdress = new LiteralValue(null);
|
|
1145
1199
|
const bodyLine = new AddressResolver(bodyAdress);
|
|
1146
1200
|
if (!scase.test) {
|
|
1147
1201
|
[defaultJump] = c.handle(innerScope, scase, () => [
|
|
@@ -1195,25 +1249,33 @@ const SwitchStatement = (c, scope, node) => {
|
|
|
1195
1249
|
const WhileStatement = (c, scope, node) => {
|
|
1196
1250
|
const lines = [];
|
|
1197
1251
|
const [test, testLines] = c.handleConsume(scope, node.test);
|
|
1198
|
-
const
|
|
1199
|
-
const
|
|
1200
|
-
const
|
|
1201
|
-
const
|
|
1252
|
+
const childScope = scope.createScope();
|
|
1253
|
+
const startLoopAddr = new LiteralValue(null);
|
|
1254
|
+
const endLoopAddr = new LiteralValue(null);
|
|
1255
|
+
const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(childScope);
|
|
1256
|
+
const endLoopLine = new AddressResolver(endLoopAddr).bindBreak(childScope);
|
|
1257
|
+
if (scope.label) {
|
|
1258
|
+
startLoopLine.bindContinue(scope);
|
|
1259
|
+
}
|
|
1202
1260
|
if (test instanceof LiteralValue) {
|
|
1203
1261
|
if (test.data) {
|
|
1204
|
-
lines.push(startLoopLine, ...c.handle(
|
|
1262
|
+
lines.push(startLoopLine, ...c.handle(childScope, node.body)[1], new JumpInstruction(startLoopAddr, EJumpKind.Always), endLoopLine);
|
|
1205
1263
|
}
|
|
1206
1264
|
return [null, lines];
|
|
1207
1265
|
}
|
|
1208
|
-
lines.push(startLoopLine, ...testLines, new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1266
|
+
lines.push(startLoopLine, ...testLines, new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(0)), ...withAlwaysRuns(c.handle(childScope, node.body), false)[1], new JumpInstruction(startLoopAddr, EJumpKind.Always), endLoopLine);
|
|
1209
1267
|
return [null, lines];
|
|
1210
1268
|
};
|
|
1211
1269
|
const DoWhileStatement = (c, scope, node) => {
|
|
1212
1270
|
const lines = [];
|
|
1213
1271
|
const [test, testLines] = c.handleConsume(scope, node.test);
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1216
|
-
const
|
|
1272
|
+
const childScope = scope.createScope();
|
|
1273
|
+
const startLoopAddr = new LiteralValue(null);
|
|
1274
|
+
const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(childScope);
|
|
1275
|
+
if (scope.label) {
|
|
1276
|
+
startLoopLine.bindContinue(scope);
|
|
1277
|
+
}
|
|
1278
|
+
const [, bodyLines] = c.handle(childScope, node.body);
|
|
1217
1279
|
if (test instanceof LiteralValue) {
|
|
1218
1280
|
if (!test.data)
|
|
1219
1281
|
return [null, [...lines, ...bodyLines]];
|
|
@@ -1227,28 +1289,31 @@ const DoWhileStatement = (c, scope, node) => {
|
|
|
1227
1289
|
],
|
|
1228
1290
|
];
|
|
1229
1291
|
}
|
|
1230
|
-
lines.push(startLoopLine, ...bodyLines, ...testLines, new JumpInstruction(startLoopAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1292
|
+
lines.push(startLoopLine, ...bodyLines, ...testLines, new JumpInstruction(startLoopAddr, EJumpKind.Equal, test, new LiteralValue(1)));
|
|
1231
1293
|
return [null, lines];
|
|
1232
1294
|
};
|
|
1233
1295
|
|
|
1234
|
-
const ForStatement = (c,
|
|
1235
|
-
scope =
|
|
1296
|
+
const ForStatement = (c, parentScope, node) => {
|
|
1297
|
+
const scope = parentScope.createScope();
|
|
1236
1298
|
const initInst = node.init ? c.handle(scope, node.init)[1] : [];
|
|
1237
1299
|
const [test, testLines] = node.test
|
|
1238
1300
|
? c.handleConsume(scope, node.test)
|
|
1239
|
-
: [new LiteralValue(
|
|
1301
|
+
: [new LiteralValue(1), []];
|
|
1240
1302
|
const updateLines = node.update ? c.handle(scope, node.update)[1] : [];
|
|
1241
|
-
const startLoopAddr = new LiteralValue(
|
|
1242
|
-
const endLoopAddr = new LiteralValue(
|
|
1303
|
+
const startLoopAddr = new LiteralValue(null);
|
|
1304
|
+
const endLoopAddr = new LiteralValue(null);
|
|
1243
1305
|
const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(scope);
|
|
1244
1306
|
const endLoopLine = new AddressResolver(endLoopAddr).bindBreak(scope);
|
|
1307
|
+
if (parentScope.label) {
|
|
1308
|
+
startLoopLine.bindContinue(parentScope);
|
|
1309
|
+
}
|
|
1245
1310
|
return [
|
|
1246
1311
|
null,
|
|
1247
1312
|
[
|
|
1248
1313
|
...initInst,
|
|
1249
1314
|
startLoopLine,
|
|
1250
1315
|
...testLines,
|
|
1251
|
-
new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1316
|
+
new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(0)),
|
|
1252
1317
|
...withAlwaysRuns(c.handle(scope, node.body), false)[1],
|
|
1253
1318
|
...updateLines,
|
|
1254
1319
|
new JumpInstruction(startLoopAddr, EJumpKind.Always),
|
|
@@ -1258,20 +1323,20 @@ const ForStatement = (c, scope, node) => {
|
|
|
1258
1323
|
};
|
|
1259
1324
|
|
|
1260
1325
|
class FunctionValue extends VoidValue {
|
|
1261
|
-
constructor({ scope, params, body, c,
|
|
1262
|
-
super(
|
|
1326
|
+
constructor({ scope, params, body, c, }) {
|
|
1327
|
+
super();
|
|
1263
1328
|
this.mutability = EMutability.constant;
|
|
1264
1329
|
this.macro = true;
|
|
1265
1330
|
this.paramOwners = [];
|
|
1266
1331
|
this.bundled = false;
|
|
1267
1332
|
this.initialized = false;
|
|
1333
|
+
this.scope = scope;
|
|
1268
1334
|
this.body = body;
|
|
1269
1335
|
this.c = c;
|
|
1270
|
-
this.node = node;
|
|
1271
1336
|
this.params = params;
|
|
1272
1337
|
}
|
|
1273
|
-
typeof(
|
|
1274
|
-
return [new LiteralValue(
|
|
1338
|
+
typeof() {
|
|
1339
|
+
return [new LiteralValue("function"), []];
|
|
1275
1340
|
}
|
|
1276
1341
|
initScope(name) {
|
|
1277
1342
|
this.childScope = this.scope.createFunction(name);
|
|
@@ -1299,7 +1364,7 @@ class FunctionValue extends VoidValue {
|
|
|
1299
1364
|
this.initialized = true;
|
|
1300
1365
|
const { name } = this.owner;
|
|
1301
1366
|
this.initScope(name);
|
|
1302
|
-
this.addr = new LiteralValue(
|
|
1367
|
+
this.addr = new LiteralValue(null);
|
|
1303
1368
|
this.temp = new ValueOwner({
|
|
1304
1369
|
scope: this.childScope,
|
|
1305
1370
|
name: `${internalPrefix}f${name}`,
|
|
@@ -1333,7 +1398,7 @@ class FunctionValue extends VoidValue {
|
|
|
1333
1398
|
if (!this.bundled)
|
|
1334
1399
|
this.childScope.inst.push(...this.inst);
|
|
1335
1400
|
this.bundled = true;
|
|
1336
|
-
const callAddressLiteral = new LiteralValue(
|
|
1401
|
+
const callAddressLiteral = new LiteralValue(null);
|
|
1337
1402
|
const inst = this.paramOwners
|
|
1338
1403
|
.map(({ value: param }, i) => param["="](scope, args[i])[1])
|
|
1339
1404
|
.reduce((s, c) => s.concat(c), [])
|
|
@@ -1371,7 +1436,7 @@ class FunctionValue extends VoidValue {
|
|
|
1371
1436
|
name: owner.name,
|
|
1372
1437
|
}));
|
|
1373
1438
|
});
|
|
1374
|
-
this.inlineEnd = new LiteralValue(
|
|
1439
|
+
this.inlineEnd = new LiteralValue(null);
|
|
1375
1440
|
this.tryingInline = true;
|
|
1376
1441
|
let inst = this.c.handle(fnScope, this.body)[1];
|
|
1377
1442
|
this.tryingInline = false;
|
|
@@ -1430,7 +1495,6 @@ function handleFunctionNode(c, scope, node) {
|
|
|
1430
1495
|
}
|
|
1431
1496
|
return [
|
|
1432
1497
|
new FunctionValue({
|
|
1433
|
-
node,
|
|
1434
1498
|
scope,
|
|
1435
1499
|
params: params,
|
|
1436
1500
|
body,
|
|
@@ -1476,8 +1540,8 @@ const NewExpression = CallExpression;
|
|
|
1476
1540
|
const TaggedTemplateExpression = (c, scope, node) => {
|
|
1477
1541
|
const [tag, tagInst] = c.handleConsume(scope, node.tag);
|
|
1478
1542
|
const template = node.quasi;
|
|
1479
|
-
const stringsObject = ObjectValue.fromArray(
|
|
1480
|
-
raw: ObjectValue.fromArray(
|
|
1543
|
+
const stringsObject = ObjectValue.fromArray(template.quasis.map(quasi => new LiteralValue(quasi.value.cooked ?? "")), {
|
|
1544
|
+
raw: ObjectValue.fromArray(template.quasis.map(quasi => new LiteralValue(quasi.value.raw))),
|
|
1481
1545
|
});
|
|
1482
1546
|
const expressions = [];
|
|
1483
1547
|
const expressionInsts = [];
|
|
@@ -1522,7 +1586,7 @@ const ObjectExpression = (c, scope, node) => {
|
|
|
1522
1586
|
data[index] = member;
|
|
1523
1587
|
inst.push(...memberInst);
|
|
1524
1588
|
}
|
|
1525
|
-
return [new ObjectValue(
|
|
1589
|
+
return [new ObjectValue(data), inst];
|
|
1526
1590
|
};
|
|
1527
1591
|
const ArrayExpression = (c, scope, node) => {
|
|
1528
1592
|
const items = [];
|
|
@@ -1534,13 +1598,13 @@ const ArrayExpression = (c, scope, node) => {
|
|
|
1534
1598
|
items.push(value);
|
|
1535
1599
|
inst.push(...valueInst);
|
|
1536
1600
|
});
|
|
1537
|
-
return [ObjectValue.fromArray(
|
|
1601
|
+
return [ObjectValue.fromArray(items), inst];
|
|
1538
1602
|
};
|
|
1539
1603
|
const MemberExpression = (c, scope, node) => {
|
|
1540
1604
|
const [obj, objInst] = c.handleConsume(scope, node.object);
|
|
1541
1605
|
const [prop, propInst] = node.computed
|
|
1542
1606
|
? c.handleConsume(scope, node.property)
|
|
1543
|
-
: [new LiteralValue(
|
|
1607
|
+
: [new LiteralValue(node.property.name), []];
|
|
1544
1608
|
const [got, gotInst] = obj.get(scope, prop);
|
|
1545
1609
|
return [got, [...objInst, ...propInst, ...gotInst]];
|
|
1546
1610
|
};
|
|
@@ -1555,9 +1619,9 @@ const ArrayPattern = (c, scope, node) => {
|
|
|
1555
1619
|
if (!valueInst[0])
|
|
1556
1620
|
throw new CompilerError("Destructuring element must resolve to a value", element);
|
|
1557
1621
|
inst.push(...valueInst[1]);
|
|
1558
|
-
members.set(new LiteralValue(
|
|
1622
|
+
members.set(new LiteralValue(i), valueInst[0]);
|
|
1559
1623
|
}
|
|
1560
|
-
return [new DestructuringValue(
|
|
1624
|
+
return [new DestructuringValue(members), inst];
|
|
1561
1625
|
};
|
|
1562
1626
|
const ObjectPattern = (c, scope, node) => {
|
|
1563
1627
|
const inst = [];
|
|
@@ -1569,7 +1633,7 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
1569
1633
|
continue;
|
|
1570
1634
|
const { key } = prop;
|
|
1571
1635
|
const keyInst = !prop.computed && key.type === "Identifier"
|
|
1572
|
-
? [new LiteralValue(
|
|
1636
|
+
? [new LiteralValue(key.name), []]
|
|
1573
1637
|
: c.handleConsume(scope, prop.key);
|
|
1574
1638
|
inst.push(...keyInst[1]);
|
|
1575
1639
|
const valueInst = c.handle(scope, prop.value);
|
|
@@ -1578,7 +1642,7 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
1578
1642
|
inst.push(...valueInst[1]);
|
|
1579
1643
|
members.set(keyInst[0], valueInst[0]);
|
|
1580
1644
|
}
|
|
1581
|
-
return [new DestructuringValue(
|
|
1645
|
+
return [new DestructuringValue(members), inst];
|
|
1582
1646
|
};
|
|
1583
1647
|
|
|
1584
1648
|
const TemplateLiteral = () => {
|
|
@@ -1618,7 +1682,7 @@ const TSEnumDeclaration = (c, scope, node) => {
|
|
|
1618
1682
|
throw new CompilerError("This enum member must be initialized", member);
|
|
1619
1683
|
const [value] = member.initializer
|
|
1620
1684
|
? c.handleEval(scope, member.initializer)
|
|
1621
|
-
: [new LiteralValue(
|
|
1685
|
+
: [new LiteralValue(counter)];
|
|
1622
1686
|
if (!(value instanceof LiteralValue))
|
|
1623
1687
|
throw new CompilerError("Enum members must contain literal values", member);
|
|
1624
1688
|
if (typeof value.data === "number") {
|
|
@@ -1633,7 +1697,7 @@ const TSEnumDeclaration = (c, scope, node) => {
|
|
|
1633
1697
|
}
|
|
1634
1698
|
scope.set(new ValueOwner({
|
|
1635
1699
|
scope,
|
|
1636
|
-
value: new ObjectValue(
|
|
1700
|
+
value: new ObjectValue(data),
|
|
1637
1701
|
constant: true,
|
|
1638
1702
|
identifier: node.id.name,
|
|
1639
1703
|
name: nodeName(node, !c.compactNames && node.id.name),
|
|
@@ -1665,6 +1729,7 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1665
1729
|
BreakStatement: BreakStatement,
|
|
1666
1730
|
ContinueStatement: ContinueStatement,
|
|
1667
1731
|
ReturnStatement: ReturnStatement,
|
|
1732
|
+
LabeledStatement: LabeledStatement,
|
|
1668
1733
|
IfStatement: IfStatement,
|
|
1669
1734
|
SwitchStatement: SwitchStatement,
|
|
1670
1735
|
WhileStatement: WhileStatement,
|
|
@@ -1694,14 +1759,14 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1694
1759
|
});
|
|
1695
1760
|
|
|
1696
1761
|
class MacroFunction extends VoidValue {
|
|
1697
|
-
constructor(
|
|
1698
|
-
super(
|
|
1762
|
+
constructor(fn) {
|
|
1763
|
+
super();
|
|
1699
1764
|
this.macro = true;
|
|
1700
|
-
this.
|
|
1765
|
+
this.mutability = EMutability.constant;
|
|
1701
1766
|
this.fn = fn;
|
|
1702
1767
|
}
|
|
1703
1768
|
call(scope, args) {
|
|
1704
|
-
return this.fn.apply(this, args);
|
|
1769
|
+
return this.fn.apply(this, [scope, ...args]);
|
|
1705
1770
|
}
|
|
1706
1771
|
eval(_scope) {
|
|
1707
1772
|
return [this, []];
|
|
@@ -1732,16 +1797,31 @@ const mathOperations = {
|
|
|
1732
1797
|
sqrt: a => Math.sqrt(a),
|
|
1733
1798
|
rand: null,
|
|
1734
1799
|
};
|
|
1800
|
+
function mathConstant(scope, name) {
|
|
1801
|
+
return new ValueOwner({
|
|
1802
|
+
scope,
|
|
1803
|
+
constant: true,
|
|
1804
|
+
name,
|
|
1805
|
+
value: assign(new StoreValue(scope), {
|
|
1806
|
+
mutability: EMutability.constant,
|
|
1807
|
+
}),
|
|
1808
|
+
}).value;
|
|
1809
|
+
}
|
|
1735
1810
|
function createMacroMathOperations(scope) {
|
|
1736
|
-
const macroMathOperations = {
|
|
1811
|
+
const macroMathOperations = {
|
|
1812
|
+
PI: mathConstant(scope, "@pi"),
|
|
1813
|
+
E: mathConstant(scope, "@e"),
|
|
1814
|
+
degToRad: mathConstant(scope, "@degToRad"),
|
|
1815
|
+
radToDeg: mathConstant(scope, "@radToDeg"),
|
|
1816
|
+
};
|
|
1737
1817
|
for (const key in mathOperations) {
|
|
1738
1818
|
const fn = mathOperations[key];
|
|
1739
|
-
macroMathOperations[key] = new MacroFunction(scope,
|
|
1819
|
+
macroMathOperations[key] = new MacroFunction((scope, a, b) => {
|
|
1740
1820
|
if (b) {
|
|
1741
1821
|
if (fn && a instanceof LiteralValue && b instanceof LiteralValue) {
|
|
1742
1822
|
if (typeof a.data !== "number" || typeof b.data !== "number")
|
|
1743
1823
|
throw new CompilerError("Cannot do math operation with non-numerical literals.");
|
|
1744
|
-
return [new LiteralValue(
|
|
1824
|
+
return [new LiteralValue(fn(a.num, b.num)), []];
|
|
1745
1825
|
}
|
|
1746
1826
|
const temp = new StoreValue(scope);
|
|
1747
1827
|
return [temp, [new OperationInstruction(key, temp, a, b)]];
|
|
@@ -1749,7 +1829,7 @@ function createMacroMathOperations(scope) {
|
|
|
1749
1829
|
if (fn && a instanceof LiteralValue) {
|
|
1750
1830
|
if (typeof a.data !== "number")
|
|
1751
1831
|
throw new CompilerError("Cannot do math operation with non-numerical literal.");
|
|
1752
|
-
return [new LiteralValue(
|
|
1832
|
+
return [new LiteralValue(fn(a.num)), []];
|
|
1753
1833
|
}
|
|
1754
1834
|
const temp = new StoreValue(scope);
|
|
1755
1835
|
return [temp, [new OperationInstruction(key, temp, a, b)]];
|
|
@@ -1759,20 +1839,20 @@ function createMacroMathOperations(scope) {
|
|
|
1759
1839
|
}
|
|
1760
1840
|
class MlogMath extends ObjectValue {
|
|
1761
1841
|
constructor(scope) {
|
|
1762
|
-
super(
|
|
1842
|
+
super(createMacroMathOperations(scope));
|
|
1763
1843
|
}
|
|
1764
1844
|
}
|
|
1765
1845
|
// op angle result a b
|
|
1766
1846
|
// op len result a b
|
|
1767
1847
|
|
|
1768
1848
|
class Concat extends MacroFunction {
|
|
1769
|
-
constructor(
|
|
1770
|
-
super(scope,
|
|
1849
|
+
constructor() {
|
|
1850
|
+
super((scope, ...values) => {
|
|
1771
1851
|
for (const value of values)
|
|
1772
1852
|
if (!(value instanceof LiteralValue))
|
|
1773
1853
|
throw new CompilerError("Concat arguments must all be literal values.");
|
|
1774
1854
|
return [
|
|
1775
|
-
new LiteralValue(
|
|
1855
|
+
new LiteralValue(values.map(v => v.data).join("")),
|
|
1776
1856
|
[],
|
|
1777
1857
|
];
|
|
1778
1858
|
});
|
|
@@ -1827,18 +1907,18 @@ function assertObjectFields(value, fields) {
|
|
|
1827
1907
|
}
|
|
1828
1908
|
|
|
1829
1909
|
/** Used to create namespaces that contain multiple methods that map into instructions */
|
|
1830
|
-
function createOverloadNamespace({
|
|
1910
|
+
function createOverloadNamespace({ overloads, handler, }) {
|
|
1831
1911
|
const result = {};
|
|
1832
1912
|
for (const key in overloads) {
|
|
1833
1913
|
const { named, args } = overloads[key];
|
|
1834
1914
|
if (named) {
|
|
1835
|
-
result[key] = new MacroFunction(scope, options => {
|
|
1915
|
+
result[key] = new MacroFunction((scope, options) => {
|
|
1836
1916
|
assertIsObjectMacro(options, named);
|
|
1837
|
-
return handler(key, ...assertObjectFields(options, args));
|
|
1917
|
+
return handler(scope, key, ...assertObjectFields(options, args));
|
|
1838
1918
|
});
|
|
1839
1919
|
continue;
|
|
1840
1920
|
}
|
|
1841
|
-
result[key] = new MacroFunction(scope,
|
|
1921
|
+
result[key] = new MacroFunction((scope, ...params) => {
|
|
1842
1922
|
const handlerParams = [];
|
|
1843
1923
|
// validate the paramters
|
|
1844
1924
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -1855,16 +1935,15 @@ function createOverloadNamespace({ scope, overloads, handler, }) {
|
|
|
1855
1935
|
arg.validate?.(param);
|
|
1856
1936
|
handlerParams.push(param);
|
|
1857
1937
|
}
|
|
1858
|
-
return handler(key, ...handlerParams);
|
|
1938
|
+
return handler(scope, key, ...handlerParams);
|
|
1859
1939
|
});
|
|
1860
1940
|
}
|
|
1861
1941
|
return result;
|
|
1862
1942
|
}
|
|
1863
1943
|
|
|
1864
1944
|
class Draw extends ObjectValue {
|
|
1865
|
-
constructor(
|
|
1945
|
+
constructor() {
|
|
1866
1946
|
const data = createOverloadNamespace({
|
|
1867
|
-
scope,
|
|
1868
1947
|
overloads: {
|
|
1869
1948
|
clear: {
|
|
1870
1949
|
args: ["r", "g", "b"],
|
|
@@ -1901,17 +1980,17 @@ class Draw extends ObjectValue {
|
|
|
1901
1980
|
args: ["x", "y", "image", "size", "rotation"],
|
|
1902
1981
|
},
|
|
1903
1982
|
},
|
|
1904
|
-
handler(overload, ...args) {
|
|
1983
|
+
handler(scope, overload, ...args) {
|
|
1905
1984
|
return [null, [new InstructionBase("draw", overload, ...args)]];
|
|
1906
1985
|
},
|
|
1907
1986
|
});
|
|
1908
|
-
super(
|
|
1987
|
+
super(data);
|
|
1909
1988
|
}
|
|
1910
1989
|
}
|
|
1911
1990
|
|
|
1912
1991
|
class Print extends MacroFunction {
|
|
1913
|
-
constructor(
|
|
1914
|
-
super(scope,
|
|
1992
|
+
constructor() {
|
|
1993
|
+
super((scope, ...values) => {
|
|
1915
1994
|
const [first] = values;
|
|
1916
1995
|
const inst = [];
|
|
1917
1996
|
if (!isTemplateObjectArray(first)) {
|
|
@@ -1924,12 +2003,12 @@ class Print extends MacroFunction {
|
|
|
1924
2003
|
// maybe this should be checked in another way?
|
|
1925
2004
|
const { length } = first.data;
|
|
1926
2005
|
for (let i = 1; i < values.length; i++) {
|
|
1927
|
-
const [string] = first.get(scope, new LiteralValue(
|
|
2006
|
+
const [string] = first.get(scope, new LiteralValue(i - 1));
|
|
1928
2007
|
if (string.data)
|
|
1929
2008
|
inst.push(new InstructionBase("print", string));
|
|
1930
2009
|
inst.push(new InstructionBase("print", values[i]));
|
|
1931
2010
|
}
|
|
1932
|
-
const [tail] = first.get(scope, new LiteralValue(
|
|
2011
|
+
const [tail] = first.get(scope, new LiteralValue(length.data - 1));
|
|
1933
2012
|
if (tail.data)
|
|
1934
2013
|
inst.push(new InstructionBase("print", tail));
|
|
1935
2014
|
return [null, inst];
|
|
@@ -1939,8 +2018,8 @@ class Print extends MacroFunction {
|
|
|
1939
2018
|
|
|
1940
2019
|
const defaultTargetName$1 = "message1";
|
|
1941
2020
|
class PrintFlush extends MacroFunction {
|
|
1942
|
-
constructor(
|
|
1943
|
-
super(scope,
|
|
2021
|
+
constructor() {
|
|
2022
|
+
super((scope, target) => {
|
|
1944
2023
|
if (!target)
|
|
1945
2024
|
return [null, [new InstructionBase("printflush", defaultTargetName$1)]];
|
|
1946
2025
|
if (!(target instanceof SenseableValue))
|
|
@@ -1952,8 +2031,8 @@ class PrintFlush extends MacroFunction {
|
|
|
1952
2031
|
|
|
1953
2032
|
const defaultTargetName = "display1";
|
|
1954
2033
|
class DrawFlush extends MacroFunction {
|
|
1955
|
-
constructor(
|
|
1956
|
-
super(scope,
|
|
2034
|
+
constructor() {
|
|
2035
|
+
super((scope, target) => {
|
|
1957
2036
|
if (!target)
|
|
1958
2037
|
return [null, [new InstructionBase("drawflush", defaultTargetName)]];
|
|
1959
2038
|
if (!(target instanceof SenseableValue))
|
|
@@ -1964,16 +2043,15 @@ class DrawFlush extends MacroFunction {
|
|
|
1964
2043
|
}
|
|
1965
2044
|
|
|
1966
2045
|
class GetBlock extends ObjectValue {
|
|
1967
|
-
constructor(
|
|
2046
|
+
constructor() {
|
|
1968
2047
|
const data = createOverloadNamespace({
|
|
1969
|
-
scope,
|
|
1970
2048
|
overloads: {
|
|
1971
2049
|
floor: { args: ["x", "y"] },
|
|
1972
2050
|
ore: { args: ["x", "y"] },
|
|
1973
2051
|
block: { args: ["x", "y"] },
|
|
1974
2052
|
building: { args: ["x", "y"] },
|
|
1975
2053
|
},
|
|
1976
|
-
handler(overload, x, y) {
|
|
2054
|
+
handler(scope, overload, x, y) {
|
|
1977
2055
|
const output = overload === "building"
|
|
1978
2056
|
? new SenseableValue(scope)
|
|
1979
2057
|
: new StoreValue(scope);
|
|
@@ -1983,13 +2061,13 @@ class GetBlock extends ObjectValue {
|
|
|
1983
2061
|
];
|
|
1984
2062
|
},
|
|
1985
2063
|
});
|
|
1986
|
-
super(
|
|
2064
|
+
super(data);
|
|
1987
2065
|
}
|
|
1988
2066
|
}
|
|
1989
2067
|
|
|
1990
2068
|
class GetLink extends MacroFunction {
|
|
1991
|
-
constructor(
|
|
1992
|
-
super(scope,
|
|
2069
|
+
constructor() {
|
|
2070
|
+
super((scope, index) => {
|
|
1993
2071
|
if (!(index instanceof StoreValue) &&
|
|
1994
2072
|
(!(index instanceof LiteralValue) || typeof index.data !== "number"))
|
|
1995
2073
|
throw new CompilerError("The getlink index must be a number literal or a store");
|
|
@@ -2000,9 +2078,8 @@ class GetLink extends MacroFunction {
|
|
|
2000
2078
|
}
|
|
2001
2079
|
|
|
2002
2080
|
class Control extends ObjectValue {
|
|
2003
|
-
constructor(
|
|
2004
|
-
super(
|
|
2005
|
-
scope,
|
|
2081
|
+
constructor() {
|
|
2082
|
+
super(createOverloadNamespace({
|
|
2006
2083
|
overloads: {
|
|
2007
2084
|
enabled: { args: ["building", "value"] },
|
|
2008
2085
|
shoot: {
|
|
@@ -2016,7 +2093,7 @@ class Control extends ObjectValue {
|
|
|
2016
2093
|
config: { args: ["building", "value"] },
|
|
2017
2094
|
color: { args: ["building", "r", "g", "b"] },
|
|
2018
2095
|
},
|
|
2019
|
-
handler(overload, ...args) {
|
|
2096
|
+
handler(scope, overload, ...args) {
|
|
2020
2097
|
return [null, [new InstructionBase("control", overload, ...args)]];
|
|
2021
2098
|
},
|
|
2022
2099
|
}));
|
|
@@ -2041,8 +2118,8 @@ const validRadarSorts = [
|
|
|
2041
2118
|
"maxHealth",
|
|
2042
2119
|
];
|
|
2043
2120
|
class Radar extends MacroFunction {
|
|
2044
|
-
constructor(
|
|
2045
|
-
super(scope, options => {
|
|
2121
|
+
constructor() {
|
|
2122
|
+
super((scope, options) => {
|
|
2046
2123
|
assertIsObjectMacro(options, "The radar options");
|
|
2047
2124
|
const { building, filters, order, sort } = options.data;
|
|
2048
2125
|
if (!(building instanceof SenseableValue))
|
|
@@ -2073,8 +2150,8 @@ class Radar extends MacroFunction {
|
|
|
2073
2150
|
}
|
|
2074
2151
|
|
|
2075
2152
|
class Sensor extends MacroFunction {
|
|
2076
|
-
constructor(
|
|
2077
|
-
super(scope,
|
|
2153
|
+
constructor() {
|
|
2154
|
+
super((scope, property, target) => {
|
|
2078
2155
|
if (!(property instanceof StoreValue))
|
|
2079
2156
|
throw new CompilerError("The sensor property must be a store");
|
|
2080
2157
|
if (!(target instanceof SenseableValue))
|
|
@@ -2088,8 +2165,8 @@ class Sensor extends MacroFunction {
|
|
|
2088
2165
|
}
|
|
2089
2166
|
|
|
2090
2167
|
class Wait extends MacroFunction {
|
|
2091
|
-
constructor(
|
|
2092
|
-
super(scope, seconds => {
|
|
2168
|
+
constructor() {
|
|
2169
|
+
super((scope, seconds) => {
|
|
2093
2170
|
if (!(seconds instanceof StoreValue) &&
|
|
2094
2171
|
!(seconds instanceof LiteralValue && typeof seconds.data === "number"))
|
|
2095
2172
|
throw new CompilerError("The wait seconds must be either a number literal or a store");
|
|
@@ -2099,16 +2176,15 @@ class Wait extends MacroFunction {
|
|
|
2099
2176
|
}
|
|
2100
2177
|
|
|
2101
2178
|
class Lookup extends ObjectValue {
|
|
2102
|
-
constructor(
|
|
2179
|
+
constructor() {
|
|
2103
2180
|
const data = createOverloadNamespace({
|
|
2104
|
-
scope,
|
|
2105
2181
|
overloads: {
|
|
2106
2182
|
block: { args: ["index"] },
|
|
2107
2183
|
unit: { args: ["index"] },
|
|
2108
2184
|
item: { args: ["index"] },
|
|
2109
2185
|
liquid: { args: ["index"] },
|
|
2110
2186
|
},
|
|
2111
|
-
handler(overload, index) {
|
|
2187
|
+
handler(scope, overload, index) {
|
|
2112
2188
|
const output = new StoreValue(scope);
|
|
2113
2189
|
return [
|
|
2114
2190
|
output,
|
|
@@ -2116,13 +2192,13 @@ class Lookup extends ObjectValue {
|
|
|
2116
2192
|
];
|
|
2117
2193
|
},
|
|
2118
2194
|
});
|
|
2119
|
-
super(
|
|
2195
|
+
super(data);
|
|
2120
2196
|
}
|
|
2121
2197
|
}
|
|
2122
2198
|
|
|
2123
2199
|
class PackColor extends MacroFunction {
|
|
2124
|
-
constructor(
|
|
2125
|
-
super(scope,
|
|
2200
|
+
constructor() {
|
|
2201
|
+
super((scope, ...args) => {
|
|
2126
2202
|
if (args.length !== 4) {
|
|
2127
2203
|
throw new CompilerError(`Expected 4 arguments, received ${args.length}`);
|
|
2128
2204
|
}
|
|
@@ -2137,15 +2213,14 @@ class PackColor extends MacroFunction {
|
|
|
2137
2213
|
}
|
|
2138
2214
|
|
|
2139
2215
|
class End extends MacroFunction {
|
|
2140
|
-
constructor(
|
|
2141
|
-
super(
|
|
2216
|
+
constructor() {
|
|
2217
|
+
super(() => [null, [new EndInstruction()]]);
|
|
2142
2218
|
}
|
|
2143
2219
|
}
|
|
2144
2220
|
|
|
2145
2221
|
class SetBlock extends ObjectValue {
|
|
2146
|
-
constructor(
|
|
2222
|
+
constructor() {
|
|
2147
2223
|
const data = createOverloadNamespace({
|
|
2148
|
-
scope,
|
|
2149
2224
|
overloads: {
|
|
2150
2225
|
floor: { args: ["x", "y", "to"] },
|
|
2151
2226
|
ore: { args: ["x", "y", "to"] },
|
|
@@ -2154,7 +2229,7 @@ class SetBlock extends ObjectValue {
|
|
|
2154
2229
|
args: ["x", "y", "to", "team", { key: "rotation", default: "0" }],
|
|
2155
2230
|
},
|
|
2156
2231
|
},
|
|
2157
|
-
handler(overload, x, y, to, team, rotation) {
|
|
2232
|
+
handler(scope, overload, x, y, to, team, rotation) {
|
|
2158
2233
|
return [
|
|
2159
2234
|
null,
|
|
2160
2235
|
[
|
|
@@ -2163,13 +2238,13 @@ class SetBlock extends ObjectValue {
|
|
|
2163
2238
|
];
|
|
2164
2239
|
},
|
|
2165
2240
|
});
|
|
2166
|
-
super(
|
|
2241
|
+
super(data);
|
|
2167
2242
|
}
|
|
2168
2243
|
}
|
|
2169
2244
|
|
|
2170
2245
|
class SpawnUnit extends MacroFunction {
|
|
2171
|
-
constructor(
|
|
2172
|
-
super(scope, options => {
|
|
2246
|
+
constructor() {
|
|
2247
|
+
super((scope, options) => {
|
|
2173
2248
|
assertIsObjectMacro(options, "The options");
|
|
2174
2249
|
const { type, x, y, team, rotation } = options.data;
|
|
2175
2250
|
assertIsRuntimeValue(type, "type");
|
|
@@ -2188,14 +2263,14 @@ class SpawnUnit extends MacroFunction {
|
|
|
2188
2263
|
}
|
|
2189
2264
|
|
|
2190
2265
|
class Stop extends MacroFunction {
|
|
2191
|
-
constructor(
|
|
2192
|
-
super(
|
|
2266
|
+
constructor() {
|
|
2267
|
+
super(() => [null, [new InstructionBase("stop")]]);
|
|
2193
2268
|
}
|
|
2194
2269
|
}
|
|
2195
2270
|
|
|
2196
2271
|
class UnitBind extends MacroFunction {
|
|
2197
|
-
constructor(
|
|
2198
|
-
super(scope, type => {
|
|
2272
|
+
constructor() {
|
|
2273
|
+
super((scope, type) => {
|
|
2199
2274
|
if (!(type instanceof StoreValue))
|
|
2200
2275
|
throw new CompilerError("The unitBind type must be a store");
|
|
2201
2276
|
return [null, [new InstructionBase("ubind", type)]];
|
|
@@ -2204,9 +2279,8 @@ class UnitBind extends MacroFunction {
|
|
|
2204
2279
|
}
|
|
2205
2280
|
|
|
2206
2281
|
class UnitControl extends ObjectValue {
|
|
2207
|
-
constructor(
|
|
2282
|
+
constructor() {
|
|
2208
2283
|
const data = createOverloadNamespace({
|
|
2209
|
-
scope,
|
|
2210
2284
|
overloads: {
|
|
2211
2285
|
idle: { args: [] },
|
|
2212
2286
|
stop: { args: [] },
|
|
@@ -2235,21 +2309,21 @@ class UnitControl extends ObjectValue {
|
|
|
2235
2309
|
args: ["x", "y", "radius"],
|
|
2236
2310
|
},
|
|
2237
2311
|
},
|
|
2238
|
-
handler(overload, ...args) {
|
|
2312
|
+
handler(scope, overload, ...args) {
|
|
2239
2313
|
let result = null;
|
|
2240
2314
|
let extraArgs = [];
|
|
2241
2315
|
switch (overload) {
|
|
2242
2316
|
case "getBlock": {
|
|
2243
2317
|
const outType = new StoreValue(scope);
|
|
2244
2318
|
const outBuilding = new SenseableValue(scope);
|
|
2245
|
-
result = ObjectValue.fromArray(
|
|
2246
|
-
extraArgs = [outType, outBuilding, new LiteralValue(
|
|
2319
|
+
result = ObjectValue.fromArray([outType, outBuilding]);
|
|
2320
|
+
extraArgs = [outType, outBuilding, new LiteralValue(0)];
|
|
2247
2321
|
break;
|
|
2248
2322
|
}
|
|
2249
2323
|
case "within": {
|
|
2250
2324
|
const temp = new StoreValue(scope);
|
|
2251
2325
|
result = temp;
|
|
2252
|
-
extraArgs = [temp, new LiteralValue(
|
|
2326
|
+
extraArgs = [temp, new LiteralValue(0)];
|
|
2253
2327
|
break;
|
|
2254
2328
|
}
|
|
2255
2329
|
}
|
|
@@ -2259,13 +2333,13 @@ class UnitControl extends ObjectValue {
|
|
|
2259
2333
|
];
|
|
2260
2334
|
},
|
|
2261
2335
|
});
|
|
2262
|
-
super(
|
|
2336
|
+
super(data);
|
|
2263
2337
|
}
|
|
2264
2338
|
}
|
|
2265
2339
|
|
|
2266
2340
|
class UnitRadar extends MacroFunction {
|
|
2267
|
-
constructor(
|
|
2268
|
-
super(scope, options => {
|
|
2341
|
+
constructor() {
|
|
2342
|
+
super((scope, options) => {
|
|
2269
2343
|
assertIsObjectMacro(options, "The radar options");
|
|
2270
2344
|
const { filters, order, sort } = options.data;
|
|
2271
2345
|
assertIsArrayMacro(filters, "filters");
|
|
@@ -2306,9 +2380,8 @@ const validBuildingGroups = [
|
|
|
2306
2380
|
"reactor",
|
|
2307
2381
|
];
|
|
2308
2382
|
class UnitLocate extends ObjectValue {
|
|
2309
|
-
constructor(
|
|
2383
|
+
constructor() {
|
|
2310
2384
|
const data = createOverloadNamespace({
|
|
2311
|
-
scope,
|
|
2312
2385
|
overloads: {
|
|
2313
2386
|
ore: {
|
|
2314
2387
|
args: ["ore"],
|
|
@@ -2321,7 +2394,7 @@ class UnitLocate extends ObjectValue {
|
|
|
2321
2394
|
args: [],
|
|
2322
2395
|
},
|
|
2323
2396
|
},
|
|
2324
|
-
handler(overload, ...args) {
|
|
2397
|
+
handler(scope, overload, ...args) {
|
|
2325
2398
|
const outFound = new StoreValue(scope);
|
|
2326
2399
|
const outX = new StoreValue(scope);
|
|
2327
2400
|
const outY = new StoreValue(scope);
|
|
@@ -2349,7 +2422,7 @@ class UnitLocate extends ObjectValue {
|
|
|
2349
2422
|
}
|
|
2350
2423
|
}
|
|
2351
2424
|
return [
|
|
2352
|
-
ObjectValue.fromArray(
|
|
2425
|
+
ObjectValue.fromArray([
|
|
2353
2426
|
outFound,
|
|
2354
2427
|
outX,
|
|
2355
2428
|
outY,
|
|
@@ -2359,7 +2432,7 @@ class UnitLocate extends ObjectValue {
|
|
|
2359
2432
|
];
|
|
2360
2433
|
},
|
|
2361
2434
|
});
|
|
2362
|
-
super(
|
|
2435
|
+
super(data);
|
|
2363
2436
|
}
|
|
2364
2437
|
}
|
|
2365
2438
|
|
|
@@ -2380,16 +2453,15 @@ const validEffects = [
|
|
|
2380
2453
|
"blasted",
|
|
2381
2454
|
];
|
|
2382
2455
|
class ApplyStatus extends ObjectValue {
|
|
2383
|
-
constructor(
|
|
2456
|
+
constructor() {
|
|
2384
2457
|
const data = createOverloadNamespace({
|
|
2385
|
-
scope,
|
|
2386
2458
|
overloads: {
|
|
2387
2459
|
apply: {
|
|
2388
2460
|
args: ["status", "unit", { key: "duration", default: "10" }],
|
|
2389
2461
|
},
|
|
2390
2462
|
clear: { args: ["status", "unit"] },
|
|
2391
2463
|
},
|
|
2392
|
-
handler(overload, effect, unit, duration) {
|
|
2464
|
+
handler(scope, overload, effect, unit, duration) {
|
|
2393
2465
|
if (!(effect instanceof LiteralValue))
|
|
2394
2466
|
throw new CompilerError("The status effect must be a string literal");
|
|
2395
2467
|
assertLiteralOneOf(effect, validEffects, "The status effect");
|
|
@@ -2401,13 +2473,13 @@ class ApplyStatus extends ObjectValue {
|
|
|
2401
2473
|
];
|
|
2402
2474
|
},
|
|
2403
2475
|
});
|
|
2404
|
-
super(
|
|
2476
|
+
super(data);
|
|
2405
2477
|
}
|
|
2406
2478
|
}
|
|
2407
2479
|
|
|
2408
2480
|
class SpawnWave extends MacroFunction {
|
|
2409
|
-
constructor(
|
|
2410
|
-
super(scope,
|
|
2481
|
+
constructor() {
|
|
2482
|
+
super((scope, natural, x, y) => {
|
|
2411
2483
|
if (!(natural instanceof LiteralValue) ||
|
|
2412
2484
|
(natural.data !== 1 && natural.data !== 0))
|
|
2413
2485
|
throw new CompilerError("The 'natural' argument must be a boolean literal");
|
|
@@ -2422,9 +2494,8 @@ class SpawnWave extends MacroFunction {
|
|
|
2422
2494
|
}
|
|
2423
2495
|
|
|
2424
2496
|
class SetRule extends ObjectValue {
|
|
2425
|
-
constructor(
|
|
2497
|
+
constructor() {
|
|
2426
2498
|
const data = createOverloadNamespace({
|
|
2427
|
-
scope,
|
|
2428
2499
|
overloads: {
|
|
2429
2500
|
currentWaveTime: { args: ["seconds"] },
|
|
2430
2501
|
waveTimer: { args: ["enabled"] },
|
|
@@ -2442,13 +2513,14 @@ class SetRule extends ObjectValue {
|
|
|
2442
2513
|
solarMultiplier: { args: ["multiplier"] },
|
|
2443
2514
|
buildSpeed: { args: ["team", "multiplier"] },
|
|
2444
2515
|
unitBuildSpeed: { args: ["team", "multiplier"] },
|
|
2516
|
+
unitCost: { args: ["team", "multiplier"] },
|
|
2445
2517
|
unitDamage: { args: ["team", "multiplier"] },
|
|
2446
2518
|
blockHealth: { args: ["team", "multiplier"] },
|
|
2447
2519
|
blockDamage: { args: ["team", "multiplier"] },
|
|
2448
2520
|
rtsMinWeight: { args: ["team", "value"] },
|
|
2449
2521
|
rtsMinSquad: { args: ["team", "value"] },
|
|
2450
2522
|
},
|
|
2451
|
-
handler(overload, ...args) {
|
|
2523
|
+
handler(scope, overload, ...args) {
|
|
2452
2524
|
const params = ["10", "0", "0", "100", "100"];
|
|
2453
2525
|
switch (overload) {
|
|
2454
2526
|
case "mapArea": {
|
|
@@ -2461,6 +2533,7 @@ class SetRule extends ObjectValue {
|
|
|
2461
2533
|
}
|
|
2462
2534
|
case "buildSpeed":
|
|
2463
2535
|
case "unitBuildSpeed":
|
|
2536
|
+
case "unitCost":
|
|
2464
2537
|
case "unitDamage":
|
|
2465
2538
|
case "blockHealth":
|
|
2466
2539
|
case "blockDamage":
|
|
@@ -2468,7 +2541,7 @@ class SetRule extends ObjectValue {
|
|
|
2468
2541
|
case "rtsMinSquad": {
|
|
2469
2542
|
const [team, value] = args;
|
|
2470
2543
|
params[1] = team;
|
|
2471
|
-
params[
|
|
2544
|
+
params[0] = value;
|
|
2472
2545
|
break;
|
|
2473
2546
|
}
|
|
2474
2547
|
default:
|
|
@@ -2477,49 +2550,47 @@ class SetRule extends ObjectValue {
|
|
|
2477
2550
|
return [null, [new InstructionBase("setrule", overload, ...params)]];
|
|
2478
2551
|
},
|
|
2479
2552
|
});
|
|
2480
|
-
super(
|
|
2553
|
+
super(data);
|
|
2481
2554
|
}
|
|
2482
2555
|
}
|
|
2483
2556
|
|
|
2484
2557
|
class FlushMessage extends ObjectValue {
|
|
2485
|
-
constructor(
|
|
2558
|
+
constructor() {
|
|
2486
2559
|
const data = createOverloadNamespace({
|
|
2487
|
-
scope,
|
|
2488
2560
|
overloads: {
|
|
2489
2561
|
notify: { args: [] },
|
|
2490
2562
|
mission: { args: [] },
|
|
2491
2563
|
announce: { args: ["duration"] },
|
|
2492
2564
|
toast: { args: ["duration"] },
|
|
2493
2565
|
},
|
|
2494
|
-
handler(overload, duration) {
|
|
2566
|
+
handler(scope, overload, duration) {
|
|
2495
2567
|
return [null, [new InstructionBase("message", overload, duration)]];
|
|
2496
2568
|
},
|
|
2497
2569
|
});
|
|
2498
|
-
super(
|
|
2570
|
+
super(data);
|
|
2499
2571
|
}
|
|
2500
2572
|
}
|
|
2501
2573
|
|
|
2502
2574
|
class Cutscene extends ObjectValue {
|
|
2503
|
-
constructor(
|
|
2575
|
+
constructor() {
|
|
2504
2576
|
const data = createOverloadNamespace({
|
|
2505
|
-
scope,
|
|
2506
2577
|
overloads: {
|
|
2507
2578
|
pan: { named: "options", args: ["x", "y", "speed"] },
|
|
2508
2579
|
zoom: { args: ["level"] },
|
|
2509
2580
|
stop: { args: [] },
|
|
2510
2581
|
},
|
|
2511
|
-
handler(overload, ...args) {
|
|
2582
|
+
handler(scope, overload, ...args) {
|
|
2512
2583
|
const params = Object.assign(["100", "100", "0.06", "0"], args);
|
|
2513
2584
|
return [null, [new InstructionBase("cutscene", overload, ...params)]];
|
|
2514
2585
|
},
|
|
2515
2586
|
});
|
|
2516
|
-
super(
|
|
2587
|
+
super(data);
|
|
2517
2588
|
}
|
|
2518
2589
|
}
|
|
2519
2590
|
|
|
2520
2591
|
class Explosion extends MacroFunction {
|
|
2521
|
-
constructor(
|
|
2522
|
-
super(scope, options => {
|
|
2592
|
+
constructor() {
|
|
2593
|
+
super((scope, options) => {
|
|
2523
2594
|
assertIsObjectMacro(options, "The options");
|
|
2524
2595
|
const params = assertObjectFields(options, [
|
|
2525
2596
|
"team",
|
|
@@ -2537,15 +2608,14 @@ class Explosion extends MacroFunction {
|
|
|
2537
2608
|
}
|
|
2538
2609
|
|
|
2539
2610
|
class SetRate extends MacroFunction {
|
|
2540
|
-
constructor(
|
|
2541
|
-
super(scope, ipt => [null, [new InstructionBase("setrate", ipt)]]);
|
|
2611
|
+
constructor() {
|
|
2612
|
+
super((scope, ipt) => [null, [new InstructionBase("setrate", ipt)]]);
|
|
2542
2613
|
}
|
|
2543
2614
|
}
|
|
2544
2615
|
|
|
2545
2616
|
class Fetch extends ObjectValue {
|
|
2546
|
-
constructor(
|
|
2617
|
+
constructor() {
|
|
2547
2618
|
const data = createOverloadNamespace({
|
|
2548
|
-
scope,
|
|
2549
2619
|
overloads: {
|
|
2550
2620
|
unit: { args: ["team", "index"] },
|
|
2551
2621
|
unitCount: { args: ["team"] },
|
|
@@ -2556,7 +2626,7 @@ class Fetch extends ObjectValue {
|
|
|
2556
2626
|
build: { args: ["team", "index", "block"] },
|
|
2557
2627
|
buildCount: { args: ["team", "block"] },
|
|
2558
2628
|
},
|
|
2559
|
-
handler(overload, team, ...rest) {
|
|
2629
|
+
handler(scope, overload, team, ...rest) {
|
|
2560
2630
|
const output = new SenseableValue(scope);
|
|
2561
2631
|
const params = ["0", "@conveyor"];
|
|
2562
2632
|
if (overload === "buildCount") {
|
|
@@ -2571,13 +2641,13 @@ class Fetch extends ObjectValue {
|
|
|
2571
2641
|
];
|
|
2572
2642
|
},
|
|
2573
2643
|
});
|
|
2574
|
-
super(
|
|
2644
|
+
super(data);
|
|
2575
2645
|
}
|
|
2576
2646
|
}
|
|
2577
2647
|
|
|
2578
2648
|
class GetFlag extends MacroFunction {
|
|
2579
|
-
constructor(
|
|
2580
|
-
super(scope, flag => {
|
|
2649
|
+
constructor() {
|
|
2650
|
+
super((scope, flag) => {
|
|
2581
2651
|
const result = new StoreValue(scope);
|
|
2582
2652
|
return [result, [new InstructionBase("getflag", result, flag)]];
|
|
2583
2653
|
});
|
|
@@ -2585,8 +2655,8 @@ class GetFlag extends MacroFunction {
|
|
|
2585
2655
|
}
|
|
2586
2656
|
|
|
2587
2657
|
class SetFlag extends MacroFunction {
|
|
2588
|
-
constructor(
|
|
2589
|
-
super(scope,
|
|
2658
|
+
constructor() {
|
|
2659
|
+
super((scope, flag, value) => {
|
|
2590
2660
|
if (!flag)
|
|
2591
2661
|
throw new CompilerError("Missing flag argument");
|
|
2592
2662
|
if (!value)
|
|
@@ -2596,36 +2666,48 @@ class SetFlag extends MacroFunction {
|
|
|
2596
2666
|
}
|
|
2597
2667
|
}
|
|
2598
2668
|
|
|
2599
|
-
class MemoryEntry extends
|
|
2669
|
+
class MemoryEntry extends BaseValue {
|
|
2600
2670
|
constructor(scope, mem, prop) {
|
|
2601
|
-
super(
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
return [temp, [new InstructionBase("read", temp, mem.cell, prop)]];
|
|
2607
|
-
}),
|
|
2608
|
-
$consume: new MacroFunction(scope, () => {
|
|
2609
|
-
if (this.store)
|
|
2610
|
-
return [this.store, []];
|
|
2611
|
-
this.ensureOwned();
|
|
2612
|
-
this.store = new StoreValue(scope);
|
|
2613
|
-
this.owner.own(this.store);
|
|
2614
|
-
return [
|
|
2615
|
-
this.store,
|
|
2616
|
-
[new InstructionBase("read", this.store, mem.cell, prop)],
|
|
2617
|
-
];
|
|
2618
|
-
}),
|
|
2619
|
-
"$=": new MacroFunction(scope, value => {
|
|
2620
|
-
const [data, dataInst] = value.consume(scope);
|
|
2621
|
-
return [
|
|
2622
|
-
data,
|
|
2623
|
-
[...dataInst, new InstructionBase("write", data, mem.cell, prop)],
|
|
2624
|
-
];
|
|
2625
|
-
}),
|
|
2626
|
-
});
|
|
2671
|
+
super();
|
|
2672
|
+
this.scope = scope;
|
|
2673
|
+
this.mem = mem;
|
|
2674
|
+
this.prop = prop;
|
|
2675
|
+
this.macro = true;
|
|
2627
2676
|
this.store = null;
|
|
2628
2677
|
}
|
|
2678
|
+
eval(scope) {
|
|
2679
|
+
if (this.store)
|
|
2680
|
+
return [this.store, []];
|
|
2681
|
+
const temp = new StoreValue(scope);
|
|
2682
|
+
return [
|
|
2683
|
+
temp,
|
|
2684
|
+
[new InstructionBase("read", temp, this.mem.cell, this.prop)],
|
|
2685
|
+
];
|
|
2686
|
+
}
|
|
2687
|
+
consume(scope) {
|
|
2688
|
+
if (this.store)
|
|
2689
|
+
return [this.store, []];
|
|
2690
|
+
this.ensureOwned();
|
|
2691
|
+
this.store = new StoreValue(scope);
|
|
2692
|
+
this.owner.own(this.store);
|
|
2693
|
+
return [
|
|
2694
|
+
this.store,
|
|
2695
|
+
[new InstructionBase("read", this.store, this.mem.cell, this.prop)],
|
|
2696
|
+
];
|
|
2697
|
+
}
|
|
2698
|
+
"="(scope, value) {
|
|
2699
|
+
const [data, dataInst] = value.consume(scope);
|
|
2700
|
+
return [
|
|
2701
|
+
data,
|
|
2702
|
+
[
|
|
2703
|
+
...dataInst,
|
|
2704
|
+
new InstructionBase("write", data, this.mem.cell, this.prop),
|
|
2705
|
+
],
|
|
2706
|
+
];
|
|
2707
|
+
}
|
|
2708
|
+
ensureOwned() {
|
|
2709
|
+
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
2710
|
+
}
|
|
2629
2711
|
}
|
|
2630
2712
|
for (const operator of operators) {
|
|
2631
2713
|
if (operator === "=")
|
|
@@ -2636,9 +2718,9 @@ for (const operator of operators) {
|
|
|
2636
2718
|
};
|
|
2637
2719
|
}
|
|
2638
2720
|
class MemoryMacro extends ObjectValue {
|
|
2639
|
-
constructor(
|
|
2640
|
-
super(
|
|
2641
|
-
$get: new MacroFunction(scope,
|
|
2721
|
+
constructor(cell, size) {
|
|
2722
|
+
super({
|
|
2723
|
+
$get: new MacroFunction((scope, prop) => {
|
|
2642
2724
|
if (prop instanceof LiteralValue && typeof prop.data !== "number")
|
|
2643
2725
|
throw new CompilerError(`Invalid memory object property: "${prop.data}"`);
|
|
2644
2726
|
const obj = new MemoryEntry(scope, this, prop);
|
|
@@ -2648,21 +2730,20 @@ class MemoryMacro extends ObjectValue {
|
|
|
2648
2730
|
size,
|
|
2649
2731
|
});
|
|
2650
2732
|
this.cell = cell;
|
|
2651
|
-
this.name = cell.toString();
|
|
2652
2733
|
}
|
|
2653
2734
|
toString() {
|
|
2654
|
-
return this.
|
|
2735
|
+
return this.cell.toString();
|
|
2655
2736
|
}
|
|
2656
2737
|
}
|
|
2657
2738
|
class MemoryBuilder extends ObjectValue {
|
|
2658
|
-
constructor(
|
|
2659
|
-
super(
|
|
2660
|
-
$call: new MacroFunction(scope,
|
|
2739
|
+
constructor() {
|
|
2740
|
+
super({
|
|
2741
|
+
$call: new MacroFunction((scope, cell, size = new LiteralValue(64)) => {
|
|
2661
2742
|
if (!(cell instanceof SenseableValue))
|
|
2662
2743
|
throw new CompilerError("Memory cell must be a senseable value.");
|
|
2663
2744
|
if (!(size instanceof LiteralValue && typeof size.data === "number"))
|
|
2664
2745
|
throw new CompilerError("The memory size must be a number literal.");
|
|
2665
|
-
return [new MemoryMacro(
|
|
2746
|
+
return [new MemoryMacro(cell, size), []];
|
|
2666
2747
|
}),
|
|
2667
2748
|
});
|
|
2668
2749
|
}
|
|
@@ -2670,9 +2751,9 @@ class MemoryBuilder extends ObjectValue {
|
|
|
2670
2751
|
|
|
2671
2752
|
const dynamicVars = ["time", "tick"];
|
|
2672
2753
|
class NamespaceMacro extends ObjectValue {
|
|
2673
|
-
constructor(
|
|
2674
|
-
super(
|
|
2675
|
-
$get: new MacroFunction(scope, prop => {
|
|
2754
|
+
constructor({ changeCasing = false } = {}) {
|
|
2755
|
+
super({
|
|
2756
|
+
$get: new MacroFunction((scope, prop) => {
|
|
2676
2757
|
if (!(prop instanceof LiteralValue) || typeof prop.data !== "string")
|
|
2677
2758
|
throw new CompilerError("Cannot use dynamic properties on namespace macros");
|
|
2678
2759
|
const symbolName = this.changeCasing
|
|
@@ -2696,7 +2777,7 @@ class NamespaceMacro extends ObjectValue {
|
|
|
2696
2777
|
}
|
|
2697
2778
|
class VarsNamespace extends NamespaceMacro {
|
|
2698
2779
|
constructor(scope) {
|
|
2699
|
-
super(
|
|
2780
|
+
super();
|
|
2700
2781
|
Object.assign(this.data, {
|
|
2701
2782
|
unit: new ValueOwner({
|
|
2702
2783
|
scope,
|
|
@@ -2713,8 +2794,8 @@ class VarsNamespace extends NamespaceMacro {
|
|
|
2713
2794
|
}
|
|
2714
2795
|
|
|
2715
2796
|
class GetGlobal extends MacroFunction {
|
|
2716
|
-
constructor(
|
|
2717
|
-
super(scope,
|
|
2797
|
+
constructor(mutability) {
|
|
2798
|
+
super((scope, name) => {
|
|
2718
2799
|
if (!(name instanceof LiteralValue) || typeof name.data !== "string")
|
|
2719
2800
|
throw new CompilerError("The name parameter must be a string literal.");
|
|
2720
2801
|
const owner = new ValueOwner({
|
|
@@ -2730,22 +2811,77 @@ class GetGlobal extends MacroFunction {
|
|
|
2730
2811
|
}
|
|
2731
2812
|
|
|
2732
2813
|
class Asm extends MacroFunction {
|
|
2733
|
-
constructor(
|
|
2734
|
-
super(scope,
|
|
2814
|
+
constructor() {
|
|
2815
|
+
super((scope, stringsArray, ...values) => {
|
|
2735
2816
|
if (!isTemplateObjectArray(stringsArray))
|
|
2736
2817
|
throw new CompilerError("Expected to receive a template strings array");
|
|
2737
2818
|
const args = [];
|
|
2738
2819
|
for (let i = 0; i < values.length; i++) {
|
|
2739
|
-
const [item] = stringsArray.get(scope, new LiteralValue(
|
|
2820
|
+
const [item] = stringsArray.get(scope, new LiteralValue(i));
|
|
2740
2821
|
args.push(item.data);
|
|
2741
2822
|
args.push(values[i]);
|
|
2742
2823
|
}
|
|
2743
2824
|
const { length } = stringsArray.data;
|
|
2744
|
-
const [tail] = stringsArray.get(scope, new LiteralValue(
|
|
2825
|
+
const [tail] = stringsArray.get(scope, new LiteralValue(length.data - 1));
|
|
2745
2826
|
args.push(tail.data);
|
|
2746
|
-
return [null,
|
|
2827
|
+
return [null, formatInstructions(args)];
|
|
2747
2828
|
});
|
|
2748
2829
|
}
|
|
2830
|
+
}
|
|
2831
|
+
/** Splits multiline asm calls and formats each line. */
|
|
2832
|
+
function formatInstructions(args) {
|
|
2833
|
+
const instructions = [];
|
|
2834
|
+
let buffer = [];
|
|
2835
|
+
for (let i = 0; i < args.length; i++) {
|
|
2836
|
+
const arg = args[i];
|
|
2837
|
+
if (typeof arg !== "string" || !arg.includes("\n")) {
|
|
2838
|
+
buffer.push(arg);
|
|
2839
|
+
continue;
|
|
2840
|
+
}
|
|
2841
|
+
const segments = arg.split("\n");
|
|
2842
|
+
const params = [...buffer, segments[0]];
|
|
2843
|
+
if (validateInstructionArgs(params)) {
|
|
2844
|
+
instructions.push(new ZeroSpaceInstruction(...params));
|
|
2845
|
+
buffer = [];
|
|
2846
|
+
}
|
|
2847
|
+
// iterates over all segments except the first and last
|
|
2848
|
+
// the first segment was already processed above
|
|
2849
|
+
// the last segment will be added to the buffer because there might
|
|
2850
|
+
// be an interpolation after it
|
|
2851
|
+
// and putting it in the buffer makes sure it has a proper output format
|
|
2852
|
+
for (let i = 1; i < segments.length - 1; i++) {
|
|
2853
|
+
const trimmed = segments[i].trim();
|
|
2854
|
+
if (trimmed.length == 0)
|
|
2855
|
+
continue;
|
|
2856
|
+
instructions.push(new ZeroSpaceInstruction(trimmed));
|
|
2857
|
+
}
|
|
2858
|
+
if (segments.length > 1) {
|
|
2859
|
+
buffer.push(segments[segments.length - 1]);
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
if (buffer.length > 0 && validateInstructionArgs(buffer)) {
|
|
2863
|
+
instructions.push(new ZeroSpaceInstruction(...buffer));
|
|
2864
|
+
}
|
|
2865
|
+
return instructions;
|
|
2866
|
+
}
|
|
2867
|
+
/** Determines if an asm line should be generated and trims it at the start and end */
|
|
2868
|
+
function validateInstructionArgs(args) {
|
|
2869
|
+
if (args.length === 0)
|
|
2870
|
+
return false;
|
|
2871
|
+
if (args.length === 1) {
|
|
2872
|
+
const item = args[0];
|
|
2873
|
+
if (typeof item !== "string")
|
|
2874
|
+
return true;
|
|
2875
|
+
args[0] = item.trim();
|
|
2876
|
+
return args[0].length !== 0;
|
|
2877
|
+
}
|
|
2878
|
+
const first = args[0];
|
|
2879
|
+
const last = args[args.length - 1];
|
|
2880
|
+
if (typeof first === "string")
|
|
2881
|
+
args[0] = first.trimStart();
|
|
2882
|
+
if (typeof last === "string")
|
|
2883
|
+
args[args.length - 1] = last.trimEnd();
|
|
2884
|
+
return true;
|
|
2749
2885
|
}
|
|
2750
2886
|
|
|
2751
2887
|
/**
|
|
@@ -2753,53 +2889,53 @@ class Asm extends MacroFunction {
|
|
|
2753
2889
|
*/
|
|
2754
2890
|
function initScope(scope) {
|
|
2755
2891
|
// namespaces
|
|
2756
|
-
scope.hardSet("ControlKind", new NamespaceMacro(
|
|
2892
|
+
scope.hardSet("ControlKind", new NamespaceMacro());
|
|
2757
2893
|
scope.hardSet("Vars", new VarsNamespace(scope));
|
|
2758
|
-
scope.hardSet("Teams", new NamespaceMacro(
|
|
2759
|
-
scope.hardSet("Items", new NamespaceMacro(
|
|
2760
|
-
scope.hardSet("Liquids", new NamespaceMacro(
|
|
2761
|
-
scope.hardSet("Units", new NamespaceMacro(
|
|
2762
|
-
scope.hardSet("LAccess", new NamespaceMacro(
|
|
2763
|
-
scope.hardSet("Blocks", new NamespaceMacro(
|
|
2894
|
+
scope.hardSet("Teams", new NamespaceMacro());
|
|
2895
|
+
scope.hardSet("Items", new NamespaceMacro({ changeCasing: true }));
|
|
2896
|
+
scope.hardSet("Liquids", new NamespaceMacro());
|
|
2897
|
+
scope.hardSet("Units", new NamespaceMacro({ changeCasing: true }));
|
|
2898
|
+
scope.hardSet("LAccess", new NamespaceMacro());
|
|
2899
|
+
scope.hardSet("Blocks", new NamespaceMacro({ changeCasing: true }));
|
|
2764
2900
|
// helper methods
|
|
2765
|
-
scope.hardSet("getBuilding", new GetGlobal(
|
|
2766
|
-
scope.hardSet("getVar", new GetGlobal(
|
|
2767
|
-
scope.hardSet("concat", new Concat(
|
|
2768
|
-
scope.hardSet("asm", new Asm(
|
|
2901
|
+
scope.hardSet("getBuilding", new GetGlobal(EMutability.constant));
|
|
2902
|
+
scope.hardSet("getVar", new GetGlobal(EMutability.mutable));
|
|
2903
|
+
scope.hardSet("concat", new Concat());
|
|
2904
|
+
scope.hardSet("asm", new Asm());
|
|
2769
2905
|
scope.hardSet("Math", new MlogMath(scope));
|
|
2770
|
-
scope.hardSet("Memory", new MemoryBuilder(
|
|
2906
|
+
scope.hardSet("Memory", new MemoryBuilder());
|
|
2771
2907
|
// commands
|
|
2772
|
-
scope.hardSet("draw", new Draw(
|
|
2773
|
-
scope.hardSet("print", new Print(
|
|
2774
|
-
scope.hardSet("printFlush", new PrintFlush(
|
|
2775
|
-
scope.hardSet("drawFlush", new DrawFlush(
|
|
2776
|
-
scope.hardSet("getLink", new GetLink(
|
|
2777
|
-
scope.hardSet("control", new Control(
|
|
2778
|
-
scope.hardSet("radar", new Radar(
|
|
2779
|
-
scope.hardSet("sensor", new Sensor(
|
|
2780
|
-
scope.hardSet("wait", new Wait(
|
|
2781
|
-
scope.hardSet("lookup", new Lookup(
|
|
2782
|
-
scope.hardSet("packColor", new PackColor(
|
|
2783
|
-
scope.hardSet("endScript", new End(
|
|
2784
|
-
scope.hardSet("stopScript", new Stop(
|
|
2785
|
-
scope.hardSet("unitBind", new UnitBind(
|
|
2786
|
-
scope.hardSet("unitControl", new UnitControl(
|
|
2787
|
-
scope.hardSet("unitRadar", new UnitRadar(
|
|
2788
|
-
scope.hardSet("unitLocate", new UnitLocate(
|
|
2908
|
+
scope.hardSet("draw", new Draw());
|
|
2909
|
+
scope.hardSet("print", new Print());
|
|
2910
|
+
scope.hardSet("printFlush", new PrintFlush());
|
|
2911
|
+
scope.hardSet("drawFlush", new DrawFlush());
|
|
2912
|
+
scope.hardSet("getLink", new GetLink());
|
|
2913
|
+
scope.hardSet("control", new Control());
|
|
2914
|
+
scope.hardSet("radar", new Radar());
|
|
2915
|
+
scope.hardSet("sensor", new Sensor());
|
|
2916
|
+
scope.hardSet("wait", new Wait());
|
|
2917
|
+
scope.hardSet("lookup", new Lookup());
|
|
2918
|
+
scope.hardSet("packColor", new PackColor());
|
|
2919
|
+
scope.hardSet("endScript", new End());
|
|
2920
|
+
scope.hardSet("stopScript", new Stop());
|
|
2921
|
+
scope.hardSet("unitBind", new UnitBind());
|
|
2922
|
+
scope.hardSet("unitControl", new UnitControl());
|
|
2923
|
+
scope.hardSet("unitRadar", new UnitRadar());
|
|
2924
|
+
scope.hardSet("unitLocate", new UnitLocate());
|
|
2789
2925
|
// world processor commands
|
|
2790
|
-
scope.hardSet("getBlock", new GetBlock(
|
|
2791
|
-
scope.hardSet("setBlock", new SetBlock(
|
|
2792
|
-
scope.hardSet("spawnUnit", new SpawnUnit(
|
|
2793
|
-
scope.hardSet("applyStatus", new ApplyStatus(
|
|
2794
|
-
scope.hardSet("spawnWave", new SpawnWave(
|
|
2795
|
-
scope.hardSet("setRule", new SetRule(
|
|
2796
|
-
scope.hardSet("flushMessage", new FlushMessage(
|
|
2797
|
-
scope.hardSet("cutscene", new Cutscene(
|
|
2798
|
-
scope.hardSet("explosion", new Explosion(
|
|
2799
|
-
scope.hardSet("setRate", new SetRate(
|
|
2800
|
-
scope.hardSet("fetch", new Fetch(
|
|
2801
|
-
scope.hardSet("getFlag", new GetFlag(
|
|
2802
|
-
scope.hardSet("setFlag", new SetFlag(
|
|
2926
|
+
scope.hardSet("getBlock", new GetBlock());
|
|
2927
|
+
scope.hardSet("setBlock", new SetBlock());
|
|
2928
|
+
scope.hardSet("spawnUnit", new SpawnUnit());
|
|
2929
|
+
scope.hardSet("applyStatus", new ApplyStatus());
|
|
2930
|
+
scope.hardSet("spawnWave", new SpawnWave());
|
|
2931
|
+
scope.hardSet("setRule", new SetRule());
|
|
2932
|
+
scope.hardSet("flushMessage", new FlushMessage());
|
|
2933
|
+
scope.hardSet("cutscene", new Cutscene());
|
|
2934
|
+
scope.hardSet("explosion", new Explosion());
|
|
2935
|
+
scope.hardSet("setRate", new SetRate());
|
|
2936
|
+
scope.hardSet("fetch", new Fetch());
|
|
2937
|
+
scope.hardSet("getFlag", new GetFlag());
|
|
2938
|
+
scope.hardSet("setFlag", new SetFlag());
|
|
2803
2939
|
}
|
|
2804
2940
|
|
|
2805
2941
|
class Compiler {
|
|
@@ -2906,7 +3042,7 @@ class Compiler {
|
|
|
2906
3042
|
*/
|
|
2907
3043
|
handleMany(scope, nodes, handler) {
|
|
2908
3044
|
const lines = [];
|
|
2909
|
-
for (const node of nodes) {
|
|
3045
|
+
for (const node of hoistedFunctionNodes(nodes)) {
|
|
2910
3046
|
const [, nodeLines] = this.handle(scope, node, handler && (() => handler(node)));
|
|
2911
3047
|
lines.push(...nodeLines);
|
|
2912
3048
|
}
|
|
@@ -2936,6 +3072,20 @@ function hideRedundantJumps(inst) {
|
|
|
2936
3072
|
current = inst[searchIndex];
|
|
2937
3073
|
}
|
|
2938
3074
|
}
|
|
3075
|
+
}
|
|
3076
|
+
function* hoistedFunctionNodes(nodes) {
|
|
3077
|
+
// sorting is O(n long n) while this is just O(n)
|
|
3078
|
+
// besides, it's better not to modify the node array
|
|
3079
|
+
for (const node of nodes) {
|
|
3080
|
+
if (node.type === "FunctionDeclaration") {
|
|
3081
|
+
yield node;
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
for (const node of nodes) {
|
|
3085
|
+
if (node.type !== "FunctionDeclaration") {
|
|
3086
|
+
yield node;
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
2939
3089
|
}
|
|
2940
3090
|
|
|
2941
3091
|
exports.Compiler = Compiler;
|