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.
- package/dist/cjs/BaseVisitor.js +150 -21
- package/dist/cjs/antlr/CircuitScriptLexer.js +241 -236
- package/dist/cjs/antlr/CircuitScriptParser.js +568 -431
- package/dist/cjs/builtinMethods.js +6 -2
- package/dist/cjs/environment.js +4 -0
- package/dist/cjs/execute.js +88 -57
- package/dist/cjs/globals.js +4 -1
- package/dist/cjs/helpers.js +6 -2
- package/dist/cjs/objects/ExecutionScope.js +9 -0
- package/dist/cjs/objects/types.js +21 -2
- package/dist/cjs/parser.js +6 -2
- package/dist/cjs/validate/SymbolTable.js +7 -1
- package/dist/cjs/validate/SymbolValidatorVisitor.js +54 -7
- package/dist/cjs/visitor.js +15 -47
- package/dist/esm/BaseVisitor.js +152 -23
- package/dist/esm/antlr/CircuitScriptLexer.js +241 -236
- package/dist/esm/antlr/CircuitScriptParser.js +567 -429
- package/dist/esm/antlr/CircuitScriptVisitor.js +3 -1
- package/dist/esm/builtinMethods.js +7 -3
- package/dist/esm/environment.js +4 -0
- package/dist/esm/execute.js +89 -58
- package/dist/esm/globals.js +2 -0
- package/dist/esm/helpers.js +6 -2
- package/dist/esm/objects/ExecutionScope.js +9 -0
- package/dist/esm/objects/types.js +27 -1
- package/dist/esm/parser.js +6 -2
- package/dist/esm/validate/SymbolTable.js +5 -0
- package/dist/esm/validate/SymbolValidatorVisitor.js +53 -6
- package/dist/esm/visitor.js +16 -45
- package/dist/types/BaseVisitor.d.ts +12 -5
- package/dist/types/antlr/CircuitScriptLexer.d.ts +43 -42
- package/dist/types/antlr/CircuitScriptParser.d.ts +71 -45
- package/dist/types/antlr/CircuitScriptVisitor.d.ts +6 -2
- package/dist/types/environment.d.ts +1 -0
- package/dist/types/execute.d.ts +2 -2
- package/dist/types/globals.d.ts +2 -0
- package/dist/types/objects/ExecutionScope.d.ts +3 -1
- package/dist/types/objects/types.d.ts +22 -1
- package/dist/types/validate/SymbolTable.d.ts +1 -0
- package/dist/types/validate/SymbolValidatorVisitor.d.ts +6 -2
- package/dist/types/visitor.d.ts +3 -1
- package/package.json +4 -1
package/dist/esm/BaseVisitor.js
CHANGED
|
@@ -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.
|
|
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
|
|
115
|
-
const
|
|
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
|
-
|
|
132
|
-
for (
|
|
133
|
-
|
|
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.
|
|
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
|
|
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
|
|
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) {
|