circuitscript 0.1.29 → 0.1.31

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 (42) hide show
  1. package/dist/cjs/BaseVisitor.js +150 -21
  2. package/dist/cjs/antlr/CircuitScriptLexer.js +241 -236
  3. package/dist/cjs/antlr/CircuitScriptParser.js +568 -431
  4. package/dist/cjs/builtinMethods.js +6 -2
  5. package/dist/cjs/environment.js +4 -0
  6. package/dist/cjs/execute.js +88 -57
  7. package/dist/cjs/globals.js +4 -1
  8. package/dist/cjs/helpers.js +6 -2
  9. package/dist/cjs/objects/ExecutionScope.js +9 -0
  10. package/dist/cjs/objects/types.js +21 -2
  11. package/dist/cjs/parser.js +6 -2
  12. package/dist/cjs/validate/SymbolTable.js +7 -1
  13. package/dist/cjs/validate/SymbolValidatorVisitor.js +54 -7
  14. package/dist/cjs/visitor.js +15 -47
  15. package/dist/esm/BaseVisitor.js +152 -23
  16. package/dist/esm/antlr/CircuitScriptLexer.js +241 -236
  17. package/dist/esm/antlr/CircuitScriptParser.js +567 -429
  18. package/dist/esm/antlr/CircuitScriptVisitor.js +3 -1
  19. package/dist/esm/builtinMethods.js +7 -3
  20. package/dist/esm/environment.js +4 -0
  21. package/dist/esm/execute.js +89 -58
  22. package/dist/esm/globals.js +2 -0
  23. package/dist/esm/helpers.js +6 -2
  24. package/dist/esm/objects/ExecutionScope.js +9 -0
  25. package/dist/esm/objects/types.js +27 -1
  26. package/dist/esm/parser.js +6 -2
  27. package/dist/esm/validate/SymbolTable.js +5 -0
  28. package/dist/esm/validate/SymbolValidatorVisitor.js +53 -6
  29. package/dist/esm/visitor.js +16 -45
  30. package/dist/types/BaseVisitor.d.ts +12 -5
  31. package/dist/types/antlr/CircuitScriptLexer.d.ts +43 -42
  32. package/dist/types/antlr/CircuitScriptParser.d.ts +71 -45
  33. package/dist/types/antlr/CircuitScriptVisitor.d.ts +6 -2
  34. package/dist/types/environment.d.ts +1 -0
  35. package/dist/types/execute.d.ts +2 -2
  36. package/dist/types/globals.d.ts +2 -0
  37. package/dist/types/objects/ExecutionScope.d.ts +3 -1
  38. package/dist/types/objects/types.d.ts +22 -1
  39. package/dist/types/validate/SymbolTable.d.ts +1 -0
  40. package/dist/types/validate/SymbolValidatorVisitor.d.ts +6 -2
  41. package/dist/types/visitor.d.ts +3 -1
  42. package/package.json +4 -1
@@ -1,25 +1,26 @@
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
19
  silent = false;
20
20
  logger;
21
21
  printStream = [];
22
22
  printToConsole = true;
23
+ allowParseImports = false;
23
24
  acceptedDirections = [Direction.Up, Direction.Down,
24
25
  Direction.Right, Direction.Left];
25
26
  resultData = new Map;
@@ -44,12 +45,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
44
45
  this.logger = new Logger();
45
46
  this.onErrorHandler = onErrorHandler;
46
47
  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);
48
+ this.startingContext = new ExecutionContext(DoubleDelimiter1, BaseNamespace, '/', 0, 0, silent, this.logger, this.warnings, null);
53
49
  const scope = this.startingContext.scope;
54
50
  scope.sequence.push([
55
51
  SequenceAction.At, scope.componentRoot, scope.currentPin
@@ -111,8 +107,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
111
107
  };
112
108
  }
