circuitscript 0.0.24 → 0.0.26

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 (73) hide show
  1. package/LICENSE +1 -1
  2. package/dist/cjs/BaseVisitor.js +485 -0
  3. package/dist/cjs/SemanticTokenVisitor.js +218 -0
  4. package/dist/cjs/SymbolValidatorVisitor.js +233 -0
  5. package/dist/cjs/antlr/CircuitScriptLexer.js +256 -219
  6. package/dist/cjs/antlr/CircuitScriptParser.js +2891 -2151
  7. package/dist/cjs/antlr/CircuitScriptVisitor.js +4 -3
  8. package/dist/cjs/draw_symbols.js +73 -22
  9. package/dist/cjs/execute.js +70 -78
  10. package/dist/cjs/export.js +91 -5
  11. package/dist/cjs/geometry.js +28 -8
  12. package/dist/cjs/globals.js +1 -2
  13. package/dist/cjs/helpers.js +180 -7
  14. package/dist/cjs/index.js +2 -0
  15. package/dist/cjs/layout.js +8 -0
  16. package/dist/cjs/lexer.js +19 -22
  17. package/dist/cjs/main.js +27 -20
  18. package/dist/cjs/objects/ClassComponent.js +4 -0
  19. package/dist/cjs/objects/ExecutionScope.js +1 -0
  20. package/dist/cjs/objects/types.js +7 -1
  21. package/dist/cjs/parser.js +29 -258
  22. package/dist/cjs/render.js +1 -1
  23. package/dist/cjs/validate.js +81 -0
  24. package/dist/cjs/visitor.js +601 -823
  25. package/dist/esm/BaseVisitor.mjs +486 -0
  26. package/dist/esm/SemanticTokenVisitor.mjs +215 -0
  27. package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
  28. package/dist/esm/antlr/CircuitScriptLexer.mjs +231 -218
  29. package/dist/esm/antlr/CircuitScriptParser.mjs +2852 -2144
  30. package/dist/esm/antlr/CircuitScriptVisitor.mjs +13 -4
  31. package/dist/esm/draw_symbols.mjs +74 -23
  32. package/dist/esm/execute.mjs +70 -75
  33. package/dist/esm/export.mjs +89 -6
  34. package/dist/esm/geometry.mjs +28 -8
  35. package/dist/esm/globals.mjs +1 -2
  36. package/dist/esm/helpers.mjs +171 -9
  37. package/dist/esm/index.mjs +2 -0
  38. package/dist/esm/layout.mjs +8 -0
  39. package/dist/esm/lexer.mjs +10 -10
  40. package/dist/esm/main.mjs +28 -21
  41. package/dist/esm/objects/ClassComponent.mjs +4 -0
  42. package/dist/esm/objects/ExecutionScope.mjs +1 -0
  43. package/dist/esm/objects/types.mjs +6 -0
  44. package/dist/esm/parser.mjs +25 -230
  45. package/dist/esm/render.mjs +2 -2
  46. package/dist/esm/validate.mjs +74 -0
  47. package/dist/esm/visitor.mjs +415 -643
  48. package/dist/types/BaseVisitor.d.ts +66 -0
  49. package/dist/types/SemanticTokenVisitor.d.ts +36 -0
  50. package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
  51. package/dist/types/antlr/CircuitScriptLexer.d.ts +37 -29
  52. package/dist/types/antlr/CircuitScriptParser.d.ts +606 -494
  53. package/dist/types/antlr/CircuitScriptVisitor.d.ts +78 -60
  54. package/dist/types/draw_symbols.d.ts +12 -3
  55. package/dist/types/execute.d.ts +5 -10
  56. package/dist/types/export.d.ts +27 -1
  57. package/dist/types/geometry.d.ts +4 -0
  58. package/dist/types/globals.d.ts +2 -3
  59. package/dist/types/helpers.d.ts +32 -1
  60. package/dist/types/index.d.ts +2 -0
  61. package/dist/types/lexer.d.ts +2 -2
  62. package/dist/types/objects/ClassComponent.d.ts +1 -0
  63. package/dist/types/objects/ExecutionScope.d.ts +4 -1
  64. package/dist/types/objects/types.d.ts +5 -0
  65. package/dist/types/parser.d.ts +15 -28
  66. package/dist/types/validate.d.ts +2 -0
  67. package/dist/types/visitor.d.ts +43 -95
  68. package/fonts/Inter-Bold.ttf +0 -0
  69. package/fonts/Inter-Regular.ttf +0 -0
  70. package/fonts/OpenSans-Regular.ttf +0 -0
  71. package/fonts/Roboto-Regular.ttf +0 -0
  72. package/libs/lib.cst +184 -0
  73. package/package.json +11 -6
@@ -1,239 +1,85 @@
1
- import { ParseTreeVisitor } from 'antlr4';
2
- import { readFileSync } from 'fs';
3
- import { join } from 'path';
4
- import { ExecutionContext } from './execute.mjs';
5
1
  import { ClassComponent } from './objects/ClassComponent.mjs';
6
- import { NumericValue, ParamDefinition, PercentageValue, PinBlankValue, } from './objects/ParamDefinition.mjs';
2
+ import { NumericValue, ParamDefinition, } from './objects/ParamDefinition.mjs';
7
3
  import { PinDefinition, PinIdType } from './objects/PinDefinition.mjs';
8
4
  import { PinTypes } from './objects/PinTypes.mjs';
9
5
  import { UndeclaredReference } from './objects/types.mjs';
10
- import { Logger } from './logger.mjs';
11
- import { BlockTypes, ComponentTypes, NoNetText } from './globals.mjs';
6
+ import { BlockTypes, ComponentTypes, NoNetText, ReferenceTypes } from './globals.mjs';
12
7
  import { SymbolDrawingCommands } from './draw_symbols.mjs';
