circuitscript 0.1.19 → 0.1.22

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 (50) 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 +964 -831
  6. package/dist/cjs/environment.js +15 -1
  7. package/dist/cjs/execute.js +45 -2
  8. package/dist/cjs/graph.js +23 -2
  9. package/dist/cjs/helpers.js +21 -4
  10. package/dist/cjs/layout.js +3 -0
  11. package/dist/cjs/lexer.js +21 -9
  12. package/dist/cjs/main.js +13 -0
  13. package/dist/cjs/objects/ClassComponent.js +4 -1
  14. package/dist/cjs/objects/ExecutionScope.js +1 -0
  15. package/dist/cjs/parser.js +1 -0
  16. package/dist/cjs/visitor.js +119 -71
  17. package/dist/esm/BaseVisitor.js +22 -0
  18. package/dist/esm/ComponentAnnotater.js +84 -0
  19. package/dist/esm/RefdesAnnotationVisitor.js +196 -0
  20. package/dist/esm/antlr/CircuitScriptLexer.js +202 -197
  21. package/dist/esm/antlr/CircuitScriptParser.js +960 -829
  22. package/dist/esm/antlr/CircuitScriptVisitor.js +2 -0
  23. package/dist/esm/environment.js +15 -1
  24. package/dist/esm/execute.js +45 -2
  25. package/dist/esm/graph.js +23 -2
  26. package/dist/esm/helpers.js +21 -4
  27. package/dist/esm/layout.js +4 -0
  28. package/dist/esm/lexer.js +21 -9
  29. package/dist/esm/main.js +13 -0
  30. package/dist/esm/objects/ClassComponent.js +4 -1
  31. package/dist/esm/objects/ExecutionScope.js +1 -0
  32. package/dist/esm/parser.js +1 -0
  33. package/dist/esm/visitor.js +117 -69
  34. package/dist/types/BaseVisitor.d.ts +3 -0
  35. package/dist/types/ComponentAnnotater.d.ts +16 -0
  36. package/dist/types/RefdesAnnotationVisitor.d.ts +35 -0
  37. package/dist/types/antlr/CircuitScriptLexer.d.ts +15 -14
  38. package/dist/types/antlr/CircuitScriptParser.d.ts +80 -60
  39. package/dist/types/antlr/CircuitScriptVisitor.d.ts +4 -0
  40. package/dist/types/environment.d.ts +1 -0
  41. package/dist/types/execute.d.ts +8 -1
  42. package/dist/types/helpers.d.ts +6 -3
  43. package/dist/types/layout.d.ts +2 -0
  44. package/dist/types/lexer.d.ts +1 -1
  45. package/dist/types/objects/ClassComponent.d.ts +9 -0
  46. package/dist/types/objects/ExecutionScope.d.ts +2 -1
  47. package/dist/types/objects/types.d.ts +1 -0
  48. package/dist/types/parser.d.ts +2 -1
  49. package/dist/types/visitor.d.ts +8 -1
  50. package/package.json +1 -1
