circuitscript 0.1.15 → 0.1.17

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 (49) hide show
  1. package/dist/cjs/BaseVisitor.js +98 -35
  2. package/dist/cjs/antlr/CircuitScriptLexer.js +3 -3
  3. package/dist/cjs/antlr/CircuitScriptParser.js +868 -757
  4. package/dist/cjs/builtinMethods.js +11 -1
  5. package/dist/cjs/draw_symbols.js +18 -17
  6. package/dist/cjs/execute.js +58 -31
  7. package/dist/cjs/globals.js +4 -1
  8. package/dist/cjs/graph.js +372 -0
  9. package/dist/cjs/helpers.js +6 -2
  10. package/dist/cjs/layout.js +18 -259
  11. package/dist/cjs/objects/ClassComponent.js +27 -20
  12. package/dist/cjs/objects/ExecutionScope.js +7 -2
  13. package/dist/cjs/objects/Net.js +1 -1
  14. package/dist/cjs/objects/PinDefinition.js +55 -3
  15. package/dist/cjs/objects/types.js +42 -6
  16. package/dist/cjs/visitor.js +88 -48
  17. package/dist/esm/BaseVisitor.js +98 -35
  18. package/dist/esm/antlr/CircuitScriptLexer.js +3 -3
  19. package/dist/esm/antlr/CircuitScriptParser.js +864 -755
  20. package/dist/esm/antlr/CircuitScriptVisitor.js +2 -0
  21. package/dist/esm/builtinMethods.js +11 -1
  22. package/dist/esm/draw_symbols.js +18 -17
  23. package/dist/esm/execute.js +60 -33
  24. package/dist/esm/globals.js +3 -0
  25. package/dist/esm/graph.js +344 -0
  26. package/dist/esm/helpers.js +6 -2
  27. package/dist/esm/layout.js +14 -235
  28. package/dist/esm/objects/ClassComponent.js +28 -21
  29. package/dist/esm/objects/ExecutionScope.js +7 -2
  30. package/dist/esm/objects/Net.js +1 -1
  31. package/dist/esm/objects/PinDefinition.js +53 -2
  32. package/dist/esm/objects/types.js +42 -6
  33. package/dist/esm/visitor.js +90 -50
  34. package/dist/libs/std.cst +3 -2
  35. package/dist/types/BaseVisitor.d.ts +5 -2
  36. package/dist/types/antlr/CircuitScriptParser.d.ts +42 -26
  37. package/dist/types/antlr/CircuitScriptVisitor.d.ts +4 -0
  38. package/dist/types/draw_symbols.d.ts +13 -7
  39. package/dist/types/execute.d.ts +12 -12
  40. package/dist/types/globals.d.ts +4 -1
  41. package/dist/types/graph.d.ts +29 -0
  42. package/dist/types/layout.d.ts +4 -9
  43. package/dist/types/objects/ClassComponent.d.ts +8 -8
  44. package/dist/types/objects/ExecutionScope.d.ts +8 -7
  45. package/dist/types/objects/Net.d.ts +2 -2
  46. package/dist/types/objects/PinDefinition.d.ts +17 -2
  47. package/dist/types/objects/types.d.ts +31 -7
  48. package/libs/std.cst +3 -2
  49. package/package.json +2 -1
@@ -22,19 +22,23 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
22
22
  this.setResult(ctx, [id, value]);
23
23
  };
24
24
  this.visitPin_select_expr = (ctx) => {
25
- let value = null;
25
+ let pinId = null;
26
26
  const ctxData = ctx.data_expr();
27
27
  const result = this.visitResult(ctxData);
28
+ let pinValue;
28
29
  if (result instanceof ParamDefinition_js_1.NumericValue) {
29
- value = result.toNumber();
30
+ pinValue = result.toNumber();
30
31
  }
31
32
  else if (typeof result === 'string') {
32
- value = result;
33
+ pinValue = result;
33
34
  }
34
35
  else {
35
- throw new utils_js_2.RuntimeExecutionError("Invalid value for pin", ctx);
36
+ throw new utils_js_2.RuntimeExecutionError("Invalid select pin: " + result, ctx);
36
37
  }
37
- this.setResult(ctx, value);
38
+ if (pinValue !== undefined) {
39
+ pinId = new PinDefinition_js_1.PinId(pinValue);
40
+ }
41
+ this.setResult(ctx, pinId);
38
42
  };
