circuitscript 0.1.11 → 0.1.13

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 (46) hide show
  1. package/dist/cjs/BaseVisitor.js +147 -115
  2. package/dist/cjs/antlr/CircuitScriptParser.js +949 -932
  3. package/dist/cjs/builtinMethods.js +7 -1
  4. package/dist/cjs/execute.js +67 -35
  5. package/dist/cjs/globals.js +7 -1
  6. package/dist/cjs/helpers.js +11 -8
  7. package/dist/cjs/layout.js +50 -16
  8. package/dist/cjs/objects/ExecutionScope.js +3 -0
  9. package/dist/cjs/objects/Net.js +1 -0
  10. package/dist/cjs/objects/ParamDefinition.js +3 -0
  11. package/dist/cjs/objects/types.js +19 -10
  12. package/dist/cjs/parser.js +3 -1
  13. package/dist/cjs/render.js +48 -6
  14. package/dist/cjs/utils.js +16 -1
  15. package/dist/cjs/visitor.js +69 -52
  16. package/dist/esm/BaseVisitor.js +113 -81
  17. package/dist/esm/antlr/CircuitScriptParser.js +943 -926
  18. package/dist/esm/antlr/CircuitScriptVisitor.js +4 -4
  19. package/dist/esm/builtinMethods.js +8 -2
  20. package/dist/esm/execute.js +68 -36
  21. package/dist/esm/globals.js +6 -0
  22. package/dist/esm/helpers.js +11 -8
  23. package/dist/esm/layout.js +53 -17
  24. package/dist/esm/objects/ExecutionScope.js +3 -0
  25. package/dist/esm/objects/Net.js +1 -0
  26. package/dist/esm/objects/ParamDefinition.js +4 -1
  27. package/dist/esm/objects/types.js +21 -15
  28. package/dist/esm/parser.js +3 -1
  29. package/dist/esm/render.js +49 -7
  30. package/dist/esm/utils.js +13 -0
  31. package/dist/esm/visitor.js +57 -40
  32. package/dist/types/BaseVisitor.d.ts +5 -6
  33. package/dist/types/antlr/CircuitScriptParser.d.ts +58 -58
  34. package/dist/types/antlr/CircuitScriptVisitor.d.ts +8 -8
  35. package/dist/types/execute.d.ts +4 -2
  36. package/dist/types/globals.d.ts +5 -0
  37. package/dist/types/layout.d.ts +16 -3
  38. package/dist/types/objects/ExecutionScope.d.ts +15 -3
  39. package/dist/types/objects/Net.d.ts +1 -0
  40. package/dist/types/objects/types.d.ts +25 -18
  41. package/dist/types/parser.d.ts +1 -0
  42. package/dist/types/utils.d.ts +3 -1
  43. package/dist/types/visitor.d.ts +3 -2
  44. package/package.json +1 -1
  45. /package/dist/libs/{lib.cst → std.cst} +0 -0
  46. /package/libs/{lib.cst → std.cst} +0 -0
@@ -7,9 +7,10 @@ const PinDefinition_js_1 = require("./objects/PinDefinition.js");
7
7
  const PinTypes_js_1 = require("./objects/PinTypes.js");
8
8
  const types_js_1 = require("./objects/types.js");
9
9
  const globals_js_1 = require("./globals.js");
10
+ const utils_js_1 = require("./utils.js");
10
11
  const draw_symbols_js_1 = require("./draw_symbols.js");
11
12
  const BaseVisitor_js_1 = require("./BaseVisitor.js");
12
- const utils_js_1 = require("./utils.js");
13
+ const utils_js_2 = require("./utils.js");
13
14
  const helpers_js_1 = require("./helpers.js");
14
15
  const Frame_js_1 = require("./objects/Frame.js");
15
16
  class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
@@ -31,7 +32,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
31
32
  value = result;
32
33
  }
33
34
  else {
34
- throw new utils_js_1.RuntimeExecutionError("Invalid value for pin", ctx);
35
+ throw new utils_js_2.RuntimeExecutionError("Invalid value for pin", ctx);
35
36
  }
36
37
  this.setResult(ctx, value);
37
38
  };
@@ -55,7 +56,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
55
56
  });
56
57
  }