13
- import { parseFileWithVisitor } from './parser.mjs';
14
- export class MainVisitor extends ParseTreeVisitor {
15
- indentLevel = 0;
16
- startingContext;
17
- executionStack;
18
- silent = false;
19
- logger;
20
- printStream = [];
21
- printToConsole = true;
22
- acceptedDirections = ['left', 'right', 'up', 'down'];
23
- pinTypesList = [
24
- PinTypes.Any,
25
- PinTypes.Input,
26
- PinTypes.Output,
27
- PinTypes.IO,
28
- PinTypes.Power,
29
- ];
30
- onImportFile = (visitor, filePath) => {
31
- throw "Import file not implemented";
32
- };
33
- constructor(silent = false) {
34
- super();
35
- this.logger = new Logger();
36
- this.startingContext = new ExecutionContext('__', '__.', '/', 0, 0, silent, this.logger);
37
- this.setupPrintFunction(this.startingContext);
38
- this.executionStack = [this.startingContext];
39
- this.startingContext.resolveNet =
40
- this.createNetResolver(this.executionStack);
41
- this.silent = silent;
42
- }
43
- getExecutor() {
44
- return this.executionStack[this.executionStack.length - 1];
45
- }
46
- visit(ctx) {
47
- if (Array.isArray(ctx)) {
48
- return ctx.map(function (child) {
49
- try {
50
- return child.accept(this);
51
- }
52
- catch (err) {
53
- this.handleError(child, err);
54
- }
55
- }, this);
56
- }
57
- else {
58
- try {
59
- return ctx.accept(this);
60
- }
61
- catch (err) {
62
- this.handleError(ctx, err);
63
- }
64
- }
65
- }
66
- handleError(ctx, err) {
67
- if (!(err instanceof VisitorExecutionException)) {
68
- throw new VisitorExecutionException(ctx, err);
69
- }
70
- else {
71
- throw err;
72
- }
73
- }
74
- visitScript(ctx) {
75
- this.print('===', 'start', '===');
76
- const result = this.visitChildren(ctx);
77
- this.print('===', 'end', '===');
78
- return result;
79
- }
80
- visitParameters(ctx) {
81
- const dataExpressions = ctx.data_expr_list();
82
- const keywordAssignmentExpressions = ctx.keyword_assignment_expr_list();
83
- const returnList = [];
84
- dataExpressions.forEach((item, index) => {
85
- const value = this.visit(item);
86
- returnList.push(['position', index, value]);
87
- });
88
- keywordAssignmentExpressions.forEach((item) => {
89
- const [key, value] = this.visit(item);
90
- returnList.push(['keyword', key, value]);
91
- });
92
- return returnList;
93
- }
94
- visitKeyword_assignment_expr(ctx) {
8
+ import { BaseVisitor } from './BaseVisitor.mjs';
9
+ export class ParserVisitor extends BaseVisitor {
10
+ visitKeyword_assignment_expr = (ctx) => {
95
11
  const id = ctx.ID().getText();
96
- const value = this.visit(ctx.data_expr());
97
- return [id, value];
98
- }
99
- visitAssignment_expr(ctx) {
100
- const atomStr = ctx.atom_expr().getText();
101
- if (atomStr.indexOf('(') !== -1 || atomStr.indexOf(')') !== -1) {
102
- throw "Invalid assignment expression!";
103
- }
104
- const reference = this.visit(ctx.atom_expr());
105
- const value = this.visit(ctx.data_expr());
106
- if (value instanceof ClassComponent) {
107
- const instances = this.getExecutor().scope.instances;
108
- const tmpComponent = value;
109
- const oldName = tmpComponent.instanceName;
110
- tmpComponent.instanceName = reference.name;
111
- instances.delete(oldName);
112
- instances.set(reference.name, tmpComponent);
113
- this.getExecutor().print(`assigned '${reference.name}' to ClassComponent`);
114
- }
115
- else {
116
- const trailers = reference.trailers ?? [];
117
- if (trailers.length === 0) {
118
- this.getExecutor().scope.variables.set(reference.name, value);
119
- }
120
- else if (reference.value instanceof ClassComponent) {
121
- this.setInstanceParam(reference.value, trailers, value);
122
- }
123
- }
124
- return value;
125
- }
126
- setInstanceParam(object, trailers, value) {
127
- const paramName = trailers[0].slice(1);
128
- object.setParam(paramName, value);
129
- this.getExecutor().print(`set instance ${object.instanceName} param ${paramName} to ${value}`);
130
- }
131
- visitValue_expr(ctx) {
132
- const sign = ctx.Minus() ? -1 : 1;
133
- if (ctx.INTEGER_VALUE() || ctx.DECIMAL_VALUE() || ctx.NUMERIC_VALUE()) {
134
- if (ctx.INTEGER_VALUE()) {
135
- return sign * Number(ctx.INTEGER_VALUE().getText());
136
- }
137
- else if (ctx.DECIMAL_VALUE()) {
138
- return sign * Number(ctx.DECIMAL_VALUE().getText());
139
- }
140
- else if (ctx.NUMERIC_VALUE()) {
141
- const textExtra = ctx.Minus() ? '-' : '';
142
- return new NumericValue(textExtra + ctx.NUMERIC_VALUE().getText());
143
- }
144
- }
145
- else {
146
- if (sign === -1) {
147
- throw "Invalid value!";
148
- }
149
- }
150
- if (ctx.BOOLEAN_VALUE()) {
151
- const stringValue = ctx.BOOLEAN_VALUE().getText();
152
- if (stringValue === 'true') {
153
- return true;
154
- }
155
- else if (stringValue === 'false') {
156
- return false;
157
- }
158
- }
159
- else if (ctx.STRING_VALUE()) {
160
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
161
- }
162
- else if (ctx.PERCENTAGE_VALUE()) {
163
- return new PercentageValue(ctx.PERCENTAGE_VALUE().getText());
164
- }
165
- else if (ctx.blank_expr()) {
166
- return this.visit(ctx.blank_expr());
167
- }
168
- }
169
- visitBlank_expr(ctx) {
170
- return new PinBlankValue(Number(ctx.INTEGER_VALUE().getText()));
171
- }
172
- visitPin_select_expr(ctx) {
173
- if (ctx.INTEGER_VALUE()) {
174
- return Number(ctx.INTEGER_VALUE().getText());
175
- }
176
- else if (ctx.STRING_VALUE()) {
177
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
12
+ const ctxDataExpr = ctx.data_expr();
13
+ this.visit(ctxDataExpr);
14
+ const value = this.getResult(ctxDataExpr);
15
+ this.setResult(ctx, [id, value]);
16
+ };
17
+ visitPin_select_expr = (ctx) => {
18
+ let value = null;
19
+ const ctxIntegerValue = ctx.INTEGER_VALUE();
20
+ const ctxStringValue = ctx.STRING_VALUE();
21
+ if (ctxIntegerValue) {
22
+ value = Number(ctxIntegerValue.getText());
178
23
  }
179
- return null;
180
- }
181
- visitAdd_component_expr(ctx) {
182
- const [component, pinValue] = this.visit(ctx.data_expr_with_assignment());
183
- if (ctx.ID()) {
184
- this.setComponentOrientation(component, pinValue, ctx.ID().getText());
24
+ else if (ctxStringValue) {
25
+ value = this.prepareStringValue(ctxStringValue.getText());
185
26
  }
27
+ this.setResult(ctx, value);
28
+ };
29
+ visitAdd_component_expr = (ctx) => {
30
+ const ctxDataWithAssignmentExpr = ctx.data_expr_with_assignment();
31
+ this.visit(ctxDataWithAssignmentExpr);
32
+ const [component, pinValue] = this.getResult(ctxDataWithAssignmentExpr);
186
33
  return this.getExecutor().addComponentExisting(component, pinValue);
187
- }
188
- visitAt_component_expr(ctx) {
34
+ };
35
+ visitAt_component_expr = (ctx) => {
189
36
  if (ctx.Point()) {
190
37
  this.getExecutor().atPointBlock();
191
38
  }
192
39
  else {
193
- const [component, pin] = this.visit(ctx.component_select_expr());
194
- const currentPoint = this.getExecutor().atComponent(component, pin, {
195
- addSequence: true,
196
- cloneNetComponent: true
40
+ const ctxComponentSelectExpr = ctx.component_select_expr();
41
+ this.visit(ctxComponentSelectExpr);
42
+ const [component, pin] = this.getResult(ctxComponentSelectExpr);
43
+ this.getExecutor().atComponent(component, pin, {
44
+ addSequence: true
197
45
  });
198
- if (ctx.ID()) {
199
- this.setComponentOrientation(currentPoint[0], currentPoint[1], ctx.ID().getText());
200
- }
201
46
  }
202
47
  return this.getExecutor().getCurrentPoint();
203
- }
204
- visitTo_component_expr(ctx) {
205
- let currentPoint;
48
+ };
49
+ visitTo_component_expr = (ctx) => {
206
50
  if (ctx.Point()) {
207
51
  this.getExecutor().toPointBlock();
208
52
  }
209
53
  else {
210
- ctx.component_select_expr_list().forEach((item) => {
211
- const [component, pin] = this.visit(item);
212
- currentPoint = this.getExecutor().toComponent(component, pin, {
213
- addSequence: true, cloneNetComponent: true
54
+ ctx.component_select_expr().forEach(item => {
55
+ this.visit(item);
56
+ const [component, pin] = this.getResult(item);
57
+ this.getExecutor().toComponent(component, pin, {
58
+ addSequence: true
214
59
  });
215
60
  });
216
- if (ctx.ID()) {
217
- this.setComponentOrientation(currentPoint[0], currentPoint[1], ctx.ID().getText());
218
- }
219
61
  }
220
62
  return this.getExecutor().getCurrentPoint();
221
- }
222
- visitComponent_select_expr(ctx) {
223
- if (ctx.data_expr_with_assignment()) {
224
- return this.visit(ctx.data_expr_with_assignment());
63
+ };
64
+ visitComponent_select_expr = (ctx) => {
65
+ const ctxDataExprWithAssigment = ctx.data_expr_with_assignment();
66
+ if (ctxDataExprWithAssigment) {
67
+ this.visit(ctxDataExprWithAssigment);
68
+ this.setResult(ctx, this.getResult(ctxDataExprWithAssigment));
225
69
  }
226
70
  else {
227
71
  const component = this.getExecutor().scope.currentComponent;
228
72
  let pinId = null;
229
- if (ctx.pin_select_expr()) {
230
- pinId = this.visit(ctx.pin_select_expr());
73
+ const ctxPinSelectExpr = ctx.pin_select_expr();
74
+ if (ctxPinSelectExpr) {
75
+ this.visit(ctxPinSelectExpr);
76
+ pinId = this.getResult(ctxPinSelectExpr);
231
77
  }
232
- return [component, pinId];
78
+ this.setResult(ctx, [component, pinId]);
233
79
  }
234
- }
235
- visitPath_blocks(ctx) {
236
- const blocks = ctx.path_block_inner_list();
80
+ };
81
+ visitPath_blocks = (ctx) => {
82
+ const blocks = ctx.path_block_inner();
237
83
  let blockIndex = 0;
238
84
  let blockType = BlockTypes.Branch;
239
85
  let prevBlockType = null;
@@ -265,13 +111,9 @@ export class MainVisitor extends ParseTreeVisitor {
265
111
  });
266
112
  this.getExecutor().exitBlocks();
267
113
  return this.getExecutor().getCurrentPoint();
268
- }
269
- visitBreak_keyword() {
270
- this.getExecutor().breakBranch();
271
- return -1;
272
- }
273
- visitCreate_component_expr(ctx) {
274
- const properties = this.getPropertyExprList(ctx.property_expr_list());
114
+ };
115
+ visitCreate_component_expr = (ctx) => {
116
+ const properties = this.getPropertyExprList(ctx.property_expr());
275
117
  const pins = this.parseCreateComponentPins(properties.get('pins'));
276
118
  let instanceName = this.getExecutor().getUniqueInstanceName('');
277
119
  const propParams = properties.get('params');
@@ -291,6 +133,8 @@ export class MainVisitor extends ParseTreeVisitor {
291
133
  properties.get('display') : null;
292
134
  const type = properties.has('type') ?
293
135
  properties.get('type') : null;
136
+ const copy = properties.has('copy') ?
137
+ properties.get('copy') : false;
294
138
  const width = properties.has('width') ?
295
139
  properties.get('width') : null;
296
140
  const props = {
@@ -298,12 +142,14 @@ export class MainVisitor extends ParseTreeVisitor {
298
142
  display,
299
143
  type,
300
144
  width,
145
+ copy
301
146
  };
302
- return this.getExecutor().createComponent(instanceName, pins, params, props);
303
- }
304
- visitCreate_graphic_expr(ctx) {
305
- const commands = ctx.sub_expr_list().reduce((accum, item) => {
306
- const [commandName, parameters] = this.visit(item);
147
+ this.setResult(ctx, this.getExecutor().createComponent(instanceName, pins, params, props));
148
+ };
149
+ visitCreate_graphic_expr = (ctx) => {
150
+ const commands = ctx.graphic_expr().reduce((accum, item) => {
151
+ this.visit(item);
152
+ const [commandName, parameters] = this.getResult(item);
307
153
  const keywordParams = new Map();
308
154
  const positionParams = parameters.reduce((accum, [argType, name, value]) => {
309
155
  if (argType === 'position') {
@@ -317,100 +163,139 @@ export class MainVisitor extends ParseTreeVisitor {
317
163
  accum.push([commandName, positionParams, keywordParams]);
318
164
  return accum;
319
165
  }, []);
320
- return new SymbolDrawingCommands(commands);
321
- }
322
- visitSub_expr(ctx) {
166
+ const drawing = new SymbolDrawingCommands(commands);
167
+ drawing.source = ctx.getText();
168
+ this.setResult(ctx, drawing);
169
+ };
170
+ visitGraphic_expr = (ctx) => {
323
171
  let commandName = null;
324
- if (ctx.ID()) {
325
- commandName = ctx.ID().getText();
326
- }
327
- else if (ctx.Pin()) {
328
- commandName = ctx.Pin().getText();
172
+ const command = ctx._command;
173
+ if (command) {
174
+ commandName = command.text;
329
175
  }
330
176
  else {
331
177
  throw "Invalid command!";
332
178
  }
333
- const parameters = this.visit(ctx.parameters());
334
- return [commandName, parameters];
335
- }
336
- visitProperty_expr(ctx) {
337
- const keyName = this.visit(ctx.property_key_expr());
338
- const value = this.visit(ctx.property_value_expr());
179
+ const ctxParameters = ctx.parameters();
180
+ this.visit(ctxParameters);
181
+ const parameters = this.getResult(ctxParameters);
182
+ this.setResult(ctx, [commandName, parameters]);
183
+ };
184
+ visitProperty_expr = (ctx) => {
185
+ const ctxPropertyKeyExpr = ctx.property_key_expr();
186
+ const ctxPropertyValueExpr = ctx.property_value_expr();
187
+ this.visit(ctxPropertyKeyExpr);
188
+ this.visit(ctxPropertyValueExpr);
189
+ const keyName = this.getResult(ctxPropertyKeyExpr);
190
+ const value = this.getResult(ctxPropertyValueExpr);
339
191
  const map = new Map();
340
192
  map.set(keyName, value);
341
- return map;
342
- }
343
- visitSingle_line_property(ctx) {
193
+ this.setResult(ctx, map);
194
+ };
195
+ visitSingle_line_property = (ctx) => {
344
196
  let value;
345
- if (ctx.data_expr_list().length === 1) {
346
- value = this.visit(ctx.data_expr(0));
197
+ if (ctx.data_expr().length === 1) {
198
+ const ctxFirst = ctx.data_expr(0);
199
+ this.visit(ctxFirst);
200
+ value = this.getResult(ctxFirst);
347
201
  }
348
202
  else {
349
- value = ctx.data_expr_list().map(item => {
350
- return this.visit(item);
203
+ value = ctx.data_expr().map(item => {
204
+ this.visit(item);
205
+ return this.getResult(item);
351
206
  });
352
207
  }
353
- return value;
354
- }
355
- visitNested_properties(ctx) {
208
+ this.setResult(ctx, value);
209
+ };
210
+ visitNested_properties = (ctx) => {
356
211
  const result = new Map();
357
- ctx.property_expr_list().forEach((item) => {
358
- const property = this.visit(item);
212
+ ctx.property_expr().forEach((item) => {
213
+ this.visit(item);
214
+ const property = this.getResult(item);
359
215
  for (const [key, value] of property) {
360
216
  result.set(key, value);
361
217
  }
362
218
  });
363
- return result;
364
- }
365
- visitProperty_key_expr(ctx) {
366
- if (ctx.ID()) {
367
- return ctx.ID().getText();
219
+ this.setResult(ctx, result);
220
+ };
221
+ visitProperty_key_expr = (ctx) => {
222
+ const ctxID = ctx.ID();
223
+ const ctxIntegerValue = ctx.INTEGER_VALUE();
224
+ const ctxStringValue = ctx.STRING_VALUE();
225
+ let result = null;
226
+ if (ctxID) {
227
+ result = ctxID.getText();
368
228
  }
369
- else if (ctx.INTEGER_VALUE()) {
370
- return Number(ctx.INTEGER_VALUE().getText());
229
+ else if (ctxIntegerValue) {
230
+ result = Number(ctxIntegerValue.getText());
371
231
  }
372
- else if (ctx.STRING_VALUE()) {
373
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
232
+ else if (ctxStringValue) {
233
+ result = this.prepareStringValue(ctxStringValue.getText());
374
234
  }
375
- }
376
- visitData_expr_with_assignment(ctx) {
377
- let component;
378
- if (ctx.data_expr()) {
379
- component = this.visit(ctx.data_expr());
235
+ this.setResult(ctx, result);
236
+ };
237
+ visitData_expr_with_assignment = (ctx) => {
238
+ let component = null;
239
+ const ctxDataExpr = ctx.data_expr();
240
+ const ctxAssignmentExpr = ctx.assignment_expr();
241
+ if (ctxDataExpr) {
242
+ this.visit(ctxDataExpr);
243
+ component = this.getResult(ctxDataExpr);
380
244
  if (component === null || component === undefined) {
381
- throw "Could not find component: " + ctx.data_expr().getText();
382
- }
383
- }
384
- else if (ctx.assignment_expr()) {
385
- component = this.visit(ctx.assignment_expr());
245
+ throw "Could not find component: " + ctxDataExpr.getText();
246
+ }
247
+ }
248
+ else if (ctxAssignmentExpr) {
249
+ this.visit(ctxAssignmentExpr);
250
+ component = this.getResult(ctxAssignmentExpr);
251
+ }
252
+ if (component instanceof ClassComponent
253
+ && component.copyProp) {
254
+ component = this.getExecutor().copyComponent(component);
255
+ }
256
+ if (component && component instanceof ClassComponent) {
257
+ const modifiers = ctx.component_modifier_expr();
258
+ modifiers.forEach(modifier => {
259
+ const modifierText = modifier.ID(0).getText();
260
+ const ctxValueExpr = modifier.value_expr();
261
+ const ctxID2 = modifier.ID(1);
262
+ let result = null;
263
+ if (ctxValueExpr) {
264
+ this.visit(ctxValueExpr);
265
+ result = this.getResult(ctxValueExpr);
266
+ }
267
+ else if (ctxID2) {
268
+ result = ctxID2.getText();
269
+ }
270
+ if (modifierText === 'flip') {
271
+ const flipValue = result;
272
+ if (flipValue.indexOf('x') !== -1) {
273
+ component.setParam('flipX', 1);
274
+ }
275
+ if (flipValue.indexOf('y') !== -1) {
276
+ component.setParam('flipY', 1);
277
+ }
278
+ }
279
+ else if (modifierText === 'angle') {
280
+ const angleValue = Number(result);
281
+ component.setParam('angle', angleValue);
282
+ }
283
+ });
386
284
  }
387
285
  let pinValue = null;
388
- if (ctx.pin_select_expr()) {
389
- pinValue = this.visit(ctx.pin_select_expr());
286
+ const ctxPinSelectExpr = ctx.pin_select_expr();
287
+ if (ctxPinSelectExpr) {
288
+ this.visit(ctxPinSelectExpr);
289
+ pinValue = this.getResult(ctxPinSelectExpr);
390
290
  }
391
291
  else {
392
292
  pinValue = component.getDefaultPin();
393
293
  }
394
- return [component, pinValue];
395
- }
396
- visitValueAtomExpr(ctx) {
397
- let value;
398
- if (ctx.value_expr()) {
399
- value = this.visit(ctx.value_expr());
400
- }
401
- else if (ctx.atom_expr()) {
402
- const reference = this.visit(ctx.atom_expr());
403
- if (!reference.found) {
404
- value = new UndeclaredReference(reference);
405
- }
406
- else {
407
- value = reference.value;
408
- }
409
- }
410
- return value;
411
- }
412
- visitUnaryOperatorExpr(ctx) {
413
- const value = this.visit(ctx.data_expr());
294
+ this.setResult(ctx, [component, pinValue]);
295
+ };
296
+ visitUnaryOperatorExpr = (ctx) => {
297
+ this.visit(ctx.data_expr());
298
+ let value = this.getResult(ctx.data_expr());
414
299
  const unaryOp = ctx.unary_operator();
415
300
  if (unaryOp) {
416
301
  if (unaryOp.Not()) {
@@ -423,334 +308,269 @@ export class MainVisitor extends ParseTreeVisitor {
423
308
  }
424
309
  else if (unaryOp.Minus()) {
425
310
  if (typeof value === 'number') {
426
- return -value;
311
+ value = -value;
427
312
  }
428
313
  else {
429
314
  throw "Failed to do Negation operator";
430
315
  }
431
316
  }
432
317
  }
433
- return value;
434
- }
435
- visitDataExpr(ctx) {
318
+ this.setResult(ctx, value);
319
+ };
320
+ visitDataExpr = (ctx) => {
436
321
  let value;
437
- if (ctx.create_component_expr()) {
438
- value = this.visit(ctx.create_component_expr());
322
+ const ctxCreateComponentExpr = ctx.create_component_expr();
323
+ const ctxCreateGraphicExpr = ctx.create_graphic_expr();
324
+ if (ctxCreateComponentExpr) {
325
+ this.visit(ctxCreateComponentExpr);
326
+ value = this.getResult(ctxCreateComponentExpr);
439
327
  }
440
- else if (ctx.create_graphic_expr()) {
441
- value = this.visit(ctx.create_graphic_expr());
328
+ else if (ctxCreateGraphicExpr) {
329
+ this.visit(ctxCreateGraphicExpr);
330
+ value = this.getResult(ctxCreateGraphicExpr);
442
331
  }
443
- return value;
444
- }
445
- visitBinaryOperatorExpr(ctx) {
446
- const value1 = this.visit(ctx.data_expr(0));
447
- const value2 = this.visit(ctx.data_expr(1));
332
+ else {
333
+ throw "Invalid data expression";
334
+ }
335
+ this.setResult(ctx, value);
336
+ };
337
+ visitBinaryOperatorExpr = (ctx) => {
338
+ const ctx0 = ctx.data_expr(0);
339
+ const ctx1 = ctx.data_expr(1);
340
+ this.visit(ctx0);
341
+ this.visit(ctx1);
342
+ const value1 = this.getResult(ctx0);
343
+ const value2 = this.getResult(ctx1);
448
344
  const binaryOperatorType = ctx.binary_operator();
345
+ let result = null;
449
346
  if (binaryOperatorType.Equals()) {
450
- return value1 == value2;
347
+ result = value1 == value2;
451
348
  }
452
349
  else if (binaryOperatorType.NotEquals()) {
453
- return value1 != value2;
350
+ result = value1 != value2;
454
351
  }
455
- }
456
- visitMultiplyExpr(ctx) {
457
- const value1 = this.visit(ctx.data_expr(0));
458
- const value2 = this.visit(ctx.data_expr(1));
352
+ else if (binaryOperatorType.GreaterThan()) {
353
+ result = value1 > value2;
354
+ }
355
+ else if (binaryOperatorType.GreatOrEqualThan()) {
356
+ result = value1 >= value2;
357
+ }
358
+ else if (binaryOperatorType.LessThan()) {
359
+ result = value1 < value2;
360
+ }
361
+ else if (binaryOperatorType.LessOrEqualThan()) {
362
+ result = value1 <= value2;
363
+ }
364
+ this.setResult(ctx, result);
365
+ };
366
+ visitLogicalOperatorExpr = (ctx) => {
367
+ const ctx0 = ctx.data_expr(0);
368
+ const ctx1 = ctx.data_expr(1);
369
+ this.visit(ctx0);
370
+ const value1 = this.getResult(ctx0);
371
+ let value2 = false;
372
+ let skipNext = false;
373
+ if (ctx.LogicalOr() && value1) {
374
+ skipNext = true;
375
+ }
376
+ if (!skipNext) {
377
+ this.visit(ctx1);
378
+ value2 = this.getResult(ctx1);
379
+ }
380
+ let result = null;
381
+ if (ctx.LogicalAnd()) {
382
+ result = value1 && value2;
383
+ }
384
+ else if (ctx.LogicalOr()) {
385
+ result = value1 || value2;
386
+ }
387
+ this.setResult(ctx, result);
388
+ };
389
+ visitMultiplyExpr = (ctx) => {
390
+ this.visit(ctx.data_expr(0));
391
+ this.visit(ctx.data_expr(1));
392
+ const value1 = this.getResult(ctx.data_expr(0));
393
+ const value2 = this.getResult(ctx.data_expr(1));
394
+ let result = null;
459
395
  if (ctx.Multiply()) {
460
- return value1 * value2;
396
+ result = value1 * value2;
461
397
  }
462
398
  else if (ctx.Divide()) {
463
- return value1 / value2;
399
+ result = value1 / value2;
464
400
  }
465
- }
466
- visitAdditionExpr(ctx) {
467
- const value1 = this.visit(ctx.data_expr(0));
468
- const value2 = this.visit(ctx.data_expr(1));
401
+ this.setResult(ctx, result);
402
+ };
403
+ visitAdditionExpr = (ctx) => {
404
+ this.visit(ctx.data_expr(0));
405
+ this.visit(ctx.data_expr(1));
406
+ const value1 = this.getResult(ctx.data_expr(0));
407
+ const value2 = this.getResult(ctx.data_expr(1));
408
+ let result = null;
469
409
  if (ctx.Addition()) {
470
- return value1 + value2;
410
+ result = value1 + value2;
471
411
  }
472
412
  else if (ctx.Minus()) {
473
- return value1 - value2;
413
+ result = value1 - value2;
474
414
  }
475
- }
476
- visitFunction_args_expr(ctx) {
477
- const defaultValuesProvided = ctx.value_expr_list();
478
- const IDs = ctx.ID_list();
479
- const boundary = IDs.length - defaultValuesProvided.length;
480
- return IDs.map((id, index) => {
481
- if (index >= boundary) {
482
- const defaultValue = this.visit(defaultValuesProvided[index - boundary]);
483
- return [id.getText(), defaultValue];
484
- }
485
- else {
486
- return [id.getText()];
487
- }
488
- });
489
- }
490
- createNetResolver(executionStack) {
491
- const resolveNet = (netName, netNamespace) => {
492
- this.print('find net', netNamespace, netName);
493
- const reversed = [...executionStack].reverse();
494
- for (let i = 0; i < reversed.length; i++) {
495
- const context = reversed[i];
496
- const net = context.scope.getNetWithName(netName);
497
- if (net !== null && net.namespace === netNamespace) {
498
- return {
499
- found: true,
500
- net,
501
- };
502
- }
503
- }
504
- return {
505
- found: false
506
- };
507
- };
508
- return resolveNet;
509
- }
510
- visitFunction_def_expr(ctx) {
415
+ this.setResult(ctx, result);
416
+ };
417
+ visitFunction_def_expr = (ctx) => {
511
418
  const functionName = ctx.ID().getText();
512
419
  let funcDefinedParameters = [];
513
- if (ctx.function_args_expr()) {
514
- funcDefinedParameters = this.visit(ctx.function_args_expr());
420
+ const ctxFunctionArgsExpr = ctx.function_args_expr();
421
+ if (ctxFunctionArgsExpr) {
422
+ this.visit(ctxFunctionArgsExpr);
423
+ funcDefinedParameters = this.getResult(ctxFunctionArgsExpr);
515
424
  }
516
425
  const executionStack = this.executionStack;
517
426
  const functionCounter = { counter: 0 };
518
427
  const resolveNet = this.createNetResolver(this.executionStack);
519
428
  const __runFunc = (passedInParameters, options) => {
520
- const { netNamespace = "" } = options;
521
- const currentExecutionContext = executionStack[executionStack.length - 1];
522
- const executionLevel = currentExecutionContext.executionLevel;
523
429
  const executionContextName = functionName + '_' + functionCounter['counter'];
524
- const executionContextNamespace = currentExecutionContext.namespace
525
- + executionContextName + ".";
430
+ const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, options, funcDefinedParameters, passedInParameters);
526
431
  functionCounter['counter'] += 1;
527
- const newExecutor = new ExecutionContext(executionContextName, executionContextNamespace, netNamespace, executionLevel + 1, this.getExecutor().scope.indentLevel + 1, currentExecutionContext.silent, currentExecutionContext.logger);
528
- this.setupPrintFunction(newExecutor);
529
432
  newExecutor.resolveNet = resolveNet;
530
- executionStack.push(newExecutor);
531
- this.setupDefinedParameters(functionName, funcDefinedParameters, passedInParameters, newExecutor);
532
- const returnValue = this.runExpressions(newExecutor, ctx.function_expr_list());
433
+ const returnValue = this.runExpressions(newExecutor, ctx.function_expr());
533
434
  const lastExecution = executionStack.pop();
534
435
  const nextLastExecution = executionStack[executionStack.length - 1];
535
436
  nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
536
437
  return [lastExecution, returnValue];
537
438
  };
538
439
  this.getExecutor().createFunction(functionName, __runFunc);
539
- }
540
- setupDefinedParameters(functionName, funcDefinedParameters, passedInParameters, executor) {
541
- for (let i = 0; i < funcDefinedParameters.length; i++) {
542
- const tmpFuncArg = funcDefinedParameters[i];
543
- if (i < passedInParameters.length) {
544
- const tmpPassedInArgs = passedInParameters[i];
545
- if (tmpPassedInArgs[0] === 'position') {
546
- const variableName = tmpFuncArg[0];
547
- executor.print('set variable in scope, var name: ', variableName);
548
- executor.scope.variables.set(variableName, tmpPassedInArgs[2]);
549
- if (tmpPassedInArgs[2] instanceof ClassComponent) {
550
- const component = tmpPassedInArgs[2];
551
- for (const [pinNumber, net] of component.pinNets) {
552
- executor.scope.setNet(component, pinNumber, net);
553
- }
554
- }
555
- }
556
- }
557
- else if (tmpFuncArg.length === 2) {
558
- const variableName = tmpFuncArg[0];
559
- const defaultValue = tmpFuncArg[1];
560
- executor.print('set variable in scope, var name: ', variableName);
561
- executor.scope.variables.set(variableName, defaultValue);
562
- }
563
- else {
564
- throw `Invalid arguments for function '${functionName}', got: `
565
- + passedInParameters;
566
- }
567
- }
568
- }
569
- visitFunction_return_expr(ctx) {
570
- const executor = this.getExecutor();
571
- executor.print('return from function');
572
- const returnValue = this.visit(ctx.data_expr());
573
- executor.stopFurtherExpressions = true;
574
- executor.returnValue = returnValue;
575
- return returnValue;
576
- }
577
- visitAtom_expr(ctx) {
578
- const executor = this.getExecutor();
579
- const atomId = ctx.ID().getText();
580
- let passedNetNamespace = null;
581
- if (ctx.net_namespace_expr()) {
582
- passedNetNamespace = this.visit(ctx.net_namespace_expr());
583
- }
584
- let currentReference;
585
- if (this.pinTypesList.indexOf(atomId) !== -1) {
586
- currentReference = {
587
- found: true,
588
- value: atomId
589
- };
590
- }
591
- else {
592
- currentReference = executor.resolveVariable(this.executionStack, atomId);
593
- }
594
- if (currentReference.found && currentReference.type === 'instance') {
595
- const tmpComponent = currentReference.value;
596
- for (const [pinId, net] of tmpComponent.pinNets) {
597
- executor.scope.setNet(tmpComponent, pinId, net);
598
- }
599
- }
600
- if (ctx.trailer_expr_list().length > 0) {
601
- if (!currentReference.found) {
602
- throw "Could not find reference! " + atomId;
603
- }
604
- currentReference.trailers = [];
605
- ctx.trailer_expr_list().forEach(item => {
606
- const itemValue = item.getText();
607
- if (item.OPEN_PAREN() && item.CLOSE_PAREN()) {
608
- let parameters = [];
609
- if (item.parameters()) {
610
- parameters = this.visit(item.parameters());
611
- }
612
- const useNetNamespace = this.getNetNamespace(executor.netNamespace, passedNetNamespace);
613
- const [, functionResult] = executor.callFunction(currentReference.name, parameters, this.executionStack, useNetNamespace);
614
- currentReference = {
615
- found: true,
616
- value: functionResult,
617
- type: (functionResult instanceof ClassComponent) ?
618
- 'instance' : 'value',
619
- };
620
- }
621
- else {
622
- currentReference.trailers.push(itemValue);
623
- }
624
- });
625
- }
626
- return currentReference;
627
- }
628
- visitPin_select_expr2(ctx) {
629
- if (ctx.STRING_VALUE()) {
630
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
440
+ };
441
+ visitPin_select_expr2 = (ctx) => {
442
+ const ctxStringValue = ctx.STRING_VALUE();
443
+ const ctxIntegerValue = ctx.INTEGER_VALUE();
444
+ let result = null;
445
+ if (ctxStringValue) {
446
+ result = this.prepareStringValue(ctxStringValue.getText());
631
447
  }
632
- else if (ctx.INTEGER_VALUE()) {
633
- return Number(ctx.INTEGER_VALUE().getText());
448
+ else if (ctxIntegerValue) {
449
+ result = Number(ctxIntegerValue.getText());
634
450
  }
635
- }
636
- visitAt_block_pin_expr(ctx) {
637
- const atPin = this.visit(ctx.pin_select_expr2());
451
+ this.setResult(ctx, result);
452
+ };
453
+ visitAt_block_pin_expr = (ctx) => {
454
+ const ctxPinSelectExpr2 = ctx.pin_select_expr2();
455
+ this.visit(ctxPinSelectExpr2);
456
+ const atPin = this.getResult(ctxPinSelectExpr2);
638
457
  const executor = this.getExecutor();
639
458
  const currentComponent = executor.scope.currentComponent;
640
459
  const currentPin = executor.scope.currentPin;
641
460
  executor.atComponent(currentComponent, atPin, {
642
461
  addSequence: true
643
462
  });
644
- executor.print('at block pin expressions');
645
- if (ctx.at_block_pin_expression_simple()) {
646
- this.visit(ctx.at_block_pin_expression_simple());
463
+ executor.log('at block pin expressions');
464
+ const ctxAtBlockSimple = ctx.at_block_pin_expression_simple();
465
+ const ctxAtBlockComplex = ctx.at_block_pin_expression_complex();
466
+ if (ctxAtBlockSimple) {
467
+ this.visit(ctxAtBlockSimple);
647
468
  }
648
- else if (ctx.at_block_pin_expression_complex()) {
649
- this.visit(ctx.at_block_pin_expression_complex());
469
+ else if (ctxAtBlockComplex) {
470
+ this.visit(ctxAtBlockComplex);
650
471
  }
651
- executor.print('end at block pin expressions');
652
- return executor.atComponent(currentComponent, currentPin);
653
- }
654
- visitAt_block(ctx) {
472
+ executor.log('end at block pin expressions');
473
+ executor.atComponent(currentComponent, currentPin);
474
+ };
475
+ visitAt_block = (ctx) => {
655
476
  const executor = this.getExecutor();
656
- executor.print('entering at block');
477
+ executor.log('entering at block');
657
478
  this.visit(ctx.at_component_expr());
658
479
  const currentComponent = executor.scope.currentComponent;
659
480
  const currentPin = executor.scope.currentPin;
660
481
  executor.scope.indentLevel += 1;
661
- ctx.at_block_expressions_list().forEach(expression => {
482
+ ctx.at_block_expressions().forEach(expression => {
662
483
  this.visit(expression);
663
484
  });
664
485
  executor.scope.indentLevel -= 1;
665
486
  executor.scope.currentComponent = currentComponent;
666
487
  executor.scope.currentPin = currentPin;
667
- executor.print('leaving at block');
668
- return executor.getCurrentPoint();
669
- }
670
- visitAt_block_pin_expression_simple(ctx) {
671
- if (ctx.expression()) {
672
- this.visit(ctx.expression());
488
+ executor.log('leaving at block');
489
+ };
490
+ visitAt_block_pin_expression_simple = (ctx) => {
491
+ const ctxExpression = ctx.expression();
492
+ if (ctxExpression) {
493
+ this.visit(ctxExpression);
673
494
  }
674
495
  else if (ctx.NOT_CONNECTED()) {
675
496
  return;
676
497
  }
677
- }
678
- visitAt_block_pin_expression_complex(ctx) {
679
- ctx.expression_list().forEach(item => {
498
+ };
499
+ visitAt_block_pin_expression_complex = (ctx) => {
500
+ ctx.expression().forEach(item => {
680
501
  this.visit(item);
681
502
  });
682
- return this.getExecutor().getCurrentPoint();
683
- }
684
- visitWire_expr(ctx) {
685
- const segments = [];
686
- const parts = ctx.children.slice(1);
687
- for (let i = 0; i < parts.length; i++) {
688
- const textValue = parts[i].getText();
689
- if (this.acceptedDirections.indexOf(textValue) !== -1) {
690
- const segment = [textValue];
691
- let skipNext = false;
692
- let invalidValue = true;
693
- if (i + 1 < parts.length) {
694
- const nextValue = parts[i + 1].getText();
695
- const nextValueNumber = Number(nextValue);
696
- if (!isNaN(nextValueNumber)) {
697
- invalidValue = false;
698
- segment.push(nextValueNumber);
699
- skipNext = true;
700
- }
701
- }
702
- if (invalidValue) {
703
- throw `Invalid value provided for direction ${textValue} in wire`;
704
- }
705
- segments.push(segment);
706
- if (skipNext) {
707
- i += 1;
708
- }
503
+ };
504
+ visitWire_expr_direction_only = (ctx) => {
505
+ const value = ctx.ID().getText();
506
+ if (value === 'auto' || value === 'auto_') {
507
+ this.setResult(ctx, [value]);
508
+ }
509
+ else {
510
+ throw 'Invalid direction for wire';
511
+ }
512
+ };
513
+ visitWire_expr_direction_value = (ctx) => {
514
+ const direction = ctx.ID().getText();
515
+ if (this.acceptedDirections.indexOf(direction) !== -1) {
516
+ let useValue = null;
517
+ const ctxIntegerValue = ctx.INTEGER_VALUE();
518
+ const ctxDataExpr = ctx.data_expr();
519
+ if (ctxIntegerValue) {
520
+ useValue = Number(ctxIntegerValue);
521
+ }
522
+ else if (ctxDataExpr) {
523
+ this.visit(ctxDataExpr);
524
+ useValue = this.getResult(ctxDataExpr);
709
525
  }
710
- else if (textValue === "auto" || textValue === "auto_") {
711
- segments.push([textValue]);
526
+ if (useValue !== null) {
527
+ this.setResult(ctx, [direction, useValue]);
528
+ return;
712
529
  }
713
530
  }
531
+ throw "Invalid direction or value for wire";
532
+ };
533
+ visitWire_expr = (ctx) => {
534
+ const wireAtomExpr = ctx.wire_atom_expr();
535
+ const segments = wireAtomExpr.map(wireSegment => {
536
+ this.visit(wireSegment);
537
+ return this.getResult(wireSegment);
538
+ });
714
539
  this.getExecutor().addWire(segments);
715
- }
716
- visitPoint_expr(ctx) {
540
+ };
541
+ visitPoint_expr = (ctx) => {
717
542
  const ID = ctx.ID();
718
543
  return this.getExecutor().addPoint(ID.getText());
719
- }
720
- visitImport_expr(ctx) {
721
- const ID = ctx.ID().toString();
722
- this.print('import', ID);
723
- const { hasError, hasParseError } = this.onImportFile(this, ID);
724
- if (hasError || hasParseError) {
725
- this.print('import', ID, 'failed');
726
- throw `import ${ID} failed`;
727
- }
728
- this.print('done import', ID);
729
- }
730
- visitProperty_set_expr(ctx) {
731
- const result = this.visit(ctx.data_expr());
732
- const resolvedProperty = this.visit(ctx.atom_expr());
544
+ };
545
+ visitProperty_set_expr = (ctx) => {
546
+ const ctxDataExpr = ctx.data_expr();
547
+ this.visit(ctxDataExpr);
548
+ const result = this.getResult(ctxDataExpr);
549
+ const ctxAtomExpr = ctx.atom_expr();
550
+ this.visit(ctxAtomExpr);
551
+ const resolvedProperty = this.getResult(ctxAtomExpr);
733
552
  this.getExecutor().setProperty(resolvedProperty, result);
734
- }
735
- visitDouble_dot_property_set_expr(ctx) {
736
- const result = this.visit(ctx.data_expr());
553
+ };
554
+ visitDouble_dot_property_set_expr = (ctx) => {
555
+ const ctxDataExpr = ctx.data_expr();
556
+ this.visit(ctxDataExpr);
557
+ const result = this.getResult(ctxDataExpr);
737
558
  const propertyName = ctx.ID().getText();
738
559
  this.getExecutor().setProperty('..' + propertyName, result);
739
- }
740
- visitRoundedBracketsExpr(ctx) {
741
- return this.visit(ctx.data_expr());
742
- }
743
- visitFrame_expr(ctx) {
560
+ };
561
+ visitFrame_expr = (ctx) => {
744
562
  const frameId = this.getExecutor().enterFrame();
745
- this.runExpressions(this.getExecutor(), ctx.expression_list());
563
+ this.runExpressions(this.getExecutor(), ctx.expression());
746
564
  this.getExecutor().exitFrame(frameId);
747
- }
748
- visitNet_namespace_expr(ctx) {
565
+ };
566
+ visitNet_namespace_expr = (ctx) => {
749
567
  let dataValue = null;
750
568
  let netNamespace = null;
751
569
  const hasPlus = ctx.Addition();
752
- if (ctx.data_expr()) {
753
- dataValue = this.visit(ctx.data_expr());
570
+ const ctxDataExpr = ctx.data_expr();
571
+ if (ctxDataExpr) {
572
+ this.visit(ctxDataExpr);
573
+ dataValue = this.getResult(ctxDataExpr);
754
574
  if (dataValue instanceof UndeclaredReference) {
755
575
  netNamespace = "/" + dataValue.reference.name;
756
576
  }
@@ -764,8 +584,44 @@ export class MainVisitor extends ParseTreeVisitor {
764
584
  else {
765
585
  netNamespace = "/";
766
586
  }
767
- return (hasPlus ? "+" : "") + netNamespace;
768
- }
587
+ this.setResult(ctx, (hasPlus ? "+" : "") + netNamespace);
588
+ };
589
+ visitIf_expr = (ctx) => {
590
+ const ctxDataExpr = ctx.data_expr();
591
+ this.visit(ctxDataExpr);
592
+ const result = this.getResult(ctxDataExpr);
593
+ if (result) {
594
+ this.runExpressions(this.getExecutor(), ctx.expression());
595
+ }
596
+ else {
597
+ const ctxInnerIfExprs = ctx.if_inner_expr();
598
+ let innerIfWasTrue = false;
599
+ for (let i = 0; i < ctxInnerIfExprs.length; i++) {
600
+ const tmpCtx = ctxInnerIfExprs[i];
601
+ this.visit(tmpCtx);
602
+ const innerResult = this.getResult(tmpCtx);
603
+ if (innerResult) {
604
+ innerIfWasTrue = true;
605
+ break;
606
+ }
607
+ }
608
+ if (!innerIfWasTrue) {
609
+ const elseCtx = ctx.else_expr();
610
+ if (elseCtx) {
611
+ this.visit(elseCtx);
612
+ }
613
+ }
614
+ }
615
+ };
616
+ visitIf_inner_expr = (ctx) => {
617
+ const ctxDataExpr = ctx.data_expr();
618
+ this.visit(ctxDataExpr);
619
+ const result = this.getResult(ctxDataExpr);
620
+ if (result) {
621
+ this.runExpressions(this.getExecutor(), ctx.expression());
622
+ }
623
+ this.setResult(ctx, result);
624
+ };
769
625
  pinTypes = [
770
626
  PinTypes.Any,
771
627
  PinTypes.IO,
@@ -773,44 +629,6 @@ export class MainVisitor extends ParseTreeVisitor {
773
629
  PinTypes.Output,
774
630
  PinTypes.Power,
775
631
  ];
776
- createImportFileHandler(directory, defaultLibsPath) {
777
- return (visitor, importPath) => {
778
- let importResult;
779
- importResult = this.importLib(visitor, directory, importPath);
780
- if (!importResult.pathExists && importPath == 'lib') {
781
- importResult = this.importLib(visitor, defaultLibsPath, importPath);
782
- }
783
- return importResult;
784
- };
785
- }
786
- importLib(visitor, directory, filename) {
787
- const tmpFilePath = join(directory, filename + ".cst");
788
- visitor.print('importing path:', tmpFilePath);
789
- let pathExists = false;
790
- let fileData = null;
791
- try {
792
- fileData = readFileSync(tmpFilePath, { encoding: 'utf8' });
793
- pathExists = true;
794
- }
795
- catch (err) {
796
- pathExists = false;
797
- }
798
- try {
799
- if (pathExists) {
800
- visitor.print('done reading imported file data');
801
- const { hasError, hasParseError } = parseFileWithVisitor(visitor, fileData);
802
- return { hasError, hasParseError, pathExists };
803
- }
804
- }
805
- catch (err) {
806
- visitor.print('Failed to import file: ', err.message);
807
- }
808
- return {
809
- hasError: true,
810
- hasParseError: true,
811
- pathExists,
812
- };
813
- }
814
632
  parseCreateComponentPins(pinData) {
815
633
  const pins = [];
816
634
  if (typeof pinData === 'number') {
@@ -831,8 +649,10 @@ export class MainVisitor extends ParseTreeVisitor {
831
649
  }
832
650
  if (Array.isArray(pinDef)) {
833
651
  const firstValue = pinDef[0];
834
- if (this.pinTypes.indexOf(firstValue) !== -1) {
835
- pinType = firstValue;
652
+ if (firstValue.type
653
+ && firstValue.type === ReferenceTypes.pinType
654
+ && this.pinTypes.indexOf(firstValue.value) !== -1) {
655
+ pinType = firstValue.value;
836
656
  pinName = pinDef[1];
837
657
  if (pinDef.length > 2) {
838
658
  altPinNames = pinDef.slice(2);
@@ -862,18 +682,6 @@ export class MainVisitor extends ParseTreeVisitor {
862
682
  }
863
683
  return result;
864
684
  }
865
- prepareStringValue(value) {
866
- return value.slice(1, value.length - 1);
867
- }
868
- print(...params) {
869
- const indentOutput = ''.padStart(this.indentLevel * 4, ' ');
870
- const indentLevelText = this.indentLevel.toString().padStart(3, ' ');
871
- const args = ['[' + indentLevelText + ']', indentOutput, ...params];
872
- this.logger.add(args.join(' '));
873
- if (!this.silent) {
874
- console.log.apply(null, args);
875
- }
876
- }
877
685
  printNets() {
878
686
  this.getExecutor().scope.printNets();
879
687
  }
@@ -935,7 +743,10 @@ export class MainVisitor extends ParseTreeVisitor {
935
743
  }
936
744
  getGraph() {
937
745
  const executor = this.getExecutor();
938
- const sequence = executor.scope.sequence;
746
+ const fullSequence = executor.scope.sequence;
747
+ const tmpNet = executor.scope.getNet(executor.scope.componentRoot, 1);
748
+ const sequence = (tmpNet === null)
749
+ ? fullSequence.slice(1) : fullSequence;
939
750
  const nets = executor.scope.getNets();
940
751
  return {
941
752
  sequence,
@@ -944,7 +755,7 @@ export class MainVisitor extends ParseTreeVisitor {
944
755
  };
945
756
  }
946
757
  annotateComponents() {
947
- this.print('===== annotate components =====');
758
+ this.log('===== annotate components =====');
948
759
  const annotater = new ComponentAnnotater();
949
760
  const instances = this.getExecutor().scope.instances;
950
761
  const toAnnotate = [];
@@ -956,7 +767,7 @@ export class MainVisitor extends ParseTreeVisitor {
956
767
  continue;
957
768
  }
958
769
  if (instance.typeProp === null) {
959
- this.print('Instance has no type:', instance.instanceName, ' assuming connector');
770
+ this.log('Instance has no type:', instance.instanceName, ' assuming connector');
960
771
  instance.typeProp = 'conn';
961
772
  }
962
773
  if (instance.parameters.has('refdes')) {
@@ -964,7 +775,7 @@ export class MainVisitor extends ParseTreeVisitor {
964
775
  if (refdes) {
965
776
  instance.assignedRefDes = refdes;
966
777
  annotater.trackRefDes(refdes);
967
- this.print(refdes, '-', instance.instanceName);
778
+ this.log(refdes, '-', instance.instanceName);
968
779
  continue;
969
780
  }
970
781
  }
@@ -975,14 +786,14 @@ export class MainVisitor extends ParseTreeVisitor {
975
786
  const newRefDes = annotater.getAnnotation(instance.typeProp);
976
787
  if (newRefDes !== null) {
977
788
  instance.assignedRefDes = newRefDes;
978
- this.print(newRefDes, '-', instance.instanceName);
789
+ this.log(newRefDes, '-', instance.instanceName);
979
790
  }
980
791
  else {
981
- this.print('Failed to annotate:', instance.instanceName);
792
+ this.log('Failed to annotate:', instance.instanceName);
982
793
  }
983
794
  });
984
- this.print('===== annotate done =====');
985
- this.print('');
795
+ this.log('===== annotate done =====');
796
+ this.log('');
986
797
  }
987
798
  resolveNets(scope, instance) {
988
799
  const result = [];
@@ -1011,61 +822,22 @@ export class MainVisitor extends ParseTreeVisitor {
1011
822
  throw "Invalid modifier for orientation";
1012
823
  }
1013
824
  }
825
+ setComponentFlip(component, flipValue) {
826
+ if (this.acceptedFlip.indexOf(flipValue) !== -1) {
827
+ component.setParam(flipValue, 1);
828
+ }
829
+ }
1014
830
  getPropertyExprList(items) {
1015
831
  const properties = new Map();
1016
832
  items.forEach((item) => {
1017
- const result = this.visit(item);
833
+ this.visit(item);
834
+ const result = this.getResult(item);
1018
835
  for (const [key, value] of result) {
1019
836
  properties.set(key, value);
1020
837
  }
1021
838
  });
1022
839
  return properties;
1023
840
  }
1024
- runExpressions(executor, expressions) {
1025
- let returnValue = null;
1026
- for (let i = 0; i < expressions.length; i++) {
1027
- const expr = expressions[i];
1028
- this.visit(expr);
1029
- if (executor.stopFurtherExpressions) {
1030
- returnValue = executor.returnValue;
1031
- break;
1032
- }
1033
- }
1034
- return returnValue;
1035
- }
1036
- setupPrintFunction(context) {
1037
- context.createFunction('print', (params) => {
1038
- const items = params.map(([, , value]) => {
1039
- return value;
1040
- });
1041
- if (this.printToConsole) {
1042
- console.log('::', ...items);
1043
- }
1044
- this.printStream.push(...items);
1045
- return [this, null];
1046
- });
1047
- }
1048
- getNetNamespace(executorNetNamespace, passedNetNamespace) {
1049
- let result = executorNetNamespace;
1050
- if (passedNetNamespace !== null && passedNetNamespace.length > 0) {
1051
- if (passedNetNamespace === '/' || passedNetNamespace === '_') {
1052
- result = '';
1053
- }
1054
- else if (passedNetNamespace[0] === '+') {
1055
- if (executorNetNamespace === '/') {
1056
- result = passedNetNamespace.slice(1);
1057
- }
1058
- else {
1059
- result = executorNetNamespace + passedNetNamespace.slice(2);
1060
- }
1061
- }
1062
- else {
1063
- result = passedNetNamespace;
1064
- }
1065
- result = result + '/';
1066
- }
1067
- return result;
1068
- }
1069
841
  }
1070
842
  const ComponentRefDesPrefixes = {
1071
843
  'res': 'R',