mlogjs 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Compiler.d.ts +39 -0
- package/dist/CompilerError.d.ts +33 -0
- package/dist/Scope.d.ts +24 -0
- package/dist/assertions.d.ts +28 -0
- package/dist/bin.cjs +7 -14
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.d.ts +1 -0
- package/dist/handlers/BlockStatement.d.ts +2 -0
- package/dist/handlers/CallExpression.d.ts +4 -0
- package/dist/handlers/File.d.ts +2 -0
- package/dist/handlers/ForStatement.d.ts +2 -0
- package/dist/handlers/Function.d.ts +5 -0
- package/dist/handlers/Identifier.d.ts +2 -0
- package/dist/handlers/IfStatement.d.ts +2 -0
- package/dist/handlers/Literal.d.ts +5 -0
- package/dist/handlers/Object.d.ts +6 -0
- package/dist/handlers/OperationExpressions.d.ts +8 -0
- package/dist/handlers/Program.d.ts +2 -0
- package/dist/handlers/Statements.d.ts +5 -0
- package/dist/handlers/SwitchStatement.d.ts +2 -0
- package/dist/handlers/TemplateExpression.d.ts +2 -0
- package/dist/handlers/Typescript.d.ts +7 -0
- package/dist/handlers/VariableDeclaration.d.ts +3 -0
- package/dist/handlers/WhileStatement.d.ts +3 -0
- package/dist/handlers/index.d.ts +17 -0
- package/dist/index.cjs +1037 -315
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +1037 -315
- package/dist/index.mjs.map +1 -1
- package/dist/initScope.d.ts +5 -0
- package/dist/instructions/AddressResolver.d.ts +12 -0
- package/dist/instructions/ControlInstructions.d.ts +10 -0
- package/dist/instructions/EndInstruction.d.ts +4 -0
- package/dist/instructions/InstructionBase.d.ts +14 -0
- package/dist/instructions/JumpInstruction.d.ts +16 -0
- package/dist/instructions/OperationInstruction.d.ts +5 -0
- package/dist/instructions/SetCounterInstruction.d.ts +5 -0
- package/dist/instructions/SetInstruction.d.ts +6 -0
- package/dist/instructions/ZeroSpaceInstruction.d.ts +4 -0
- package/dist/instructions/index.d.ts +9 -0
- package/dist/{types/macros/RawValue.d.ts → macros/Asm.d.ts} +1 -1
- package/dist/macros/Function.d.ts +13 -0
- package/dist/macros/GetGlobal.d.ts +5 -0
- package/dist/macros/Math.d.ts +5 -0
- package/dist/macros/Memory.d.ts +5 -0
- package/dist/macros/Namespace.d.ts +13 -0
- package/dist/macros/Other.d.ts +5 -0
- package/dist/macros/commands/ApplyStatus.d.ts +5 -0
- package/dist/macros/commands/Control.d.ts +5 -0
- package/dist/macros/commands/Cutscene.d.ts +5 -0
- package/dist/macros/commands/Draw.d.ts +5 -0
- package/dist/macros/commands/DrawFlush.d.ts +5 -0
- package/dist/macros/commands/End.d.ts +5 -0
- package/dist/macros/commands/Explosion.d.ts +5 -0
- package/dist/macros/commands/Fetch.d.ts +5 -0
- package/dist/macros/commands/FlushMessage.d.ts +5 -0
- package/dist/macros/commands/GetBlock.d.ts +5 -0
- package/dist/macros/commands/GetFlag.d.ts +5 -0
- package/dist/macros/commands/GetLink.d.ts +5 -0
- package/dist/macros/commands/Lookup.d.ts +5 -0
- package/dist/macros/commands/PackColor.d.ts +5 -0
- package/dist/macros/commands/Print.d.ts +5 -0
- package/dist/macros/commands/PrintFlush.d.ts +5 -0
- package/dist/macros/commands/Radar.d.ts +7 -0
- package/dist/macros/commands/Sensor.d.ts +5 -0
- package/dist/macros/commands/SetBlock.d.ts +5 -0
- package/dist/macros/commands/SetFlag.d.ts +5 -0
- package/dist/macros/commands/SetRate.d.ts +5 -0
- package/dist/macros/commands/SetRule.d.ts +5 -0
- package/dist/macros/commands/SpawnUnit.d.ts +5 -0
- package/dist/macros/commands/SpawnWave.d.ts +5 -0
- package/dist/macros/commands/Stop.d.ts +5 -0
- package/dist/macros/commands/UnitBind.d.ts +5 -0
- package/dist/macros/commands/UnitControl.d.ts +5 -0
- package/dist/macros/commands/UnitLocate.d.ts +5 -0
- package/dist/macros/commands/UnitRadar.d.ts +5 -0
- package/dist/macros/commands/Wait.d.ts +5 -0
- package/dist/macros/commands/index.d.ts +30 -0
- package/dist/macros/index.d.ts +6 -0
- package/dist/macros/util.d.ts +18 -0
- package/dist/operators.d.ts +25 -0
- package/dist/types/Compiler.d.ts +17 -4
- package/dist/types/CompilerError.d.ts +28 -4
- package/dist/types/assertions.d.ts +28 -0
- package/dist/types/handlers/CallExpression.d.ts +1 -0
- package/dist/types/handlers/SwitchStatement.d.ts +2 -0
- package/dist/types/handlers/index.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/instructions/ControlInstructions.d.ts +3 -1
- package/dist/types/instructions/InstructionBase.d.ts +5 -1
- package/dist/types/instructions/JumpInstruction.d.ts +1 -0
- package/dist/types/macros/Asm.d.ts +5 -0
- package/dist/types/macros/Namespace.d.ts +0 -3
- package/dist/types/macros/commands/ApplyStatus.d.ts +5 -0
- package/dist/types/macros/commands/Control.d.ts +2 -2
- package/dist/types/macros/commands/Cutscene.d.ts +5 -0
- package/dist/types/macros/commands/Draw.d.ts +2 -2
- package/dist/types/macros/commands/Explosion.d.ts +5 -0
- package/dist/types/macros/commands/Fetch.d.ts +5 -0
- package/dist/types/macros/commands/FlushMessage.d.ts +5 -0
- package/dist/types/macros/commands/GetBlock.d.ts +5 -0
- package/dist/types/macros/commands/GetFlag.d.ts +5 -0
- package/dist/types/macros/commands/Lookup.d.ts +2 -2
- package/dist/types/macros/commands/PackColor.d.ts +5 -0
- package/dist/types/macros/commands/Radar.d.ts +2 -2
- package/dist/types/macros/commands/SetBlock.d.ts +5 -0
- package/dist/types/macros/commands/SetFlag.d.ts +5 -0
- package/dist/types/macros/commands/SetRate.d.ts +5 -0
- package/dist/types/macros/commands/SetRule.d.ts +5 -0
- package/dist/types/macros/commands/SpawnUnit.d.ts +5 -0
- package/dist/types/macros/commands/SpawnWave.d.ts +5 -0
- package/dist/types/macros/commands/Stop.d.ts +5 -0
- package/dist/types/macros/commands/UnitControl.d.ts +3 -3
- package/dist/types/macros/commands/UnitLocate.d.ts +2 -2
- package/dist/types/macros/commands/index.d.ts +15 -0
- package/dist/types/macros/util.d.ts +18 -0
- package/dist/types/types.d.ts +14 -0
- package/dist/types/utils.d.ts +19 -2
- package/dist/types/values/BaseValue.d.ts +2 -0
- package/dist/types/values/FunctionValue.d.ts +1 -1
- package/dist/types/values/ObjectValue.d.ts +1 -1
- package/dist/types.d.ts +238 -0
- package/dist/utils.d.ts +47 -0
- package/dist/values/BaseValue.d.ts +9 -0
- package/dist/values/DestructuringValue.d.ts +17 -0
- package/dist/values/FunctionValue.d.ts +47 -0
- package/dist/values/LiteralValue.d.ts +13 -0
- package/dist/values/ObjectValue.d.ts +23 -0
- package/dist/values/SenseableValue.d.ts +23 -0
- package/dist/{types/values/StackValue.d.ts → values/StoreValue.d.ts} +5 -6
- package/dist/values/ValueOwner.d.ts +27 -0
- package/dist/values/VoidValue.d.ts +16 -0
- package/dist/values/index.d.ts +7 -0
- package/lib/commands.d.ts +849 -418
- package/lib/eslib/lib.es2015.core.d.ts +3 -0
- package/lib/globals.d.ts +331 -19
- package/lib/helpers.d.ts +14 -0
- package/lib/kinds.d.ts +3 -2
- package/lib/memory.d.ts +1 -1
- package/lib/traits.d.ts +6 -0
- package/lib/util.d.ts +16 -0
- package/package.json +15 -16
- package/build/Compiler.js +0 -105
- package/build/Compiler.js.map +0 -1
- package/build/CompilerError.js +0 -11
- package/build/CompilerError.js.map +0 -1
- package/build/Scope.js +0 -71
- package/build/Scope.js.map +0 -1
- package/build/bin.js +0 -75
- package/build/bin.js.map +0 -1
- package/build/handlers/BlockStatement.js +0 -14
- package/build/handlers/BlockStatement.js.map +0 -1
- package/build/handlers/CallExpression.js +0 -20
- package/build/handlers/CallExpression.js.map +0 -1
- package/build/handlers/File.js +0 -9
- package/build/handlers/File.js.map +0 -1
- package/build/handlers/ForStatement.js +0 -32
- package/build/handlers/ForStatement.js.map +0 -1
- package/build/handlers/Function.js +0 -47
- package/build/handlers/Function.js.map +0 -1
- package/build/handlers/Identifier.js +0 -8
- package/build/handlers/Identifier.js.map +0 -1
- package/build/handlers/IfStatement.js +0 -25
- package/build/handlers/IfStatement.js.map +0 -1
- package/build/handlers/Literal.js +0 -15
- package/build/handlers/Literal.js.map +0 -1
- package/build/handlers/Object.js +0 -55
- package/build/handlers/Object.js.map +0 -1
- package/build/handlers/OperationExpressions.js +0 -38
- package/build/handlers/OperationExpressions.js.map +0 -1
- package/build/handlers/Program.js +0 -9
- package/build/handlers/Program.js.map +0 -1
- package/build/handlers/Statements.js +0 -30
- package/build/handlers/Statements.js.map +0 -1
- package/build/handlers/TemplateExpression.js +0 -18
- package/build/handlers/TemplateExpression.js.map +0 -1
- package/build/handlers/VariableDeclaration.js +0 -72
- package/build/handlers/VariableDeclaration.js.map +0 -1
- package/build/handlers/WhileStatement.js +0 -23
- package/build/handlers/WhileStatement.js.map +0 -1
- package/build/handlers/index.js +0 -32
- package/build/handlers/index.js.map +0 -1
- package/build/index.js +0 -8
- package/build/index.js.map +0 -1
- package/build/initScope.js +0 -40
- package/build/initScope.js.map +0 -1
- package/build/instructions/AddressResolver.js +0 -31
- package/build/instructions/AddressResolver.js.map +0 -1
- package/build/instructions/ControlInstructions.js +0 -23
- package/build/instructions/ControlInstructions.js.map +0 -1
- package/build/instructions/EndInstruction.js +0 -11
- package/build/instructions/EndInstruction.js.map +0 -1
- package/build/instructions/InstructionBase.js +0 -21
- package/build/instructions/InstructionBase.js.map +0 -1
- package/build/instructions/JumpInstruction.js +0 -22
- package/build/instructions/JumpInstruction.js.map +0 -1
- package/build/instructions/OperationInstruction.js +0 -11
- package/build/instructions/OperationInstruction.js.map +0 -1
- package/build/instructions/SetCounterInstruction.js +0 -11
- package/build/instructions/SetCounterInstruction.js.map +0 -1
- package/build/instructions/SetInstruction.js +0 -11
- package/build/instructions/SetInstruction.js.map +0 -1
- package/build/instructions/ZeroSpaceInstruction.js +0 -11
- package/build/instructions/ZeroSpaceInstruction.js.map +0 -1
- package/build/instructions/index.js +0 -26
- package/build/instructions/index.js.map +0 -1
- package/build/macros/Building.js +0 -89
- package/build/macros/Building.js.map +0 -1
- package/build/macros/Function.js +0 -20
- package/build/macros/Function.js.map +0 -1
- package/build/macros/Math.js +0 -62
- package/build/macros/Math.js.map +0 -1
- package/build/macros/Memory.js +0 -63
- package/build/macros/Memory.js.map +0 -1
- package/build/macros/Namespace.js +0 -111
- package/build/macros/Namespace.js.map +0 -1
- package/build/macros/Other.js +0 -21
- package/build/macros/Other.js.map +0 -1
- package/build/macros/RawValue.js +0 -17
- package/build/macros/RawValue.js.map +0 -1
- package/build/macros/commands/Control.js +0 -26
- package/build/macros/commands/Control.js.map +0 -1
- package/build/macros/commands/Draw.js +0 -40
- package/build/macros/commands/Draw.js.map +0 -1
- package/build/macros/commands/DrawFlush.js +0 -18
- package/build/macros/commands/DrawFlush.js.map +0 -1
- package/build/macros/commands/GetLink.js +0 -25
- package/build/macros/commands/GetLink.js.map +0 -1
- package/build/macros/commands/Lookup.js +0 -25
- package/build/macros/commands/Lookup.js.map +0 -1
- package/build/macros/commands/Print.js +0 -18
- package/build/macros/commands/Print.js.map +0 -1
- package/build/macros/commands/PrintFlush.js +0 -18
- package/build/macros/commands/PrintFlush.js.map +0 -1
- package/build/macros/commands/Radar.js +0 -65
- package/build/macros/commands/Radar.js.map +0 -1
- package/build/macros/commands/Sensor.js +0 -21
- package/build/macros/commands/Sensor.js.map +0 -1
- package/build/macros/commands/UnitBind.js +0 -18
- package/build/macros/commands/UnitBind.js.map +0 -1
- package/build/macros/commands/UnitControl.js +0 -73
- package/build/macros/commands/UnitControl.js.map +0 -1
- package/build/macros/commands/UnitLocate.js +0 -76
- package/build/macros/commands/UnitLocate.js.map +0 -1
- package/build/macros/commands/UnitRadar.js +0 -48
- package/build/macros/commands/UnitRadar.js.map +0 -1
- package/build/macros/commands/Wait.js +0 -19
- package/build/macros/commands/Wait.js.map +0 -1
- package/build/macros/commands/index.js +0 -33
- package/build/macros/commands/index.js.map +0 -1
- package/build/macros/index.js +0 -40
- package/build/macros/index.js.map +0 -1
- package/build/operators.js +0 -102
- package/build/operators.js.map +0 -1
- package/build/types.js +0 -28
- package/build/types.js.map +0 -1
- package/build/utils.js +0 -18
- package/build/utils.js.map +0 -1
- package/build/values/BaseValue.js +0 -112
- package/build/values/BaseValue.js.map +0 -1
- package/build/values/FunctionValue.js +0 -116
- package/build/values/FunctionValue.js.map +0 -1
- package/build/values/LiteralValue.js +0 -89
- package/build/values/LiteralValue.js.map +0 -1
- package/build/values/ObjectValue.js +0 -55
- package/build/values/ObjectValue.js.map +0 -1
- package/build/values/StoreValue.js +0 -32
- package/build/values/StoreValue.js.map +0 -1
- package/build/values/TempValue.js +0 -78
- package/build/values/TempValue.js.map +0 -1
- package/build/values/VoidValue.js +0 -32
- package/build/values/VoidValue.js.map +0 -1
- package/build/values/index.js +0 -23
- package/build/values/index.js.map +0 -1
- package/dist/types/macros/Building.d.ts +0 -10
- package/dist/types/macros/Entities.d.ts +0 -11
- package/dist/types/values/TempValue.d.ts +0 -19
package/dist/index.cjs
CHANGED
|
@@ -26,12 +26,58 @@ function _interopNamespace(e) {
|
|
|
26
26
|
var es__namespace = /*#__PURE__*/_interopNamespace(es);
|
|
27
27
|
|
|
28
28
|
class CompilerError extends Error {
|
|
29
|
-
constructor(message,
|
|
29
|
+
constructor(message, source) {
|
|
30
30
|
super(message);
|
|
31
|
-
this.
|
|
31
|
+
this.loc = source;
|
|
32
|
+
}
|
|
33
|
+
get loc() {
|
|
34
|
+
return this._loc;
|
|
35
|
+
}
|
|
36
|
+
set loc(value) {
|
|
37
|
+
if (!value)
|
|
38
|
+
return;
|
|
39
|
+
if ("type" in value) {
|
|
40
|
+
this._loc = value.loc;
|
|
41
|
+
}
|
|
42
|
+
else if ("start" in value) {
|
|
43
|
+
this._loc = value;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this._loc = {
|
|
47
|
+
start: value,
|
|
48
|
+
end: value,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
static from(error, source) {
|
|
53
|
+
let message;
|
|
54
|
+
if (error && typeof error === "object" && "loc" in error) {
|
|
55
|
+
const err = error;
|
|
56
|
+
message = err.toString();
|
|
57
|
+
source ??= err.loc;
|
|
58
|
+
}
|
|
59
|
+
else if (error instanceof Error) {
|
|
60
|
+
message = error.message;
|
|
61
|
+
}
|
|
62
|
+
else if (typeof error === "string") {
|
|
63
|
+
message = error;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
message = `Unknown error: ${error}`;
|
|
67
|
+
}
|
|
68
|
+
const result = new CompilerError(message, source);
|
|
69
|
+
result.inner = error;
|
|
70
|
+
return result;
|
|
32
71
|
}
|
|
33
72
|
}
|
|
34
73
|
|
|
74
|
+
var EInstIntent;
|
|
75
|
+
(function (EInstIntent) {
|
|
76
|
+
EInstIntent[EInstIntent["none"] = 0] = "none";
|
|
77
|
+
EInstIntent[EInstIntent["break"] = 1] = "break";
|
|
78
|
+
EInstIntent[EInstIntent["continue"] = 2] = "continue";
|
|
79
|
+
EInstIntent[EInstIntent["return"] = 3] = "return";
|
|
80
|
+
})(EInstIntent || (EInstIntent = {}));
|
|
35
81
|
/** Defines the possible types of mutability of a value */
|
|
36
82
|
var EMutability;
|
|
37
83
|
(function (EMutability) {
|
|
@@ -159,6 +205,8 @@ for (const key of operators) {
|
|
|
159
205
|
|
|
160
206
|
class InstructionBase {
|
|
161
207
|
constructor(...args) {
|
|
208
|
+
this.intent = EInstIntent.none;
|
|
209
|
+
this.alwaysRuns = true;
|
|
162
210
|
this._hidden = false;
|
|
163
211
|
this.args = args;
|
|
164
212
|
}
|
|
@@ -235,6 +283,7 @@ var EJumpKind;
|
|
|
235
283
|
class JumpInstruction extends InstructionBase {
|
|
236
284
|
constructor(address, kind, left = null, right = null) {
|
|
237
285
|
super("jump", address, kind, left, right);
|
|
286
|
+
this.address = address;
|
|
238
287
|
}
|
|
239
288
|
}
|
|
240
289
|
|
|
@@ -253,11 +302,13 @@ class ZeroSpaceInstruction extends InstructionBase {
|
|
|
253
302
|
class BreakInstruction extends JumpInstruction {
|
|
254
303
|
constructor(address) {
|
|
255
304
|
super(address, EJumpKind.Always);
|
|
305
|
+
this.intent = EInstIntent.break;
|
|
256
306
|
}
|
|
257
307
|
}
|
|
258
308
|
class ContinueInstruction extends JumpInstruction {
|
|
259
309
|
constructor(address) {
|
|
260
310
|
super(address, EJumpKind.Always);
|
|
311
|
+
this.intent = EInstIntent.continue;
|
|
261
312
|
}
|
|
262
313
|
}
|
|
263
314
|
|
|
@@ -309,6 +360,20 @@ class BaseValue extends VoidValue {
|
|
|
309
360
|
// TODO: should it return 0 + this ?
|
|
310
361
|
return this.eval(scope);
|
|
311
362
|
}
|
|
363
|
+
"!"(scope) {
|
|
364
|
+
const [that, inst] = this.consume(scope);
|
|
365
|
+
const temp = new StoreValue(scope);
|
|
366
|
+
const falseLiteral = new LiteralValue(scope, 0);
|
|
367
|
+
return [
|
|
368
|
+
temp,
|
|
369
|
+
[...inst, new OperationInstruction("equal", temp, that, falseLiteral)],
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
"~"(scope) {
|
|
373
|
+
const [that, inst] = this.consume(scope);
|
|
374
|
+
const temp = new StoreValue(scope);
|
|
375
|
+
return [temp, [...inst, new OperationInstruction("not", temp, that, null)]];
|
|
376
|
+
}
|
|
312
377
|
ensureOwned() {
|
|
313
378
|
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
314
379
|
}
|
|
@@ -353,18 +418,6 @@ for (const key in operatorMap$1) {
|
|
|
353
418
|
];
|
|
354
419
|
};
|
|
355
420
|
}
|
|
356
|
-
const unaryOperatorMap$1 = {
|
|
357
|
-
"!": "not",
|
|
358
|
-
"~": "flip",
|
|
359
|
-
};
|
|
360
|
-
for (const key in unaryOperatorMap$1) {
|
|
361
|
-
const name = unaryOperatorMap$1[key];
|
|
362
|
-
BaseValue.prototype[key] = function (scope) {
|
|
363
|
-
const [that, inst] = this.consume(scope);
|
|
364
|
-
const temp = new StoreValue(scope);
|
|
365
|
-
return [temp, [...inst, new OperationInstruction(name, temp, that, null)]];
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
421
|
const assignmentToBinary = {
|
|
369
422
|
"+=": "+",
|
|
370
423
|
"-=": "-",
|
|
@@ -477,18 +530,22 @@ for (const key in operatorMap) {
|
|
|
477
530
|
if (!(value instanceof LiteralValue)) {
|
|
478
531
|
return BaseValue.prototype[key].apply(this, [scope, value]);
|
|
479
532
|
}
|
|
480
|
-
return [
|
|
533
|
+
return [
|
|
534
|
+
new LiteralValue(scope, fn(this.data, value.data)),
|
|
535
|
+
[],
|
|
536
|
+
];
|
|
481
537
|
};
|
|
482
538
|
}
|
|
483
539
|
const unaryOperatorMap = {
|
|
484
540
|
"!": v => +!v,
|
|
485
541
|
"~": v => ~v,
|
|
486
542
|
"u-": v => -v,
|
|
543
|
+
"u+": v => +v,
|
|
487
544
|
};
|
|
488
545
|
for (const key in unaryOperatorMap) {
|
|
489
546
|
LiteralValue.prototype[key] = function (scope) {
|
|
490
547
|
const fn = unaryOperatorMap[key];
|
|
491
|
-
return [new LiteralValue(scope, fn(this.
|
|
548
|
+
return [new LiteralValue(scope, fn(this.data)), []];
|
|
492
549
|
};
|
|
493
550
|
}
|
|
494
551
|
|
|
@@ -543,8 +600,28 @@ const itemNames = [
|
|
|
543
600
|
/**
|
|
544
601
|
* A more type safe version of `Object.assign`
|
|
545
602
|
*/
|
|
603
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
546
604
|
function assign(obj, props) {
|
|
547
605
|
return Object.assign(obj, props);
|
|
606
|
+
}
|
|
607
|
+
function appendSourceLocations(valueInst, node) {
|
|
608
|
+
for (const inst of valueInst[1]) {
|
|
609
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
610
|
+
inst.source ??= node.loc;
|
|
611
|
+
}
|
|
612
|
+
return valueInst;
|
|
613
|
+
}
|
|
614
|
+
function withAlwaysRuns(valueInst, value) {
|
|
615
|
+
valueInst[1].forEach(inst => (inst.alwaysRuns = value));
|
|
616
|
+
return valueInst;
|
|
617
|
+
}
|
|
618
|
+
function isTemplateObjectArray(value) {
|
|
619
|
+
return (value instanceof ObjectValue &&
|
|
620
|
+
value.data.length instanceof LiteralValue &&
|
|
621
|
+
typeof value.data.length.data === "number" &&
|
|
622
|
+
value.data.raw instanceof ObjectValue &&
|
|
623
|
+
value.data.raw.data.length instanceof LiteralValue &&
|
|
624
|
+
typeof value.data.raw.data.length.data === "number");
|
|
548
625
|
}
|
|
549
626
|
|
|
550
627
|
/**
|
|
@@ -596,8 +673,9 @@ class ObjectValue extends VoidValue {
|
|
|
596
673
|
this.macro = true;
|
|
597
674
|
this.data = data;
|
|
598
675
|
}
|
|
599
|
-
static fromArray(scope, items) {
|
|
676
|
+
static fromArray(scope, items, intialData) {
|
|
600
677
|
const data = {
|
|
678
|
+
...intialData,
|
|
601
679
|
length: new LiteralValue(scope, items.length),
|
|
602
680
|
};
|
|
603
681
|
items.forEach((item, i) => {
|
|
@@ -698,7 +776,9 @@ class SenseableValue extends StoreValue {
|
|
|
698
776
|
];
|
|
699
777
|
}
|
|
700
778
|
if (prop instanceof StoreValue) {
|
|
701
|
-
const temp = new
|
|
779
|
+
const temp = assign(new SenseableValue(scope), {
|
|
780
|
+
mutability: EMutability.readonly,
|
|
781
|
+
});
|
|
702
782
|
return [temp, [new InstructionBase("sensor", temp, this, prop)]];
|
|
703
783
|
}
|
|
704
784
|
throw new CompilerError(`Cannot sense "${prop}" property`);
|
|
@@ -823,7 +903,7 @@ const Program = (c, scope, node) => {
|
|
|
823
903
|
};
|
|
824
904
|
|
|
825
905
|
const VariableDeclaration = (c, scope, node) => {
|
|
826
|
-
return c.handleMany(scope, node.declarations,
|
|
906
|
+
return c.handleMany(scope, node.declarations, child => VariableDeclarator(c, scope, child, node.kind));
|
|
827
907
|
};
|
|
828
908
|
const VariableDeclarator = (c, scope, node, kind = "let") => {
|
|
829
909
|
const [init, inst] = node.init
|
|
@@ -833,24 +913,24 @@ const VariableDeclarator = (c, scope, node, kind = "let") => {
|
|
|
833
913
|
return [null, inst];
|
|
834
914
|
};
|
|
835
915
|
const Declare = (c, scope, node, kind, init) => {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
node
|
|
846
|
-
|
|
847
|
-
}
|
|
916
|
+
return c.handle(scope, node, () => {
|
|
917
|
+
switch (node.type) {
|
|
918
|
+
case "Identifier":
|
|
919
|
+
return DeclareIdentifier(c, scope, node, kind, init);
|
|
920
|
+
case "ArrayPattern":
|
|
921
|
+
return DeclareArrayPattern(c, scope, node, kind, init);
|
|
922
|
+
case "ObjectPattern":
|
|
923
|
+
return DeclareObjectPattern(c, scope, node, kind, init);
|
|
924
|
+
default:
|
|
925
|
+
throw new CompilerError(`Unsupported declaration type: ${node.type}`, node);
|
|
926
|
+
}
|
|
927
|
+
});
|
|
848
928
|
};
|
|
849
929
|
const DeclareIdentifier = (c, scope, node, kind, init) => {
|
|
850
930
|
const { name: identifier } = node;
|
|
851
931
|
const name = nodeName(node, !c.compactNames && identifier);
|
|
852
932
|
if (kind === "const" && !init)
|
|
853
|
-
throw new CompilerError("Constants must be initialized.",
|
|
933
|
+
throw new CompilerError("Constants must be initialized.", node);
|
|
854
934
|
if (kind === "const" && init?.mutability === EMutability.constant) {
|
|
855
935
|
const owner = new ValueOwner({
|
|
856
936
|
scope,
|
|
@@ -867,9 +947,7 @@ const DeclareIdentifier = (c, scope, node, kind, init) => {
|
|
|
867
947
|
const inst = [];
|
|
868
948
|
if (init) {
|
|
869
949
|
if (init.macro)
|
|
870
|
-
throw new CompilerError("Macro values must be held by constants",
|
|
871
|
-
node,
|
|
872
|
-
]);
|
|
950
|
+
throw new CompilerError("Macro values must be held by constants", node);
|
|
873
951
|
inst.push(...value["="](scope, init)[1]);
|
|
874
952
|
}
|
|
875
953
|
if (kind === "const")
|
|
@@ -888,29 +966,28 @@ const DeclareArrayPattern = (c, scope, node, kind, init) => {
|
|
|
888
966
|
continue;
|
|
889
967
|
const val = init.data[i];
|
|
890
968
|
if (!val)
|
|
891
|
-
throw new CompilerError(`The target object does not have a value at index ${i}`,
|
|
969
|
+
throw new CompilerError(`The target object does not have a value at index ${i}`, element);
|
|
892
970
|
inst.push(...Declare(c, scope, element, kind, val)[1]);
|
|
893
971
|
}
|
|
894
972
|
return [null, inst];
|
|
895
973
|
};
|
|
896
974
|
const DeclareObjectPattern = (c, scope, node, kind, base) => {
|
|
897
975
|
if (!base)
|
|
898
|
-
throw new CompilerError("Cannot use object destructuring without an initializer",
|
|
976
|
+
throw new CompilerError("Cannot use object destructuring without an initializer", node);
|
|
899
977
|
const { properties } = node;
|
|
900
978
|
const [init, inst] = base.consume(scope);
|
|
901
|
-
|
|
979
|
+
const propertiesInst = c.handleMany(scope, properties, prop => {
|
|
902
980
|
if (prop.type === "RestElement")
|
|
903
|
-
throw new CompilerError("The rest operator is not supported",
|
|
981
|
+
throw new CompilerError("The rest operator is not supported", prop);
|
|
904
982
|
const { key, value } = prop;
|
|
905
|
-
const
|
|
983
|
+
const keyInst = key.type === "Identifier" && !prop.computed
|
|
906
984
|
? [new LiteralValue(scope, key.name), []]
|
|
907
985
|
: c.handleConsume(scope, prop.key);
|
|
908
|
-
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
return [null, inst];
|
|
986
|
+
const propInit = init.get(scope, keyInst[0]);
|
|
987
|
+
const declarationInst = Declare(c, scope, value, kind, propInit[0]);
|
|
988
|
+
return [null, [...keyInst[1], ...propInit[1], ...declarationInst[1]]];
|
|
989
|
+
});
|
|
990
|
+
return [null, [...inst, ...propertiesInst[1]]];
|
|
914
991
|
};
|
|
915
992
|
|
|
916
993
|
const Literal = (_c, scope, node) => [new LiteralValue(scope, node.value), []];
|
|
@@ -929,7 +1006,34 @@ const LRExpression = (c, scope, node) => {
|
|
|
929
1006
|
return [op, [...leftInst, ...rightInst, ...opInst]];
|
|
930
1007
|
};
|
|
931
1008
|
const BinaryExpression = LRExpression;
|
|
932
|
-
const LogicalExpression =
|
|
1009
|
+
const LogicalExpression = (c, scope, node) => {
|
|
1010
|
+
if (node.operator !== "??")
|
|
1011
|
+
return LRExpression(c, scope, node);
|
|
1012
|
+
const nullLiteral = new LiteralValue(scope, null);
|
|
1013
|
+
const endAdress = new LiteralValue(scope, null);
|
|
1014
|
+
const [left, leftInst] = c.handleEval(scope, node.left);
|
|
1015
|
+
const [nullTest] = left["=="](scope, nullLiteral);
|
|
1016
|
+
if (nullTest instanceof LiteralValue) {
|
|
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
|
+
];
|
|
1036
|
+
};
|
|
933
1037
|
const AssignmentExpression = (c, scope, node) => {
|
|
934
1038
|
const [left, leftInst] = c.handle(scope, node.left);
|
|
935
1039
|
// doesn't need to consume because the operators already do that
|
|
@@ -1019,13 +1123,75 @@ const IfStatement = (c, scope, node) => {
|
|
|
1019
1123
|
return [null, inst];
|
|
1020
1124
|
}
|
|
1021
1125
|
const endIfAddr = new LiteralValue(scope, null);
|
|
1022
|
-
inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)), ...c.handle(scope, node.consequent)[1], new AddressResolver(endIfAddr));
|
|
1126
|
+
inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)), ...withAlwaysRuns(c.handle(scope, node.consequent), false)[1], new AddressResolver(endIfAddr));
|
|
1023
1127
|
const endElseAddr = new LiteralValue(scope, null);
|
|
1024
|
-
if (node.alternate)
|
|
1025
|
-
inst.push(new JumpInstruction(endElseAddr, EJumpKind.Always), new AddressResolver(endIfAddr), ...c.handle(scope, node.alternate)[1], new AddressResolver(endElseAddr));
|
|
1128
|
+
if (node.alternate) {
|
|
1129
|
+
inst.push(new JumpInstruction(endElseAddr, EJumpKind.Always), new AddressResolver(endIfAddr), ...withAlwaysRuns(c.handle(scope, node.alternate), false)[1], new AddressResolver(endElseAddr));
|
|
1130
|
+
}
|
|
1026
1131
|
return [null, inst];
|
|
1027
1132
|
};
|
|
1028
1133
|
|
|
1134
|
+
const SwitchStatement = (c, scope, node) => {
|
|
1135
|
+
const innerScope = scope.createScope();
|
|
1136
|
+
const [ref, refInst] = c.handleConsume(scope, node.discriminant);
|
|
1137
|
+
const inst = [];
|
|
1138
|
+
const endAdress = new LiteralValue(innerScope, null);
|
|
1139
|
+
const endLine = new AddressResolver(endAdress).bindBreak(innerScope);
|
|
1140
|
+
const caseJumps = [];
|
|
1141
|
+
let defaultJump;
|
|
1142
|
+
for (const scase of node.cases) {
|
|
1143
|
+
const [, bodyInst] = c.handleMany(innerScope, scase.consequent);
|
|
1144
|
+
const bodyAdress = new LiteralValue(innerScope, null);
|
|
1145
|
+
const bodyLine = new AddressResolver(bodyAdress);
|
|
1146
|
+
if (!scase.test) {
|
|
1147
|
+
[defaultJump] = c.handle(innerScope, scase, () => [
|
|
1148
|
+
null,
|
|
1149
|
+
[new JumpInstruction(bodyAdress, EJumpKind.Always)],
|
|
1150
|
+
])[1];
|
|
1151
|
+
inst.push(bodyLine, ...bodyInst);
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
const [test, testInst] = c.handleConsume(innerScope, scase.test);
|
|
1155
|
+
// check if it can be evaluated at compile time
|
|
1156
|
+
const [comp] = ref["=="](innerScope, test);
|
|
1157
|
+
// if the constant expression resolves to false
|
|
1158
|
+
// the whole case gets omitted
|
|
1159
|
+
// otherwise it returns the instructions for
|
|
1160
|
+
// the body of this case
|
|
1161
|
+
if (comp instanceof LiteralValue) {
|
|
1162
|
+
if (comp.data)
|
|
1163
|
+
return [null, bodyInst];
|
|
1164
|
+
else
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
// makes sourcemapping for the jump more specific
|
|
1168
|
+
const [, jump] = c.handle(innerScope, scase, () => [
|
|
1169
|
+
null,
|
|
1170
|
+
[new JumpInstruction(bodyAdress, EJumpKind.StrictEqual, ref, test)],
|
|
1171
|
+
]);
|
|
1172
|
+
caseJumps.push(...testInst, ...jump);
|
|
1173
|
+
inst.push(bodyLine, ...bodyInst);
|
|
1174
|
+
}
|
|
1175
|
+
// ensures that the processor exits
|
|
1176
|
+
// the switch if no cases match
|
|
1177
|
+
defaultJump ??= new JumpInstruction(endAdress, EJumpKind.Always);
|
|
1178
|
+
if (caseJumps.length > 0) {
|
|
1179
|
+
withAlwaysRuns([null, inst], false);
|
|
1180
|
+
withAlwaysRuns([null, [...caseJumps.slice(1), defaultJump]], false);
|
|
1181
|
+
withAlwaysRuns([null, inst], false);
|
|
1182
|
+
}
|
|
1183
|
+
return [
|
|
1184
|
+
null,
|
|
1185
|
+
[
|
|
1186
|
+
...refInst,
|
|
1187
|
+
...caseJumps,
|
|
1188
|
+
...(caseJumps.length > 0 ? [defaultJump] : []),
|
|
1189
|
+
...inst,
|
|
1190
|
+
endLine,
|
|
1191
|
+
],
|
|
1192
|
+
];
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1029
1195
|
const WhileStatement = (c, scope, node) => {
|
|
1030
1196
|
const lines = [];
|
|
1031
1197
|
const [test, testLines] = c.handleConsume(scope, node.test);
|
|
@@ -1039,7 +1205,7 @@ const WhileStatement = (c, scope, node) => {
|
|
|
1039
1205
|
}
|
|
1040
1206
|
return [null, lines];
|
|
1041
1207
|
}
|
|
1042
|
-
lines.push(startLoopLine, ...testLines, new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)), ...c.handle(scope, node.body)[1], new JumpInstruction(startLoopAddr, EJumpKind.Always), endLoopLine);
|
|
1208
|
+
lines.push(startLoopLine, ...testLines, new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)), ...withAlwaysRuns(c.handle(scope, node.body), false)[1], new JumpInstruction(startLoopAddr, EJumpKind.Always), endLoopLine);
|
|
1043
1209
|
return [null, lines];
|
|
1044
1210
|
};
|
|
1045
1211
|
const DoWhileStatement = (c, scope, node) => {
|
|
@@ -1083,7 +1249,7 @@ const ForStatement = (c, scope, node) => {
|
|
|
1083
1249
|
startLoopLine,
|
|
1084
1250
|
...testLines,
|
|
1085
1251
|
new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)),
|
|
1086
|
-
...c.handle(scope, node.body)[1],
|
|
1252
|
+
...withAlwaysRuns(c.handle(scope, node.body), false)[1],
|
|
1087
1253
|
...updateLines,
|
|
1088
1254
|
new JumpInstruction(startLoopAddr, EJumpKind.Always),
|
|
1089
1255
|
endLoopLine,
|
|
@@ -1114,7 +1280,9 @@ class FunctionValue extends VoidValue {
|
|
|
1114
1280
|
const name = nodeName(id, !this.c.compactNames && id.name);
|
|
1115
1281
|
const owner = new ValueOwner({
|
|
1116
1282
|
scope: this.childScope,
|
|
1117
|
-
value: new
|
|
1283
|
+
value: assign(new SenseableValue(this.childScope), {
|
|
1284
|
+
mutability: EMutability.mutable,
|
|
1285
|
+
}),
|
|
1118
1286
|
identifier: id.name,
|
|
1119
1287
|
name,
|
|
1120
1288
|
});
|
|
@@ -1149,12 +1317,17 @@ class FunctionValue extends VoidValue {
|
|
|
1149
1317
|
...this.c.handle(this.childScope, this.body)[1],
|
|
1150
1318
|
];
|
|
1151
1319
|
if (!endsWithReturn(this.inst)) {
|
|
1152
|
-
this.inst.push(new SetCounterInstruction(this.ret.value)
|
|
1320
|
+
this.inst.push(assign(new SetCounterInstruction(this.ret.value), {
|
|
1321
|
+
intent: EInstIntent.return,
|
|
1322
|
+
}));
|
|
1153
1323
|
}
|
|
1154
1324
|
}
|
|
1155
1325
|
normalReturn(scope, arg) {
|
|
1156
1326
|
const argInst = arg ? this.temp.value["="](scope, arg)[1] : [];
|
|
1157
|
-
|
|
1327
|
+
const returnInst = assign(new SetCounterInstruction(this.ret.value), {
|
|
1328
|
+
intent: EInstIntent.return,
|
|
1329
|
+
});
|
|
1330
|
+
return [null, [...argInst, returnInst]];
|
|
1158
1331
|
}
|
|
1159
1332
|
normalCall(scope, args) {
|
|
1160
1333
|
if (!this.bundled)
|
|
@@ -1169,7 +1342,12 @@ class FunctionValue extends VoidValue {
|
|
|
1169
1342
|
}
|
|
1170
1343
|
inlineReturn(scope, arg) {
|
|
1171
1344
|
const argInst = arg ? this.inlineTemp.value["="](scope, arg)[1] : [];
|
|
1172
|
-
|
|
1345
|
+
if (!this.inlineEnd)
|
|
1346
|
+
throw new CompilerError("Error during inline attempt: missing inline end adress");
|
|
1347
|
+
const jump = assign(new JumpInstruction(this.inlineEnd, EJumpKind.Always), {
|
|
1348
|
+
intent: EInstIntent.return,
|
|
1349
|
+
});
|
|
1350
|
+
return [null, [...argInst, jump]];
|
|
1173
1351
|
}
|
|
1174
1352
|
inlineCall(scope, args) {
|
|
1175
1353
|
// create return value
|
|
@@ -1179,7 +1357,6 @@ class FunctionValue extends VoidValue {
|
|
|
1179
1357
|
mutability: EMutability.mutable,
|
|
1180
1358
|
}),
|
|
1181
1359
|
});
|
|
1182
|
-
this.inlineEnd = new LiteralValue(scope, null);
|
|
1183
1360
|
// make a copy of the function scope
|
|
1184
1361
|
const fnScope = this.childScope.copy();
|
|
1185
1362
|
// hard set variables within the function scope
|
|
@@ -1194,16 +1371,13 @@ class FunctionValue extends VoidValue {
|
|
|
1194
1371
|
name: owner.name,
|
|
1195
1372
|
}));
|
|
1196
1373
|
});
|
|
1374
|
+
this.inlineEnd = new LiteralValue(scope, null);
|
|
1197
1375
|
this.tryingInline = true;
|
|
1198
|
-
|
|
1376
|
+
let inst = this.c.handle(fnScope, this.body)[1];
|
|
1199
1377
|
this.tryingInline = false;
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
// if (jump instanceof JumpInstruction) {
|
|
1204
|
-
// // remove useless jump
|
|
1205
|
-
// if (jump.args[1] === this.inlineEnd) inst.pop();
|
|
1206
|
-
// }
|
|
1378
|
+
const returnIndex = inst.findIndex(i => i.alwaysRuns && i.intent === EInstIntent.return);
|
|
1379
|
+
if (returnIndex !== -1)
|
|
1380
|
+
inst = inst.slice(0, returnIndex + 1);
|
|
1207
1381
|
inst.push(new AddressResolver(this.inlineEnd));
|
|
1208
1382
|
// return the function value
|
|
1209
1383
|
return [this.inlineTemp.value, inst];
|
|
@@ -1248,7 +1422,11 @@ function endsWithReturn(inst) {
|
|
|
1248
1422
|
function handleFunctionNode(c, scope, node) {
|
|
1249
1423
|
let { params, body } = node;
|
|
1250
1424
|
if (es__namespace.isExpression(body)) {
|
|
1251
|
-
|
|
1425
|
+
const { loc } = body;
|
|
1426
|
+
const statement = es__namespace.returnStatement(body);
|
|
1427
|
+
statement.loc = loc;
|
|
1428
|
+
body = es__namespace.blockStatement([statement]);
|
|
1429
|
+
body.loc = loc;
|
|
1252
1430
|
}
|
|
1253
1431
|
return [
|
|
1254
1432
|
new FunctionValue({
|
|
@@ -1294,16 +1472,32 @@ const CallExpression = (c, scope, node) => {
|
|
|
1294
1472
|
inst.push(...callInst);
|
|
1295
1473
|
return [callValue, inst];
|
|
1296
1474
|
};
|
|
1297
|
-
const NewExpression = CallExpression;
|
|
1475
|
+
const NewExpression = CallExpression;
|
|
1476
|
+
const TaggedTemplateExpression = (c, scope, node) => {
|
|
1477
|
+
const [tag, tagInst] = c.handleConsume(scope, node.tag);
|
|
1478
|
+
const template = node.quasi;
|
|
1479
|
+
const stringsObject = ObjectValue.fromArray(scope, template.quasis.map(quasi => new LiteralValue(scope, quasi.value.cooked ?? "")), {
|
|
1480
|
+
raw: ObjectValue.fromArray(scope, template.quasis.map(quasi => new LiteralValue(scope, quasi.value.raw))),
|
|
1481
|
+
});
|
|
1482
|
+
const expressions = [];
|
|
1483
|
+
const expressionInsts = [];
|
|
1484
|
+
template.expressions.forEach(expression => {
|
|
1485
|
+
const [value, inst] = c.handleConsume(scope, expression);
|
|
1486
|
+
expressions.push(value);
|
|
1487
|
+
expressionInsts.push(...inst);
|
|
1488
|
+
});
|
|
1489
|
+
const [result, resultInst] = tag.call(scope, [stringsObject, ...expressions]);
|
|
1490
|
+
return [result, [...expressionInsts, ...tagInst, ...resultInst]];
|
|
1491
|
+
};
|
|
1298
1492
|
|
|
1299
1493
|
const ObjectExpression = (c, scope, node) => {
|
|
1300
1494
|
const data = {};
|
|
1301
1495
|
const inst = [];
|
|
1302
1496
|
for (const prop of node.properties) {
|
|
1303
1497
|
if (prop.type === "SpreadElement")
|
|
1304
|
-
throw new CompilerError("Cannot handle spread element",
|
|
1498
|
+
throw new CompilerError("Cannot handle spread element", prop);
|
|
1305
1499
|
if (prop.computed)
|
|
1306
|
-
throw new CompilerError("Cannot handle computed property.",
|
|
1500
|
+
throw new CompilerError("Cannot handle computed property.", prop);
|
|
1307
1501
|
const { key } = prop;
|
|
1308
1502
|
const value = prop.type === "ObjectProperty" ? prop.value : prop;
|
|
1309
1503
|
let index;
|
|
@@ -1314,17 +1508,18 @@ const ObjectExpression = (c, scope, node) => {
|
|
|
1314
1508
|
index = `${key.value}`;
|
|
1315
1509
|
}
|
|
1316
1510
|
else {
|
|
1317
|
-
throw new CompilerError(`Unsupported object key type: ${key.type}`,
|
|
1318
|
-
key,
|
|
1319
|
-
]);
|
|
1511
|
+
throw new CompilerError(`Unsupported object key type: ${key.type}`, key);
|
|
1320
1512
|
}
|
|
1321
1513
|
const [member, memberInst] = c.handleEval(scope, value);
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1514
|
+
// TODO: use an approach that can be defined by each type
|
|
1515
|
+
if (!member.owner && !(member instanceof LiteralValue)) {
|
|
1516
|
+
new ValueOwner({
|
|
1517
|
+
scope,
|
|
1518
|
+
constant: true,
|
|
1519
|
+
value: member,
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1522
|
+
data[index] = member;
|
|
1328
1523
|
inst.push(...memberInst);
|
|
1329
1524
|
}
|
|
1330
1525
|
return [new ObjectValue(scope, data), inst];
|
|
@@ -1358,9 +1553,7 @@ const ArrayPattern = (c, scope, node) => {
|
|
|
1358
1553
|
continue;
|
|
1359
1554
|
const valueInst = c.handle(scope, element);
|
|
1360
1555
|
if (!valueInst[0])
|
|
1361
|
-
throw new CompilerError("Destructuring element must resolve to a value",
|
|
1362
|
-
element,
|
|
1363
|
-
]);
|
|
1556
|
+
throw new CompilerError("Destructuring element must resolve to a value", element);
|
|
1364
1557
|
inst.push(...valueInst[1]);
|
|
1365
1558
|
members.set(new LiteralValue(scope, i), valueInst[0]);
|
|
1366
1559
|
}
|
|
@@ -1381,26 +1574,15 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
1381
1574
|
inst.push(...keyInst[1]);
|
|
1382
1575
|
const valueInst = c.handle(scope, prop.value);
|
|
1383
1576
|
if (!valueInst[0])
|
|
1384
|
-
throw new CompilerError("Destructuring member must resolve to a value",
|
|
1385
|
-
prop.value,
|
|
1386
|
-
]);
|
|
1577
|
+
throw new CompilerError("Destructuring member must resolve to a value", prop.value);
|
|
1387
1578
|
inst.push(...valueInst[1]);
|
|
1388
1579
|
members.set(keyInst[0], valueInst[0]);
|
|
1389
1580
|
}
|
|
1390
1581
|
return [new DestructuringValue(scope, members), inst];
|
|
1391
1582
|
};
|
|
1392
1583
|
|
|
1393
|
-
const TemplateLiteral = (
|
|
1394
|
-
|
|
1395
|
-
const inst = [];
|
|
1396
|
-
node.expressions.forEach((expression, i) => {
|
|
1397
|
-
const [v, vi] = c.handleConsume(scope, expression);
|
|
1398
|
-
inst.push(...vi);
|
|
1399
|
-
args.push(node.quasis[i].value.raw, v);
|
|
1400
|
-
});
|
|
1401
|
-
args.push(node.quasis.slice(-1)[0].value.raw);
|
|
1402
|
-
inst.push(new ZeroSpaceInstruction(...args));
|
|
1403
|
-
return [null, inst];
|
|
1584
|
+
const TemplateLiteral = () => {
|
|
1585
|
+
throw new CompilerError("Template strings are currently unavailable. To inline mlog code use the asm function.");
|
|
1404
1586
|
};
|
|
1405
1587
|
|
|
1406
1588
|
const BlockStatement = (c, scope, node) => {
|
|
@@ -1433,14 +1615,12 @@ const TSEnumDeclaration = (c, scope, node) => {
|
|
|
1433
1615
|
const data = {};
|
|
1434
1616
|
for (const member of node.members) {
|
|
1435
1617
|
if (lastType === "string" && !member.initializer)
|
|
1436
|
-
throw new CompilerError("This enum member must be initialized",
|
|
1618
|
+
throw new CompilerError("This enum member must be initialized", member);
|
|
1437
1619
|
const [value] = member.initializer
|
|
1438
1620
|
? c.handleEval(scope, member.initializer)
|
|
1439
1621
|
: [new LiteralValue(scope, counter)];
|
|
1440
1622
|
if (!(value instanceof LiteralValue))
|
|
1441
|
-
throw new CompilerError("Enum members must contain literal values",
|
|
1442
|
-
member,
|
|
1443
|
-
]);
|
|
1623
|
+
throw new CompilerError("Enum members must contain literal values", member);
|
|
1444
1624
|
if (typeof value.data === "number") {
|
|
1445
1625
|
lastType = "number";
|
|
1446
1626
|
counter = value.data + 1;
|
|
@@ -1486,6 +1666,7 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1486
1666
|
ContinueStatement: ContinueStatement,
|
|
1487
1667
|
ReturnStatement: ReturnStatement,
|
|
1488
1668
|
IfStatement: IfStatement,
|
|
1669
|
+
SwitchStatement: SwitchStatement,
|
|
1489
1670
|
WhileStatement: WhileStatement,
|
|
1490
1671
|
DoWhileStatement: DoWhileStatement,
|
|
1491
1672
|
ForStatement: ForStatement,
|
|
@@ -1495,6 +1676,7 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1495
1676
|
ObjectMethod: ObjectMethod,
|
|
1496
1677
|
CallExpression: CallExpression,
|
|
1497
1678
|
NewExpression: NewExpression,
|
|
1679
|
+
TaggedTemplateExpression: TaggedTemplateExpression,
|
|
1498
1680
|
ObjectExpression: ObjectExpression,
|
|
1499
1681
|
ArrayExpression: ArrayExpression,
|
|
1500
1682
|
MemberExpression: MemberExpression,
|
|
@@ -1597,53 +1779,170 @@ class Concat extends MacroFunction {
|
|
|
1597
1779
|
}
|
|
1598
1780
|
}
|
|
1599
1781
|
|
|
1600
|
-
|
|
1782
|
+
/** Asserts that `value` is a `LiteralValue` that contains a string */
|
|
1783
|
+
function assertStringLiteral(value, name) {
|
|
1784
|
+
if (!(value instanceof LiteralValue) || typeof value.data !== "string")
|
|
1785
|
+
throw new CompilerError(`${name} must be a string literal`);
|
|
1786
|
+
}
|
|
1787
|
+
/** Asserts that `value` is a string literal that is part of a given set of `members`*/
|
|
1788
|
+
function assertLiteralOneOf(value, members, name) {
|
|
1789
|
+
assertStringLiteral(value, name);
|
|
1790
|
+
if (!members.includes(value.data))
|
|
1791
|
+
throw new CompilerError(`${name} must be one of: ${members
|
|
1792
|
+
.slice(0, -1)
|
|
1793
|
+
.map(member => `"${member}"`)
|
|
1794
|
+
.join(", ")} or "${members[members.length - 1]}"`);
|
|
1795
|
+
}
|
|
1796
|
+
/** Asserts that `value` is either a store or a literal */
|
|
1797
|
+
function assertIsRuntimeValue(value, name) {
|
|
1798
|
+
if (!(value instanceof LiteralValue) && !(value instanceof StoreValue))
|
|
1799
|
+
throw new CompilerError(`${name} must be a valid runtime value`);
|
|
1800
|
+
}
|
|
1801
|
+
/** Asserts that `value` is an `ObjectValue` */
|
|
1802
|
+
function assertIsObjectMacro(value, name) {
|
|
1803
|
+
if (!(value instanceof ObjectValue))
|
|
1804
|
+
throw new CompilerError(`${name} must be an object macro`);
|
|
1805
|
+
}
|
|
1806
|
+
/** Asserts that `value` is an `ObjectValue` that has a length property */
|
|
1807
|
+
function assertIsArrayMacro(value, name) {
|
|
1808
|
+
if (!(value instanceof ObjectValue) || !value.data.length)
|
|
1809
|
+
throw new CompilerError(`${name} must be an array macro`);
|
|
1810
|
+
}
|
|
1811
|
+
/** Asserts that all of the fields described are present on `value`*/
|
|
1812
|
+
function assertObjectFields(value, fields) {
|
|
1813
|
+
const result = [];
|
|
1814
|
+
for (const field of fields) {
|
|
1815
|
+
const param = typeof field === "object" ? field : { key: field };
|
|
1816
|
+
const item = value.data[param.key];
|
|
1817
|
+
if (item) {
|
|
1818
|
+
param.validate?.(item);
|
|
1819
|
+
result.push(item);
|
|
1820
|
+
continue;
|
|
1821
|
+
}
|
|
1822
|
+
if (param.default == undefined)
|
|
1823
|
+
throw new CompilerError(`The field "${param.name ?? param.key}" must be present`);
|
|
1824
|
+
result.push(param.default);
|
|
1825
|
+
}
|
|
1826
|
+
return result;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
/** Used to create namespaces that contain multiple methods that map into instructions */
|
|
1830
|
+
function createOverloadNamespace({ scope, overloads, handler, }) {
|
|
1831
|
+
const result = {};
|
|
1832
|
+
for (const key in overloads) {
|
|
1833
|
+
const { named, args } = overloads[key];
|
|
1834
|
+
if (named) {
|
|
1835
|
+
result[key] = new MacroFunction(scope, options => {
|
|
1836
|
+
assertIsObjectMacro(options, named);
|
|
1837
|
+
return handler(key, ...assertObjectFields(options, args));
|
|
1838
|
+
});
|
|
1839
|
+
continue;
|
|
1840
|
+
}
|
|
1841
|
+
result[key] = new MacroFunction(scope, (...params) => {
|
|
1842
|
+
const handlerParams = [];
|
|
1843
|
+
// validate the paramters
|
|
1844
|
+
for (let i = 0; i < args.length; i++) {
|
|
1845
|
+
let arg = args[i];
|
|
1846
|
+
if (typeof arg === "string")
|
|
1847
|
+
arg = { key: arg };
|
|
1848
|
+
const param = params[i];
|
|
1849
|
+
if (!param) {
|
|
1850
|
+
if (arg.default == undefined)
|
|
1851
|
+
throw new CompilerError(`Missing argument: ${arg.name ?? arg.key}`);
|
|
1852
|
+
handlerParams.push(arg.default);
|
|
1853
|
+
continue;
|
|
1854
|
+
}
|
|
1855
|
+
arg.validate?.(param);
|
|
1856
|
+
handlerParams.push(param);
|
|
1857
|
+
}
|
|
1858
|
+
return handler(key, ...handlerParams);
|
|
1859
|
+
});
|
|
1860
|
+
}
|
|
1861
|
+
return result;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
class Draw extends ObjectValue {
|
|
1601
1865
|
constructor(scope) {
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1866
|
+
const data = createOverloadNamespace({
|
|
1867
|
+
scope,
|
|
1868
|
+
overloads: {
|
|
1869
|
+
clear: {
|
|
1870
|
+
args: ["r", "g", "b"],
|
|
1871
|
+
},
|
|
1872
|
+
color: {
|
|
1873
|
+
args: ["r", "g", "b", { key: "a", default: "" }],
|
|
1874
|
+
},
|
|
1875
|
+
stroke: {
|
|
1876
|
+
args: ["width"],
|
|
1877
|
+
},
|
|
1878
|
+
line: {
|
|
1879
|
+
named: "options",
|
|
1880
|
+
args: ["x", "y", "x2", "y2"],
|
|
1881
|
+
},
|
|
1882
|
+
rect: {
|
|
1883
|
+
named: "options",
|
|
1884
|
+
args: ["x", "y", "width", "height"],
|
|
1885
|
+
},
|
|
1886
|
+
lineRect: { named: "options", args: ["x", "y", "width", "height"] },
|
|
1887
|
+
linePoly: {
|
|
1888
|
+
named: "options",
|
|
1889
|
+
args: ["x", "y", "sides", "radius", "rotation"],
|
|
1890
|
+
},
|
|
1891
|
+
poly: {
|
|
1892
|
+
named: "options",
|
|
1893
|
+
args: ["x", "y", "sides", "radius", "rotation"],
|
|
1894
|
+
},
|
|
1895
|
+
triangle: {
|
|
1896
|
+
named: "options",
|
|
1897
|
+
args: ["x", "y", "x2", "y2", "x3", "y3"],
|
|
1898
|
+
},
|
|
1899
|
+
image: {
|
|
1900
|
+
named: "options",
|
|
1901
|
+
args: ["x", "y", "image", "size", "rotation"],
|
|
1902
|
+
},
|
|
1903
|
+
},
|
|
1904
|
+
handler(overload, ...args) {
|
|
1905
|
+
return [null, [new InstructionBase("draw", overload, ...args)]];
|
|
1906
|
+
},
|
|
1628
1907
|
});
|
|
1908
|
+
super(scope, data);
|
|
1629
1909
|
}
|
|
1630
1910
|
}
|
|
1631
1911
|
|
|
1632
1912
|
class Print extends MacroFunction {
|
|
1633
1913
|
constructor(scope) {
|
|
1634
1914
|
super(scope, (...values) => {
|
|
1915
|
+
const [first] = values;
|
|
1635
1916
|
const inst = [];
|
|
1636
|
-
|
|
1637
|
-
|
|
1917
|
+
if (!isTemplateObjectArray(first)) {
|
|
1918
|
+
for (const value of values) {
|
|
1919
|
+
inst.push(new InstructionBase("print", value));
|
|
1920
|
+
}
|
|
1921
|
+
return [null, inst];
|
|
1638
1922
|
}
|
|
1923
|
+
// `first` is likely a template strings array
|
|
1924
|
+
// maybe this should be checked in another way?
|
|
1925
|
+
const { length } = first.data;
|
|
1926
|
+
for (let i = 1; i < values.length; i++) {
|
|
1927
|
+
const [string] = first.get(scope, new LiteralValue(scope, i - 1));
|
|
1928
|
+
if (string.data)
|
|
1929
|
+
inst.push(new InstructionBase("print", string));
|
|
1930
|
+
inst.push(new InstructionBase("print", values[i]));
|
|
1931
|
+
}
|
|
1932
|
+
const [tail] = first.get(scope, new LiteralValue(scope, length.data - 1));
|
|
1933
|
+
if (tail.data)
|
|
1934
|
+
inst.push(new InstructionBase("print", tail));
|
|
1639
1935
|
return [null, inst];
|
|
1640
1936
|
});
|
|
1641
1937
|
}
|
|
1642
1938
|
}
|
|
1643
1939
|
|
|
1940
|
+
const defaultTargetName$1 = "message1";
|
|
1644
1941
|
class PrintFlush extends MacroFunction {
|
|
1645
1942
|
constructor(scope) {
|
|
1646
1943
|
super(scope, (target) => {
|
|
1944
|
+
if (!target)
|
|
1945
|
+
return [null, [new InstructionBase("printflush", defaultTargetName$1)]];
|
|
1647
1946
|
if (!(target instanceof SenseableValue))
|
|
1648
1947
|
throw new CompilerError("The printflush target must be a senseable value");
|
|
1649
1948
|
return [null, [new InstructionBase("printflush", target)]];
|
|
@@ -1651,9 +1950,12 @@ class PrintFlush extends MacroFunction {
|
|
|
1651
1950
|
}
|
|
1652
1951
|
}
|
|
1653
1952
|
|
|
1953
|
+
const defaultTargetName = "display1";
|
|
1654
1954
|
class DrawFlush extends MacroFunction {
|
|
1655
1955
|
constructor(scope) {
|
|
1656
1956
|
super(scope, (target) => {
|
|
1957
|
+
if (!target)
|
|
1958
|
+
return [null, [new InstructionBase("drawflush", defaultTargetName)]];
|
|
1657
1959
|
if (!(target instanceof SenseableValue))
|
|
1658
1960
|
throw new CompilerError("The drawflush target must be a senseable value");
|
|
1659
1961
|
return [null, [new InstructionBase("drawflush", target)]];
|
|
@@ -1661,6 +1963,30 @@ class DrawFlush extends MacroFunction {
|
|
|
1661
1963
|
}
|
|
1662
1964
|
}
|
|
1663
1965
|
|
|
1966
|
+
class GetBlock extends ObjectValue {
|
|
1967
|
+
constructor(scope) {
|
|
1968
|
+
const data = createOverloadNamespace({
|
|
1969
|
+
scope,
|
|
1970
|
+
overloads: {
|
|
1971
|
+
floor: { args: ["x", "y"] },
|
|
1972
|
+
ore: { args: ["x", "y"] },
|
|
1973
|
+
block: { args: ["x", "y"] },
|
|
1974
|
+
building: { args: ["x", "y"] },
|
|
1975
|
+
},
|
|
1976
|
+
handler(overload, x, y) {
|
|
1977
|
+
const output = overload === "building"
|
|
1978
|
+
? new SenseableValue(scope)
|
|
1979
|
+
: new StoreValue(scope);
|
|
1980
|
+
return [
|
|
1981
|
+
output,
|
|
1982
|
+
[new InstructionBase("getblock", overload, output, x, y)],
|
|
1983
|
+
];
|
|
1984
|
+
},
|
|
1985
|
+
});
|
|
1986
|
+
super(scope, data);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1664
1990
|
class GetLink extends MacroFunction {
|
|
1665
1991
|
constructor(scope) {
|
|
1666
1992
|
super(scope, (index) => {
|
|
@@ -1673,21 +1999,27 @@ class GetLink extends MacroFunction {
|
|
|
1673
1999
|
}
|
|
1674
2000
|
}
|
|
1675
2001
|
|
|
1676
|
-
|
|
1677
|
-
class Control extends MacroFunction {
|
|
2002
|
+
class Control extends ObjectValue {
|
|
1678
2003
|
constructor(scope) {
|
|
1679
|
-
super(scope, (
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
2004
|
+
super(scope, createOverloadNamespace({
|
|
2005
|
+
scope,
|
|
2006
|
+
overloads: {
|
|
2007
|
+
enabled: { args: ["building", "value"] },
|
|
2008
|
+
shoot: {
|
|
2009
|
+
named: "options",
|
|
2010
|
+
args: ["building", "x", "y", "shoot"],
|
|
2011
|
+
},
|
|
2012
|
+
shootp: {
|
|
2013
|
+
named: "options",
|
|
2014
|
+
args: ["building", "unit", "shoot"],
|
|
2015
|
+
},
|
|
2016
|
+
config: { args: ["building", "value"] },
|
|
2017
|
+
color: { args: ["building", "r", "g", "b"] },
|
|
2018
|
+
},
|
|
2019
|
+
handler(overload, ...args) {
|
|
2020
|
+
return [null, [new InstructionBase("control", overload, ...args)]];
|
|
2021
|
+
},
|
|
2022
|
+
}));
|
|
1691
2023
|
}
|
|
1692
2024
|
}
|
|
1693
2025
|
|
|
@@ -1710,28 +2042,25 @@ const validRadarSorts = [
|
|
|
1710
2042
|
];
|
|
1711
2043
|
class Radar extends MacroFunction {
|
|
1712
2044
|
constructor(scope) {
|
|
1713
|
-
super(scope,
|
|
2045
|
+
super(scope, options => {
|
|
2046
|
+
assertIsObjectMacro(options, "The radar options");
|
|
2047
|
+
const { building, filters, order, sort } = options.data;
|
|
1714
2048
|
if (!(building instanceof SenseableValue))
|
|
1715
2049
|
throw new CompilerError("The building must a senseable value");
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
if (!validRadarFilters.includes(filter3.data))
|
|
1728
|
-
throw new CompilerError("Invalid value for filter3");
|
|
2050
|
+
assertIsArrayMacro(filters, "filters");
|
|
2051
|
+
const { length } = filters.data;
|
|
2052
|
+
if (!(length instanceof LiteralValue) || typeof length.data !== "number")
|
|
2053
|
+
throw new CompilerError("The length of an array macro must be");
|
|
2054
|
+
if (length.data !== 3)
|
|
2055
|
+
throw new CompilerError("The filters array must have 3 items");
|
|
2056
|
+
// data is not an array
|
|
2057
|
+
const { 0: filter1, 1: filter2, 2: filter3 } = filters.data;
|
|
2058
|
+
assertLiteralOneOf(filter1, validRadarFilters, "The first filter");
|
|
2059
|
+
assertLiteralOneOf(filter2, validRadarFilters, "The second filter");
|
|
2060
|
+
assertLiteralOneOf(filter3, validRadarFilters, "The third filter");
|
|
1729
2061
|
if (!(order instanceof LiteralValue || order instanceof StoreValue))
|
|
1730
2062
|
throw new CompilerError("The radar order must be a literal or a store");
|
|
1731
|
-
|
|
1732
|
-
throw new CompilerError("The radar sort must be a string literal");
|
|
1733
|
-
if (!validRadarSorts.includes(sort.data))
|
|
1734
|
-
throw new CompilerError("Invalid sort value");
|
|
2063
|
+
assertLiteralOneOf(sort, validRadarSorts, "The radar sort");
|
|
1735
2064
|
const outUnit = new SenseableValue(scope);
|
|
1736
2065
|
return [
|
|
1737
2066
|
outUnit,
|
|
@@ -1750,7 +2079,9 @@ class Sensor extends MacroFunction {
|
|
|
1750
2079
|
throw new CompilerError("The sensor property must be a store");
|
|
1751
2080
|
if (!(target instanceof SenseableValue))
|
|
1752
2081
|
throw new CompilerError("The sensor target must be a senseable value");
|
|
1753
|
-
const temp = new
|
|
2082
|
+
const temp = assign(new SenseableValue(scope), {
|
|
2083
|
+
mutability: EMutability.readonly,
|
|
2084
|
+
});
|
|
1754
2085
|
return [temp, [new InstructionBase("sensor", temp, target, property)]];
|
|
1755
2086
|
});
|
|
1756
2087
|
}
|
|
@@ -1767,19 +2098,40 @@ class Wait extends MacroFunction {
|
|
|
1767
2098
|
}
|
|
1768
2099
|
}
|
|
1769
2100
|
|
|
1770
|
-
|
|
1771
|
-
class Lookup extends MacroFunction {
|
|
2101
|
+
class Lookup extends ObjectValue {
|
|
1772
2102
|
constructor(scope) {
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
2103
|
+
const data = createOverloadNamespace({
|
|
2104
|
+
scope,
|
|
2105
|
+
overloads: {
|
|
2106
|
+
block: { args: ["index"] },
|
|
2107
|
+
unit: { args: ["index"] },
|
|
2108
|
+
item: { args: ["index"] },
|
|
2109
|
+
liquid: { args: ["index"] },
|
|
2110
|
+
},
|
|
2111
|
+
handler(overload, index) {
|
|
2112
|
+
const output = new StoreValue(scope);
|
|
2113
|
+
return [
|
|
2114
|
+
output,
|
|
2115
|
+
[new InstructionBase("lookup", overload, output, index)],
|
|
2116
|
+
];
|
|
2117
|
+
},
|
|
2118
|
+
});
|
|
2119
|
+
super(scope, data);
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
class PackColor extends MacroFunction {
|
|
2124
|
+
constructor(scope) {
|
|
2125
|
+
super(scope, (...args) => {
|
|
2126
|
+
if (args.length !== 4) {
|
|
2127
|
+
throw new CompilerError(`Expected 4 arguments, received ${args.length}`);
|
|
2128
|
+
}
|
|
2129
|
+
if (!args.every((value) => value instanceof StoreValue ||
|
|
2130
|
+
(value instanceof LiteralValue && typeof value.data === "number"))) {
|
|
2131
|
+
throw new CompilerError("packColor arguments must be either stores or number literals");
|
|
2132
|
+
}
|
|
2133
|
+
const output = new StoreValue(scope);
|
|
2134
|
+
return [output, [new InstructionBase("packcolor", output, ...args)]];
|
|
1783
2135
|
});
|
|
1784
2136
|
}
|
|
1785
2137
|
}
|
|
@@ -1790,6 +2142,57 @@ class End extends MacroFunction {
|
|
|
1790
2142
|
}
|
|
1791
2143
|
}
|
|
1792
2144
|
|
|
2145
|
+
class SetBlock extends ObjectValue {
|
|
2146
|
+
constructor(scope) {
|
|
2147
|
+
const data = createOverloadNamespace({
|
|
2148
|
+
scope,
|
|
2149
|
+
overloads: {
|
|
2150
|
+
floor: { args: ["x", "y", "to"] },
|
|
2151
|
+
ore: { args: ["x", "y", "to"] },
|
|
2152
|
+
block: {
|
|
2153
|
+
named: "options",
|
|
2154
|
+
args: ["x", "y", "to", "team", { key: "rotation", default: "0" }],
|
|
2155
|
+
},
|
|
2156
|
+
},
|
|
2157
|
+
handler(overload, x, y, to, team, rotation) {
|
|
2158
|
+
return [
|
|
2159
|
+
null,
|
|
2160
|
+
[
|
|
2161
|
+
new InstructionBase("setblock", overload, to, x, y, team ?? "@delerict", rotation ?? "0"),
|
|
2162
|
+
],
|
|
2163
|
+
];
|
|
2164
|
+
},
|
|
2165
|
+
});
|
|
2166
|
+
super(scope, data);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
class SpawnUnit extends MacroFunction {
|
|
2171
|
+
constructor(scope) {
|
|
2172
|
+
super(scope, options => {
|
|
2173
|
+
assertIsObjectMacro(options, "The options");
|
|
2174
|
+
const { type, x, y, team, rotation } = options.data;
|
|
2175
|
+
assertIsRuntimeValue(type, "type");
|
|
2176
|
+
assertIsRuntimeValue(x, "x");
|
|
2177
|
+
assertIsRuntimeValue(y, "y");
|
|
2178
|
+
assertIsRuntimeValue(team, "team");
|
|
2179
|
+
const output = new SenseableValue(scope);
|
|
2180
|
+
return [
|
|
2181
|
+
output,
|
|
2182
|
+
[
|
|
2183
|
+
new InstructionBase("spawn", type, x, y, rotation ?? "0", team, output),
|
|
2184
|
+
],
|
|
2185
|
+
];
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
class Stop extends MacroFunction {
|
|
2191
|
+
constructor(scope) {
|
|
2192
|
+
super(scope, () => [null, [new InstructionBase("stop")]]);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
|
|
1793
2196
|
class UnitBind extends MacroFunction {
|
|
1794
2197
|
constructor(scope) {
|
|
1795
2198
|
super(scope, type => {
|
|
@@ -1800,82 +2203,85 @@ class UnitBind extends MacroFunction {
|
|
|
1800
2203
|
}
|
|
1801
2204
|
}
|
|
1802
2205
|
|
|
1803
|
-
|
|
1804
|
-
"idle",
|
|
1805
|
-
"stop",
|
|
1806
|
-
"move",
|
|
1807
|
-
"approach",
|
|
1808
|
-
"boost",
|
|
1809
|
-
"pathfind",
|
|
1810
|
-
"target",
|
|
1811
|
-
"targetp",
|
|
1812
|
-
"itemDrop",
|
|
1813
|
-
"itemTake",
|
|
1814
|
-
"payDrop",
|
|
1815
|
-
"payTake",
|
|
1816
|
-
"payEnter",
|
|
1817
|
-
"mine",
|
|
1818
|
-
"flag",
|
|
1819
|
-
"build",
|
|
1820
|
-
"getBlock",
|
|
1821
|
-
"within",
|
|
1822
|
-
];
|
|
1823
|
-
class UnitControl extends MacroFunction {
|
|
2206
|
+
class UnitControl extends ObjectValue {
|
|
1824
2207
|
constructor(scope) {
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
2208
|
+
const data = createOverloadNamespace({
|
|
2209
|
+
scope,
|
|
2210
|
+
overloads: {
|
|
2211
|
+
idle: { args: [] },
|
|
2212
|
+
stop: { args: [] },
|
|
2213
|
+
move: { args: ["x", "y"] },
|
|
2214
|
+
approach: { named: "options", args: ["x", "y", "radius"] },
|
|
2215
|
+
boost: { args: ["enable"] },
|
|
2216
|
+
pathfind: { args: [] },
|
|
2217
|
+
target: { named: "options", args: ["x", "y", "shoot"] },
|
|
2218
|
+
targetp: { named: "options", args: ["unit", "shoot"] },
|
|
2219
|
+
itemDrop: { args: ["target", "amount"] },
|
|
2220
|
+
itemTake: { args: ["target", "item", "amount"] },
|
|
2221
|
+
payDrop: { args: [] },
|
|
2222
|
+
payTake: { named: "options", args: ["takeUnits"] },
|
|
2223
|
+
payEnter: { args: [] },
|
|
2224
|
+
mine: { args: ["x", "y"] },
|
|
2225
|
+
flag: { args: ["value"] },
|
|
2226
|
+
build: {
|
|
2227
|
+
named: "options",
|
|
2228
|
+
args: ["x", "y", "block", "rotation", { key: "config", default: "" }],
|
|
2229
|
+
},
|
|
2230
|
+
getBlock: {
|
|
2231
|
+
args: ["x", "y"],
|
|
2232
|
+
},
|
|
2233
|
+
within: {
|
|
2234
|
+
named: "options",
|
|
2235
|
+
args: ["x", "y", "radius"],
|
|
2236
|
+
},
|
|
2237
|
+
},
|
|
2238
|
+
handler(overload, ...args) {
|
|
2239
|
+
let result = null;
|
|
2240
|
+
let extraArgs = [];
|
|
2241
|
+
switch (overload) {
|
|
2242
|
+
case "getBlock": {
|
|
2243
|
+
const outType = new StoreValue(scope);
|
|
2244
|
+
const outBuilding = new SenseableValue(scope);
|
|
2245
|
+
result = ObjectValue.fromArray(scope, [outType, outBuilding]);
|
|
2246
|
+
extraArgs = [outType, outBuilding, new LiteralValue(scope, 0)];
|
|
2247
|
+
break;
|
|
2248
|
+
}
|
|
2249
|
+
case "within": {
|
|
2250
|
+
const temp = new StoreValue(scope);
|
|
2251
|
+
result = temp;
|
|
2252
|
+
extraArgs = [temp, new LiteralValue(scope, 0)];
|
|
2253
|
+
break;
|
|
2254
|
+
}
|
|
1847
2255
|
}
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2256
|
+
return [
|
|
2257
|
+
result,
|
|
2258
|
+
[new InstructionBase("ucontrol", overload, ...args, ...extraArgs)],
|
|
2259
|
+
];
|
|
2260
|
+
},
|
|
1853
2261
|
});
|
|
2262
|
+
super(scope, data);
|
|
1854
2263
|
}
|
|
1855
2264
|
}
|
|
1856
2265
|
|
|
1857
2266
|
class UnitRadar extends MacroFunction {
|
|
1858
2267
|
constructor(scope) {
|
|
1859
|
-
super(scope,
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
2268
|
+
super(scope, options => {
|
|
2269
|
+
assertIsObjectMacro(options, "The radar options");
|
|
2270
|
+
const { filters, order, sort } = options.data;
|
|
2271
|
+
assertIsArrayMacro(filters, "filters");
|
|
2272
|
+
const { length } = filters.data;
|
|
2273
|
+
if (!(length instanceof LiteralValue) || typeof length.data !== "number")
|
|
2274
|
+
throw new CompilerError("The length of an array macro must be");
|
|
2275
|
+
if (length.data !== 3)
|
|
2276
|
+
throw new CompilerError("The filters array must have 3 items");
|
|
2277
|
+
// data is not an array
|
|
2278
|
+
const { 0: filter1, 1: filter2, 2: filter3 } = filters.data;
|
|
2279
|
+
assertLiteralOneOf(filter1, validRadarFilters, "The first filter");
|
|
2280
|
+
assertLiteralOneOf(filter2, validRadarFilters, "The second filter");
|
|
2281
|
+
assertLiteralOneOf(filter3, validRadarFilters, "The third filter");
|
|
1873
2282
|
if (!(order instanceof LiteralValue || order instanceof StoreValue))
|
|
1874
2283
|
throw new CompilerError("The radar order must be a literal or a store");
|
|
1875
|
-
|
|
1876
|
-
throw new CompilerError("The radar sort must be a string literal");
|
|
1877
|
-
if (!validRadarSorts.includes(sort.data))
|
|
1878
|
-
throw new CompilerError("Invalid sort value");
|
|
2284
|
+
assertLiteralOneOf(sort, validRadarSorts, "The radar sort");
|
|
1879
2285
|
const outUnit = new SenseableValue(scope);
|
|
1880
2286
|
return [
|
|
1881
2287
|
outUnit,
|
|
@@ -1888,7 +2294,6 @@ class UnitRadar extends MacroFunction {
|
|
|
1888
2294
|
}
|
|
1889
2295
|
}
|
|
1890
2296
|
|
|
1891
|
-
const validFinds = ["ore", "building", "spawn", "damaged"];
|
|
1892
2297
|
const validBuildingGroups = [
|
|
1893
2298
|
"core",
|
|
1894
2299
|
"storage",
|
|
@@ -1900,56 +2305,297 @@ const validBuildingGroups = [
|
|
|
1900
2305
|
"battery",
|
|
1901
2306
|
"reactor",
|
|
1902
2307
|
];
|
|
1903
|
-
class UnitLocate extends
|
|
2308
|
+
class UnitLocate extends ObjectValue {
|
|
1904
2309
|
constructor(scope) {
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2310
|
+
const data = createOverloadNamespace({
|
|
2311
|
+
scope,
|
|
2312
|
+
overloads: {
|
|
2313
|
+
ore: {
|
|
2314
|
+
args: ["ore"],
|
|
2315
|
+
},
|
|
2316
|
+
building: { named: "options", args: ["group", "enemy"] },
|
|
2317
|
+
spawn: {
|
|
2318
|
+
args: [],
|
|
2319
|
+
},
|
|
2320
|
+
damaged: {
|
|
2321
|
+
args: [],
|
|
2322
|
+
},
|
|
2323
|
+
},
|
|
2324
|
+
handler(overload, ...args) {
|
|
2325
|
+
const outFound = new StoreValue(scope);
|
|
2326
|
+
const outX = new StoreValue(scope);
|
|
2327
|
+
const outY = new StoreValue(scope);
|
|
2328
|
+
const outBuilding = new SenseableValue(scope);
|
|
2329
|
+
const outArgs = [outX, outY, outFound, outBuilding];
|
|
2330
|
+
let inputArgs = [];
|
|
2331
|
+
switch (overload) {
|
|
2332
|
+
case "ore": {
|
|
2333
|
+
const [ore] = args;
|
|
2334
|
+
inputArgs = [overload, "core", "true", ore];
|
|
2335
|
+
break;
|
|
2336
|
+
}
|
|
2337
|
+
case "building": {
|
|
2338
|
+
const [group, enemy] = args;
|
|
2339
|
+
if (!(group instanceof LiteralValue))
|
|
2340
|
+
throw new CompilerError("The building group must be a string literal");
|
|
2341
|
+
assertLiteralOneOf(group, validBuildingGroups, "The building group");
|
|
2342
|
+
inputArgs = [overload, group.data, enemy, "@copper"];
|
|
2343
|
+
break;
|
|
2344
|
+
}
|
|
2345
|
+
case "spawn":
|
|
2346
|
+
case "damaged": {
|
|
2347
|
+
inputArgs = [overload, "core", "true", "@copper"];
|
|
2348
|
+
break;
|
|
1928
2349
|
}
|
|
1929
|
-
if (!validBuildingGroups.includes(group.data))
|
|
1930
|
-
throw new CompilerError("Invalid building group");
|
|
1931
|
-
inputArgs = [find.data, group.data, enemy, "@copper"];
|
|
1932
|
-
break;
|
|
1933
|
-
}
|
|
1934
|
-
case "spawn":
|
|
1935
|
-
case "damaged": {
|
|
1936
|
-
inputArgs = [find.data, "core", "true", "@copper"];
|
|
1937
|
-
break;
|
|
1938
2350
|
}
|
|
1939
|
-
|
|
2351
|
+
return [
|
|
2352
|
+
ObjectValue.fromArray(scope, [
|
|
2353
|
+
outFound,
|
|
2354
|
+
outX,
|
|
2355
|
+
outY,
|
|
2356
|
+
...(overload !== "ore" ? [outBuilding] : []),
|
|
2357
|
+
]),
|
|
2358
|
+
[new InstructionBase("ulocate", ...inputArgs, ...outArgs)],
|
|
2359
|
+
];
|
|
2360
|
+
},
|
|
2361
|
+
});
|
|
2362
|
+
super(scope, data);
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
const validEffects = [
|
|
2367
|
+
"burning",
|
|
2368
|
+
"freezing",
|
|
2369
|
+
"unmoving",
|
|
2370
|
+
"wet",
|
|
2371
|
+
"melting",
|
|
2372
|
+
"sapped",
|
|
2373
|
+
"electrified",
|
|
2374
|
+
"spore-slowed",
|
|
2375
|
+
"tarred",
|
|
2376
|
+
"overdrive",
|
|
2377
|
+
"overclock",
|
|
2378
|
+
"boss",
|
|
2379
|
+
"shocked",
|
|
2380
|
+
"blasted",
|
|
2381
|
+
];
|
|
2382
|
+
class ApplyStatus extends ObjectValue {
|
|
2383
|
+
constructor(scope) {
|
|
2384
|
+
const data = createOverloadNamespace({
|
|
2385
|
+
scope,
|
|
2386
|
+
overloads: {
|
|
2387
|
+
apply: {
|
|
2388
|
+
args: ["status", "unit", { key: "duration", default: "10" }],
|
|
2389
|
+
},
|
|
2390
|
+
clear: { args: ["status", "unit"] },
|
|
2391
|
+
},
|
|
2392
|
+
handler(overload, effect, unit, duration) {
|
|
2393
|
+
if (!(effect instanceof LiteralValue))
|
|
2394
|
+
throw new CompilerError("The status effect must be a string literal");
|
|
2395
|
+
assertLiteralOneOf(effect, validEffects, "The status effect");
|
|
2396
|
+
return [
|
|
2397
|
+
null,
|
|
2398
|
+
[
|
|
2399
|
+
new InstructionBase("status", String(overload !== "apply"), effect.data, unit, duration),
|
|
2400
|
+
],
|
|
2401
|
+
];
|
|
2402
|
+
},
|
|
2403
|
+
});
|
|
2404
|
+
super(scope, data);
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
class SpawnWave extends MacroFunction {
|
|
2409
|
+
constructor(scope) {
|
|
2410
|
+
super(scope, (natural, x, y) => {
|
|
2411
|
+
if (!(natural instanceof LiteralValue) ||
|
|
2412
|
+
(natural.data !== 1 && natural.data !== 0))
|
|
2413
|
+
throw new CompilerError("The 'natural' argument must be a boolean literal");
|
|
1940
2414
|
return [
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
...(find.data !== "ore" ? [outBuilding] : []),
|
|
1946
|
-
]),
|
|
1947
|
-
[new InstructionBase("ulocate", ...inputArgs, ...outArgs)],
|
|
2415
|
+
null,
|
|
2416
|
+
[
|
|
2417
|
+
new InstructionBase("spawnwave", x ?? "10", y ?? "10", String(!!natural.data)),
|
|
2418
|
+
],
|
|
1948
2419
|
];
|
|
1949
2420
|
});
|
|
1950
2421
|
}
|
|
1951
2422
|
}
|
|
1952
2423
|
|
|
2424
|
+
class SetRule extends ObjectValue {
|
|
2425
|
+
constructor(scope) {
|
|
2426
|
+
const data = createOverloadNamespace({
|
|
2427
|
+
scope,
|
|
2428
|
+
overloads: {
|
|
2429
|
+
currentWaveTime: { args: ["seconds"] },
|
|
2430
|
+
waveTimer: { args: ["enabled"] },
|
|
2431
|
+
waves: { args: ["enabled"] },
|
|
2432
|
+
wave: { args: ["number"] },
|
|
2433
|
+
waveSpacing: { args: ["seconds"] },
|
|
2434
|
+
waveSending: { args: ["enabled"] },
|
|
2435
|
+
attackMode: { args: ["enabled"] },
|
|
2436
|
+
enemyCoreBuildRadius: { args: ["radius"] },
|
|
2437
|
+
dropZoneRadius: { args: ["radius"] },
|
|
2438
|
+
unitCap: { args: ["cap"] },
|
|
2439
|
+
mapArea: { named: "options", args: ["x", "y", "width", "height"] },
|
|
2440
|
+
lighting: { args: ["enabled"] },
|
|
2441
|
+
ambientLight: { args: ["rgbaData"] },
|
|
2442
|
+
solarMultiplier: { args: ["multiplier"] },
|
|
2443
|
+
buildSpeed: { args: ["team", "multiplier"] },
|
|
2444
|
+
unitBuildSpeed: { args: ["team", "multiplier"] },
|
|
2445
|
+
unitDamage: { args: ["team", "multiplier"] },
|
|
2446
|
+
blockHealth: { args: ["team", "multiplier"] },
|
|
2447
|
+
blockDamage: { args: ["team", "multiplier"] },
|
|
2448
|
+
rtsMinWeight: { args: ["team", "value"] },
|
|
2449
|
+
rtsMinSquad: { args: ["team", "value"] },
|
|
2450
|
+
},
|
|
2451
|
+
handler(overload, ...args) {
|
|
2452
|
+
const params = ["10", "0", "0", "100", "100"];
|
|
2453
|
+
switch (overload) {
|
|
2454
|
+
case "mapArea": {
|
|
2455
|
+
const [x, y, width, height] = args;
|
|
2456
|
+
params[1] = x;
|
|
2457
|
+
params[2] = y;
|
|
2458
|
+
params[3] = width;
|
|
2459
|
+
params[4] = height;
|
|
2460
|
+
break;
|
|
2461
|
+
}
|
|
2462
|
+
case "buildSpeed":
|
|
2463
|
+
case "unitBuildSpeed":
|
|
2464
|
+
case "unitDamage":
|
|
2465
|
+
case "blockHealth":
|
|
2466
|
+
case "blockDamage":
|
|
2467
|
+
case "rtsMinWeight":
|
|
2468
|
+
case "rtsMinSquad": {
|
|
2469
|
+
const [team, value] = args;
|
|
2470
|
+
params[1] = team;
|
|
2471
|
+
params[2] = value;
|
|
2472
|
+
break;
|
|
2473
|
+
}
|
|
2474
|
+
default:
|
|
2475
|
+
params[0] = args[0]; // the general value
|
|
2476
|
+
}
|
|
2477
|
+
return [null, [new InstructionBase("setrule", overload, ...params)]];
|
|
2478
|
+
},
|
|
2479
|
+
});
|
|
2480
|
+
super(scope, data);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
class FlushMessage extends ObjectValue {
|
|
2485
|
+
constructor(scope) {
|
|
2486
|
+
const data = createOverloadNamespace({
|
|
2487
|
+
scope,
|
|
2488
|
+
overloads: {
|
|
2489
|
+
notify: { args: [] },
|
|
2490
|
+
mission: { args: [] },
|
|
2491
|
+
announce: { args: ["duration"] },
|
|
2492
|
+
toast: { args: ["duration"] },
|
|
2493
|
+
},
|
|
2494
|
+
handler(overload, duration) {
|
|
2495
|
+
return [null, [new InstructionBase("message", overload, duration)]];
|
|
2496
|
+
},
|
|
2497
|
+
});
|
|
2498
|
+
super(scope, data);
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
class Cutscene extends ObjectValue {
|
|
2503
|
+
constructor(scope) {
|
|
2504
|
+
const data = createOverloadNamespace({
|
|
2505
|
+
scope,
|
|
2506
|
+
overloads: {
|
|
2507
|
+
pan: { named: "options", args: ["x", "y", "speed"] },
|
|
2508
|
+
zoom: { args: ["level"] },
|
|
2509
|
+
stop: { args: [] },
|
|
2510
|
+
},
|
|
2511
|
+
handler(overload, ...args) {
|
|
2512
|
+
const params = Object.assign(["100", "100", "0.06", "0"], args);
|
|
2513
|
+
return [null, [new InstructionBase("cutscene", overload, ...params)]];
|
|
2514
|
+
},
|
|
2515
|
+
});
|
|
2516
|
+
super(scope, data);
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
class Explosion extends MacroFunction {
|
|
2521
|
+
constructor(scope) {
|
|
2522
|
+
super(scope, options => {
|
|
2523
|
+
assertIsObjectMacro(options, "The options");
|
|
2524
|
+
const params = assertObjectFields(options, [
|
|
2525
|
+
"team",
|
|
2526
|
+
"x",
|
|
2527
|
+
"y",
|
|
2528
|
+
"radius",
|
|
2529
|
+
"damage",
|
|
2530
|
+
"air",
|
|
2531
|
+
"ground",
|
|
2532
|
+
"pierce",
|
|
2533
|
+
]);
|
|
2534
|
+
return [null, [new InstructionBase("explosion", ...params)]];
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
class SetRate extends MacroFunction {
|
|
2540
|
+
constructor(scope) {
|
|
2541
|
+
super(scope, ipt => [null, [new InstructionBase("setrate", ipt)]]);
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
class Fetch extends ObjectValue {
|
|
2546
|
+
constructor(scope) {
|
|
2547
|
+
const data = createOverloadNamespace({
|
|
2548
|
+
scope,
|
|
2549
|
+
overloads: {
|
|
2550
|
+
unit: { args: ["team", "index"] },
|
|
2551
|
+
unitCount: { args: ["team"] },
|
|
2552
|
+
player: { args: ["team", "index"] },
|
|
2553
|
+
playerCount: { args: ["team"] },
|
|
2554
|
+
core: { args: ["team", "index"] },
|
|
2555
|
+
coreCount: { args: ["team"] },
|
|
2556
|
+
build: { args: ["team", "index", "block"] },
|
|
2557
|
+
buildCount: { args: ["team", "block"] },
|
|
2558
|
+
},
|
|
2559
|
+
handler(overload, team, ...rest) {
|
|
2560
|
+
const output = new SenseableValue(scope);
|
|
2561
|
+
const params = ["0", "@conveyor"];
|
|
2562
|
+
if (overload === "buildCount") {
|
|
2563
|
+
params[1] = rest[0];
|
|
2564
|
+
}
|
|
2565
|
+
else {
|
|
2566
|
+
Object.assign(params, rest);
|
|
2567
|
+
}
|
|
2568
|
+
return [
|
|
2569
|
+
output,
|
|
2570
|
+
[new InstructionBase("fetch", overload, output, team, ...params)],
|
|
2571
|
+
];
|
|
2572
|
+
},
|
|
2573
|
+
});
|
|
2574
|
+
super(scope, data);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
class GetFlag extends MacroFunction {
|
|
2579
|
+
constructor(scope) {
|
|
2580
|
+
super(scope, flag => {
|
|
2581
|
+
const result = new StoreValue(scope);
|
|
2582
|
+
return [result, [new InstructionBase("getflag", result, flag)]];
|
|
2583
|
+
});
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
class SetFlag extends MacroFunction {
|
|
2588
|
+
constructor(scope) {
|
|
2589
|
+
super(scope, (flag, value) => {
|
|
2590
|
+
if (!flag)
|
|
2591
|
+
throw new CompilerError("Missing flag argument");
|
|
2592
|
+
if (!value)
|
|
2593
|
+
throw new CompilerError("Missing flag value");
|
|
2594
|
+
return [null, [new InstructionBase("setflag", flag, value)]];
|
|
2595
|
+
});
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
|
|
1953
2599
|
class MemoryEntry extends ObjectValue {
|
|
1954
2600
|
constructor(scope, mem, prop) {
|
|
1955
2601
|
super(scope, {
|
|
@@ -2064,24 +2710,6 @@ class VarsNamespace extends NamespaceMacro {
|
|
|
2064
2710
|
}).value,
|
|
2065
2711
|
});
|
|
2066
2712
|
}
|
|
2067
|
-
}
|
|
2068
|
-
class UCommandsNamespace extends NamespaceMacro {
|
|
2069
|
-
constructor(scope) {
|
|
2070
|
-
super(scope);
|
|
2071
|
-
this.data.$get = new MacroFunction(scope, prop => {
|
|
2072
|
-
if (!(prop instanceof LiteralValue) || typeof prop.data !== "string")
|
|
2073
|
-
throw new CompilerError("Cannot use dynamic properties on namespace macros");
|
|
2074
|
-
const symbolName = prop.data[0].toUpperCase() + prop.data.slice(1);
|
|
2075
|
-
const owner = new ValueOwner({
|
|
2076
|
-
scope,
|
|
2077
|
-
name: `@command${symbolName}`,
|
|
2078
|
-
value: assign(new StoreValue(scope), {
|
|
2079
|
-
mutability: EMutability.constant,
|
|
2080
|
-
}),
|
|
2081
|
-
});
|
|
2082
|
-
return [owner.value, []];
|
|
2083
|
-
});
|
|
2084
|
-
}
|
|
2085
2713
|
}
|
|
2086
2714
|
|
|
2087
2715
|
class GetGlobal extends MacroFunction {
|
|
@@ -2101,6 +2729,25 @@ class GetGlobal extends MacroFunction {
|
|
|
2101
2729
|
}
|
|
2102
2730
|
}
|
|
2103
2731
|
|
|
2732
|
+
class Asm extends MacroFunction {
|
|
2733
|
+
constructor(scope) {
|
|
2734
|
+
super(scope, (stringsArray, ...values) => {
|
|
2735
|
+
if (!isTemplateObjectArray(stringsArray))
|
|
2736
|
+
throw new CompilerError("Expected to receive a template strings array");
|
|
2737
|
+
const args = [];
|
|
2738
|
+
for (let i = 0; i < values.length; i++) {
|
|
2739
|
+
const [item] = stringsArray.get(scope, new LiteralValue(scope, i));
|
|
2740
|
+
args.push(item.data);
|
|
2741
|
+
args.push(values[i]);
|
|
2742
|
+
}
|
|
2743
|
+
const { length } = stringsArray.data;
|
|
2744
|
+
const [tail] = stringsArray.get(scope, new LiteralValue(scope, length.data - 1));
|
|
2745
|
+
args.push(tail.data);
|
|
2746
|
+
return [null, [new ZeroSpaceInstruction(...args)]];
|
|
2747
|
+
});
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2104
2751
|
/**
|
|
2105
2752
|
* Adds all the compiler globals to `scope`
|
|
2106
2753
|
*/
|
|
@@ -2108,16 +2755,17 @@ function initScope(scope) {
|
|
|
2108
2755
|
// namespaces
|
|
2109
2756
|
scope.hardSet("ControlKind", new NamespaceMacro(scope));
|
|
2110
2757
|
scope.hardSet("Vars", new VarsNamespace(scope));
|
|
2758
|
+
scope.hardSet("Teams", new NamespaceMacro(scope));
|
|
2111
2759
|
scope.hardSet("Items", new NamespaceMacro(scope, { changeCasing: true }));
|
|
2112
2760
|
scope.hardSet("Liquids", new NamespaceMacro(scope));
|
|
2113
|
-
scope.hardSet("Units", new NamespaceMacro(scope));
|
|
2761
|
+
scope.hardSet("Units", new NamespaceMacro(scope, { changeCasing: true }));
|
|
2114
2762
|
scope.hardSet("LAccess", new NamespaceMacro(scope));
|
|
2115
|
-
scope.hardSet("UnitCommands", new UCommandsNamespace(scope));
|
|
2116
2763
|
scope.hardSet("Blocks", new NamespaceMacro(scope, { changeCasing: true }));
|
|
2117
2764
|
// helper methods
|
|
2118
2765
|
scope.hardSet("getBuilding", new GetGlobal(scope, EMutability.constant));
|
|
2119
2766
|
scope.hardSet("getVar", new GetGlobal(scope, EMutability.mutable));
|
|
2120
2767
|
scope.hardSet("concat", new Concat(scope));
|
|
2768
|
+
scope.hardSet("asm", new Asm(scope));
|
|
2121
2769
|
scope.hardSet("Math", new MlogMath(scope));
|
|
2122
2770
|
scope.hardSet("Memory", new MemoryBuilder(scope));
|
|
2123
2771
|
// commands
|
|
@@ -2131,36 +2779,58 @@ function initScope(scope) {
|
|
|
2131
2779
|
scope.hardSet("sensor", new Sensor(scope));
|
|
2132
2780
|
scope.hardSet("wait", new Wait(scope));
|
|
2133
2781
|
scope.hardSet("lookup", new Lookup(scope));
|
|
2782
|
+
scope.hardSet("packColor", new PackColor(scope));
|
|
2134
2783
|
scope.hardSet("endScript", new End(scope));
|
|
2784
|
+
scope.hardSet("stopScript", new Stop(scope));
|
|
2135
2785
|
scope.hardSet("unitBind", new UnitBind(scope));
|
|
2136
2786
|
scope.hardSet("unitControl", new UnitControl(scope));
|
|
2137
2787
|
scope.hardSet("unitRadar", new UnitRadar(scope));
|
|
2138
2788
|
scope.hardSet("unitLocate", new UnitLocate(scope));
|
|
2789
|
+
// world processor commands
|
|
2790
|
+
scope.hardSet("getBlock", new GetBlock(scope));
|
|
2791
|
+
scope.hardSet("setBlock", new SetBlock(scope));
|
|
2792
|
+
scope.hardSet("spawnUnit", new SpawnUnit(scope));
|
|
2793
|
+
scope.hardSet("applyStatus", new ApplyStatus(scope));
|
|
2794
|
+
scope.hardSet("spawnWave", new SpawnWave(scope));
|
|
2795
|
+
scope.hardSet("setRule", new SetRule(scope));
|
|
2796
|
+
scope.hardSet("flushMessage", new FlushMessage(scope));
|
|
2797
|
+
scope.hardSet("cutscene", new Cutscene(scope));
|
|
2798
|
+
scope.hardSet("explosion", new Explosion(scope));
|
|
2799
|
+
scope.hardSet("setRate", new SetRate(scope));
|
|
2800
|
+
scope.hardSet("fetch", new Fetch(scope));
|
|
2801
|
+
scope.hardSet("getFlag", new GetFlag(scope));
|
|
2802
|
+
scope.hardSet("setFlag", new SetFlag(scope));
|
|
2139
2803
|
}
|
|
2140
2804
|
|
|
2141
2805
|
class Compiler {
|
|
2142
|
-
constructor({ stackName, compactNames = false } = {}) {
|
|
2806
|
+
constructor({ stackName, compactNames = false, sourcemap = false, } = {}) {
|
|
2143
2807
|
this.handlers = handlers;
|
|
2144
2808
|
this.usingStack = !!stackName;
|
|
2145
2809
|
this.stackName = stackName;
|
|
2146
2810
|
this.compactNames = compactNames;
|
|
2811
|
+
this.sourcemap = sourcemap;
|
|
2147
2812
|
}
|
|
2148
2813
|
compile(script) {
|
|
2149
2814
|
let output;
|
|
2815
|
+
let sourcemaps;
|
|
2150
2816
|
try {
|
|
2151
2817
|
const program = this.parse(script);
|
|
2152
2818
|
const scope = new Scope({});
|
|
2153
2819
|
initScope(scope);
|
|
2154
2820
|
const valueInst = this.handle(scope, program);
|
|
2155
2821
|
valueInst[1].push(new EndInstruction(), ...scope.inst);
|
|
2822
|
+
hideRedundantJumps(valueInst[1]);
|
|
2156
2823
|
this.resolve(valueInst);
|
|
2157
2824
|
output = this.serialize(valueInst) + "\n";
|
|
2825
|
+
if (this.sourcemap) {
|
|
2826
|
+
sourcemaps = this.mapSources(valueInst);
|
|
2827
|
+
}
|
|
2158
2828
|
}
|
|
2159
2829
|
catch (error) {
|
|
2160
|
-
const
|
|
2161
|
-
return [null,
|
|
2830
|
+
const err = error instanceof CompilerError ? error : CompilerError.from(error);
|
|
2831
|
+
return [null, err];
|
|
2162
2832
|
}
|
|
2163
|
-
return [output, null,
|
|
2833
|
+
return [output, null, sourcemaps];
|
|
2164
2834
|
}
|
|
2165
2835
|
resolve(valueInst) {
|
|
2166
2836
|
let i = 0;
|
|
@@ -2180,40 +2850,92 @@ class Compiler {
|
|
|
2180
2850
|
plugins: ["typescript"],
|
|
2181
2851
|
});
|
|
2182
2852
|
}
|
|
2183
|
-
|
|
2853
|
+
mapSources(valueInst) {
|
|
2854
|
+
const result = [];
|
|
2855
|
+
for (const inst of valueInst[1]) {
|
|
2856
|
+
if (!inst.hidden)
|
|
2857
|
+
result.push(inst.source);
|
|
2858
|
+
}
|
|
2859
|
+
return result;
|
|
2860
|
+
}
|
|
2861
|
+
handle(scope, node, handler = this.handlers[node.type]) {
|
|
2184
2862
|
try {
|
|
2185
|
-
const handler = this.handlers[node.type];
|
|
2186
2863
|
if (!handler)
|
|
2187
2864
|
throw new CompilerError("Missing handler for " + node.type);
|
|
2188
|
-
|
|
2865
|
+
const result = handler(this, scope, node, null);
|
|
2866
|
+
if (this.sourcemap)
|
|
2867
|
+
return appendSourceLocations(result, node);
|
|
2868
|
+
return result;
|
|
2189
2869
|
}
|
|
2190
2870
|
catch (error) {
|
|
2191
2871
|
if (error instanceof CompilerError) {
|
|
2192
|
-
error.
|
|
2872
|
+
error.loc ??= node.loc;
|
|
2193
2873
|
}
|
|
2194
2874
|
throw error;
|
|
2195
2875
|
}
|
|
2196
2876
|
}
|
|
2197
2877
|
handleEval(scope, node) {
|
|
2198
2878
|
const [res, inst] = this.handle(scope, node);
|
|
2199
|
-
|
|
2879
|
+
if (!res)
|
|
2880
|
+
throw new CompilerError("Cannot eval null", node);
|
|
2200
2881
|
const [evaluated, evaluatedInst] = res.eval(scope);
|
|
2201
|
-
|
|
2882
|
+
const result = [evaluated, [...inst, ...evaluatedInst]];
|
|
2883
|
+
if (this.sourcemap)
|
|
2884
|
+
return appendSourceLocations(result, node);
|
|
2885
|
+
return result;
|
|
2202
2886
|
}
|
|
2203
2887
|
handleConsume(scope, node) {
|
|
2204
2888
|
const [res, inst] = this.handle(scope, node);
|
|
2205
|
-
|
|
2889
|
+
if (!res)
|
|
2890
|
+
throw new CompilerError("Cannot consume null", node);
|
|
2206
2891
|
const [evaluated, evaluatedInst] = res.consume(scope);
|
|
2207
|
-
|
|
2892
|
+
const result = [evaluated, [...inst, ...evaluatedInst]];
|
|
2893
|
+
if (this.sourcemap)
|
|
2894
|
+
return appendSourceLocations(result, node);
|
|
2895
|
+
return result;
|
|
2208
2896
|
}
|
|
2209
|
-
|
|
2897
|
+
/**
|
|
2898
|
+
* Handles many nodes in order.
|
|
2899
|
+
*
|
|
2900
|
+
* The usage of this method over a regular loop over an array of nodes
|
|
2901
|
+
* is only required if the code inside the loop generates
|
|
2902
|
+
* instructions that are not tracked by the compiler
|
|
2903
|
+
* handler methods ({@link handle}, {@link handleEval}, {@link handleConsume}
|
|
2904
|
+
* and {@link handleMany})
|
|
2905
|
+
*
|
|
2906
|
+
*/
|
|
2907
|
+
handleMany(scope, nodes, handler) {
|
|
2210
2908
|
const lines = [];
|
|
2211
2909
|
for (const node of nodes) {
|
|
2212
|
-
const [, nodeLines] =
|
|
2910
|
+
const [, nodeLines] = this.handle(scope, node, handler && (() => handler(node)));
|
|
2213
2911
|
lines.push(...nodeLines);
|
|
2214
2912
|
}
|
|
2215
2913
|
return [null, lines];
|
|
2216
2914
|
}
|
|
2915
|
+
}
|
|
2916
|
+
/** Removes jump instructions that point right to the next line */
|
|
2917
|
+
function hideRedundantJumps(inst) {
|
|
2918
|
+
for (let i = 0; i < inst.length; i++) {
|
|
2919
|
+
const instruction = inst[i];
|
|
2920
|
+
if (!(instruction instanceof JumpInstruction))
|
|
2921
|
+
continue;
|
|
2922
|
+
const { address } = instruction;
|
|
2923
|
+
let searchIndex = i + 1;
|
|
2924
|
+
let current = inst[searchIndex];
|
|
2925
|
+
while (current.hidden) {
|
|
2926
|
+
if (current instanceof AddressResolver &&
|
|
2927
|
+
current.bonds.includes(address)) {
|
|
2928
|
+
// only gets assigned if `current` is an adress resolver
|
|
2929
|
+
// that resolves the jump adress
|
|
2930
|
+
// and that is also right next to the jump,
|
|
2931
|
+
// without any actual instructions in between
|
|
2932
|
+
instruction.hidden = true;
|
|
2933
|
+
break;
|
|
2934
|
+
}
|
|
2935
|
+
searchIndex++;
|
|
2936
|
+
current = inst[searchIndex];
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2217
2939
|
}
|
|
2218
2940
|
|
|
2219
2941
|
exports.Compiler = Compiler;
|