57
58
  catch (err) {
58
- throw new utils_js_1.RuntimeExecutionError(err.message, ctx);
59
+ throw new utils_js_2.RuntimeExecutionError(err.message, ctx);
59
60
  }
60
61
  });
61
62
  return this.getExecutor().getCurrentPoint();
@@ -87,39 +88,55 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
87
88
  }
88
89
  this.setResult(ctx, componentPin);
89
90
  };
90
- this.visitPath_blocks = (ctx) => {
91
- const blocks = ctx.path_block_inner();
92
- let blockIndex = 0;
91
+ this.visitPath_block = (ctx) => {
93
92
  let blockType = globals_js_1.BlockTypes.Branch;
94
- let prevBlockType = null;
95
- blocks.forEach((block, index) => {
96
- if (block.Branch()) {
97
- blockType = globals_js_1.BlockTypes.Branch;
98
- }
99
- else if (block.Join()) {
100
- blockType = globals_js_1.BlockTypes.Join;
101
- }
102
- else if (block.Parallel()) {
103
- blockType = globals_js_1.BlockTypes.Parallel;
104
- }
105
- else if (block.Point()) {
106
- blockType = globals_js_1.BlockTypes.Point;
93
+ if (ctx.Branch()) {
94
+ blockType = globals_js_1.BlockTypes.Branch;
95
+ }
96
+ else if (ctx.Join()) {
97
+ blockType = globals_js_1.BlockTypes.Join;
98
+ }
99
+ else if (ctx.Parallel()) {
100
+ blockType = globals_js_1.BlockTypes.Parallel;
101
+ }
102
+ else if (ctx.Point()) {
103
+ blockType = globals_js_1.BlockTypes.Point;
104
+ }
105
+ const scope = this.getScope();
106
+ const executor = this.getExecutor();
107
+ const indentLevel = scope.indentLevel;
108
+ if (scope.blockStack.has(indentLevel)) {
109
+ const blockStackEntry = scope.blockStack.get(indentLevel);
110
+ if (blockStackEntry.type !== blockType) {
111
+ executor.exitBlocks();
107
112
  }
108
- if (prevBlockType !== blockType) {
109
- if (index > 0) {
110
- this.getExecutor().exitBlocks();
111
- }
112
- this.getExecutor().enterBlocks(blockType);
113
- blockIndex = 0;
113
+ }
114
+ if (!scope.blockStack.has(indentLevel)) {
115
+ executor.enterBlocks(blockType);
116
+ }
117
+ const blockStackEntry = scope.blockStack.get(indentLevel);
118
+ const { current_index } = blockStackEntry;
119
+ executor.enterBlock(current_index);
120
+ this.visit(ctx.expressions_block());
121
+ executor.exitBlock(current_index);
122
+ blockStackEntry.current_index++;
123
+ };
124
+ this.visitGraph_expressions = (ctx) => {
125
+ if (ctx.path_block() === null) {
126
+ const scope = this.getScope();
127
+ const indentLevel = scope.indentLevel;
128
+ if (scope.blockStack.has(indentLevel)) {
129
+ this.getExecutor().exitBlocks();
114
130
  }
115
- this.getExecutor().enterBlock(blockIndex);
116
- this.visit(block);
117
- this.getExecutor().exitBlock(blockIndex);
118
- blockIndex += 1;
119
- prevBlockType = blockType;
120
- });
121
- this.getExecutor().exitBlocks();
122
- return this.getExecutor().getCurrentPoint();
131
+ }
132
+ const ctxPathBlock = ctx.path_block();
133
+ const ctxNotPathBlock = ctx.graph_linear_expression();
134
+ if (ctxPathBlock) {
135
+ this.visit(ctxPathBlock);
136
+ }
137
+ if (ctxNotPathBlock) {
138
+ this.visit(ctxNotPathBlock);
139
+ }
123
140
  };
124
141
  this.visitCreate_component_expr = (ctx) => {
125
142
  const scope = this.getScope();
@@ -155,13 +172,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
155
172
  break;
156
173
  case 'display':
157
174
  if (didDefineArrangeProp) {
158
- throw new utils_js_1.RuntimeExecutionError("arrange property has already been defined", ctx);
175
+ throw new utils_js_2.RuntimeExecutionError("arrange property has already been defined", ctx);
159
176
  }
160
177
  didDefineDisplayProp = true;
161
178
  break;
162
179
  case 'arrange':
163
180
  if (didDefineDisplayProp) {
164
- throw new utils_js_1.RuntimeExecutionError("display property already defined", ctx);
181
+ throw new utils_js_2.RuntimeExecutionError("display property already defined", ctx);
165
182
  }
166
183
  didDefineArrangeProp = true;
167
184
  break;
@@ -182,7 +199,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
182
199
  this.validateBoolean(value, ctx);
183
200
  }
184
201
  else {
185
- throw new utils_js_1.RuntimeExecutionError("Invalid value for 'copy' property", ctx);
202
+ throw new utils_js_2.RuntimeExecutionError("Invalid value for 'copy' property", ctx);
186
203
  }
187
204
  break;
188
205
  }
@@ -192,7 +209,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
192
209
  if (keyName === 'arrange') {
193
210
  const [sideKeyCtx, sideKeyName] = path[1];
194
211
  if (globals_js_1.ValidPinSides.indexOf(sideKeyName) === -1) {
195
- throw new utils_js_1.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx);
212
+ throw new utils_js_2.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx);
196
213
  }
197
214
  else {
198
215
  if (path.length === 2 && value instanceof ParamDefinition_js_1.NumericValue) {
@@ -203,12 +220,12 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
203
220
  const goodBlank = value.length === 1 &&
204
221
  value[0] instanceof ParamDefinition_js_1.NumericValue;
205
222
  if (!goodBlank) {
206
- throw new utils_js_1.RuntimeExecutionError(`Invalid blank specifier`, ctx);
223
+ throw new utils_js_2.RuntimeExecutionError(`Invalid blank specifier`, ctx);
207
224
  }
208
225
  }
209
226
  else {
210
227
  if (!(value instanceof ParamDefinition_js_1.NumericValue)) {
211
- throw new utils_js_1.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx);
228
+ throw new utils_js_2.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx);
212
229
  }
213
230
  else {
214
231
  checkPinExistsAndNotDuplicated(value.toNumber(), ctx);
@@ -237,7 +254,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
237
254
  if (value.length === 2) {
238
255
  const [pinType,] = value;
239
256
  if (pinType instanceof types_js_1.UndeclaredReference) {
240
- throw new utils_js_1.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx);
257
+ throw new utils_js_2.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx);
241
258
  }
242
259
  }
