mlogjs 0.2.1 → 0.3.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.
Files changed (234) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -2
  3. package/build/Compiler.js +104 -99
  4. package/build/Compiler.js.map +1 -1
  5. package/build/CompilerError.js +11 -0
  6. package/build/CompilerError.js.map +1 -0
  7. package/build/Scope.js +70 -60
  8. package/build/Scope.js.map +1 -1
  9. package/build/bin.js +74 -60
  10. package/build/bin.js.map +1 -1
  11. package/build/handlers/BlockStatement.js +13 -13
  12. package/build/handlers/BlockStatement.js.map +1 -1
  13. package/build/handlers/CallExpression.js +19 -19
  14. package/build/handlers/CallExpression.js.map +1 -1
  15. package/build/handlers/File.js +9 -0
  16. package/build/handlers/File.js.map +1 -0
  17. package/build/handlers/ForStatement.js +31 -31
  18. package/build/handlers/ForStatement.js.map +1 -1
  19. package/build/handlers/Function.js +46 -35
  20. package/build/handlers/Function.js.map +1 -1
  21. package/build/handlers/Identifier.js +7 -7
  22. package/build/handlers/IfStatement.js +24 -24
  23. package/build/handlers/IfStatement.js.map +1 -1
  24. package/build/handlers/Literal.js +14 -17
  25. package/build/handlers/Literal.js.map +1 -1
  26. package/build/handlers/Object.js +54 -43
  27. package/build/handlers/Object.js.map +1 -1
  28. package/build/handlers/OperationExpressions.js +37 -32
  29. package/build/handlers/OperationExpressions.js.map +1 -1
  30. package/build/handlers/Program.js +8 -8
  31. package/build/handlers/Program.js.map +1 -1
  32. package/build/handlers/Statements.js +29 -29
  33. package/build/handlers/Statements.js.map +1 -1
  34. package/build/handlers/TemplateExpression.js +17 -17
  35. package/build/handlers/TemplateExpression.js.map +1 -1
  36. package/build/handlers/VariableDeclaration.js +71 -55
  37. package/build/handlers/VariableDeclaration.js.map +1 -1
  38. package/build/handlers/WhileStatement.js +22 -22
  39. package/build/handlers/WhileStatement.js.map +1 -1
  40. package/build/handlers/index.js +31 -30
  41. package/build/handlers/index.js.map +1 -1
  42. package/build/index.js +7 -7
  43. package/build/index.js.map +1 -1
  44. package/build/initScope.js +39 -39
  45. package/build/instructions/AddressResolver.js +30 -30
  46. package/build/instructions/ControlInstructions.js +22 -22
  47. package/build/instructions/EndInstruction.js +10 -10
  48. package/build/instructions/InstructionBase.js +20 -20
  49. package/build/instructions/InstructionBase.js.map +1 -1
  50. package/build/instructions/JumpInstruction.js +21 -21
  51. package/build/instructions/JumpInstruction.js.map +1 -1
  52. package/build/instructions/OperationInstruction.js +10 -10
  53. package/build/instructions/OperationInstruction.js.map +1 -1
  54. package/build/instructions/SetCounterInstruction.js +10 -10
  55. package/build/instructions/SetInstruction.js +10 -10
  56. package/build/instructions/ZeroSpaceInstruction.js +10 -10
  57. package/build/instructions/index.js +25 -25
  58. package/build/macros/Building.js +88 -80
  59. package/build/macros/Building.js.map +1 -1
  60. package/build/macros/Function.js +19 -19
  61. package/build/macros/Function.js.map +1 -1
  62. package/build/macros/Math.js +61 -56
  63. package/build/macros/Math.js.map +1 -1
  64. package/build/macros/Memory.js +62 -60
  65. package/build/macros/Memory.js.map +1 -1
  66. package/build/macros/Namespace.js +110 -97
  67. package/build/macros/Namespace.js.map +1 -1
  68. package/build/macros/Other.js +20 -19
  69. package/build/macros/Other.js.map +1 -1
  70. package/build/macros/RawValue.js +16 -15
  71. package/build/macros/RawValue.js.map +1 -1
  72. package/build/macros/commands/Control.js +25 -24
  73. package/build/macros/commands/Control.js.map +1 -1
  74. package/build/macros/commands/Draw.js +39 -38
  75. package/build/macros/commands/Draw.js.map +1 -1
  76. package/build/macros/commands/DrawFlush.js +17 -16
  77. package/build/macros/commands/DrawFlush.js.map +1 -1
  78. package/build/macros/commands/GetLink.js +24 -20
  79. package/build/macros/commands/GetLink.js.map +1 -1
  80. package/build/macros/commands/Lookup.js +24 -23
  81. package/build/macros/commands/Lookup.js.map +1 -1
  82. package/build/macros/commands/Print.js +17 -13
  83. package/build/macros/commands/Print.js.map +1 -1
  84. package/build/macros/commands/PrintFlush.js +17 -16
  85. package/build/macros/commands/PrintFlush.js.map +1 -1
  86. package/build/macros/commands/Radar.js +64 -60
  87. package/build/macros/commands/Radar.js.map +1 -1
  88. package/build/macros/commands/Sensor.js +20 -19
  89. package/build/macros/commands/Sensor.js.map +1 -1
  90. package/build/macros/commands/UnitBind.js +17 -16
  91. package/build/macros/commands/UnitBind.js.map +1 -1
  92. package/build/macros/commands/UnitControl.js +72 -67
  93. package/build/macros/commands/UnitControl.js.map +1 -1
  94. package/build/macros/commands/UnitLocate.js +75 -54
  95. package/build/macros/commands/UnitLocate.js.map +1 -1
  96. package/build/macros/commands/UnitRadar.js +47 -40
  97. package/build/macros/commands/UnitRadar.js.map +1 -1
  98. package/build/macros/commands/Wait.js +18 -17
  99. package/build/macros/commands/Wait.js.map +1 -1
  100. package/build/macros/commands/index.js +32 -32
  101. package/build/macros/index.js +39 -39
  102. package/build/operators.js +101 -101
  103. package/build/operators.js.map +1 -1
  104. package/build/types.js +27 -27
  105. package/build/types.js.map +1 -1
  106. package/build/utils.js +17 -12
  107. package/build/utils.js.map +1 -1
  108. package/build/values/BaseValue.js +111 -111
  109. package/build/values/BaseValue.js.map +1 -1
  110. package/build/values/FunctionValue.js +115 -103
  111. package/build/values/FunctionValue.js.map +1 -1
  112. package/build/values/LiteralValue.js +88 -87
  113. package/build/values/LiteralValue.js.map +1 -1
  114. package/build/values/ObjectValue.js +54 -49
  115. package/build/values/ObjectValue.js.map +1 -1
  116. package/build/values/StoreValue.js +31 -30
  117. package/build/values/StoreValue.js.map +1 -1
  118. package/build/values/TempValue.js +77 -66
  119. package/build/values/TempValue.js.map +1 -1
  120. package/build/values/VoidValue.js +31 -30
  121. package/build/values/VoidValue.js.map +1 -1
  122. package/build/values/index.js +22 -22
  123. package/dist/bin.cjs +82 -0
  124. package/dist/bin.cjs.map +1 -0
  125. package/dist/index.cjs +2220 -0
  126. package/dist/index.cjs.map +1 -0
  127. package/dist/index.mjs +2195 -0
  128. package/dist/index.mjs.map +1 -0
  129. package/dist/types/Compiler.d.ts +26 -0
  130. package/dist/types/CompilerError.d.ts +9 -0
  131. package/dist/types/Scope.d.ts +24 -0
  132. package/dist/types/bin.d.ts +1 -0
  133. package/dist/types/handlers/BlockStatement.d.ts +2 -0
  134. package/dist/types/handlers/CallExpression.d.ts +3 -0
  135. package/dist/types/handlers/File.d.ts +2 -0
  136. package/dist/types/handlers/ForStatement.d.ts +2 -0
  137. package/{build → dist/types}/handlers/Function.d.ts +5 -4
  138. package/{build → dist/types}/handlers/Identifier.d.ts +2 -2
  139. package/dist/types/handlers/IfStatement.d.ts +2 -0
  140. package/dist/types/handlers/Literal.d.ts +5 -0
  141. package/{build → dist/types}/handlers/Object.d.ts +6 -4
  142. package/{build → dist/types}/handlers/OperationExpressions.d.ts +8 -7
  143. package/dist/types/handlers/Program.d.ts +2 -0
  144. package/dist/types/handlers/Statements.d.ts +5 -0
  145. package/dist/types/handlers/TemplateExpression.d.ts +2 -0
  146. package/dist/types/handlers/Typescript.d.ts +7 -0
  147. package/dist/types/handlers/VariableDeclaration.d.ts +3 -0
  148. package/dist/types/handlers/WhileStatement.d.ts +3 -0
  149. package/{build → dist/types}/handlers/index.d.ts +16 -14
  150. package/dist/types/index.d.ts +2 -0
  151. package/{build → dist/types}/initScope.d.ts +5 -2
  152. package/{build → dist/types}/instructions/AddressResolver.d.ts +12 -12
  153. package/{build → dist/types}/instructions/ControlInstructions.d.ts +8 -11
  154. package/{build → dist/types}/instructions/EndInstruction.d.ts +4 -4
  155. package/{build → dist/types}/instructions/InstructionBase.d.ts +10 -10
  156. package/{build → dist/types}/instructions/JumpInstruction.d.ts +15 -15
  157. package/{build → dist/types}/instructions/OperationInstruction.d.ts +5 -5
  158. package/{build → dist/types}/instructions/SetCounterInstruction.d.ts +5 -5
  159. package/{build → dist/types}/instructions/SetInstruction.d.ts +6 -5
  160. package/{build → dist/types}/instructions/ZeroSpaceInstruction.d.ts +4 -4
  161. package/{build → dist/types}/instructions/index.d.ts +9 -9
  162. package/{build → dist/types}/macros/Building.d.ts +10 -11
  163. package/dist/types/macros/Entities.d.ts +11 -0
  164. package/dist/types/macros/Function.d.ts +13 -0
  165. package/dist/types/macros/GetGlobal.d.ts +5 -0
  166. package/{build → dist/types}/macros/Math.d.ts +5 -5
  167. package/{build → dist/types}/macros/Memory.d.ts +5 -5
  168. package/{build → dist/types}/macros/Namespace.d.ts +16 -21
  169. package/{build → dist/types}/macros/Other.d.ts +5 -5
  170. package/{build → dist/types}/macros/RawValue.d.ts +5 -5
  171. package/{build → dist/types}/macros/commands/Control.d.ts +5 -5
  172. package/dist/types/macros/commands/Draw.d.ts +5 -0
  173. package/{build → dist/types}/macros/commands/DrawFlush.d.ts +5 -5
  174. package/{build/macros/commands/Draw.d.ts → dist/types/macros/commands/End.d.ts} +5 -5
  175. package/{build → dist/types}/macros/commands/GetLink.d.ts +5 -5
  176. package/{build → dist/types}/macros/commands/Lookup.d.ts +5 -5
  177. package/{build → dist/types}/macros/commands/Print.d.ts +5 -5
  178. package/{build → dist/types}/macros/commands/PrintFlush.d.ts +5 -5
  179. package/{build → dist/types}/macros/commands/Radar.d.ts +7 -7
  180. package/{build → dist/types}/macros/commands/Sensor.d.ts +5 -5
  181. package/{build → dist/types}/macros/commands/UnitBind.d.ts +5 -5
  182. package/dist/types/macros/commands/UnitControl.d.ts +5 -0
  183. package/{build → dist/types}/macros/commands/UnitLocate.d.ts +5 -5
  184. package/{build → dist/types}/macros/commands/UnitRadar.d.ts +5 -5
  185. package/{build → dist/types}/macros/commands/Wait.d.ts +5 -5
  186. package/{build → dist/types}/macros/commands/index.d.ts +15 -14
  187. package/{build → dist/types}/macros/index.d.ts +6 -7
  188. package/{build → dist/types}/operators.d.ts +25 -25
  189. package/dist/types/types.d.ts +224 -0
  190. package/dist/types/utils.d.ts +30 -0
  191. package/dist/types/values/BaseValue.d.ts +7 -0
  192. package/dist/types/values/DestructuringValue.d.ts +17 -0
  193. package/dist/types/values/FunctionValue.d.ts +47 -0
  194. package/{build → dist/types}/values/LiteralValue.d.ts +13 -12
  195. package/dist/types/values/ObjectValue.d.ts +23 -0
  196. package/dist/types/values/SenseableValue.d.ts +23 -0
  197. package/dist/types/values/StackValue.d.ts +16 -0
  198. package/dist/types/values/StoreValue.d.ts +15 -0
  199. package/{build → dist/types}/values/TempValue.d.ts +19 -12
  200. package/dist/types/values/ValueOwner.d.ts +27 -0
  201. package/dist/types/values/VoidValue.d.ts +16 -0
  202. package/{build → dist/types}/values/index.d.ts +7 -6
  203. package/lib/commands.d.ts +242 -36
  204. package/lib/eslib/lib.es5.d.ts +1 -1
  205. package/lib/globals.d.ts +172 -159
  206. package/lib/helpers.d.ts +2 -2
  207. package/lib/memory.d.ts +1 -1
  208. package/lib/traits.d.ts +130 -110
  209. package/package.json +33 -38
  210. package/build/Compiler.d.ts +0 -18
  211. package/build/Scope.d.ts +0 -26
  212. package/build/bin.d.ts +0 -2
  213. package/build/handlers/BlockStatement.d.ts +0 -2
  214. package/build/handlers/CallExpression.d.ts +0 -3
  215. package/build/handlers/ForStatement.d.ts +0 -2
  216. package/build/handlers/IfStatement.d.ts +0 -2
  217. package/build/handlers/Literal.d.ts +0 -2
  218. package/build/handlers/Program.d.ts +0 -2
  219. package/build/handlers/Statements.d.ts +0 -5
  220. package/build/handlers/TemplateExpression.d.ts +0 -2
  221. package/build/handlers/VariableDeclaration.d.ts +0 -3
  222. package/build/handlers/WhileStatement.d.ts +0 -2
  223. package/build/index.d.ts +0 -1
  224. package/build/macros/Function.d.ts +0 -12
  225. package/build/macros/commands/UnitControl.d.ts +0 -5
  226. package/build/types.d.ts +0 -49
  227. package/build/utils.d.ts +0 -3
  228. package/build/values/BaseValue.d.ts +0 -5
  229. package/build/values/FunctionValue.d.ts +0 -34
  230. package/build/values/ObjectValue.d.ts +0 -17
  231. package/build/values/StoreValue.d.ts +0 -11
  232. package/build/values/VoidValue.d.ts +0 -11
  233. package/dist/mlogjs.es.js +0 -6366
  234. package/dist/mlogjs.umd.js +0 -8
