circuitscript 0.1.29 → 0.1.32

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 (71) hide show
  1. package/dist/cjs/BaseVisitor.js +185 -22
  2. package/dist/cjs/RefdesAnnotationVisitor.js +27 -10
  3. package/dist/cjs/antlr/CircuitScriptLexer.js +241 -236
  4. package/dist/cjs/antlr/CircuitScriptParser.js +1197 -901
  5. package/dist/cjs/builtinMethods.js +6 -2
  6. package/dist/cjs/draw_symbols.js +38 -34
  7. package/dist/cjs/environment.js +28 -4
  8. package/dist/cjs/execute.js +195 -125
  9. package/dist/cjs/globals.js +6 -1
  10. package/dist/cjs/graph.js +14 -12
  11. package/dist/cjs/helpers.js +90 -17
  12. package/dist/cjs/layout.js +50 -25
  13. package/dist/cjs/main.js +16 -14
  14. package/dist/cjs/objects/ClassComponent.js +199 -30
  15. package/dist/cjs/objects/ExecutionScope.js +9 -0
  16. package/dist/cjs/objects/types.js +25 -2
  17. package/dist/cjs/parser.js +6 -2
  18. package/dist/cjs/regenerate-tests.js +3 -3
  19. package/dist/cjs/render.js +5 -3
  20. package/dist/cjs/rules-check/no-connect-on-connected-pin.js +9 -8
  21. package/dist/cjs/rules-check/rules.js +7 -2
  22. package/dist/cjs/rules-check/unconnected-pins.js +10 -8
  23. package/dist/cjs/utils.js +2 -1
  24. package/dist/cjs/validate/SymbolTable.js +7 -1
  25. package/dist/cjs/validate/SymbolValidatorVisitor.js +54 -17
  26. package/dist/cjs/visitor.js +299 -238
  27. package/dist/esm/BaseVisitor.js +187 -24
  28. package/dist/esm/RefdesAnnotationVisitor.js +27 -10
  29. package/dist/esm/antlr/CircuitScriptLexer.js +241 -236
  30. package/dist/esm/antlr/CircuitScriptParser.js +1196 -899
  31. package/dist/esm/antlr/CircuitScriptVisitor.js +4 -1
  32. package/dist/esm/builtinMethods.js +7 -3
  33. package/dist/esm/draw_symbols.js +38 -34
  34. package/dist/esm/environment.js +25 -1
  35. package/dist/esm/execute.js +197 -127
  36. package/dist/esm/globals.js +4 -0
  37. package/dist/esm/graph.js +14 -12
  38. package/dist/esm/helpers.js +91 -18
  39. package/dist/esm/layout.js +51 -26
  40. package/dist/esm/main.js +16 -14
  41. package/dist/esm/objects/ClassComponent.js +201 -30
  42. package/dist/esm/objects/ExecutionScope.js +9 -0
  43. package/dist/esm/objects/types.js +33 -1
  44. package/dist/esm/parser.js +6 -2
  45. package/dist/esm/regenerate-tests.js +3 -3
  46. package/dist/esm/render.js +5 -3
  47. package/dist/esm/rules-check/no-connect-on-connected-pin.js +9 -8
  48. package/dist/esm/rules-check/rules.js +7 -2
  49. package/dist/esm/rules-check/unconnected-pins.js +10 -8
  50. package/dist/esm/utils.js +2 -1
  51. package/dist/esm/validate/SymbolTable.js +5 -0
  52. package/dist/esm/validate/SymbolValidatorVisitor.js +53 -16
  53. package/dist/esm/visitor.js +201 -137
  54. package/dist/types/BaseVisitor.d.ts +27 -10
  55. package/dist/types/RefdesAnnotationVisitor.d.ts +2 -0
  56. package/dist/types/antlr/CircuitScriptLexer.d.ts +43 -42
  57. package/dist/types/antlr/CircuitScriptParser.d.ts +102 -58
  58. package/dist/types/antlr/CircuitScriptVisitor.d.ts +8 -2
  59. package/dist/types/environment.d.ts +8 -1
  60. package/dist/types/execute.d.ts +6 -3
  61. package/dist/types/globals.d.ts +4 -0
  62. package/dist/types/graph.d.ts +2 -2
  63. package/dist/types/helpers.d.ts +2 -1
  64. package/dist/types/layout.d.ts +5 -4
  65. package/dist/types/objects/ClassComponent.d.ts +34 -9
  66. package/dist/types/objects/ExecutionScope.d.ts +3 -1
  67. package/dist/types/objects/types.d.ts +40 -3
  68. package/dist/types/validate/SymbolTable.d.ts +1 -0
  69. package/dist/types/validate/SymbolValidatorVisitor.d.ts +6 -6
  70. package/dist/types/visitor.d.ts +10 -2
  71. package/package.json +4 -1
