mlogjs 0.3.0-beta.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 +1096 -341
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +1096 -341
- 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/GetGlobal.d.ts +2 -2
- 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 +30 -1
- package/dist/types/utils.d.ts +24 -1
- package/dist/types/values/BaseValue.d.ts +2 -0
- package/dist/types/values/FunctionValue.d.ts +3 -3
- package/dist/types/values/LiteralValue.d.ts +2 -2
- package/dist/types/values/ObjectValue.d.ts +3 -3
- package/dist/types/values/SenseableValue.d.ts +5 -5
- package/dist/types/values/StoreValue.d.ts +2 -2
- package/dist/types/values/VoidValue.d.ts +2 -2
- 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,75 @@ 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 = {}));
|
|
81
|
+
/** Defines the possible types of mutability of a value */
|
|
82
|
+
var EMutability;
|
|
83
|
+
(function (EMutability) {
|
|
84
|
+
/**
|
|
85
|
+
* The value can be changed by the user's code,
|
|
86
|
+
* by the mlog runtime, or us
|
|
87
|
+
*/
|
|
88
|
+
EMutability[EMutability["mutable"] = 0] = "mutable";
|
|
89
|
+
/**
|
|
90
|
+
* The value cannot be directly assigned,
|
|
91
|
+
* but it's still not safe from mutations coming from the runtime.
|
|
92
|
+
*/
|
|
93
|
+
EMutability[EMutability["readonly"] = 1] = "readonly";
|
|
94
|
+
/** Constant values, won't change during execution */
|
|
95
|
+
EMutability[EMutability["constant"] = 2] = "constant";
|
|
96
|
+
})(EMutability || (EMutability = {}));
|
|
97
|
+
|
|
35
98
|
const arithmeticBinaryOperators = [
|
|
36
99
|
"*",
|
|
37
100
|
"**",
|
|
@@ -110,7 +173,7 @@ const operators = [...leftRightOperators, ...singleOperators];
|
|
|
110
173
|
class VoidValue {
|
|
111
174
|
constructor(scope) {
|
|
112
175
|
this.owner = null;
|
|
113
|
-
this.
|
|
176
|
+
this.mutability = EMutability.mutable;
|
|
114
177
|
this.macro = false;
|
|
115
178
|
this.scope = scope;
|
|
116
179
|
}
|
|
@@ -142,6 +205,8 @@ for (const key of operators) {
|
|
|
142
205
|
|
|
143
206
|
class InstructionBase {
|
|
144
207
|
constructor(...args) {
|
|
208
|
+
this.intent = EInstIntent.none;
|
|
209
|
+
this.alwaysRuns = true;
|
|
145
210
|
this._hidden = false;
|
|
146
211
|
this.args = args;
|
|
147
212
|
}
|
|
@@ -218,6 +283,7 @@ var EJumpKind;
|
|
|
218
283
|
class JumpInstruction extends InstructionBase {
|
|
219
284
|
constructor(address, kind, left = null, right = null) {
|
|
220
285
|
super("jump", address, kind, left, right);
|
|
286
|
+
this.address = address;
|
|
221
287
|
}
|
|
222
288
|
}
|
|
223
289
|
|
|
@@ -236,11 +302,13 @@ class ZeroSpaceInstruction extends InstructionBase {
|
|
|
236
302
|
class BreakInstruction extends JumpInstruction {
|
|
237
303
|
constructor(address) {
|
|
238
304
|
super(address, EJumpKind.Always);
|
|
305
|
+
this.intent = EInstIntent.break;
|
|
239
306
|
}
|
|
240
307
|
}
|
|
241
308
|
class ContinueInstruction extends JumpInstruction {
|
|
242
309
|
constructor(address) {
|
|
243
310
|
super(address, EJumpKind.Always);
|
|
311
|
+
this.intent = EInstIntent.continue;
|
|
244
312
|
}
|
|
245
313
|
}
|
|
246
314
|
|
|
@@ -292,6 +360,20 @@ class BaseValue extends VoidValue {
|
|
|
292
360
|
// TODO: should it return 0 + this ?
|
|
293
361
|
return this.eval(scope);
|
|
294
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
|
+
}
|
|
295
377
|
ensureOwned() {
|
|
296
378
|
this.owner ??= new ValueOwner({ scope: this.scope, value: this });
|
|
297
379
|
}
|
|
@@ -336,18 +418,6 @@ for (const key in operatorMap$1) {
|
|
|
336
418
|
];
|
|
337
419
|
};
|
|
338
420
|
}
|
|
339
|
-
const unaryOperatorMap$1 = {
|
|
340
|
-
"!": "not",
|
|
341
|
-
"~": "flip",
|
|
342
|
-
};
|
|
343
|
-
for (const key in unaryOperatorMap$1) {
|
|
344
|
-
const name = unaryOperatorMap$1[key];
|
|
345
|
-
BaseValue.prototype[key] = function (scope) {
|
|
346
|
-
const [that, inst] = this.consume(scope);
|
|
347
|
-
const temp = new StoreValue(scope);
|
|
348
|
-
return [temp, [...inst, new OperationInstruction(name, temp, that, null)]];
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
421
|
const assignmentToBinary = {
|
|
352
422
|
"+=": "+",
|
|
353
423
|
"-=": "-",
|
|
@@ -399,7 +469,7 @@ const literalMethods = {
|
|
|
399
469
|
class LiteralValue extends BaseValue {
|
|
400
470
|
constructor(scope, data) {
|
|
401
471
|
super(scope);
|
|
402
|
-
this.
|
|
472
|
+
this.mutability = EMutability.constant;
|
|
403
473
|
this.data = data;
|
|
404
474
|
}
|
|
405
475
|
eval(_scope) {
|
|
@@ -460,18 +530,22 @@ for (const key in operatorMap) {
|
|
|
460
530
|
if (!(value instanceof LiteralValue)) {
|
|
461
531
|
return BaseValue.prototype[key].apply(this, [scope, value]);
|
|
462
532
|
}
|
|
463
|
-
return [
|
|
533
|
+
return [
|
|
534
|
+
new LiteralValue(scope, fn(this.data, value.data)),
|
|
535
|
+
[],
|
|
536
|
+
];
|
|
464
537
|
};
|
|
465
538
|
}
|
|
466
539
|
const unaryOperatorMap = {
|
|
467
540
|
"!": v => +!v,
|
|
468
541
|
"~": v => ~v,
|
|
469
542
|
"u-": v => -v,
|
|
543
|
+
"u+": v => +v,
|
|
470
544
|
};
|
|
471
545
|
for (const key in unaryOperatorMap) {
|
|
472
546
|
LiteralValue.prototype[key] = function (scope) {
|
|
473
547
|
const fn = unaryOperatorMap[key];
|
|
474
|
-
return [new LiteralValue(scope, fn(this.
|
|
548
|
+
return [new LiteralValue(scope, fn(this.data)), []];
|
|
475
549
|
};
|
|
476
550
|
}
|
|
477
551
|
|
|
@@ -522,7 +596,33 @@ const itemNames = [
|
|
|
522
596
|
"sporePod",
|
|
523
597
|
"blastCompound",
|
|
524
598
|
"pyratite",
|
|
525
|
-
];
|
|
599
|
+
];
|
|
600
|
+
/**
|
|
601
|
+
* A more type safe version of `Object.assign`
|
|
602
|
+
*/
|
|
603
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
604
|
+
function assign(obj, props) {
|
|
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");
|
|
625
|
+
}
|
|
526
626
|
|
|
527
627
|
/**
|
|
528
628
|
* `StoreValue` represents values unknown at compile time,
|
|
@@ -531,13 +631,13 @@ const itemNames = [
|
|
|
531
631
|
class StoreValue extends BaseValue {
|
|
532
632
|
constructor(scope) {
|
|
533
633
|
super(scope);
|
|
534
|
-
this.
|
|
634
|
+
this.mutability = EMutability.mutable;
|
|
535
635
|
}
|
|
536
636
|
typeof(scope) {
|
|
537
637
|
return [new LiteralValue(scope, "store"), []];
|
|
538
638
|
}
|
|
539
639
|
"="(scope, value) {
|
|
540
|
-
if (this.
|
|
640
|
+
if (this.mutability !== EMutability.mutable)
|
|
541
641
|
throw new CompilerError(`Cannot assign to immutable store '${this}'.`);
|
|
542
642
|
if (this.owner) {
|
|
543
643
|
if (this.owner === value.owner && value instanceof StoreValue)
|
|
@@ -569,12 +669,13 @@ class StoreValue extends BaseValue {
|
|
|
569
669
|
class ObjectValue extends VoidValue {
|
|
570
670
|
constructor(scope, data = {}) {
|
|
571
671
|
super(scope);
|
|
572
|
-
this.
|
|
672
|
+
this.mutability = EMutability.constant;
|
|
573
673
|
this.macro = true;
|
|
574
674
|
this.data = data;
|
|
575
675
|
}
|
|
576
|
-
static fromArray(scope, items) {
|
|
676
|
+
static fromArray(scope, items, intialData) {
|
|
577
677
|
const data = {
|
|
678
|
+
...intialData,
|
|
578
679
|
length: new LiteralValue(scope, items.length),
|
|
579
680
|
};
|
|
580
681
|
items.forEach((item, i) => {
|
|
@@ -651,14 +752,15 @@ const senseableProps = ["controller"];
|
|
|
651
752
|
* Note that these values are constant by default, so make sure
|
|
652
753
|
* to set that field to `false` if you want them to be assignable. Example:
|
|
653
754
|
* ```
|
|
654
|
-
* const value = new SenseableValue(scope)
|
|
655
|
-
*
|
|
755
|
+
* const value = assign(new SenseableValue(scope), {
|
|
756
|
+
* mutability: EMutability.mutable
|
|
757
|
+
* })
|
|
656
758
|
* ```
|
|
657
759
|
*/
|
|
658
760
|
class SenseableValue extends StoreValue {
|
|
659
761
|
constructor(scope) {
|
|
660
762
|
super(scope);
|
|
661
|
-
this.
|
|
763
|
+
this.mutability = EMutability.constant;
|
|
662
764
|
}
|
|
663
765
|
get(scope, prop) {
|
|
664
766
|
if (prop instanceof LiteralValue && typeof prop.data === "string") {
|
|
@@ -674,14 +776,13 @@ class SenseableValue extends StoreValue {
|
|
|
674
776
|
];
|
|
675
777
|
}
|
|
676
778
|
if (prop instanceof StoreValue) {
|
|
677
|
-
const temp = new
|
|
779
|
+
const temp = assign(new SenseableValue(scope), {
|
|
780
|
+
mutability: EMutability.readonly,
|
|
781
|
+
});
|
|
678
782
|
return [temp, [new InstructionBase("sensor", temp, this, prop)]];
|
|
679
783
|
}
|
|
680
784
|
throw new CompilerError(`Cannot sense "${prop}" property`);
|
|
681
785
|
}
|
|
682
|
-
typeof(scope) {
|
|
683
|
-
return [new LiteralValue(scope, "senseable"), []];
|
|
684
|
-
}
|
|
685
786
|
}
|
|
686
787
|
|
|
687
788
|
/**
|
|
@@ -778,11 +879,11 @@ class Scope {
|
|
|
778
879
|
return owner.value;
|
|
779
880
|
}
|
|
780
881
|
make(identifier, name) {
|
|
781
|
-
const value = new SenseableValue(this);
|
|
782
|
-
value.constant = false;
|
|
783
882
|
const owner = new ValueOwner({
|
|
784
883
|
scope: this,
|
|
785
|
-
value,
|
|
884
|
+
value: assign(new SenseableValue(this), {
|
|
885
|
+
mutability: EMutability.mutable,
|
|
886
|
+
}),
|
|
786
887
|
identifier,
|
|
787
888
|
name,
|
|
788
889
|
});
|
|
@@ -802,7 +903,7 @@ const Program = (c, scope, node) => {
|
|
|
802
903
|
};
|
|
803
904
|
|
|
804
905
|
const VariableDeclaration = (c, scope, node) => {
|
|
805
|
-
return c.handleMany(scope, node.declarations,
|
|
906
|
+
return c.handleMany(scope, node.declarations, child => VariableDeclarator(c, scope, child, node.kind));
|
|
806
907
|
};
|
|
807
908
|
const VariableDeclarator = (c, scope, node, kind = "let") => {
|
|
808
909
|
const [init, inst] = node.init
|
|
@@ -812,25 +913,25 @@ const VariableDeclarator = (c, scope, node, kind = "let") => {
|
|
|
812
913
|
return [null, inst];
|
|
813
914
|
};
|
|
814
915
|
const Declare = (c, scope, node, kind, init) => {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
node
|
|
825
|
-
|
|
826
|
-
}
|
|
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
|
+
});
|
|
827
928
|
};
|
|
828
929
|
const DeclareIdentifier = (c, scope, node, kind, init) => {
|
|
829
930
|
const { name: identifier } = node;
|
|
830
931
|
const name = nodeName(node, !c.compactNames && identifier);
|
|
831
932
|
if (kind === "const" && !init)
|
|
832
|
-
throw new CompilerError("Constants must be initialized.",
|
|
833
|
-
if (kind === "const" && init?.constant) {
|
|
933
|
+
throw new CompilerError("Constants must be initialized.", node);
|
|
934
|
+
if (kind === "const" && init?.mutability === EMutability.constant) {
|
|
834
935
|
const owner = new ValueOwner({
|
|
835
936
|
scope,
|
|
836
937
|
identifier,
|
|
@@ -846,13 +947,11 @@ const DeclareIdentifier = (c, scope, node, kind, init) => {
|
|
|
846
947
|
const inst = [];
|
|
847
948
|
if (init) {
|
|
848
949
|
if (init.macro)
|
|
849
|
-
throw new CompilerError("Macro values must be held by constants",
|
|
850
|
-
node,
|
|
851
|
-
]);
|
|
950
|
+
throw new CompilerError("Macro values must be held by constants", node);
|
|
852
951
|
inst.push(...value["="](scope, init)[1]);
|
|
853
952
|
}
|
|
854
953
|
if (kind === "const")
|
|
855
|
-
value.
|
|
954
|
+
value.mutability = EMutability.constant;
|
|
856
955
|
return [null, inst];
|
|
857
956
|
}
|
|
858
957
|
};
|
|
@@ -867,29 +966,28 @@ const DeclareArrayPattern = (c, scope, node, kind, init) => {
|
|
|
867
966
|
continue;
|
|
868
967
|
const val = init.data[i];
|
|
869
968
|
if (!val)
|
|
870
|
-
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);
|
|
871
970
|
inst.push(...Declare(c, scope, element, kind, val)[1]);
|
|
872
971
|
}
|
|
873
972
|
return [null, inst];
|
|
874
973
|
};
|
|
875
974
|
const DeclareObjectPattern = (c, scope, node, kind, base) => {
|
|
876
975
|
if (!base)
|
|
877
|
-
throw new CompilerError("Cannot use object destructuring without an initializer",
|
|
976
|
+
throw new CompilerError("Cannot use object destructuring without an initializer", node);
|
|
878
977
|
const { properties } = node;
|
|
879
978
|
const [init, inst] = base.consume(scope);
|
|
880
|
-
|
|
979
|
+
const propertiesInst = c.handleMany(scope, properties, prop => {
|
|
881
980
|
if (prop.type === "RestElement")
|
|
882
|
-
throw new CompilerError("The rest operator is not supported",
|
|
981
|
+
throw new CompilerError("The rest operator is not supported", prop);
|
|
883
982
|
const { key, value } = prop;
|
|
884
|
-
const
|
|
983
|
+
const keyInst = key.type === "Identifier" && !prop.computed
|
|
885
984
|
? [new LiteralValue(scope, key.name), []]
|
|
886
985
|
: c.handleConsume(scope, prop.key);
|
|
887
|
-
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
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]]];
|
|
893
991
|
};
|
|
894
992
|
|
|
895
993
|
const Literal = (_c, scope, node) => [new LiteralValue(scope, node.value), []];
|
|
@@ -908,7 +1006,34 @@ const LRExpression = (c, scope, node) => {
|
|
|
908
1006
|
return [op, [...leftInst, ...rightInst, ...opInst]];
|
|
909
1007
|
};
|
|
910
1008
|
const BinaryExpression = LRExpression;
|
|
911
|
-
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
|
+
};
|
|
912
1037
|
const AssignmentExpression = (c, scope, node) => {
|
|
913
1038
|
const [left, leftInst] = c.handle(scope, node.left);
|
|
914
1039
|
// doesn't need to consume because the operators already do that
|
|
@@ -998,13 +1123,75 @@ const IfStatement = (c, scope, node) => {
|
|
|
998
1123
|
return [null, inst];
|
|
999
1124
|
}
|
|
1000
1125
|
const endIfAddr = new LiteralValue(scope, null);
|
|
1001
|
-
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));
|
|
1002
1127
|
const endElseAddr = new LiteralValue(scope, null);
|
|
1003
|
-
if (node.alternate)
|
|
1004
|
-
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
|
+
}
|
|
1005
1131
|
return [null, inst];
|
|
1006
1132
|
};
|
|
1007
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
|
+
|
|
1008
1195
|
const WhileStatement = (c, scope, node) => {
|
|
1009
1196
|
const lines = [];
|
|
1010
1197
|
const [test, testLines] = c.handleConsume(scope, node.test);
|
|
@@ -1018,7 +1205,7 @@ const WhileStatement = (c, scope, node) => {
|
|
|
1018
1205
|
}
|
|
1019
1206
|
return [null, lines];
|
|
1020
1207
|
}
|
|
1021
|
-
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);
|
|
1022
1209
|
return [null, lines];
|
|
1023
1210
|
};
|
|
1024
1211
|
const DoWhileStatement = (c, scope, node) => {
|
|
@@ -1062,7 +1249,7 @@ const ForStatement = (c, scope, node) => {
|
|
|
1062
1249
|
startLoopLine,
|
|
1063
1250
|
...testLines,
|
|
1064
1251
|
new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)),
|
|
1065
|
-
...c.handle(scope, node.body)[1],
|
|
1252
|
+
...withAlwaysRuns(c.handle(scope, node.body), false)[1],
|
|
1066
1253
|
...updateLines,
|
|
1067
1254
|
new JumpInstruction(startLoopAddr, EJumpKind.Always),
|
|
1068
1255
|
endLoopLine,
|
|
@@ -1073,7 +1260,7 @@ const ForStatement = (c, scope, node) => {
|
|
|
1073
1260
|
class FunctionValue extends VoidValue {
|
|
1074
1261
|
constructor({ scope, params, body, c, node, }) {
|
|
1075
1262
|
super(scope);
|
|
1076
|
-
this.
|
|
1263
|
+
this.mutability = EMutability.constant;
|
|
1077
1264
|
this.macro = true;
|
|
1078
1265
|
this.paramOwners = [];
|
|
1079
1266
|
this.bundled = false;
|
|
@@ -1093,7 +1280,9 @@ class FunctionValue extends VoidValue {
|
|
|
1093
1280
|
const name = nodeName(id, !this.c.compactNames && id.name);
|
|
1094
1281
|
const owner = new ValueOwner({
|
|
1095
1282
|
scope: this.childScope,
|
|
1096
|
-
value: new
|
|
1283
|
+
value: assign(new SenseableValue(this.childScope), {
|
|
1284
|
+
mutability: EMutability.mutable,
|
|
1285
|
+
}),
|
|
1097
1286
|
identifier: id.name,
|
|
1098
1287
|
name,
|
|
1099
1288
|
});
|
|
@@ -1108,15 +1297,16 @@ class FunctionValue extends VoidValue {
|
|
|
1108
1297
|
if (this.initialized)
|
|
1109
1298
|
return;
|
|
1110
1299
|
this.initialized = true;
|
|
1111
|
-
const name =
|
|
1300
|
+
const { name } = this.owner;
|
|
1112
1301
|
this.initScope(name);
|
|
1113
1302
|
this.addr = new LiteralValue(this.childScope, null);
|
|
1114
1303
|
this.temp = new ValueOwner({
|
|
1115
1304
|
scope: this.childScope,
|
|
1116
1305
|
name: `${internalPrefix}f${name}`,
|
|
1117
|
-
value: new SenseableValue(this.childScope),
|
|
1306
|
+
value: assign(new SenseableValue(this.childScope), {
|
|
1307
|
+
mutability: EMutability.mutable,
|
|
1308
|
+
}),
|
|
1118
1309
|
});
|
|
1119
|
-
this.temp.value.constant = false;
|
|
1120
1310
|
this.ret = new ValueOwner({
|
|
1121
1311
|
scope: this.childScope,
|
|
1122
1312
|
name: `${internalPrefix}r${name}`,
|
|
@@ -1127,12 +1317,17 @@ class FunctionValue extends VoidValue {
|
|
|
1127
1317
|
...this.c.handle(this.childScope, this.body)[1],
|
|
1128
1318
|
];
|
|
1129
1319
|
if (!endsWithReturn(this.inst)) {
|
|
1130
|
-
this.inst.push(new SetCounterInstruction(this.ret.value)
|
|
1320
|
+
this.inst.push(assign(new SetCounterInstruction(this.ret.value), {
|
|
1321
|
+
intent: EInstIntent.return,
|
|
1322
|
+
}));
|
|
1131
1323
|
}
|
|
1132
1324
|
}
|
|
1133
1325
|
normalReturn(scope, arg) {
|
|
1134
1326
|
const argInst = arg ? this.temp.value["="](scope, arg)[1] : [];
|
|
1135
|
-
|
|
1327
|
+
const returnInst = assign(new SetCounterInstruction(this.ret.value), {
|
|
1328
|
+
intent: EInstIntent.return,
|
|
1329
|
+
});
|
|
1330
|
+
return [null, [...argInst, returnInst]];
|
|
1136
1331
|
}
|
|
1137
1332
|
normalCall(scope, args) {
|
|
1138
1333
|
if (!this.bundled)
|
|
@@ -1147,16 +1342,21 @@ class FunctionValue extends VoidValue {
|
|
|
1147
1342
|
}
|
|
1148
1343
|
inlineReturn(scope, arg) {
|
|
1149
1344
|
const argInst = arg ? this.inlineTemp.value["="](scope, arg)[1] : [];
|
|
1150
|
-
|
|
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]];
|
|
1151
1351
|
}
|
|
1152
1352
|
inlineCall(scope, args) {
|
|
1153
1353
|
// create return value
|
|
1154
1354
|
this.inlineTemp = new ValueOwner({
|
|
1155
1355
|
scope: this.childScope,
|
|
1156
|
-
value: new SenseableValue(scope),
|
|
1356
|
+
value: assign(new SenseableValue(scope), {
|
|
1357
|
+
mutability: EMutability.mutable,
|
|
1358
|
+
}),
|
|
1157
1359
|
});
|
|
1158
|
-
this.inlineTemp.value.constant = false;
|
|
1159
|
-
this.inlineEnd = new LiteralValue(scope, null);
|
|
1160
1360
|
// make a copy of the function scope
|
|
1161
1361
|
const fnScope = this.childScope.copy();
|
|
1162
1362
|
// hard set variables within the function scope
|
|
@@ -1171,16 +1371,13 @@ class FunctionValue extends VoidValue {
|
|
|
1171
1371
|
name: owner.name,
|
|
1172
1372
|
}));
|
|
1173
1373
|
});
|
|
1374
|
+
this.inlineEnd = new LiteralValue(scope, null);
|
|
1174
1375
|
this.tryingInline = true;
|
|
1175
|
-
|
|
1376
|
+
let inst = this.c.handle(fnScope, this.body)[1];
|
|
1176
1377
|
this.tryingInline = false;
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
// if (jump instanceof JumpInstruction) {
|
|
1181
|
-
// // remove useless jump
|
|
1182
|
-
// if (jump.args[1] === this.inlineEnd) inst.pop();
|
|
1183
|
-
// }
|
|
1378
|
+
const returnIndex = inst.findIndex(i => i.alwaysRuns && i.intent === EInstIntent.return);
|
|
1379
|
+
if (returnIndex !== -1)
|
|
1380
|
+
inst = inst.slice(0, returnIndex + 1);
|
|
1184
1381
|
inst.push(new AddressResolver(this.inlineEnd));
|
|
1185
1382
|
// return the function value
|
|
1186
1383
|
return [this.inlineTemp.value, inst];
|
|
@@ -1225,7 +1422,11 @@ function endsWithReturn(inst) {
|
|
|
1225
1422
|
function handleFunctionNode(c, scope, node) {
|
|
1226
1423
|
let { params, body } = node;
|
|
1227
1424
|
if (es__namespace.isExpression(body)) {
|
|
1228
|
-
|
|
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;
|
|
1229
1430
|
}
|
|
1230
1431
|
return [
|
|
1231
1432
|
new FunctionValue({
|
|
@@ -1271,16 +1472,32 @@ const CallExpression = (c, scope, node) => {
|
|
|
1271
1472
|
inst.push(...callInst);
|
|
1272
1473
|
return [callValue, inst];
|
|
1273
1474
|
};
|
|
1274
|
-
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
|
+
};
|
|
1275
1492
|
|
|
1276
1493
|
const ObjectExpression = (c, scope, node) => {
|
|
1277
1494
|
const data = {};
|
|
1278
1495
|
const inst = [];
|
|
1279
1496
|
for (const prop of node.properties) {
|
|
1280
1497
|
if (prop.type === "SpreadElement")
|
|
1281
|
-
throw new CompilerError("Cannot handle spread element",
|
|
1498
|
+
throw new CompilerError("Cannot handle spread element", prop);
|
|
1282
1499
|
if (prop.computed)
|
|
1283
|
-
throw new CompilerError("Cannot handle computed property.",
|
|
1500
|
+
throw new CompilerError("Cannot handle computed property.", prop);
|
|
1284
1501
|
const { key } = prop;
|
|
1285
1502
|
const value = prop.type === "ObjectProperty" ? prop.value : prop;
|
|
1286
1503
|
let index;
|
|
@@ -1291,17 +1508,18 @@ const ObjectExpression = (c, scope, node) => {
|
|
|
1291
1508
|
index = `${key.value}`;
|
|
1292
1509
|
}
|
|
1293
1510
|
else {
|
|
1294
|
-
throw new CompilerError(`Unsupported object key type: ${key.type}`,
|
|
1295
|
-
key,
|
|
1296
|
-
]);
|
|
1511
|
+
throw new CompilerError(`Unsupported object key type: ${key.type}`, key);
|
|
1297
1512
|
}
|
|
1298
1513
|
const [member, memberInst] = c.handleEval(scope, value);
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
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;
|
|
1305
1523
|
inst.push(...memberInst);
|
|
1306
1524
|
}
|
|
1307
1525
|
return [new ObjectValue(scope, data), inst];
|
|
@@ -1335,9 +1553,7 @@ const ArrayPattern = (c, scope, node) => {
|
|
|
1335
1553
|
continue;
|
|
1336
1554
|
const valueInst = c.handle(scope, element);
|
|
1337
1555
|
if (!valueInst[0])
|
|
1338
|
-
throw new CompilerError("Destructuring element must resolve to a value",
|
|
1339
|
-
element,
|
|
1340
|
-
]);
|
|
1556
|
+
throw new CompilerError("Destructuring element must resolve to a value", element);
|
|
1341
1557
|
inst.push(...valueInst[1]);
|
|
1342
1558
|
members.set(new LiteralValue(scope, i), valueInst[0]);
|
|
1343
1559
|
}
|
|
@@ -1358,26 +1574,15 @@ const ObjectPattern = (c, scope, node) => {
|
|
|
1358
1574
|
inst.push(...keyInst[1]);
|
|
1359
1575
|
const valueInst = c.handle(scope, prop.value);
|
|
1360
1576
|
if (!valueInst[0])
|
|
1361
|
-
throw new CompilerError("Destructuring member must resolve to a value",
|
|
1362
|
-
prop.value,
|
|
1363
|
-
]);
|
|
1577
|
+
throw new CompilerError("Destructuring member must resolve to a value", prop.value);
|
|
1364
1578
|
inst.push(...valueInst[1]);
|
|
1365
1579
|
members.set(keyInst[0], valueInst[0]);
|
|
1366
1580
|
}
|
|
1367
1581
|
return [new DestructuringValue(scope, members), inst];
|
|
1368
1582
|
};
|
|
1369
1583
|
|
|
1370
|
-
const TemplateLiteral = (
|
|
1371
|
-
|
|
1372
|
-
const inst = [];
|
|
1373
|
-
node.expressions.forEach((expression, i) => {
|
|
1374
|
-
const [v, vi] = c.handleConsume(scope, expression);
|
|
1375
|
-
inst.push(...vi);
|
|
1376
|
-
args.push(node.quasis[i].value.raw, v);
|
|
1377
|
-
});
|
|
1378
|
-
args.push(node.quasis.slice(-1)[0].value.raw);
|
|
1379
|
-
inst.push(new ZeroSpaceInstruction(...args));
|
|
1380
|
-
return [null, inst];
|
|
1584
|
+
const TemplateLiteral = () => {
|
|
1585
|
+
throw new CompilerError("Template strings are currently unavailable. To inline mlog code use the asm function.");
|
|
1381
1586
|
};
|
|
1382
1587
|
|
|
1383
1588
|
const BlockStatement = (c, scope, node) => {
|
|
@@ -1410,14 +1615,12 @@ const TSEnumDeclaration = (c, scope, node) => {
|
|
|
1410
1615
|
const data = {};
|
|
1411
1616
|
for (const member of node.members) {
|
|
1412
1617
|
if (lastType === "string" && !member.initializer)
|
|
1413
|
-
throw new CompilerError("This enum member must be initialized",
|
|
1618
|
+
throw new CompilerError("This enum member must be initialized", member);
|
|
1414
1619
|
const [value] = member.initializer
|
|
1415
1620
|
? c.handleEval(scope, member.initializer)
|
|
1416
1621
|
: [new LiteralValue(scope, counter)];
|
|
1417
1622
|
if (!(value instanceof LiteralValue))
|
|
1418
|
-
throw new CompilerError("Enum members must contain literal values",
|
|
1419
|
-
member,
|
|
1420
|
-
]);
|
|
1623
|
+
throw new CompilerError("Enum members must contain literal values", member);
|
|
1421
1624
|
if (typeof value.data === "number") {
|
|
1422
1625
|
lastType = "number";
|
|
1423
1626
|
counter = value.data + 1;
|
|
@@ -1463,6 +1666,7 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1463
1666
|
ContinueStatement: ContinueStatement,
|
|
1464
1667
|
ReturnStatement: ReturnStatement,
|
|
1465
1668
|
IfStatement: IfStatement,
|
|
1669
|
+
SwitchStatement: SwitchStatement,
|
|
1466
1670
|
WhileStatement: WhileStatement,
|
|
1467
1671
|
DoWhileStatement: DoWhileStatement,
|
|
1468
1672
|
ForStatement: ForStatement,
|
|
@@ -1472,6 +1676,7 @@ var handlers = /*#__PURE__*/Object.freeze({
|
|
|
1472
1676
|
ObjectMethod: ObjectMethod,
|
|
1473
1677
|
CallExpression: CallExpression,
|
|
1474
1678
|
NewExpression: NewExpression,
|
|
1679
|
+
TaggedTemplateExpression: TaggedTemplateExpression,
|
|
1475
1680
|
ObjectExpression: ObjectExpression,
|
|
1476
1681
|
ArrayExpression: ArrayExpression,
|
|
1477
1682
|
MemberExpression: MemberExpression,
|
|
@@ -1574,53 +1779,170 @@ class Concat extends MacroFunction {
|
|
|
1574
1779
|
}
|
|
1575
1780
|
}
|
|
1576
1781
|
|
|
1577
|
-
|
|
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 {
|
|
1578
1865
|
constructor(scope) {
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
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
|
+
},
|
|
1605
1907
|
});
|
|
1908
|
+
super(scope, data);
|
|
1606
1909
|
}
|
|
1607
1910
|
}
|
|
1608
1911
|
|
|
1609
1912
|
class Print extends MacroFunction {
|
|
1610
1913
|
constructor(scope) {
|
|
1611
1914
|
super(scope, (...values) => {
|
|
1915
|
+
const [first] = values;
|
|
1612
1916
|
const inst = [];
|
|
1613
|
-
|
|
1614
|
-
|
|
1917
|
+
if (!isTemplateObjectArray(first)) {
|
|
1918
|
+
for (const value of values) {
|
|
1919
|
+
inst.push(new InstructionBase("print", value));
|
|
1920
|
+
}
|
|
1921
|
+
return [null, inst];
|
|
1615
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));
|
|
1616
1935
|
return [null, inst];
|
|
1617
1936
|
});
|
|
1618
1937
|
}
|
|
1619
1938
|
}
|
|
1620
1939
|
|
|
1940
|
+
const defaultTargetName$1 = "message1";
|
|
1621
1941
|
class PrintFlush extends MacroFunction {
|
|
1622
1942
|
constructor(scope) {
|
|
1623
1943
|
super(scope, (target) => {
|
|
1944
|
+
if (!target)
|
|
1945
|
+
return [null, [new InstructionBase("printflush", defaultTargetName$1)]];
|
|
1624
1946
|
if (!(target instanceof SenseableValue))
|
|
1625
1947
|
throw new CompilerError("The printflush target must be a senseable value");
|
|
1626
1948
|
return [null, [new InstructionBase("printflush", target)]];
|
|
@@ -1628,9 +1950,12 @@ class PrintFlush extends MacroFunction {
|
|
|
1628
1950
|
}
|
|
1629
1951
|
}
|
|
1630
1952
|
|
|
1953
|
+
const defaultTargetName = "display1";
|
|
1631
1954
|
class DrawFlush extends MacroFunction {
|
|
1632
1955
|
constructor(scope) {
|
|
1633
1956
|
super(scope, (target) => {
|
|
1957
|
+
if (!target)
|
|
1958
|
+
return [null, [new InstructionBase("drawflush", defaultTargetName)]];
|
|
1634
1959
|
if (!(target instanceof SenseableValue))
|
|
1635
1960
|
throw new CompilerError("The drawflush target must be a senseable value");
|
|
1636
1961
|
return [null, [new InstructionBase("drawflush", target)]];
|
|
@@ -1638,6 +1963,30 @@ class DrawFlush extends MacroFunction {
|
|
|
1638
1963
|
}
|
|
1639
1964
|
}
|
|
1640
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
|
+
|
|
1641
1990
|
class GetLink extends MacroFunction {
|
|
1642
1991
|
constructor(scope) {
|
|
1643
1992
|
super(scope, (index) => {
|
|
@@ -1650,21 +1999,27 @@ class GetLink extends MacroFunction {
|
|
|
1650
1999
|
}
|
|
1651
2000
|
}
|
|
1652
2001
|
|
|
1653
|
-
|
|
1654
|
-
class Control extends MacroFunction {
|
|
2002
|
+
class Control extends ObjectValue {
|
|
1655
2003
|
constructor(scope) {
|
|
1656
|
-
super(scope, (
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
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
|
+
}));
|
|
1668
2023
|
}
|
|
1669
2024
|
}
|
|
1670
2025
|
|
|
@@ -1687,28 +2042,25 @@ const validRadarSorts = [
|
|
|
1687
2042
|
];
|
|
1688
2043
|
class Radar extends MacroFunction {
|
|
1689
2044
|
constructor(scope) {
|
|
1690
|
-
super(scope,
|
|
2045
|
+
super(scope, options => {
|
|
2046
|
+
assertIsObjectMacro(options, "The radar options");
|
|
2047
|
+
const { building, filters, order, sort } = options.data;
|
|
1691
2048
|
if (!(building instanceof SenseableValue))
|
|
1692
2049
|
throw new CompilerError("The building must a senseable value");
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
if (!validRadarFilters.includes(filter3.data))
|
|
1705
|
-
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");
|
|
1706
2061
|
if (!(order instanceof LiteralValue || order instanceof StoreValue))
|
|
1707
2062
|
throw new CompilerError("The radar order must be a literal or a store");
|
|
1708
|
-
|
|
1709
|
-
throw new CompilerError("The radar sort must be a string literal");
|
|
1710
|
-
if (!validRadarSorts.includes(sort.data))
|
|
1711
|
-
throw new CompilerError("Invalid sort value");
|
|
2063
|
+
assertLiteralOneOf(sort, validRadarSorts, "The radar sort");
|
|
1712
2064
|
const outUnit = new SenseableValue(scope);
|
|
1713
2065
|
return [
|
|
1714
2066
|
outUnit,
|
|
@@ -1727,7 +2079,9 @@ class Sensor extends MacroFunction {
|
|
|
1727
2079
|
throw new CompilerError("The sensor property must be a store");
|
|
1728
2080
|
if (!(target instanceof SenseableValue))
|
|
1729
2081
|
throw new CompilerError("The sensor target must be a senseable value");
|
|
1730
|
-
const temp = new
|
|
2082
|
+
const temp = assign(new SenseableValue(scope), {
|
|
2083
|
+
mutability: EMutability.readonly,
|
|
2084
|
+
});
|
|
1731
2085
|
return [temp, [new InstructionBase("sensor", temp, target, property)]];
|
|
1732
2086
|
});
|
|
1733
2087
|
}
|
|
@@ -1744,19 +2098,40 @@ class Wait extends MacroFunction {
|
|
|
1744
2098
|
}
|
|
1745
2099
|
}
|
|
1746
2100
|
|
|
1747
|
-
|
|
1748
|
-
class Lookup extends MacroFunction {
|
|
2101
|
+
class Lookup extends ObjectValue {
|
|
1749
2102
|
constructor(scope) {
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
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)]];
|
|
1760
2135
|
});
|
|
1761
2136
|
}
|
|
1762
2137
|
}
|
|
@@ -1767,6 +2142,57 @@ class End extends MacroFunction {
|
|
|
1767
2142
|
}
|
|
1768
2143
|
}
|
|
1769
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
|
+
|
|
1770
2196
|
class UnitBind extends MacroFunction {
|
|
1771
2197
|
constructor(scope) {
|
|
1772
2198
|
super(scope, type => {
|
|
@@ -1777,82 +2203,85 @@ class UnitBind extends MacroFunction {
|
|
|
1777
2203
|
}
|
|
1778
2204
|
}
|
|
1779
2205
|
|
|
1780
|
-
|
|
1781
|
-
"idle",
|
|
1782
|
-
"stop",
|
|
1783
|
-
"move",
|
|
1784
|
-
"approach",
|
|
1785
|
-
"boost",
|
|
1786
|
-
"pathfind",
|
|
1787
|
-
"target",
|
|
1788
|
-
"targetp",
|
|
1789
|
-
"itemDrop",
|
|
1790
|
-
"itemTake",
|
|
1791
|
-
"payDrop",
|
|
1792
|
-
"payTake",
|
|
1793
|
-
"payEnter",
|
|
1794
|
-
"mine",
|
|
1795
|
-
"flag",
|
|
1796
|
-
"build",
|
|
1797
|
-
"getBlock",
|
|
1798
|
-
"within",
|
|
1799
|
-
];
|
|
1800
|
-
class UnitControl extends MacroFunction {
|
|
2206
|
+
class UnitControl extends ObjectValue {
|
|
1801
2207
|
constructor(scope) {
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
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
|
+
}
|
|
1824
2255
|
}
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
2256
|
+
return [
|
|
2257
|
+
result,
|
|
2258
|
+
[new InstructionBase("ucontrol", overload, ...args, ...extraArgs)],
|
|
2259
|
+
];
|
|
2260
|
+
},
|
|
1830
2261
|
});
|
|
2262
|
+
super(scope, data);
|
|
1831
2263
|
}
|
|
1832
2264
|
}
|
|
1833
2265
|
|
|
1834
2266
|
class UnitRadar extends MacroFunction {
|
|
1835
2267
|
constructor(scope) {
|
|
1836
|
-
super(scope,
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
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");
|
|
1850
2282
|
if (!(order instanceof LiteralValue || order instanceof StoreValue))
|
|
1851
2283
|
throw new CompilerError("The radar order must be a literal or a store");
|
|
1852
|
-
|
|
1853
|
-
throw new CompilerError("The radar sort must be a string literal");
|
|
1854
|
-
if (!validRadarSorts.includes(sort.data))
|
|
1855
|
-
throw new CompilerError("Invalid sort value");
|
|
2284
|
+
assertLiteralOneOf(sort, validRadarSorts, "The radar sort");
|
|
1856
2285
|
const outUnit = new SenseableValue(scope);
|
|
1857
2286
|
return [
|
|
1858
2287
|
outUnit,
|
|
@@ -1865,7 +2294,6 @@ class UnitRadar extends MacroFunction {
|
|
|
1865
2294
|
}
|
|
1866
2295
|
}
|
|
1867
2296
|
|
|
1868
|
-
const validFinds = ["ore", "building", "spawn", "damaged"];
|
|
1869
2297
|
const validBuildingGroups = [
|
|
1870
2298
|
"core",
|
|
1871
2299
|
"storage",
|
|
@@ -1877,56 +2305,297 @@ const validBuildingGroups = [
|
|
|
1877
2305
|
"battery",
|
|
1878
2306
|
"reactor",
|
|
1879
2307
|
];
|
|
1880
|
-
class UnitLocate extends
|
|
2308
|
+
class UnitLocate extends ObjectValue {
|
|
1881
2309
|
constructor(scope) {
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
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;
|
|
1905
2349
|
}
|
|
1906
|
-
if (!validBuildingGroups.includes(group.data))
|
|
1907
|
-
throw new CompilerError("Invalid building group");
|
|
1908
|
-
inputArgs = [find.data, group.data, enemy, "@copper"];
|
|
1909
|
-
break;
|
|
1910
|
-
}
|
|
1911
|
-
case "spawn":
|
|
1912
|
-
case "damaged": {
|
|
1913
|
-
inputArgs = [find.data, "core", "true", "@copper"];
|
|
1914
|
-
break;
|
|
1915
2350
|
}
|
|
1916
|
-
|
|
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");
|
|
1917
2414
|
return [
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
...(find.data !== "ore" ? [outBuilding] : []),
|
|
1923
|
-
]),
|
|
1924
|
-
[new InstructionBase("ulocate", ...inputArgs, ...outArgs)],
|
|
2415
|
+
null,
|
|
2416
|
+
[
|
|
2417
|
+
new InstructionBase("spawnwave", x ?? "10", y ?? "10", String(!!natural.data)),
|
|
2418
|
+
],
|
|
1925
2419
|
];
|
|
1926
2420
|
});
|
|
1927
2421
|
}
|
|
1928
2422
|
}
|
|
1929
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
|
+
|
|
1930
2599
|
class MemoryEntry extends ObjectValue {
|
|
1931
2600
|
constructor(scope, mem, prop) {
|
|
1932
2601
|
super(scope, {
|
|
@@ -1999,6 +2668,7 @@ class MemoryBuilder extends ObjectValue {
|
|
|
1999
2668
|
}
|
|
2000
2669
|
}
|
|
2001
2670
|
|
|
2671
|
+
const dynamicVars = ["time", "tick"];
|
|
2002
2672
|
class NamespaceMacro extends ObjectValue {
|
|
2003
2673
|
constructor(scope, { changeCasing = false } = {}) {
|
|
2004
2674
|
super(scope, {
|
|
@@ -2008,9 +2678,14 @@ class NamespaceMacro extends ObjectValue {
|
|
|
2008
2678
|
const symbolName = this.changeCasing
|
|
2009
2679
|
? camelToDashCase(prop.data)
|
|
2010
2680
|
: prop.data;
|
|
2681
|
+
const mutability = dynamicVars.includes(symbolName)
|
|
2682
|
+
? EMutability.readonly
|
|
2683
|
+
: EMutability.constant;
|
|
2011
2684
|
const owner = new ValueOwner({
|
|
2012
2685
|
scope,
|
|
2013
|
-
value: new StoreValue(scope),
|
|
2686
|
+
value: assign(new StoreValue(scope), {
|
|
2687
|
+
mutability,
|
|
2688
|
+
}),
|
|
2014
2689
|
name: `@${symbolName}`,
|
|
2015
2690
|
});
|
|
2016
2691
|
return [owner.value, []];
|
|
@@ -2035,39 +2710,44 @@ class VarsNamespace extends NamespaceMacro {
|
|
|
2035
2710
|
}).value,
|
|
2036
2711
|
});
|
|
2037
2712
|
}
|
|
2038
|
-
}
|
|
2039
|
-
class UCommandsNamespace extends NamespaceMacro {
|
|
2040
|
-
constructor(scope) {
|
|
2041
|
-
super(scope);
|
|
2042
|
-
this.data.$get = new MacroFunction(scope, prop => {
|
|
2043
|
-
if (!(prop instanceof LiteralValue) || typeof prop.data !== "string")
|
|
2044
|
-
throw new CompilerError("Cannot use dynamic properties on namespace macros");
|
|
2045
|
-
const symbolName = prop.data[0].toUpperCase() + prop.data.slice(1);
|
|
2046
|
-
const owner = new ValueOwner({
|
|
2047
|
-
scope,
|
|
2048
|
-
name: `@command${symbolName}`,
|
|
2049
|
-
value: new StoreValue(scope),
|
|
2050
|
-
});
|
|
2051
|
-
return [owner.value, []];
|
|
2052
|
-
});
|
|
2053
|
-
}
|
|
2054
2713
|
}
|
|
2055
2714
|
|
|
2056
2715
|
class GetGlobal extends MacroFunction {
|
|
2057
|
-
constructor(scope) {
|
|
2716
|
+
constructor(scope, mutability) {
|
|
2058
2717
|
super(scope, (name) => {
|
|
2059
2718
|
if (!(name instanceof LiteralValue) || typeof name.data !== "string")
|
|
2060
2719
|
throw new CompilerError("The name parameter must be a string literal.");
|
|
2061
2720
|
const owner = new ValueOwner({
|
|
2062
2721
|
scope,
|
|
2063
2722
|
name: name.data,
|
|
2064
|
-
value: new SenseableValue(scope),
|
|
2723
|
+
value: assign(new SenseableValue(scope), {
|
|
2724
|
+
mutability,
|
|
2725
|
+
}),
|
|
2065
2726
|
});
|
|
2066
2727
|
return [owner.value, []];
|
|
2067
2728
|
});
|
|
2068
2729
|
}
|
|
2069
2730
|
}
|
|
2070
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
|
+
|
|
2071
2751
|
/**
|
|
2072
2752
|
* Adds all the compiler globals to `scope`
|
|
2073
2753
|
*/
|
|
@@ -2075,16 +2755,17 @@ function initScope(scope) {
|
|
|
2075
2755
|
// namespaces
|
|
2076
2756
|
scope.hardSet("ControlKind", new NamespaceMacro(scope));
|
|
2077
2757
|
scope.hardSet("Vars", new VarsNamespace(scope));
|
|
2758
|
+
scope.hardSet("Teams", new NamespaceMacro(scope));
|
|
2078
2759
|
scope.hardSet("Items", new NamespaceMacro(scope, { changeCasing: true }));
|
|
2079
2760
|
scope.hardSet("Liquids", new NamespaceMacro(scope));
|
|
2080
|
-
scope.hardSet("Units", new NamespaceMacro(scope));
|
|
2761
|
+
scope.hardSet("Units", new NamespaceMacro(scope, { changeCasing: true }));
|
|
2081
2762
|
scope.hardSet("LAccess", new NamespaceMacro(scope));
|
|
2082
|
-
scope.hardSet("UnitCommands", new UCommandsNamespace(scope));
|
|
2083
2763
|
scope.hardSet("Blocks", new NamespaceMacro(scope, { changeCasing: true }));
|
|
2084
2764
|
// helper methods
|
|
2085
|
-
scope.hardSet("getBuilding", new GetGlobal(scope));
|
|
2086
|
-
scope.hardSet("getVar", new GetGlobal(scope));
|
|
2765
|
+
scope.hardSet("getBuilding", new GetGlobal(scope, EMutability.constant));
|
|
2766
|
+
scope.hardSet("getVar", new GetGlobal(scope, EMutability.mutable));
|
|
2087
2767
|
scope.hardSet("concat", new Concat(scope));
|
|
2768
|
+
scope.hardSet("asm", new Asm(scope));
|
|
2088
2769
|
scope.hardSet("Math", new MlogMath(scope));
|
|
2089
2770
|
scope.hardSet("Memory", new MemoryBuilder(scope));
|
|
2090
2771
|
// commands
|
|
@@ -2098,36 +2779,58 @@ function initScope(scope) {
|
|
|
2098
2779
|
scope.hardSet("sensor", new Sensor(scope));
|
|
2099
2780
|
scope.hardSet("wait", new Wait(scope));
|
|
2100
2781
|
scope.hardSet("lookup", new Lookup(scope));
|
|
2782
|
+
scope.hardSet("packColor", new PackColor(scope));
|
|
2101
2783
|
scope.hardSet("endScript", new End(scope));
|
|
2784
|
+
scope.hardSet("stopScript", new Stop(scope));
|
|
2102
2785
|
scope.hardSet("unitBind", new UnitBind(scope));
|
|
2103
2786
|
scope.hardSet("unitControl", new UnitControl(scope));
|
|
2104
2787
|
scope.hardSet("unitRadar", new UnitRadar(scope));
|
|
2105
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));
|
|
2106
2803
|
}
|
|
2107
2804
|
|
|
2108
2805
|
class Compiler {
|
|
2109
|
-
constructor({ stackName, compactNames = false } = {}) {
|
|
2806
|
+
constructor({ stackName, compactNames = false, sourcemap = false, } = {}) {
|
|
2110
2807
|
this.handlers = handlers;
|
|
2111
2808
|
this.usingStack = !!stackName;
|
|
2112
2809
|
this.stackName = stackName;
|
|
2113
2810
|
this.compactNames = compactNames;
|
|
2811
|
+
this.sourcemap = sourcemap;
|
|
2114
2812
|
}
|
|
2115
2813
|
compile(script) {
|
|
2116
2814
|
let output;
|
|
2815
|
+
let sourcemaps;
|
|
2117
2816
|
try {
|
|
2118
2817
|
const program = this.parse(script);
|
|
2119
2818
|
const scope = new Scope({});
|
|
2120
2819
|
initScope(scope);
|
|
2121
2820
|
const valueInst = this.handle(scope, program);
|
|
2122
2821
|
valueInst[1].push(new EndInstruction(), ...scope.inst);
|
|
2822
|
+
hideRedundantJumps(valueInst[1]);
|
|
2123
2823
|
this.resolve(valueInst);
|
|
2124
2824
|
output = this.serialize(valueInst) + "\n";
|
|
2825
|
+
if (this.sourcemap) {
|
|
2826
|
+
sourcemaps = this.mapSources(valueInst);
|
|
2827
|
+
}
|
|
2125
2828
|
}
|
|
2126
2829
|
catch (error) {
|
|
2127
|
-
const
|
|
2128
|
-
return [null,
|
|
2830
|
+
const err = error instanceof CompilerError ? error : CompilerError.from(error);
|
|
2831
|
+
return [null, err];
|
|
2129
2832
|
}
|
|
2130
|
-
return [output, null,
|
|
2833
|
+
return [output, null, sourcemaps];
|
|
2131
2834
|
}
|
|
2132
2835
|
resolve(valueInst) {
|
|
2133
2836
|
let i = 0;
|
|
@@ -2147,40 +2850,92 @@ class Compiler {
|
|
|
2147
2850
|
plugins: ["typescript"],
|
|
2148
2851
|
});
|
|
2149
2852
|
}
|
|
2150
|
-
|
|
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]) {
|
|
2151
2862
|
try {
|
|
2152
|
-
const handler = this.handlers[node.type];
|
|
2153
2863
|
if (!handler)
|
|
2154
2864
|
throw new CompilerError("Missing handler for " + node.type);
|
|
2155
|
-
|
|
2865
|
+
const result = handler(this, scope, node, null);
|
|
2866
|
+
if (this.sourcemap)
|
|
2867
|
+
return appendSourceLocations(result, node);
|
|
2868
|
+
return result;
|
|
2156
2869
|
}
|
|
2157
2870
|
catch (error) {
|
|
2158
2871
|
if (error instanceof CompilerError) {
|
|
2159
|
-
error.
|
|
2872
|
+
error.loc ??= node.loc;
|
|
2160
2873
|
}
|
|
2161
2874
|
throw error;
|
|
2162
2875
|
}
|
|
2163
2876
|
}
|
|
2164
2877
|
handleEval(scope, node) {
|
|
2165
2878
|
const [res, inst] = this.handle(scope, node);
|
|
2166
|
-
|
|
2879
|
+
if (!res)
|
|
2880
|
+
throw new CompilerError("Cannot eval null", node);
|
|
2167
2881
|
const [evaluated, evaluatedInst] = res.eval(scope);
|
|
2168
|
-
|
|
2882
|
+
const result = [evaluated, [...inst, ...evaluatedInst]];
|
|
2883
|
+
if (this.sourcemap)
|
|
2884
|
+
return appendSourceLocations(result, node);
|
|
2885
|
+
return result;
|
|
2169
2886
|
}
|
|
2170
2887
|
handleConsume(scope, node) {
|
|
2171
2888
|
const [res, inst] = this.handle(scope, node);
|
|
2172
|
-
|
|
2889
|
+
if (!res)
|
|
2890
|
+
throw new CompilerError("Cannot consume null", node);
|
|
2173
2891
|
const [evaluated, evaluatedInst] = res.consume(scope);
|
|
2174
|
-
|
|
2892
|
+
const result = [evaluated, [...inst, ...evaluatedInst]];
|
|
2893
|
+
if (this.sourcemap)
|
|
2894
|
+
return appendSourceLocations(result, node);
|
|
2895
|
+
return result;
|
|
2175
2896
|
}
|
|
2176
|
-
|
|
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) {
|
|
2177
2908
|
const lines = [];
|
|
2178
2909
|
for (const node of nodes) {
|
|
2179
|
-
const [, nodeLines] =
|
|
2910
|
+
const [, nodeLines] = this.handle(scope, node, handler && (() => handler(node)));
|
|
2180
2911
|
lines.push(...nodeLines);
|
|
2181
2912
|
}
|
|
2182
2913
|
return [null, lines];
|
|
2183
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
|
+
}
|
|
2184
2939
|
}
|
|
2185
2940
|
|
|
2186
2941
|
exports.Compiler = Compiler;
|