39
43
  this.visitAdd_component_expr = (ctx) => {
40
44
  const [component, pinValue] = this.visitResult(ctx.data_expr_with_assignment());
@@ -221,11 +225,18 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
221
225
  }
222
226
  }
223
227
  else {
224
- if (!(value instanceof ParamDefinition_js_1.NumericValue)) {
228
+ if (!(value instanceof ParamDefinition_js_1.NumericValue) && !(typeof value === 'string')) {
225
229
  throw new utils_js_2.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx);
226
230
  }
227
231
  else {
228
- checkPinExistsAndNotDuplicated(value.toNumber(), ctx);
232
+ let useValue;
233
+ if (value instanceof ParamDefinition_js_1.NumericValue) {
234
+ useValue = value.toNumber();
235
+ }
236
+ else if (typeof value === 'string') {
237
+ useValue = value;
238
+ }
239
+ value && checkPinExistsAndNotDuplicated(useValue, ctx);
229
240
  }
230
241
  }
231
242
  }
@@ -265,7 +276,6 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
265
276
  scope.exitContext();
266
277
  scope.popOnPropertyHandler();
267
278
  const properties = this.getPropertyExprList(ctx.property_expr());
268
- const pins = this.parseCreateComponentPins(properties.get('pins'));
269
279
  let instanceName = this.getExecutor().getUniqueInstanceName();
270
280
  const propParams = properties.get('params');
271
281
  const params = this.parseCreateComponentParams(propParams);
@@ -278,11 +288,11 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
278
288
  }
279
289
  instanceName += `${globals_js_1.Delimiter1}${appendValue}`;
280
290
  }
281
- const arrange = properties.has('arrange') ?
291
+ const arrangeProp = properties.has('arrange') ?
282
292
  properties.get('arrange') : null;
283
- const display = properties.has('display') ?
293
+ const displayProp = properties.has('display') ?
284
294
  properties.get('display') : null;
285
- const type = properties.has('type') ?
295
+ const typeProp = properties.has('type') ?
286
296
  properties.get('type') : null;
287
297
  const copy = properties.has('copy') ?
288
298
  properties.get('copy') : false;
@@ -294,8 +304,29 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
294
304
  properties.get(globals_js_1.ParamKeys.angle) : null;
295
305
  const followWireOrientation = properties.has('followWireOrientation') ?
296
306
  properties.get('followWireOrientation') : true;
307
+ let pins = [];
308
+ if (displayProp !== null && arrangeProp === null
309
+ && typeProp !== types_js_1.TypeProps.Graphic) {
310
+ const drawCommands = displayProp.getCommands();
311
+ drawCommands.forEach(command => {
312
+ const [commandValue,] = command;
313
+ if (commandValue === draw_symbols_js_1.PlaceHolderCommands.vpin
314
+ || commandValue === draw_symbols_js_1.PlaceHolderCommands.hpin
315
+ || commandValue === draw_symbols_js_1.PlaceHolderCommands.pin) {
316
+ const id = PinDefinition_js_1.PinId.from(command[1][0]);
317
+ const pinType = id.getType();
318
+ const pinName = id.toString();
319
+ pins.push(new PinDefinition_js_1.PinDefinition(id, pinType, pinName, PinTypes_js_1.PinTypes.Any));
320
+ }
321
+ });
322
+ }
323
+ else {
324
+ pins = this.parseCreateComponentPins(properties.get('pins'));
325
+ }
297
326
  const props = {
298
- arrange, display, type, width, height, copy,
327
+ arrange: arrangeProp,
328
+ display: displayProp,
329
+ type: typeProp, width, height, copy,
299
330
  angle, followWireOrientation
300
331
  };