@@ -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,18 @@ 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
+ };
877
949
  this.visitAt_block = (ctx) => {
878
950
  const executor = this.getExecutor();
879
951
  executor.log('entering at block');
880
- this.visit(ctx.at_component_expr());
952
+ const ctxAtBlockComponent = ctx.at_block_header();
953
+ this.visit(ctxAtBlockComponent);
881
954
  const [currentComponent, currentPin] = executor.getCurrentPoint();
882
955
  executor.scope.scopeLevel += 1;
883
956
  ctx.at_block_expressions().forEach(expression => {
@@ -1037,10 +1110,14 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1037
1110
  const dataExpr = ctx.data_expr();
1038
1111
  let keepLooping = true;
1039
1112
  this.log('enter while loop');
1040
- this.getExecutor().addBreakContext(ctx);
1113
+ const executor = this.getExecutor();
1114
+ executor.addBreakContext(ctx);
1115
+ let counter = 0;
1041
1116
  while (keepLooping) {
1042
1117
  const result = this.visitResult(dataExpr);
1043
1118
  if (result) {
1119
+ executor.setBreakContextIndex(counter);
1120
+ executor.resetBreakContextFunctionCalls();
1044
1121
  this.visit(ctx.expressions_block());
1045
1122
  keepLooping = true;
1046
1123
  const currentResult = this.getResult(ctx) ?? {};
@@ -1055,6 +1132,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1055
1132
  continueSignal: false
1056
1133
  });
1057
1134
  }
1135
+ counter++;
1058
1136
  }
1059
1137
  else {
1060
1138
  keepLooping = false;
@@ -1068,7 +1146,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1068
1146
  const forVariableNames = ctx.ID().map(item => item.getText());
1069
1147
  let listItems = this.visitResult(ctx.data_expr());
1070
1148
  listItems = (0, utils_js_1.unwrapValue)(listItems);
1071
- this.getExecutor().addBreakContext(ctx);
1149
+ const executor = this.getExecutor();
1150
+ executor.addBreakContext(ctx);
1072
1151
  let keepLooping = true;
1073
1152
  let counter = 0;
1074
1153
  while (keepLooping) {
@@ -1080,6 +1159,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1080
1159
  useValueArray.forEach((value, index) => {
1081
1160
  this.getScope().setVariable(forVariableNames[index], value);
1082
1161
  });
1162
+ executor.setBreakContextIndex(counter);
1163
+ executor.resetBreakContextFunctionCalls();
1083
1164
  this.visit(ctx.expressions_block());
1084
1165
  keepLooping = true;
1085
1166
  const currentResult = this.getResult(ctx) ?? {};
@@ -1101,7 +1182,19 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1101
1182
  keepLooping = false;
1102
1183
  }
1103
1184
  }
1104
- this.getExecutor().popBreakContext();
1185
+ executor.popBreakContext();
1186
+ };
1187
+ this.visitAnnotation_comment_expr = (ctx) => {
1188
+ const refdesID = ctx.ID().getText();
1189
+ const currentComponent = this.getScope().currentComponent;
1190
+ if (currentComponent !== null) {
1191
+ if (refdesID.indexOf('_') === -1) {
1192
+ currentComponent.setParam('refdes', refdesID);
1193
+ }
1194
+ else {
1195
+ currentComponent.placeHolderRefDes = refdesID;
1196
+ }
1197
+ }
1105
1198
  };
1106
1199
  this.pinTypes = [
1107
1200
  PinTypes_js_1.PinTypes.Any,
@@ -1346,7 +1439,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1346
1439
  }
