circuitscript 0.1.20 → 0.1.23

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 (45) hide show
  1. package/dist/cjs/BaseVisitor.js +22 -0
  2. package/dist/cjs/ComponentAnnotater.js +88 -0
  3. package/dist/cjs/RefdesAnnotationVisitor.js +197 -0
  4. package/dist/cjs/antlr/CircuitScriptLexer.js +202 -197
  5. package/dist/cjs/antlr/CircuitScriptParser.js +975 -833
  6. package/dist/cjs/environment.js +15 -1
  7. package/dist/cjs/execute.js +45 -2
  8. package/dist/cjs/helpers.js +20 -2
  9. package/dist/cjs/lexer.js +21 -9
  10. package/dist/cjs/main.js +13 -0
  11. package/dist/cjs/objects/ClassComponent.js +4 -1
  12. package/dist/cjs/objects/ExecutionScope.js +1 -0
  13. package/dist/cjs/parser.js +1 -0
  14. package/dist/cjs/visitor.js +122 -71
  15. package/dist/esm/BaseVisitor.js +22 -0
  16. package/dist/esm/ComponentAnnotater.js +84 -0
  17. package/dist/esm/RefdesAnnotationVisitor.js +196 -0
  18. package/dist/esm/antlr/CircuitScriptLexer.js +202 -197
  19. package/dist/esm/antlr/CircuitScriptParser.js +971 -831
  20. package/dist/esm/antlr/CircuitScriptVisitor.js +2 -0
  21. package/dist/esm/environment.js +15 -1
  22. package/dist/esm/execute.js +45 -2
  23. package/dist/esm/helpers.js +20 -2
  24. package/dist/esm/lexer.js +21 -9
  25. package/dist/esm/main.js +13 -0
  26. package/dist/esm/objects/ClassComponent.js +4 -1
  27. package/dist/esm/objects/ExecutionScope.js +1 -0
  28. package/dist/esm/parser.js +1 -0
  29. package/dist/esm/visitor.js +120 -69
  30. package/dist/types/BaseVisitor.d.ts +3 -0
  31. package/dist/types/ComponentAnnotater.d.ts +16 -0
  32. package/dist/types/RefdesAnnotationVisitor.d.ts +35 -0
  33. package/dist/types/antlr/CircuitScriptLexer.d.ts +15 -14
  34. package/dist/types/antlr/CircuitScriptParser.d.ts +81 -60
  35. package/dist/types/antlr/CircuitScriptVisitor.d.ts +4 -0
  36. package/dist/types/environment.d.ts +1 -0
  37. package/dist/types/execute.d.ts +8 -1
  38. package/dist/types/helpers.d.ts +4 -1
  39. package/dist/types/lexer.d.ts +1 -1
  40. package/dist/types/objects/ClassComponent.d.ts +9 -0
  41. package/dist/types/objects/ExecutionScope.d.ts +2 -1
  42. package/dist/types/objects/types.d.ts +1 -0
  43. package/dist/types/parser.d.ts +2 -1
  44. package/dist/types/visitor.d.ts +8 -1
  45. package/package.json +1 -1