243
260
  }
@@ -298,7 +315,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
298
315
  if (ctxId !== null) {
299
316
  const varName = ctxId.getText();
300
317
  paramIds.push(varName);
301
- this.getScope().variables.set(varName, {});
318
+ this.getScope().setVariable(varName, {});
302
319
  }
303
320
  const executor = this.getExecutor();
304
321
  const stack = [...this.executionStack];
@@ -308,7 +325,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
308
325
  variables.forEach((value, key) => {
309
326
  obj[key] = value;
310
327
  });
311
- executor.scope.variables.set(paramIds[0], obj);
328
+ executor.scope.setVariable(paramIds[0], obj);
312
329
  }
313
330
  const currentStack = this.executionStack.splice(0);
314
331
  this.executionStack.push(...stack);
@@ -389,7 +406,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
389
406
  };
390
407
  this.visitGraphicForExpr = (ctx) => {
391
408
  const forVariableNames = ctx.ID().map(item => item.getText());
392
- const listItems = this.visitResult(ctx.data_expr());
409
+ const listItems = (0, utils_js_1.unwrapValue)(this.visitResult(ctx.data_expr()));
393
410
  let keepLooping = true;
394
411
  let counter = 0;
395
412
  let allCommands = [];
@@ -400,7 +417,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
400
417
  useValueArray = [useValueArray];
401
418
  }
402
419
  useValueArray.forEach((value, index) => {
403
- this.getScope().variables.set(forVariableNames[index], value);
420
+ this.getScope().setVariable(forVariableNames[index], value);
404
421
  });
405
422
  const commands = this.visitResult(ctx.graphic_expressions_block());
406
423
  allCommands = allCommands.concat(commands);
@@ -531,6 +548,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
531
548
  const ctxAssignmentExpr = ctx.assignment_expr();
