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.mjs
CHANGED
|
@@ -114,7 +114,7 @@ const arithmeticAssignmentOperators = [
|
|
|
114
114
|
"-=",
|
|
115
115
|
"/=",
|
|
116
116
|
];
|
|
117
|
-
const logicalAssignmentOperators = ["&&=", "||="];
|
|
117
|
+
const logicalAssignmentOperators = ["&&=", "||=", "??="];
|
|
118
118
|
const bitwiseAssignmentOperators = [
|
|
119
119
|
"<<=",
|
|
120
120
|
">>=",
|
|
@@ -147,11 +147,10 @@ const singleOperators = [...unaryOperators, ...updateOperators];
|
|
|
147
147
|
const operators = [...leftRightOperators, ...singleOperators];
|
|
148
148
|
|
|
149
149
|
class VoidValue {
|
|
150
|
-
constructor(
|
|
150
|
+
constructor() {
|
|
151
151
|
this.owner = null;
|
|
152
152
|
this.mutability = EMutability.mutable;
|
|
153
153
|
this.macro = false;
|
|
154
|
-
this.scope = scope;
|
|
155
154
|
}
|
|
156
155
|
eval(_scope) {
|
|
157
156
|
throw new CompilerError(`${this} cannot eval.`);
|
|
@@ -208,8 +207,22 @@ class SetInstruction extends InstructionBase {
|
|
|
208
207
|
constructor(store, value) {
|
|
209
208
|
super("set", store, value);
|
|
210
209
|
}
|
|
210
|
+
get store() {
|
|
211
|
+
return this.args[1];
|
|
212
|
+
}
|
|
213
|
+
get value() {
|
|
214
|
+
return this.args[2];
|
|
215
|
+
}
|
|
211
216
|
get hidden() {
|
|
212
|
-
|
|
217
|
+
const { store, value } = this;
|
|
218
|
+
return (this._hidden ||
|
|
219
|
+
// assignment to discarded value
|
|
220
|
+
!store.owner ||
|
|
221
|
+
// self assignment of a store
|
|
222
|
+
(!!store.owner &&
|
|
223
|
+
store instanceof StoreValue &&
|
|
224
|
+
value instanceof StoreValue &&
|
|
225
|
+
store.owner === value.owner));
|
|
213
226
|
}
|
|
214
227
|
}
|
|
215
228
|
|
|
@@ -288,38 +301,6 @@ class ContinueInstruction extends JumpInstruction {
|
|
|
288
301
|
}
|
|
289
302
|
}
|
|
290
303
|
|
|
291
|
-
class ValueOwner {
|
|
292
|
-
/**
|
|
293
|
-
* Creates a new `ValueOwner`, if `value` is already owned,
|
|
294
|
-
* `this` will be aliased to `value`, else `this` will own `value`
|
|
295
|
-
*/
|
|
296
|
-
constructor({ scope, constant = false, value, identifier, name, }) {
|
|
297
|
-
this.scope = scope;
|
|
298
|
-
this.constant = constant;
|
|
299
|
-
this.value = value;
|
|
300
|
-
this.identifier = identifier;
|
|
301
|
-
this.name = name ?? scope.makeTempName();
|
|
302
|
-
this.persistent = !!name;
|
|
303
|
-
this.owned = new Set();
|
|
304
|
-
if (!value.owner?.persistent)
|
|
305
|
-
this.own(value);
|
|
306
|
-
}
|
|
307
|
-
own(target) {
|
|
308
|
-
target.owner = this;
|
|
309
|
-
this.owned.add(target);
|
|
310
|
-
}
|
|
311
|
-
replace(target) {
|
|
312
|
-
this.value.owner = null;
|
|
313
|
-
this.owned.delete(this.value);
|
|
314
|
-
this.value = target;
|
|
315
|
-
this.own(target);
|
|
316
|
-
}
|
|
317
|
-
moveInto(owner) {
|
|
318
|
-
this.owned.forEach(value => owner.own(value));
|
|
319
|
-
this.owned.clear();
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
304
|
class BaseValue extends VoidValue {
|
|
324
305
|
"u-"(scope) {
|
|
325
306
|
const [that, inst] = this.consume(scope);
|
|
@@ -328,7 +309,7 @@ class BaseValue extends VoidValue {
|
|
|
328
309
|
temp,
|
|
329
310
|
[
|
|
330
311
|
...inst,
|
|
331
|
-
new OperationInstruction("sub", temp, new LiteralValue(
|
|
312
|
+
new OperationInstruction("sub", temp, new LiteralValue(0), that),
|
|
332
313
|
],
|
|
333
314
|
];
|
|
334
315
|
}
|
|
@@ -339,7 +320,7 @@ class BaseValue extends VoidValue {
|
|
|
339
320
|
"!"(scope) {
|
|
340
321
|
const [that, inst] = this.consume(scope);
|
|
341
322
|
const temp = new StoreValue(scope);
|
|
342
|
-
const falseLiteral = new LiteralValue(
|
|
323
|
+
const falseLiteral = new LiteralValue(0);
|
|
343
324
|
return [
|
|
344
325
|
temp,
|
|
345
326
|
[...inst, new OperationInstruction("equal", temp, that, falseLiteral)],
|
|
@@ -350,8 +331,33 @@ class BaseValue extends VoidValue {
|
|
|
350
331
|
const temp = new StoreValue(scope);
|
|
351
332
|
return [temp, [...inst, new OperationInstruction("not", temp, that, null)]];
|
|
352
333
|
}
|
|
353
|
-
|
|
354
|
-
|
|
334
|
+
// requires special handling
|
|
335
|
+
// the handler should give an object value to allow the lazy evaluation
|
|
336
|
+
"??"(scope, other) {
|
|
337
|
+
const [left, leftInst] = this.eval(scope);
|
|
338
|
+
const nullLiteral = new LiteralValue(null);
|
|
339
|
+
const endAdress = new LiteralValue(null);
|
|
340
|
+
const [nullTest] = left["=="](scope, nullLiteral);
|
|
341
|
+
if (nullTest instanceof LiteralValue) {
|
|
342
|
+
if (nullTest.data)
|
|
343
|
+
return other.eval(scope);
|
|
344
|
+
else
|
|
345
|
+
return [left, leftInst];
|
|
346
|
+
}
|
|
347
|
+
const [right, rightInst] = other.eval(scope);
|
|
348
|
+
const result = new StoreValue(scope);
|
|
349
|
+
result.ensureOwned();
|
|
350
|
+
return [
|
|
351
|
+
result,
|
|
352
|
+
[
|
|
353
|
+
...leftInst,
|
|
354
|
+
...result["="](scope, left)[1],
|
|
355
|
+
new JumpInstruction(endAdress, EJumpKind.NotEqual, result, nullLiteral),
|
|
356
|
+
...rightInst,
|
|
357
|
+
...result["="](scope, right)[1],
|
|
358
|
+
new AddressResolver(endAdress),
|
|
359
|
+
],
|
|
360
|
+
];
|
|
355
361
|
}
|
|
356
362
|
}
|
|
357
363
|
const operatorMap$1 = {
|
|
@@ -409,6 +415,7 @@ const assignmentToBinary = {
|
|
|
409
415
|
"<<=": "<<",
|
|
410
416
|
"&&=": "&&",
|
|
411
417
|
"||=": "||",
|
|
418
|
+
"??=": "??",
|
|
412
419
|
};
|
|
413
420
|
for (const op in assignmentToBinary) {
|
|
414
421
|
BaseValue.prototype[op] = function (scope, value) {
|
|
@@ -428,23 +435,20 @@ for (const key of updateOperators) {
|
|
|
428
435
|
inst.push(...tempInst);
|
|
429
436
|
}
|
|
430
437
|
const kind = key === "++" ? "+=" : "-=";
|
|
431
|
-
return [
|
|
432
|
-
ret,
|
|
433
|
-
[...inst, ...this[kind](scope, new LiteralValue(scope, 1))[1]],
|
|
434
|
-
];
|
|
438
|
+
return [ret, [...inst, ...this[kind](scope, new LiteralValue(1))[1]]];
|
|
435
439
|
};
|
|
436
440
|
}
|
|
437
441
|
|
|
438
442
|
const literalMethods = {
|
|
439
|
-
length: function (
|
|
443
|
+
length: function () {
|
|
440
444
|
if (typeof this.data !== "string")
|
|
441
445
|
throw new CompilerError("Length method only works on string literal values.");
|
|
442
|
-
return new LiteralValue(
|
|
446
|
+
return new LiteralValue(this.data.length);
|
|
443
447
|
},
|
|
444
448
|
};
|
|
445
449
|
class LiteralValue extends BaseValue {
|
|
446
|
-
constructor(
|
|
447
|
-
super(
|
|
450
|
+
constructor(data) {
|
|
451
|
+
super();
|
|
448
452
|
this.mutability = EMutability.constant;
|
|
449
453
|
this.data = data;
|
|
450
454
|
}
|
|
@@ -472,9 +476,10 @@ class LiteralValue extends BaseValue {
|
|
|
472
476
|
return 1;
|
|
473
477
|
return this.data;
|
|
474
478
|
}
|
|
475
|
-
typeof(
|
|
476
|
-
return [new LiteralValue(
|
|
479
|
+
typeof() {
|
|
480
|
+
return [new LiteralValue("literal"), []];
|
|
477
481
|
}
|
|
482
|
+
ensureOwned() { }
|
|
478
483
|
}
|
|
479
484
|
const operatorMap = {
|
|
480
485
|
"==": (a, b) => +(a == b),
|
|
@@ -506,10 +511,7 @@ for (const key in operatorMap) {
|
|
|
506
511
|
if (!(value instanceof LiteralValue)) {
|
|
507
512
|
return BaseValue.prototype[key].apply(this, [scope, value]);
|
|
508
513
|
}
|
|
509
|
-
return [
|
|
510
|
-
new LiteralValue(scope, fn(this.data, value.data)),
|
|
511
|
-
[],
|
|
512
|
-
];
|
|
514
|
+
return [new LiteralValue(fn(this.data, value.data)), []];
|
|
513
515
|
};
|
|
514
516
|
}
|
|
515
517
|
const unaryOperatorMap = {
|
|
@@ -519,9 +521,9 @@ const unaryOperatorMap = {
|
|
|
519
521
|
"u+": v => +v,
|
|
520
522
|
};
|
|
521
523
|
for (const key in unaryOperatorMap) {
|
|
522
|
-
LiteralValue.prototype[key] = function (
|
|
524
|
+
LiteralValue.prototype[key] = function () {
|
|
523
525
|
const fn = unaryOperatorMap[key];
|
|
524
|
-
return [new LiteralValue(
|
|
526
|
+
return [new LiteralValue(fn(this.data)), []];
|
|
525
527
|
};
|
|
526
528
|
}
|
|
527
529
|
|
|
@@ -600,17 +602,50 @@ function isTemplateObjectArray(value) {
|
|
|
600
602
|
typeof value.data.raw.data.length.data === "number");
|
|
601
603
|
}
|
|
602
604
|
|
|
605
|
+
class ValueOwner {
|
|
606
|
+
/**
|
|
607
|
+
* Creates a new `ValueOwner`, if `value` is already owned,
|
|
608
|
+
* `this` will be aliased to `value`, else `this` will own `value`
|
|
609
|
+
*/
|
|
610
|
+
constructor({ scope, constant = false, value, identifier, name, }) {
|
|
611
|
+
this.scope = scope;
|
|
612
|
+
this.constant = constant;
|
|
613
|
+
this.value = value;
|
|
614
|
+
this.identifier = identifier;
|
|
615
|
+
this.name = name ?? scope.makeTempName();
|
|
616
|
+
this.persistent = !!name;
|
|
617
|
+
this.owned = new Set();
|
|
618
|
+
if (!value.owner?.persistent)
|
|
619
|
+
this.own(value);
|
|
620
|
+
}
|
|
621
|
+
own(target) {
|
|
622
|
+
target.owner = this;
|
|
623
|
+
this.owned.add(target);
|
|
624
|
+
}
|
|
625
|
+
replace(target) {
|
|
626
|
+
this.value.owner = null;
|
|
627
|
+
this.owned.delete(this.value);
|
|
628
|
+
this.value = target;
|
|
629
|
+
this.own(target);
|
|
630
|
+
}
|
|
631
|
+
moveInto(owner) {
|
|
632
|
+
this.owned.forEach(value => owner.own(value));
|
|
633
|
+
this.owned.clear();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
603
637
|
/**
|
|
604
638
|
* `StoreValue` represents values unknown at compile time,
|
|
605
639
|
* mostly used with mutable variables and temporary values
|
|
606
640
|
*/
|
|
607
641
|
class StoreValue extends BaseValue {
|
|
608
642
|
constructor(scope) {
|
|
609
|
-
super(
|
|
643
|
+
super();
|
|
644
|
+
this.scope = scope;
|
|
610
645
|
this.mutability = EMutability.mutable;
|
|
611
646
|
}
|
|
612
|
-
typeof(
|
|
613
|
-
return [new LiteralValue(
|
|
647
|
+
typeof() {
|
|
648
|
+
return [new LiteralValue("store"), []];
|
|
614
649
|
}
|
|
615
650
|
"="(scope, value) {
|
|
616
651
|
if (this.mutability !== EMutability.mutable)
|
|
@@ -637,31 +672,34 @@ class StoreValue extends BaseValue {
|
|
|
637
672
|
this.ensureOwned();
|
|
638
673
|
return [this, []];
|
|
639
674
|
}
|
|
675
|
+
ensureOwned() {
|
|
676
|
+
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
677
|
+
}
|
|
640
678
|
toString() {
|
|
641
679
|
return this.owner?.name ?? discardedName;
|
|
642
680
|
}
|
|
643
681
|
}
|
|
644
682
|
|
|
645
683
|
class ObjectValue extends VoidValue {
|
|
646
|
-
constructor(
|
|
647
|
-
super(
|
|
684
|
+
constructor(data = {}) {
|
|
685
|
+
super();
|
|
648
686
|
this.mutability = EMutability.constant;
|
|
649
687
|
this.macro = true;
|
|
650
688
|
this.data = data;
|
|
651
689
|
}
|
|
652
|
-
static fromArray(
|
|
690
|
+
static fromArray(items, intialData) {
|
|
653
691
|
const data = {
|
|
654
692
|
...intialData,
|
|
655
|
-
length: new LiteralValue(
|
|
693
|
+
length: new LiteralValue(items.length),
|
|
656
694
|
};
|
|
657
695
|
items.forEach((item, i) => {
|
|
658
696
|
if (item)
|
|
659
697
|
data[i] = item;
|
|
660
698
|
});
|
|
661
|
-
return new ObjectValue(
|
|
699
|
+
return new ObjectValue(data);
|
|
662
700
|
}
|
|
663
|
-
typeof(
|
|
664
|
-
return [new LiteralValue(
|
|
701
|
+
typeof() {
|
|
702
|
+
return [new LiteralValue("object"), []];
|
|
665
703
|
}
|
|
666
704
|
get(scope, key) {
|
|
667
705
|
// avoids naming collisions with keys like
|
|
@@ -698,9 +736,7 @@ class ObjectValue extends VoidValue {
|
|
|
698
736
|
return super.call(scope, args);
|
|
699
737
|
return $call.call(scope, args);
|
|
700
738
|
}
|
|
701
|
-
ensureOwned() {
|
|
702
|
-
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
703
|
-
}
|
|
739
|
+
ensureOwned() { }
|
|
704
740
|
}
|
|
705
741
|
for (const op of operators) {
|
|
706
742
|
ObjectValue.prototype[op] = function (...args) {
|
|
@@ -769,8 +805,8 @@ class SenseableValue extends StoreValue {
|
|
|
769
805
|
* each of them to their counterparts on the right hand value.
|
|
770
806
|
*/
|
|
771
807
|
class DestructuringValue extends VoidValue {
|
|
772
|
-
constructor(
|
|
773
|
-
super(
|
|
808
|
+
constructor(members) {
|
|
809
|
+
super();
|
|
774
810
|
this.members = members;
|
|
775
811
|
this.macro = true;
|
|
776
812
|
}
|
|
@@ -957,7 +993,7 @@ const DeclareObjectPattern = (c, scope, node, kind, base) => {
|
|
|
957
993
|
throw new CompilerError("The rest operator is not supported", prop);
|
|
958
994
|
const { key, value } = prop;
|
|
959
995
|
const keyInst = key.type === "Identifier" && !prop.computed
|
|
960
|
-
? [new LiteralValue(
|
|
996
|
+
? [new LiteralValue(key.name), []]
|
|
961
997
|
: c.handleConsume(scope, prop.key);
|
|
962
998
|
const propInit = init.get(scope, keyInst[0]);
|
|
963
999
|
const declarationInst = Declare(c, scope, value, kind, propInit[0]);
|
|
@@ -966,14 +1002,14 @@ const DeclareObjectPattern = (c, scope, node, kind, base) => {
|
|
|
966
1002
|
return [null, [...inst, ...propertiesInst[1]]];
|
|
967
1003
|
};
|
|
968
1004
|
|
|
969
|
-
const Literal = (_c, scope, node) => [new LiteralValue(
|
|
1005
|
+
const Literal = (_c, scope, node) => [new LiteralValue(node.value), []];
|
|
970
1006
|
const NumericLiteral = Literal;
|
|
971
1007
|
const StringLiteral = Literal;
|
|
972
|
-
const NullLiteral = (
|
|
973
|
-
new LiteralValue(
|
|
1008
|
+
const NullLiteral = () => [
|
|
1009
|
+
new LiteralValue(null),
|
|
974
1010
|
[],
|
|
975
1011
|
];
|
|
976
|
-
const BooleanLiteral = (_c, scope, node) => [new LiteralValue(
|
|
1012
|
+
const BooleanLiteral = (_c, scope, node) => [new LiteralValue(+node.value), []];
|
|
977
1013
|
|
|
978
1014
|
const LRExpression = (c, scope, node) => {
|
|
979
1015
|
const [left, leftInst] = c.handleConsume(scope, node.left);
|
|
@@ -985,35 +1021,26 @@ const BinaryExpression = LRExpression;
|
|
|
985
1021
|
const LogicalExpression = (c, scope, node) => {
|
|
986
1022
|
if (node.operator !== "??")
|
|
987
1023
|
return LRExpression(c, scope, node);
|
|
988
|
-
const
|
|
989
|
-
|
|
1024
|
+
const other = lazyValue({
|
|
1025
|
+
eval: scope => c.handleEval(scope, node.right),
|
|
1026
|
+
consume: scope => c.handleConsume(scope, node.right),
|
|
1027
|
+
});
|
|
990
1028
|
const [left, leftInst] = c.handleEval(scope, node.left);
|
|
991
|
-
const [
|
|
992
|
-
|
|
993
|
-
if (nullTest.data)
|
|
994
|
-
return c.handleEval(scope, node.right);
|
|
995
|
-
else
|
|
996
|
-
return [left, leftInst];
|
|
997
|
-
}
|
|
998
|
-
const [right, rightInst] = c.handleEval(scope, node.right);
|
|
999
|
-
const result = new StoreValue(scope);
|
|
1000
|
-
result.ensureOwned();
|
|
1001
|
-
return [
|
|
1002
|
-
result,
|
|
1003
|
-
[
|
|
1004
|
-
...leftInst,
|
|
1005
|
-
...result["="](scope, left)[1],
|
|
1006
|
-
new JumpInstruction(endAdress, EJumpKind.NotEqual, result, nullLiteral),
|
|
1007
|
-
...rightInst,
|
|
1008
|
-
...result["="](scope, right)[1],
|
|
1009
|
-
new AddressResolver(endAdress),
|
|
1010
|
-
],
|
|
1011
|
-
];
|
|
1029
|
+
const [result, resultInst] = left["??"](scope, other);
|
|
1030
|
+
return [result, [...leftInst, ...resultInst]];
|
|
1012
1031
|
};
|
|
1013
1032
|
const AssignmentExpression = (c, scope, node) => {
|
|
1014
1033
|
const [left, leftInst] = c.handle(scope, node.left);
|
|
1015
1034
|
// doesn't need to consume because the operators already do that
|
|
1016
|
-
const [right, rightInst] =
|
|
1035
|
+
const [right, rightInst] = node.operator !== "??="
|
|
1036
|
+
? c.handleEval(scope, node.right)
|
|
1037
|
+
: [
|
|
1038
|
+
lazyValue({
|
|
1039
|
+
eval: scope => c.handleEval(scope, node.right),
|
|
1040
|
+
consume: scope => c.handleConsume(scope, node.right),
|
|
1041
|
+
}),
|
|
1042
|
+
[],
|
|
1043
|
+
];
|
|
1017
1044
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1018
1045
|
const [op, opInst] = left[node.operator](scope, right);
|
|
1019
1046
|
return [op, [...leftInst, ...rightInst, ...opInst]];
|
|
@@ -1045,13 +1072,13 @@ const ConditionalExpression = (c, scope, node) => {
|
|
|
1045
1072
|
result.ensureOwned();
|
|
1046
1073
|
const consequent = c.handleEval(scope, node.consequent);
|
|
1047
1074
|
const alternate = c.handleEval(scope, node.alternate);
|
|
1048
|
-
const alternateStartAdress = new LiteralValue(
|
|
1049
|
-
const endExpressionAdress = new LiteralValue(
|
|
1075
|
+
const alternateStartAdress = new LiteralValue(null);
|
|
1076
|
+
const endExpressionAdress = new LiteralValue(null);
|
|
1050
1077
|
return [
|
|
1051
1078
|
result,
|
|
1052
1079
|
[
|
|
1053
1080
|
...testInst,
|
|
1054
|
-
new JumpInstruction(alternateStartAdress, EJumpKind.Equal, test, new LiteralValue(
|
|
1081
|
+
new JumpInstruction(alternateStartAdress, EJumpKind.Equal, test, new LiteralValue(0)),
|
|
1055
1082
|
...consequent[1],
|
|
1056
1083
|
...result["="](scope, consequent[0])[1],
|
|
1057
1084
|
new JumpInstruction(endExpressionAdress, EJumpKind.Always),
|
|
@@ -1061,7 +1088,13 @@ const ConditionalExpression = (c, scope, node) => {
|
|
|
1061
1088
|
new AddressResolver(endExpressionAdress),
|
|
1062
1089
|
],
|
|
1063
1090
|
];
|
|
1064
|
-
};
|
|
1091
|
+
};
|
|
1092
|
+
function lazyValue(options) {
|
|
1093
|
+
const value = new VoidValue();
|
|
1094
|
+
value.eval = options.eval;
|
|
1095
|
+
value.consume = options.consume;
|
|
1096
|
+
return value;
|
|
1097
|
+
}
|
|
1065
1098
|
|
|
1066
1099
|
const Identifier = (c, scope, node) => {
|
|
1067
1100
|
return [scope.get(node.name), []];
|
|
@@ -1070,14 +1103,18 @@ const Identifier = (c, scope, node) => {
|
|
|
1070
1103
|
const ExpressionStatement = (c, scope, node) => {
|
|
1071
1104
|
return c.handle(scope, node.expression);
|
|
1072
1105
|
};
|
|
1073
|
-
const BreakStatement = (_, scope) => {
|
|
1074
|
-
const
|
|
1075
|
-
scope
|
|
1106
|
+
const BreakStatement = (_, scope, node) => {
|
|
1107
|
+
const label = node.label?.name;
|
|
1108
|
+
const target = label ? findScopeLabel(scope, label) : scope;
|
|
1109
|
+
const addr = new LiteralValue(null);
|
|
1110
|
+
target.break.bind(addr);
|
|
1076
1111
|
return [null, [new BreakInstruction(addr)]];
|
|
1077
1112
|
};
|
|
1078
|
-
const ContinueStatement = (_, scope) => {
|
|
1079
|
-
const addr = new LiteralValue(
|
|
1080
|
-
|
|
1113
|
+
const ContinueStatement = (_, scope, node) => {
|
|
1114
|
+
const addr = new LiteralValue(null);
|
|
1115
|
+
const label = node.label?.name;
|
|
1116
|
+
const target = label ? findScopeLabel(scope, label) : scope;
|
|
1117
|
+
target.continue.bind(addr);
|
|
1081
1118
|
return [null, [new ContinueInstruction(addr)]];
|
|
1082
1119
|
};
|
|
1083
1120
|
const ReturnStatement = (c, scope, node) => {
|
|
@@ -1086,7 +1123,24 @@ const ReturnStatement = (c, scope, node) => {
|
|
|
1086
1123
|
: [null, []];
|
|
1087
1124
|
const [ret, retInst] = scope.function.return(scope, arg);
|
|
1088
1125
|
return [ret, [...argInst, ...retInst]];
|
|
1089
|
-
};
|
|
1126
|
+
};
|
|
1127
|
+
const LabeledStatement = (c, scope, node) => {
|
|
1128
|
+
const inner = scope.createScope();
|
|
1129
|
+
inner.label = node.label.name;
|
|
1130
|
+
const end = new LiteralValue(null);
|
|
1131
|
+
const endAdress = new AddressResolver(end).bindBreak(inner);
|
|
1132
|
+
const [, bodyInst] = c.handle(inner, node.body);
|
|
1133
|
+
return [null, [...bodyInst, endAdress]];
|
|
1134
|
+
};
|
|
1135
|
+
function findScopeLabel(scope, label) {
|
|
1136
|
+
let current = scope;
|
|
1137
|
+
while (current !== null) {
|
|
1138
|
+
if (current.label === label)
|
|
1139
|
+
return current;
|
|
1140
|
+
current = current.parent;
|
|
1141
|
+
}
|
|
1142
|
+
throw new CompilerError(`Could not find label "${label}"`);
|
|
1143
|
+
}
|
|
1090
1144
|
|
|
1091
1145
|
const IfStatement = (c, scope, node) => {
|
|
1092
1146
|
const inst = [];
|
|
@@ -1098,9 +1152,9 @@ const IfStatement = (c, scope, node) => {
|
|
|
1098
1152
|
inst.push(...c.handle(scope, node.alternate)[1]);
|
|
1099
1153
|
return [null, inst];
|
|
1100
1154
|
}
|
|
1101
|
-
const endIfAddr = new LiteralValue(
|
|
1102
|
-
inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1103
|
-
const endElseAddr = new LiteralValue(
|
|
1155
|
+
const endIfAddr = new LiteralValue(null);
|
|
1156
|
+
inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(0)), ...withAlwaysRuns(c.handle(scope, node.consequent), false)[1], new AddressResolver(endIfAddr));
|
|
1157
|
+
const endElseAddr = new LiteralValue(null);
|
|
1104
1158
|
if (node.alternate) {
|
|
1105
1159
|
inst.push(new JumpInstruction(endElseAddr, EJumpKind.Always), new AddressResolver(endIfAddr), ...withAlwaysRuns(c.handle(scope, node.alternate), false)[1], new AddressResolver(endElseAddr));
|
|
1106
1160
|
}
|
|
@@ -1111,13 +1165,13 @@ const SwitchStatement = (c, scope, node) => {
|
|
|
1111
1165
|
const innerScope = scope.createScope();
|
|
1112
1166
|
const [ref, refInst] = c.handleConsume(scope, node.discriminant);
|
|
1113
1167
|
const inst = [];
|
|
1114
|
-
const endAdress = new LiteralValue(
|
|
1168
|
+
const endAdress = new LiteralValue(null);
|
|
1115
1169
|
const endLine = new AddressResolver(endAdress).bindBreak(innerScope);
|
|
1116
1170
|
const caseJumps = [];
|
|
1117
1171
|
let defaultJump;
|
|
1118
1172
|
for (const scase of node.cases) {
|
|
1119
1173
|
const [, bodyInst] = c.handleMany(innerScope, scase.consequent);
|
|
1120
|
-
const bodyAdress = new LiteralValue(
|
|
1174
|
+
const bodyAdress = new LiteralValue(null);
|
|
1121
1175
|
const bodyLine = new AddressResolver(bodyAdress);
|
|
1122
1176
|
if (!scase.test) {
|
|
1123
1177
|
[defaultJump] = c.handle(innerScope, scase, () => [
|
|
@@ -1171,25 +1225,33 @@ const SwitchStatement = (c, scope, node) => {
|
|
|
1171
1225
|
const WhileStatement = (c, scope, node) => {
|
|
1172
1226
|
const lines = [];
|
|
1173
1227
|
const [test, testLines] = c.handleConsume(scope, node.test);
|
|
1174
|
-
const
|
|
1175
|
-
const
|
|
1176
|
-
const
|
|
1177
|
-
const
|
|
1228
|
+
const childScope = scope.createScope();
|
|
1229
|
+
const startLoopAddr = new LiteralValue(null);
|
|
1230
|
+
const endLoopAddr = new LiteralValue(null);
|
|
1231
|
+
const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(childScope);
|
|
1232
|
+
const endLoopLine = new AddressResolver(endLoopAddr).bindBreak(childScope);
|
|
1233
|
+
if (scope.label) {
|
|
1234
|
+
startLoopLine.bindContinue(scope);
|
|
1235
|
+
}
|
|
1178
1236
|
if (test instanceof LiteralValue) {
|
|
1179
1237
|
if (test.data) {
|
|
1180
|
-
lines.push(startLoopLine, ...c.handle(
|
|
1238
|
+
lines.push(startLoopLine, ...c.handle(childScope, node.body)[1], new JumpInstruction(startLoopAddr, EJumpKind.Always), endLoopLine);
|
|
1181
1239
|
}
|
|
1182
1240
|
return [null, lines];
|
|
1183
1241
|
}
|
|
1184
|
-
lines.push(startLoopLine, ...testLines, new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1242
|
+
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);
|
|
1185
1243
|
return [null, lines];
|
|
1186
1244
|
};
|
|
1187
1245
|
const DoWhileStatement = (c, scope, node) => {
|
|
1188
1246
|
const lines = [];
|
|
1189
1247
|
const [test, testLines] = c.handleConsume(scope, node.test);
|
|
1190
|
-
const
|
|
1191
|
-
const
|
|
1192
|
-
const
|
|
1248
|
+
const childScope = scope.createScope();
|
|
1249
|
+
const startLoopAddr = new LiteralValue(null);
|
|
1250
|
+
const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(childScope);
|
|
1251
|
+
if (scope.label) {
|
|
1252
|
+
startLoopLine.bindContinue(scope);
|
|
1253
|
+
}
|
|
1254
|
+
const [, bodyLines] = c.handle(childScope, node.body);
|
|
1193
1255
|
if (test instanceof LiteralValue) {
|
|
1194
1256
|
if (!test.data)
|
|
1195
1257
|
return [null, [...lines, ...bodyLines]];
|
|
@@ -1203,28 +1265,31 @@ const DoWhileStatement = (c, scope, node) => {
|
|
|
1203
1265
|
],
|
|
1204
1266
|
];
|
|
1205
1267
|
}
|
|
1206
|
-
lines.push(startLoopLine, ...bodyLines, ...testLines, new JumpInstruction(startLoopAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1268
|
+
lines.push(startLoopLine, ...bodyLines, ...testLines, new JumpInstruction(startLoopAddr, EJumpKind.Equal, test, new LiteralValue(1)));
|
|
1207
1269
|
return [null, lines];
|
|
1208
1270
|
};
|
|
1209
1271
|
|
|
1210
|
-
const ForStatement = (c,
|
|
1211
|
-
scope =
|
|
1272
|
+
const ForStatement = (c, parentScope, node) => {
|
|
1273
|
+
const scope = parentScope.createScope();
|
|
1212
1274
|
const initInst = node.init ? c.handle(scope, node.init)[1] : [];
|
|
1213
1275
|
const [test, testLines] = node.test
|
|
1214
1276
|
? c.handleConsume(scope, node.test)
|
|
1215
|
-
: [new LiteralValue(
|
|
1277
|
+
: [new LiteralValue(1), []];
|
|
1216
1278
|
const updateLines = node.update ? c.handle(scope, node.update)[1] : [];
|
|
1217
|
-
const startLoopAddr = new LiteralValue(
|
|
1218
|
-
const endLoopAddr = new LiteralValue(
|
|
1279
|
+
const startLoopAddr = new LiteralValue(null);
|
|
1280
|
+
const endLoopAddr = new LiteralValue(null);
|
|
1219
1281
|
const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(scope);
|
|
1220
1282
|
const endLoopLine = new AddressResolver(endLoopAddr).bindBreak(scope);
|
|
1283
|
+
if (parentScope.label) {
|
|
1284
|
+
startLoopLine.bindContinue(parentScope);
|
|
1285
|
+
}
|
|
1221
1286
|
return [
|
|
1222
1287
|
null,
|
|
1223
1288
|
[
|
|
1224
1289
|
...initInst,
|
|
1225
1290
|
startLoopLine,
|
|
1226
1291
|
...testLines,
|
|
1227
|
-
new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(
|
|
1292
|
+
new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(0)),
|
|
1228
1293
|
...withAlwaysRuns(c.handle(scope, node.body), false)[1],
|
|
1229
1294
|
...updateLines,
|
|
1230
1295
|
new JumpInstruction(startLoopAddr, EJumpKind.Always),
|
|
@@ -1234,20 +1299,20 @@ const ForStatement = (c, scope, node) => {
|
|
|
1234
1299
|
};
|
|
1235
1300
|
|
|
1236
1301
|
class FunctionValue extends VoidValue {
|
|
1237
|
-
constructor({ scope, params, body, c,
|
|
1238
|
-
super(
|
|
1302
|
+
constructor({ scope, params, body, c, }) {
|
|
1303
|
+
super();
|
|
1239
1304
|
this.mutability = EMutability.constant;
|
|
1240
1305
|
this.macro = true;
|
|
1241
1306
|
this.paramOwners = [];
|
|
1242
1307
|
this.bundled = false;
|
|
1243
1308
|
this.initialized = false;
|
|
1309
|
+
this.scope = scope;
|
|
1244
1310
|
this.body = body;
|
|
1245
1311
|
this.c = c;
|
|
1246
|
-
this.node = node;
|
|
1247
1312
|
this.params = params;
|
|
1248
1313
|
}
|
|
1249
|
-
typeof(
|
|
1250
|
-
return [new LiteralValue(
|
|
1314
|
+
typeof() {
|
|
1315
|
+
return [new LiteralValue("function"), []];
|
|
1251
1316
|
}
|
|
1252
1317
|
initScope(name) {
|
|
1253
1318
|
this.childScope = this.scope.createFunction(name);
|
|
@@ -1275,7 +1340,7 @@ class FunctionValue extends VoidValue {
|
|
|
1275
1340
|
this.initialized = true;
|
|
1276
1341
|
const { name } = this.owner;
|
|
1277
1342
|
this.initScope(name);
|
|
1278
|
-
this.addr = new LiteralValue(
|
|
1343
|
+
this.addr = new LiteralValue(null);
|
|
1279
1344
|
this.temp = new ValueOwner({
|
|
1280
1345
|
scope: this.childScope,
|
|
1281
1346
|
name: `${internalPrefix}f${name}`,
|
|
@@ -1309,7 +1374,7 @@ class FunctionValue extends VoidValue {
|
|
|
1309
1374
|
if (!this.bundled)
|
|
1310
1375
|
this.childScope.inst.push(...this.inst);
|
|
1311
1376
|
this.bundled = true;
|
|
1312
|
-
const callAddressLiteral = new LiteralValue(
|
|
1377
|
+
const callAddressLiteral = new LiteralValue(null);
|
|
1313
1378
|
const inst = this.paramOwners
|
|
1314
1379
|
.map(({ value: param }, i) => param["="](scope, args[i])[1])
|
|
1315
1380
|
.reduce((s, c) => s.concat(c), [])
|
|
@@ -1347,7 +1412,7 @@ class FunctionValue extends VoidValue {
|
|
|
1347
1412
|
name: owner.name,
|
|
1348
1413
|
}));
|
|
1349
1414
|
});
|
|
1350
|
-
this.inlineEnd = new LiteralValue(
|
|
1415
|
+
this.inlineEnd = new LiteralValue(null);
|
|
1351
1416
|
this.tryingInline = true;
|
|
1352
1417
|
let inst = this.c.handle(fnScope, this.body)[1];
|
|
1353
1418
|
this.tryingInline = false;
|
|
@@ -1406,7 +1471,6 @@ function handleFunctionNode(c, scope, node) {
|
|
|
1406
1471
|
}
|
|
1407
1472
|
return [
|
|
1408
1473
|
new FunctionValue({
|
|
1409
|
-
node,
|
|
1410
1474
|
scope,
|
|
1411
1475
|
params: params,
|
|
1412
1476
|
body,
|
|
@@ -1452,8 +1516,8 @@ const NewExpression = CallExpression;
|
|
|
1452
1516
|
const TaggedTemplateExpression = (c, scope, node) => {
|
|
1453
1517
|
const [tag, tagInst] = c.handleConsume(scope, node.tag);
|
|
1454
1518
|
const template = node.quasi;
|
|
1455
|
-
const stringsObject = ObjectValue.fromArray(
|
|
1456
|
-
raw: ObjectValue.fromArray(
|
|
1519
|
+
const stringsObject = ObjectValue.fromArray(template.quasis.map(quasi => new LiteralValue(quasi.value.cooked ?? "")), {
|
|
1520
|
+
raw: ObjectValue.fromArray(template.quasis.map(quasi => new LiteralValue(quasi.value.raw))),
|
|
1457
1521
|
});
|
|
1458
1522
|
const expressions = [];
|
|
1459
1523
|
const expressionInsts = [];
|
|
@@ -1498,7 +1562,7 @@ const ObjectExpression = (c, scope, node) => {
|
|
|
1498
1562
|
data[index] = member;
|
|
1499
1563
|
inst.push(...memberInst);
|
|
1500
1564
|
}
|
|
1501
|
-
return [new ObjectValue(
|
|
1565
|
+
return [new ObjectValue(data), inst];
|
|
1502
1566
|
};
|
|
1503
1567
|
const ArrayExpression = (c, scope, node) => {
|
|
1504
1568
|
const items = [];
|
|
@@ -1510,13 +1574,13 @@ const ArrayExpression = (c, scope, node) => {
|
|
|
1510
1574
|
items.push(value);
|
|
1511
1575
|
inst.push(...valueInst);
|
|
1512
1576
|
});
|
|
1513
|
-
return [ObjectValue.fromArray(
|
|
1577
|
+
return [ObjectValue.fromArray(items), inst];
|
|
1514
1578
|
};
|
|
1515
1579
|
const MemberExpression = (c, scope, node) => {
|
|
1516
1580
|
const [obj, objInst] = c.handleConsume(scope, node.object);
|
|
1517
1581
|
const [prop, propInst] = node.computed
|
|
1518
1582
|
? c.handleConsume(scope, node.property)
|
|
1519
|
-
: [new LiteralValue(
|
|
1583
|
+
: [new LiteralValue(node.property.name), []];
|
|
1520
1584
|
const [got, gotInst] = obj.get(scope, prop);
|
|
1521
1585
|
return [got, [...objInst, ...propInst, ...gotInst]];
|
|
1522
1586
|
};
|
|
@@ -1531,9 +1595,9 @@ const ArrayPattern = (c, scope, node) => {
|
|
|
1531
1595
|
if (!valueInst[0])
|
|
1532
1596
|
throw new CompilerError("Destructuring element must resolve to a value", element);
|
|
1533
1597
|
inst.push(...valueInst[1]);
|
|
1534
|
-
members.set(new LiteralValue(
|
|
1598
|
+
members.set(new LiteralValue(i), valueInst[0]);
|
|
1535
1599
|
}
|
|
1536
|
-
return [new DestructuringValue(
|
|
1600
|
+
return [new DestructuringValue(members), inst];
|
|
1537
1601
|
};
|
|
1538
1602
|
const ObjectPattern = (c, scope, node) => {
|
|
1539
1603
|
const inst = [];
|
|
@@ -1545,7 +1609,7 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
1545
1609
|
continue;
|
|
1546
1610
|
const { key } = prop;
|
|
1547
1611
|
const keyInst = !prop.computed && key.type === "Identifier"
|
|
1548
|
-
? [new LiteralValue(
|
|
1612
|
+
? [new LiteralValue(key.name), []]
|
|
1549
1613
|
: c.handleConsume(scope, prop.key);
|
|
1550
1614
|
inst.push(...keyInst[1]);
|
|
1551
1615
|
const valueInst = c.handle(scope, prop.value);
|
|
@@ -1554,7 +1618,7 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
1554
1618
|
inst.push(...valueInst[1]);
|
|
1555
1619
|
members.set(keyInst[0], valueInst[0]);
|
|
1556
1620
|
}
|
|
1557
|
-
return [new DestructuringValue(
|
|
1621
|
+
return [new DestructuringValue(members), inst];
|
|
1558
1622
|
};
|
|
1559
1623
|
|
|
1560
1624
|
const TemplateLiteral = () => {
|
|
@@ -1594,7 +1658,7 @@ const TSEnumDeclaration = (c, scope, node) => {
|
|
|
1594
1658
|
throw new CompilerError("This enum member must be initialized", member);
|
|
1595
1659
|
const [value] = member.initializer
|
|
1596
1660
|
? c.handleEval(scope, member.initializer)
|
|
1597
|
-
: [new LiteralValue(
|
|
1661
|
+
: [new LiteralValue(counter)];
|
|
1598
1662
|
if (!(value instanceof LiteralValue))
|
|
1599
1663
|
throw new CompilerError("Enum members must contain literal values", member);
|
|
1600
1664
|
if (typeof value.data === "number") {
|
|
@@ -1609,7 +1673,7 @@ const TSEnumDeclaration = (c, scope, node) => {
|
|
|
1609
1673
|
}
|
|
1610
1674
|
scope.set(new ValueOwner({
|
|
1611
1675
|
scope,
|
|
1612
|
-
value: new ObjectValue(
|
|
1676
|
+
value: new ObjectValue(data),
|
|
1613
1677
|
constant: true,
|
|
1614
1678
|
identifier: node.id.name,
|
|
1615
1679
|
name: nodeName(node, !c.compactNames && node.id.name),
|
|
@@ -1641,6 +1705,7 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1641
1705
|
BreakStatement: BreakStatement,
|
|
1642
1706
|
ContinueStatement: ContinueStatement,
|
|
1643
1707
|
ReturnStatement: ReturnStatement,
|
|
1708
|
+
LabeledStatement: LabeledStatement,
|
|
1644
1709
|
IfStatement: IfStatement,
|
|
1645
1710
|
SwitchStatement: SwitchStatement,
|
|
1646
1711
|
WhileStatement: WhileStatement,
|
|
@@ -1670,14 +1735,14 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1670
1735
|
});
|
|
1671
1736
|
|
|
1672
1737
|
class MacroFunction extends VoidValue {
|
|
1673
|
-
constructor(
|
|
1674
|
-
super(
|
|
1738
|
+
constructor(fn) {
|
|
1739
|
+
super();
|
|
1675
1740
|
this.macro = true;
|
|
1676
|
-
this.
|
|
1741
|
+
this.mutability = EMutability.constant;
|
|
1677
1742
|
this.fn = fn;
|
|
1678
1743
|
}
|
|
1679
1744
|
call(scope, args) {
|
|
1680
|
-
return this.fn.apply(this, args);
|
|
1745
|
+
return this.fn.apply(this, [scope, ...args]);
|
|
1681
1746
|
}
|
|
1682
1747
|
eval(_scope) {
|
|
1683
1748
|
return [this, []];
|
|
@@ -1708,16 +1773,31 @@ const mathOperations = {
|
|
|
1708
1773
|
sqrt: a => Math.sqrt(a),
|
|
1709
1774
|
rand: null,
|
|
1710
1775
|
};
|
|
1776
|
+
function mathConstant(scope, name) {
|
|
1777
|
+
return new ValueOwner({
|
|
1778
|
+
scope,
|
|
1779
|
+
constant: true,
|
|
1780
|
+
name,
|
|
1781
|
+
value: assign(new StoreValue(scope), {
|
|
1782
|
+
mutability: EMutability.constant,
|
|
1783
|
+
}),
|
|
1784
|
+
}).value;
|
|
1785
|
+
}
|
|
1711
1786
|
function createMacroMathOperations(scope) {
|
|
1712
|
-
const macroMathOperations = {
|
|
1787
|
+
const macroMathOperations = {
|
|
1788
|
+
PI: mathConstant(scope, "@pi"),
|
|
1789
|
+
E: mathConstant(scope, "@e"),
|
|
1790
|
+
degToRad: mathConstant(scope, "@degToRad"),
|
|
1791
|
+
radToDeg: mathConstant(scope, "@radToDeg"),
|
|
1792
|
+
};
|
|
1713
1793
|
for (const key in mathOperations) {
|
|
1714
1794
|
const fn = mathOperations[key];
|
|
1715
|
-
macroMathOperations[key] = new MacroFunction(scope,
|
|
1795
|
+
macroMathOperations[key] = new MacroFunction((scope, a, b) => {
|
|
1716
1796
|
if (b) {
|
|
1717
1797
|
if (fn && a instanceof LiteralValue && b instanceof LiteralValue) {
|
|
1718
1798
|
if (typeof a.data !== "number" || typeof b.data !== "number")
|
|
1719
1799
|
throw new CompilerError("Cannot do math operation with non-numerical literals.");
|
|
1720
|
-
return [new LiteralValue(
|
|
1800
|
+
return [new LiteralValue(fn(a.num, b.num)), []];
|
|
1721
1801
|
}
|
|
1722
1802
|
const temp = new StoreValue(scope);
|
|
1723
1803
|
return [temp, [new OperationInstruction(key, temp, a, b)]];
|
|
@@ -1725,7 +1805,7 @@ function createMacroMathOperations(scope) {
|
|
|
1725
1805
|
if (fn && a instanceof LiteralValue) {
|
|
1726
1806
|
if (typeof a.data !== "number")
|
|
1727
1807
|
throw new CompilerError("Cannot do math operation with non-numerical literal.");
|
|
1728
|
-
return [new LiteralValue(
|
|
1808
|
+
return [new LiteralValue(fn(a.num)), []];
|
|
1729
1809
|
}
|
|
1730
1810
|
const temp = new StoreValue(scope);
|
|
1731
1811
|
return [temp, [new OperationInstruction(key, temp, a, b)]];
|
|
@@ -1735,20 +1815,20 @@ function createMacroMathOperations(scope) {
|
|
|
1735
1815
|
}
|
|
1736
1816
|
class MlogMath extends ObjectValue {
|
|
1737
1817
|
constructor(scope) {
|
|
1738
|
-
super(
|
|
1818
|
+
super(createMacroMathOperations(scope));
|
|
1739
1819
|
}
|
|
1740
1820
|
}
|
|
1741
1821
|
// op angle result a b
|
|
1742
1822
|
// op len result a b
|
|
1743
1823
|
|
|
1744
1824
|
class Concat extends MacroFunction {
|
|
1745
|
-
constructor(
|
|
1746
|
-
super(scope,
|
|
1825
|
+
constructor() {
|
|
1826
|
+
super((scope, ...values) => {
|
|
1747
1827
|
for (const value of values)
|
|
1748
1828
|
if (!(value instanceof LiteralValue))
|
|
1749
1829
|
throw new CompilerError("Concat arguments must all be literal values.");
|
|
1750
1830
|
return [
|
|
1751
|
-
new LiteralValue(
|
|
1831
|
+
new LiteralValue(values.map(v => v.data).join("")),
|
|
1752
1832
|
[],
|
|
1753
1833
|
];
|
|
1754
1834
|
});
|
|
@@ -1803,18 +1883,18 @@ function assertObjectFields(value, fields) {
|
|
|
1803
1883
|
}
|
|
1804
1884
|
|
|
1805
1885
|
/** Used to create namespaces that contain multiple methods that map into instructions */
|
|
1806
|
-
function createOverloadNamespace({
|
|
1886
|
+
function createOverloadNamespace({ overloads, handler, }) {
|
|
1807
1887
|
const result = {};
|
|
1808
1888
|
for (const key in overloads) {
|
|
1809
1889
|
const { named, args } = overloads[key];
|
|
1810
1890
|
if (named) {
|
|
1811
|
-
result[key] = new MacroFunction(scope, options => {
|
|
1891
|
+
result[key] = new MacroFunction((scope, options) => {
|
|
1812
1892
|
assertIsObjectMacro(options, named);
|
|
1813
|
-
return handler(key, ...assertObjectFields(options, args));
|
|
1893
|
+
return handler(scope, key, ...assertObjectFields(options, args));
|
|
1814
1894
|
});
|
|
1815
1895
|
continue;
|
|
1816
1896
|
}
|
|
1817
|
-
result[key] = new MacroFunction(scope,
|
|
1897
|
+
result[key] = new MacroFunction((scope, ...params) => {
|
|
1818
1898
|
const handlerParams = [];
|
|
1819
1899
|
// validate the paramters
|
|
1820
1900
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -1831,16 +1911,15 @@ function createOverloadNamespace({ scope, overloads, handler, }) {
|
|
|
1831
1911
|
arg.validate?.(param);
|
|
1832
1912
|
handlerParams.push(param);
|
|
1833
1913
|
}
|
|
1834
|
-
return handler(key, ...handlerParams);
|
|
1914
|
+
return handler(scope, key, ...handlerParams);
|
|
1835
1915
|
});
|
|
1836
1916
|
}
|
|
1837
1917
|
return result;
|
|
1838
1918
|
}
|
|
1839
1919
|
|
|
1840
1920
|
class Draw extends ObjectValue {
|
|
1841
|
-
constructor(
|
|
1921
|
+
constructor() {
|
|
1842
1922
|
const data = createOverloadNamespace({
|
|
1843
|
-
scope,
|
|
1844
1923
|
overloads: {
|
|
1845
1924
|
clear: {
|
|
1846
1925
|
args: ["r", "g", "b"],
|
|
@@ -1877,17 +1956,17 @@ class Draw extends ObjectValue {
|
|
|
1877
1956
|
args: ["x", "y", "image", "size", "rotation"],
|
|
1878
1957
|
},
|
|
1879
1958
|
},
|
|
1880
|
-
handler(overload, ...args) {
|
|
1959
|
+
handler(scope, overload, ...args) {
|
|
1881
1960
|
return [null, [new InstructionBase("draw", overload, ...args)]];
|
|
1882
1961
|
},
|
|
1883
1962
|
});
|
|
1884
|
-
super(
|
|
1963
|
+
super(data);
|
|
1885
1964
|
}
|
|
1886
1965
|
}
|
|
1887
1966
|
|
|
1888
1967
|
class Print extends MacroFunction {
|
|
1889
|
-
constructor(
|
|
1890
|
-
super(scope,
|
|
1968
|
+
constructor() {
|
|
1969
|
+
super((scope, ...values) => {
|
|
1891
1970
|
const [first] = values;
|
|
1892
1971
|
const inst = [];
|
|
1893
1972
|
if (!isTemplateObjectArray(first)) {
|
|
@@ -1900,12 +1979,12 @@ class Print extends MacroFunction {
|
|
|
1900
1979
|
// maybe this should be checked in another way?
|
|
1901
1980
|
const { length } = first.data;
|
|
1902
1981
|
for (let i = 1; i < values.length; i++) {
|
|
1903
|
-
const [string] = first.get(scope, new LiteralValue(
|
|
1982
|
+
const [string] = first.get(scope, new LiteralValue(i - 1));
|
|
1904
1983
|
if (string.data)
|
|
1905
1984
|
inst.push(new InstructionBase("print", string));
|
|
1906
1985
|
inst.push(new InstructionBase("print", values[i]));
|
|
1907
1986
|
}
|
|
1908
|
-
const [tail] = first.get(scope, new LiteralValue(
|
|
1987
|
+
const [tail] = first.get(scope, new LiteralValue(length.data - 1));
|
|
1909
1988
|
if (tail.data)
|
|
1910
1989
|
inst.push(new InstructionBase("print", tail));
|
|
1911
1990
|
return [null, inst];
|
|
@@ -1915,8 +1994,8 @@ class Print extends MacroFunction {
|
|
|
1915
1994
|
|
|
1916
1995
|
const defaultTargetName$1 = "message1";
|
|
1917
1996
|
class PrintFlush extends MacroFunction {
|
|
1918
|
-
constructor(
|
|
1919
|
-
super(scope,
|
|
1997
|
+
constructor() {
|
|
1998
|
+
super((scope, target) => {
|
|
1920
1999
|
if (!target)
|
|
1921
2000
|
return [null, [new InstructionBase("printflush", defaultTargetName$1)]];
|
|
1922
2001
|
if (!(target instanceof SenseableValue))
|
|
@@ -1928,8 +2007,8 @@ class PrintFlush extends MacroFunction {
|
|
|
1928
2007
|
|
|
1929
2008
|
const defaultTargetName = "display1";
|
|
1930
2009
|
class DrawFlush extends MacroFunction {
|
|
1931
|
-
constructor(
|
|
1932
|
-
super(scope,
|
|
2010
|
+
constructor() {
|
|
2011
|
+
super((scope, target) => {
|
|
1933
2012
|
if (!target)
|
|
1934
2013
|
return [null, [new InstructionBase("drawflush", defaultTargetName)]];
|
|
1935
2014
|
if (!(target instanceof SenseableValue))
|
|
@@ -1940,16 +2019,15 @@ class DrawFlush extends MacroFunction {
|
|
|
1940
2019
|
}
|
|
1941
2020
|
|
|
1942
2021
|
class GetBlock extends ObjectValue {
|
|
1943
|
-
constructor(
|
|
2022
|
+
constructor() {
|
|
1944
2023
|
const data = createOverloadNamespace({
|
|
1945
|
-
scope,
|
|
1946
2024
|
overloads: {
|
|
1947
2025
|
floor: { args: ["x", "y"] },
|
|
1948
2026
|
ore: { args: ["x", "y"] },
|
|
1949
2027
|
block: { args: ["x", "y"] },
|
|
1950
2028
|
building: { args: ["x", "y"] },
|
|
1951
2029
|
},
|
|
1952
|
-
handler(overload, x, y) {
|
|
2030
|
+
handler(scope, overload, x, y) {
|
|
1953
2031
|
const output = overload === "building"
|
|
1954
2032
|
? new SenseableValue(scope)
|
|
1955
2033
|
: new StoreValue(scope);
|
|
@@ -1959,13 +2037,13 @@ class GetBlock extends ObjectValue {
|
|
|
1959
2037
|
];
|
|
1960
2038
|
},
|
|
1961
2039
|
});
|
|
1962
|
-
super(
|
|
2040
|
+
super(data);
|
|
1963
2041
|
}
|
|
1964
2042
|
}
|
|
1965
2043
|
|
|
1966
2044
|
class GetLink extends MacroFunction {
|
|
1967
|
-
constructor(
|
|
1968
|
-
super(scope,
|
|
2045
|
+
constructor() {
|
|
2046
|
+
super((scope, index) => {
|
|
1969
2047
|
if (!(index instanceof StoreValue) &&
|
|
1970
2048
|
(!(index instanceof LiteralValue) || typeof index.data !== "number"))
|
|
1971
2049
|
throw new CompilerError("The getlink index must be a number literal or a store");
|
|
@@ -1976,9 +2054,8 @@ class GetLink extends MacroFunction {
|
|
|
1976
2054
|
}
|
|
1977
2055
|
|
|
1978
2056
|
class Control extends ObjectValue {
|
|
1979
|
-
constructor(
|
|
1980
|
-
super(
|
|
1981
|
-
scope,
|
|
2057
|
+
constructor() {
|
|
2058
|
+
super(createOverloadNamespace({
|
|
1982
2059
|
overloads: {
|
|
1983
2060
|
enabled: { args: ["building", "value"] },
|
|
1984
2061
|
shoot: {
|
|
@@ -1992,7 +2069,7 @@ class Control extends ObjectValue {
|
|
|
1992
2069
|
config: { args: ["building", "value"] },
|
|
1993
2070
|
color: { args: ["building", "r", "g", "b"] },
|
|
1994
2071
|
},
|
|
1995
|
-
handler(overload, ...args) {
|
|
2072
|
+
handler(scope, overload, ...args) {
|
|
1996
2073
|
return [null, [new InstructionBase("control", overload, ...args)]];
|
|
1997
2074
|
},
|
|
1998
2075
|
}));
|
|
@@ -2017,8 +2094,8 @@ const validRadarSorts = [
|
|
|
2017
2094
|
"maxHealth",
|
|
2018
2095
|
];
|
|
2019
2096
|
class Radar extends MacroFunction {
|
|
2020
|
-
constructor(
|
|
2021
|
-
super(scope, options => {
|
|
2097
|
+
constructor() {
|
|
2098
|
+
super((scope, options) => {
|
|
2022
2099
|
assertIsObjectMacro(options, "The radar options");
|
|
2023
2100
|
const { building, filters, order, sort } = options.data;
|
|
2024
2101
|
if (!(building instanceof SenseableValue))
|
|
@@ -2049,8 +2126,8 @@ class Radar extends MacroFunction {
|
|
|
2049
2126
|
}
|
|
2050
2127
|
|
|
2051
2128
|
class Sensor extends MacroFunction {
|
|
2052
|
-
constructor(
|
|
2053
|
-
super(scope,
|
|
2129
|
+
constructor() {
|
|
2130
|
+
super((scope, property, target) => {
|
|
2054
2131
|
if (!(property instanceof StoreValue))
|
|
2055
2132
|
throw new CompilerError("The sensor property must be a store");
|
|
2056
2133
|
if (!(target instanceof SenseableValue))
|
|
@@ -2064,8 +2141,8 @@ class Sensor extends MacroFunction {
|
|
|
2064
2141
|
}
|
|
2065
2142
|
|
|
2066
2143
|
class Wait extends MacroFunction {
|
|
2067
|
-
constructor(
|
|
2068
|
-
super(scope, seconds => {
|
|
2144
|
+
constructor() {
|
|
2145
|
+
super((scope, seconds) => {
|
|
2069
2146
|
if (!(seconds instanceof StoreValue) &&
|
|
2070
2147
|
!(seconds instanceof LiteralValue && typeof seconds.data === "number"))
|
|
2071
2148
|
throw new CompilerError("The wait seconds must be either a number literal or a store");
|
|
@@ -2075,16 +2152,15 @@ class Wait extends MacroFunction {
|
|
|
2075
2152
|
}
|
|
2076
2153
|
|
|
2077
2154
|
class Lookup extends ObjectValue {
|
|
2078
|
-
constructor(
|
|
2155
|
+
constructor() {
|
|
2079
2156
|
const data = createOverloadNamespace({
|
|
2080
|
-
scope,
|
|
2081
2157
|
overloads: {
|
|
2082
2158
|
block: { args: ["index"] },
|
|
2083
2159
|
unit: { args: ["index"] },
|
|
2084
2160
|
item: { args: ["index"] },
|
|
2085
2161
|
liquid: { args: ["index"] },
|
|
2086
2162
|
},
|
|
2087
|
-
handler(overload, index) {
|
|
2163
|
+
handler(scope, overload, index) {
|
|
2088
2164
|
const output = new StoreValue(scope);
|
|
2089
2165
|
return [
|
|
2090
2166
|
output,
|
|
@@ -2092,13 +2168,13 @@ class Lookup extends ObjectValue {
|
|
|
2092
2168
|
];
|
|
2093
2169
|
},
|
|
2094
2170
|
});
|
|
2095
|
-
super(
|
|
2171
|
+
super(data);
|
|
2096
2172
|
}
|
|
2097
2173
|
}
|
|
2098
2174
|
|
|
2099
2175
|
class PackColor extends MacroFunction {
|
|
2100
|
-
constructor(
|
|
2101
|
-
super(scope,
|
|
2176
|
+
constructor() {
|
|
2177
|
+
super((scope, ...args) => {
|
|
2102
2178
|
if (args.length !== 4) {
|
|
2103
2179
|
throw new CompilerError(`Expected 4 arguments, received ${args.length}`);
|
|
2104
2180
|
}
|
|
@@ -2113,15 +2189,14 @@ class PackColor extends MacroFunction {
|
|
|
2113
2189
|
}
|
|
2114
2190
|
|
|
2115
2191
|
class End extends MacroFunction {
|
|
2116
|
-
constructor(
|
|
2117
|
-
super(
|
|
2192
|
+
constructor() {
|
|
2193
|
+
super(() => [null, [new EndInstruction()]]);
|
|
2118
2194
|
}
|
|
2119
2195
|
}
|
|
2120
2196
|
|
|
2121
2197
|
class SetBlock extends ObjectValue {
|
|
2122
|
-
constructor(
|
|
2198
|
+
constructor() {
|
|
2123
2199
|
const data = createOverloadNamespace({
|
|
2124
|
-
scope,
|
|
2125
2200
|
overloads: {
|
|
2126
2201
|
floor: { args: ["x", "y", "to"] },
|
|
2127
2202
|
ore: { args: ["x", "y", "to"] },
|
|
@@ -2130,7 +2205,7 @@ class SetBlock extends ObjectValue {
|
|
|
2130
2205
|
args: ["x", "y", "to", "team", { key: "rotation", default: "0" }],
|
|
2131
2206
|
},
|
|
2132
2207
|
},
|
|
2133
|
-
handler(overload, x, y, to, team, rotation) {
|
|
2208
|
+
handler(scope, overload, x, y, to, team, rotation) {
|
|
2134
2209
|
return [
|
|
2135
2210
|
null,
|
|
2136
2211
|
[
|
|
@@ -2139,13 +2214,13 @@ class SetBlock extends ObjectValue {
|
|
|
2139
2214
|
];
|
|
2140
2215
|
},
|
|
2141
2216
|
});
|
|
2142
|
-
super(
|
|
2217
|
+
super(data);
|
|
2143
2218
|
}
|
|
2144
2219
|
}
|
|
2145
2220
|
|
|
2146
2221
|
class SpawnUnit extends MacroFunction {
|
|
2147
|
-
constructor(
|
|
2148
|
-
super(scope, options => {
|
|
2222
|
+
constructor() {
|
|
2223
|
+
super((scope, options) => {
|
|
2149
2224
|
assertIsObjectMacro(options, "The options");
|
|
2150
2225
|
const { type, x, y, team, rotation } = options.data;
|
|
2151
2226
|
assertIsRuntimeValue(type, "type");
|
|
@@ -2164,14 +2239,14 @@ class SpawnUnit extends MacroFunction {
|
|
|
2164
2239
|
}
|
|
2165
2240
|
|
|
2166
2241
|
class Stop extends MacroFunction {
|
|
2167
|
-
constructor(
|
|
2168
|
-
super(
|
|
2242
|
+
constructor() {
|
|
2243
|
+
super(() => [null, [new InstructionBase("stop")]]);
|
|
2169
2244
|
}
|
|
2170
2245
|
}
|
|
2171
2246
|
|
|
2172
2247
|
class UnitBind extends MacroFunction {
|
|
2173
|
-
constructor(
|
|
2174
|
-
super(scope, type => {
|
|
2248
|
+
constructor() {
|
|
2249
|
+
super((scope, type) => {
|
|
2175
2250
|
if (!(type instanceof StoreValue))
|
|
2176
2251
|
throw new CompilerError("The unitBind type must be a store");
|
|
2177
2252
|
return [null, [new InstructionBase("ubind", type)]];
|
|
@@ -2180,9 +2255,8 @@ class UnitBind extends MacroFunction {
|
|
|
2180
2255
|
}
|
|
2181
2256
|
|
|
2182
2257
|
class UnitControl extends ObjectValue {
|
|
2183
|
-
constructor(
|
|
2258
|
+
constructor() {
|
|
2184
2259
|
const data = createOverloadNamespace({
|
|
2185
|
-
scope,
|
|
2186
2260
|
overloads: {
|
|
2187
2261
|
idle: { args: [] },
|
|
2188
2262
|
stop: { args: [] },
|
|
@@ -2211,21 +2285,21 @@ class UnitControl extends ObjectValue {
|
|
|
2211
2285
|
args: ["x", "y", "radius"],
|
|
2212
2286
|
},
|
|
2213
2287
|
},
|
|
2214
|
-
handler(overload, ...args) {
|
|
2288
|
+
handler(scope, overload, ...args) {
|
|
2215
2289
|
let result = null;
|
|
2216
2290
|
let extraArgs = [];
|
|
2217
2291
|
switch (overload) {
|
|
2218
2292
|
case "getBlock": {
|
|
2219
2293
|
const outType = new StoreValue(scope);
|
|
2220
2294
|
const outBuilding = new SenseableValue(scope);
|
|
2221
|
-
result = ObjectValue.fromArray(
|
|
2222
|
-
extraArgs = [outType, outBuilding, new LiteralValue(
|
|
2295
|
+
result = ObjectValue.fromArray([outType, outBuilding]);
|
|
2296
|
+
extraArgs = [outType, outBuilding, new LiteralValue(0)];
|
|
2223
2297
|
break;
|
|
2224
2298
|
}
|
|
2225
2299
|
case "within": {
|
|
2226
2300
|
const temp = new StoreValue(scope);
|
|
2227
2301
|
result = temp;
|
|
2228
|
-
extraArgs = [temp, new LiteralValue(
|
|
2302
|
+
extraArgs = [temp, new LiteralValue(0)];
|
|
2229
2303
|
break;
|
|
2230
2304
|
}
|
|
2231
2305
|
}
|
|
@@ -2235,13 +2309,13 @@ class UnitControl extends ObjectValue {
|
|
|
2235
2309
|
];
|
|
2236
2310
|
},
|
|
2237
2311
|
});
|
|
2238
|
-
super(
|
|
2312
|
+
super(data);
|
|
2239
2313
|
}
|
|
2240
2314
|
}
|
|
2241
2315
|
|
|
2242
2316
|
class UnitRadar extends MacroFunction {
|
|
2243
|
-
constructor(
|
|
2244
|
-
super(scope, options => {
|
|
2317
|
+
constructor() {
|
|
2318
|
+
super((scope, options) => {
|
|
2245
2319
|
assertIsObjectMacro(options, "The radar options");
|
|
2246
2320
|
const { filters, order, sort } = options.data;
|
|
2247
2321
|
assertIsArrayMacro(filters, "filters");
|
|
@@ -2282,9 +2356,8 @@ const validBuildingGroups = [
|
|
|
2282
2356
|
"reactor",
|
|
2283
2357
|
];
|
|
2284
2358
|
class UnitLocate extends ObjectValue {
|
|
2285
|
-
constructor(
|
|
2359
|
+
constructor() {
|
|
2286
2360
|
const data = createOverloadNamespace({
|
|
2287
|
-
scope,
|
|
2288
2361
|
overloads: {
|
|
2289
2362
|
ore: {
|
|
2290
2363
|
args: ["ore"],
|
|
@@ -2297,7 +2370,7 @@ class UnitLocate extends ObjectValue {
|
|
|
2297
2370
|
args: [],
|
|
2298
2371
|
},
|
|
2299
2372
|
},
|
|
2300
|
-
handler(overload, ...args) {
|
|
2373
|
+
handler(scope, overload, ...args) {
|
|
2301
2374
|
const outFound = new StoreValue(scope);
|
|
2302
2375
|
const outX = new StoreValue(scope);
|
|
2303
2376
|
const outY = new StoreValue(scope);
|
|
@@ -2325,7 +2398,7 @@ class UnitLocate extends ObjectValue {
|
|
|
2325
2398
|
}
|
|
2326
2399
|
}
|
|
2327
2400
|
return [
|
|
2328
|
-
ObjectValue.fromArray(
|
|
2401
|
+
ObjectValue.fromArray([
|
|
2329
2402
|
outFound,
|
|
2330
2403
|
outX,
|
|
2331
2404
|
outY,
|
|
@@ -2335,7 +2408,7 @@ class UnitLocate extends ObjectValue {
|
|
|
2335
2408
|
];
|
|
2336
2409
|
},
|
|
2337
2410
|
});
|
|
2338
|
-
super(
|
|
2411
|
+
super(data);
|
|
2339
2412
|
}
|
|
2340
2413
|
}
|
|
2341
2414
|
|
|
@@ -2356,16 +2429,15 @@ const validEffects = [
|
|
|
2356
2429
|
"blasted",
|
|
2357
2430
|
];
|
|
2358
2431
|
class ApplyStatus extends ObjectValue {
|
|
2359
|
-
constructor(
|
|
2432
|
+
constructor() {
|
|
2360
2433
|
const data = createOverloadNamespace({
|
|
2361
|
-
scope,
|
|
2362
2434
|
overloads: {
|
|
2363
2435
|
apply: {
|
|
2364
2436
|
args: ["status", "unit", { key: "duration", default: "10" }],
|
|
2365
2437
|
},
|
|
2366
2438
|
clear: { args: ["status", "unit"] },
|
|
2367
2439
|
},
|
|
2368
|
-
handler(overload, effect, unit, duration) {
|
|
2440
|
+
handler(scope, overload, effect, unit, duration) {
|
|
2369
2441
|
if (!(effect instanceof LiteralValue))
|
|
2370
2442
|
throw new CompilerError("The status effect must be a string literal");
|
|
2371
2443
|
assertLiteralOneOf(effect, validEffects, "The status effect");
|
|
@@ -2377,13 +2449,13 @@ class ApplyStatus extends ObjectValue {
|
|
|
2377
2449
|
];
|
|
2378
2450
|
},
|
|
2379
2451
|
});
|
|
2380
|
-
super(
|
|
2452
|
+
super(data);
|
|
2381
2453
|
}
|
|
2382
2454
|
}
|
|
2383
2455
|
|
|
2384
2456
|
class SpawnWave extends MacroFunction {
|
|
2385
|
-
constructor(
|
|
2386
|
-
super(scope,
|
|
2457
|
+
constructor() {
|
|
2458
|
+
super((scope, natural, x, y) => {
|
|
2387
2459
|
if (!(natural instanceof LiteralValue) ||
|
|
2388
2460
|
(natural.data !== 1 && natural.data !== 0))
|
|
2389
2461
|
throw new CompilerError("The 'natural' argument must be a boolean literal");
|
|
@@ -2398,9 +2470,8 @@ class SpawnWave extends MacroFunction {
|
|
|
2398
2470
|
}
|
|
2399
2471
|
|
|
2400
2472
|
class SetRule extends ObjectValue {
|
|
2401
|
-
constructor(
|
|
2473
|
+
constructor() {
|
|
2402
2474
|
const data = createOverloadNamespace({
|
|
2403
|
-
scope,
|
|
2404
2475
|
overloads: {
|
|
2405
2476
|
currentWaveTime: { args: ["seconds"] },
|
|
2406
2477
|
waveTimer: { args: ["enabled"] },
|
|
@@ -2418,13 +2489,14 @@ class SetRule extends ObjectValue {
|
|
|
2418
2489
|
solarMultiplier: { args: ["multiplier"] },
|
|
2419
2490
|
buildSpeed: { args: ["team", "multiplier"] },
|
|
2420
2491
|
unitBuildSpeed: { args: ["team", "multiplier"] },
|
|
2492
|
+
unitCost: { args: ["team", "multiplier"] },
|
|
2421
2493
|
unitDamage: { args: ["team", "multiplier"] },
|
|
2422
2494
|
blockHealth: { args: ["team", "multiplier"] },
|
|
2423
2495
|
blockDamage: { args: ["team", "multiplier"] },
|
|
2424
2496
|
rtsMinWeight: { args: ["team", "value"] },
|
|
2425
2497
|
rtsMinSquad: { args: ["team", "value"] },
|
|
2426
2498
|
},
|
|
2427
|
-
handler(overload, ...args) {
|
|
2499
|
+
handler(scope, overload, ...args) {
|
|
2428
2500
|
const params = ["10", "0", "0", "100", "100"];
|
|
2429
2501
|
switch (overload) {
|
|
2430
2502
|
case "mapArea": {
|
|
@@ -2437,6 +2509,7 @@ class SetRule extends ObjectValue {
|
|
|
2437
2509
|
}
|
|
2438
2510
|
case "buildSpeed":
|
|
2439
2511
|
case "unitBuildSpeed":
|
|
2512
|
+
case "unitCost":
|
|
2440
2513
|
case "unitDamage":
|
|
2441
2514
|
case "blockHealth":
|
|
2442
2515
|
case "blockDamage":
|
|
@@ -2444,7 +2517,7 @@ class SetRule extends ObjectValue {
|
|
|
2444
2517
|
case "rtsMinSquad": {
|
|
2445
2518
|
const [team, value] = args;
|
|
2446
2519
|
params[1] = team;
|
|
2447
|
-
params[
|
|
2520
|
+
params[0] = value;
|
|
2448
2521
|
break;
|
|
2449
2522
|
}
|
|
2450
2523
|
default:
|
|
@@ -2453,49 +2526,47 @@ class SetRule extends ObjectValue {
|
|
|
2453
2526
|
return [null, [new InstructionBase("setrule", overload, ...params)]];
|
|
2454
2527
|
},
|
|
2455
2528
|
});
|
|
2456
|
-
super(
|
|
2529
|
+
super(data);
|
|
2457
2530
|
}
|
|
2458
2531
|
}
|
|
2459
2532
|
|
|
2460
2533
|
class FlushMessage extends ObjectValue {
|
|
2461
|
-
constructor(
|
|
2534
|
+
constructor() {
|
|
2462
2535
|
const data = createOverloadNamespace({
|
|
2463
|
-
scope,
|
|
2464
2536
|
overloads: {
|
|
2465
2537
|
notify: { args: [] },
|
|
2466
2538
|
mission: { args: [] },
|
|
2467
2539
|
announce: { args: ["duration"] },
|
|
2468
2540
|
toast: { args: ["duration"] },
|
|
2469
2541
|
},
|
|
2470
|
-
handler(overload, duration) {
|
|
2542
|
+
handler(scope, overload, duration) {
|
|
2471
2543
|
return [null, [new InstructionBase("message", overload, duration)]];
|
|
2472
2544
|
},
|
|
2473
2545
|
});
|
|
2474
|
-
super(
|
|
2546
|
+
super(data);
|
|
2475
2547
|
}
|
|
2476
2548
|
}
|
|
2477
2549
|
|
|
2478
2550
|
class Cutscene extends ObjectValue {
|
|
2479
|
-
constructor(
|
|
2551
|
+
constructor() {
|
|
2480
2552
|
const data = createOverloadNamespace({
|
|
2481
|
-
scope,
|
|
2482
2553
|
overloads: {
|
|
2483
2554
|
pan: { named: "options", args: ["x", "y", "speed"] },
|
|
2484
2555
|
zoom: { args: ["level"] },
|
|
2485
2556
|
stop: { args: [] },
|
|
2486
2557
|
},
|
|
2487
|
-
handler(overload, ...args) {
|
|
2558
|
+
handler(scope, overload, ...args) {
|
|
2488
2559
|
const params = Object.assign(["100", "100", "0.06", "0"], args);
|
|
2489
2560
|
return [null, [new InstructionBase("cutscene", overload, ...params)]];
|
|
2490
2561
|
},
|
|
2491
2562
|
});
|
|
2492
|
-
super(
|
|
2563
|
+
super(data);
|
|
2493
2564
|
}
|
|
2494
2565
|
}
|
|
2495
2566
|
|
|
2496
2567
|
class Explosion extends MacroFunction {
|
|
2497
|
-
constructor(
|
|
2498
|
-
super(scope, options => {
|
|
2568
|
+
constructor() {
|
|
2569
|
+
super((scope, options) => {
|
|
2499
2570
|
assertIsObjectMacro(options, "The options");
|
|
2500
2571
|
const params = assertObjectFields(options, [
|
|
2501
2572
|
"team",
|
|
@@ -2513,15 +2584,14 @@ class Explosion extends MacroFunction {
|
|
|
2513
2584
|
}
|
|
2514
2585
|
|
|
2515
2586
|
class SetRate extends MacroFunction {
|
|
2516
|
-
constructor(
|
|
2517
|
-
super(scope, ipt => [null, [new InstructionBase("setrate", ipt)]]);
|
|
2587
|
+
constructor() {
|
|
2588
|
+
super((scope, ipt) => [null, [new InstructionBase("setrate", ipt)]]);
|
|
2518
2589
|
}
|
|
2519
2590
|
}
|
|
2520
2591
|
|
|
2521
2592
|
class Fetch extends ObjectValue {
|
|
2522
|
-
constructor(
|
|
2593
|
+
constructor() {
|
|
2523
2594
|
const data = createOverloadNamespace({
|
|
2524
|
-
scope,
|
|
2525
2595
|
overloads: {
|
|
2526
2596
|
unit: { args: ["team", "index"] },
|
|
2527
2597
|
unitCount: { args: ["team"] },
|
|
@@ -2532,7 +2602,7 @@ class Fetch extends ObjectValue {
|
|
|
2532
2602
|
build: { args: ["team", "index", "block"] },
|
|
2533
2603
|
buildCount: { args: ["team", "block"] },
|
|
2534
2604
|
},
|
|
2535
|
-
handler(overload, team, ...rest) {
|
|
2605
|
+
handler(scope, overload, team, ...rest) {
|
|
2536
2606
|
const output = new SenseableValue(scope);
|
|
2537
2607
|
const params = ["0", "@conveyor"];
|
|
2538
2608
|
if (overload === "buildCount") {
|
|
@@ -2547,13 +2617,13 @@ class Fetch extends ObjectValue {
|
|
|
2547
2617
|
];
|
|
2548
2618
|
},
|
|
2549
2619
|
});
|
|
2550
|
-
super(
|
|
2620
|
+
super(data);
|
|
2551
2621
|
}
|
|
2552
2622
|
}
|
|
2553
2623
|
|
|
2554
2624
|
class GetFlag extends MacroFunction {
|
|
2555
|
-
constructor(
|
|
2556
|
-
super(scope, flag => {
|
|
2625
|
+
constructor() {
|
|
2626
|
+
super((scope, flag) => {
|
|
2557
2627
|
const result = new StoreValue(scope);
|
|
2558
2628
|
return [result, [new InstructionBase("getflag", result, flag)]];
|
|
2559
2629
|
});
|
|
@@ -2561,8 +2631,8 @@ class GetFlag extends MacroFunction {
|
|
|
2561
2631
|
}
|
|
2562
2632
|
|
|
2563
2633
|
class SetFlag extends MacroFunction {
|
|
2564
|
-
constructor(
|
|
2565
|
-
super(scope,
|
|
2634
|
+
constructor() {
|
|
2635
|
+
super((scope, flag, value) => {
|
|
2566
2636
|
if (!flag)
|
|
2567
2637
|
throw new CompilerError("Missing flag argument");
|
|
2568
2638
|
if (!value)
|
|
@@ -2572,36 +2642,48 @@ class SetFlag extends MacroFunction {
|
|
|
2572
2642
|
}
|
|
2573
2643
|
}
|
|
2574
2644
|
|
|
2575
|
-
class MemoryEntry extends
|
|
2645
|
+
class MemoryEntry extends BaseValue {
|
|
2576
2646
|
constructor(scope, mem, prop) {
|
|
2577
|
-
super(
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
return [temp, [new InstructionBase("read", temp, mem.cell, prop)]];
|
|
2583
|
-
}),
|
|
2584
|
-
$consume: new MacroFunction(scope, () => {
|
|
2585
|
-
if (this.store)
|
|
2586
|
-
return [this.store, []];
|
|
2587
|
-
this.ensureOwned();
|
|
2588
|
-
this.store = new StoreValue(scope);
|
|
2589
|
-
this.owner.own(this.store);
|
|
2590
|
-
return [
|
|
2591
|
-
this.store,
|
|
2592
|
-
[new InstructionBase("read", this.store, mem.cell, prop)],
|
|
2593
|
-
];
|
|
2594
|
-
}),
|
|
2595
|
-
"$=": new MacroFunction(scope, value => {
|
|
2596
|
-
const [data, dataInst] = value.consume(scope);
|
|
2597
|
-
return [
|
|
2598
|
-
data,
|
|
2599
|
-
[...dataInst, new InstructionBase("write", data, mem.cell, prop)],
|
|
2600
|
-
];
|
|
2601
|
-
}),
|
|
2602
|
-
});
|
|
2647
|
+
super();
|
|
2648
|
+
this.scope = scope;
|
|
2649
|
+
this.mem = mem;
|
|
2650
|
+
this.prop = prop;
|
|
2651
|
+
this.macro = true;
|
|
2603
2652
|
this.store = null;
|
|
2604
2653
|
}
|
|
2654
|
+
eval(scope) {
|
|
2655
|
+
if (this.store)
|
|
2656
|
+
return [this.store, []];
|
|
2657
|
+
const temp = new StoreValue(scope);
|
|
2658
|
+
return [
|
|
2659
|
+
temp,
|
|
2660
|
+
[new InstructionBase("read", temp, this.mem.cell, this.prop)],
|
|
2661
|
+
];
|
|
2662
|
+
}
|
|
2663
|
+
consume(scope) {
|
|
2664
|
+
if (this.store)
|
|
2665
|
+
return [this.store, []];
|
|
2666
|
+
this.ensureOwned();
|
|
2667
|
+
this.store = new StoreValue(scope);
|
|
2668
|
+
this.owner.own(this.store);
|
|
2669
|
+
return [
|
|
2670
|
+
this.store,
|
|
2671
|
+
[new InstructionBase("read", this.store, this.mem.cell, this.prop)],
|
|
2672
|
+
];
|
|
2673
|
+
}
|
|
2674
|
+
"="(scope, value) {
|
|
2675
|
+
const [data, dataInst] = value.consume(scope);
|
|
2676
|
+
return [
|
|
2677
|
+
data,
|
|
2678
|
+
[
|
|
2679
|
+
...dataInst,
|
|
2680
|
+
new InstructionBase("write", data, this.mem.cell, this.prop),
|
|
2681
|
+
],
|
|
2682
|
+
];
|
|
2683
|
+
}
|
|
2684
|
+
ensureOwned() {
|
|
2685
|
+
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
2686
|
+
}
|
|
2605
2687
|
}
|
|
2606
2688
|
for (const operator of operators) {
|
|
2607
2689
|
if (operator === "=")
|
|
@@ -2612,9 +2694,9 @@ for (const operator of operators) {
|
|
|
2612
2694
|
};
|
|
2613
2695
|
}
|
|
2614
2696
|
class MemoryMacro extends ObjectValue {
|
|
2615
|
-
constructor(
|
|
2616
|
-
super(
|
|
2617
|
-
$get: new MacroFunction(scope,
|
|
2697
|
+
constructor(cell, size) {
|
|
2698
|
+
super({
|
|
2699
|
+
$get: new MacroFunction((scope, prop) => {
|
|
2618
2700
|
if (prop instanceof LiteralValue && typeof prop.data !== "number")
|
|
2619
2701
|
throw new CompilerError(`Invalid memory object property: "${prop.data}"`);
|
|
2620
2702
|
const obj = new MemoryEntry(scope, this, prop);
|
|
@@ -2624,21 +2706,20 @@ class MemoryMacro extends ObjectValue {
|
|
|
2624
2706
|
size,
|
|
2625
2707
|
});
|
|
2626
2708
|
this.cell = cell;
|
|
2627
|
-
this.name = cell.toString();
|
|
2628
2709
|
}
|
|
2629
2710
|
toString() {
|
|
2630
|
-
return this.
|
|
2711
|
+
return this.cell.toString();
|
|
2631
2712
|
}
|
|
2632
2713
|
}
|
|
2633
2714
|
class MemoryBuilder extends ObjectValue {
|
|
2634
|
-
constructor(
|
|
2635
|
-
super(
|
|
2636
|
-
$call: new MacroFunction(scope,
|
|
2715
|
+
constructor() {
|
|
2716
|
+
super({
|
|
2717
|
+
$call: new MacroFunction((scope, cell, size = new LiteralValue(64)) => {
|
|
2637
2718
|
if (!(cell instanceof SenseableValue))
|
|
2638
2719
|
throw new CompilerError("Memory cell must be a senseable value.");
|
|
2639
2720
|
if (!(size instanceof LiteralValue && typeof size.data === "number"))
|
|
2640
2721
|
throw new CompilerError("The memory size must be a number literal.");
|
|
2641
|
-
return [new MemoryMacro(
|
|
2722
|
+
return [new MemoryMacro(cell, size), []];
|
|
2642
2723
|
}),
|
|
2643
2724
|
});
|
|
2644
2725
|
}
|
|
@@ -2646,9 +2727,9 @@ class MemoryBuilder extends ObjectValue {
|
|
|
2646
2727
|
|
|
2647
2728
|
const dynamicVars = ["time", "tick"];
|
|
2648
2729
|
class NamespaceMacro extends ObjectValue {
|
|
2649
|
-
constructor(
|
|
2650
|
-
super(
|
|
2651
|
-
$get: new MacroFunction(scope, prop => {
|
|
2730
|
+
constructor({ changeCasing = false } = {}) {
|
|
2731
|
+
super({
|
|
2732
|
+
$get: new MacroFunction((scope, prop) => {
|
|
2652
2733
|
if (!(prop instanceof LiteralValue) || typeof prop.data !== "string")
|
|
2653
2734
|
throw new CompilerError("Cannot use dynamic properties on namespace macros");
|
|
2654
2735
|
const symbolName = this.changeCasing
|
|
@@ -2672,7 +2753,7 @@ class NamespaceMacro extends ObjectValue {
|
|
|
2672
2753
|
}
|
|
2673
2754
|
class VarsNamespace extends NamespaceMacro {
|
|
2674
2755
|
constructor(scope) {
|
|
2675
|
-
super(
|
|
2756
|
+
super();
|
|
2676
2757
|
Object.assign(this.data, {
|
|
2677
2758
|
unit: new ValueOwner({
|
|
2678
2759
|
scope,
|
|
@@ -2689,8 +2770,8 @@ class VarsNamespace extends NamespaceMacro {
|
|
|
2689
2770
|
}
|
|
2690
2771
|
|
|
2691
2772
|
class GetGlobal extends MacroFunction {
|
|
2692
|
-
constructor(
|
|
2693
|
-
super(scope,
|
|
2773
|
+
constructor(mutability) {
|
|
2774
|
+
super((scope, name) => {
|
|
2694
2775
|
if (!(name instanceof LiteralValue) || typeof name.data !== "string")
|
|
2695
2776
|
throw new CompilerError("The name parameter must be a string literal.");
|
|
2696
2777
|
const owner = new ValueOwner({
|
|
@@ -2706,22 +2787,77 @@ class GetGlobal extends MacroFunction {
|
|
|
2706
2787
|
}
|
|
2707
2788
|
|
|
2708
2789
|
class Asm extends MacroFunction {
|
|
2709
|
-
constructor(
|
|
2710
|
-
super(scope,
|
|
2790
|
+
constructor() {
|
|
2791
|
+
super((scope, stringsArray, ...values) => {
|
|
2711
2792
|
if (!isTemplateObjectArray(stringsArray))
|
|
2712
2793
|
throw new CompilerError("Expected to receive a template strings array");
|
|
2713
2794
|
const args = [];
|
|
2714
2795
|
for (let i = 0; i < values.length; i++) {
|
|
2715
|
-
const [item] = stringsArray.get(scope, new LiteralValue(
|
|
2796
|
+
const [item] = stringsArray.get(scope, new LiteralValue(i));
|
|
2716
2797
|
args.push(item.data);
|
|
2717
2798
|
args.push(values[i]);
|
|
2718
2799
|
}
|
|
2719
2800
|
const { length } = stringsArray.data;
|
|
2720
|
-
const [tail] = stringsArray.get(scope, new LiteralValue(
|
|
2801
|
+
const [tail] = stringsArray.get(scope, new LiteralValue(length.data - 1));
|
|
2721
2802
|
args.push(tail.data);
|
|
2722
|
-
return [null,
|
|
2803
|
+
return [null, formatInstructions(args)];
|
|
2723
2804
|
});
|
|
2724
2805
|
}
|
|
2806
|
+
}
|
|
2807
|
+
/** Splits multiline asm calls and formats each line. */
|
|
2808
|
+
function formatInstructions(args) {
|
|
2809
|
+
const instructions = [];
|
|
2810
|
+
let buffer = [];
|
|
2811
|
+
for (let i = 0; i < args.length; i++) {
|
|
2812
|
+
const arg = args[i];
|
|
2813
|
+
if (typeof arg !== "string" || !arg.includes("\n")) {
|
|
2814
|
+
buffer.push(arg);
|
|
2815
|
+
continue;
|
|
2816
|
+
}
|
|
2817
|
+
const segments = arg.split("\n");
|
|
2818
|
+
const params = [...buffer, segments[0]];
|
|
2819
|
+
if (validateInstructionArgs(params)) {
|
|
2820
|
+
instructions.push(new ZeroSpaceInstruction(...params));
|
|
2821
|
+
buffer = [];
|
|
2822
|
+
}
|
|
2823
|
+
// iterates over all segments except the first and last
|
|
2824
|
+
// the first segment was already processed above
|
|
2825
|
+
// the last segment will be added to the buffer because there might
|
|
2826
|
+
// be an interpolation after it
|
|
2827
|
+
// and putting it in the buffer makes sure it has a proper output format
|
|
2828
|
+
for (let i = 1; i < segments.length - 1; i++) {
|
|
2829
|
+
const trimmed = segments[i].trim();
|
|
2830
|
+
if (trimmed.length == 0)
|
|
2831
|
+
continue;
|
|
2832
|
+
instructions.push(new ZeroSpaceInstruction(trimmed));
|
|
2833
|
+
}
|
|
2834
|
+
if (segments.length > 1) {
|
|
2835
|
+
buffer.push(segments[segments.length - 1]);
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
if (buffer.length > 0 && validateInstructionArgs(buffer)) {
|
|
2839
|
+
instructions.push(new ZeroSpaceInstruction(...buffer));
|
|
2840
|
+
}
|
|
2841
|
+
return instructions;
|
|
2842
|
+
}
|
|
2843
|
+
/** Determines if an asm line should be generated and trims it at the start and end */
|
|
2844
|
+
function validateInstructionArgs(args) {
|
|
2845
|
+
if (args.length === 0)
|
|
2846
|
+
return false;
|
|
2847
|
+
if (args.length === 1) {
|
|
2848
|
+
const item = args[0];
|
|
2849
|
+
if (typeof item !== "string")
|
|
2850
|
+
return true;
|
|
2851
|
+
args[0] = item.trim();
|
|
2852
|
+
return args[0].length !== 0;
|
|
2853
|
+
}
|
|
2854
|
+
const first = args[0];
|
|
2855
|
+
const last = args[args.length - 1];
|
|
2856
|
+
if (typeof first === "string")
|
|
2857
|
+
args[0] = first.trimStart();
|
|
2858
|
+
if (typeof last === "string")
|
|
2859
|
+
args[args.length - 1] = last.trimEnd();
|
|
2860
|
+
return true;
|
|
2725
2861
|
}
|
|
2726
2862
|
|
|
2727
2863
|
/**
|
|
@@ -2729,53 +2865,53 @@ class Asm extends MacroFunction {
|
|
|
2729
2865
|
*/
|
|
2730
2866
|
function initScope(scope) {
|
|
2731
2867
|
// namespaces
|
|
2732
|
-
scope.hardSet("ControlKind", new NamespaceMacro(
|
|
2868
|
+
scope.hardSet("ControlKind", new NamespaceMacro());
|
|
2733
2869
|
scope.hardSet("Vars", new VarsNamespace(scope));
|
|
2734
|
-
scope.hardSet("Teams", new NamespaceMacro(
|
|
2735
|
-
scope.hardSet("Items", new NamespaceMacro(
|
|
2736
|
-
scope.hardSet("Liquids", new NamespaceMacro(
|
|
2737
|
-
scope.hardSet("Units", new NamespaceMacro(
|
|
2738
|
-
scope.hardSet("LAccess", new NamespaceMacro(
|
|
2739
|
-
scope.hardSet("Blocks", new NamespaceMacro(
|
|
2870
|
+
scope.hardSet("Teams", new NamespaceMacro());
|
|
2871
|
+
scope.hardSet("Items", new NamespaceMacro({ changeCasing: true }));
|
|
2872
|
+
scope.hardSet("Liquids", new NamespaceMacro());
|
|
2873
|
+
scope.hardSet("Units", new NamespaceMacro({ changeCasing: true }));
|
|
2874
|
+
scope.hardSet("LAccess", new NamespaceMacro());
|
|
2875
|
+
scope.hardSet("Blocks", new NamespaceMacro({ changeCasing: true }));
|
|
2740
2876
|
// helper methods
|
|
2741
|
-
scope.hardSet("getBuilding", new GetGlobal(
|
|
2742
|
-
scope.hardSet("getVar", new GetGlobal(
|
|
2743
|
-
scope.hardSet("concat", new Concat(
|
|
2744
|
-
scope.hardSet("asm", new Asm(
|
|
2877
|
+
scope.hardSet("getBuilding", new GetGlobal(EMutability.constant));
|
|
2878
|
+
scope.hardSet("getVar", new GetGlobal(EMutability.mutable));
|
|
2879
|
+
scope.hardSet("concat", new Concat());
|
|
2880
|
+
scope.hardSet("asm", new Asm());
|
|
2745
2881
|
scope.hardSet("Math", new MlogMath(scope));
|
|
2746
|
-
scope.hardSet("Memory", new MemoryBuilder(
|
|
2882
|
+
scope.hardSet("Memory", new MemoryBuilder());
|
|
2747
2883
|
// commands
|
|
2748
|
-
scope.hardSet("draw", new Draw(
|
|
2749
|
-
scope.hardSet("print", new Print(
|
|
2750
|
-
scope.hardSet("printFlush", new PrintFlush(
|
|
2751
|
-
scope.hardSet("drawFlush", new DrawFlush(
|
|
2752
|
-
scope.hardSet("getLink", new GetLink(
|
|
2753
|
-
scope.hardSet("control", new Control(
|
|
2754
|
-
scope.hardSet("radar", new Radar(
|
|
2755
|
-
scope.hardSet("sensor", new Sensor(
|
|
2756
|
-
scope.hardSet("wait", new Wait(
|
|
2757
|
-
scope.hardSet("lookup", new Lookup(
|
|
2758
|
-
scope.hardSet("packColor", new PackColor(
|
|
2759
|
-
scope.hardSet("endScript", new End(
|
|
2760
|
-
scope.hardSet("stopScript", new Stop(
|
|
2761
|
-
scope.hardSet("unitBind", new UnitBind(
|
|
2762
|
-
scope.hardSet("unitControl", new UnitControl(
|
|
2763
|
-
scope.hardSet("unitRadar", new UnitRadar(
|
|
2764
|
-
scope.hardSet("unitLocate", new UnitLocate(
|
|
2884
|
+
scope.hardSet("draw", new Draw());
|
|
2885
|
+
scope.hardSet("print", new Print());
|
|
2886
|
+
scope.hardSet("printFlush", new PrintFlush());
|
|
2887
|
+
scope.hardSet("drawFlush", new DrawFlush());
|
|
2888
|
+
scope.hardSet("getLink", new GetLink());
|
|
2889
|
+
scope.hardSet("control", new Control());
|
|
2890
|
+
scope.hardSet("radar", new Radar());
|
|
2891
|
+
scope.hardSet("sensor", new Sensor());
|
|
2892
|
+
scope.hardSet("wait", new Wait());
|
|
2893
|
+
scope.hardSet("lookup", new Lookup());
|
|
2894
|
+
scope.hardSet("packColor", new PackColor());
|
|
2895
|
+
scope.hardSet("endScript", new End());
|
|
2896
|
+
scope.hardSet("stopScript", new Stop());
|
|
2897
|
+
scope.hardSet("unitBind", new UnitBind());
|
|
2898
|
+
scope.hardSet("unitControl", new UnitControl());
|
|
2899
|
+
scope.hardSet("unitRadar", new UnitRadar());
|
|
2900
|
+
scope.hardSet("unitLocate", new UnitLocate());
|
|
2765
2901
|
// world processor commands
|
|
2766
|
-
scope.hardSet("getBlock", new GetBlock(
|
|
2767
|
-
scope.hardSet("setBlock", new SetBlock(
|
|
2768
|
-
scope.hardSet("spawnUnit", new SpawnUnit(
|
|
2769
|
-
scope.hardSet("applyStatus", new ApplyStatus(
|
|
2770
|
-
scope.hardSet("spawnWave", new SpawnWave(
|
|
2771
|
-
scope.hardSet("setRule", new SetRule(
|
|
2772
|
-
scope.hardSet("flushMessage", new FlushMessage(
|
|
2773
|
-
scope.hardSet("cutscene", new Cutscene(
|
|
2774
|
-
scope.hardSet("explosion", new Explosion(
|
|
2775
|
-
scope.hardSet("setRate", new SetRate(
|
|
2776
|
-
scope.hardSet("fetch", new Fetch(
|
|
2777
|
-
scope.hardSet("getFlag", new GetFlag(
|
|
2778
|
-
scope.hardSet("setFlag", new SetFlag(
|
|
2902
|
+
scope.hardSet("getBlock", new GetBlock());
|
|
2903
|
+
scope.hardSet("setBlock", new SetBlock());
|
|
2904
|
+
scope.hardSet("spawnUnit", new SpawnUnit());
|
|
2905
|
+
scope.hardSet("applyStatus", new ApplyStatus());
|
|
2906
|
+
scope.hardSet("spawnWave", new SpawnWave());
|
|
2907
|
+
scope.hardSet("setRule", new SetRule());
|
|
2908
|
+
scope.hardSet("flushMessage", new FlushMessage());
|
|
2909
|
+
scope.hardSet("cutscene", new Cutscene());
|
|
2910
|
+
scope.hardSet("explosion", new Explosion());
|
|
2911
|
+
scope.hardSet("setRate", new SetRate());
|
|
2912
|
+
scope.hardSet("fetch", new Fetch());
|
|
2913
|
+
scope.hardSet("getFlag", new GetFlag());
|
|
2914
|
+
scope.hardSet("setFlag", new SetFlag());
|
|
2779
2915
|
}
|
|
2780
2916
|
|
|
2781
2917
|
class Compiler {
|
|
@@ -2882,7 +3018,7 @@ class Compiler {
|
|
|
2882
3018
|
*/
|
|
2883
3019
|
handleMany(scope, nodes, handler) {
|
|
2884
3020
|
const lines = [];
|
|
2885
|
-
for (const node of nodes) {
|
|
3021
|
+
for (const node of hoistedFunctionNodes(nodes)) {
|
|
2886
3022
|
const [, nodeLines] = this.handle(scope, node, handler && (() => handler(node)));
|
|
2887
3023
|
lines.push(...nodeLines);
|
|
2888
3024
|
}
|
|
@@ -2912,6 +3048,20 @@ function hideRedundantJumps(inst) {
|
|
|
2912
3048
|
current = inst[searchIndex];
|
|
2913
3049
|
}
|
|
2914
3050
|
}
|
|
3051
|
+
}
|
|
3052
|
+
function* hoistedFunctionNodes(nodes) {
|
|
3053
|
+
// sorting is O(n long n) while this is just O(n)
|
|
3054
|
+
// besides, it's better not to modify the node array
|
|
3055
|
+
for (const node of nodes) {
|
|
3056
|
+
if (node.type === "FunctionDeclaration") {
|
|
3057
|
+
yield node;
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
for (const node of nodes) {
|
|
3061
|
+
if (node.type !== "FunctionDeclaration") {
|
|
3062
|
+
yield node;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
2915
3065
|
}
|
|
2916
3066
|
|
|
2917
3067
|
export { Compiler, CompilerError };
|