@@ -14,6 +14,7 @@ class NodeScriptEnvironment {
14
14
  this.useModuleDirectoryPath = null;
15
15
  this.useDefaultLibsPath = null;
16
16
  this.globalCreateSVGWindow = null;
17
+ this.cachedVersion = null;
17
18
  this.supportedFonts = {
18
19
  'Arial': 'Arial.ttf',
19
20
  };
@@ -31,7 +32,20 @@ class NodeScriptEnvironment {
31
32
  this.useDefaultLibsPath = path;
32
33
  }
33
34
  getPackageVersion() {
34
- return globals_js_1.TOOL_VERSION;
35
+ if (this.cachedVersion !== null) {
36
+ return this.cachedVersion;
37
+ }
38
+ try {
39
+ const packageJsonPath = path_1.default.join(this.getToolsPath(), '../', 'package.json');
40
+ const packageJsonContent = fs_1.default.readFileSync(packageJsonPath, 'utf-8');
41
+ const packageJson = JSON.parse(packageJsonContent);
42
+ this.cachedVersion = packageJson.version || globals_js_1.TOOL_VERSION;
43
+ return this.cachedVersion;
44
+ }
45
+ catch (error) {
46
+ console.warn('Failed to read version from package.json, using fallback version:', error);
47
+ return globals_js_1.TOOL_VERSION;
48
+ }
35
49
  }
36
50
  getModuleDirectory() {
37
51
  if (this.useModuleDirectoryPath !== null) {
@@ -24,6 +24,7 @@ class ExecutionContext {
24
24
  this.__functionCache = new Map();
25
25
  this.componentAngleFollowsWire = true;
26
26
  this.warnings = [];
27
+ this.indexedStack = new Map();
27
28
  this.name = name;
28
29
  this.namespace = namespace;
29
30
  this.netNamespace = netNamespace;
@@ -542,9 +543,39 @@ class ExecutionContext {
542
543
  this.log('did not find block point');
543
544
  return null;
544
545
  }
546
+ getParentBreakContext() {
547
+ if (this.scope.breakStack.length > 0) {
548
+ return this.scope.breakStack[this.scope.breakStack.length - 1];
549
+ }
550
+ return null;
551
+ }
545
552
  addBreakContext(ctx) {
546
553
  this.log('add break context');
547
554
  this.scope.breakStack.push(ctx);
555
+ this.indexedStack.set(ctx, {
556
+ index: 0,
557
+ funcCallIndex: new Map(),
558
+ });
559
+ }
560
+ setBreakContextIndex(index) {
561
+ const latestCtx = this.scope.breakStack[this.scope.breakStack.length - 1];
562
+ if (latestCtx) {
563
+ const current = this.indexedStack.get(latestCtx);
564
+ this.indexedStack.set(latestCtx, {
565
+ ...current,
566
+ index,
567
+ });
568
+ }
569
+ }
570
+ resetBreakContextFunctionCalls() {
571
+ const latestCtx = this.scope.breakStack[this.scope.breakStack.length - 1];
572
+ if (latestCtx) {
573
+ const current = this.indexedStack.get(latestCtx);
574
+ this.indexedStack.set(latestCtx, {
575
+ index: current.index,
576
+ funcCallIndex: new Map(),
577
+ });
578
+ }
548
579
  }
549
580
  popBreakContext() {
550
581
  this.log('pop break context');
@@ -667,9 +698,18 @@ class ExecutionContext {
667
698
  __runFunc = this.__functionCache.get(functionName);
668
699
  }
669
700
  if (__runFunc !== null) {
701
+ let functionCallIndex = -1;
702
+ if (!this.scope.functionCounter.has(__runFunc)) {
703
+ this.scope.functionCounter.set(__runFunc, 0);
704
+ functionCallIndex = 0;
705
+ }
706
+ else {
707
+ functionCallIndex = this.scope.functionCounter.get(__runFunc);
708
+ }
709
+ this.scope.functionCounter.set(__runFunc, functionCallIndex + 1);
670
710
  this.log(`call function '${functionName}'`);
671
711
  this.log(`net namespace: ${netNamespace}`);
672
- const functionResult = __runFunc(functionParams, { netNamespace });
712
+ const functionResult = __runFunc(functionParams, { netNamespace, functionCallIndex });
673
713
  this.log(`done call function '${functionName}'`);
674
714
  return functionResult;
675
715
  }
@@ -682,6 +722,7 @@ class ExecutionContext {
682
722
  const { currentComponent, currentPin, currentWireId } = this.scope;
683
723
  const tmpInstances = childScope.instances;
684
724
  const tmpNets = childScope.getNets();
725
+ const mergedInstances = [];
685
726
  for (const [instanceName, component] of tmpInstances) {
686
727
  const newInstanceName = `${namespace}.${instanceName}`;
687
728
  component.instanceName = newInstanceName;
@@ -694,6 +735,7 @@ class ExecutionContext {
694
735
  else {
695
736
  throw "Invalid instance name to merge into parent scope!";
696
737
  }
738
+ mergedInstances.push(component);
697
739
  }
698
740
  const childScopeUniqueNets = new Set(tmpNets.map(([, , net]) => net));
699
741
  childScopeUniqueNets.forEach(net => {
@@ -767,6 +809,7 @@ class ExecutionContext {
767
809
  return accum;
768
810
  }, []);
769
811
  this.log('-- done merging scope --');
812
+ return mergedInstances;
770
813
  }
771
814
  addWire(segments) {
772
815
  if (this.scope.currentComponent === null) {
@@ -890,7 +933,7 @@ class ExecutionContext {
890
933
  idName = this.scope.currentComponent.instanceName;
891
934
  if (this.scope.instances.has(idName)) {
892
935
  const component = this.scope.instances.get(idName);
893
- component.parameters.set(paramName, value);
936
+ component.setParam(paramName, value);
894
937
  }
895
938
  else if (this.scope.variables.has(idName)) {
896
939
  throw "Not implemented yet!";
@@ -24,6 +24,7 @@ const Frame_js_1 = require("./objects/Frame.js");
24
24
  const big_js_1 = __importDefault(require("big.js"));
25
25
  const logger_js_1 = require("./logger.js");
26
26
  const graph_js_1 = require("./graph.js");
27
+ const RefdesAnnotationVisitor_js_1 = require("./RefdesAnnotationVisitor.js");
27
28
  var JSModuleType;
28
29
  (function (JSModuleType) {
29
30
  JSModuleType["CommonJs"] = "cjs";
@@ -165,7 +166,7 @@ async function renderScript(scriptData, outputPath, options) {
165
166
  }
166
167
  exports.renderScript = renderScript;
167
168
  async function renderScriptCustom(scriptData, outputPath, options, parseHandlers) {
168
- const { dumpNets = false, dumpData = false, showStats = false, environment } = options;
169
+ const { dumpNets = false, dumpData = false, showStats = false, environment, inputPath = null, updateSource = false, saveAnnotatedCopy = undefined, } = options;
169
170
  const errors = [];
170
171
  const onErrorHandler = (message, context, error) => {
171
172
  if (error && error instanceof utils_js_1.RuntimeExecutionError) {
@@ -209,7 +210,7 @@ async function renderScriptCustom(scriptData, outputPath, options, parseHandlers
209
210
  (0, fs_1.mkdirSync)(dumpDirectory);
210
211
  }
211
212
  }
212
- const { tree, parser, parserTimeTaken, lexerTimeTaken, throwError } = await (0, parser_js_1.parseFileWithVisitor)(visitor, scriptData);
213
+ const { tree, parser, tokens, parserTimeTaken, lexerTimeTaken, throwError } = await (0, parser_js_1.parseFileWithVisitor)(visitor, scriptData);
213
214
  (0, utils_js_1.printWarnings)(visitor.getWarnings());
214
215
  showStats && console.log('Lexing took:', lexerTimeTaken);
215
216
  showStats && console.log('Parsing took:', parserTimeTaken);
@@ -219,6 +220,23 @@ async function renderScriptCustom(scriptData, outputPath, options, parseHandlers
219
220
  catch (err) {
220
221
  throw new utils_js_1.RenderError(`Error during component annotation: ${err}`, 'annotation');
221
222
  }
223
+ const componentLinks = visitor.getComponentCtxLinks();
224
+ const refdesVisitor = new RefdesAnnotationVisitor_js_1.RefdesAnnotationVisitor(true, scriptData, tokens, componentLinks);
225
+ await refdesVisitor.visitAsync(tree);
226
+ if (inputPath && (updateSource || saveAnnotatedCopy !== undefined)) {
227
+ let usePath = inputPath;
228
+ if (saveAnnotatedCopy === true) {
229
+ const dir = path_1.default.dirname(inputPath);
230
+ const ext = path_1.default.extname(inputPath);
231
+ const basename = path_1.default.basename(inputPath, ext);
232
+ usePath = path_1.default.join(dir, `${basename}.annotated${ext}`);
233
+ }
234
+ else if (typeof saveAnnotatedCopy === 'string') {
235
+ usePath = saveAnnotatedCopy;
236
+ }
237
+ console.log('Annotations saved to ' + usePath);
238
+ (0, fs_1.writeFileSync)(usePath, refdesVisitor.getOutput());
239
+ }
222
240
  if (dumpNets) {
223
241
  const nets = visitor.dumpNets();
224
242
  nets.forEach(item => console.log(item.join(" | ")));
package/dist/cjs/lexer.js CHANGED
@@ -26,12 +26,14 @@ class MainLexer extends CircuitScriptLexer_js_1.CircuitScriptLexer {
26
26
  this.tokens = this.tokens.filter(function (val) {
27
27
  return val.type !== CircuitScriptParser_js_1.CircuitScriptParser.EOF;
28
28
  });
29
- this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.NEWLINE, "\n"));
29
+ const fillerNewLine = this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.NEWLINE, "");
30
+ this.emitToken(fillerNewLine);
31
+ fillerNewLine.__skip = true;
30
32
  while (this.indents.length) {
31
33
  this.emitToken(this.createDedent());
32
34
  this.indents.pop();
33
35
  }
34
- this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.EOF, "<EOF>"));
36
+ this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.EOF, ""));
35
37
  }
36
38
  const next = super.nextToken();
37
39
  return this.tokens.length ? this.tokens.shift() : next;
@@ -42,16 +44,24 @@ class MainLexer extends CircuitScriptLexer_js_1.CircuitScriptLexer {
42
44
  getCharIndex() {
43
45
  return this.inputStream.index;
44
46
  }
45
- commonToken(type, text) {
46
- const stop = this.getCharIndex() - 1;
47
- const start = text.length ? stop - text.length + 1 : stop;
47
+ commonToken(type, text, start = -1, stop = -1) {
48
+ if (start === -1 && stop === -1) {
49
+ stop = this.getCharIndex() - 1;
50
+ start = text.length ? stop - text.length + 1 : stop;
51
+ }
48
52
  const token = antlr4ng_1.CommonToken.fromSource([this, this.inputStream], type, 0, start, stop);
49
53
  let tokenTypeString = null;
50
54
  if (type === CircuitScriptParser_js_1.CircuitScriptParser.INDENT) {
51
- tokenTypeString = "indent";
55
+ tokenTypeString = 'indent';
52
56
  }
53
57
  else if (type === CircuitScriptParser_js_1.CircuitScriptParser.DEDENT) {
54
- tokenTypeString = "dedent";
58
+ tokenTypeString = 'dedent';
59
+ }
60
+ else if (type === CircuitScriptParser_js_1.CircuitScriptParser.NEWLINE) {
61
+ tokenTypeString = 'newline';
62
+ }
63
+ else if (type === CircuitScriptParser_js_1.CircuitScriptParser.EOF) {
64
+ tokenTypeString = 'EOF';
55
65
  }
56
66
  if (tokenTypeString !== null) {
57
67
  token.text = tokenTypeString;
@@ -89,7 +99,9 @@ class MainLexer extends CircuitScriptLexer_js_1.CircuitScriptLexer {
89
99
  this.skip();
90
100
  }
91
101
  else {
92
- this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.NEWLINE, newLine));
102
+ const start = this.getCharIndex() - this.text.length;
103
+ const stop = this.getCharIndex() - 1;
104
+ this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.NEWLINE, newLine, start, start));
93
105
  const indent = this.getIndentationCount(spaces);
94
106
  const previous = this.indents.length ? this.indents[this.indents.length - 1] : 0;
95
107
  if (indent === previous) {
@@ -97,7 +109,7 @@ class MainLexer extends CircuitScriptLexer_js_1.CircuitScriptLexer {
97
109
  }
98
110
  else if (indent > previous) {
99
111
  this.indents.push(indent);
100
- this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.INDENT, spaces));
112
+ this.emitToken(this.commonToken(CircuitScriptParser_js_1.CircuitScriptParser.INDENT, spaces, start + 1, stop));
101
113
  }
102
114
  else {
103
115
  while (this.indents.length && this.indents[this.indents.length - 1] > indent) {
package/dist/cjs/main.js CHANGED
@@ -20,6 +20,8 @@ async function main() {
20
20
  .argument('[output path]', 'Output path')
21
21
  .option('-i, --input text <input text>', 'Input text directly')
22
22
  .option('-c, --current-directory <path>', 'Set current directory')
23
+ .option('-u, --update-source', 'Update source file with refdes annotation')
24
+ .option('-j, --annotated-path [file-path]', 'Save annotated source file at given path')
23
25
  .option('-w, --watch', 'Watch for file changes')
24
26
  .option('-n, --dump-nets', 'Dump out net information')
25
27
  .option('-d, --dump-data', 'Dump data during parsing')
@@ -67,11 +69,22 @@ async function main() {
67
69
  console.error("Error: No input provided");
68
70
  return;
69
71
  }
72
+ let updateSource = false;
73
+ if (options.updateSource !== undefined) {
74
+ updateSource = options.updateSource;
75
+ }
76
+ let saveAnnotatedCopyPath = undefined;
77
+ if (options.annotatedPath !== undefined) {
78
+ saveAnnotatedCopyPath = options.annotatedPath;
79
+ }
70
80
  const scriptOptions = {
71
81
  dumpNets,
72
82
  dumpData,
73
83
  showStats: options.stats,
74
84
  environment: env,
85
+ inputPath: inputFilePath,
86
+ updateSource,
87
+ saveAnnotatedCopy: saveAnnotatedCopyPath,
75
88
  };
76
89
  let outputPath = null;
77
90
  if (args.length > 0 && args[1]) {
@@ -28,6 +28,9 @@ class ClassComponent {
28
28
  this.useWireOrientationAngle = true;
29
29
  this.didSetWireOrientationAngle = false;
30
30
  this.assignedRefDes = null;
31
+ this.placeHolderRefDes = null;
32
+ this.ctxReferences = [];
33
+ this._creationIndex = -1;
31
34
  this.instanceName = instanceName;
32
35
  this.numPins = numPins;
33
36
  }
@@ -106,7 +109,7 @@ class ClassComponent {
106
109
  return this.parameters.get(key);
107
110
  }
108
111
  else {
109
- throw 'Invalid parameter key';
112
+ throw 'Invalid parameter key: ' + key;
110
113
  }
111
114
  }
112
115
  toString() {
@@ -9,6 +9,7 @@ class ExecutionScope {
9
9
  this.nets = [];
10
10
  this.instances = new Map();
11
11
  this.functions = new Map();
12
+ this.functionCounter = new Map();
12
13
  this.variables = new Map();
13
14
  this.symbols = new Map();
14
15
  this.blockStack = new Map();
@@ -38,6 +38,7 @@ async function parseFileWithVisitor(visitor, data) {
38
38
  const parserTimeTaken = parserTimer.lap();
39
39
  return {
40
40
  tree, parser,
41
+ tokens,
41
42
  hasParseError: false,
42
43
  hasError: false,
43
44
  parserTimeTaken,
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VisitorExecutionException = exports.ParserVisitor = void 0;
3
+ exports.VisitorExecutionException = exports.ComponentRefDesPrefixes = exports.ParserVisitor = void 0;
4
4
  const ClassComponent_js_1 = require("./objects/ClassComponent.js");
5
5
  const ParamDefinition_js_1 = require("./objects/ParamDefinition.js");
6
6
  const PinDefinition_js_1 = require("./objects/PinDefinition.js");
@@ -13,9 +13,11 @@ const BaseVisitor_js_1 = require("./BaseVisitor.js");
13
13
  const utils_js_2 = require("./utils.js");
14
14
  const helpers_js_1 = require("./helpers.js");
15
15
  const Frame_js_1 = require("./objects/Frame.js");
16
+ const ComponentAnnotater_js_1 = require("./ComponentAnnotater.js");
16
17
  class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
17
18
  constructor() {
18
19
  super(...arguments);
20
+ this.componentCreationIndex = 0;
19
21
  this.visitKeyword_assignment_expr = (ctx) => {
20
22
  const id = ctx.ID().getText();
21
23
  const value = this.visitResult(ctx.data_expr());
@@ -40,28 +42,53 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
40
42
  }
41
43
  this.setResult(ctx, pinId);
42
44
  };
45
+ this.trackNewComponentCreated = (callback) => {
46
+ const preCreatedIndex = this.componentCreationIndex;
47
+ callback();
48
+ const postCreatedIndex = this.componentCreationIndex;
49
+ let creationFlag = false;
50
+ if (postCreatedIndex > preCreatedIndex) {
51
+ creationFlag = true;
52
+ }
53
+ return creationFlag;
54
+ };
43
55
  this.visitAdd_component_expr = (ctx) => {
44
- const [component, pinValue] = this.visitResult(ctx.data_expr_with_assignment());
45
- this.getExecutor().addComponentExisting(component, pinValue);
56
+ let refComponent;
57
+ const creationFlag = this.trackNewComponentCreated(() => {
58
+ const [component, pinValue] = this.visitResult(ctx.data_expr_with_assignment());
59
+ this.getExecutor().addComponentExisting(component, pinValue);
60
+ refComponent = component;
61
+ });
62
+ this.linkComponentToCtx(ctx, refComponent, creationFlag);
46
63
  };
47
64
  this.visitAt_component_expr = (ctx) => {
48
- const [component, pin] = this.visitResult(ctx.component_select_expr());
49
- this.getExecutor().atComponent(component, pin, {
50
- addSequence: true
65
+ let refComponent;
66
+ const creationFlag = this.trackNewComponentCreated(() => {
67
+ const [component, pin] = this.visitResult(ctx.component_select_expr());
68
+ this.getExecutor().atComponent(component, pin, {
69
+ addSequence: true
70
+ });
71
+ refComponent = component;
51
72
  });
73
+ this.linkComponentToCtx(ctx, refComponent, creationFlag);
52
74
  return this.getExecutor().getCurrentPoint();
53
75
  };
54
76
  this.visitTo_component_expr = (ctx) => {
55
77
  ctx.component_select_expr().forEach(item => {
56
- const [component, pin] = this.visitResult(item);
57
- try {
58
- this.getExecutor().toComponent(component, pin, {
59
- addSequence: true
60
- });
61
- }
62
- catch (err) {
63
- throw new utils_js_2.RuntimeExecutionError(err.message, ctx);
64
- }
78
+ let refComponent;
79
+ const creationFlag = this.trackNewComponentCreated(() => {
80
+ const [component, pin] = this.visitResult(item);
81
+ try {
82
+ this.getExecutor().toComponent(component, pin, {
83
+ addSequence: true
84
+ });
85
+ refComponent = component;
86
+ }
87
+ catch (err) {
88
+ throw new utils_js_2.RuntimeExecutionError(err.message, ctx);
89
+ }
90
+ });
91
+ this.linkComponentToCtx(item, refComponent, creationFlag);
65
92
  });
66
93
  return this.getExecutor().getCurrentPoint();
67
94
  };
@@ -332,6 +359,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
332
359
  try {
333
360
  const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
334
361
  this.setResult(ctx, createdComponent);
362
+ createdComponent._creationIndex = this.componentCreationIndex++;
335
363
  }
336
364
  catch (error) {
337
365
  this.throwWithContext(ctx, error.message);
@@ -822,7 +850,28 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
822
850
  const resolveNet = this.createNetResolver(this.executionStack);
823
851
  const resolveComponentPinNet = this.createComponentPinNetResolver(this.executionStack);
824
852
  const __runFunc = (passedInParameters, options) => {
825
- const executionContextName = `${functionName}-${functionCounter['counter']}`;
853
+ const executor = this.getExecutor();
854
+ const parentBreakContext = executor.getParentBreakContext();
855
+ executor.addBreakContext(ctx);
856
+ let useIndex = -1;
857
+ if (parentBreakContext === null) {
858
+ useIndex = options.functionCallIndex;
859
+ }
860
+ else {
861
+ const parentEntry = executor.indexedStack.get(parentBreakContext);
862
+ const { funcCallIndex } = parentEntry;
863
+ if (!funcCallIndex.has(ctx)) {
864
+ funcCallIndex.set(ctx, 0);
865
+ useIndex = 0;
866
+ }
867
+ else {
868
+ useIndex = funcCallIndex.get(ctx) + 1;
869
+ funcCallIndex.set(ctx, useIndex);
870
+ }
871
+ }
872
+ executor.setBreakContextIndex(useIndex);
873
+ const functionCounterIndex = functionCounter['counter'];
874
+ const executionContextName = `${functionName}-${functionCounterIndex}`;
826
875
  const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, options, funcDefinedParameters, passedInParameters);
827
876
  functionCounter['counter'] += 1;
828
877
  newExecutor.resolveNet = resolveNet;
@@ -830,7 +879,23 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
830
879
  const returnValue = this.runExpressions(newExecutor, ctx.function_expr());
831
880
  const lastExecution = executionStack.pop();
832
881
  const nextLastExecution = executionStack[executionStack.length - 1];
833
- nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
882
+ const mergedComponents = nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
883
+ const scope = this.getScope();
884
+ const indexedStack = [];
885
+ if (scope.breakStack.length > 0) {
886
+ const executor = this.getExecutor();
887
+ scope.breakStack.forEach(stackCtx => {
888
+ const entry = executor.indexedStack.get(stackCtx);
889
+ const { index } = entry;
890
+ indexedStack.push([stackCtx, index]);
891
+ });
892
+ mergedComponents.forEach(component => {
893
+ component.ctxReferences.forEach(ref => {
894
+ ref.indexedStack = [...indexedStack, ...ref.indexedStack];
895
+ });
896
+ });
897
+ }
898
+ executor.popBreakContext();
834
899
  return [lastExecution, returnValue];
835
900
  };
836
901
  this.getExecutor().createFunction(functionName, __runFunc, ctx, uniqueFunctionID);
@@ -874,10 +939,21 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
874
939
  executor.log('end at block pin expressions');
875
940
  executor.atComponent(currentComponent, currentPin);
876
941
  };
942
+ this.visitAt_block_header = (ctx) => {
943
+ const ctxAtComponent = ctx.at_component_expr();
944
+ this.visit(ctxAtComponent);
945
+ const [currentComponent,] = this.getExecutor().getCurrentPoint();
946
+ this.componentCtxLinks.delete(ctxAtComponent);
947
+ this.componentCtxLinks.set(ctx, currentComponent);
948
+ ctx.annotation_comment_expr().forEach(ctx => {
949
+ this.visit(ctx);
950
+ });
951
+ };
877
952
  this.visitAt_block = (ctx) => {
878
953
  const executor = this.getExecutor();
879
954
  executor.log('entering at block');
880
- this.visit(ctx.at_component_expr());
955
+ const ctxAtBlockComponent = ctx.at_block_header();
956
+ this.visit(ctxAtBlockComponent);
881
957
  const [currentComponent, currentPin] = executor.getCurrentPoint();
882
958
  executor.scope.scopeLevel += 1;
883
959
  ctx.at_block_expressions().forEach(expression => {
@@ -1037,10 +1113,14 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1037
1113
  const dataExpr = ctx.data_expr();
1038
1114
  let keepLooping = true;
1039
1115
  this.log('enter while loop');
1040
- this.getExecutor().addBreakContext(ctx);
1116
+ const executor = this.getExecutor();
1117
+ executor.addBreakContext(ctx);
1118
+ let counter = 0;
1041
1119
  while (keepLooping) {
1042
1120
  const result = this.visitResult(dataExpr);
1043
1121
  if (result) {
1122
+ executor.setBreakContextIndex(counter);
1123
+ executor.resetBreakContextFunctionCalls();
1044
1124
  this.visit(ctx.expressions_block());
1045
1125
  keepLooping = true;
1046
1126
  const currentResult = this.getResult(ctx) ?? {};
@@ -1055,6 +1135,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1055
1135
  continueSignal: false
1056
1136
  });
1057
1137
  }
1138
+ counter++;
1058
1139
  }
1059
1140
  else {
1060
1141
  keepLooping = false;
@@ -1068,7 +1149,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1068
1149
  const forVariableNames = ctx.ID().map(item => item.getText());
1069
1150
  let listItems = this.visitResult(ctx.data_expr());
1070
1151
  listItems = (0, utils_js_1.unwrapValue)(listItems);
1071
- this.getExecutor().addBreakContext(ctx);
1152
+ const executor = this.getExecutor();
1153
+ executor.addBreakContext(ctx);
1072
1154
  let keepLooping = true;
1073
1155
  let counter = 0;
1074
1156
  while (keepLooping) {
@@ -1080,6 +1162,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1080
1162
  useValueArray.forEach((value, index) => {
1081
1163
  this.getScope().setVariable(forVariableNames[index], value);
1082
1164
  });
1165
+ executor.setBreakContextIndex(counter);
1166
+ executor.resetBreakContextFunctionCalls();
1083
1167
  this.visit(ctx.expressions_block());
1084
1168
  keepLooping = true;
1085
1169
  const currentResult = this.getResult(ctx) ?? {};
@@ -1101,7 +1185,19 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1101
1185
  keepLooping = false;
1102
1186
  }
1103
1187
  }
1104
- this.getExecutor().popBreakContext();
1188
+ executor.popBreakContext();
1189
+ };
1190
+ this.visitAnnotation_comment_expr = (ctx) => {
1191
+ const refdesID = ctx.ID().getText();
1192
+ const currentComponent = this.getScope().currentComponent;
1193
+ if (currentComponent !== null) {
1194
+ if (refdesID.indexOf('_') === -1) {
1195
+ currentComponent.setParam('refdes', refdesID);
1196
+ }
1197
+ else {
1198
+ currentComponent.placeHolderRefDes = refdesID;
1199
+ }
1200
+ }
1105
1201
  };
1106
1202
  this.pinTypes = [
1107
1203
  PinTypes_js_1.PinTypes.Any,
@@ -1346,7 +1442,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1346
1442
  }
1347
1443
  annotateComponents() {
1348
1444
  this.log('===== annotate components =====');
1349
- const annotater = new ComponentAnnotater();
1445
+ const annotater = new ComponentAnnotater_js_1.ComponentAnnotater();
1350
1446
  const instances = this.getScope().instances;
1351
1447
  const toAnnotate = [];
1352
1448
  for (const [, instance] of instances) {
@@ -1355,8 +1451,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1355
1451
  continue;
1356
1452
  }
1357
1453
  if (instance.assignedRefDes === null) {
1358
- if (instance.parameters.has('refdes')) {
1359
- const refdes = instance.parameters.get('refdes');
1454
+ if (instance.hasParam('refdes')) {
1455
+ const refdes = instance.getParam('refdes');
1360
1456
  if (refdes) {
1361
1457
  instance.assignedRefDes = refdes;
1362
1458
  annotater.trackRefDes(refdes);
@@ -1368,10 +1464,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1368
1464
  }
1369
1465
  }
1370
1466
  toAnnotate.forEach(instance => {
1371
- const useTypeProp = instance.typeProp ?? 'conn';
1372
- instance.typeProp === null
1373
- && this.log('Instance has no type:', instance.instanceName, ' assuming connector');
1374
- const newRefDes = annotater.getAnnotation(useTypeProp);
1467
+ const newRefDes = annotater.getAnnotation(instance);
1375
1468
  if (newRefDes !== null) {
1376
1469
  instance.assignedRefDes = newRefDes;
1377
1470
  this.log(newRefDes, '-', instance.instanceName);
@@ -1456,7 +1549,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1456
1549
  }
1457
1550
  }
1458
1551
  exports.ParserVisitor = ParserVisitor;
1459
- const ComponentRefDesPrefixes = {
1552
+ exports.ComponentRefDesPrefixes = {
1460
1553
  res: 'R',
1461
1554
  cap: 'C',
1462
1555
  ind: 'L',
@@ -1467,48 +1560,6 @@ const ComponentRefDesPrefixes = {
1467
1560
  ic: 'U',
1468
1561
  '?': '?',
1469
1562
  };
1470
- class ComponentAnnotater {
1471
- constructor() {
1472
- this.counter = {};
1473
- this.existingRefDes = [];
1474
- for (const key in ComponentRefDesPrefixes) {
1475
- this.counter[key] = 1;
1476
- }
1477
- }
1478
- getAnnotation(type) {
1479
- if (this.counter[type] === undefined && type.length <= 2) {
1480
- for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
1481
- if (value === type) {
1482
- throw "Refdes prefix is already in use!";
1483
- }
1484
- }
1485
- if (ComponentRefDesPrefixes[type] === undefined) {
1486
- ComponentRefDesPrefixes[type] = type;
1487
- this.counter[type] = 1;
1488
- }
1489
- }
1490
- if (ComponentRefDesPrefixes[type] === undefined) {
1491
- return null;
1492
- }
1493
- let attempts = 100;
1494
- let proposedName = "";
1495
- while (attempts >= 0) {
1496
- proposedName = ComponentRefDesPrefixes[type] + this.counter[type];
1497
- this.counter[type]++;
1498
- if (this.existingRefDes.indexOf(proposedName) === -1) {
1499
- break;
1500
- }
1501
- attempts--;
1502
- }
1503
- if (attempts === 0) {
1504
- throw "Annotation failed!";
1505
- }
1506
- return proposedName;
1507
- }
1508
- trackRefDes(name) {
1509
- this.existingRefDes.push(name);
1510
- }
1511
- }
1512
1563
  class VisitorExecutionException {
1513
1564
  constructor(context, errorMessage) {
1514
1565
  this.errorMessage = errorMessage;