532
549
  if (ctxDataExpr) {
533
550
  component = this.visitResult(ctxDataExpr);
551
+ component = (0, utils_js_1.unwrapValue)(component);
534
552
  componentCtx = ctxDataExpr;
535
553
  if (component === null || component === undefined) {
536
554
  this.throwWithContext(ctxDataExpr, "Could not find component: " + ctxDataExpr.getText());
@@ -822,15 +840,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
822
840
  const executor = this.getExecutor();
823
841
  executor.log('entering at block');
824
842
  this.visit(ctx.at_component_expr());
825
- const currentComponent = executor.scope.currentComponent;
826
- const currentPin = executor.scope.currentPin;
843
+ const [currentComponent, currentPin] = executor.getCurrentPoint();
827
844
  executor.scope.indentLevel += 1;
828
845
  ctx.at_block_expressions().forEach(expression => {
829
846
  this.visit(expression);
830
847
  });
831
848
  executor.scope.indentLevel -= 1;
832
- executor.scope.currentComponent = currentComponent;
833
- executor.scope.currentPin = currentPin;
849
+ executor.scope.setCurrent(currentComponent, currentPin);
834
850
  executor.log('leaving at block');
835
851
  };
836
852
  this.visitAt_block_pin_expression_simple = (ctx) => {
@@ -893,7 +909,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
893
909
  pointValue = resultValue;
894
910
  }
895
911
  else {
896
- throw new utils_js_1.RuntimeExecutionError('Invalid value for point');
912
+ throw new utils_js_2.RuntimeExecutionError('Invalid value for point');
897
913
  }
898
914
  }
899
915
  else if (ID) {
@@ -1012,7 +1028,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1012
1028
  this.visitFor_expr = (ctx) => {
1013
1029
  this.log('in for loop');
1014
1030
  const forVariableNames = ctx.ID().map(item => item.getText());
1015
- const listItems = this.visitResult(ctx.data_expr());
1031
+ let listItems = this.visitResult(ctx.data_expr());
1032
+ listItems = (0, utils_js_1.unwrapValue)(listItems);
1016
1033
  this.getExecutor().addBreakContext(ctx);
1017
1034
  let keepLooping = true;
1018
1035
  let counter = 0;
@@ -1023,7 +1040,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1023
1040
  useValueArray = [useValueArray];
1024
1041
  }
1025
1042
  useValueArray.forEach((value, index) => {
1026
- this.getScope().variables.set(forVariableNames[index], value);
1043
+ this.getScope().setVariable(forVariableNames[index], value);
1027
1044
  });
1028
1045
  this.visit(ctx.expressions_block());
1029
1046
  keepLooping = true;
@@ -1088,7 +1105,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1088
1105
  const portName = component.parameters.get(globals_js_1.ParamKeys.net_name);
1089
1106
  const modulePinId = modulePinMapping.get(portName);
1090
1107
  pinIdToPortMap.set(modulePinId, component);
1091
- const portType = (0, utils_js_1.getPortType)(component);
1108
+ const portType = (0, utils_js_2.getPortType)(component);
1092
1109
  const tmpPin = moduleComponent.pins.get(modulePinId);
1093
1110
  tmpPin.pinType = portType;
1094
1111
  }
@@ -6,8 +6,9 @@ import { Logger } from "./logger.js";
6
6
  import { ClassComponent } from "./objects/ClassComponent.js";
7
7
  import { NumberOperator, NumericValue, PercentageValue } from "./objects/ParamDefinition.js";
8
8
  import { PinTypes } from "./objects/PinTypes.js";
9
- import { Direction, UndeclaredReference } from "./objects/types.js";
10
- import { DoubleDelimiter1, GlobalDocumentName, ReferenceTypes } from './globals.js';
9
+ import { Direction, AnyReference, UndeclaredReference } from "./objects/types.js";
10
+ import { ComponentTypes, DoubleDelimiter1, GlobalDocumentName, ReferenceTypes } from './globals.js';
11
+ import { isReference, unwrapValue as unwrapValue } from "./utils.js";
11
12
  import { linkBuiltInMethods } from './builtinMethods.js';
12
13
  import { resolveToNumericValue, RuntimeExecutionError, throwWithContext } from './utils.js';
13
14
  import { SequenceAction } from './objects/ExecutionScope.js';