113
109
  log(...params) {
114
- const indentOutput = ''.padStart(this.indentLevel * 4, ' ');
115
- const indentLevelText = this.indentLevel.toString().padStart(3, ' ');
110
+ const indentLevel = this.getScope().scopeLevel;
111
+ const indentOutput = ''.padStart(indentLevel * 4, ' ');
112
+ const indentLevelText = indentLevel.toString().padStart(3, ' ');
116
113
  const args = ['[' + indentLevelText + ']', indentOutput, ...params];
117
114
  this.logger.add(args.join(' '));
118
115
  if (!this.silent) {
@@ -128,17 +125,36 @@ export class BaseVisitor extends CircuitScriptVisitor {
128
125
  }
129
126
  visitScript = async (ctx) => {
130
127
  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);
128
+ this.allowParseImports = true;
129
+ for (const ctxImport of ctx.import_expr()) {
130
+ await this.visit(ctxImport);
136
131
  }
132
+ this.allowParseImports = false;
137
133
  const result = this.runExpressions(this.getExecutor(), ctx.expression());
138
134
  this.setResult(ctx, result);
139
135
  this.getExecutor().closeOpenPathBlocks();
140
136
  this.log('===', 'end', '===');
141
137
  };
138
+ async importCommon(ctx, handling) {
139
+ const specificImports = [];
140
+ if (ctx instanceof Import_specificContext) {
141
+ const tmpSpecificImports = ctx._funcNames.map(item => {
142
+ return item.text;
143
+ });
144
+ specificImports.push(...tmpSpecificImports);
145
+ }
146
+ const id = ctx._moduleName.text;
147
+ await this.handleImportFile(id, handling, true, ctx, specificImports);
148
+ }
149
+ visitImport_simple = async (ctx) => {
150
+ await this.importCommon(ctx, ImportFunctionHandling.AllWithNamespace);
151
+ };
152
+ visitImport_all_simple = async (ctx) => {
153
+ await this.importCommon(ctx, ImportFunctionHandling.AllMergeIntoNamespace);
154
+ };
155
+ visitImport_specific = async (ctx) => {
156
+ await this.importCommon(ctx, ImportFunctionHandling.SpecificMergeIntoNamespace);
157
+ };
142
158
  visitAssignment_expr = (ctx) => {
143
159
  const ctxAtom = ctx.atom_expr();
144
160
  const ctxFuncCallRef = ctx.function_call_expr();
@@ -370,7 +386,8 @@ export class BaseVisitor extends CircuitScriptVisitor {
370
386
  let currentReference = executor.resolveVariable(this.executionStack, atomId);
371
387
  if (ctx.trailer_expr().length > 0) {
372
388
  if (!currentReference.found) {
373
- this.throwWithContext(ctx, "Unknown function name: " + atomId);
389
+ this.log(`could not resolve function: ${atomId}`);
390
+ this.throwWithContext(ctx, "could not resolve function: " + atomId);
374
391
  }
375
392
  currentReference.trailers = [];
376
393
  ctx.trailer_expr().forEach(item => {
@@ -387,7 +404,24 @@ export class BaseVisitor extends CircuitScriptVisitor {
387
404
  }
388
405
  const useNetNamespace = this.getNetNamespace(executor.netNamespace, passedNetNamespace);
389
406
  try {
390
- const [, functionResult] = executor.callFunction(currentReference.name, parameters, this.executionStack, useNetNamespace);
407
+ const isModuleFunction = currentReference.rootValue
408
+ && currentReference.rootValue instanceof ImportedModule;
409
+ if (isModuleFunction) {
410
+ this.log('create new module context');
411
+ const importedModule = currentReference.rootValue;
412
+ const importedModuleContext = importedModule.context;
413
+ const newExecutor = this.handleEnterContext(this.getExecutor(), this.executionStack, importedModuleContext.name, ctx, {
414
+ netNamespace: executor.netNamespace,
415
+ namespace: importedModule.moduleNamespace
416
+ }, [], [], false);
417
+ this.log('copy module context scope');
418
+ importedModuleContext.scope.copyTo(newExecutor.scope);
419
+ }
420
+ const [, functionResult] = executor.callFunction(currentReference, parameters, this.executionStack, useNetNamespace);
421
+ if (isModuleFunction) {
422
+ this.log('pop module context scope');
423
+ this.handlePopContext(this.getExecutor(), this.executionStack, "", false);
424
+ }
391
425
  if (isReference(functionResult)) {
392
426
  currentReference = functionResult;
393
427
  }
@@ -414,6 +448,54 @@ export class BaseVisitor extends CircuitScriptVisitor {
414
448
  }
415
449
  this.setResult(ctx, currentReference);
416
450
  }
451
+ handleEnterContext(executor, executionStack, contextName, ctx, options, funcDefinedParameters, passedInParameters, isBreakContext = true) {
452
+ if (isBreakContext) {
453
+ const parentBreakContext = executor.getParentBreakContext();
454
+ executor.addBreakContext(ctx);
455
+ let useIndex = -1;
456
+ if (parentBreakContext === null) {
457
+ useIndex = options.functionCallIndex;
458
+ }
459
+ else {
460
+ const parentEntry = executor.indexedStack.get(parentBreakContext);
461
+ const { funcCallIndex } = parentEntry;
462
+ if (!funcCallIndex.has(ctx)) {
463
+ funcCallIndex.set(ctx, 0);
464
+ useIndex = 0;
465
+ }
466
+ else {
467
+ useIndex = funcCallIndex.get(ctx) + 1;
468
+ funcCallIndex.set(ctx, useIndex);
469
+ }
470
+ }
471
+ executor.setBreakContextIndex(useIndex);
472
+ }
473
+ return this.enterNewChildContext(executionStack, executor, contextName, options, funcDefinedParameters, passedInParameters);
474
+ }
475
+ handlePopContext(executor, executionStack, namespaceExtension, isBreakContext = true) {
476
+ const poppedContext = executionStack.pop();
477
+ const nextLastExecution = executionStack[executionStack.length - 1];
478
+ const mergedComponents = nextLastExecution.mergeScope(poppedContext.scope, namespaceExtension);
479
+ if (isBreakContext) {
480
+ const scope = this.getScope();
481
+ const indexedStack = [];
482
+ if (scope.breakStack.length > 0) {
483
+ const executor = this.getExecutor();
484
+ scope.breakStack.forEach(stackCtx => {
485
+ const entry = executor.indexedStack.get(stackCtx);
486
+ const { index } = entry;
487
+ indexedStack.push([stackCtx, index]);
488
+ });
489
+ mergedComponents.forEach(component => {
490
+ component.ctxReferences.forEach(ref => {
491
+ ref.indexedStack = [...indexedStack, ...ref.indexedStack];
492
+ });
493
+ });
494
+ }
495
+ executor.popBreakContext();
496
+ }
497
+ return poppedContext;
498
+ }
417
499
  visitValue_expr = (ctx) => {
418
500
  const sign = ctx.Minus() ? -1 : 1;
419
501
  const ctxIntegerValue = ctx.INTEGER_VALUE();
@@ -608,12 +690,34 @@ export class BaseVisitor extends CircuitScriptVisitor {
608
690
  this.visit(ctx);
609
691
  return this.getResult(ctx);
610
692
  }
611
- async handleImportFile(name, throwErrors = true, ctx = null) {
693
+ async handleImportFile(name, importHandling, throwErrors = true, ctx = null, specificImports = []) {
612
694
  name = name.trim();
613
695
  const importAlready = this.importedFiles.find(item => {
614
696
  return item.id === name;
615
697
  });
616
698
  if (importAlready) {
699
+ const tmpImportedModule = importAlready.importedModule;
700
+ const alreadyImportedFlag = tmpImportedModule.importHandlingFlag;
701
+ const isMergedNamespace = alreadyImportedFlag === ImportFunctionHandling.AllMergeIntoNamespace
702
+ || alreadyImportedFlag === ImportFunctionHandling.SpecificMergeIntoNamespace;
703
+ const invalidImportCondition1 = alreadyImportedFlag === ImportFunctionHandling.AllWithNamespace &&
704
+ importHandling !== ImportFunctionHandling.AllWithNamespace;
705
+ const invalidImportCondition2 = alreadyImportedFlag !== ImportFunctionHandling.AllWithNamespace &&
706
+ importHandling === ImportFunctionHandling.AllWithNamespace;
707
+ if (invalidImportCondition1 || invalidImportCondition2) {
708
+ throw new RuntimeExecutionError(`Namespace import and wildcard/specific imports cannot be mixed: ${name}`, ctx);
709
+ }
710
+ if (isMergedNamespace) {
711
+ if (alreadyImportedFlag === ImportFunctionHandling.AllMergeIntoNamespace) {
712
+ }
713
+ else if (alreadyImportedFlag === ImportFunctionHandling.SpecificMergeIntoNamespace && importHandling === ImportFunctionHandling.AllMergeIntoNamespace) {
714
+ tmpImportedModule.specifiedImports = [];
715
+ tmpImportedModule.importHandlingFlag = ImportFunctionHandling.AllMergeIntoNamespace;
716
+ }
717
+ else if (alreadyImportedFlag === ImportFunctionHandling.SpecificMergeIntoNamespace && importHandling === ImportFunctionHandling.SpecificMergeIntoNamespace) {
718
+ tmpImportedModule.specifiedImports.push(...specificImports);
719
+ }
720
+ }
617
721
  return importAlready;
618
722
  }
619
723
  let hasError = false;
@@ -632,6 +736,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
632
736
  this.log('failed to read file');
633
737
  pathExists = false;
634
738
  }
739
+ let importedModule;
635
740
  if (!pathExists) {
636
741
  try {
637
742
  const tmpFilePath2 = this.environment.getRelativeToDefaultLibs(name + ".cst");
@@ -646,16 +751,36 @@ export class BaseVisitor extends CircuitScriptVisitor {
646
751
  }
647
752
  }
648
753
  try {
649
- if (pathExists) {
754
+ if (pathExists && filePathUsed) {
650
755
  this.log('done reading imported file data');
756
+ const executionStack = this.executionStack;
757
+ const executor = this.getExecutor();
758
+ const executionContextName = name;
759
+ const netNamespace = executor.netNamespace;
760
+ const moduleNamespace = `${BaseNamespace}${name}.`;
761
+ this.enterNewChildContext(executionStack, executor, executionContextName, {
762
+ netNamespace,
763
+ namespace: moduleNamespace,
764
+ }, [], []);
651
765
  const importResult = await this.onImportFile(this, filePathUsed, fileData, this.onErrorHandler);
652
766
  hasError = importResult.hasError;
653
767
  hasParseError = importResult.hasParseError;
768
+ const importContext = executionStack.pop();
769
+ this.log(`import handling flag: ${importHandling}`);
770
+ importedModule = new ImportedModule(name, moduleNamespace, filePathUsed, importContext, importHandling, specificImports);
771
+ if (specificImports.length > 0) {
772
+ this.log('specific import: ' + specificImports.join(', '));
773
+ }
774
+ const scope = this.getScope();
775
+ scope.modules.set(name, importedModule);
776
+ importedModule.context.scope.modules.forEach((module, key) => {
777
+ scope.modules.set(key, module);
778
+ });
654
779
  }
655
780
  }
656
781
  catch (err) {
657
782
  if (ctx != null) {
658
- throw new RuntimeExecutionError("An error occurred while importing file", ctx);
783
+ throw err;
659
784
  }
660
785
  else {
661
786
  this.log('An error occurred while importing file:', err.message);
@@ -678,6 +803,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
678
803
  hasError,
679
804
  hasParseError,
680
805
  pathExists,
806
+ importedModule: importedModule
681
807
  };
682
808
  this.importedFiles.push(newImportedFile);
683
809
  return newImportedFile;
@@ -771,14 +897,17 @@ export class BaseVisitor extends CircuitScriptVisitor {
771
897
  return object.getParam(paramName);
772
898
  }
773
899
  enterNewChildContext(executionStack, parentContext, executionContextName, options, funcDefinedParameters, passedInParameters) {
774
- const { netNamespace = "" } = options;
900
+ const { netNamespace = "", namespace = null, } = options;
775
901
  const currentExecutionContext = executionStack[executionStack.length - 1];
776
902
  const executionLevel = currentExecutionContext.executionLevel;
777
- const executionContextNamespace = currentExecutionContext.namespace
903
+ const executionContextNamespace = namespace ?? currentExecutionContext.namespace
778
904
  + executionContextName + ".";
779
905
  const newExecutor = new ExecutionContext(executionContextName, executionContextNamespace, netNamespace, executionLevel + 1, this.getExecutor().scope.scopeLevel + 1, currentExecutionContext.silent, currentExecutionContext.logger, currentExecutionContext.warnings, parentContext);
780
906
  executionStack.push(newExecutor);
781
907
  this.setupDefinedParameters(funcDefinedParameters, passedInParameters, newExecutor);
908
+ newExecutor.resolveNet = this.createNetResolver(executionStack);
909
+ newExecutor.resolveComponentPinNet =
910
+ this.createComponentPinNetResolver(executionStack);
782
911
  return newExecutor;
783
912
  }
784
913
  prepareStringValue(value) {