@@ -1,25 +1,27 @@
1
1
  import { Big } from 'big.js';
2
+ import { Import_specificContext } from "./antlr/CircuitScriptParser.js";
2
3
  import { CircuitScriptVisitor } from "./antlr/CircuitScriptVisitor.js";
3
4
  import { ExecutionContext } from "./execute.js";
4
5
  import { Logger } from "./logger.js";
5
6
  import { ClassComponent } from "./objects/ClassComponent.js";
6
7
  import { NumberOperator, NumericValue, PercentageValue } from "./objects/ParamDefinition.js";
7
8
  import { PinTypes } from "./objects/PinTypes.js";
8
- import { Direction, AnyReference, UndeclaredReference } from "./objects/types.js";
9
- import { ComponentTypes, DoubleDelimiter1, GlobalDocumentName, ReferenceTypes, TrailerArrayIndex } from './globals.js';
9
+ import { Direction, AnyReference, UndeclaredReference, ImportedModule, ImportFunctionHandling as ImportFunctionHandling } from "./objects/types.js";
10
+ import { BaseNamespace, ComponentTypes, DoubleDelimiter1, GlobalDocumentName, ReferenceTypes, TrailerArrayIndex } from './globals.js';
10
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';
14
15
  import { PinId } from './objects/PinDefinition.js';
