@minduscript/compiler 1.0.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 (42) hide show
  1. package/.npmignore +2 -0
  2. package/dist/asm/gen-asm.d.ts +2 -0
  3. package/dist/asm/gen-asm.js +432 -0
  4. package/dist/counter.d.ts +5 -0
  5. package/dist/counter.js +13 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +17 -0
  8. package/dist/ir/build-ir.d.ts +3 -0
  9. package/dist/ir/build-ir.js +1057 -0
  10. package/dist/ir/gather-macros.d.ts +8 -0
  11. package/dist/ir/gather-macros.js +204 -0
  12. package/dist/ir/ir.d.ts +478 -0
  13. package/dist/ir/ir.js +120 -0
  14. package/dist/ir/project.d.ts +24 -0
  15. package/dist/ir/project.js +339 -0
  16. package/dist/ir/symbol-table.d.ts +19 -0
  17. package/dist/ir/symbol-table.js +385 -0
  18. package/dist/macro/check-macro.d.ts +14 -0
  19. package/dist/macro/check-macro.js +136 -0
  20. package/dist/macro/expand-macros.d.ts +6 -0
  21. package/dist/macro/expand-macros.js +285 -0
  22. package/dist/optimizer/default-passes.d.ts +2 -0
  23. package/dist/optimizer/default-passes.js +20 -0
  24. package/dist/optimizer/merge-labels.d.ts +2 -0
  25. package/dist/optimizer/merge-labels.js +45 -0
  26. package/dist/optimizer/optimizer.d.ts +4 -0
  27. package/dist/optimizer/optimizer.js +26 -0
  28. package/dist/optimizer/passes/constant-folding.d.ts +2 -0
  29. package/dist/optimizer/passes/constant-folding.js +160 -0
  30. package/dist/optimizer/passes/control-flow.d.ts +5 -0
  31. package/dist/optimizer/passes/control-flow.js +138 -0
  32. package/dist/optimizer/passes/copy-propagation.d.ts +2 -0
  33. package/dist/optimizer/passes/copy-propagation.js +127 -0
  34. package/dist/optimizer/passes/dead-code.d.ts +2 -0
  35. package/dist/optimizer/passes/dead-code.js +200 -0
  36. package/dist/optimizer/passes/merge-labels-pass.d.ts +2 -0
  37. package/dist/optimizer/passes/merge-labels-pass.js +14 -0
  38. package/dist/optimizer/types.d.ts +10 -0
  39. package/dist/optimizer/types.js +3 -0
  40. package/dist/test.d.ts +1 -0
  41. package/dist/test.js +14 -0
  42. package/package.json +22 -0
