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
@@ -3,7 +3,7 @@ import { NumberOperator, numeric, NumericValue, ParamDefinition } from './object
3
3
  import { PinDefinition, PinId, PinIdType } from './objects/PinDefinition.js';
4
4
  import { PinTypes } from './objects/PinTypes.js';
5
5
  import { AnyReference, DeclaredReference, TypeProps, UndeclaredReference } from './objects/types.js';
6
- import { BlockTypes, ComponentTypes, Delimiter1, FrameType, GlobalDocumentName, ModuleContainsKeyword, NoNetText, ParamKeys, ReferenceTypes, SymbolPinSide, ValidPinSides, WireAutoDirection } from './globals.js';
6
+ import { BlockTypes, ComponentTypes, Delimiter1, FrameType, GlobalDocumentName, ModuleContainsKeyword, NoNetText, ParamKeys, RefdesFileSuffix, ReferenceTypes, SymbolPinSide, ValidPinSides, WireAutoDirection } from './globals.js';
7
7
  import { unwrapValue } from "./utils.js";
8
8
  import { PlaceHolderCommands, SymbolDrawingCommands } from './draw_symbols.js';
9
9
  import { BaseVisitor } from './BaseVisitor.js';
@@ -13,6 +13,16 @@ import { FrameParamKeys } from './objects/Frame.js';
13
13
  import { ComponentAnnotater } from './ComponentAnnotater.js';
14
14
  import { applyPartConditions, extractPartConditions, flattenConditionNodes } from './ComponentMatchConditions.js';