15
16
  export class BaseVisitor extends CircuitScriptVisitor {
16
- indentLevel = 0;
17
17
  startingContext;
18
18
  executionStack;
19
+ filePathStack = [];
19
20
  silent = false;
20
21
  logger;
21
22
  printStream = [];
22
23
  printToConsole = true;
24
+ allowParseImports = false;
23
25
  acceptedDirections = [Direction.Up, Direction.Down,
24
26
  Direction.Right, Direction.Left];
25
27
  resultData = new Map;
@@ -38,18 +40,14 @@ export class BaseVisitor extends CircuitScriptVisitor {
38
40
  onImportFile = async (visitor, filePath, fileData, onErrorHandler) => {
39
41
  throw "Import file not implemented";
40
42
  };
43
+ refdesFileAnnotations = new Map();
41
44
  constructor(silent = false, onErrorHandler = null, environment) {
42
45
  super();
43
46
  this.silent = silent;
44
47
  this.logger = new Logger();
45
48
  this.onErrorHandler = onErrorHandler;
46
49
  this.environment = environment;
47
- this.log('-- Environment --');
48
- this.log('Module directory: ' + environment.getModuleDirectory());
49
- this.log('Default libs path: ' + environment.getDefaultLibsPath());
50
- this.log('Current file: ' + environment.getCurrentFile());
51
- this.log('-----------------');
52
- this.startingContext = new ExecutionContext(DoubleDelimiter1, `${DoubleDelimiter1}.`, '/', 0, 0, silent, this.logger, this.warnings, null);
50
+ this.startingContext = new ExecutionContext(DoubleDelimiter1, BaseNamespace, '/', 0, 0, silent, this.logger, this.warnings, null);
53
51
  const scope = this.startingContext.scope;
54
52
  scope.sequence.push([
55
53
  SequenceAction.At, scope.componentRoot, scope.currentPin
@@ -111,8 +109,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
111
109
  };
112
110
  }
113
111
  log(...params) {
114
- const indentOutput = ''.padStart(this.indentLevel * 4, ' ');
115
- const indentLevelText = this.indentLevel.toString().padStart(3, ' ');
112
+ const indentLevel = this.getScope().scopeLevel;
113
+ const indentOutput = ''.padStart(indentLevel * 4, ' ');
114
+ const indentLevelText = indentLevel.toString().padStart(3, ' ');
116
115
  const args = ['[' + indentLevelText + ']', indentOutput, ...params];
117
116
  this.logger.add(args.join(' '));
118
117
  if (!this.silent) {
@@ -128,17 +127,47 @@ export class BaseVisitor extends CircuitScriptVisitor {
128
127
  }
129
128
  visitScript = async (ctx) => {
130
129
  this.log('===', 'start', '===');
131
- const imports = ctx.import_expr();
132
- for (let i = 0; i < imports.length; i++) {
133
- const ctxImport = imports[i];
134
- const ID = ctxImport.ID().toString();
135
- await this.handleImportFile(ID, true, ctxImport);
130
+ this.allowParseImports = true;
131
+ for (const ctxImport of ctx.import_expr()) {
132
+ await this.visit(ctxImport);
136
133
  }
134
+ this.allowParseImports = false;
137
135
  const result = this.runExpressions(this.getExecutor(), ctx.expression());
138
136
  this.setResult(ctx, result);
139
137
  this.getExecutor().closeOpenPathBlocks();
140
138
  this.log('===', 'end', '===');
141
139
  };
140
+ async importCommon(ctx, handling) {
141
+ const specificImports = [];
142
+ if (ctx instanceof Import_specificContext) {
143
+ const tmpSpecificImports = ctx._funcNames.map(item => {
144
+ return item.text;
145
+ });
146
+ specificImports.push(...tmpSpecificImports);
147
+ }
148
+ const id = ctx._moduleName.text;
149
+ const importedFile = await this.handleImportFile(id, handling, true, ctx, specificImports);
150
+ const ctxImportAnnotation = ctx.import_annotation_expr();
151
+ if (ctxImportAnnotation) {
152
+ const textValue = ctxImportAnnotation.getText().replace('#=', '');
153
+ const { importedModule } = importedFile;
154
+ if (textValue === 'annotate') {
155
+ importedModule.enableRefdesAnnotation = true;
156
+ }
157
+ else if (textValue === 'annotate-external') {
158
+ importedModule.enableRefdesAnnotationFile = true;
159
+ }
160
+ }
161
+ }
162
+ visitImport_simple = async (ctx) => {
163
+ await this.importCommon(ctx, ImportFunctionHandling.AllWithNamespace);
164
+ };
165
+ visitImport_all_simple = async (ctx) => {
166
+ await this.importCommon(ctx, ImportFunctionHandling.AllMergeIntoNamespace);
167
+ };
168
+ visitImport_specific = async (ctx) => {
169
+ await this.importCommon(ctx, ImportFunctionHandling.SpecificMergeIntoNamespace);
170
+ };
142
171
  visitAssignment_expr = (ctx) => {
143
172
  const ctxAtom = ctx.atom_expr();
144
173
  const ctxFuncCallRef = ctx.function_call_expr();
@@ -370,7 +399,8 @@ export class BaseVisitor extends CircuitScriptVisitor {
370
399
  let currentReference = executor.resolveVariable(this.executionStack, atomId);
371
400
  if (ctx.trailer_expr().length > 0) {
372
401
  if (!currentReference.found) {
373
- this.throwWithContext(ctx, "Unknown function name: " + atomId);
402
+ this.log(`could not resolve function: ${atomId}`);
403
+ this.throwWithContext(ctx, "could not resolve function: " + atomId);
374
404
  }
375
405
  currentReference.trailers = [];
376
406
  ctx.trailer_expr().forEach(item => {
@@ -387,7 +417,26 @@ export class BaseVisitor extends CircuitScriptVisitor {
387
417
  }
388
418
  const useNetNamespace = this.getNetNamespace(executor.netNamespace, passedNetNamespace);
389
419
  try {
390
- const [, functionResult] = executor.callFunction(currentReference.name, parameters, this.executionStack, useNetNamespace);
420
+ const isModuleFunction = currentReference.rootValue
421
+ && currentReference.rootValue instanceof ImportedModule;
422
+ if (isModuleFunction) {
423
+ this.log('create new module context');
424
+ const importedModule = currentReference.rootValue;
425
+ const importedModuleContext = importedModule.context;
426
+ this.enterFile(importedModule.moduleFilePath);
427
+ const newExecutor = this.handleEnterContext(this.getExecutor(), this.executionStack, importedModuleContext.name, ctx, {
428
+ netNamespace: executor.netNamespace,
429
+ namespace: importedModule.moduleNamespace
430
+ }, [], [], false);
431
+ this.log('copy module context scope');
432
+ importedModuleContext.scope.copyTo(newExecutor.scope);
433
+ }
434
+ const [, functionResult] = executor.callFunction(currentReference, parameters, this.executionStack, useNetNamespace);
435
+ if (isModuleFunction) {
436
+ this.log('pop module context scope');
437
+ this.handlePopContext(this.getExecutor(), this.executionStack, "", false);
438
+ this.exitFile();
439
+ }
391
440
  if (isReference(functionResult)) {
392
441
  currentReference = functionResult;
393
442
  }
@@ -414,6 +463,54 @@ export class BaseVisitor extends CircuitScriptVisitor {
414
463
  }
415
464
  this.setResult(ctx, currentReference);
416
465
  }
466
+ handleEnterContext(executor, executionStack, contextName, ctx, options, funcDefinedParameters, passedInParameters, isBreakContext = true) {
467
+ if (isBreakContext) {
468
+ const parentBreakContext = executor.getParentBreakContext();
469
+ executor.addBreakContext(ctx);
470
+ let useIndex = -1;
471
+ if (parentBreakContext === null) {
472
+ useIndex = options.functionCallIndex;
473
+ }
474
+ else {
475
+ const parentEntry = executor.indexedStack.get(parentBreakContext);
476
+ const { funcCallIndex } = parentEntry;
477
+ if (!funcCallIndex.has(ctx)) {
478
+ funcCallIndex.set(ctx, 0);
479
+ useIndex = 0;
480
+ }
481
+ else {
482
+ useIndex = funcCallIndex.get(ctx) + 1;
483
+ funcCallIndex.set(ctx, useIndex);
484
+ }
485
+ }
486
+ executor.setBreakContextIndex(useIndex);
487
+ }
488
+ return this.enterNewChildContext(executionStack, executor, contextName, options, funcDefinedParameters, passedInParameters);
489
+ }
490
+ handlePopContext(executor, executionStack, namespaceExtension, isBreakContext = true) {
491
+ const poppedContext = executionStack.pop();
492
+ const nextLastExecution = executionStack[executionStack.length - 1];
493
+ const mergedComponents = nextLastExecution.mergeScope(poppedContext.scope, namespaceExtension);
494
+ if (isBreakContext) {
495
+ const scope = this.getScope();
496
+ const indexedStack = [];
497
+ if (scope.breakStack.length > 0) {
498
+ const executor = this.getExecutor();
499
+ scope.breakStack.forEach(stackCtx => {
500
+ const entry = executor.indexedStack.get(stackCtx);
501
+ const { index } = entry;
502
+ indexedStack.push([stackCtx, index]);
503
+ });
504
+ mergedComponents.forEach(component => {
505
+ component.ctxReferences.forEach(ref => {
506
+ ref.indexedStack = [...indexedStack, ...ref.indexedStack];
507
+ });
508
+ });
509
+ }
510
+ executor.popBreakContext();
511
+ }
512
+ return poppedContext;
513
+ }
417
514
  visitValue_expr = (ctx) => {
418
515
  const sign = ctx.Minus() ? -1 : 1;
419
516
  const ctxIntegerValue = ctx.INTEGER_VALUE();
@@ -597,7 +694,8 @@ export class BaseVisitor extends CircuitScriptVisitor {
597
694
  instance.ctxReferences.push({
598
695
  ctx,
599
696
  indexedStack,
600
- creationFlag
697
+ creationFlag,
698
+ filePath: this.getCurrentFile(),
601
699
  });
602
700
  this.componentCtxLinks.set(ctx, instance);
603
701
  }
@@ -608,12 +706,34 @@ export class BaseVisitor extends CircuitScriptVisitor {
608
706
  this.visit(ctx);
609
707
  return this.getResult(ctx);
610
708
  }
611
- async handleImportFile(name, throwErrors = true, ctx = null) {
709
+ async handleImportFile(name, importHandling, throwErrors = true, ctx = null, specificImports = []) {
612
710
  name = name.trim();
613
711
  const importAlready = this.importedFiles.find(item => {
614
712
  return item.id === name;
615
713
  });
616
714
  if (importAlready) {
715
+ const tmpImportedModule = importAlready.importedModule;
716
+ const alreadyImportedFlag = tmpImportedModule.importHandlingFlag;
717
+ const isMergedNamespace = alreadyImportedFlag === ImportFunctionHandling.AllMergeIntoNamespace
718
+ || alreadyImportedFlag === ImportFunctionHandling.SpecificMergeIntoNamespace;
719
+ const invalidImportCondition1 = alreadyImportedFlag === ImportFunctionHandling.AllWithNamespace &&
720
+ importHandling !== ImportFunctionHandling.AllWithNamespace;
721
+ const invalidImportCondition2 = alreadyImportedFlag !== ImportFunctionHandling.AllWithNamespace &&
722
+ importHandling === ImportFunctionHandling.AllWithNamespace;
723
+ if (invalidImportCondition1 || invalidImportCondition2) {
724
+ throw new RuntimeExecutionError(`Namespace import and wildcard/specific imports cannot be mixed: ${name}`, ctx);
725
+ }
726
+ if (isMergedNamespace) {
727
+ if (alreadyImportedFlag === ImportFunctionHandling.AllMergeIntoNamespace) {
728
+ }
729
+ else if (alreadyImportedFlag === ImportFunctionHandling.SpecificMergeIntoNamespace && importHandling === ImportFunctionHandling.AllMergeIntoNamespace) {
730
+ tmpImportedModule.specifiedImports = [];
731
+ tmpImportedModule.importHandlingFlag = ImportFunctionHandling.AllMergeIntoNamespace;
732
+ }
733
+ else if (alreadyImportedFlag === ImportFunctionHandling.SpecificMergeIntoNamespace && importHandling === ImportFunctionHandling.SpecificMergeIntoNamespace) {
734
+ tmpImportedModule.specifiedImports.push(...specificImports);
735
+ }
736
+ }
617
737
  return importAlready;
618
738
  }
619
739
  let hasError = false;
@@ -632,6 +752,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
632
752
  this.log('failed to read file');
633
753
  pathExists = false;
634
754
  }
755
+ let importedModule;
635
756
  if (!pathExists) {
636
757
  try {
637
758
  const tmpFilePath2 = this.environment.getRelativeToDefaultLibs(name + ".cst");
@@ -646,16 +767,37 @@ export class BaseVisitor extends CircuitScriptVisitor {
646
767
  }
647
768
  }
648
769
  try {
649
- if (pathExists) {
770
+ if (pathExists && filePathUsed) {
650
771
  this.log('done reading imported file data');
772
+ const executionStack = this.executionStack;
773
+ const executor = this.getExecutor();
774
+ const executionContextName = name;
775
+ const netNamespace = executor.netNamespace;
776
+ const moduleNamespace = `${BaseNamespace}${name}.`;
777
+ this.enterNewChildContext(executionStack, executor, executionContextName, {
778
+ netNamespace,
779
+ namespace: moduleNamespace,
780
+ }, [], []);
651
781
  const importResult = await this.onImportFile(this, filePathUsed, fileData, this.onErrorHandler);
652
782
  hasError = importResult.hasError;
653
783
  hasParseError = importResult.hasParseError;
784
+ const importContext = executionStack.pop();
785
+ this.log(`import handling flag: ${importHandling}`);
786
+ importedModule = new ImportedModule(name, moduleNamespace, filePathUsed, importResult.tree, importResult.tokens, importContext, importHandling, specificImports);
787
+ if (specificImports.length > 0) {
788
+ this.log('specific import: ' + specificImports.join(', '));
789
+ }
790
+ const scope = this.getScope();
791
+ scope.modules.set(name, importedModule);
792
+ importedModule.context.scope.modules.forEach((module, key) => {
793
+ scope.modules.set(key, module);
794
+ });
795
+ await this.checkModuleHasRefdesFile(filePathUsed);
654
796
  }
655
797
  }
656
798
  catch (err) {
657
799
  if (ctx != null) {
658
- throw new RuntimeExecutionError("An error occurred while importing file", ctx);
800
+ throw err;
659
801
  }
660
802
  else {
661
803
  this.log('An error occurred while importing file:', err.message);
@@ -678,10 +820,17 @@ export class BaseVisitor extends CircuitScriptVisitor {
678
820
  hasError,
679
821
  hasParseError,
680
822
  pathExists,
823
+ importedModule: importedModule
681
824
  };
682
825
  this.importedFiles.push(newImportedFile);
683
826
  return newImportedFile;
684
827
  }
828
+ async checkModuleHasRefdesFile(filePath) {
829
+ return;
830
+ }
831
+ getRefdesFileAnnotation(filePath, startLine, startColumn, stopLine, stopColumn) {
832
+ return `${filePath}:${startLine}:${startColumn}:${stopLine}:${stopColumn}`;
833
+ }
685
834
  visitRoundedBracketsExpr = (ctx) => {
686
835
  const ctxDataExpr = ctx.data_expr();
687
836
  this.visit(ctxDataExpr);
@@ -771,14 +920,17 @@ export class BaseVisitor extends CircuitScriptVisitor {
771
920
  return object.getParam(paramName);
772
921
  }
773
922
  enterNewChildContext(executionStack, parentContext, executionContextName, options, funcDefinedParameters, passedInParameters) {
774
- const { netNamespace = "" } = options;
923
+ const { netNamespace = "", namespace = null, } = options;
775
924
  const currentExecutionContext = executionStack[executionStack.length - 1];
776
925
  const executionLevel = currentExecutionContext.executionLevel;
777
- const executionContextNamespace = currentExecutionContext.namespace
926
+ const executionContextNamespace = namespace ?? currentExecutionContext.namespace
778
927
  + executionContextName + ".";
779
928
  const newExecutor = new ExecutionContext(executionContextName, executionContextNamespace, netNamespace, executionLevel + 1, this.getExecutor().scope.scopeLevel + 1, currentExecutionContext.silent, currentExecutionContext.logger, currentExecutionContext.warnings, parentContext);
780
929
  executionStack.push(newExecutor);
781
930
  this.setupDefinedParameters(funcDefinedParameters, passedInParameters, newExecutor);
931
+ newExecutor.resolveNet = this.createNetResolver(executionStack);
932
+ newExecutor.resolveComponentPinNet =
933
+ this.createComponentPinNetResolver(executionStack);
782
934
  return newExecutor;
783
935
  }
784
936
  prepareStringValue(value) {
@@ -812,4 +964,15 @@ export class BaseVisitor extends CircuitScriptVisitor {
812
964
  return (val instanceof NumericValue);
813
965
  }, 'numeric value');
814
966
  }
967
+ enterFile(filePath) {
968
+ this.log(`enter file: ${filePath}`);
969
+ this.filePathStack.push(filePath);
970
+ }
971
+ exitFile() {
972
+ this.log(`exit file: ${this.getCurrentFile()}`);
973
+ this.filePathStack.pop();
974
+ }
975
+ getCurrentFile() {
976
+ return this.filePathStack[this.filePathStack.length - 1];
977
+ }
815
978
  }
@@ -22,8 +22,7 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
22
22
  return this.sourceText.substring(startIndex, stopIndex + 1);
23
23
  }
24
24
  visitScript = async (ctx) => {
25
- const result = this.runExpressions(this.getExecutor(), ctx.expression());
26
- this.setResult(ctx, result);
25
+ this.runExpressions(this.getExecutor(), ctx.expression());
27
26
  this.getExecutor().closeOpenPathBlocks();
28
27
  this.resultText = this.generateModifiedText();
29
28
  };
@@ -55,8 +54,10 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
55
54
  });
56
55
  if (allRefdes.length > 0) {
57
56
  const originalText = this.getOriginalText(ctx);
58
- const annotation = ' #= ' + allRefdes.join(',');
59
- this.modifications.set(ctx, originalText + annotation);
57
+ this.modifications.set(ctx, {
58
+ originalText,
59
+ refdes: allRefdes,
60
+ });
60
61
  }
61
62
  };
62
63
  visitFunction_def_expr = (ctx) => {
@@ -77,10 +78,10 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
77
78
  const instance = this.componentCtxLinks.get(ctx);
78
79
  const alreadyHaveRefdesAnnotation = instance.assignedRefDes !== null ?
79
80
  (this.addedRefdesAnnotations.indexOf(instance.assignedRefDes) !== -1) : false;
80
- if (!instance.hasParam('refdes')
81
+ const { forceSaveRefdesAnnotation: forceSaveRefdes } = instance;
82
+ if (!alreadyHaveRefdesAnnotation && (forceSaveRefdes || (!instance.hasParam('refdes')
81
83
  && instance.placeHolderRefDes === null
82
- && instance.assignedRefDes
83
- && !alreadyHaveRefdesAnnotation) {
84
+ && instance.assignedRefDes))) {
84
85
  let useRefDes = instance.assignedRefDes;
85
86
  let isPlaceholderRefdes = false;
86
87
  const { ctxReferences } = instance;
@@ -106,13 +107,25 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
106
107
  const refdes = this.generateRefdesAnnotationComment(ctx);
107
108
  if (refdes !== null) {
108
109
  const originalText = this.getOriginalText(ctx);
109
- const annotation = ' #= ' + refdes;
110
- this.modifications.set(ctx, originalText + annotation);
110
+ this.modifications.set(ctx, {
111
+ originalText,
112
+ refdes: [refdes]
113
+ });
111
114
  }
112
115
  }
113
116
  getOutput() {
114
117
  return this.resultText;
115
118
  }
119
+ getOutputForExternalRefdesFile() {
120
+ const result = [];
121
+ this.modifications.forEach((modification, ctx) => {
122
+ const { line: startLine, column: startColumn } = ctx.start;
123
+ const { line: stopLine, column: stopColumn } = ctx.stop;
124
+ const joinedRefdes = modification.refdes.join(',');
125
+ result.push(`${startLine}:${startColumn}:${stopLine}:${stopColumn}:${joinedRefdes}`);
126
+ });
127
+ return result;
128
+ }
116
129
  generateModifiedText() {
117
130
  const output = [];
118
131
  const allTokens = this.tokenStream.getTokens();
@@ -140,7 +153,7 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
140
153
  output.push(this.sourceText.substring(lastSourcePos, token.start));
141
154
  }
142
155
  if (this.modifications.has(ctx)) {
143
- output.push(this.modifications.get(ctx));
156
+ output.push(this.generateReplacementText(this.modifications.get(ctx)));
144
157
  this.markTokensAsProcessed(ctx, processedTokens);
145
158
  if (ctx.stop) {
146
159
  lastSourcePos = ctx.stop.stop + 1;
@@ -193,4 +206,8 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
193
206
  console.log(...message);
194
207
  }
195
208
  }
209
+ generateReplacementText(modification) {
210
+ const joinedRefdes = modification.refdes.join(', ');
211
+ return `${modification.originalText} #= ${joinedRefdes}`;
212
+ }
196
213
  }