1347
1440
  annotateComponents() {
1348
1441
  this.log('===== annotate components =====');
1349
- const annotater = new ComponentAnnotater();
1442
+ const annotater = new ComponentAnnotater_js_1.ComponentAnnotater();
1350
1443
  const instances = this.getScope().instances;
1351
1444
  const toAnnotate = [];
1352
1445
  for (const [, instance] of instances) {
@@ -1355,8 +1448,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1355
1448
  continue;
1356
1449
  }
1357
1450
  if (instance.assignedRefDes === null) {
1358
- if (instance.parameters.has('refdes')) {
1359
- const refdes = instance.parameters.get('refdes');
1451
+ if (instance.hasParam('refdes')) {
1452
+ const refdes = instance.getParam('refdes');
1360
1453
  if (refdes) {
1361
1454
  instance.assignedRefDes = refdes;
1362
1455
  annotater.trackRefDes(refdes);
@@ -1368,10 +1461,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1368
1461
  }
1369
1462
  }
1370
1463
  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);
1464
+ const newRefDes = annotater.getAnnotation(instance);
1375
1465
  if (newRefDes !== null) {
1376
1466
  instance.assignedRefDes = newRefDes;
1377
1467
  this.log(newRefDes, '-', instance.instanceName);
@@ -1456,7 +1546,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1456
1546
  }
1457
1547
  }
1458
1548
  exports.ParserVisitor = ParserVisitor;
1459
- const ComponentRefDesPrefixes = {
1549
+ exports.ComponentRefDesPrefixes = {
1460
1550
  res: 'R',
1461
1551
  cap: 'C',
1462
1552
  ind: 'L',
@@ -1467,48 +1557,6 @@ const ComponentRefDesPrefixes = {
1467
1557
  ic: 'U',
1468
1558
  '?': '?',
1469
1559
  };
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
1560
  class VisitorExecutionException {
1513
1561
  constructor(context, errorMessage) {
1514
1562
  this.errorMessage = errorMessage;
@@ -23,6 +23,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
23
23
  acceptedDirections = [Direction.Up, Direction.Down,
24
24
  Direction.Right, Direction.Left];
25
25
  resultData = new Map;
26
+ componentCtxLinks = new Map;
26
27
  pinTypesList = [
27
28
  PinTypes.Any,
28
29
  PinTypes.Input,
@@ -564,6 +565,27 @@ export class BaseVisitor extends CircuitScriptVisitor {
564
565
  getResult(ctx) {
565
566
  return this.resultData.get(ctx);
566
567
  }
568
+ linkComponentToCtx(ctx, instance, creationFlag = true) {
569
+ const scope = this.getScope();
570
+ const indexedStack = [];
571
+ if (scope.breakStack.length > 0) {
572
+ const executor = this.getExecutor();
573
+ scope.breakStack.forEach(stackCtx => {
574
+ const entry = executor.indexedStack.get(stackCtx);
575
+ const { index } = entry;
576
+ indexedStack.push([stackCtx, index]);
577
+ });
578
+ }
579
+ instance.ctxReferences.push({
580
+ ctx,
581
+ indexedStack,
582
+ creationFlag
583
+ });
584
+ this.componentCtxLinks.set(ctx, instance);
585
+ }
586
+ getComponentCtxLinks() {
587
+ return this.componentCtxLinks;
588
+ }
567
589
  visitResult(ctx) {
568
590
  this.visit(ctx);
569
591
  return this.getResult(ctx);
@@ -0,0 +1,84 @@
1
+ import { ComponentRefDesPrefixes } from './visitor.js';
2
+ export class ComponentAnnotater {
3
+ counter = {};
4
+ indexedContextPrefix = new Map();
5
+ existingRefDes = [];
6
+ constructor() {
7
+ for (const key in ComponentRefDesPrefixes) {
8
+ this.counter[key] = 1;
9
+ }
10
+ }
11
+ getAnnotation(instance) {
12
+ const type = instance.typeProp ?? 'conn';
13
+ if (this.counter[type] === undefined && type.length <= 2) {
14
+ for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
15
+ if (value === type) {
16
+ throw "Refdes prefix is already in use!";
17
+ }
18
+ }
19
+ if (ComponentRefDesPrefixes[type] === undefined) {
20
+ ComponentRefDesPrefixes[type] = type;
21
+ this.counter[type] = 1;
22
+ }
23
+ }
24
+ if (ComponentRefDesPrefixes[type] === undefined) {
25
+ return null;
26
+ }
27
+ let prefix = '';
28
+ let resultRefdes = '';
29
+ const { ctxReferences } = instance;
30
+ if (ctxReferences.length > 0) {
31
+ const firstReference = ctxReferences[0];
32
+ const { ctx: useCtx, indexedStack, creationFlag } = firstReference;
33
+ if (indexedStack.length > 0 && creationFlag) {
34
+ const indexes = indexedStack.map(item => {
35
+ return item[1] + 1;
36
+ });
37
+ if (!this.indexedContextPrefix.has(useCtx)) {
38
+ if (instance.placeHolderRefDes) {
39
+ prefix = instance.placeHolderRefDes.replaceAll('_', '');
40
+ }
41
+ else {
42
+ const { index: nextIndex, proposedName } = this.getNextRefdesCounter(ComponentRefDesPrefixes[type], this.counter[type]);
43
+ this.counter[type] = nextIndex;
44
+ prefix = proposedName;
45
+ }
46
+ this.existingRefDes.push(prefix);
47
+ this.indexedContextPrefix.set(useCtx, prefix);
48
+ }
49
+ const prefixParts = [this.indexedContextPrefix.get(useCtx), ...indexes];
50
+ resultRefdes = prefixParts.join('_');
51
+ if (this.existingRefDes.indexOf(resultRefdes) !== -1) {
52
+ console.log('Warning: Refdes already used:', resultRefdes);
53
+ }
54
+ }
55
+ else {
56
+ const refdesCounter = this.getNextRefdesCounter(ComponentRefDesPrefixes[type], this.counter[type]);
57
+ this.counter[type] = refdesCounter.index;
58
+ resultRefdes = refdesCounter.proposedName;
59
+ }
60
+ this.existingRefDes.push(resultRefdes);
61
+ return resultRefdes;
62
+ }
63
+ }
64
+ getNextRefdesCounter(prefix, startingIndex) {
65
+ let attempts = 100;
66
+ let proposedName = "";
67
+ let index = startingIndex;
68
+ while (attempts >= 0) {
69
+ proposedName = prefix + index;
70
+ index++;
71
+ if (this.existingRefDes.indexOf(proposedName) === -1) {
72
+ break;
73
+ }
74
+ attempts--;
75
+ }
76
+ if (attempts === 0) {
77
+ throw "Annotation failed";
78
+ }
79
+ return { index, proposedName };
80
+ }
81
+ trackRefDes(name) {
82
+ this.existingRefDes.push(name);
83
+ }
84
+ }
@@ -0,0 +1,196 @@
1
+ import { CircuitScriptParser } from './antlr/CircuitScriptParser.js';
2
+ import { BaseVisitor } from './BaseVisitor.js';
3
+ export class RefdesAnnotationVisitor extends BaseVisitor {
4
+ sourceText;
5
+ tokenStream;
6
+ modifications = new Map();
7
+ resultText = '';
8
+ debug = false;
9
+ componentCtxLinks;
10
+ constructor(silent, sourceText, tokenStream, componentCtxLinks) {
11
+ super(true);
12
+ this.sourceText = sourceText;
13
+ this.tokenStream = tokenStream;
14
+ this.componentCtxLinks = componentCtxLinks;
15
+ }
16
+ getOriginalText(ctx) {
17
+ if (!ctx.start || !ctx.stop) {
18
+ return '';
19
+ }
20
+ const startIndex = ctx.start.start;
21
+ const stopIndex = ctx.stop.stop;
22
+ return this.sourceText.substring(startIndex, stopIndex + 1);
23
+ }
24
+ visitScript = async (ctx) => {
25
+ const result = this.runExpressions(this.getExecutor(), ctx.expression());
26
+ this.setResult(ctx, result);
27
+ this.getExecutor().closeOpenPathBlocks();
28
+ this.resultText = this.generateModifiedText();
29
+ };
30
+ visitAdd_component_expr = (ctx) => {
31
+ this.addRefdesAnnotationComment(ctx);
32
+ };
33
+ visitAt_component_expr = (ctx) => {
34
+ this.addRefdesAnnotationComment(ctx);
35
+ };
36
+ visitComponent_select_expr = (ctx) => {
37
+ this.addRefdesAnnotationComment(ctx);
38
+ };
39
+ visitAt_block_header = (ctx) => {
40
+ this.addRefdesAnnotationComment(ctx);
41
+ };
42
+ visitAt_block = (ctx) => {
43
+ this.visit(ctx.at_block_header());
44
+ ctx.at_block_expressions().forEach(expression => {
45
+ this.visit(expression);
46
+ });
47
+ };
48
+ visitTo_component_expr = (ctx) => {
49
+ const allRefdes = [];
50
+ ctx.component_select_expr().forEach(itemCtx => {
51
+ const tmpRefdes = this.generateRefdesAnnotationComment(itemCtx);
52
+ if (tmpRefdes !== null) {
53
+ allRefdes.push(tmpRefdes);
54
+ }
55
+ });
56
+ if (allRefdes.length > 0) {
57
+ const originalText = this.getOriginalText(ctx);
58
+ const annotation = ' #= ' + allRefdes.join(',');
59
+ this.modifications.set(ctx, originalText + annotation);
60
+ }
61
+ };
62
+ visitFunction_def_expr = (ctx) => {
63
+ this.runExpressions(this.getExecutor(), ctx.function_expr());
64
+ };
65
+ visitFunction_return_expr = (ctx) => {
66
+ };
67
+ visitFrame_expr = (ctx) => {
68
+ this.visit(ctx.expressions_block());
69
+ };
70
+ visitFunction_call_expr = (ctx) => {
71
+ };
72
+ visitParameters = (ctx) => {
73
+ };
74
+ addedRefdesAnnotations = [];
75
+ generateRefdesAnnotationComment(ctx) {
76
+ if (this.componentCtxLinks.has(ctx)) {
77
+ const instance = this.componentCtxLinks.get(ctx);
78
+ const alreadyHaveRefdesAnnotation = instance.assignedRefDes !== null ?
79
+ (this.addedRefdesAnnotations.indexOf(instance.assignedRefDes) !== -1) : false;
80
+ if (!instance.hasParam('refdes')
81
+ && instance.placeHolderRefDes === null
82
+ && instance.assignedRefDes
83
+ && !alreadyHaveRefdesAnnotation) {
84
+ let useRefDes = instance.assignedRefDes;
85
+ let isPlaceholderRefdes = false;
86
+ const { ctxReferences } = instance;
87
+ if (ctxReferences.length > 0) {
88
+ const firstReference = ctxReferences[0];
89
+ const { indexedStack: loopStack = [] } = firstReference;
90
+ if (loopStack.length > 0) {
91
+ isPlaceholderRefdes = true;
92
+ const parts = instance.assignedRefDes.split('_');
93
+ useRefDes = parts[0] + '_';
94
+ }
95
+ if (this.addedRefdesAnnotations.indexOf(instance.assignedRefDes) === -1
96
+ && !isPlaceholderRefdes) {
97
+ this.addedRefdesAnnotations.push(instance.assignedRefDes);
98
+ }
99
+ return useRefDes;
100
+ }
101
+ }
102
+ }
103
+ return null;
104
+ }
105
+ addRefdesAnnotationComment(ctx) {
106
+ const refdes = this.generateRefdesAnnotationComment(ctx);
107
+ if (refdes !== null) {
108
+ const originalText = this.getOriginalText(ctx);
109
+ const annotation = ' #= ' + refdes;
110
+ this.modifications.set(ctx, originalText + annotation);
111
+ }
112
+ }
113
+ getOutput() {
114
+ return this.resultText;
115
+ }
116
+ generateModifiedText() {
117
+ const output = [];
118
+ const allTokens = this.tokenStream.getTokens();
119
+ const processedTokens = new Set();
120
+ let lastSourcePos = 0;
121
+ const contextTokenRanges = this.buildContextTokenRanges();
122
+ for (let i = 0; i < allTokens.length; i++) {
123
+ const token = allTokens[i];
124
+ if (processedTokens.has(i)) {
125
+ continue;
126
+ }
127
+ const tokenText = this.sourceText.substring(token.start, token.stop + 1);
128
+ this.log(i, `token: [${tokenText}], length: ${tokenText.length}, text: [${token.text}]`);
129
+ if (token.type === CircuitScriptParser.DEDENT
130
+ || token.type === CircuitScriptParser.EOF
131
+ || (token.type === CircuitScriptParser.NEWLINE && token.__skip)) {
132
+ this.log('--skip dedent/EOF token');
133
+ continue;
134
+ }
135
+ const ctx = this.findContextForToken(token, contextTokenRanges);
136
+ if (ctx) {
137
+ const isFirstTokenInContext = token.tokenIndex === ctx.start?.tokenIndex;
138
+ if (isFirstTokenInContext) {
139
+ if (token.start > lastSourcePos) {
140
+ output.push(this.sourceText.substring(lastSourcePos, token.start));
141
+ }
142
+ if (this.modifications.has(ctx)) {
143
+ output.push(this.modifications.get(ctx));
144
+ this.markTokensAsProcessed(ctx, processedTokens);
145
+ if (ctx.stop) {
146
+ lastSourcePos = ctx.stop.stop + 1;
147
+ }
148
+ continue;
149
+ }
150
+ }
151
+ }
152
+ if (token.start > lastSourcePos) {
153
+ output.push(this.sourceText.substring(lastSourcePos, token.start));
154
+ }
155
+ if (tokenText.length > 0) {
156
+ output.push(tokenText);
157
+ }
158
+ processedTokens.add(i);
159
+ lastSourcePos = token.stop + 1;
160
+ }
161
+ if (lastSourcePos < this.sourceText.length) {
162
+ output.push(this.sourceText.substring(lastSourcePos));
163
+ }
164
+ return output.join('');
165
+ }
166
+ buildContextTokenRanges() {
167
+ const ranges = new Map();
168
+ for (const ctx of this.modifications.keys()) {
169
+ if (ctx.start && ctx.stop) {
170
+ ranges.set(ctx, [ctx.start.tokenIndex, ctx.stop.tokenIndex]);
171
+ }
172
+ }
173
+ return ranges;
174
+ }
175
+ findContextForToken(token, contextRanges) {
176
+ for (const [ctx, [start, end]] of contextRanges) {
177
+ if (token.tokenIndex >= start && token.tokenIndex <= end) {
178
+ return ctx;
179
+ }
180
+ }
181
+ return null;
182
+ }
183
+ markTokensAsProcessed(ctx, processedTokens) {
184
+ if (!ctx.start || !ctx.stop) {
185
+ return;
186
+ }
187
+ for (let i = ctx.start.tokenIndex; i <= ctx.stop.tokenIndex; i++) {
188
+ processedTokens.add(i);
189
+ }
190
+ }
191
+ log(...message) {
192
+ if (this.debug) {
193
+ console.log(...message);
194
+ }
195
+ }
196
+ }