package/dist/index.mjs ADDED
@@ -0,0 +1,2195 @@
1
+ import { parse } from '@babel/parser';
2
+ import * as es from '@babel/types';
3
+
4
+ class CompilerError extends Error {
5
+ constructor(message, nodeStack = []) {
6
+ super(message);
7
+ this.nodeStack = nodeStack;
8
+ }
9
+ }
10
+
11
+ /** Defines the possible types of mutability of a value */
12
+ var EMutability;
13
+ (function (EMutability) {
14
+ /**
15
+ * The value can be changed by the user's code,
16
+ * by the mlog runtime, or us
17
+ */
18
+ EMutability[EMutability["mutable"] = 0] = "mutable";
19
+ /**
20
+ * The value cannot be directly assigned,
21
+ * but it's still not safe from mutations coming from the runtime.
22
+ */
23
+ EMutability[EMutability["readonly"] = 1] = "readonly";
24
+ /** Constant values, won't change during execution */
25
+ EMutability[EMutability["constant"] = 2] = "constant";
26
+ })(EMutability || (EMutability = {}));
27
+
28
+ const arithmeticBinaryOperators = [
29
+ "*",
30
+ "**",
31
+ "+",
32
+ "-",
33
+ "/",
34
+ "%",
35
+ ];
36
+ const comparisonBinaryOperators = [
37
+ "!=",
38
+ "!==",
39
+ "<",
40
+ "<=",
41
+ "==",
42
+ "===",
43
+ ">",
44
+ ">=",
45
+ ];
46
+ const bitwiseBinaryOperators = [
47
+ "&",
48
+ "<<",
49
+ ">>",
50
+ ">>>",
51
+ "^",
52
+ "|",
53
+ ];
54
+ const binaryOperators = [
55
+ ...arithmeticBinaryOperators,
56
+ ...comparisonBinaryOperators,
57
+ ...bitwiseBinaryOperators,
58
+ "instanceof",
59
+ "in",
60
+ ];
61
+ const logicalOperators = ["&&", "??", "||"];
62
+ const arithmeticAssignmentOperators = [
63
+ "%=",
64
+ "&=",
65
+ "*=",
66
+ "**=",
67
+ "+=",
68
+ "-=",
69
+ "/=",
70
+ ];
71
+ const logicalAssignmentOperators = ["&&=", "||="];
72
+ const bitwiseAssignmentOperators = [
73
+ "<<=",
74
+ ">>=",
75
+ ">>>=",
76
+ "^=",
77
+ "|=",
78
+ ];
79
+ const assignmentOperators = [
80
+ ...arithmeticAssignmentOperators,
81
+ ...logicalAssignmentOperators,
82
+ ...bitwiseAssignmentOperators,
83
+ "=",
84
+ ];
85
+ const leftRightOperators = [
86
+ ...binaryOperators,
87
+ ...logicalOperators,
88
+ ...assignmentOperators,
89
+ ];
90
+ const unaryOperators = [
91
+ "!",
92
+ "u+",
93
+ "u-",
94
+ "delete",
95
+ "typeof",
96
+ "void",
97
+ "~",
98
+ ];
99
+ const updateOperators = ["++", "--"];
100
+ const singleOperators = [...unaryOperators, ...updateOperators];
101
+ const operators = [...leftRightOperators, ...singleOperators];
102
+
103
+ class VoidValue {
104
+ constructor(scope) {
105
+ this.owner = null;
106
+ this.mutability = EMutability.mutable;
107
+ this.macro = false;
108
+ this.scope = scope;
109
+ }
110
+ eval(_scope) {
111
+ throw new CompilerError(`${this} cannot eval.`);
112
+ }
113
+ consume(_scope) {
114
+ throw new CompilerError(`${this} cannot be consumed.`);
115
+ }
116
+ call(_scope, _args) {
117
+ throw new CompilerError(`${this} cannot call.`);
118
+ }
119
+ get(_scope, _name) {
120
+ throw new CompilerError(`${this} cannot get.`);
121
+ }
122
+ ensureOwned() {
123
+ throw new CompilerError(`${this} cannot be owned`);
124
+ }
125
+ toString() {
126
+ return "void";
127
+ }
128
+ }
129
+ for (const key of operators) {
130
+ VoidValue.prototype[key] = function () {
131
+ console.log(this);
132
+ throw new CompilerError(`${this} cannot '${key}' operation.`);
133
+ };
134
+ }
135
+
136
+ class InstructionBase {
137
+ constructor(...args) {
138
+ this._hidden = false;
139
+ this.args = args;
140
+ }
141
+ get hidden() {
142
+ return this._hidden;
143
+ }
144
+ set hidden(value) {
145
+ this._hidden = value;
146
+ }
147
+ resolve(_i) { }
148
+ toString() {
149
+ return this.args.filter(arg => arg).join(" ");
150
+ }
151
+ }
152
+
153
+ class OperationInstruction extends InstructionBase {
154
+ constructor(kind, temp, left, right) {
155
+ super("op", kind, temp, left, right);
156
+ }
157
+ }
158
+
159
+ class SetInstruction extends InstructionBase {
160
+ constructor(store, value) {
161
+ super("set", store, value);
162
+ }
163
+ get hidden() {
164
+ return this._hidden || !this.args[1].owner;
165
+ }
166
+ }
167
+
168
+ class EndInstruction extends InstructionBase {
169
+ constructor() {
170
+ super("end");
171
+ }
172
+ }
173
+
174
+ class AddressResolver extends InstructionBase {
175
+ constructor(...bonds) {
176
+ super();
177
+ this.bonds = bonds;
178
+ }
179
+ get hidden() {
180
+ return true;
181
+ }
182
+ set hidden(value) { }
183
+ resolve(i) {
184
+ for (const literal of this.bonds)
185
+ literal.data = i;
186
+ }
187
+ bind(bond) {
188
+ this.bonds.push(bond);
189
+ }
190
+ bindBreak(scope) {
191
+ scope.break = this;
192
+ return this;
193
+ }
194
+ bindContinue(scope) {
195
+ scope.continue = this;
196
+ return this;
197
+ }
198
+ }
199
+
200
+ var EJumpKind;
201
+ (function (EJumpKind) {
202
+ EJumpKind["Equal"] = "equal";
203
+ EJumpKind["NotEqual"] = "notEqual";
204
+ EJumpKind["LessThan"] = "lessThan";
205
+ EJumpKind["LessThanEq"] = "lessThanEq";
206
+ EJumpKind["GreaterThan"] = "greaterThan";
207
+ EJumpKind["GreaterThanEq"] = "greaterThanEq";
208
+ EJumpKind["StrictEqual"] = "strictEqual";
209
+ EJumpKind["Always"] = "always";
210
+ })(EJumpKind || (EJumpKind = {}));
211
+ class JumpInstruction extends InstructionBase {
212
+ constructor(address, kind, left = null, right = null) {
213
+ super("jump", address, kind, left, right);
214
+ }
215
+ }
216
+
217
+ class SetCounterInstruction extends InstructionBase {
218
+ constructor(value) {
219
+ super("set", "@counter", value);
220
+ }
221
+ }
222
+
223
+ class ZeroSpaceInstruction extends InstructionBase {
224
+ toString() {
225
+ return this.args.join("");
226
+ }
227
+ }
228
+
229
+ class BreakInstruction extends JumpInstruction {
230
+ constructor(address) {
231
+ super(address, EJumpKind.Always);
232
+ }
233
+ }
234
+ class ContinueInstruction extends JumpInstruction {
235
+ constructor(address) {
236
+ super(address, EJumpKind.Always);
237
+ }
238
+ }
239
+
240
+ class ValueOwner {
241
+ /**
242
+ * Creates a new `ValueOwner`, if `value` is already owned,
243
+ * `this` will be aliased to `value`, else `this` will own `value`
244
+ */
245
+ constructor({ scope, constant = false, value, identifier, name, }) {
246
+ this.scope = scope;
247
+ this.constant = constant;
248
+ this.value = value;
249
+ this.identifier = identifier;
250
+ this.name = name ?? scope.makeTempName();
251
+ this.persistent = !!name;
252
+ this.owned = new Set();
253
+ if (!value.owner?.persistent)
254
+ this.own(value);
255
+ }
256
+ own(target) {
257
+ target.owner = this;
258
+ this.owned.add(target);
259
+ }
260
+ replace(target) {
261
+ this.value.owner = null;
262
+ this.owned.delete(this.value);
263
+ this.value = target;
264
+ this.own(target);
265
+ }
266
+ moveInto(owner) {
267
+ this.owned.forEach(value => owner.own(value));
268
+ this.owned.clear();
269
+ }
270
+ }
271
+
272
+ class BaseValue extends VoidValue {
273
+ "u-"(scope) {
274
+ const [that, inst] = this.consume(scope);
275
+ const temp = new StoreValue(scope);
276
+ return [
277
+ temp,
278
+ [
279
+ ...inst,
280
+ new OperationInstruction("sub", temp, new LiteralValue(scope, 0), that),
281
+ ],
282
+ ];
283
+ }
284
+ "u+"(scope) {
285
+ // TODO: should it return 0 + this ?
286
+ return this.eval(scope);
287
+ }
288
+ ensureOwned() {
289
+ this.owner ??= new ValueOwner({ scope: this.scope, value: this });
290
+ }
291
+ }
292
+ const operatorMap$1 = {
293
+ "==": "equal",
294
+ "===": "strictEqual",
295
+ "!=": "notEqual",
296
+ "!==": "notEqual",
297
+ "<": "lessThan",
298
+ ">": "greaterThan",
299
+ "<=": "lessThanEq",
300
+ ">=": "greaterThanEq",
301
+ "+": "add",
302
+ "-": "sub",
303
+ "*": "mul",
304
+ "/": "div",
305
+ "%": "mod",
306
+ "**": "pow",
307
+ "|": "or",
308
+ "&": "and",
309
+ "^": "xor",
310
+ ">>": "shr",
311
+ ">>>": "shr",
312
+ "<<": "shl",
313
+ "&&": "land",
314
+ "||": "or",
315
+ };
316
+ for (const key in operatorMap$1) {
317
+ const kind = operatorMap$1[key];
318
+ BaseValue.prototype[key] = function (scope, value) {
319
+ const [left, leftInst] = this.consume(scope);
320
+ const [right, rightInst] = value.consume(scope);
321
+ const temp = new StoreValue(scope);
322
+ return [
323
+ temp,
324
+ [
325
+ ...leftInst,
326
+ ...rightInst,
327
+ new OperationInstruction(kind, temp, left, right),
328
+ ],
329
+ ];
330
+ };
331
+ }
332
+ const unaryOperatorMap$1 = {
333
+ "!": "not",
334
+ "~": "flip",
335
+ };
336
+ for (const key in unaryOperatorMap$1) {
337
+ const name = unaryOperatorMap$1[key];
338
+ BaseValue.prototype[key] = function (scope) {
339
+ const [that, inst] = this.consume(scope);
340
+ const temp = new StoreValue(scope);
341
+ return [temp, [...inst, new OperationInstruction(name, temp, that, null)]];
342
+ };
343
+ }
344
+ const assignmentToBinary = {
345
+ "+=": "+",
346
+ "-=": "-",
347
+ "*=": "*",
348
+ "/=": "/",
349
+ "%=": "%",
350
+ "**=": "**",
351
+ "|=": "|",
352
+ "&=": "&",
353
+ "^=": "^",
354
+ ">>=": ">>",
355
+ ">>>=": ">>>",
356
+ "<<=": "<<",
357
+ "&&=": "&&",
358
+ "||=": "||",
359
+ };
360
+ for (const op in assignmentToBinary) {
361
+ BaseValue.prototype[op] = function (scope, value) {
362
+ this.ensureOwned();
363
+ const [opValue, opInst] = this[assignmentToBinary[op]](scope, value);
364
+ const [retValue, retInst] = this["="](scope, opValue);
365
+ return [retValue, [...opInst, ...retInst]];
366
+ };
367
+ }
368
+ for (const key of updateOperators) {
369
+ BaseValue.prototype[key] = function (scope, prefix) {
370
+ let [ret, inst] = this.consume(scope);
371
+ if (!prefix) {
372
+ const temp = new StoreValue(scope);
373
+ const [tempValue, tempInst] = temp["="](scope, ret);
374
+ ret = tempValue;
375
+ inst.push(...tempInst);
376
+ }
377
+ const kind = key === "++" ? "+=" : "-=";
378
+ return [
379
+ ret,
380
+ [...inst, ...this[kind](scope, new LiteralValue(scope, 1))[1]],
381
+ ];
382
+ };
383
+ }
384
+
385
+ const literalMethods = {
386
+ length: function (scope) {
387
+ if (typeof this.data !== "string")
388
+ throw new CompilerError("Length method only works on string literal values.");
389
+ return new LiteralValue(scope, this.data.length);
390
+ },
391
+ };
392
+ class LiteralValue extends BaseValue {
393
+ constructor(scope, data) {
394
+ super(scope);
395
+ this.mutability = EMutability.constant;
396
+ this.data = data;
397
+ }
398
+ eval(_scope) {
399
+ return [this, []];
400
+ }
401
+ consume(_scope) {
402
+ return [this, []];
403
+ }
404
+ toString() {
405
+ return JSON.stringify(this.data);
406
+ }
407
+ get(scope, name) {
408
+ if (!(name instanceof LiteralValue && typeof name.data === "string"))
409
+ return super.get(scope, name);
410
+ const method = literalMethods[name.data];
411
+ if (!method)
412
+ throw new CompilerError(`Method ${name.data} does not exist on literal values.`);
413
+ return [method.apply(this, [scope]), []];
414
+ }
415
+ get num() {
416
+ if (this.data === null)
417
+ return 0;
418
+ if (typeof this.data === "string")
419
+ return 1;
420
+ return this.data;
421
+ }
422
+ typeof(scope) {
423
+ return [new LiteralValue(scope, "literal"), []];
424
+ }
425
+ }
426
+ const operatorMap = {
427
+ "==": (a, b) => +(a == b),
428
+ "===": (a, b) => +(a === b),
429
+ "!=": (a, b) => +(a != b),
430
+ "!==": (a, b) => +(a !== b),
431
+ "<": (a, b) => +(a < b),
432
+ ">": (a, b) => +(a > b),
433
+ "<=": (a, b) => +(a <= b),
434
+ ">=": (a, b) => +(a >= b),
435
+ "+": (a, b) => a + b,
436
+ "-": (a, b) => a - b,
437
+ "*": (a, b) => a * b,
438
+ "/": (a, b) => a / b,
439
+ "%": (a, b) => a % b,
440
+ "**": (a, b) => a ** b,
441
+ "|": (a, b) => a | b,
442
+ "&": (a, b) => a & b,
443
+ "^": (a, b) => a ^ b,
444
+ ">>": (a, b) => a >> b,
445
+ ">>>": (a, b) => a >> b,
446
+ "<<": (a, b) => a << b,
447
+ "&&": (a, b) => +(a && b),
448
+ "||": (a, b) => +(a || b),
449
+ };
450
+ for (const key in operatorMap) {
451
+ const fn = operatorMap[key];
452
+ LiteralValue.prototype[key] = function (scope, value) {
453
+ if (!(value instanceof LiteralValue)) {
454
+ return BaseValue.prototype[key].apply(this, [scope, value]);
455
+ }
456
+ return [new LiteralValue(scope, fn(this.num, value.num)), []];
457
+ };
458
+ }
459
+ const unaryOperatorMap = {
460
+ "!": v => +!v,
461
+ "~": v => ~v,
462
+ "u-": v => -v,
463
+ };
464
+ for (const key in unaryOperatorMap) {
465
+ LiteralValue.prototype[key] = function (scope) {
466
+ const fn = unaryOperatorMap[key];
467
+ return [new LiteralValue(scope, fn(this.num)), []];
468
+ };
469
+ }
470
+
471
+ /**
472
+ * The prefix for internal variables inside the compiler output
473
+ */
474
+ const internalPrefix = "&";
475
+ const discardedName = `${internalPrefix}_`;
476
+ /**
477
+ * Returns a string that has the format: [line]:[column].
478
+ *
479
+ * If `name` is provided, and it is a string, the resulting string will
480
+ * have the format: [name]:[line]:[column].
481
+ */
482
+ function nodeName(node, name) {
483
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
484
+ const { line, column } = node.loc.start;
485
+ if (typeof name === "string")
486
+ return `${name}:${line}:${column}`;
487
+ return `${line}:${column}`;
488
+ }
489
+ /**
490
+ * Converts a camel case string into a dash case one.
491
+ *
492
+ * As an example `camelCase` becomes `camel-case`
493
+ * @example
494
+ * ```
495
+ * camelToDashCase("camelCase") // returns "camel-case"
496
+ * ```
497
+ */
498
+ function camelToDashCase(name) {
499
+ return name.replace(/[A-Z]/g, str => `-${str.toLowerCase()}`);
500
+ }
501
+ const itemNames = [
502
+ "copper",
503
+ "lead",
504
+ "metaglass",
505
+ "graphite",
506
+ "sand",
507
+ "coal",
508
+ "titanium",
509
+ "thorium",
510
+ "scrap",
511
+ "silicon",
512
+ "plastanium",
513
+ "phaseFabric",
514
+ "surgeAlloy",
515
+ "sporePod",
516
+ "blastCompound",
517
+ "pyratite",
518
+ ];
519
+ /**
520
+ * A more type safe version of `Object.assign`
521
+ */
522
+ function assign(obj, props) {
523
+ return Object.assign(obj, props);
524
+ }
525
+
526
+ /**
527
+ * `StoreValue` represents values unknown at compile time,
528
+ * mostly used with mutable variables and temporary values
529
+ */
530
+ class StoreValue extends BaseValue {
531
+ constructor(scope) {
532
+ super(scope);
533
+ this.mutability = EMutability.mutable;
534
+ }
535
+ typeof(scope) {
536
+ return [new LiteralValue(scope, "store"), []];
537
+ }
538
+ "="(scope, value) {
539
+ if (this.mutability !== EMutability.mutable)
540
+ throw new CompilerError(`Cannot assign to immutable store '${this}'.`);
541
+ if (this.owner) {
542
+ if (this.owner === value.owner && value instanceof StoreValue)
543
+ return [this, []];
544
+ if (!value.owner?.persistent) {
545
+ if (!value.owner)
546
+ this.owner.own(value);
547
+ else
548
+ value.owner.moveInto(this.owner);
549
+ if (value instanceof StoreValue)
550
+ return [this, []];
551
+ }
552
+ }
553
+ const [evalValue, evalInst] = value.consume(scope);
554
+ return [this, [...evalInst, new SetInstruction(this, evalValue)]];
555
+ }
556
+ eval(_scope) {
557
+ return [this, []];
558
+ }
559
+ consume(_scope) {
560
+ this.ensureOwned();
561
+ return [this, []];
562
+ }
563
+ toString() {
564
+ return this.owner?.name ?? discardedName;
565
+ }
566
+ }
567
+
568
+ class ObjectValue extends VoidValue {
569
+ constructor(scope, data = {}) {
570
+ super(scope);
571
+ this.mutability = EMutability.constant;
572
+ this.macro = true;
573
+ this.data = data;
574
+ }
575
+ static fromArray(scope, items) {
576
+ const data = {
577
+ length: new LiteralValue(scope, items.length),
578
+ };
579
+ items.forEach((item, i) => {
580
+ if (item)
581
+ data[i] = item;
582
+ });
583
+ return new ObjectValue(scope, data);
584
+ }
585
+ typeof(scope) {
586
+ return [new LiteralValue(scope, "object"), []];
587
+ }
588
+ get(scope, key) {
589
+ // avoids naming collisions with keys like
590
+ // constructor or toString
591
+ if (Object.prototype.hasOwnProperty.call(this.data, key.data)) {
592
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
593
+ const member = this.data[key.data];
594
+ return [member, []];
595
+ }
596
+ const { $get } = this.data;
597
+ if (!$get)
598
+ throw new CompilerError("Cannot get undefined member.");
599
+ return $get.call(scope, [key]);
600
+ }
601
+ eval(scope) {
602
+ const { $eval } = this.data;
603
+ if (!$eval)
604
+ return [this, []];
605
+ return $eval.call(scope, []);
606
+ }
607
+ consume(scope) {
608
+ const { $consume } = this.data;
609
+ if ($consume)
610
+ return $consume.call(scope, []);
611
+ const result = this.eval(scope);
612
+ // required by typescript
613
+ const res = result[0];
614
+ res.ensureOwned();
615
+ return result;
616
+ }
617
+ call(scope, args) {
618
+ const { $call } = this.data;
619
+ if (!$call)
620
+ return super.call(scope, args);
621
+ return $call.call(scope, args);
622
+ }
623
+ ensureOwned() {
624
+ this.owner ??= new ValueOwner({ scope: this.scope, value: this });
625
+ }
626
+ }
627
+ for (const op of operators) {
628
+ ObjectValue.prototype[op] = function (...args) {
629
+ const $ = this.data[`$${op}`];
630
+ // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-unsafe-return
631
+ if (!$)
632
+ return VoidValue.prototype[op].apply(this, args);
633
+ const [scope, ...fnArgs] = args;
634
+ return $.call(scope, fnArgs);
635
+ };
636
+ }
637
+
638
+ /**
639
+ * Properties that should return a new `SenseableValue`
640
+ */
641
+ const senseableProps = ["controller"];
642
+ /**
643
+ * Senseable values are "objects" in the mlog runtime that
644
+ * have special properties that can be accessed
645
+ * via the `sense` instruction.
646
+ *
647
+ * This class extends `StoreValue` to allow dynamic behavior
648
+ * that is not possible with object macros.
649
+ *
650
+ * Note that these values are constant by default, so make sure
651
+ * to set that field to `false` if you want them to be assignable. Example:
652
+ * ```
653
+ * const value = assign(new SenseableValue(scope), {
654
+ * mutability: EMutability.mutable
655
+ * })
656
+ * ```
657
+ */
658
+ class SenseableValue extends StoreValue {
659
+ constructor(scope) {
660
+ super(scope);
661
+ this.mutability = EMutability.constant;
662
+ }
663
+ get(scope, prop) {
664
+ if (prop instanceof LiteralValue && typeof prop.data === "string") {
665
+ const name = itemNames.includes(prop.data)
666
+ ? camelToDashCase(prop.data)
667
+ : prop.data;
668
+ const result = senseableProps.includes(prop.data)
669
+ ? new SenseableValue(scope)
670
+ : new StoreValue(scope);
671
+ return [
672
+ result,
673
+ [new InstructionBase("sensor", result, this, `@${name}`)],
674
+ ];
675
+ }
676
+ if (prop instanceof StoreValue) {
677
+ const temp = new StoreValue(scope);
678
+ return [temp, [new InstructionBase("sensor", temp, this, prop)]];
679
+ }
680
+ throw new CompilerError(`Cannot sense "${prop}" property`);
681
+ }
682
+ }
683
+
684
+ /**
685
+ * Specific case class, required on the ArrayPattern and ObjectPattern handlers
686
+ * in order to keep the separation of concerns and make the code more modular.
687
+ *
688
+ * When it is assign a value, it will get it's own properties and recursively assign
689
+ * each of them to their counterparts on the right hand value.
690
+ */
691
+ class DestructuringValue extends VoidValue {
692
+ constructor(scope, members) {
693
+ super(scope);
694
+ this.members = members;
695
+ this.macro = true;
696
+ }
697
+ "="(scope, right) {
698
+ const inst = [];
699
+ for (const [key, value] of this.members) {
700
+ const [item, itemInst] = right.get(scope, key);
701
+ inst.push(...itemInst);
702
+ inst.push(...value["="](scope, item)[1]);
703
+ }
704
+ return [right, inst];
705
+ }
706
+ eval(_scope) {
707
+ return [this, []];
708
+ }
709
+ consume(_scope) {
710
+ return [this, []];
711
+ }
712
+ }
713
+
714
+ class Scope {
715
+ constructor(values, parent = null, stacked = false, ntemp = 0, name = "", inst = []) {
716
+ this.parent = parent;
717
+ this.stacked = stacked;
718
+ this.ntemp = ntemp;
719
+ this.name = name;
720
+ this.inst = inst;
721
+ this.data = values;
722
+ }
723
+ copy() {
724
+ const scope = new Scope({ ...this.data }, this.parent, this.stacked, this.ntemp, this.name, this.inst);
725
+ scope.break = this.break;
726
+ scope.continue = this.continue;
727
+ scope.function = this.function;
728
+ return scope;
729
+ }
730
+ createScope() {
731
+ const scope = this.copy();
732
+ scope.data = {};
733
+ scope.parent = this;
734
+ return scope;
735
+ }
736
+ createFunction(name, stacked = this.stacked) {
737
+ return new Scope({}, this, stacked, 0, name, this.inst);
738
+ }
739
+ has(identifier) {
740
+ if (identifier in this.data)
741
+ return true;
742
+ if (this.parent)
743
+ return this.parent.has(identifier);
744
+ return false;
745
+ }
746
+ get(identifier) {
747
+ const owner = this.data[identifier];
748
+ if (owner)
749
+ return owner.value;
750
+ if (this.parent)
751
+ return this.parent.get(identifier);
752
+ throw new CompilerError(`${identifier} is not declared.`);
753
+ }
754
+ set(...args) {
755
+ const name = args.length === 1 ? args[0].identifier : args[0];
756
+ if (!name)
757
+ throw new CompilerError("Values in a scope must have an identifier");
758
+ if (name in this.data)
759
+ throw new CompilerError(`${name} is already declared.`);
760
+ return this.hardSet(...args);
761
+ }
762
+ hardSet(...args) {
763
+ const owner = args.length === 1
764
+ ? args[0]
765
+ : new ValueOwner({
766
+ scope: this,
767
+ identifier: args[0],
768
+ name: args[0],
769
+ value: args[1],
770
+ });
771
+ const { identifier } = owner;
772
+ if (!identifier)
773
+ throw new CompilerError("Values in a scope must have an identifier");
774
+ this.data[identifier] = owner;
775
+ return owner.value;
776
+ }
777
+ make(identifier, name) {
778
+ const owner = new ValueOwner({
779
+ scope: this,
780
+ value: assign(new SenseableValue(this), {
781
+ mutability: EMutability.mutable,
782
+ }),
783
+ identifier,
784
+ name,
785
+ });
786
+ return this.set(owner);
787
+ }
788
+ makeTempName() {
789
+ let result = `${internalPrefix}t${this.ntemp}`;
790
+ if (this.name)
791
+ result += `:${this.name}`;
792
+ this.ntemp++;
793
+ return result;
794
+ }
795
+ }
796
+
797
+ const Program = (c, scope, node) => {
798
+ return c.handleMany(scope ?? new Scope({}), node.body);
799
+ };
800
+
801
+ const VariableDeclaration = (c, scope, node) => {
802
+ return c.handleMany(scope, node.declarations, (scope, child) => VariableDeclarator(c, scope, child, node.kind));
803
+ };
804
+ const VariableDeclarator = (c, scope, node, kind = "let") => {
805
+ const [init, inst] = node.init
806
+ ? c.handleEval(scope, node.init)
807
+ : [null, []];
808
+ inst.push(...Declare(c, scope, node.id, kind, init)[1]);
809
+ return [null, inst];
810
+ };
811
+ const Declare = (c, scope, node, kind, init) => {
812
+ switch (node.type) {
813
+ case "Identifier":
814
+ return DeclareIdentifier(c, scope, node, kind, init);
815
+ case "ArrayPattern":
816
+ return DeclareArrayPattern(c, scope, node, kind, init);
817
+ case "ObjectPattern":
818
+ return DeclareObjectPattern(c, scope, node, kind, init);
819
+ default:
820
+ throw new CompilerError(`Unsupported declaration type: ${node.type}`, [
821
+ node,
822
+ ]);
823
+ }
824
+ };
825
+ const DeclareIdentifier = (c, scope, node, kind, init) => {
826
+ const { name: identifier } = node;
827
+ const name = nodeName(node, !c.compactNames && identifier);
828
+ if (kind === "const" && !init)
829
+ throw new CompilerError("Constants must be initialized.", [node]);
830
+ if (kind === "const" && init?.mutability === EMutability.constant) {
831
+ const owner = new ValueOwner({
832
+ scope,
833
+ identifier,
834
+ name,
835
+ value: init,
836
+ constant: true,
837
+ });
838
+ scope.set(owner);
839
+ return [null, []];
840
+ }
841
+ else {
842
+ const value = scope.make(identifier, name);
843
+ const inst = [];
844
+ if (init) {
845
+ if (init.macro)
846
+ throw new CompilerError("Macro values must be held by constants", [
847
+ node,
848
+ ]);
849
+ inst.push(...value["="](scope, init)[1]);
850
+ }
851
+ if (kind === "const")
852
+ value.mutability = EMutability.constant;
853
+ return [null, inst];
854
+ }
855
+ };
856
+ const DeclareArrayPattern = (c, scope, node, kind, init) => {
857
+ const { elements } = node;
858
+ if (!(init instanceof ObjectValue))
859
+ throw new CompilerError("The value being destructured must be an object value");
860
+ const inst = [];
861
+ for (let i = 0; i < elements.length; i++) {
862
+ const element = elements[i];
863
+ if (!element)
864
+ continue;
865
+ const val = init.data[i];
866
+ if (!val)
867
+ throw new CompilerError(`The target object does not have a value at index ${i}`, [element]);
868
+ inst.push(...Declare(c, scope, element, kind, val)[1]);
869
+ }
870
+ return [null, inst];
871
+ };
872
+ const DeclareObjectPattern = (c, scope, node, kind, base) => {
873
+ if (!base)
874
+ throw new CompilerError("Cannot use object destructuring without an initializer", [node]);
875
+ const { properties } = node;
876
+ const [init, inst] = base.consume(scope);
877
+ for (const prop of properties) {
878
+ if (prop.type === "RestElement")
879
+ throw new CompilerError("The rest operator is not supported", [prop]);
880
+ const { key, value } = prop;
881
+ const child = key.type === "Identifier" && !prop.computed
882
+ ? [new LiteralValue(scope, key.name), []]
883
+ : c.handleConsume(scope, prop.key);
884
+ inst.push(...child[1]);
885
+ const propInit = init.get(scope, child[0]);
886
+ inst.push(...propInit[1]);
887
+ inst.push(...Declare(c, scope, value, kind, propInit[0])[1]);
888
+ }
889
+ return [null, inst];
890
+ };
891
+
892
+ const Literal = (_c, scope, node) => [new LiteralValue(scope, node.value), []];
893
+ const NumericLiteral = Literal;
894
+ const StringLiteral = Literal;
895
+ const NullLiteral = (_c, scope) => [
896
+ new LiteralValue(scope, null),
897
+ [],
898
+ ];
899
+ const BooleanLiteral = (_c, scope, node) => [new LiteralValue(scope, +node.value), []];
900
+
901
+ const LRExpression = (c, scope, node) => {
902
+ const [left, leftInst] = c.handleConsume(scope, node.left);
903
+ const [right, rightInst] = c.handleConsume(scope, node.right);
904
+ const [op, opInst] = left[node.operator](scope, right);
905
+ return [op, [...leftInst, ...rightInst, ...opInst]];
906
+ };
907
+ const BinaryExpression = LRExpression;
908
+ const LogicalExpression = LRExpression;
909
+ const AssignmentExpression = (c, scope, node) => {
910
+ const [left, leftInst] = c.handle(scope, node.left);
911
+ // doesn't need to consume because the operators already do that
912
+ const [right, rightInst] = c.handleEval(scope, node.right);
913
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
914
+ const [op, opInst] = left[node.operator](scope, right);
915
+ return [op, [...leftInst, ...rightInst, ...opInst]];
916
+ };
917
+ const UnaryExpression = (c, scope, { argument, operator }) => {
918
+ const [arg, argInst] = c.handleConsume(scope, argument);
919
+ const operatorId = operator == "+" || operator == "-" ? `u${operator}` : operator;
920
+ if (operatorId === "throw")
921
+ throw new CompilerError("throw operator is not supported");
922
+ const [op, opInst] = arg[operatorId](scope);
923
+ return [op, [...argInst, ...opInst]];
924
+ };
925
+ const UpdateExpression = (c, scope, { argument, operator, prefix }) => {
926
+ const [arg, argInst] = c.handle(scope, argument);
927
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
928
+ const [op, opInst] = arg[operator](scope, prefix);
929
+ return [op, [...argInst, ...opInst]];
930
+ };
931
+ const ConditionalExpression = (c, scope, node) => {
932
+ const [test, testInst] = c.handleConsume(scope, node.test);
933
+ if (test instanceof LiteralValue) {
934
+ if (test.data)
935
+ return c.handleEval(scope, node.consequent);
936
+ return c.handleEval(scope, node.alternate);
937
+ }
938
+ // TODO: this creates those annoying jumps on the
939
+ // temp counter, specially if you nest ternary operators
940
+ const result = new StoreValue(scope);
941
+ result.ensureOwned();
942
+ const consequent = c.handleEval(scope, node.consequent);
943
+ const alternate = c.handleEval(scope, node.alternate);
944
+ const alternateStartAdress = new LiteralValue(scope, null);
945
+ const endExpressionAdress = new LiteralValue(scope, null);
946
+ return [
947
+ result,
948
+ [
949
+ ...testInst,
950
+ new JumpInstruction(alternateStartAdress, EJumpKind.Equal, test, new LiteralValue(scope, 0)),
951
+ ...consequent[1],
952
+ ...result["="](scope, consequent[0])[1],
953
+ new JumpInstruction(endExpressionAdress, EJumpKind.Always),
954
+ new AddressResolver(alternateStartAdress),
955
+ ...alternate[1],
956
+ ...result["="](scope, alternate[0])[1],
957
+ new AddressResolver(endExpressionAdress),
958
+ ],
959
+ ];
960
+ };
961
+
962
+ const Identifier = (c, scope, node) => {
963
+ return [scope.get(node.name), []];
964
+ };
965
+
966
+ const ExpressionStatement = (c, scope, node) => {
967
+ return c.handle(scope, node.expression);
968
+ };
969
+ const BreakStatement = (_, scope) => {
970
+ const addr = new LiteralValue(scope, null);
971
+ scope.break.bind(addr);
972
+ return [null, [new BreakInstruction(addr)]];
973
+ };
974
+ const ContinueStatement = (_, scope) => {
975
+ const addr = new LiteralValue(scope, null);
976
+ scope.continue.bind(addr);
977
+ return [null, [new ContinueInstruction(addr)]];
978
+ };
979
+ const ReturnStatement = (c, scope, node) => {
980
+ const [arg, argInst] = node.argument
981
+ ? c.handle(scope, node.argument)
982
+ : [null, []];
983
+ const [ret, retInst] = scope.function.return(scope, arg);
984
+ return [ret, [...argInst, ...retInst]];
985
+ };
986
+
987
+ const IfStatement = (c, scope, node) => {
988
+ const inst = [];
989
+ const [test, testInst] = c.handleConsume(scope, node.test);
990
+ if (test instanceof LiteralValue) {
991
+ if (test.data)
992
+ inst.push(...c.handle(scope, node.consequent)[1]);
993
+ else if (node.alternate)
994
+ inst.push(...c.handle(scope, node.alternate)[1]);
995
+ return [null, inst];
996
+ }
997
+ const endIfAddr = new LiteralValue(scope, null);
998
+ inst.push(...testInst, new JumpInstruction(endIfAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)), ...c.handle(scope, node.consequent)[1], new AddressResolver(endIfAddr));
999
+ const endElseAddr = new LiteralValue(scope, null);
1000
+ if (node.alternate)
1001
+ inst.push(new JumpInstruction(endElseAddr, EJumpKind.Always), new AddressResolver(endIfAddr), ...c.handle(scope, node.alternate)[1], new AddressResolver(endElseAddr));
1002
+ return [null, inst];
1003
+ };
1004
+
1005
+ const WhileStatement = (c, scope, node) => {
1006
+ const lines = [];
1007
+ const [test, testLines] = c.handleConsume(scope, node.test);
1008
+ const startLoopAddr = new LiteralValue(scope, null);
1009
+ const endLoopAddr = new LiteralValue(scope, null);
1010
+ const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(scope);
1011
+ const endLoopLine = new AddressResolver(endLoopAddr).bindBreak(scope);
1012
+ if (test instanceof LiteralValue) {
1013
+ if (test.data) {
1014
+ lines.push(startLoopLine, ...c.handle(scope, node.body)[1], new JumpInstruction(startLoopAddr, EJumpKind.Always), endLoopLine);
1015
+ }
1016
+ return [null, lines];
1017
+ }
1018
+ 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);
1019
+ return [null, lines];
1020
+ };
1021
+ const DoWhileStatement = (c, scope, node) => {
1022
+ const lines = [];
1023
+ const [test, testLines] = c.handleConsume(scope, node.test);
1024
+ const startLoopAddr = new LiteralValue(scope, null);
1025
+ const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(scope);
1026
+ const [, bodyLines] = c.handle(scope, node.body);
1027
+ if (test instanceof LiteralValue) {
1028
+ if (!test.data)
1029
+ return [null, [...lines, ...bodyLines]];
1030
+ return [
1031
+ null,
1032
+ [
1033
+ ...lines,
1034
+ startLoopLine,
1035
+ ...bodyLines,
1036
+ new JumpInstruction(startLoopAddr, EJumpKind.Always),
1037
+ ],
1038
+ ];
1039
+ }
1040
+ lines.push(startLoopLine, ...bodyLines, ...testLines, new JumpInstruction(startLoopAddr, EJumpKind.Equal, test, new LiteralValue(scope, 1)));
1041
+ return [null, lines];
1042
+ };
1043
+
1044
+ const ForStatement = (c, scope, node) => {
1045
+ scope = scope.createScope();
1046
+ const initInst = node.init ? c.handle(scope, node.init)[1] : [];
1047
+ const [test, testLines] = node.test
1048
+ ? c.handleConsume(scope, node.test)
1049
+ : [new LiteralValue(scope, 1), []];
1050
+ const updateLines = node.update ? c.handle(scope, node.update)[1] : [];
1051
+ const startLoopAddr = new LiteralValue(scope, null);
1052
+ const endLoopAddr = new LiteralValue(scope, null);
1053
+ const startLoopLine = new AddressResolver(startLoopAddr).bindContinue(scope);
1054
+ const endLoopLine = new AddressResolver(endLoopAddr).bindBreak(scope);
1055
+ return [
1056
+ null,
1057
+ [
1058
+ ...initInst,
1059
+ startLoopLine,
1060
+ ...testLines,
1061
+ new JumpInstruction(endLoopAddr, EJumpKind.Equal, test, new LiteralValue(scope, 0)),
1062
+ ...c.handle(scope, node.body)[1],
1063
+ ...updateLines,
1064
+ new JumpInstruction(startLoopAddr, EJumpKind.Always),
1065
+ endLoopLine,
1066
+ ],
1067
+ ];
1068
+ };
1069
+
1070
+ class FunctionValue extends VoidValue {
1071
+ constructor({ scope, params, body, c, node, }) {
1072
+ super(scope);
1073
+ this.mutability = EMutability.constant;
1074
+ this.macro = true;
1075
+ this.paramOwners = [];
1076
+ this.bundled = false;
1077
+ this.initialized = false;
1078
+ this.body = body;
1079
+ this.c = c;
1080
+ this.node = node;
1081
+ this.params = params;
1082
+ }
1083
+ typeof(scope) {
1084
+ return [new LiteralValue(scope, "function"), []];
1085
+ }
1086
+ initScope(name) {
1087
+ this.childScope = this.scope.createFunction(name);
1088
+ this.childScope.function = this;
1089
+ for (const id of this.params) {
1090
+ const name = nodeName(id, !this.c.compactNames && id.name);
1091
+ const owner = new ValueOwner({
1092
+ scope: this.childScope,
1093
+ value: new StoreValue(this.childScope),
1094
+ identifier: id.name,
1095
+ name,
1096
+ });
1097
+ this.childScope.set(owner);
1098
+ this.paramOwners.push(owner);
1099
+ }
1100
+ this.callSize = this.paramOwners.length + 2;
1101
+ }
1102
+ ensureInit() {
1103
+ if (!this.owner)
1104
+ throw new CompilerError(`Functions must be owned by a variable`);
1105
+ if (this.initialized)
1106
+ return;
1107
+ this.initialized = true;
1108
+ const { name } = this.owner;
1109
+ this.initScope(name);
1110
+ this.addr = new LiteralValue(this.childScope, null);
1111
+ this.temp = new ValueOwner({
1112
+ scope: this.childScope,
1113
+ name: `${internalPrefix}f${name}`,
1114
+ value: assign(new SenseableValue(this.childScope), {
1115
+ mutability: EMutability.mutable,
1116
+ }),
1117
+ });
1118
+ this.ret = new ValueOwner({
1119
+ scope: this.childScope,
1120
+ name: `${internalPrefix}r${name}`,
1121
+ value: new StoreValue(this.childScope),
1122
+ });
1123
+ this.inst = [
1124
+ new AddressResolver(this.addr),
1125
+ ...this.c.handle(this.childScope, this.body)[1],
1126
+ ];
1127
+ if (!endsWithReturn(this.inst)) {
1128
+ this.inst.push(new SetCounterInstruction(this.ret.value));
1129
+ }
1130
+ }
1131
+ normalReturn(scope, arg) {
1132
+ const argInst = arg ? this.temp.value["="](scope, arg)[1] : [];
1133
+ return [null, [...argInst, new SetCounterInstruction(this.ret.value)]];
1134
+ }
1135
+ normalCall(scope, args) {
1136
+ if (!this.bundled)
1137
+ this.childScope.inst.push(...this.inst);
1138
+ this.bundled = true;
1139
+ const callAddressLiteral = new LiteralValue(scope, null);
1140
+ const inst = this.paramOwners
1141
+ .map(({ value: param }, i) => param["="](scope, args[i])[1])
1142
+ .reduce((s, c) => s.concat(c), [])
1143
+ .concat(...this.ret.value["="](scope, callAddressLiteral)[1], new JumpInstruction(this.addr, EJumpKind.Always), new AddressResolver(callAddressLiteral));
1144
+ return [this.temp.value, inst];
1145
+ }
1146
+ inlineReturn(scope, arg) {
1147
+ const argInst = arg ? this.inlineTemp.value["="](scope, arg)[1] : [];
1148
+ return [null, argInst];
1149
+ }
1150
+ inlineCall(scope, args) {
1151
+ // create return value
1152
+ this.inlineTemp = new ValueOwner({
1153
+ scope: this.childScope,
1154
+ value: assign(new SenseableValue(scope), {
1155
+ mutability: EMutability.mutable,
1156
+ }),
1157
+ });
1158
+ this.inlineEnd = new LiteralValue(scope, null);
1159
+ // make a copy of the function scope
1160
+ const fnScope = this.childScope.copy();
1161
+ // hard set variables within the function scope
1162
+ this.paramOwners.forEach((owner, i) => {
1163
+ const value = args[i];
1164
+ if (!value.owner?.persistent)
1165
+ owner.own(value);
1166
+ fnScope.hardSet(new ValueOwner({
1167
+ scope: fnScope,
1168
+ value,
1169
+ identifier: owner.identifier,
1170
+ name: owner.name,
1171
+ }));
1172
+ });
1173
+ this.tryingInline = true;
1174
+ const inst = this.c.handle(fnScope, this.body)[1];
1175
+ this.tryingInline = false;
1176
+ // removing useless instruction
1177
+ // get the last instructions
1178
+ // const [jump] = inst.slice(-1);
1179
+ // if (jump instanceof JumpInstruction) {
1180
+ // // remove useless jump
1181
+ // if (jump.args[1] === this.inlineEnd) inst.pop();
1182
+ // }
1183
+ inst.push(new AddressResolver(this.inlineEnd));
1184
+ // return the function value
1185
+ return [this.inlineTemp.value, inst];
1186
+ }
1187
+ call(scope, args) {
1188
+ this.ensureInit();
1189
+ if (args.length !== this.paramOwners.length)
1190
+ throw new CompilerError("Cannot call: argument count not matching.");
1191
+ const inlineCall = this.inlineCall(scope, args);
1192
+ const inlineSize = inlineCall[1].filter(i => !i.hidden).length;
1193
+ if (this.inline || inlineSize <= this.callSize)
1194
+ return inlineCall;
1195
+ return this.normalCall(scope, args);
1196
+ }
1197
+ return(scope, arg) {
1198
+ this.ensureInit();
1199
+ if (arg && arg.macro) {
1200
+ this.inline = true;
1201
+ return [null, []];
1202
+ }
1203
+ if (this.inline || this.tryingInline)
1204
+ return this.inlineReturn(scope, arg);
1205
+ return this.normalReturn(scope, arg);
1206
+ }
1207
+ eval(_scope) {
1208
+ return [this, []];
1209
+ }
1210
+ consume(_scope) {
1211
+ return [this, []];
1212
+ }
1213
+ }
1214
+ function endsWithReturn(inst) {
1215
+ for (let i = inst.length - 1; i >= 0; i--) {
1216
+ const instruction = inst[i];
1217
+ if (instruction.hidden)
1218
+ continue;
1219
+ return instruction instanceof SetCounterInstruction;
1220
+ }
1221
+ return false;
1222
+ }
1223
+
1224
+ function handleFunctionNode(c, scope, node) {
1225
+ let { params, body } = node;
1226
+ if (es.isExpression(body)) {
1227
+ body = es.blockStatement([es.returnStatement(body)]);
1228
+ }
1229
+ return [
1230
+ new FunctionValue({
1231
+ node,
1232
+ scope,
1233
+ params: params,
1234
+ body,
1235
+ c,
1236
+ }),
1237
+ [],
1238
+ ];
1239
+ }
1240
+ const ArrowFunctionExpression = (c, scope, node) => {
1241
+ return handleFunctionNode(c, scope, node);
1242
+ };
1243
+ const FunctionDeclaration = (c, scope, node) => {
1244
+ const identifier = node.id.name;
1245
+ const name = nodeName(node, !c.compactNames && identifier);
1246
+ const functionIns = handleFunctionNode(c, scope, node);
1247
+ const owner = new ValueOwner({
1248
+ scope,
1249
+ value: functionIns[0],
1250
+ identifier,
1251
+ name,
1252
+ });
1253
+ return [scope.set(owner), []];
1254
+ };
1255
+ const FunctionExpression = ArrowFunctionExpression;
1256
+ const ObjectMethod = ArrowFunctionExpression;
1257
+
1258
+ const CallExpression = (c, scope, node) => {
1259
+ const inst = [];
1260
+ const args = node.arguments.map(node => {
1261
+ // TODO: this might be why t0 did not increment
1262
+ // TODO: figure out if the previous todo is still relevant
1263
+ const [v, i] = c.handleConsume(scope, node);
1264
+ inst.push(...i);
1265
+ return v;
1266
+ });
1267
+ const [callee, calleeInst] = c.handleConsume(scope, node.callee);
1268
+ inst.push(...calleeInst);
1269
+ const [callValue, callInst] = callee.call(scope, args);
1270
+ inst.push(...callInst);
1271
+ return [callValue, inst];
1272
+ };
1273
+ const NewExpression = CallExpression;
1274
+
1275
+ const ObjectExpression = (c, scope, node) => {
1276
+ const data = {};
1277
+ const inst = [];
1278
+ for (const prop of node.properties) {
1279
+ if (prop.type === "SpreadElement")
1280
+ throw new CompilerError("Cannot handle spread element", [prop]);
1281
+ if (prop.computed)
1282
+ throw new CompilerError("Cannot handle computed property.", [prop]);
1283
+ const { key } = prop;
1284
+ const value = prop.type === "ObjectProperty" ? prop.value : prop;
1285
+ let index;
1286
+ if (key.type === "Identifier") {
1287
+ index = key.name;
1288
+ }
1289
+ else if (key.type === "StringLiteral" || key.type === "NumericLiteral") {
1290
+ index = `${key.value}`;
1291
+ }
1292
+ else {
1293
+ throw new CompilerError(`Unsupported object key type: ${key.type}`, [
1294
+ key,
1295
+ ]);
1296
+ }
1297
+ const [member, memberInst] = c.handleEval(scope, value);
1298
+ const owner = new ValueOwner({
1299
+ scope,
1300
+ constant: true,
1301
+ value: member,
1302
+ });
1303
+ data[index] = owner.value;
1304
+ inst.push(...memberInst);
1305
+ }
1306
+ return [new ObjectValue(scope, data), inst];
1307
+ };
1308
+ const ArrayExpression = (c, scope, node) => {
1309
+ const items = [];
1310
+ const inst = [];
1311
+ node.elements.forEach(element => {
1312
+ const [value, valueInst] = element
1313
+ ? c.handleEval(scope, element)
1314
+ : [undefined, []];
1315
+ items.push(value);
1316
+ inst.push(...valueInst);
1317
+ });
1318
+ return [ObjectValue.fromArray(scope, items), inst];
1319
+ };
1320
+ const MemberExpression = (c, scope, node) => {
1321
+ const [obj, objInst] = c.handleConsume(scope, node.object);
1322
+ const [prop, propInst] = node.computed
1323
+ ? c.handleConsume(scope, node.property)
1324
+ : [new LiteralValue(scope, node.property.name), []];
1325
+ const [got, gotInst] = obj.get(scope, prop);
1326
+ return [got, [...objInst, ...propInst, ...gotInst]];
1327
+ };
1328
+ const ArrayPattern = (c, scope, node) => {
1329
+ const inst = [];
1330
+ const members = new Map();
1331
+ for (let i = 0; i < node.elements.length; i++) {
1332
+ const element = node.elements[i];
1333
+ if (!element)
1334
+ continue;
1335
+ const valueInst = c.handle(scope, element);
1336
+ if (!valueInst[0])
1337
+ throw new CompilerError("Destructuring element must resolve to a value", [
1338
+ element,
1339
+ ]);
1340
+ inst.push(...valueInst[1]);
1341
+ members.set(new LiteralValue(scope, i), valueInst[0]);
1342
+ }
1343
+ return [new DestructuringValue(scope, members), inst];
1344
+ };
1345
+ const ObjectPattern = (c, scope, node) => {
1346
+ const inst = [];
1347
+ const members = new Map();
1348
+ for (const prop of node.properties) {
1349
+ if (prop.type === "RestElement")
1350
+ throw new CompilerError("The rest operator is not supported");
1351
+ if (!prop)
1352
+ continue;
1353
+ const { key } = prop;
1354
+ const keyInst = !prop.computed && key.type === "Identifier"
1355
+ ? [new LiteralValue(scope, key.name), []]
1356
+ : c.handleConsume(scope, prop.key);
1357
+ inst.push(...keyInst[1]);
1358
+ const valueInst = c.handle(scope, prop.value);
1359
+ if (!valueInst[0])
1360
+ throw new CompilerError("Destructuring member must resolve to a value", [
1361
+ prop.value,
1362
+ ]);
1363
+ inst.push(...valueInst[1]);
1364
+ members.set(keyInst[0], valueInst[0]);
1365
+ }
1366
+ return [new DestructuringValue(scope, members), inst];
1367
+ };
1368
+
1369
+ const TemplateLiteral = (c, scope, node) => {
1370
+ const args = [];
1371
+ const inst = [];
1372
+ node.expressions.forEach((expression, i) => {
1373
+ const [v, vi] = c.handleConsume(scope, expression);
1374
+ inst.push(...vi);
1375
+ args.push(node.quasis[i].value.raw, v);
1376
+ });
1377
+ args.push(node.quasis.slice(-1)[0].value.raw);
1378
+ inst.push(new ZeroSpaceInstruction(...args));
1379
+ return [null, inst];
1380
+ };
1381
+
1382
+ const BlockStatement = (c, scope, node) => {
1383
+ const [value, insts] = c.handleMany(scope.createScope(), node.body);
1384
+ // const cleanInst = []
1385
+ // for (const inst of insts) {
1386
+ // if (inst instanceof BreakInstruction || inst instanceof ContinueInstruction || inst instanceof ReturnInstruction || inst instanceof SetCounterInstruction) break
1387
+ // cleanInst.push(inst)
1388
+ // }
1389
+ return [value, insts];
1390
+ };
1391
+
1392
+ const File = (c, scope, node) => {
1393
+ return c.handle(scope ?? new Scope({}), node.program);
1394
+ };
1395
+
1396
+ const TypeCastExpression = (c, scope, node) => {
1397
+ return c.handle(scope, node.expression);
1398
+ };
1399
+ const TSAsExpression = TypeCastExpression;
1400
+ const TSTypeAssertion = TypeCastExpression;
1401
+ const IgnoredHandler = () => [null, []];
1402
+ const TSInterfaceDeclaration = IgnoredHandler;
1403
+ const TSTypeAliasDeclaration = IgnoredHandler;
1404
+ const TSEnumDeclaration = (c, scope, node) => {
1405
+ if (!node.const)
1406
+ throw new CompilerError("All enums must be declared with the const keyword before enum");
1407
+ let counter = 0;
1408
+ let lastType = "number";
1409
+ const data = {};
1410
+ for (const member of node.members) {
1411
+ if (lastType === "string" && !member.initializer)
1412
+ throw new CompilerError("This enum member must be initialized", [member]);
1413
+ const [value] = member.initializer
1414
+ ? c.handleEval(scope, member.initializer)
1415
+ : [new LiteralValue(scope, counter)];
1416
+ if (!(value instanceof LiteralValue))
1417
+ throw new CompilerError("Enum members must contain literal values", [
1418
+ member,
1419
+ ]);
1420
+ if (typeof value.data === "number") {
1421
+ lastType = "number";
1422
+ counter = value.data + 1;
1423
+ }
1424
+ else {
1425
+ lastType = "string";
1426
+ }
1427
+ const name = member.id.type === "Identifier" ? member.id.name : member.id.value;
1428
+ data[name] = value;
1429
+ }
1430
+ scope.set(new ValueOwner({
1431
+ scope,
1432
+ value: new ObjectValue(scope, data),
1433
+ constant: true,
1434
+ identifier: node.id.name,
1435
+ name: nodeName(node, !c.compactNames && node.id.name),
1436
+ }));
1437
+ return [null, []];
1438
+ };
1439
+ const TSNonNullExpression = (c, scope, node) => {
1440
+ return c.handle(scope, node.expression);
1441
+ };
1442
+
1443
+ var handlers = /*#__PURE__*/Object.freeze({
1444
+ __proto__: null,
1445
+ Program: Program,
1446
+ VariableDeclaration: VariableDeclaration,
1447
+ VariableDeclarator: VariableDeclarator,
1448
+ NumericLiteral: NumericLiteral,
1449
+ StringLiteral: StringLiteral,
1450
+ NullLiteral: NullLiteral,
1451
+ BooleanLiteral: BooleanLiteral,
1452
+ LRExpression: LRExpression,
1453
+ BinaryExpression: BinaryExpression,
1454
+ LogicalExpression: LogicalExpression,
1455
+ AssignmentExpression: AssignmentExpression,
1456
+ UnaryExpression: UnaryExpression,
1457
+ UpdateExpression: UpdateExpression,
1458
+ ConditionalExpression: ConditionalExpression,
1459
+ Identifier: Identifier,
1460
+ ExpressionStatement: ExpressionStatement,
1461
+ BreakStatement: BreakStatement,
1462
+ ContinueStatement: ContinueStatement,
1463
+ ReturnStatement: ReturnStatement,
1464
+ IfStatement: IfStatement,
1465
+ WhileStatement: WhileStatement,
1466
+ DoWhileStatement: DoWhileStatement,
1467
+ ForStatement: ForStatement,
1468
+ ArrowFunctionExpression: ArrowFunctionExpression,
1469
+ FunctionDeclaration: FunctionDeclaration,
1470
+ FunctionExpression: FunctionExpression,
1471
+ ObjectMethod: ObjectMethod,
1472
+ CallExpression: CallExpression,
1473
+ NewExpression: NewExpression,
1474
+ ObjectExpression: ObjectExpression,
1475
+ ArrayExpression: ArrayExpression,
1476
+ MemberExpression: MemberExpression,
1477
+ ArrayPattern: ArrayPattern,
1478
+ ObjectPattern: ObjectPattern,
1479
+ TemplateLiteral: TemplateLiteral,
1480
+ BlockStatement: BlockStatement,
1481
+ File: File,
1482
+ TSAsExpression: TSAsExpression,
1483
+ TSTypeAssertion: TSTypeAssertion,
1484
+ TSInterfaceDeclaration: TSInterfaceDeclaration,
1485
+ TSTypeAliasDeclaration: TSTypeAliasDeclaration,
1486
+ TSEnumDeclaration: TSEnumDeclaration,
1487
+ TSNonNullExpression: TSNonNullExpression
1488
+ });
1489
+
1490
+ class MacroFunction extends VoidValue {
1491
+ constructor(scope, fn) {
1492
+ super(scope);
1493
+ this.macro = true;
1494
+ this.constant = true;
1495
+ this.fn = fn;
1496
+ }
1497
+ call(scope, args) {
1498
+ return this.fn.apply(this, args);
1499
+ }
1500
+ eval(_scope) {
1501
+ return [this, []];
1502
+ }
1503
+ consume(_scope) {
1504
+ return [this, []];
1505
+ }
1506
+ }
1507
+
1508
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
1509
+ const mathOperations = {
1510
+ max: (a, b) => Math.max(a, b),
1511
+ min: (a, b) => Math.min(a, b),
1512
+ angle: (x, y) => {
1513
+ const angle = (Math.atan2(y, x) * 180) / Math.PI;
1514
+ return angle < 0 ? angle + 360 : angle;
1515
+ },
1516
+ len: (a, b) => Math.sqrt(a ** 2 + b ** 2),
1517
+ noise: null,
1518
+ abs: a => Math.abs(a),
1519
+ log: a => Math.log(a),
1520
+ log10: a => Math.log10(a),
1521
+ sin: a => Math.sin(a),
1522
+ cos: a => Math.cos(a),
1523
+ tan: a => Math.tan(a),
1524
+ floor: a => Math.floor(a),
1525
+ ceil: a => Math.ceil(a),
1526
+ sqrt: a => Math.sqrt(a),
1527
+ rand: null,
1528
+ };
1529
+ function createMacroMathOperations(scope) {
1530
+ const macroMathOperations = {};
1531
+ for (const key in mathOperations) {
1532
+ const fn = mathOperations[key];
1533
+ macroMathOperations[key] = new MacroFunction(scope, (a, b) => {
1534
+ if (b) {
1535
+ if (fn && a instanceof LiteralValue && b instanceof LiteralValue) {
1536
+ if (typeof a.data !== "number" || typeof b.data !== "number")
1537
+ throw new CompilerError("Cannot do math operation with non-numerical literals.");
1538
+ return [new LiteralValue(scope, fn(a.num, b.num)), []];
1539
+ }
1540
+ const temp = new StoreValue(scope);
1541
+ return [temp, [new OperationInstruction(key, temp, a, b)]];
1542
+ }
1543
+ if (fn && a instanceof LiteralValue) {
1544
+ if (typeof a.data !== "number")
1545
+ throw new CompilerError("Cannot do math operation with non-numerical literal.");
1546
+ return [new LiteralValue(scope, fn(a.num)), []];
1547
+ }
1548
+ const temp = new StoreValue(scope);
1549
+ return [temp, [new OperationInstruction(key, temp, a, b)]];
1550
+ });
1551
+ }
1552
+ return macroMathOperations;
1553
+ }
1554
+ class MlogMath extends ObjectValue {
1555
+ constructor(scope) {
1556
+ super(scope, createMacroMathOperations(scope));
1557
+ }
1558
+ }
1559
+ // op angle result a b
1560
+ // op len result a b
1561
+
1562
+ class Concat extends MacroFunction {
1563
+ constructor(scope) {
1564
+ super(scope, (...values) => {
1565
+ for (const value of values)
1566
+ if (!(value instanceof LiteralValue))
1567
+ throw new CompilerError("Concat arguments must all be literal values.");
1568
+ return [
1569
+ new LiteralValue(scope, values.map(v => v.data).join("")),
1570
+ [],
1571
+ ];
1572
+ });
1573
+ }
1574
+ }
1575
+
1576
+ class Draw extends MacroFunction {
1577
+ constructor(scope) {
1578
+ super(scope, (kind, ...args) => {
1579
+ if (!(kind instanceof LiteralValue && typeof kind.data === "string"))
1580
+ throw new CompilerError("Draw kind must be a string literal.");
1581
+ if ([
1582
+ "clear",
1583
+ "color",
1584
+ "stroke",
1585
+ "line",
1586
+ "rect",
1587
+ "lineRect",
1588
+ "poly",
1589
+ "linePoly",
1590
+ "triangle",
1591
+ "image",
1592
+ ].indexOf(kind.data) === -1)
1593
+ throw new CompilerError("Invalid draw kind");
1594
+ return [
1595
+ null,
1596
+ [
1597
+ new InstructionBase("draw", kind.data, ...args.map(v => {
1598
+ if (v instanceof LiteralValue && typeof v.data === "string")
1599
+ return v.data;
1600
+ return v;
1601
+ })),
1602
+ ],
1603
+ ];
1604
+ });
1605
+ }
1606
+ }
1607
+
1608
+ class Print extends MacroFunction {
1609
+ constructor(scope) {
1610
+ super(scope, (...values) => {
1611
+ const inst = [];
1612
+ for (const value of values) {
1613
+ inst.push(new InstructionBase("print", value));
1614
+ }
1615
+ return [null, inst];
1616
+ });
1617
+ }
1618
+ }
1619
+
1620
+ class PrintFlush extends MacroFunction {
1621
+ constructor(scope) {
1622
+ super(scope, (target) => {
1623
+ if (!(target instanceof SenseableValue))
1624
+ throw new CompilerError("The printflush target must be a senseable value");
1625
+ return [null, [new InstructionBase("printflush", target)]];
1626
+ });
1627
+ }
1628
+ }
1629
+
1630
+ class DrawFlush extends MacroFunction {
1631
+ constructor(scope) {
1632
+ super(scope, (target) => {
1633
+ if (!(target instanceof SenseableValue))
1634
+ throw new CompilerError("The drawflush target must be a senseable value");
1635
+ return [null, [new InstructionBase("drawflush", target)]];
1636
+ });
1637
+ }
1638
+ }
1639
+
1640
+ class GetLink extends MacroFunction {
1641
+ constructor(scope) {
1642
+ super(scope, (index) => {
1643
+ if (!(index instanceof StoreValue) &&
1644
+ (!(index instanceof LiteralValue) || typeof index.data !== "number"))
1645
+ throw new CompilerError("The getlink index must be a number literal or a store");
1646
+ const outBuild = new SenseableValue(scope);
1647
+ return [outBuild, [new InstructionBase("getlink", outBuild, index)]];
1648
+ });
1649
+ }
1650
+ }
1651
+
1652
+ const validKinds$1 = ["enabled", "shoot", "shootp", "config", "color"];
1653
+ class Control extends MacroFunction {
1654
+ constructor(scope) {
1655
+ super(scope, (kind, building, ...args) => {
1656
+ if (!(kind instanceof LiteralValue) || typeof kind.data !== "string")
1657
+ throw new CompilerError("The control kind must be a string literal");
1658
+ if (!validKinds$1.includes(kind.data))
1659
+ throw new CompilerError("Invalid control kind");
1660
+ if (!(building instanceof SenseableValue))
1661
+ throw new CompilerError("The building must be a senseable value");
1662
+ return [
1663
+ null,
1664
+ [new InstructionBase("control", kind.data, building, ...args)],
1665
+ ];
1666
+ });
1667
+ }
1668
+ }
1669
+
1670
+ const validRadarFilters = [
1671
+ "any",
1672
+ "enemy",
1673
+ "ally",
1674
+ "player",
1675
+ "attacker",
1676
+ "flying",
1677
+ "boss",
1678
+ "ground",
1679
+ ];
1680
+ const validRadarSorts = [
1681
+ "distance",
1682
+ "health",
1683
+ "shield",
1684
+ "armor",
1685
+ "maxHealth",
1686
+ ];
1687
+ class Radar extends MacroFunction {
1688
+ constructor(scope) {
1689
+ super(scope, (building, filter1, filter2, filter3, order, sort) => {
1690
+ if (!(building instanceof SenseableValue))
1691
+ throw new CompilerError("The building must a senseable value");
1692
+ if (!(filter1 instanceof LiteralValue) ||
1693
+ typeof filter1.data !== "string" ||
1694
+ !(filter2 instanceof LiteralValue) ||
1695
+ typeof filter2.data !== "string" ||
1696
+ !(filter3 instanceof LiteralValue) ||
1697
+ typeof filter3.data !== "string")
1698
+ throw new CompilerError("The filters must be string literals");
1699
+ if (!validRadarFilters.includes(filter1.data))
1700
+ throw new CompilerError("Invalid value for filter1");
1701
+ if (!validRadarFilters.includes(filter2.data))
1702
+ throw new CompilerError("Invalid value for filter2");
1703
+ if (!validRadarFilters.includes(filter3.data))
1704
+ throw new CompilerError("Invalid value for filter3");
1705
+ if (!(order instanceof LiteralValue || order instanceof StoreValue))
1706
+ throw new CompilerError("The radar order must be a literal or a store");
1707
+ if (!(sort instanceof LiteralValue) || typeof sort.data !== "string")
1708
+ throw new CompilerError("The radar sort must be a string literal");
1709
+ if (!validRadarSorts.includes(sort.data))
1710
+ throw new CompilerError("Invalid sort value");
1711
+ const outUnit = new SenseableValue(scope);
1712
+ return [
1713
+ outUnit,
1714
+ [
1715
+ new InstructionBase("radar", filter1.data, filter2.data, filter3.data, sort.data, building, order, outUnit),
1716
+ ],
1717
+ ];
1718
+ });
1719
+ }
1720
+ }
1721
+
1722
+ class Sensor extends MacroFunction {
1723
+ constructor(scope) {
1724
+ super(scope, (property, target) => {
1725
+ if (!(property instanceof StoreValue))
1726
+ throw new CompilerError("The sensor property must be a store");
1727
+ if (!(target instanceof SenseableValue))
1728
+ throw new CompilerError("The sensor target must be a senseable value");
1729
+ const temp = new StoreValue(scope);
1730
+ return [temp, [new InstructionBase("sensor", temp, target, property)]];
1731
+ });
1732
+ }
1733
+ }
1734
+
1735
+ class Wait extends MacroFunction {
1736
+ constructor(scope) {
1737
+ super(scope, seconds => {
1738
+ if (!(seconds instanceof StoreValue) &&
1739
+ !(seconds instanceof LiteralValue && typeof seconds.data === "number"))
1740
+ throw new CompilerError("The wait seconds must be either a number literal or a store");
1741
+ return [null, [new InstructionBase("wait", seconds)]];
1742
+ });
1743
+ }
1744
+ }
1745
+
1746
+ const validKinds = ["block", "unit", "item", "liquid"];
1747
+ class Lookup extends MacroFunction {
1748
+ constructor(scope) {
1749
+ super(scope, (kind, index) => {
1750
+ if (!(kind instanceof LiteralValue && typeof kind.data === "string"))
1751
+ throw new CompilerError("The lookup kind must be a string literal");
1752
+ if (!validKinds.includes(kind.data))
1753
+ throw new CompilerError("Invalid lookup kind");
1754
+ if (!(index instanceof LiteralValue && typeof index.data === "number") &&
1755
+ !(index instanceof StoreValue))
1756
+ throw new CompilerError("The lookup index must be a number literal or a store");
1757
+ const temp = new StoreValue(scope);
1758
+ return [temp, [new InstructionBase("lookup", kind.data, temp, index)]];
1759
+ });
1760
+ }
1761
+ }
1762
+
1763
+ class End extends MacroFunction {
1764
+ constructor(scope) {
1765
+ super(scope, () => [null, [new EndInstruction()]]);
1766
+ }
1767
+ }
1768
+
1769
+ class UnitBind extends MacroFunction {
1770
+ constructor(scope) {
1771
+ super(scope, type => {
1772
+ if (!(type instanceof StoreValue))
1773
+ throw new CompilerError("The unitBind type must be a store");
1774
+ return [null, [new InstructionBase("ubind", type)]];
1775
+ });
1776
+ }
1777
+ }
1778
+
1779
+ const validModes = [
1780
+ "idle",
1781
+ "stop",
1782
+ "move",
1783
+ "approach",
1784
+ "boost",
1785
+ "pathfind",
1786
+ "target",
1787
+ "targetp",
1788
+ "itemDrop",
1789
+ "itemTake",
1790
+ "payDrop",
1791
+ "payTake",
1792
+ "payEnter",
1793
+ "mine",
1794
+ "flag",
1795
+ "build",
1796
+ "getBlock",
1797
+ "within",
1798
+ ];
1799
+ class UnitControl extends MacroFunction {
1800
+ constructor(scope) {
1801
+ super(scope, (mode, ...args) => {
1802
+ if (!(mode instanceof LiteralValue) || typeof mode.data !== "string")
1803
+ throw new CompilerError("The unitControl mode must be a string literal");
1804
+ if (!validModes.includes(mode.data))
1805
+ throw new CompilerError("Invalid unitControl mode");
1806
+ if (args.some(value => !(value instanceof StoreValue || value instanceof LiteralValue)))
1807
+ throw new CompilerError("The others arguments of unitControl must be literals or stores");
1808
+ let result = null;
1809
+ let extraArgs = [];
1810
+ switch (mode.data) {
1811
+ case "getBlock": {
1812
+ const outType = new StoreValue(scope);
1813
+ const outBuilding = new SenseableValue(scope);
1814
+ result = ObjectValue.fromArray(scope, [outType, outBuilding]);
1815
+ extraArgs = [outType, outBuilding, new LiteralValue(scope, 0)];
1816
+ break;
1817
+ }
1818
+ case "within": {
1819
+ const temp = new StoreValue(scope);
1820
+ result = temp;
1821
+ extraArgs = [temp, new LiteralValue(scope, 0)];
1822
+ break;
1823
+ }
1824
+ }
1825
+ return [
1826
+ result,
1827
+ [new InstructionBase("ucontrol", mode.data, ...args, ...extraArgs)],
1828
+ ];
1829
+ });
1830
+ }
1831
+ }
1832
+
1833
+ class UnitRadar extends MacroFunction {
1834
+ constructor(scope) {
1835
+ super(scope, (filter1, filter2, filter3, order, sort) => {
1836
+ if (!(filter1 instanceof LiteralValue) ||
1837
+ typeof filter1.data !== "string" ||
1838
+ !(filter2 instanceof LiteralValue) ||
1839
+ typeof filter2.data !== "string" ||
1840
+ !(filter3 instanceof LiteralValue) ||
1841
+ typeof filter3.data !== "string")
1842
+ throw new CompilerError("The filters must be string literals");
1843
+ if (!validRadarFilters.includes(filter1.data))
1844
+ throw new CompilerError("Invalid value for filter1");
1845
+ if (!validRadarFilters.includes(filter2.data))
1846
+ throw new CompilerError("Invalid value for filter2");
1847
+ if (!validRadarFilters.includes(filter3.data))
1848
+ throw new CompilerError("Invalid value for filter3");
1849
+ if (!(order instanceof LiteralValue || order instanceof StoreValue))
1850
+ throw new CompilerError("The radar order must be a literal or a store");
1851
+ if (!(sort instanceof LiteralValue) || typeof sort.data !== "string")
1852
+ throw new CompilerError("The radar sort must be a string literal");
1853
+ if (!validRadarSorts.includes(sort.data))
1854
+ throw new CompilerError("Invalid sort value");
1855
+ const outUnit = new SenseableValue(scope);
1856
+ return [
1857
+ outUnit,
1858
+ [
1859
+ new InstructionBase("uradar", filter1.data, filter2.data, filter3.data, sort.data, "0", // I don't know why, but mindustry requires this extra parameter
1860
+ order, outUnit),
1861
+ ],
1862
+ ];
1863
+ });
1864
+ }
1865
+ }
1866
+
1867
+ const validFinds = ["ore", "building", "spawn", "damaged"];
1868
+ const validBuildingGroups = [
1869
+ "core",
1870
+ "storage",
1871
+ "generator",
1872
+ "turret",
1873
+ "factory",
1874
+ "repair",
1875
+ "rally",
1876
+ "battery",
1877
+ "reactor",
1878
+ ];
1879
+ class UnitLocate extends MacroFunction {
1880
+ constructor(scope) {
1881
+ super(scope, (find, ...args) => {
1882
+ if (!(find instanceof LiteralValue && typeof find.data === "string"))
1883
+ throw new CompilerError("The unitLocate find must be a string literal");
1884
+ if (!validFinds.includes(find.data))
1885
+ throw new CompilerError("Invalid find value");
1886
+ if (args.some(value => !(value instanceof StoreValue || value instanceof LiteralValue)))
1887
+ throw new CompilerError("The others arguments of unitLocate must be literals or stores");
1888
+ const outFound = new StoreValue(scope);
1889
+ const outX = new StoreValue(scope);
1890
+ const outY = new StoreValue(scope);
1891
+ const outBuilding = new SenseableValue(scope);
1892
+ const outArgs = [outX, outY, outFound, outBuilding];
1893
+ let inputArgs = [];
1894
+ switch (find.data) {
1895
+ case "ore": {
1896
+ const [ore] = args;
1897
+ inputArgs = [find.data, "core", "true", ore];
1898
+ break;
1899
+ }
1900
+ case "building": {
1901
+ const [group, enemy] = args;
1902
+ if (!(group instanceof LiteralValue && typeof group.data === "string")) {
1903
+ throw new CompilerError("The building group must be a string literal");
1904
+ }
1905
+ if (!validBuildingGroups.includes(group.data))
1906
+ throw new CompilerError("Invalid building group");
1907
+ inputArgs = [find.data, group.data, enemy, "@copper"];
1908
+ break;
1909
+ }
1910
+ case "spawn":
1911
+ case "damaged": {
1912
+ inputArgs = [find.data, "core", "true", "@copper"];
1913
+ break;
1914
+ }
1915
+ }
1916
+ return [
1917
+ ObjectValue.fromArray(scope, [
1918
+ outFound,
1919
+ outX,
1920
+ outY,
1921
+ ...(find.data !== "ore" ? [outBuilding] : []),
1922
+ ]),
1923
+ [new InstructionBase("ulocate", ...inputArgs, ...outArgs)],
1924
+ ];
1925
+ });
1926
+ }
1927
+ }
1928
+
1929
+ class MemoryEntry extends ObjectValue {
1930
+ constructor(scope, mem, prop) {
1931
+ super(scope, {
1932
+ $eval: new MacroFunction(scope, () => {
1933
+ if (this.store)
1934
+ return [this.store, []];
1935
+ const temp = new StoreValue(scope);
1936
+ return [temp, [new InstructionBase("read", temp, mem.cell, prop)]];
1937
+ }),
1938
+ $consume: new MacroFunction(scope, () => {
1939
+ if (this.store)
1940
+ return [this.store, []];
1941
+ this.ensureOwned();
1942
+ this.store = new StoreValue(scope);
1943
+ this.owner.own(this.store);
1944
+ return [
1945
+ this.store,
1946
+ [new InstructionBase("read", this.store, mem.cell, prop)],
1947
+ ];
1948
+ }),
1949
+ "$=": new MacroFunction(scope, value => {
1950
+ const [data, dataInst] = value.consume(scope);
1951
+ return [
1952
+ data,
1953
+ [...dataInst, new InstructionBase("write", data, mem.cell, prop)],
1954
+ ];
1955
+ }),
1956
+ });
1957
+ this.store = null;
1958
+ }
1959
+ }
1960
+ for (const operator of operators) {
1961
+ if (operator === "=")
1962
+ continue;
1963
+ MemoryEntry.prototype[operator] = function (...args) {
1964
+ // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-unsafe-return
1965
+ return BaseValue.prototype[operator].apply(this, args);
1966
+ };
1967
+ }
1968
+ class MemoryMacro extends ObjectValue {
1969
+ constructor(scope, cell, size) {
1970
+ super(scope, {
1971
+ $get: new MacroFunction(scope, (prop) => {
1972
+ if (prop instanceof LiteralValue && typeof prop.data !== "number")
1973
+ throw new CompilerError(`Invalid memory object property: "${prop.data}"`);
1974
+ const obj = new MemoryEntry(scope, this, prop);
1975
+ return [obj, []];
1976
+ }),
1977
+ length: size,
1978
+ size,
1979
+ });
1980
+ this.cell = cell;
1981
+ this.name = cell.toString();
1982
+ }
1983
+ toString() {
1984
+ return this.name;
1985
+ }
1986
+ }
1987
+ class MemoryBuilder extends ObjectValue {
1988
+ constructor(scope) {
1989
+ super(scope, {
1990
+ $call: new MacroFunction(scope, (cell, size = new LiteralValue(scope, 64)) => {
1991
+ if (!(cell instanceof SenseableValue))
1992
+ throw new CompilerError("Memory cell must be a senseable value.");
1993
+ if (!(size instanceof LiteralValue && typeof size.data === "number"))
1994
+ throw new CompilerError("The memory size must be a number literal.");
1995
+ return [new MemoryMacro(scope, cell, size), []];
1996
+ }),
1997
+ });
1998
+ }
1999
+ }
2000
+
2001
+ const dynamicVars = ["time", "tick"];
2002
+ class NamespaceMacro extends ObjectValue {
2003
+ constructor(scope, { changeCasing = false } = {}) {
2004
+ super(scope, {
2005
+ $get: new MacroFunction(scope, prop => {
2006
+ if (!(prop instanceof LiteralValue) || typeof prop.data !== "string")
2007
+ throw new CompilerError("Cannot use dynamic properties on namespace macros");
2008
+ const symbolName = this.changeCasing
2009
+ ? camelToDashCase(prop.data)
2010
+ : prop.data;
2011
+ const mutability = dynamicVars.includes(symbolName)
2012
+ ? EMutability.readonly
2013
+ : EMutability.constant;
2014
+ const owner = new ValueOwner({
2015
+ scope,
2016
+ value: assign(new StoreValue(scope), {
2017
+ mutability,
2018
+ }),
2019
+ name: `@${symbolName}`,
2020
+ });
2021
+ return [owner.value, []];
2022
+ }),
2023
+ });
2024
+ this.changeCasing = changeCasing;
2025
+ }
2026
+ }
2027
+ class VarsNamespace extends NamespaceMacro {
2028
+ constructor(scope) {
2029
+ super(scope);
2030
+ Object.assign(this.data, {
2031
+ unit: new ValueOwner({
2032
+ scope,
2033
+ name: "@unit",
2034
+ value: new SenseableValue(scope),
2035
+ }).value,
2036
+ this: new ValueOwner({
2037
+ scope,
2038
+ name: "@this",
2039
+ value: new SenseableValue(scope),
2040
+ }).value,
2041
+ });
2042
+ }
2043
+ }
2044
+ class UCommandsNamespace extends NamespaceMacro {
2045
+ constructor(scope) {
2046
+ super(scope);
2047
+ this.data.$get = new MacroFunction(scope, prop => {
2048
+ if (!(prop instanceof LiteralValue) || typeof prop.data !== "string")
2049
+ throw new CompilerError("Cannot use dynamic properties on namespace macros");
2050
+ const symbolName = prop.data[0].toUpperCase() + prop.data.slice(1);
2051
+ const owner = new ValueOwner({
2052
+ scope,
2053
+ name: `@command${symbolName}`,
2054
+ value: assign(new StoreValue(scope), {
2055
+ mutability: EMutability.constant,
2056
+ }),
2057
+ });
2058
+ return [owner.value, []];
2059
+ });
2060
+ }
2061
+ }
2062
+
2063
+ class GetGlobal extends MacroFunction {
2064
+ constructor(scope, mutability) {
2065
+ super(scope, (name) => {
2066
+ if (!(name instanceof LiteralValue) || typeof name.data !== "string")
2067
+ throw new CompilerError("The name parameter must be a string literal.");
2068
+ const owner = new ValueOwner({
2069
+ scope,
2070
+ name: name.data,
2071
+ value: assign(new SenseableValue(scope), {
2072
+ mutability,
2073
+ }),
2074
+ });
2075
+ return [owner.value, []];
2076
+ });
2077
+ }
2078
+ }
2079
+
2080
+ /**
2081
+ * Adds all the compiler globals to `scope`
2082
+ */
2083
+ function initScope(scope) {
2084
+ // namespaces
2085
+ scope.hardSet("ControlKind", new NamespaceMacro(scope));
2086
+ scope.hardSet("Vars", new VarsNamespace(scope));
2087
+ scope.hardSet("Items", new NamespaceMacro(scope, { changeCasing: true }));
2088
+ scope.hardSet("Liquids", new NamespaceMacro(scope));
2089
+ scope.hardSet("Units", new NamespaceMacro(scope));
2090
+ scope.hardSet("LAccess", new NamespaceMacro(scope));
2091
+ scope.hardSet("UnitCommands", new UCommandsNamespace(scope));
2092
+ scope.hardSet("Blocks", new NamespaceMacro(scope, { changeCasing: true }));
2093
+ // helper methods
2094
+ scope.hardSet("getBuilding", new GetGlobal(scope, EMutability.constant));
2095
+ scope.hardSet("getVar", new GetGlobal(scope, EMutability.mutable));
2096
+ scope.hardSet("concat", new Concat(scope));
2097
+ scope.hardSet("Math", new MlogMath(scope));
2098
+ scope.hardSet("Memory", new MemoryBuilder(scope));
2099
+ // commands
2100
+ scope.hardSet("draw", new Draw(scope));
2101
+ scope.hardSet("print", new Print(scope));
2102
+ scope.hardSet("printFlush", new PrintFlush(scope));
2103
+ scope.hardSet("drawFlush", new DrawFlush(scope));
2104
+ scope.hardSet("getLink", new GetLink(scope));
2105
+ scope.hardSet("control", new Control(scope));
2106
+ scope.hardSet("radar", new Radar(scope));
2107
+ scope.hardSet("sensor", new Sensor(scope));
2108
+ scope.hardSet("wait", new Wait(scope));
2109
+ scope.hardSet("lookup", new Lookup(scope));
2110
+ scope.hardSet("endScript", new End(scope));
2111
+ scope.hardSet("unitBind", new UnitBind(scope));
2112
+ scope.hardSet("unitControl", new UnitControl(scope));
2113
+ scope.hardSet("unitRadar", new UnitRadar(scope));
2114
+ scope.hardSet("unitLocate", new UnitLocate(scope));
2115
+ }
2116
+
2117
+ class Compiler {
2118
+ constructor({ stackName, compactNames = false } = {}) {
2119
+ this.handlers = handlers;
2120
+ this.usingStack = !!stackName;
2121
+ this.stackName = stackName;
2122
+ this.compactNames = compactNames;
2123
+ }
2124
+ compile(script) {
2125
+ let output;
2126
+ try {
2127
+ const program = this.parse(script);
2128
+ const scope = new Scope({});
2129
+ initScope(scope);
2130
+ const valueInst = this.handle(scope, program);
2131
+ valueInst[1].push(new EndInstruction(), ...scope.inst);
2132
+ this.resolve(valueInst);
2133
+ output = this.serialize(valueInst) + "\n";
2134
+ }
2135
+ catch (error) {
2136
+ const nodeStack = error instanceof CompilerError ? error.nodeStack : [];
2137
+ return [null, error, nodeStack];
2138
+ }
2139
+ return [output, null, []];
2140
+ }
2141
+ resolve(valueInst) {
2142
+ let i = 0;
2143
+ for (const inst of valueInst[1]) {
2144
+ inst.resolve(i);
2145
+ if (!inst.hidden)
2146
+ i++;
2147
+ }
2148
+ }
2149
+ serialize(resLines) {
2150
+ const [, inst] = resLines;
2151
+ return inst.filter(l => !l.hidden).join("\n");
2152
+ }
2153
+ parse(script) {
2154
+ return parse(script, {
2155
+ ranges: true,
2156
+ plugins: ["typescript"],
2157
+ });
2158
+ }
2159
+ handle(scope, node) {
2160
+ try {
2161
+ const handler = this.handlers[node.type];
2162
+ if (!handler)
2163
+ throw new CompilerError("Missing handler for " + node.type);
2164
+ return handler(this, scope, node, null);
2165
+ }
2166
+ catch (error) {
2167
+ if (error instanceof CompilerError) {
2168
+ error.nodeStack.push(node);
2169
+ }
2170
+ throw error;
2171
+ }
2172
+ }
2173
+ handleEval(scope, node) {
2174
+ const [res, inst] = this.handle(scope, node);
2175
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2176
+ const [evaluated, evaluatedInst] = res.eval(scope);
2177
+ return [evaluated, [...inst, ...evaluatedInst]];
2178
+ }
2179
+ handleConsume(scope, node) {
2180
+ const [res, inst] = this.handle(scope, node);
2181
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2182
+ const [evaluated, evaluatedInst] = res.consume(scope);
2183
+ return [evaluated, [...inst, ...evaluatedInst]];
2184
+ }
2185
+ handleMany(scope, nodes, handler = this.handle.bind(this)) {
2186
+ const lines = [];
2187
+ for (const node of nodes) {
2188
+ const [, nodeLines] = handler(scope, node);
2189
+ lines.push(...nodeLines);
2190
+ }
2191
+ return [null, lines];
2192
+ }
2193
+ }
2194
+
2195
+ export { Compiler, CompilerError };