@@ -22,7 +23,6 @@ export class BaseVisitor extends CircuitScriptVisitor {
22
23
  acceptedDirections = [Direction.Up, Direction.Down,
23
24
  Direction.Right, Direction.Left];
24
25
  resultData = new Map;
25
- paramData = new Map;
26
26
  pinTypesList = [
27
27
  PinTypes.Any,
28
28
  PinTypes.Input,
@@ -47,7 +47,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
47
47
  scope.sequence.push([
48
48
  SequenceAction.At, scope.componentRoot, scope.currentPin
49
49
  ]);
50
- scope.variables.set(GlobalDocumentName, {});
50
+ scope.setVariable(GlobalDocumentName, {});
51
51
  this.setupBuiltInFunctions(this.startingContext);
52
52
  this.executionStack = [this.startingContext];
53
53
  this.startingContext.resolveNet =
@@ -127,43 +127,65 @@ export class BaseVisitor extends CircuitScriptVisitor {
127
127
  }
128
128
  const result = this.runExpressions(this.getExecutor(), ctx.expression());
129
129
  this.setResult(ctx, result);
130
+ this.getExecutor().closeAllBlocks();
130
131
  this.log('===', 'end', '===');
131
132
  };
132
133
  visitAssignment_expr = (ctx) => {
133
- const reference = this.getReference(ctx.atom_expr());
134
- const ctxDataExpr = ctx.data_expr();
135
- this.visit(ctxDataExpr);
136
- const value = this.getResult(ctxDataExpr);
137
- const trailers = reference.trailers ?? [];
134
+ const ctxAtom = ctx.atom_expr();
135
+ const ctxFuncCallRef = ctx.function_call_expr();
136
+ let leftSideReference;
137
+ if (ctxAtom) {
138
+ leftSideReference = this.getReference(ctx.atom_expr());
139
+ }
140
+ else if (ctxFuncCallRef) {
141
+ this.setResult(ctxFuncCallRef, { keepReference: true });
142
+ leftSideReference = this.visitResult(ctxFuncCallRef);
143
+ }
144
+ const rhsCtxResult = this.visitResult(ctx.data_expr());
145
+ const rhsValue = unwrapValue(rhsCtxResult);
146
+ const trailers = leftSideReference.trailers ?? [];
147
+ const sequenceParts = [];
138
148
  if (trailers.length === 0) {
139
- if (value instanceof ClassComponent) {
140
- const variables = this.getExecutor().scope.variables;
141
- variables.set(reference.name, value);
142
- this.getExecutor().scope.sequence.push([SequenceAction.Assign, reference.name, value]);
143
- this.log2(`assigned '${reference.name}' to ClassComponent`);
149
+ if (rhsValue instanceof ClassComponent) {
150
+ this.getScope().setVariable(leftSideReference.name, rhsValue);
151
+ sequenceParts.push(...['instance', leftSideReference.name, rhsValue]);
152
+ this.log2(`assigned '${leftSideReference.name}' to ClassComponent`);
144
153
  }
145
154
  else {
146
- this.getExecutor().scope.variables.set(reference.name, value);
147
- this.log2(`assigned variable ${reference.name} to ${value}`);
155
+ this.getScope().setVariable(leftSideReference.name, rhsValue);
156
+ this.log2(`assigned variable ${leftSideReference.name} to ${rhsValue}`);
157
+ sequenceParts.push(...['variable', leftSideReference.name, rhsValue]);
148
158
  }
149
159
  }
150
160
  else {
151
- if (reference.parentValue instanceof ClassComponent) {
152
- this.setInstanceParam(reference.parentValue, trailers, value);
153
- this.log2(`assigned component param ${reference.parentValue} trailers: ${trailers} value: ${value}`);
161
+ if (leftSideReference.parentValue instanceof ClassComponent) {
162
+ this.setInstanceParam(leftSideReference.parentValue, trailers, rhsValue);
163
+ this.log2(`assigned component param ${leftSideReference.parentValue} trailers: ${trailers} value: ${rhsValue}`);
164
+ sequenceParts.push(...['instance', [leftSideReference.parentValue, trailers], rhsValue]);
165
+ if (leftSideReference.parentValue.typeProp === ComponentTypes.net) {
166
+ const net = this.getScope().getNet(leftSideReference.parentValue, 1);
167
+ if (net) {
168
+ const trailerValue = trailers.join(".");
169
+ net.params.set(trailerValue, rhsValue);
170
+ }
171
+ }
154
172
  }
155
- else if (reference.parentValue instanceof Object) {
156
- reference.parentValue[trailers.join('.')] = value;
157
- this.log2(`assigned object ${reference.parentValue} trailers: ${trailers} value: ${value}`);
173
+ else if (leftSideReference.parentValue instanceof Object) {
174
+ leftSideReference.parentValue[trailers.join('.')] = rhsValue;
175
+ this.log2(`assigned object ${leftSideReference.parentValue} trailers: ${trailers} value: ${rhsValue}`);
176
+ sequenceParts.push(...['variable', [leftSideReference.parentValue, trailers], rhsValue]);
158
177
  }
159
178
  }
160
- this.setResult(ctx, value);
179
+ if (sequenceParts.length > 0) {
180
+ this.getScope().sequence.push([
181
+ SequenceAction.Assign, ...sequenceParts
182
+ ]);
183
+ }
184
+ this.setResult(ctx, rhsValue);
161
185
  };
162
186
  visitOperator_assignment_expr = (ctx) => {
163
187
  const reference = this.getReference(ctx.atom_expr());
164
- const ctxDataExpr = ctx.data_expr();
165
- this.visit(ctxDataExpr);
166
- const value = this.getResult(ctxDataExpr);
188
+ const value = this.visitResult(ctx.data_expr());
167
189
  if (!reference.found) {
168
190
  this.throwWithContext(ctx, 'Undefined reference: ' + reference.name);
169
191
  }
@@ -204,7 +226,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
204
226
  this.throwWithContext(ctx, 'Operator assignment failed: could not perform operator');
205
227
  }
206
228
  if (trailers.length === 0) {
207
- this.getExecutor().scope.variables.set(reference.name, newValue);
229
+ this.getExecutor().scope.setVariable(reference.name, newValue);
208
230
  }
209
231
  else {
210
232
  if (reference.value instanceof ClassComponent) {
@@ -221,8 +243,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
221
243
  if (atomStr.indexOf('(') !== -1 || atomStr.indexOf(')') !== -1) {
222
244
  this.throwWithContext(ctx, "Invalid assignment expression!");
223
245
  }
224
- this.visit(ctx);
225
- const reference = this.getResult(ctx);
246
+ const reference = this.visitResult(ctx);
226
247
  const { trailers = [] } = reference;
227
248
  const undefinedParentWithTrailers = trailers.length > 0
228
249
  && reference.parentValue === undefined;
@@ -245,11 +266,11 @@ export class BaseVisitor extends CircuitScriptVisitor {
245
266
  }
246
267
  }
247
268
  if (this.pinTypesList.indexOf(atomId) !== -1) {
248
- currentReference = {
269
+ currentReference = new AnyReference({
249
270
  found: true,
250
271
  value: atomId,
251
272
  type: ReferenceTypes.pinType,
252
- };
273
+ });
253
274
  }
254
275
  else {
255
276
  currentReference = executor.resolveVariable(this.executionStack, atomId, idTrailers);
@@ -266,19 +287,25 @@ export class BaseVisitor extends CircuitScriptVisitor {
266
287
  this.setResult(ctx, currentReference);
267
288
  };
268
289
  visitFunctionCallExpr = (ctx) => {
269
- const tmpCtx = ctx.function_call_expr();
270
- this.visit(tmpCtx);
271
- const result = this.getResult(tmpCtx);
290
+ const result = this.visitResult(ctx.function_call_expr());
272
291
  this.setResult(ctx, result);
273
292
  };
274
293
  visitFunction_call_expr = (ctx) => {
294
+ const ctxParams = this.getResult(ctx);
295
+ const { keepReference = false } = ctxParams ?? {};
296
+ this.handleFunctionCall(ctx);
297
+ if (!keepReference) {
298
+ const functionResultReference = this.getResult(ctx);
299
+ this.setResult(ctx, functionResultReference.value);
300
+ }
301
+ };
302
+ handleFunctionCall(ctx) {
275
303
  const executor = this.getExecutor();
276
304
  const atomId = ctx.ID().getText();
277
305
  let passedNetNamespace = null;
278
306
  const netNameSpaceExpr = ctx.net_namespace_expr();
279
307
  if (netNameSpaceExpr) {
280
- this.visit(netNameSpaceExpr);
281
- passedNetNamespace = this.getResult(netNameSpaceExpr);
308
+ passedNetNamespace = this.visitResult(netNameSpaceExpr);
282
309
  }
283
310
  let currentReference = executor.resolveVariable(this.executionStack, atomId);
284
311
  if (ctx.trailer_expr().length > 0) {
@@ -287,35 +314,42 @@ export class BaseVisitor extends CircuitScriptVisitor {
287
314
  }
288
315
  currentReference.trailers = [];
289
316
  ctx.trailer_expr().forEach(item => {
290
- const itemValue = item.getText();
291
317
  if (item.OPEN_PAREN() && item.CLOSE_PAREN()) {
292
318
  let parameters = [];
293
319
  const ctxParameters = item.parameters();
294
320
  if (ctxParameters) {
295
- this.visit(ctxParameters);
296
- parameters = this.getResult(ctxParameters);
321
+ parameters = this.visitResult(ctxParameters);
297
322
  }
298
323
  const useNetNamespace = this.getNetNamespace(executor.netNamespace, passedNetNamespace);
299
324
  try {
300
325
  const [, functionResult] = executor.callFunction(currentReference.name, parameters, this.executionStack, useNetNamespace);
301
- currentReference = {
302
- found: true,
303
- value: functionResult,
304
- type: (functionResult instanceof ClassComponent) ?
305
- 'instance' : 'value',
306
- };
326
+ if (isReference(functionResult)) {
327
+ currentReference = functionResult;
328
+ }
329
+ else {
330
+ currentReference = new AnyReference({
331
+ found: true,
332
+ value: functionResult,
333
+ trailers: [],
334
+ type: (functionResult instanceof ClassComponent) ?
335
+ ReferenceTypes.instance : ReferenceTypes.value,
336
+ });
337
+ }
307
338
  }
308
339
  catch (err) {
309
340
  this.throwWithContext(ctx, err);
310
341
  }
311
342
  }
312
343
  else {
313
- currentReference.trailers.push(itemValue);
344
+ currentReference.trailers.push(item.ID().getText());
345
+ currentReference = this.getExecutor().resolveTrailers(currentReference.type, (currentReference.parentValue !== undefined)
346
+ ? currentReference.parentValue
347
+ : currentReference.value, currentReference.trailers);
314
348
  }
315
349
  });
316
350
  }
317
- this.setResult(ctx, currentReference.value);
318
- };
351
+ this.setResult(ctx, currentReference);
352
+ }
319
353
  visitValue_expr = (ctx) => {
320
354
  const sign = ctx.Minus() ? -1 : 1;
321
355
  const ctxIntegerValue = ctx.INTEGER_VALUE();
@@ -364,12 +398,10 @@ export class BaseVisitor extends CircuitScriptVisitor {
364
398
  const ctxValueExpr = ctx.value_expr();
365
399
  const ctxAtomExpr = ctx.atom_expr();
366
400
  if (ctxValueExpr) {
367
- this.visit(ctxValueExpr);
368
- value = this.getResult(ctxValueExpr);
401
+ value = this.visitResult(ctxValueExpr);
369
402
  }
370
403
  else if (ctxAtomExpr) {
371
- this.visit(ctxAtomExpr);
372
- const reference = this.getResult(ctxAtomExpr);
404
+ const reference = this.visitResult(ctxAtomExpr);
373
405
  if (!reference.found) {
374
406
  value = new UndeclaredReference(reference);
375
407
  }
@@ -412,13 +444,11 @@ export class BaseVisitor extends CircuitScriptVisitor {
412
444
  const keywordAssignmentExpressions = ctx.keyword_assignment_expr();
413
445
  const returnList = [];
414
446
  dataExpressions.forEach((item, index) => {
415
- this.visit(item);
416
- const value = this.getResult(item);
447
+ const value = this.visitResult(item);
417
448
  returnList.push(['position', index, value]);
418
449
  });
419
450
  keywordAssignmentExpressions.forEach((item) => {
420
- this.visit(item);
421
- const [key, value] = this.getResult(item);
451
+ const [key, value] = this.visitResult(item);
422
452
  returnList.push(['keyword', key, value]);
423
453
  });
424
454
  this.setResult(ctx, returnList);
@@ -436,33 +466,34 @@ export class BaseVisitor extends CircuitScriptVisitor {
436
466
  executor.returnValue = returnValue;
437
467
  this.setResult(ctx, returnValue);
438
468
  };
439
- visitBreak_keyword = (ctx) => {
440
- const breakContext = this.getExecutor().getBreakContext();
441
- const currentResult = this.getResult(breakContext) ?? {};
442
- this.setResult(breakContext, {
443
- ...currentResult,
444
- breakSignal: true
445
- });
446
- };
447
- visitContinue_keyword = (ctx) => {
448
- const breakContext = this.getExecutor().getBreakContext();
449
- const currentResult = this.getResult(breakContext) ?? {};
450
- this.setResult(breakContext, {
451
- ...currentResult,
452
- breakSignal: true,
453
- continueSignal: true,
454
- });
469
+ visitFlow_expressions = (ctx) => {
470
+ if (ctx.if_expr()) {
471
+ this.visit(ctx.if_expr());
472
+ }
473
+ else if (ctx.while_expr()) {
474
+ this.visit(ctx.while_expr());
475
+ }
476
+ else if (ctx.for_expr()) {
477
+ this.visit(ctx.for_expr());
478
+ }
479
+ else if (ctx.Break() || ctx.Continue()) {
480
+ const breakContext = this.getExecutor().getBreakContext();
481
+ const currentResult = this.getResult(breakContext) ?? {};
482
+ this.setResult(breakContext, {
483
+ ...currentResult,
484
+ breakSignal: true,
485
+ continueSignal: ctx.Continue() ? true : false
486
+ });
487
+ }
455
488
  };
456
489
  visitArray_expr = (ctx) => {
457
490
  const array = ctx.data_expr().map(item => {
458
- this.visit(item);
459
- return this.getResult(item);
491
+ return this.visitResult(item);
460
492
  });
461
493
  this.setResult(ctx, array);
462
494
  };
463
495
  visitArrayExpr = (ctx) => {
464
- this.visit(ctx.array_expr());
465
- this.setResult(ctx, this.getResult(ctx.array_expr()));
496
+ this.setResult(ctx, this.visitResult(ctx.array_expr()));
466
497
  };
467
498
  setResult(ctx, value) {
468
499
  this.resultData.set(ctx, value);
@@ -556,12 +587,13 @@ export class BaseVisitor extends CircuitScriptVisitor {
556
587
  const tmpFuncArg = funcDefinedParameters[i];
557
588
  if (i < passedInParameters.length) {
558
589
  const tmpPassedInArgs = passedInParameters[i];
590
+ const argValue = unwrapValue(tmpPassedInArgs[2]);
559
591
  if (tmpPassedInArgs[0] === 'position') {
560
592
  const variableName = tmpFuncArg[0];
561
593
  executor.log('set variable in scope, var name: ', variableName);
562
- executor.scope.variables.set(variableName, tmpPassedInArgs[2]);
563
- if (tmpPassedInArgs[2] instanceof ClassComponent) {
564
- const component = tmpPassedInArgs[2];
594
+ executor.scope.setVariable(variableName, argValue);
595
+ if (argValue instanceof ClassComponent) {
596
+ const component = argValue;
565
597
  for (const [pinNumber, net] of component.pinNets) {
566
598
  executor.scope.setNet(component, pinNumber, net);
567
599
  }
@@ -570,14 +602,14 @@ export class BaseVisitor extends CircuitScriptVisitor {
570
602
  else if (tmpPassedInArgs[0] === 'keyword') {
571
603
  const variableName = tmpPassedInArgs[1];
572
604
  executor.log('set variable in scope, var name: ', variableName);
573
- executor.scope.variables.set(variableName, tmpPassedInArgs[2]);
605
+ executor.scope.setVariable(variableName, argValue);
574
606
  }
575
607
  }
576
608
  else if (tmpFuncArg.length === 3) {
577
609
  const variableName = tmpFuncArg[0];
578
610
  const defaultValue = tmpFuncArg[2];
579
611
  executor.log('set variable in scope, var name: ', variableName);
580
- executor.scope.variables.set(variableName, defaultValue);
612
+ executor.scope.setVariable(variableName, defaultValue);
581
613
  }
582
614
  else {
583
615
  throw `Invalid arguments got: ` + passedInParameters;