@@ -0,0 +1,1057 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildIR = void 0;
4
+ const parser_1 = require("@minduscript/parser");
5
+ const counter_1 = require("../counter");
6
+ const gather_macros_1 = require("./gather-macros");
7
+ const ir_1 = require("./ir");
8
+ const lexer_1 = require("@minduscript/lexer");
9
+ const getVarName = (context, variable) => {
10
+ let current = context;
11
+ while (current) {
12
+ if (variable in current.varNameMap) {
13
+ return current.varNameMap[variable];
14
+ }
15
+ current = current.parent;
16
+ }
17
+ return variable;
18
+ };
19
+ const buildIdentifier = (name) => ({
20
+ isLiteral: false,
21
+ isMindustry: name.startsWith('@'),
22
+ name,
23
+ });
24
+ const buildLiteral = (value) => ({
25
+ isLiteral: true,
26
+ value,
27
+ });
28
+ const buildDeclaredIdentifier = (context, identifier) => {
29
+ if (context.parent) {
30
+ const newName = `$${counter_1.counter.next()}`;
31
+ context.varNameMap[identifier] = newName;
32
+ return newName;
33
+ }
34
+ else {
35
+ return identifier;
36
+ }
37
+ };
38
+ const buildOutputIdentifier = (context, identifier) => {
39
+ if (identifier.isMindustry) {
40
+ return identifier.value;
41
+ }
42
+ if (identifier.identifierType != parser_1.IdentifierType.SIMPLE && context.parent) {
43
+ context.varNameMap[identifier.value] = `$${counter_1.counter.next()}`;
44
+ return context.varNameMap[identifier.value];
45
+ }
46
+ return getVarName(context, identifier.value);
47
+ };
48
+ const expandExpression = (macroNameMap, context, expression, ir) => {
49
+ const visit = (node) => {
50
+ switch (node.type) {
51
+ case parser_1.NodeType.UNARY_OP_EXPRESSION: {
52
+ const childName = visit(node.child);
53
+ const newName = `$${counter_1.counter.next()}`;
54
+ switch (node.opType) {
55
+ case lexer_1.TokenType.NOT:
56
+ ir.push({
57
+ type: ir_1.IRNodeType.EQ,
58
+ target: newName,
59
+ left: buildIdentifier(childName),
60
+ right: buildLiteral(0),
61
+ });
62
+ break;
63
+ default:
64
+ ir.push({
65
+ type: ir_1.IRNodeType.FLIP,
66
+ target: newName,
67
+ value: buildIdentifier(childName),
68
+ });
69
+ }
70
+ return newName;
71
+ }
72
+ case parser_1.NodeType.BINARY_OP_EXPRESSION: {
73
+ const lChildName = visit(node.lChild);
74
+ const rChildName = visit(node.rChild);
75
+ const newName = `$${counter_1.counter.next()}`;
76
+ if (node.opType == lexer_1.TokenType.OR) {
77
+ const tempName1 = `$${counter_1.counter.next()}`;
78
+ const tempName2 = `$${counter_1.counter.next()}`;
79
+ ir.push({
80
+ type: ir_1.IRNodeType.NE,
81
+ target: tempName1,
82
+ left: buildIdentifier(lChildName),
83
+ right: buildLiteral(0),
84
+ });
85
+ ir.push({
86
+ type: ir_1.IRNodeType.NE,
87
+ target: tempName2,
88
+ left: buildIdentifier(rChildName),
89
+ right: buildLiteral(0),
90
+ });
91
+ ir.push({
92
+ type: ir_1.IRNodeType.BITOR,
93
+ target: newName,
94
+ left: buildIdentifier(tempName1),
95
+ right: buildIdentifier(tempName2),
96
+ });
97
+ }
98
+ else {
99
+ const temp = {
100
+ type: undefined,
101
+ target: newName,
102
+ left: buildIdentifier(lChildName),
103
+ right: buildIdentifier(rChildName),
104
+ };
105
+ switch (node.opType) {
106
+ case lexer_1.TokenType.AND:
107
+ temp.type = ir_1.IRNodeType.AND;
108
+ break;
109
+ case lexer_1.TokenType.EQ:
110
+ temp.type = ir_1.IRNodeType.EQ;
111
+ break;
112
+ case lexer_1.TokenType.NE:
113
+ temp.type = ir_1.IRNodeType.NE;
114
+ break;
115
+ case lexer_1.TokenType.LESS:
116
+ temp.type = ir_1.IRNodeType.LESS;
117
+ break;
118
+ case lexer_1.TokenType.LE:
119
+ temp.type = ir_1.IRNodeType.LE;
120
+ break;
121
+ case lexer_1.TokenType.GREATER:
122
+ temp.type = ir_1.IRNodeType.GREATER;
123
+ break;
124
+ case lexer_1.TokenType.GE:
125
+ temp.type = ir_1.IRNodeType.GE;
126
+ break;
127
+ case lexer_1.TokenType.STRICT_EQ:
128
+ temp.type = ir_1.IRNodeType.STRICT_EQ;
129
+ break;
130
+ case lexer_1.TokenType.BITOR:
131
+ temp.type = ir_1.IRNodeType.BITOR;
132
+ break;
133
+ case lexer_1.TokenType.XOR:
134
+ temp.type = ir_1.IRNodeType.XOR;
135
+ break;
136
+ case lexer_1.TokenType.BITAND:
137
+ temp.type = ir_1.IRNodeType.BITAND;
138
+ break;
139
+ case lexer_1.TokenType.SHL:
140
+ temp.type = ir_1.IRNodeType.SHL;
141
+ break;
142
+ case lexer_1.TokenType.SHR:
143
+ temp.type = ir_1.IRNodeType.SHR;
144
+ break;
145
+ case lexer_1.TokenType.ADD:
146
+ temp.type = ir_1.IRNodeType.ADD;
147
+ break;
148
+ case lexer_1.TokenType.SUB:
149
+ temp.type = ir_1.IRNodeType.SUB;
150
+ break;
151
+ case lexer_1.TokenType.MUL:
152
+ temp.type = ir_1.IRNodeType.MUL;
153
+ break;
154
+ case lexer_1.TokenType.DIV:
155
+ temp.type = ir_1.IRNodeType.DIV;
156
+ break;
157
+ case lexer_1.TokenType.IDIV:
158
+ temp.type = ir_1.IRNodeType.IDIV;
159
+ break;
160
+ case lexer_1.TokenType.MOD:
161
+ temp.type = ir_1.IRNodeType.MOD;
162
+ break;
163
+ default:
164
+ temp.type = ir_1.IRNodeType.POW;
165
+ }
166
+ ir.push(temp);
167
+ }
168
+ return newName;
169
+ }
170
+ case parser_1.NodeType.FUNCTION_CALL_EXPRESSION: {
171
+ const argCount = node.args.length;
172
+ if (argCount == 1) {
173
+ const argName = visit(node.args[0]);
174
+ const newName = `$${counter_1.counter.next()}`;
175
+ const temp = {
176
+ type: undefined,
177
+ target: newName,
178
+ value: buildIdentifier(argName),
179
+ };
180
+ switch (node.function) {
181
+ case lexer_1.TokenType.ABS:
182
+ temp.type = ir_1.IRNodeType.ABS;
183
+ break;
184
+ case lexer_1.TokenType.LOG:
185
+ temp.type = ir_1.IRNodeType.LOG;
186
+ break;
187
+ case lexer_1.TokenType.LOG10:
188
+ temp.type = ir_1.IRNodeType.LOG10;
189
+ break;
190
+ case lexer_1.TokenType.FLOOR:
191
+ temp.type = ir_1.IRNodeType.FLOOR;
192
+ break;
193
+ case lexer_1.TokenType.CEIL:
194
+ temp.type = ir_1.IRNodeType.CEIL;
195
+ break;
196
+ case lexer_1.TokenType.SQRT:
197
+ temp.type = ir_1.IRNodeType.SQRT;
198
+ break;
199
+ case lexer_1.TokenType.RAND:
200
+ temp.type = ir_1.IRNodeType.RAND;
201
+ break;
202
+ case lexer_1.TokenType.SIN:
203
+ temp.type = ir_1.IRNodeType.SIN;
204
+ break;
205
+ case lexer_1.TokenType.COS:
206
+ temp.type = ir_1.IRNodeType.COS;
207
+ break;
208
+ case lexer_1.TokenType.TAN:
209
+ temp.type = ir_1.IRNodeType.TAN;
210
+ break;
211
+ case lexer_1.TokenType.ASIN:
212
+ temp.type = ir_1.IRNodeType.ASIN;
213
+ break;
214
+ case lexer_1.TokenType.ACOS:
215
+ temp.type = ir_1.IRNodeType.ACOS;
216
+ break;
217
+ default:
218
+ temp.type = ir_1.IRNodeType.ATAN;
219
+ }
220
+ ir.push(temp);
221
+ return newName;
222
+ }
223
+ else {
224
+ const leftArgName = visit(node.args[0]);
225
+ const rightArgName = visit(node.args[1]);
226
+ const newName = `$${counter_1.counter.next()}`;
227
+ const temp = {
228
+ type: undefined,
229
+ target: newName,
230
+ left: buildIdentifier(leftArgName),
231
+ right: buildIdentifier(rightArgName),
232
+ };
233
+ switch (node.function) {
234
+ case lexer_1.TokenType.MAX:
235
+ temp.type = ir_1.IRNodeType.MAX;
236
+ break;
237
+ case lexer_1.TokenType.MIN:
238
+ temp.type = ir_1.IRNodeType.MIN;
239
+ break;
240
+ case lexer_1.TokenType.ANGLE:
241
+ temp.type = ir_1.IRNodeType.ANGLE;
242
+ break;
243
+ case lexer_1.TokenType.ANGLE_DIFF:
244
+ temp.type = ir_1.IRNodeType.ANGLE_DIFF;
245
+ break;
246
+ case lexer_1.TokenType.LEN:
247
+ temp.type = ir_1.IRNodeType.LEN;
248
+ break;
249
+ default:
250
+ temp.type = ir_1.IRNodeType.NOISE;
251
+ }
252
+ ir.push(temp);
253
+ return newName;
254
+ }
255
+ }
256
+ case parser_1.NodeType.MACRO_CALL_EXPRESSION: {
257
+ const inputNames = [];
258
+ for (const arg of node.inputArgs) {
259
+ inputNames.push(visit(arg));
260
+ }
261
+ const macroName = macroNameMap[context.filePath][node.name];
262
+ const name = macroName.name;
263
+ if (context.macroDependencies) {
264
+ context.macroDependencies.add(name);
265
+ }
266
+ const newName = `$${counter_1.counter.next()}`;
267
+ ir.push({
268
+ type: ir_1.IRNodeType.MACRO_CALL_ASSIGN,
269
+ name,
270
+ returnTarget: newName,
271
+ inputArgs: inputNames.map((n) => buildIdentifier(n)),
272
+ outputArgs: node.outputArgs.map((n) => buildOutputIdentifier(context, n)),
273
+ });
274
+ return newName;
275
+ }
276
+ case parser_1.NodeType.LITERAL_EXPRESSION: {
277
+ const newName = `$${counter_1.counter.next()}`;
278
+ ir.push({
279
+ type: ir_1.IRNodeType.ASSIGN,
280
+ target: newName,
281
+ value: buildLiteral(node.value),
282
+ });
283
+ return newName;
284
+ }
285
+ default: {
286
+ if (node.isMindustry) {
287
+ return node.value;
288
+ }
289
+ return getVarName(context, node.value);
290
+ }
291
+ }
292
+ };
293
+ return visit(expression.child);
294
+ };
295
+ const buildStatement = (macroNameMap, context, statement) => {
296
+ const result = [];
297
+ switch (statement.statementType) {
298
+ case parser_1.StatementType.EMPTY:
299
+ break;
300
+ case parser_1.StatementType.VARIABLE_DEFINE: {
301
+ result.push({
302
+ type: ir_1.IRNodeType.ASSIGN,
303
+ target: buildDeclaredIdentifier(context, statement.variableName),
304
+ value: buildIdentifier(expandExpression(macroNameMap, context, statement.expression, result)),
305
+ });
306
+ break;
307
+ }
308
+ case parser_1.StatementType.ASSIGN: {
309
+ result.push({
310
+ type: ir_1.IRNodeType.ASSIGN,
311
+ target: getVarName(context, statement.variableName),
312
+ value: buildIdentifier(expandExpression(macroNameMap, context, statement.expression, result)),
313
+ });
314
+ break;
315
+ }
316
+ case parser_1.StatementType.CONTROL: {
317
+ switch (statement.controlType) {
318
+ case parser_1.ControlType.READ: {
319
+ result.push({
320
+ type: ir_1.IRNodeType.READ,
321
+ output: buildOutputIdentifier(context, statement.output),
322
+ memoryName: buildIdentifier(expandExpression(macroNameMap, context, statement.memoryName, result)),
323
+ memoryIndex: buildIdentifier(expandExpression(macroNameMap, context, statement.memoryIndex, result)),
324
+ });
325
+ break;
326
+ }
327
+ case parser_1.ControlType.WRITE: {
328
+ result.push({
329
+ type: ir_1.IRNodeType.WRITE,
330
+ value: buildIdentifier(expandExpression(macroNameMap, context, statement.value, result)),
331
+ memoryName: buildIdentifier(expandExpression(macroNameMap, context, statement.memoryName, result)),
332
+ memoryIndex: buildIdentifier(expandExpression(macroNameMap, context, statement.memoryIndex, result)),
333
+ });
334
+ break;
335
+ }
336
+ case parser_1.ControlType.DRAW_CLEAR: {
337
+ result.push({
338
+ type: ir_1.IRNodeType.DRAW_CLEAR,
339
+ r: buildIdentifier(expandExpression(macroNameMap, context, statement.r, result)),
340
+ g: buildIdentifier(expandExpression(macroNameMap, context, statement.g, result)),
341
+ b: buildIdentifier(expandExpression(macroNameMap, context, statement.b, result)),
342
+ });
343
+ break;
344
+ }
345
+ case parser_1.ControlType.DRAW_COLOR: {
346
+ result.push({
347
+ type: ir_1.IRNodeType.DRAW_COLOR,
348
+ r: buildIdentifier(expandExpression(macroNameMap, context, statement.r, result)),
349
+ g: buildIdentifier(expandExpression(macroNameMap, context, statement.g, result)),
350
+ b: buildIdentifier(expandExpression(macroNameMap, context, statement.b, result)),
351
+ a: buildIdentifier(expandExpression(macroNameMap, context, statement.a, result)),
352
+ });
353
+ break;
354
+ }
355
+ case parser_1.ControlType.DRAW_COL: {
356
+ result.push({
357
+ type: ir_1.IRNodeType.DRAW_COL,
358
+ color: buildIdentifier(expandExpression(macroNameMap, context, statement.color, result)),
359
+ });
360
+ break;
361
+ }
362
+ case parser_1.ControlType.DRAW_STROKE: {
363
+ result.push({
364
+ type: ir_1.IRNodeType.DRAW_STROKE,
365
+ width: buildIdentifier(expandExpression(macroNameMap, context, statement.width, result)),
366
+ });
367
+ break;
368
+ }
369
+ case parser_1.ControlType.DRAW_LINE: {
370
+ result.push({
371
+ type: ir_1.IRNodeType.DRAW_LINE,
372
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
373
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
374
+ x2: buildIdentifier(expandExpression(macroNameMap, context, statement.x2, result)),
375
+ y2: buildIdentifier(expandExpression(macroNameMap, context, statement.y2, result)),
376
+ });
377
+ break;
378
+ }
379
+ case parser_1.ControlType.DRAW_RECT: {
380
+ result.push({
381
+ type: ir_1.IRNodeType.DRAW_RECT,
382
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
383
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
384
+ width: buildIdentifier(expandExpression(macroNameMap, context, statement.width, result)),
385
+ height: buildIdentifier(expandExpression(macroNameMap, context, statement.height, result)),
386
+ });
387
+ break;
388
+ }
389
+ case parser_1.ControlType.DRAW_LINE_RECT: {
390
+ result.push({
391
+ type: ir_1.IRNodeType.DRAW_LINE_RECT,
392
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
393
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
394
+ width: buildIdentifier(expandExpression(macroNameMap, context, statement.width, result)),
395
+ height: buildIdentifier(expandExpression(macroNameMap, context, statement.height, result)),
396
+ });
397
+ break;
398
+ }
399
+ case parser_1.ControlType.DRAW_POLY: {
400
+ result.push({
401
+ type: ir_1.IRNodeType.DRAW_POLY,
402
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
403
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
404
+ sides: buildIdentifier(expandExpression(macroNameMap, context, statement.sides, result)),
405
+ radius: buildIdentifier(expandExpression(macroNameMap, context, statement.radius, result)),
406
+ rotation: buildIdentifier(expandExpression(macroNameMap, context, statement.rotation, result)),
407
+ });
408
+ break;
409
+ }
410
+ case parser_1.ControlType.DRAW_LINE_POLY: {
411
+ result.push({
412
+ type: ir_1.IRNodeType.DRAW_LINE_POLY,
413
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
414
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
415
+ sides: buildIdentifier(expandExpression(macroNameMap, context, statement.sides, result)),
416
+ radius: buildIdentifier(expandExpression(macroNameMap, context, statement.radius, result)),
417
+ rotation: buildIdentifier(expandExpression(macroNameMap, context, statement.rotation, result)),
418
+ });
419
+ break;
420
+ }
421
+ case parser_1.ControlType.DRAW_TRIANGLE: {
422
+ result.push({
423
+ type: ir_1.IRNodeType.DRAW_TRIANGLE,
424
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
425
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
426
+ x2: buildIdentifier(expandExpression(macroNameMap, context, statement.x2, result)),
427
+ y2: buildIdentifier(expandExpression(macroNameMap, context, statement.y2, result)),
428
+ x3: buildIdentifier(expandExpression(macroNameMap, context, statement.x3, result)),
429
+ y3: buildIdentifier(expandExpression(macroNameMap, context, statement.y3, result)),
430
+ });
431
+ break;
432
+ }
433
+ case parser_1.ControlType.DRAW_IMAGE: {
434
+ result.push({
435
+ type: ir_1.IRNodeType.DRAW_IMAGE,
436
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
437
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
438
+ image: buildIdentifier(expandExpression(macroNameMap, context, statement.image, result)),
439
+ size: buildIdentifier(expandExpression(macroNameMap, context, statement.size, result)),
440
+ rotation: buildIdentifier(expandExpression(macroNameMap, context, statement.rotation, result)),
441
+ });
442
+ break;
443
+ }
444
+ case parser_1.ControlType.PRINT: {
445
+ result.push({
446
+ type: ir_1.IRNodeType.PRINT,
447
+ value: buildIdentifier(expandExpression(macroNameMap, context, statement.value, result)),
448
+ });
449
+ break;
450
+ }
451
+ case parser_1.ControlType.DRAW_FLUSH: {
452
+ result.push({
453
+ type: ir_1.IRNodeType.DRAW_FLUSH,
454
+ target: buildIdentifier(expandExpression(macroNameMap, context, statement.target, result)),
455
+ });
456
+ break;
457
+ }
458
+ case parser_1.ControlType.PRINT_FLUSH: {
459
+ result.push({
460
+ type: ir_1.IRNodeType.PRINT_FLUSH,
461
+ target: buildIdentifier(expandExpression(macroNameMap, context, statement.target, result)),
462
+ });
463
+ break;
464
+ }
465
+ case parser_1.ControlType.GET_LINK: {
466
+ result.push({
467
+ type: ir_1.IRNodeType.GET_LINK,
468
+ result: buildOutputIdentifier(context, statement.result),
469
+ id: buildIdentifier(expandExpression(macroNameMap, context, statement.id, result)),
470
+ });
471
+ break;
472
+ }
473
+ case parser_1.ControlType.SET_ENABLED: {
474
+ result.push({
475
+ type: ir_1.IRNodeType.SET_ENABLED,
476
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
477
+ enabled: buildIdentifier(expandExpression(macroNameMap, context, statement.value, result)),
478
+ });
479
+ break;
480
+ }
481
+ case parser_1.ControlType.SET_SHOOT: {
482
+ result.push({
483
+ type: ir_1.IRNodeType.SET_SHOOT,
484
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
485
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
486
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
487
+ shoot: buildIdentifier(expandExpression(macroNameMap, context, statement.shoot, result)),
488
+ });
489
+ break;
490
+ }
491
+ case parser_1.ControlType.SET_SHOOT_P: {
492
+ result.push({
493
+ type: ir_1.IRNodeType.SET_SHOOT_P,
494
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
495
+ unit: buildIdentifier(expandExpression(macroNameMap, context, statement.unit, result)),
496
+ shoot: buildIdentifier(expandExpression(macroNameMap, context, statement.shoot, result)),
497
+ });
498
+ break;
499
+ }
500
+ case parser_1.ControlType.SET_CONFIG: {
501
+ result.push({
502
+ type: ir_1.IRNodeType.SET_CONFIG,
503
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
504
+ config: buildIdentifier(expandExpression(macroNameMap, context, statement.config, result)),
505
+ });
506
+ break;
507
+ }
508
+ case parser_1.ControlType.SET_COLOR: {
509
+ result.push({
510
+ type: ir_1.IRNodeType.SET_COLOR,
511
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
512
+ color: buildIdentifier(expandExpression(macroNameMap, context, statement.color, result)),
513
+ });
514
+ break;
515
+ }
516
+ case parser_1.ControlType.RADAR: {
517
+ result.push({
518
+ type: ir_1.IRNodeType.RADAR,
519
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
520
+ condition1: statement.condition1,
521
+ condition2: statement.condition2,
522
+ condition3: statement.condition3,
523
+ order: buildIdentifier(expandExpression(macroNameMap, context, statement.order, result)),
524
+ sort: statement.sort,
525
+ result: buildOutputIdentifier(context, statement.result),
526
+ });
527
+ break;
528
+ }
529
+ case parser_1.ControlType.SENSOR: {
530
+ result.push({
531
+ type: ir_1.IRNodeType.SENSOR,
532
+ target: buildIdentifier(expandExpression(macroNameMap, context, statement.target, result)),
533
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
534
+ result: buildOutputIdentifier(context, statement.result),
535
+ });
536
+ break;
537
+ }
538
+ case parser_1.ControlType.PACK_COLOR: {
539
+ result.push({
540
+ type: ir_1.IRNodeType.PACK_COLOR,
541
+ result: buildOutputIdentifier(context, statement.result),
542
+ r: buildIdentifier(expandExpression(macroNameMap, context, statement.r, result)),
543
+ g: buildIdentifier(expandExpression(macroNameMap, context, statement.g, result)),
544
+ b: buildIdentifier(expandExpression(macroNameMap, context, statement.b, result)),
545
+ a: buildIdentifier(expandExpression(macroNameMap, context, statement.a, result)),
546
+ });
547
+ break;
548
+ }
549
+ case parser_1.ControlType.WAIT: {
550
+ result.push({
551
+ type: ir_1.IRNodeType.WAIT,
552
+ time: buildIdentifier(expandExpression(macroNameMap, context, statement.time, result)),
553
+ });
554
+ break;
555
+ }
556
+ case parser_1.ControlType.CPU_STOP: {
557
+ result.push({ type: ir_1.IRNodeType.CPU_STOP });
558
+ break;
559
+ }
560
+ case parser_1.ControlType.UNIT_BIND: {
561
+ result.push({
562
+ type: ir_1.IRNodeType.UNIT_BIND,
563
+ unit: buildIdentifier(expandExpression(macroNameMap, context, statement.unit, result)),
564
+ });
565
+ break;
566
+ }
567
+ case parser_1.ControlType.UNIT_RADAR: {
568
+ result.push({
569
+ type: ir_1.IRNodeType.UNIT_RADAR,
570
+ condition1: statement.condition1,
571
+ condition2: statement.condition2,
572
+ condition3: statement.condition3,
573
+ order: buildIdentifier(expandExpression(macroNameMap, context, statement.order, result)),
574
+ sort: statement.sort,
575
+ result: buildOutputIdentifier(context, statement.result),
576
+ });
577
+ break;
578
+ }
579
+ case parser_1.ControlType.UNIT_LOCATE: {
580
+ switch (statement.category) {
581
+ case parser_1.UnitLocateCategory.ORE: {
582
+ result.push({
583
+ type: ir_1.IRNodeType.UNIT_LOCATE_ORE,
584
+ target: buildIdentifier(expandExpression(macroNameMap, context, statement.target, result)),
585
+ outX: buildOutputIdentifier(context, statement.outX),
586
+ outY: buildOutputIdentifier(context, statement.outY),
587
+ found: buildOutputIdentifier(context, statement.found),
588
+ });
589
+ break;
590
+ }
591
+ case parser_1.UnitLocateCategory.BUILDING: {
592
+ result.push({
593
+ type: ir_1.IRNodeType.UNIT_LOCATE_BUILDING,
594
+ group: statement.group,
595
+ enemy: buildIdentifier(expandExpression(macroNameMap, context, statement.enemy, result)),
596
+ outX: buildOutputIdentifier(context, statement.outX),
597
+ outY: buildOutputIdentifier(context, statement.outY),
598
+ found: buildOutputIdentifier(context, statement.found),
599
+ building: buildOutputIdentifier(context, statement.building),
600
+ });
601
+ break;
602
+ }
603
+ case parser_1.UnitLocateCategory.SPAWN: {
604
+ result.push({
605
+ type: ir_1.IRNodeType.UNIT_LOCATE_SPAWN,
606
+ outX: buildOutputIdentifier(context, statement.outX),
607
+ outY: buildOutputIdentifier(context, statement.outY),
608
+ found: buildOutputIdentifier(context, statement.found),
609
+ building: buildOutputIdentifier(context, statement.building),
610
+ });
611
+ break;
612
+ }
613
+ case parser_1.UnitLocateCategory.DAMAGED: {
614
+ result.push({
615
+ type: ir_1.IRNodeType.UNIT_LOCATE_DAMAGED,
616
+ outX: buildOutputIdentifier(context, statement.outX),
617
+ outY: buildOutputIdentifier(context, statement.outY),
618
+ found: buildOutputIdentifier(context, statement.found),
619
+ building: buildOutputIdentifier(context, statement.building),
620
+ });
621
+ break;
622
+ }
623
+ }
624
+ break;
625
+ }
626
+ case parser_1.ControlType.IDLE: {
627
+ result.push({ type: ir_1.IRNodeType.IDLE });
628
+ break;
629
+ }
630
+ case parser_1.ControlType.STOP: {
631
+ result.push({ type: ir_1.IRNodeType.STOP });
632
+ break;
633
+ }
634
+ case parser_1.ControlType.MOVE: {
635
+ result.push({
636
+ type: ir_1.IRNodeType.MOVE,
637
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
638
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
639
+ });
640
+ break;
641
+ }
642
+ case parser_1.ControlType.APPROACH: {
643
+ result.push({
644
+ type: ir_1.IRNodeType.APPROACH,
645
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
646
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
647
+ distance: buildIdentifier(expandExpression(macroNameMap, context, statement.distance, result)),
648
+ });
649
+ break;
650
+ }
651
+ case parser_1.ControlType.PATH_FIND: {
652
+ result.push({
653
+ type: ir_1.IRNodeType.PATH_FIND,
654
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
655
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
656
+ });
657
+ break;
658
+ }
659
+ case parser_1.ControlType.AUTO_PATH_FIND: {
660
+ result.push({ type: ir_1.IRNodeType.AUTO_PATH_FIND });
661
+ break;
662
+ }
663
+ case parser_1.ControlType.BOOST: {
664
+ result.push({
665
+ type: ir_1.IRNodeType.BOOST,
666
+ enabled: buildIdentifier(expandExpression(macroNameMap, context, statement.enabled, result)),
667
+ });
668
+ break;
669
+ }
670
+ case parser_1.ControlType.TARGET: {
671
+ result.push({
672
+ type: ir_1.IRNodeType.TARGET,
673
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
674
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
675
+ shoot: buildIdentifier(expandExpression(macroNameMap, context, statement.shoot, result)),
676
+ });
677
+ break;
678
+ }
679
+ case parser_1.ControlType.TARGET_P: {
680
+ result.push({
681
+ type: ir_1.IRNodeType.TARGET_P,
682
+ unit: buildIdentifier(expandExpression(macroNameMap, context, statement.unit, result)),
683
+ shoot: buildIdentifier(expandExpression(macroNameMap, context, statement.shoot, result)),
684
+ });
685
+ break;
686
+ }
687
+ case parser_1.ControlType.ITEM_DROP: {
688
+ result.push({
689
+ type: ir_1.IRNodeType.ITEM_DROP,
690
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
691
+ amount: buildIdentifier(expandExpression(macroNameMap, context, statement.amount, result)),
692
+ });
693
+ break;
694
+ }
695
+ case parser_1.ControlType.ITEM_TAKE: {
696
+ result.push({
697
+ type: ir_1.IRNodeType.ITEM_TAKE,
698
+ building: buildIdentifier(expandExpression(macroNameMap, context, statement.building, result)),
699
+ item: buildIdentifier(expandExpression(macroNameMap, context, statement.item, result)),
700
+ amount: buildIdentifier(expandExpression(macroNameMap, context, statement.amount, result)),
701
+ });
702
+ break;
703
+ }
704
+ case parser_1.ControlType.PAY_DROP: {
705
+ result.push({ type: ir_1.IRNodeType.PAY_DROP });
706
+ break;
707
+ }
708
+ case parser_1.ControlType.PAY_TAKE: {
709
+ result.push({
710
+ type: ir_1.IRNodeType.PAY_TAKE,
711
+ takeUnits: buildIdentifier(expandExpression(macroNameMap, context, statement.takeUnits, result)),
712
+ });
713
+ break;
714
+ }
715
+ case parser_1.ControlType.PAY_ENTER: {
716
+ result.push({ type: ir_1.IRNodeType.PAY_ENTER });
717
+ break;
718
+ }
719
+ case parser_1.ControlType.MINE: {
720
+ result.push({
721
+ type: ir_1.IRNodeType.MINE,
722
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
723
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
724
+ });
725
+ break;
726
+ }
727
+ case parser_1.ControlType.FLAG: {
728
+ result.push({
729
+ type: ir_1.IRNodeType.FLAG,
730
+ flag: buildIdentifier(expandExpression(macroNameMap, context, statement.flag, result)),
731
+ });
732
+ break;
733
+ }
734
+ case parser_1.ControlType.BUILD: {
735
+ result.push({
736
+ type: ir_1.IRNodeType.BUILD,
737
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
738
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
739
+ block: buildIdentifier(expandExpression(macroNameMap, context, statement.block, result)),
740
+ rotation: buildIdentifier(expandExpression(macroNameMap, context, statement.rotation, result)),
741
+ config: buildIdentifier(expandExpression(macroNameMap, context, statement.config, result)),
742
+ });
743
+ break;
744
+ }
745
+ case parser_1.ControlType.GET_BLOCK: {
746
+ result.push({
747
+ type: ir_1.IRNodeType.GET_BLOCK,
748
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
749
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
750
+ outType: buildOutputIdentifier(context, statement.outType),
751
+ building: buildOutputIdentifier(context, statement.building),
752
+ floor: buildOutputIdentifier(context, statement.floor),
753
+ });
754
+ break;
755
+ }
756
+ case parser_1.ControlType.WITHIN: {
757
+ result.push({
758
+ type: ir_1.IRNodeType.WITHIN,
759
+ x: buildIdentifier(expandExpression(macroNameMap, context, statement.x, result)),
760
+ y: buildIdentifier(expandExpression(macroNameMap, context, statement.y, result)),
761
+ radius: buildIdentifier(expandExpression(macroNameMap, context, statement.radius, result)),
762
+ result: buildOutputIdentifier(context, statement.result),
763
+ });
764
+ break;
765
+ }
766
+ case parser_1.ControlType.UNBIND: {
767
+ result.push({ type: ir_1.IRNodeType.UNBIND });
768
+ break;
769
+ }
770
+ }
771
+ break;
772
+ }
773
+ case parser_1.StatementType.MACRO_CALL: {
774
+ const macroName = macroNameMap[context.filePath][statement.name];
775
+ const name = macroName.name;
776
+ if (context.macroDependencies) {
777
+ context.macroDependencies.add(name);
778
+ }
779
+ result.push({
780
+ type: ir_1.IRNodeType.MACRO_CALL,
781
+ name,
782
+ inputArgs: statement.inputArgs.map((arg) => buildIdentifier(expandExpression(macroNameMap, context, arg, result))),
783
+ outputArgs: statement.outputArgs.map((arg) => buildOutputIdentifier(context, arg)),
784
+ });
785
+ break;
786
+ }
787
+ case parser_1.StatementType.IF_ELSE: {
788
+ const elseLabel = `${counter_1.counter.next()}`;
789
+ const endLabel = `${counter_1.counter.next()}`;
790
+ const conditionName = expandExpression(macroNameMap, context, statement.condition, result);
791
+ result.push({
792
+ type: ir_1.IRNodeType.CONDITIONAL_JUMP,
793
+ condition: ir_1.JumpCondition.EQ,
794
+ left: buildIdentifier(conditionName),
795
+ right: buildLiteral(0),
796
+ label: elseLabel,
797
+ });
798
+ const newContext1 = {
799
+ ...context,
800
+ parent: context,
801
+ varNameMap: {},
802
+ };
803
+ result.push(...buildStatementList(macroNameMap, newContext1, statement.ifBody));
804
+ result.push({
805
+ type: ir_1.IRNodeType.JUMP,
806
+ label: endLabel,
807
+ });
808
+ result.push({
809
+ type: ir_1.IRNodeType.LABEL,
810
+ name: elseLabel,
811
+ });
812
+ const newContext2 = {
813
+ ...context,
814
+ parent: context,
815
+ varNameMap: {},
816
+ };
817
+ result.push(...buildStatementList(macroNameMap, newContext2, statement.elseBody));
818
+ result.push({
819
+ type: ir_1.IRNodeType.LABEL,
820
+ name: endLabel,
821
+ });
822
+ break;
823
+ }
824
+ case parser_1.StatementType.IF: {
825
+ const endLabel = `${counter_1.counter.next()}`;
826
+ const conditionName = expandExpression(macroNameMap, context, statement.condition, result);
827
+ result.push({
828
+ type: ir_1.IRNodeType.CONDITIONAL_JUMP,
829
+ condition: ir_1.JumpCondition.EQ,
830
+ left: buildIdentifier(conditionName),
831
+ right: buildLiteral(0),
832
+ label: endLabel,
833
+ });
834
+ const newContext = {
835
+ ...context,
836
+ parent: context,
837
+ varNameMap: {},
838
+ };
839
+ result.push(...buildStatementList(macroNameMap, newContext, statement.ifBody));
840
+ result.push({
841
+ type: ir_1.IRNodeType.LABEL,
842
+ name: endLabel,
843
+ });
844
+ break;
845
+ }
846
+ case parser_1.StatementType.FOR: {
847
+ const conditionLabel = `${counter_1.counter.next()}`;
848
+ const incrementLabel = `${counter_1.counter.next()}`;
849
+ const endLabel = `${counter_1.counter.next()}`;
850
+ const forContext = {
851
+ ...context,
852
+ parent: context,
853
+ varNameMap: {},
854
+ };
855
+ result.push(...buildStatement(macroNameMap, forContext, statement.init));
856
+ result.push({
857
+ type: ir_1.IRNodeType.LABEL,
858
+ name: conditionLabel,
859
+ });
860
+ const forConditionName = expandExpression(macroNameMap, forContext, statement.condition, result);
861
+ result.push({
862
+ type: ir_1.IRNodeType.CONDITIONAL_JUMP,
863
+ condition: ir_1.JumpCondition.EQ,
864
+ left: buildIdentifier(forConditionName),
865
+ right: buildLiteral(0),
866
+ label: endLabel,
867
+ });
868
+ const forBodyContext = {
869
+ ...forContext,
870
+ parent: forContext,
871
+ varNameMap: {},
872
+ breakLabel: endLabel,
873
+ continueLabel: incrementLabel,
874
+ };
875
+ result.push(...buildStatementList(macroNameMap, forBodyContext, statement.body));
876
+ result.push({
877
+ type: ir_1.IRNodeType.LABEL,
878
+ name: incrementLabel,
879
+ });
880
+ if (statement.increment) {
881
+ result.push(...buildStatement(macroNameMap, forContext, statement.increment));
882
+ }
883
+ result.push({
884
+ type: ir_1.IRNodeType.JUMP,
885
+ label: conditionLabel,
886
+ });
887
+ result.push({
888
+ type: ir_1.IRNodeType.LABEL,
889
+ name: endLabel,
890
+ });
891
+ break;
892
+ }
893
+ case parser_1.StatementType.WHILE: {
894
+ const conditionLabel = `${counter_1.counter.next()}`;
895
+ const endLabel = `${counter_1.counter.next()}`;
896
+ result.push({
897
+ type: ir_1.IRNodeType.LABEL,
898
+ name: conditionLabel,
899
+ });
900
+ const conditionName = expandExpression(macroNameMap, context, statement.condition, result);
901
+ result.push({
902
+ type: ir_1.IRNodeType.CONDITIONAL_JUMP,
903
+ condition: ir_1.JumpCondition.EQ,
904
+ left: buildIdentifier(conditionName),
905
+ right: buildLiteral(0),
906
+ label: endLabel,
907
+ });
908
+ const newContext = {
909
+ ...context,
910
+ parent: context,
911
+ varNameMap: {},
912
+ breakLabel: endLabel,
913
+ continueLabel: conditionLabel,
914
+ };
915
+ result.push(...buildStatementList(macroNameMap, newContext, statement.body));
916
+ result.push({
917
+ type: ir_1.IRNodeType.JUMP,
918
+ label: conditionLabel,
919
+ });
920
+ result.push({
921
+ type: ir_1.IRNodeType.LABEL,
922
+ name: endLabel,
923
+ });
924
+ break;
925
+ }
926
+ case parser_1.StatementType.LOOP_CONTROL: {
927
+ if (statement.controlType == parser_1.LoopControlType.BREAK) {
928
+ result.push({
929
+ type: ir_1.IRNodeType.JUMP,
930
+ label: context.breakLabel,
931
+ });
932
+ }
933
+ else {
934
+ result.push({
935
+ type: ir_1.IRNodeType.JUMP,
936
+ label: context.continueLabel,
937
+ });
938
+ }
939
+ break;
940
+ }
941
+ case parser_1.StatementType.RETURN: {
942
+ const returnValueName = expandExpression(macroNameMap, context, statement.expression, result);
943
+ result.push({
944
+ type: ir_1.IRNodeType.ASSIGN,
945
+ target: '$return',
946
+ value: buildIdentifier(returnValueName),
947
+ });
948
+ result.push({
949
+ type: ir_1.IRNodeType.JUMP,
950
+ label: context.returnLabel,
951
+ });
952
+ break;
953
+ }
954
+ case parser_1.StatementType.BIND: {
955
+ if (context.boundVariables) {
956
+ context.boundVariables.add(statement.variableName);
957
+ }
958
+ break;
959
+ }
960
+ default:
961
+ break;
962
+ }
963
+ return result;
964
+ };
965
+ const buildStatementList = (macroNameMap, context, statements) => {
966
+ const result = [];
967
+ for (const statement of statements) {
968
+ result.push(...buildStatement(macroNameMap, context, statement));
969
+ }
970
+ return result;
971
+ };
972
+ const buildMacro = (macroNameMap, filePath, macro) => {
973
+ const returnLabel = `${counter_1.counter.next()}`;
974
+ const context = {
975
+ filePath,
976
+ parent: {
977
+ filePath,
978
+ varNameMap: {},
979
+ },
980
+ varNameMap: {},
981
+ returnLabel,
982
+ macroDependencies: new Set(),
983
+ };
984
+ const inputParams = [];
985
+ for (const param of macro.inputParams) {
986
+ const newName = `$input_${counter_1.counter.next()}`;
987
+ context.varNameMap[param] = newName;
988
+ inputParams.push(newName);
989
+ }
990
+ const outputParams = [];
991
+ for (const param of macro.outputParams) {
992
+ const newName = `$output_${counter_1.counter.next()}`;
993
+ context.varNameMap[param] = newName;
994
+ outputParams.push(newName);
995
+ }
996
+ const ir = buildStatementList(macroNameMap, context, macro.body);
997
+ ir.push({
998
+ type: ir_1.IRNodeType.ASSIGN,
999
+ target: '$return',
1000
+ value: buildLiteral(null),
1001
+ });
1002
+ ir.push({
1003
+ type: ir_1.IRNodeType.LABEL,
1004
+ name: returnLabel,
1005
+ });
1006
+ return {
1007
+ name: macroNameMap[filePath][macro.name].name,
1008
+ inputParams,
1009
+ outputParams,
1010
+ body: ir,
1011
+ dependencies: context.macroDependencies,
1012
+ };
1013
+ };
1014
+ const buildMain = (macroNameMap, filePath, mainBody, boundVariables) => {
1015
+ const context = {
1016
+ filePath,
1017
+ varNameMap: {},
1018
+ boundVariables,
1019
+ };
1020
+ return buildStatementList(macroNameMap, context, mainBody);
1021
+ };
1022
+ const buildIR = (project) => {
1023
+ const macroNameMap = (0, gather_macros_1.gatherMacros)(project);
1024
+ counter_1.counter.reset();
1025
+ const macros = [];
1026
+ const visitedMacros = new Set();
1027
+ for (const filePath in macroNameMap) {
1028
+ for (const macroName in macroNameMap[filePath]) {
1029
+ const macroMetadata = macroNameMap[filePath][macroName];
1030
+ const macroId = macroMetadata.name;
1031
+ if (!visitedMacros.has(macroId)) {
1032
+ const declarationSource = project.sources[macroMetadata.filePath];
1033
+ if (!declarationSource) {
1034
+ continue;
1035
+ }
1036
+ const hasSameMacroId = (name) => macroNameMap[macroMetadata.filePath]?.[name]?.name === macroId;
1037
+ let macroNode = declarationSource.macros.find((m) => hasSameMacroId(m.name));
1038
+ if (!macroNode) {
1039
+ macroNode = declarationSource.internalMacros.find((m) => hasSameMacroId(m.name));
1040
+ }
1041
+ if (!macroNode) {
1042
+ continue;
1043
+ }
1044
+ visitedMacros.add(macroId);
1045
+ macros.push(buildMacro(macroNameMap, macroMetadata.filePath, macroNode));
1046
+ }
1047
+ }
1048
+ }
1049
+ const boundVariables = new Set();
1050
+ return {
1051
+ macros,
1052
+ boundVariables,
1053
+ main: buildMain(macroNameMap, project.entryPath, project.sources[project.entryPath].ast.statementList, boundVariables),
1054
+ };
1055
+ };
1056
+ exports.buildIR = buildIR;
1057
+ //# sourceMappingURL=build-ir.js.map