301
332
  try {
@@ -381,7 +412,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
381
412
  if (ctxNestedProperties) {
382
413
  const nestedKeyValues = this.visitResult(ctxNestedProperties);
383
414
  nestedKeyValues.forEach((value, key) => {
384
- parameters.push(['keyword', key, value]);
415
+ parameters.push(['keyword', key, (0, utils_js_1.unwrapValue)(value)]);
385
416
  });
386
417
  }
387
418
  else {
@@ -539,36 +570,36 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
539
570
  this.setResult(ctx, result);
540
571
  };
541
572
  this.visitData_expr_with_assignment = (ctx) => {
542
- let component = null;
543
- let componentCtx = null;
573
+ let dataResult = null;
574
+ let componentCtx;
544
575
  const ctxDataExpr = ctx.data_expr();
545
576
  const ctxAssignmentExpr = ctx.assignment_expr();
546
577
  if (ctxDataExpr) {
547
- component = this.visitResult(ctxDataExpr);
548
- component = (0, utils_js_1.unwrapValue)(component);
578
+ dataResult = this.visitResult(ctxDataExpr);
549
579
  componentCtx = ctxDataExpr;
550
- if (component === null || component === undefined) {
551
- this.throwWithContext(ctxDataExpr, "Could not find component: " + ctxDataExpr.getText());
552
- }
553
580
  }
554
581
  else if (ctxAssignmentExpr) {
555
- component = this.visitResult(ctxAssignmentExpr);
582
+ dataResult = this.visitResult(ctxAssignmentExpr);
556
583
  componentCtx = ctxAssignmentExpr;
557
584
  }
558
- if (component instanceof ClassComponent_js_1.ClassComponent
559
- && component.copyProp) {
560
- component = this.getExecutor().copyComponent(component);
561
- }
562
- if (component instanceof types_js_1.UndeclaredReference) {
563
- const { reference: { trailers = [], parentValue = null } } = component;
585
+ if (dataResult instanceof types_js_1.AnyReference) {
586
+ const { trailers = [], parentValue = null } = dataResult;
564
587
  if (parentValue instanceof ClassComponent_js_1.ClassComponent
565
588
  && trailers.length > 0
566
589
  && trailers[0] === globals_js_1.ModuleContainsKeyword) {
567
- component = parentValue;
568
- this.placeModuleContains(component);
590
+ dataResult = parentValue;
591
+ this.placeModuleContains(dataResult);
569
592
  }
570
593
  }
571
- if (component && component instanceof ClassComponent_js_1.ClassComponent) {
594
+ dataResult = (0, utils_js_1.unwrapValue)(dataResult);
595
+ if (dataResult === null || dataResult === undefined) {
596
+ this.throwWithContext(componentCtx, "Could not find component: " + componentCtx.getText());
597
+ }
598
+ if (dataResult instanceof ClassComponent_js_1.ClassComponent
599
+ && dataResult.copyProp) {
600
+ dataResult = this.getExecutor().copyComponent(dataResult);
601
+ }
602
+ if (dataResult && dataResult instanceof ClassComponent_js_1.ClassComponent) {
572
603
  const modifiers = ctx.component_modifier_expr();
573
604
  modifiers.forEach(modifier => {
574
605
  const modifierText = modifier.ID(0).getText();
@@ -585,23 +616,23 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
585
616
  if (modifierText === globals_js_1.ParamKeys.flip) {
586
617
  const flipValue = result;
587
618
  if (flipValue.indexOf('x') !== -1) {
588
- component.setParam(globals_js_1.ParamKeys.flipX, 1);
619
+ dataResult.setParam(globals_js_1.ParamKeys.flipX, 1);
589
620
  shouldIgnoreWireOrientation = true;
590
621
  }
591
622
  if (flipValue.indexOf('y') !== -1) {
592
- component.setParam(globals_js_1.ParamKeys.flipY, 1);
623
+ dataResult.setParam(globals_js_1.ParamKeys.flipY, 1);
593
624
  shouldIgnoreWireOrientation = true;
594
625
  }
595
626
  }
596
627
  else if (modifierText === globals_js_1.ParamKeys.angle) {
597
- component.setParam(globals_js_1.ParamKeys.angle, result);
628
+ dataResult.setParam(globals_js_1.ParamKeys.angle, result);
598
629
  shouldIgnoreWireOrientation = true;
599
630
  }
600
631
  else if (modifierText === 'anchor') {
601
- component.setParam('anchor', result);
632
+ dataResult.setParam('anchor', result);
602
633
  }
603
634
  if (shouldIgnoreWireOrientation) {
604
- component.useWireOrientationAngle = false;
635
+ dataResult.useWireOrientationAngle = false;
605
636
  }
606
637
  });
607
638
  }
@@ -611,15 +642,15 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
611
642
  pinValue = this.visitResult(ctxPinSelectExpr);
612
643
  }
613
644
  else {
614
- if (component instanceof ClassComponent_js_1.ClassComponent) {
615
- pinValue = component.getDefaultPin();
645
+ if (dataResult instanceof ClassComponent_js_1.ClassComponent) {
646
+ pinValue = dataResult.getDefaultPin();
616
647
  }
617
648
  else {
618
- const undeclaredRef = component;
649
+ const undeclaredRef = dataResult;
619
650
  this.throwWithContext(componentCtx, 'Invalid component: ' + undeclaredRef.reference.name);
620
651
  }
621
652
  }
622
- this.setResult(ctx, [component, pinValue]);
653
+ this.setResult(ctx, [dataResult, pinValue]);
623
654
  };
624
655
  this.visitUnaryOperatorExpr = (ctx) => {
625
656
  let value = this.visitResult(ctx.data_expr());
@@ -749,8 +780,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
749
780
  this.setResult(ctx, result);
750
781
  };
751
782
  this.visitAdditionExpr = (ctx) => {
752
- const value1 = this.resolveDataExpr(ctx.data_expr(0));
753
- const value2 = this.resolveDataExpr(ctx.data_expr(1));
783
+ const value1 = (0, utils_js_1.unwrapValue)(this.resolveDataExpr(ctx.data_expr(0)));
784
+ const value2 = (0, utils_js_1.unwrapValue)(this.resolveDataExpr(ctx.data_expr(1)));
754
785
  if (ctx.Addition() && (typeof value1 === 'string' || typeof value2 === 'string')) {
755
786
  let tmpValue1 = value1;
756
787
  if (value1 instanceof ParamDefinition_js_1.NumericValue) {
@@ -779,6 +810,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
779
810
  };
780
811
  this.visitFunction_def_expr = (ctx) => {
781
812
  const functionName = ctx.ID().getText();
813
+ const uniqueFunctionID = '__._' + ctx.start.line + '_'
814
+ + ctx.start.column + '_' + functionName + '_' + ctx.getText();
782
815
  let funcDefinedParameters = [];
783
816
  const ctxFunctionArgsExpr = ctx.function_args_expr();
784
817
  if (ctxFunctionArgsExpr) {
@@ -800,19 +833,26 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
800
833
  nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
801
834
  return [lastExecution, returnValue];
802
835
  };
803
- this.getExecutor().createFunction(functionName, __runFunc);
836
+ this.getExecutor().createFunction(functionName, __runFunc, ctx, uniqueFunctionID);
804
837
  };
805
838
  this.visitPin_select_expr2 = (ctx) => {
806
839
  const ctxStringValue = ctx.STRING_VALUE();
807
840
  const ctxIntegerValue = ctx.INTEGER_VALUE();
808
- let result = null;
841
+ let pinIdValue;
842
+ let pinId = null;
809
843
  if (ctxStringValue) {
810
- result = this.prepareStringValue(ctxStringValue.getText());
844
+ pinIdValue = this.prepareStringValue(ctxStringValue.getText());
811
845
  }
812
846
  else if (ctxIntegerValue) {
813
- result = Number(ctxIntegerValue.getText());
847
+ pinIdValue = Number(ctxIntegerValue.getText());
814
848
  }
815
- this.setResult(ctx, result);
849
+ if (pinIdValue !== undefined) {
850
+ pinId = new PinDefinition_js_1.PinId(pinIdValue);
851
+ }
852
+ else {
853
+ throw new utils_js_2.RuntimeExecutionError("Invalid select pin", ctx);
854
+ }
855
+ this.setResult(ctx, pinId);
816
856
  };
817
857
  this.visitAt_block_pin_expr = (ctx) => {
818
858
  const executor = this.getExecutor();
@@ -1204,7 +1244,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1204
1244
  return item;
1205
1245
  }
1206
1246
  else {
1207
- return (0, ParamDefinition_js_1.numeric)(nameToPinId.get(item));
1247
+ return new PinDefinition_js_1.PinId(nameToPinId.get(item));
1208
1248
  }
1209
1249
  });
1210
1250
  if (items.length > 0) {
@@ -1295,7 +1335,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1295
1335
  getGraph() {
1296
1336
  const executor = this.getExecutor();
1297
1337
  const fullSequence = executor.scope.sequence;
1298
- const tmpNet = executor.scope.getNet(executor.scope.componentRoot, 1);
1338
+ const tmpNet = executor.scope.getNet(executor.scope.componentRoot, new PinDefinition_js_1.PinId(1));
1299
1339
  const sequence = (tmpNet === null)
1300
1340
  ? fullSequence.slice(1) : fullSequence;
1301
1341
  const nets = executor.scope.getNets();
@@ -1,5 +1,4 @@
1
1
  import { Big } from 'big.js';
2
- import { ExpressionContext } from "./antlr/CircuitScriptParser.js";
3
2
  import { CircuitScriptVisitor } from "./antlr/CircuitScriptVisitor.js";
4
3
  import { ExecutionContext } from "./execute.js";
5
4
  import { Logger } from "./logger.js";
@@ -7,11 +6,12 @@ import { ClassComponent } from "./objects/ClassComponent.js";
7
6
  import { NumberOperator, NumericValue, PercentageValue } from "./objects/ParamDefinition.js";
8
7
  import { PinTypes } from "./objects/PinTypes.js";
9
8
  import { Direction, AnyReference, UndeclaredReference } from "./objects/types.js";
10
- import { ComponentTypes, DoubleDelimiter1, GlobalDocumentName, ReferenceTypes } from './globals.js';
9
+ import { ComponentTypes, DoubleDelimiter1, GlobalDocumentName, ReferenceTypes, TrailerArrayIndex } from './globals.js';
11
10
  import { isReference, unwrapValue as unwrapValue } from "./utils.js";
12
11
  import { linkBuiltInMethods } from './builtinMethods.js';
13
12
  import { resolveToNumericValue, RuntimeExecutionError, throwWithContext } from './utils.js';
14
13
  import { SequenceAction } from './objects/ExecutionScope.js';
14
+ import { PinId } from './objects/PinDefinition.js';
15
15
  export class BaseVisitor extends CircuitScriptVisitor {
16
16
  indentLevel = 0;
17
17
  startingContext;
@@ -134,28 +134,37 @@ export class BaseVisitor extends CircuitScriptVisitor {
134
134
  const ctxAtom = ctx.atom_expr();
135
135
  const ctxFuncCallRef = ctx.function_call_expr();
136
136
  let leftSideReference;
137
+ let lhsCtx;
137
138
  if (ctxAtom) {
138
139
  leftSideReference = this.getReference(ctx.atom_expr());
140
+ lhsCtx = ctxAtom;
139
141
  }
140
142
  else if (ctxFuncCallRef) {
141
143
  this.setResult(ctxFuncCallRef, { keepReference: true });
142
144
  leftSideReference = this.visitResult(ctxFuncCallRef);
145
+ lhsCtx = ctxFuncCallRef;
146
+ }
147
+ const rhsCtx = ctx.data_expr();
148
+ const rhsCtxResult = this.visitResult(rhsCtx);
149
+ if (isReference(rhsCtxResult) && !rhsCtxResult.found) {
150
+ this.throwWithContext(rhsCtx, rhsCtx.getText() + ' is not defined');
143
151
  }
144
- const rhsCtxResult = this.visitResult(ctx.data_expr());
145
152
  const rhsValue = unwrapValue(rhsCtxResult);
146
153
  const trailers = leftSideReference.trailers ?? [];
147
154
  const sequenceParts = [];
148
155
  if (trailers.length === 0) {
156
+ this.getScope().setVariable(leftSideReference.name, rhsValue);
157
+ let itemType = '';
149
158
  if (rhsValue instanceof ClassComponent) {
150
- this.getScope().setVariable(leftSideReference.name, rhsValue);
151
- sequenceParts.push(...['instance', leftSideReference.name, rhsValue]);
159
+ itemType = ReferenceTypes.instance;
152
160
  this.log2(`assigned '${leftSideReference.name}' to ClassComponent`);
153
161
  }
154
162
  else {
163
+ itemType = ReferenceTypes.variable;
155
164
  this.getScope().setVariable(leftSideReference.name, rhsValue);
156
165
  this.log2(`assigned variable ${leftSideReference.name} to ${rhsValue}`);
157
- sequenceParts.push(...['variable', leftSideReference.name, rhsValue]);
158
166
  }
167
+ sequenceParts.push(...[itemType, leftSideReference.name, rhsValue]);
159
168
  }
160
169
  else {
161
170
  if (leftSideReference.parentValue instanceof ClassComponent) {
@@ -163,7 +172,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
163
172
  this.log2(`assigned component param ${leftSideReference.parentValue} trailers: ${trailers} value: ${rhsValue}`);
164
173
  sequenceParts.push(...['instance', [leftSideReference.parentValue, trailers], rhsValue]);
165
174
  if (leftSideReference.parentValue.typeProp === ComponentTypes.net) {
166
- const net = this.getScope().getNet(leftSideReference.parentValue, 1);
175
+ const net = this.getScope().getNet(leftSideReference.parentValue, new PinId(1));
167
176
  if (net) {
168
177
  const trailerValue = trailers.join(".");
169
178
  net.params.set(trailerValue, rhsValue);
@@ -171,8 +180,20 @@ export class BaseVisitor extends CircuitScriptVisitor {
171
180
  }
172
181
  }
173
182
  else if (leftSideReference.parentValue instanceof Object) {
174
- leftSideReference.parentValue[trailers.join('.')] = rhsValue;
175
- this.log2(`assigned object ${leftSideReference.parentValue} trailers: ${trailers} value: ${rhsValue}`);
183
+ if (Array.isArray(trailers[0]) && trailers[0][0] === TrailerArrayIndex) {
184
+ if (Array.isArray(leftSideReference.parentValue)) {
185
+ const arrayIndexValue = trailers[0][1];
186
+ leftSideReference.parentValue[arrayIndexValue] = rhsValue;
187
+ this.log2(`assigned array index ${leftSideReference.parentValue} index: ${arrayIndexValue} value: ${rhsValue}`);
188
+ }
189
+ else {
190
+ this.throwWithContext(lhsCtx, "Invalid array");
191
+ }
192
+ }
193
+ else {
194
+ leftSideReference.parentValue[trailers.join('.')] = rhsValue;
195
+ this.log2(`assigned object ${leftSideReference.parentValue} trailers: ${trailers} value: ${rhsValue}`);
196
+ }
176
197
  sequenceParts.push(...['variable', [leftSideReference.parentValue, trailers], rhsValue]);
177
198
  }
178
199
  }
@@ -252,19 +273,39 @@ export class BaseVisitor extends CircuitScriptVisitor {
252
273
  }
253
274
  return reference;
254
275
  }
276
+ visitTrailer_expr2 = (ctx) => {
277
+ const reference = this.getResult(ctx);
278
+ const ctxID = ctx.ID();
279
+ const ctxDataExpr = ctx.data_expr();
280
+ const useValue = reference.value;
281
+ let nextReference;
282
+ if (ctxID) {
283
+ reference.trailers.push(ctxID.getText());
284
+ nextReference = this.getExecutor().resolveTrailers(reference.type, useValue, reference.trailers);
285
+ }
286
+ else if (ctxDataExpr) {
287
+ const arrayIndex = this.visitResult(ctxDataExpr);
288
+ if (arrayIndex instanceof NumericValue) {
289
+ const arrayIndexValue = arrayIndex.toNumber();
290
+ const foundValue = useValue[arrayIndexValue];
291
+ const refType = foundValue instanceof ClassComponent
292
+ ? ReferenceTypes.instance : ReferenceTypes.variable;
293
+ nextReference = new AnyReference({
294
+ found: true,
295
+ type: refType,
296
+ value: foundValue,
297
+ trailers: [[TrailerArrayIndex, arrayIndexValue]],
298
+ parentValue: useValue
299
+ });
300
+ }
301
+ }
302
+ this.setResult(ctx, nextReference);
303
+ };
255
304
  visitAtom_expr = (ctx) => {
256
305
  const executor = this.getExecutor();
257
306
  const firstId = ctx.ID(0);
258
307
  const atomId = firstId.getText();
259
308
  let currentReference;
260
- const idTrailers = [];
261
- if (ctx.ID().length > 1) {
262
- const idLength = ctx.ID().length;
263
- for (let i = 1; i < idLength; i++) {
264
- const tmpCtx = ctx.ID(i);
265
- idTrailers.push(tmpCtx.getText());
266
- }
267
- }
268
309
  if (this.pinTypesList.indexOf(atomId) !== -1) {
269
310
  currentReference = new AnyReference({
270
311
  found: true,
@@ -273,18 +314,18 @@ export class BaseVisitor extends CircuitScriptVisitor {
273
314
  });
274
315
  }
275
316
  else {
276
- currentReference = executor.resolveVariable(this.executionStack, atomId, idTrailers);
317
+ currentReference = executor.resolveVariable(this.executionStack, atomId);
277
318
  }
278
- if (currentReference.found && currentReference.type === 'instance' && idTrailers.length === 0) {
279
- const tmpComponent = currentReference.value;
280
- for (const [pinId, net] of tmpComponent.pinNets) {
281
- executor.scope.setNet(tmpComponent, pinId, net);
319
+ if (currentReference !== undefined && currentReference.found) {
320
+ const trailersLength = ctx.trailer_expr2().length;
321
+ for (let i = 0; i < trailersLength; i++) {
322
+ const trailerCtx = ctx.trailer_expr2(i);
323
+ this.setResult(trailerCtx, currentReference);
324
+ currentReference = this.visitResult(trailerCtx);
282
325
  }
283
326
  }
284
- if (ctx.parent instanceof ExpressionContext && !currentReference.found) {
285
- this.throwWithContext(ctx, "Unknown symbol: " + atomId);
286
- }
287
327
  this.setResult(ctx, currentReference);
328
+ this.log2('atom resolved: ' + ctx.getText() + ' -> ' + currentReference);
288
329
  };
289
330
  visitFunctionCallExpr = (ctx) => {
290
331
  const result = this.visitResult(ctx.function_call_expr());
@@ -315,6 +356,11 @@ export class BaseVisitor extends CircuitScriptVisitor {
315
356
  currentReference.trailers = [];
316
357
  ctx.trailer_expr().forEach(item => {
317
358
  if (item.OPEN_PAREN() && item.CLOSE_PAREN()) {
359
+ if (currentReference.type === ReferenceTypes.variable) {
360
+ if (currentReference.value instanceof AnyReference && currentReference.value.type === ReferenceTypes.function) {
361
+ currentReference = currentReference.value;
362
+ }
363
+ }
318
364
  let parameters = [];
319
365
  const ctxParameters = item.parameters();
320
366
  if (ctxParameters) {
@@ -341,10 +387,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
341
387
  }
342
388
  }
343
389
  else {
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);
390
+ const ctxTrailer = item.trailer_expr2();
391
+ this.setResult(ctxTrailer, currentReference);
392
+ currentReference = this.visitResult(ctxTrailer);
348
393
  }
349
394
  });
350
395
  }
@@ -410,7 +455,8 @@ export class BaseVisitor extends CircuitScriptVisitor {
410
455
  value = reference;
411
456
  }
412
457
  else {
413
- if (reference.trailers && reference.trailers.length > 0) {
458
+ if ((reference.trailers && reference.trailers.length > 0)
459
+ || reference.type === ReferenceTypes.function) {
414
460
  value = reference;
415
461
  }
416
462
  else {
@@ -445,11 +491,11 @@ export class BaseVisitor extends CircuitScriptVisitor {
445
491
  const returnList = [];
446
492
  dataExpressions.forEach((item, index) => {
447
493
  const value = this.visitResult(item);
448
- returnList.push(['position', index, value]);
494
+ returnList.push(['position', index, unwrapValue(value)]);
449
495
  });
450
496
  keywordAssignmentExpressions.forEach((item) => {
451
497
  const [key, value] = this.visitResult(item);
452
- returnList.push(['keyword', key, value]);
498
+ returnList.push(['keyword', key, unwrapValue(value)]);
453
499
  });
454
500
  this.setResult(ctx, returnList);
455
501
  };
@@ -459,9 +505,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
459
505
  visitFunction_return_expr = (ctx) => {
460
506
  const executor = this.getExecutor();
461
507
  executor.log('return from function');
462
- const ctxDataExpr = ctx.data_expr();
463
- this.visit(ctxDataExpr);
464
- const returnValue = this.getResult(ctxDataExpr);
508
+ const returnValue = this.visitResult(ctx.data_expr());
465
509
  executor.stopFurtherExpressions = true;
466
510
  executor.returnValue = returnValue;
467
511
  this.setResult(ctx, returnValue);
@@ -495,6 +539,25 @@ export class BaseVisitor extends CircuitScriptVisitor {
495
539
  visitArrayExpr = (ctx) => {
496
540
  this.setResult(ctx, this.visitResult(ctx.array_expr()));
497
541
  };
542
+ visitArrayIndexExpr = (ctx) => {
543
+ const ctxArray = ctx.data_expr(0);
544
+ const ctxArrayIndex = ctx.data_expr(1);
545
+ const arrayItem = this.visitResult(ctxArray);
546
+ const indexValue = this.visitResult(ctxArrayIndex);
547
+ if (!Array.isArray(arrayItem)) {
548
+ throw new RuntimeExecutionError("Invalid array", ctxArray);
549
+ }
550
+ if (!(indexValue instanceof NumericValue)) {
551
+ throw new RuntimeExecutionError("Invalid index value", ctxArrayIndex);
552
+ }
553
+ const indexValueNumber = indexValue.toNumber();
554
+ if (isNaN(indexValueNumber)) {
555
+ throw new RuntimeExecutionError("Invalid index value", ctxArrayIndex);
556
+ }
557
+ if (Array.isArray(arrayItem)) {
558
+ this.setResult(ctx, arrayItem[indexValueNumber]);
559
+ }
560
+ };
498
561
  setResult(ctx, value) {
499
562
  this.resultData.set(ctx, value);
500
563
  }
@@ -69,7 +69,7 @@ export class CircuitScriptLexer extends antlr.Lexer {
69
69
  "DEFAULT_TOKEN_CHANNEL", "HIDDEN"
70
70
  ];
71
71
  static literalNames = [
72
- null, "':'", "','", "'='", "'..'", "'.'", "'['", "']'", "'break'",
72
+ null, "':'", "','", "'='", "'..'", "'['", "']'", "'.'", "'break'",
73
73
  "'branch'", "'create'", "'component'", "'graphic'", "'module'",
74
74
  "'wire'", "'pin'", "'add'", "'at'", "'to'", "'point'", "'join'",
75
75
  "'parallel'", "'return'", "'def'", "'import'", "'for'", "'in'",
@@ -235,8 +235,8 @@ export class CircuitScriptLexer extends antlr.Lexer {
235
235
  0, 131, 473, 1, 0, 0, 0, 133, 477, 1, 0, 0, 0, 135, 486, 1, 0, 0, 0, 137, 138, 5, 58, 0,
236
236
  0, 138, 2, 1, 0, 0, 0, 139, 140, 5, 44, 0, 0, 140, 4, 1, 0, 0, 0, 141, 142, 5, 61, 0, 0,
237
237
  142, 6, 1, 0, 0, 0, 143, 144, 5, 46, 0, 0, 144, 145, 5, 46, 0, 0, 145, 8, 1, 0, 0, 0, 146,
238
- 147, 5, 46, 0, 0, 147, 10, 1, 0, 0, 0, 148, 149, 5, 91, 0, 0, 149, 12, 1, 0, 0, 0, 150,
239
- 151, 5, 93, 0, 0, 151, 14, 1, 0, 0, 0, 152, 153, 5, 98, 0, 0, 153, 154, 5, 114, 0, 0, 154,
238
+ 147, 5, 91, 0, 0, 147, 10, 1, 0, 0, 0, 148, 149, 5, 93, 0, 0, 149, 12, 1, 0, 0, 0, 150,
239
+ 151, 5, 46, 0, 0, 151, 14, 1, 0, 0, 0, 152, 153, 5, 98, 0, 0, 153, 154, 5, 114, 0, 0, 154,
240
240
  155, 5, 101, 0, 0, 155, 156, 5, 97, 0, 0, 156, 157, 5, 107, 0, 0, 157, 16, 1, 0, 0, 0,
241
241
  158, 159, 5, 98, 0, 0, 159, 160, 5, 114, 0, 0, 160, 161, 5, 97, 0, 0, 161, 162, 5, 110,
242
242
  0, 0, 162, 163, 5, 99, 0, 0, 163, 164, 5, 104, 0, 0, 164, 18, 1, 0, 0, 0, 165, 166, 5,