15
15
  export class ParserVisitor extends BaseVisitor {
16
+ constructor(silent = false, onErrorHandler = null, environment) {
17
+ super(silent, onErrorHandler, environment);
18
+ if (environment) {
19
+ this.log('-- Environment --');
20
+ this.log('Module directory: ' + environment.getModuleDirectory());
21
+ this.log('Default libs path: ' + environment.getDefaultLibsPath());
22
+ this.log('Current file: ' + environment.getCurrentFile());
23
+ this.log('-----------------');
24
+ }
25
+ }
16
26
  componentCreationIndex = 0;
17
27
  creationCtx = new Map();
18
28
  visitKeyword_assignment_expr = (ctx) => {
@@ -162,11 +172,117 @@ export class ParserVisitor extends BaseVisitor {
162
172
  if (ctxNotPathBlock) {
163
173
  this.visit(ctxNotPathBlock);
164
174
  }
175
+ if (ctx.start && ctx.stop) {
176
+ const startToken = ctx.start;
177
+ const stopToken = ctx.stop;
178
+ const annotationKey = this.getRefdesFileAnnotation(this.getCurrentFile(), startToken.line, startToken.column, stopToken.line, stopToken.column);
179
+ if (this.refdesFileAnnotations.has(annotationKey)) {
180
+ let refdesValue = this.refdesFileAnnotations.get(annotationKey);
181
+ refdesValue = refdesValue.split(',')[0];
182
+ this.setCurrentComponentRefdes(refdesValue, true);
183
+ }
184
+ }
165
185
  };
166
186
  visitCreate_component_expr = (ctx) => {
167
187
  const scope = this.getScope();
188
+ scope.setOnPropertyHandler(this.createComponentPropertyValidator());
189
+ scope.enterContext(ctx);
190
+ ctx.property_expr().forEach(item => {
191
+ this.visitResult(item);
192
+ });
193
+ scope.exitContext();
194
+ scope.popOnPropertyHandler();
195
+ const properties = this.getPropertyExprList(ctx.property_expr());
196
+ let instanceName = this.getExecutor().getUniqueInstanceName();
197
+ const propParams = properties.get('params');
198
+ const params = this.parseCreateComponentParams(propParams);
199
+ if (params.length > 0) {
200
+ const firstParam = params[0];
201
+ const paramValue = firstParam.paramValue;
202
+ let appendValue = paramValue.toString();
203
+ if (paramValue instanceof NumericValue) {
204
+ appendValue = paramValue.value;
205
+ }
206
+ instanceName += `${Delimiter1}${appendValue}`;
207
+ }
208
+ const typeProp = properties.get('type') ?? null;
209
+ const copy = properties.get('copy') ?? false;
210
+ const unitDefinitions = this.extractComponentUnitProperties(properties, typeProp);
211
+ const props = {
212
+ type: typeProp,
213
+ copy,
214
+ units: unitDefinitions
215
+ };
216
+ try {
217
+ const createdComponent = this.getExecutor().createComponent(instanceName, [], params, props);
218
+ this.setResult(ctx, createdComponent);
219
+ createdComponent._creationIndex = this.componentCreationIndex++;
220
+ }
221
+ catch (error) {
222
+ this.throwWithContext(ctx, error.message);
223
+ }
224
+ };
225
+ extractComponentUnitDefinition(properties, typeProp = null, lastNumericPinId = 0) {
226
+ const width = properties.get('width') ?? null;
227
+ const height = properties.get('height') ?? null;
228
+ const angle = properties.get(ParamKeys.angle) ?? null;
229
+ const followWireOrientation = properties.get('followWireOrientation') ?? true;
230
+ const arrange = properties.get('arrange') ?? null;
231
+ const display = properties.get('display') ?? null;
232
+ const suffix = properties.get('suffix') ?? null;
233
+ let pins = [];
234
+ if (display !== null && arrange === null && typeProp !== TypeProps.Graphic) {
235
+ const drawCommands = display.getCommands();
236
+ drawCommands.forEach(command => {
237
+ const [commandValue,] = command;
238
+ if (commandValue === PlaceHolderCommands.vpin
239
+ || commandValue === PlaceHolderCommands.hpin
240
+ || commandValue === PlaceHolderCommands.pin) {
241
+ const id = PinId.from(command[1][0]);
242
+ const pinType = id.getType();
243
+ const pinName = id.toString();
244
+ pins.push(new PinDefinition(id, pinType, pinName, PinTypes.Any));
245
+ }
246
+ });
247
+ }
248
+ else {
249
+ pins = this.extractPinDefintion(properties.get('pins'), lastNumericPinId);
250
+ }
251
+ return {
252
+ width,
253
+ height,
254
+ angle,
255
+ followWireOrientation,
256
+ display, arrange,
257
+ pins,
258
+ suffix
259
+ };
260
+ }
261
+ extractComponentUnitProperties(properties, typeProp) {
262
+ let lastNumericPinId = 0;
263
+ const unitsProperties = [];
264
+ for (const [key, value] of properties) {
265
+ if (key.split(':')[0] === 'unit') {
266
+ const unitDef = this.extractComponentUnitDefinition(value, typeProp, lastNumericPinId);
267
+ unitDef.pins.forEach(pin => {
268
+ if (pin.id.isNumeric()) {
269
+ lastNumericPinId = Math.max(lastNumericPinId, pin.id.getValue());
270
+ }
271
+ });
272
+ unitsProperties.push([key, unitDef]);
273
+ }
274
+ }
275
+ if (unitsProperties.length === 0) {
276
+ unitsProperties.push(['unit',
277
+ this.extractComponentUnitDefinition(properties, typeProp)]);
278
+ }
279
+ return unitsProperties;
280
+ }
281
+ createComponentPropertyValidator() {
168
282
  const definedPinIds = [];
169
283
  const arrangedPinIds = [];
284
+ let didDefineArrangeProp = false;
285
+ let didDefineDisplayProp = false;
170
286
  const checkPinExistsAndNotDuplicated = (pinId, ctx) => {
171
287
  if (definedPinIds.indexOf(pinId) === -1) {
172
288
  this.warnings.push({
@@ -181,9 +297,7 @@ export class ParserVisitor extends BaseVisitor {
181
297
  }
182
298
  arrangedPinIds.push(pinId);
183
299
  };
184
- let didDefineArrangeProp = false;
185
- let didDefineDisplayProp = false;
186
- scope.setOnPropertyHandler((path, value, ctx) => {
300
+ return (path, value, ctx) => {
187
301
  if (path.length === 1) {
188
302
  const [, keyName] = path[0];
189
303
  switch (keyName) {
@@ -292,76 +406,8 @@ export class ParserVisitor extends BaseVisitor {
292
406
  }
293
407
  }
294
408
  }
295
- });
296
- scope.enterContext(ctx);
297
- ctx.property_expr().forEach(item => {
298
- this.visitResult(item);
299
- });
300
- scope.exitContext();
301
- scope.popOnPropertyHandler();
302
- const properties = this.getPropertyExprList(ctx.property_expr());
303
- let instanceName = this.getExecutor().getUniqueInstanceName();
304
- const propParams = properties.get('params');
305
- const params = this.parseCreateComponentParams(propParams);
306
- if (params.length > 0) {
307
- const firstParam = params[0];
308
- const paramValue = firstParam.paramValue;
309
- let appendValue = paramValue.toString();
310
- if (paramValue instanceof NumericValue) {
311
- appendValue = paramValue.value;
312
- }
313
- instanceName += `${Delimiter1}${appendValue}`;
314
- }
315
- const arrangeProp = properties.has('arrange') ?
316
- properties.get('arrange') : null;
317
- const displayProp = properties.has('display') ?
318
- properties.get('display') : null;
319
- const typeProp = properties.has('type') ?
320
- properties.get('type') : null;
321
- const copy = properties.has('copy') ?
322
- properties.get('copy') : false;
323
- const width = properties.has('width') ?
324
- properties.get('width') : null;
325
- const height = properties.has('height') ?
326
- properties.get('height') : null;
327
- const angle = properties.has(ParamKeys.angle) ?
328
- properties.get(ParamKeys.angle) : null;
329
- const followWireOrientation = properties.has('followWireOrientation') ?
330
- properties.get('followWireOrientation') : true;
331
- let pins = [];
332
- if (displayProp !== null && arrangeProp === null
333
- && typeProp !== TypeProps.Graphic) {
334
- const drawCommands = displayProp.getCommands();
335
- drawCommands.forEach(command => {
336
- const [commandValue,] = command;
337
- if (commandValue === PlaceHolderCommands.vpin
338
- || commandValue === PlaceHolderCommands.hpin
339
- || commandValue === PlaceHolderCommands.pin) {
340
- const id = PinId.from(command[1][0]);
341
- const pinType = id.getType();
342
- const pinName = id.toString();
343
- pins.push(new PinDefinition(id, pinType, pinName, PinTypes.Any));
344
- }
345
- });
346
- }
347
- else {
348
- pins = this.parseCreateComponentPins(properties.get('pins'));
349
- }
350
- const props = {
351
- arrange: arrangeProp,
352
- display: displayProp,
353
- type: typeProp, width, height, copy,
354
- angle, followWireOrientation
355
409
  };
356
- try {
357
- const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
358
- this.setResult(ctx, createdComponent);
359
- createdComponent._creationIndex = this.componentCreationIndex++;
360
- }
361
- catch (error) {
362
- this.throwWithContext(ctx, error.message);
363
- }
364
- };
410
+ }
365
411
  visitCreate_graphic_expr = (ctx) => {
366
412
  const ctxId = ctx.ID();
367
413
  const paramIds = [];
@@ -496,19 +542,18 @@ export class ParserVisitor extends BaseVisitor {
496
542
  return new PinDefinition(index + 1, PinIdType.Int, portName, PinTypes.Any);
497
543
  });
498
544
  const arrange = this.getArrangePropFromModulePorts(modulePorts, nameToPinId);
499
- const width = properties.has('width') ?
500
- properties.get('width') : null;
501
- const height = properties.has('height') ?
502
- properties.get('height') : null;
545
+ const unitProperties = this.extractComponentUnitProperties(properties, TypeProps.Module);
546
+ const firstUnitDef = unitProperties[0][1];
547
+ firstUnitDef.pins = tmpPorts;
548
+ firstUnitDef.arrange = arrange;
503
549
  const blankParams = [];
504
550
  const props = {
505
- arrange, width, height,
506
551
  copy: false,
507
- followWireOrientation: true,
552
+ units: unitProperties,
508
553
  };
509
554
  const moduleInstanceName = this.getExecutor().getUniqueInstanceName();
510
555
  const moduleComponent = this.getExecutor().createComponent(moduleInstanceName, tmpPorts, blankParams, props, true);
511
- moduleComponent.typeProp = ComponentTypes.module;
556
+ moduleComponent.typeProp = TypeProps.Module;
512
557
  const ctxPropertyBlock = ctx.property_block_expr();
513
558
  if (ctxPropertyBlock) {
514
559
  const [firstBlock] = ctxPropertyBlock;
@@ -531,6 +576,10 @@ export class ParserVisitor extends BaseVisitor {
531
576
  visitProperty_expr = (ctx) => {
532
577
  const ctxKey = ctx.property_key_expr();
533
578
  const ctxValue = ctx.property_value_expr();
579
+ const extraValue = ctx._extra;
580
+ if (extraValue) {
581
+ console.log('extra', extraValue.text);
582
+ }
534
583
  const scope = this.getScope();
535
584
  this.getScope().enterContext(ctxKey);
536
585
  this.getScope().enterContext(ctxValue);
@@ -625,6 +674,7 @@ export class ParserVisitor extends BaseVisitor {
625
674
  dataResult = this.getExecutor().copyComponent(dataResult);
626
675
  }
627
676
  if (dataResult && dataResult instanceof ClassComponent) {
677
+ const defaultUnit = dataResult.getUnit();
628
678
  const modifiers = ctx.component_modifier_expr();
629
679
  modifiers.forEach(modifier => {
630
680
  const modifierText = modifier.ID(0).getText();
@@ -641,23 +691,23 @@ export class ParserVisitor extends BaseVisitor {
641
691
  if (modifierText === ParamKeys.flip) {
642
692
  const flipValue = result;
643
693
  if (flipValue.indexOf('x') !== -1) {
644
- dataResult.setParam(ParamKeys.flipX, 1);
694
+ defaultUnit.setParam(ParamKeys.flipX, numeric(1));
645
695
  shouldIgnoreWireOrientation = true;
646
696
  }
647
697
  if (flipValue.indexOf('y') !== -1) {
648
- dataResult.setParam(ParamKeys.flipY, 1);
698
+ defaultUnit.setParam(ParamKeys.flipY, numeric(1));
649
699
  shouldIgnoreWireOrientation = true;
650
700
  }
651
701
  }
652
702
  else if (modifierText === ParamKeys.angle) {
653
- dataResult.setParam(ParamKeys.angle, result);
703
+ defaultUnit.setParam(ParamKeys.angle, result);
654
704
  shouldIgnoreWireOrientation = true;
655
705
  }
656
706
  else if (modifierText === 'anchor') {
657
707
  dataResult.setParam('anchor', result);
658
708
  }
659
709
  if (shouldIgnoreWireOrientation) {
660
- dataResult.useWireOrientationAngle = false;
710
+ defaultUnit.useWireOrientationAngle = false;
661
711
  }
662
712
  });
663
713
  }
@@ -685,10 +735,8 @@ export class ParserVisitor extends BaseVisitor {
685
735
  + component.instanceName
686
736
  + Delimiter1 + component.moduleCounter;
687
737
  const tmpNamespace = this.getNetNamespace(netNamespace, "+/" + component.instanceName + Delimiter1 + component.moduleCounter);
688
- const newExecutor = this.enterNewChildContext(executionStack, executor, executionContextName, { netNamespace: tmpNamespace }, [], []);
738
+ this.enterNewChildContext(executionStack, executor, executionContextName, { netNamespace: tmpNamespace }, [], []);
689
739
  component.moduleCounter += 1;
690
- newExecutor.resolveNet = this.createNetResolver(executionStack);
691
- newExecutor.resolveComponentPinNet = this.createComponentPinNetResolver(executionStack);
692
740
  this.visit(component.moduleContainsExpressions);
693
741
  const executionContext = executionStack.pop();
694
742
  component.moduleExecutionContext = executionContext;
@@ -886,7 +934,7 @@ export class ParserVisitor extends BaseVisitor {
886
934
  visitFunction_def_expr = (ctx) => {
887
935
  const functionName = ctx.ID().getText();
888
936
  const uniqueFunctionID = '__._' + ctx.start.line + '_'
889
- + ctx.start.column + '_' + functionName + '_' + ctx.getText();
937
+ + ctx.start.column + '_' + functionName + '_' + this.environment.hashStringSHA256(ctx.getText());
890
938
  let funcDefinedParameters = [];
891
939
  const ctxFunctionArgsExpr = ctx.function_args_expr();
892
940
  if (ctxFunctionArgsExpr) {
@@ -898,54 +946,17 @@ export class ParserVisitor extends BaseVisitor {
898
946
  const resolveComponentPinNet = this.createComponentPinNetResolver(this.executionStack);
899
947
  const __runFunc = (passedInParameters, options) => {
900
948
  const executor = this.getExecutor();
901
- const parentBreakContext = executor.getParentBreakContext();
902
- executor.addBreakContext(ctx);
903
- let useIndex = -1;
904
- if (parentBreakContext === null) {
905
- useIndex = options.functionCallIndex;
906
- }
907
- else {
908
- const parentEntry = executor.indexedStack.get(parentBreakContext);
909
- const { funcCallIndex } = parentEntry;
910
- if (!funcCallIndex.has(ctx)) {
911
- funcCallIndex.set(ctx, 0);
912
- useIndex = 0;
913
- }
914
- else {
915
- useIndex = funcCallIndex.get(ctx) + 1;
916
- funcCallIndex.set(ctx, useIndex);
917
- }
918
- }
919
- executor.setBreakContextIndex(useIndex);
920
949
  const functionCounterIndex = functionCounter['counter'];
921
- const executionContextName = `${functionName}-${functionCounterIndex}`;
922
- const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, options, funcDefinedParameters, passedInParameters);
923
950
  functionCounter['counter'] += 1;
951
+ const executionContextName = `${functionName}-${functionCounterIndex}`;
952
+ const newExecutor = this.handleEnterContext(executor, executionStack, executionContextName, ctx, options, funcDefinedParameters, passedInParameters);
924
953
  newExecutor.resolveNet = resolveNet;
925
954
  newExecutor.resolveComponentPinNet = resolveComponentPinNet;
926
955
  const returnValue = this.runExpressions(newExecutor, ctx.function_expr());
927
- const lastExecution = executionStack.pop();
928
- const nextLastExecution = executionStack[executionStack.length - 1];
929
- const mergedComponents = nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
930
- const scope = this.getScope();
931
- const indexedStack = [];
932
- if (scope.breakStack.length > 0) {
933
- const executor = this.getExecutor();
934
- scope.breakStack.forEach(stackCtx => {
935
- const entry = executor.indexedStack.get(stackCtx);
936
- const { index } = entry;
937
- indexedStack.push([stackCtx, index]);
938
- });
939
- mergedComponents.forEach(component => {
940
- component.ctxReferences.forEach(ref => {
941
- ref.indexedStack = [...indexedStack, ...ref.indexedStack];
942
- });
943
- });
944
- }
945
- executor.popBreakContext();
956
+ const lastExecution = this.handlePopContext(executor, executionStack, executionContextName);
946
957
  return [lastExecution, returnValue];
947
958
  };
948
- this.getExecutor().createFunction(functionName, __runFunc, ctx, uniqueFunctionID);
959
+ this.getExecutor().createFunction(this.getExecutor().namespace, functionName, __runFunc, ctx, uniqueFunctionID);
949
960
  };
950
961
  visitPin_select_expr2 = (ctx) => {
951
962
  const ctxStringValue = ctx.STRING_VALUE();
@@ -1235,17 +1246,21 @@ export class ParserVisitor extends BaseVisitor {
1235
1246
  }
1236
1247
  executor.popBreakContext();
1237
1248
  };
1238
- visitAnnotation_comment_expr = (ctx) => {
1239
- const refdesID = ctx.ID().getText();
1249
+ setCurrentComponentRefdes(refdesValue, forceSave = false) {
1240
1250
  const currentComponent = this.getScope().currentComponent;
1241
1251
  if (currentComponent !== null) {
1242
- if (refdesID.indexOf('_') === -1) {
1243
- currentComponent.setParam('refdes', refdesID);
1252
+ if (refdesValue.indexOf('_') === -1) {
1253
+ currentComponent.setParam('refdes', refdesValue);
1244
1254
  }
1245
1255
  else {
1246
- currentComponent.placeHolderRefDes = refdesID;
1256
+ currentComponent.placeHolderRefDes = refdesValue;
1247
1257
  }
1258
+ currentComponent.forceSaveRefdesAnnotation = forceSave;
1248
1259
  }
1260
+ }
1261
+ visitAnnotation_comment_expr = (ctx) => {
1262
+ const refdesID = ctx.ID().getText();
1263
+ this.setCurrentComponentRefdes(refdesID);
1249
1264
  };
1250
1265
  visitPart_set_expr = (ctx) => {
1251
1266
  const paramKeys = ctx.data_expr().map(ctx => {
@@ -1360,6 +1375,28 @@ export class ParserVisitor extends BaseVisitor {
1360
1375
  children,
1361
1376
  });
1362
1377
  };
1378
+ async checkModuleHasRefdesFile(filePath) {
1379
+ const dir = this.environment.dirname(filePath);
1380
+ const ext = this.environment.extname(filePath);
1381
+ const basename = this.environment.basename(filePath, ext);
1382
+ const annotatedFilePath = this.environment.join(dir, `${basename}${RefdesFileSuffix}`);
1383
+ const exists = await this.environment.exists(annotatedFilePath);
1384
+ if (exists) {
1385
+ this.log(`Import has refdes file: ${annotatedFilePath}`);
1386
+ const fileData = await this.environment.readFile(annotatedFilePath);
1387
+ const jsonData = JSON.parse(fileData);
1388
+ const baseFilePath = this.environment.getAbsolutePath(this.filePathStack[0]);
1389
+ const basePathDirectory = this.environment.dirname(baseFilePath);
1390
+ const { file, items } = jsonData;
1391
+ for (const item of items) {
1392
+ const parts = item.split(':');
1393
+ const refdes = parts[4];
1394
+ const useFilePath = this.environment.join(basePathDirectory, file);
1395
+ const key = this.getRefdesFileAnnotation(useFilePath, Number(parts[0]), Number(parts[1]), Number(parts[2]), Number(parts[3]));
1396
+ this.refdesFileAnnotations.set(key, refdes);
1397
+ }
1398
+ }
1399
+ }
1363
1400
  resolveDataExpr(data_expr) {
1364
1401
  const value = this.visitResult(data_expr);
1365
1402
  if (value instanceof UndeclaredReference) {
@@ -1386,13 +1423,13 @@ export class ParserVisitor extends BaseVisitor {
1386
1423
  PinTypes.Output,
1387
1424
  PinTypes.Power,
1388
1425
  ];
1389
- parseCreateComponentPins(pinData) {
1426
+ extractPinDefintion(pinData, lastNumericPinId = 0) {
1390
1427
  const pins = [];
1391
1428
  if (pinData instanceof NumericValue) {
1392
1429
  const tmpMap = new Map();
1393
1430
  const lastPin = pinData.toNumber();
1394
1431
  for (let i = 0; i < lastPin; i++) {
1395
- const pinId = i + 1;
1432
+ const pinId = lastNumericPinId + i + 1;
1396
1433
  tmpMap.set(pinId, numeric(pinId));
1397
1434
  }
1398
1435
  pinData = tmpMap;
@@ -1565,6 +1602,7 @@ export class ParserVisitor extends BaseVisitor {
1565
1602
  const refdes = instance.getParam('refdes');
1566
1603
  if (refdes) {
1567
1604
  instance.assignedRefDes = refdes;
1605
+ this.setComponentUnitRefdesSuffix(instance);
1568
1606
  annotater.trackRefDes(refdes);
1569
1607
  this.log(refdes, '-', instance.instanceName);
1570
1608
  continue;
@@ -1578,6 +1616,7 @@ export class ParserVisitor extends BaseVisitor {
1578
1616
  if (newRefDes !== null) {
1579
1617
  instance.assignedRefDes = newRefDes;
1580
1618
  this.log(newRefDes, '-', instance.instanceName);
1619
+ this.setComponentUnitRefdesSuffix(instance);
1581
1620
  }
1582
1621
  else {
1583
1622
  this.log('Failed to annotate:', instance.instanceName);
@@ -1588,6 +1627,24 @@ export class ParserVisitor extends BaseVisitor {
1588
1627
  this.renameNetsWithRefdes();
1589
1628
  this.log('===== rename nets done =====');
1590
1629
  }
1630
+ setComponentUnitRefdesSuffix(instance) {
1631
+ if (instance.assignedRefDes) {
1632
+ const { units } = instance;
1633
+ if (units.length > 1) {
1634
+ units.forEach((unit, index) => {
1635
+ let useRefdes = String.fromCharCode("A".charCodeAt(0) + index);
1636
+ if (unit.suffix !== null) {
1637
+ useRefdes = unit.suffix;
1638
+ }
1639
+ unit.refdesSuffix = useRefdes;
1640
+ });
1641
+ }
1642
+ else {
1643
+ const [firstUnit] = units;
1644
+ firstUnit.refdesSuffix = '';
1645
+ }
1646
+ }
1647
+ }
1591
1648
  renameNetsWithRefdes() {
1592
1649
  const nets = this.getScope().getNets();
1593
1650
  const seenNets = [];
@@ -1646,10 +1703,17 @@ export class ParserVisitor extends BaseVisitor {
1646
1703
  }
1647
1704
  getPropertyExprList(items) {
1648
1705
  const properties = new Map();
1706
+ const keyCounter = new Map();
1649
1707
  items.forEach((item) => {
1650
1708
  const result = this.visitResult(item);
1651
1709
  for (const [key, value] of result) {
1652
- properties.set(key, value);
1710
+ let useKey = key;
1711
+ const counterValue = keyCounter.get(key) ?? 0;
1712
+ keyCounter.set(key, counterValue + 1);
1713
+ if (counterValue > 0) {
1714
+ useKey = key + ':' + counterValue;
1715
+ }
1716
+ properties.set(useKey, value);
1653
1717
  }
1654
1718
  });
1655
1719
  return properties;
@@ -1,24 +1,25 @@
1
- import { Array_exprContext, ArrayExprContext, ArrayIndexExprContext, Assignment_exprContext, Atom_exprContext, ExpressionContext, Flow_expressionsContext, Function_args_exprContext, Function_call_exprContext, Function_exprContext, Function_return_exprContext, FunctionCallExprContext, Import_exprContext, Operator_assignment_exprContext, ParametersContext, RoundedBracketsExprContext, ScriptContext, Trailer_expr2Context, Value_exprContext, ValueAtomExprContext } from "./antlr/CircuitScriptParser.js";
1
+ import { Array_exprContext, ArrayExprContext, ArrayIndexExprContext, Assignment_exprContext, Atom_exprContext, ExpressionContext, Flow_expressionsContext, Function_args_exprContext, Function_call_exprContext, Function_exprContext, Function_return_exprContext, FunctionCallExprContext, Import_all_simpleContext, Import_exprContext, Import_simpleContext, Import_specificContext, Operator_assignment_exprContext, ParametersContext, RoundedBracketsExprContext, ScriptContext, Trailer_expr2Context, Value_exprContext, ValueAtomExprContext } from "./antlr/CircuitScriptParser.js";
2
2
  import { CircuitScriptVisitor } from "./antlr/CircuitScriptVisitor.js";
3
3
  import { ExecutionContext } from "./execute.js";
4
4
  import { Logger } from "./logger.js";
5
5
  import { ClassComponent } from "./objects/ClassComponent.js";
6
6
  import { Net } from "./objects/Net.js";
7
- import { CallableParameter, CFunctionOptions, ComplexType, Direction, FunctionDefinedParameter, AnyReference } from "./objects/types.js";
8
- import { ParserRuleContext } from 'antlr4ng';
7
+ import { CallableParameter, ComplexType, Direction, FunctionDefinedParameter, AnyReference, ImportedModule, NewContextOptions, ImportFunctionHandling as ImportFunctionHandling } from "./objects/types.js";
8
+ import { CommonTokenStream, ParserRuleContext } from 'antlr4ng';
9
9
  import { ExecutionWarning } from "./utils.js";
10
10
  import { BaseError } from './utils.js';
11
11
  import { ExecutionScope } from './objects/ExecutionScope.js';
12
12
  import { NodeScriptEnvironment } from "./environment.js";
13
13
  import { PinId } from './objects/PinDefinition.js';
14
14
  export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyReference | any> {
15
- indentLevel: number;
16
15
  startingContext: ExecutionContext;
17
16
  executionStack: ExecutionContext[];
17
+ filePathStack: string[];
18
18
  silent: boolean;
19
19
  logger: Logger;
20
20
  printStream: string[];
21
21
  printToConsole: boolean;
22
+ allowParseImports: boolean;
22
23
  acceptedDirections: Direction[];
23
24
  protected resultData: Map<ParserRuleContext, any>;
24
25
  protected componentCtxLinks: Map<ParserRuleContext, ClassComponent>;
@@ -27,10 +28,8 @@ export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyR
27
28
  environment: NodeScriptEnvironment;
28
29
  protected importedFiles: ImportFile[];
29
30
  protected warnings: ExecutionWarning[];
30
- onImportFile: (visitor: BaseVisitor, filePath: string, fileData: string, onErrorHandler: OnErrorHandler) => Promise<{
31
- hasError: boolean;
32
- hasParseError: boolean;
33
- }>;
31
+ onImportFile: (visitor: BaseVisitor, filePath: string, fileData: string, onErrorHandler: OnErrorHandler) => Promise<ImportFileResult>;
32
+ refdesFileAnnotations: Map<string, string>;
34
33
  constructor(silent: boolean | undefined, onErrorHandler: OnErrorHandler | null | undefined, environment: NodeScriptEnvironment);
35
34
  getExecutor(): ExecutionContext;
36
35
  getScope(): ExecutionScope;
@@ -45,6 +44,10 @@ export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyR
45
44
  log2(message: string): void;
46
45
  visitAsync(ctx: ParserRuleContext): Promise<void>;
47
46
  visitScript: (ctx: ScriptContext) => Promise<void>;
47
+ private importCommon;
48
+ visitImport_simple: (ctx: Import_simpleContext) => Promise<void>;
49
+ visitImport_all_simple: (ctx: Import_all_simpleContext) => Promise<void>;
50
+ visitImport_specific: (ctx: Import_specificContext) => Promise<void>;
48
51
  visitAssignment_expr: (ctx: Assignment_exprContext) => void;
49
52
  visitOperator_assignment_expr: (ctx: Operator_assignment_exprContext) => void;
50
53
  private getReference;
@@ -53,6 +56,8 @@ export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyR
53
56
  visitFunctionCallExpr: (ctx: FunctionCallExprContext) => void;
54
57
  visitFunction_call_expr: (ctx: Function_call_exprContext) => void;
55
58
  private handleFunctionCall;
59
+ protected handleEnterContext(executor: ExecutionContext, executionStack: ExecutionContext[], contextName: string, ctx: ParserRuleContext, options: NewContextOptions, funcDefinedParameters: FunctionDefinedParameter[], passedInParameters: CallableParameter[], isBreakContext?: boolean): ExecutionContext;
60
+ protected handlePopContext(executor: ExecutionContext, executionStack: ExecutionContext[], namespaceExtension: string, isBreakContext?: boolean): ExecutionContext;
56
61
  visitValue_expr: (ctx: Value_exprContext) => void;
57
62
  visitValueAtomExpr: (ctx: ValueAtomExprContext) => void;
58
63
  visitFunction_args_expr: (ctx: Function_args_exprContext) => void;
@@ -68,20 +73,25 @@ export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyR
68
73
  protected linkComponentToCtx(ctx: ParserRuleContext, instance: ClassComponent, creationFlag?: boolean): void;
69
74
  getComponentCtxLinks(): Map<ParserRuleContext, ClassComponent>;
70
75
  visitResult(ctx: ParserRuleContext): any;
71
- protected handleImportFile(name: string, throwErrors?: boolean, ctx?: ParserRuleContext | null): Promise<ImportFile>;
76
+ protected handleImportFile(name: string, importHandling: ImportFunctionHandling, throwErrors?: boolean, ctx?: ParserRuleContext | null, specificImports?: string[]): Promise<ImportFile>;
77
+ checkModuleHasRefdesFile(filePath: string): Promise<void>;
78
+ getRefdesFileAnnotation(filePath: string, startLine: number, startColumn: number, stopLine: number, stopColumn: number): string;
72
79
  visitRoundedBracketsExpr: (ctx: RoundedBracketsExprContext) => void;
73
80
  protected setupDefinedParameters(funcDefinedParameters: FunctionDefinedParameter[], passedInParameters: CallableParameter[], executor: ExecutionContext): void;
74
81
  protected runExpressions(executor: ExecutionContext, expressions: ExpressionContext[] | Function_exprContext[]): ComplexType;
75
82
  protected getNetNamespace(executorNetNamespace: string, passedNetNamespace: string | null): string;
76
83
  protected setInstanceParam(object: ClassComponent, trailers: string[], value: any): void;
77
84
  protected getInstanceParam<T>(object: ClassComponent, trailers: string[]): T;
78
- protected enterNewChildContext(executionStack: ExecutionContext[], parentContext: ExecutionContext, executionContextName: string, options: CFunctionOptions, funcDefinedParameters: FunctionDefinedParameter[], passedInParameters: CallableParameter[]): ExecutionContext;
85
+ protected enterNewChildContext(executionStack: ExecutionContext[], parentContext: ExecutionContext, executionContextName: string, options: NewContextOptions, funcDefinedParameters: FunctionDefinedParameter[], passedInParameters: CallableParameter[]): ExecutionContext;
79
86
  protected prepareStringValue(value: string): string;
80
87
  protected throwWithContext(context: ParserRuleContext, messageOrError: string | BaseError): void;
81
88
  protected validateType(value: any, context: ParserRuleContext, validateFunction: (value: any) => boolean, expectedType: string): boolean;
82
89
  protected validateString(value: any, context: ParserRuleContext): void;
83
90
  protected validateBoolean(value: any, context: ParserRuleContext): void;
84
91
  protected validateNumeric(value: any, context: ParserRuleContext): void;
92
+ enterFile(filePath: string): void;
93
+ exitFile(): void;
94
+ getCurrentFile(): string;
85
95
  }
86
96
  export type OnErrorHandler = (message: string, context: ParserRuleContext, e?: any) => void;
87
97
  type ImportFile = {
@@ -89,5 +99,12 @@ type ImportFile = {
89
99
  hasError: boolean;
90
100
  hasParseError: boolean;
91
101
  pathExists: boolean;
102
+ importedModule: ImportedModule;
103
+ };
104
+ export type ImportFileResult = {
105
+ hasError: boolean;
106
+ hasParseError: boolean;
107
+ tree: ScriptContext;
108
+ tokens: CommonTokenStream;
92
109
  };
93
110
  export {};
@@ -27,9 +27,11 @@ export declare class RefdesAnnotationVisitor extends BaseVisitor {
27
27
  private generateRefdesAnnotationComment;
28
28
  private addRefdesAnnotationComment;
29
29
  getOutput(): string;
30
+ getOutputForExternalRefdesFile(): string[];
30
31
  private generateModifiedText;
31
32
  private buildContextTokenRanges;
32
33
  private findContextForToken;
33
34
  private markTokensAsProcessed;
34
35
  private log;
36
+ private generateReplacementText;
35
37
  }