circuitscript 0.1.20 → 0.1.23
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 +22 -0
- package/dist/cjs/ComponentAnnotater.js +88 -0
- package/dist/cjs/RefdesAnnotationVisitor.js +197 -0
- package/dist/cjs/antlr/CircuitScriptLexer.js +202 -197
- package/dist/cjs/antlr/CircuitScriptParser.js +975 -833
- package/dist/cjs/environment.js +15 -1
- package/dist/cjs/execute.js +45 -2
- package/dist/cjs/helpers.js +20 -2
- package/dist/cjs/lexer.js +21 -9
- package/dist/cjs/main.js +13 -0
- package/dist/cjs/objects/ClassComponent.js +4 -1
- package/dist/cjs/objects/ExecutionScope.js +1 -0
- package/dist/cjs/parser.js +1 -0
- package/dist/cjs/visitor.js +122 -71
- package/dist/esm/BaseVisitor.js +22 -0
- package/dist/esm/ComponentAnnotater.js +84 -0
- package/dist/esm/RefdesAnnotationVisitor.js +196 -0
- package/dist/esm/antlr/CircuitScriptLexer.js +202 -197
- package/dist/esm/antlr/CircuitScriptParser.js +971 -831
- package/dist/esm/antlr/CircuitScriptVisitor.js +2 -0
- package/dist/esm/environment.js +15 -1
- package/dist/esm/execute.js +45 -2
- package/dist/esm/helpers.js +20 -2
- package/dist/esm/lexer.js +21 -9
- package/dist/esm/main.js +13 -0
- package/dist/esm/objects/ClassComponent.js +4 -1
- package/dist/esm/objects/ExecutionScope.js +1 -0
- package/dist/esm/parser.js +1 -0
- package/dist/esm/visitor.js +120 -69
- package/dist/types/BaseVisitor.d.ts +3 -0
- package/dist/types/ComponentAnnotater.d.ts +16 -0
- package/dist/types/RefdesAnnotationVisitor.d.ts +35 -0
- package/dist/types/antlr/CircuitScriptLexer.d.ts +15 -14
- package/dist/types/antlr/CircuitScriptParser.d.ts +81 -60
- package/dist/types/antlr/CircuitScriptVisitor.d.ts +4 -0
- package/dist/types/environment.d.ts +1 -0
- package/dist/types/execute.d.ts +8 -1
- package/dist/types/helpers.d.ts +4 -1
- package/dist/types/lexer.d.ts +1 -1
- package/dist/types/objects/ClassComponent.d.ts +9 -0
- package/dist/types/objects/ExecutionScope.d.ts +2 -1
- package/dist/types/objects/types.d.ts +1 -0
- package/dist/types/parser.d.ts +2 -1
- package/dist/types/visitor.d.ts +8 -1
- package/package.json +1 -1
|
@@ -22,6 +22,7 @@ export class CircuitScriptVisitor extends AbstractParseTreeVisitor {
|
|
|
22
22
|
visitAt_to_multiple_line_expr_to_pin;
|
|
23
23
|
visitAt_block;
|
|
24
24
|
visitAt_block_expressions;
|
|
25
|
+
visitAt_block_header;
|
|
25
26
|
visitAt_block_pin_expr;
|
|
26
27
|
visitAt_block_pin_expression_simple;
|
|
27
28
|
visitAt_block_pin_expression_complex;
|
|
@@ -78,4 +79,5 @@ export class CircuitScriptVisitor extends AbstractParseTreeVisitor {
|
|
|
78
79
|
visitElse_expr;
|
|
79
80
|
visitWhile_expr;
|
|
80
81
|
visitFor_expr;
|
|
82
|
+
visitAnnotation_comment_expr;
|
|
81
83
|
}
|
package/dist/esm/environment.js
CHANGED
|
@@ -14,6 +14,7 @@ export class NodeScriptEnvironment {
|
|
|
14
14
|
useModuleDirectoryPath = null;
|
|
15
15
|
useDefaultLibsPath = null;
|
|
16
16
|
globalCreateSVGWindow = null;
|
|
17
|
+
cachedVersion = null;
|
|
17
18
|
supportedFonts = {
|
|
18
19
|
'Arial': 'Arial.ttf',
|
|
19
20
|
};
|
|
@@ -24,7 +25,20 @@ export class NodeScriptEnvironment {
|
|
|
24
25
|
this.useDefaultLibsPath = path;
|
|
25
26
|
}
|
|
26
27
|
getPackageVersion() {
|
|
27
|
-
|
|
28
|
+
if (this.cachedVersion !== null) {
|
|
29
|
+
return this.cachedVersion;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const packageJsonPath = path.join(this.getToolsPath(), '../', 'package.json');
|
|
33
|
+
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8');
|
|
34
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
35
|
+
this.cachedVersion = packageJson.version || TOOL_VERSION;
|
|
36
|
+
return this.cachedVersion;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.warn('Failed to read version from package.json, using fallback version:', error);
|
|
40
|
+
return TOOL_VERSION;
|
|
41
|
+
}
|
|
28
42
|
}
|
|
29
43
|
getModuleDirectory() {
|
|
30
44
|
if (this.useModuleDirectoryPath !== null) {
|
package/dist/esm/execute.js
CHANGED
|
@@ -28,6 +28,7 @@ export class ExecutionContext {
|
|
|
28
28
|
parentContext;
|
|
29
29
|
componentAngleFollowsWire = true;
|
|
30
30
|
warnings = [];
|
|
31
|
+
indexedStack = new Map();
|
|
31
32
|
constructor(name, namespace, netNamespace, executionLevel = 0, scopeLevel = 0, silent = false, logger, warnings, parent) {
|
|
32
33
|
this.name = name;
|
|
33
34
|
this.namespace = namespace;
|
|
@@ -547,9 +548,39 @@ export class ExecutionContext {
|
|
|
547
548
|
this.log('did not find block point');
|
|
548
549
|
return null;
|
|
549
550
|
}
|
|
551
|
+
getParentBreakContext() {
|
|
552
|
+
if (this.scope.breakStack.length > 0) {
|
|
553
|
+
return this.scope.breakStack[this.scope.breakStack.length - 1];
|
|
554
|
+
}
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
550
557
|
addBreakContext(ctx) {
|
|
551
558
|
this.log('add break context');
|
|
552
559
|
this.scope.breakStack.push(ctx);
|
|
560
|
+
this.indexedStack.set(ctx, {
|
|
561
|
+
index: 0,
|
|
562
|
+
funcCallIndex: new Map(),
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
setBreakContextIndex(index) {
|
|
566
|
+
const latestCtx = this.scope.breakStack[this.scope.breakStack.length - 1];
|
|
567
|
+
if (latestCtx) {
|
|
568
|
+
const current = this.indexedStack.get(latestCtx);
|
|
569
|
+
this.indexedStack.set(latestCtx, {
|
|
570
|
+
...current,
|
|
571
|
+
index,
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
resetBreakContextFunctionCalls() {
|
|
576
|
+
const latestCtx = this.scope.breakStack[this.scope.breakStack.length - 1];
|
|
577
|
+
if (latestCtx) {
|
|
578
|
+
const current = this.indexedStack.get(latestCtx);
|
|
579
|
+
this.indexedStack.set(latestCtx, {
|
|
580
|
+
index: current.index,
|
|
581
|
+
funcCallIndex: new Map(),
|
|
582
|
+
});
|
|
583
|
+
}
|
|
553
584
|
}
|
|
554
585
|
popBreakContext() {
|
|
555
586
|
this.log('pop break context');
|
|
@@ -672,9 +703,18 @@ export class ExecutionContext {
|
|
|
672
703
|
__runFunc = this.__functionCache.get(functionName);
|
|
673
704
|
}
|
|
674
705
|
if (__runFunc !== null) {
|
|
706
|
+
let functionCallIndex = -1;
|
|
707
|
+
if (!this.scope.functionCounter.has(__runFunc)) {
|
|
708
|
+
this.scope.functionCounter.set(__runFunc, 0);
|
|
709
|
+
functionCallIndex = 0;
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
functionCallIndex = this.scope.functionCounter.get(__runFunc);
|
|
713
|
+
}
|
|
714
|
+
this.scope.functionCounter.set(__runFunc, functionCallIndex + 1);
|
|
675
715
|
this.log(`call function '${functionName}'`);
|
|
676
716
|
this.log(`net namespace: ${netNamespace}`);
|
|
677
|
-
const functionResult = __runFunc(functionParams, { netNamespace });
|
|
717
|
+
const functionResult = __runFunc(functionParams, { netNamespace, functionCallIndex });
|
|
678
718
|
this.log(`done call function '${functionName}'`);
|
|
679
719
|
return functionResult;
|
|
680
720
|
}
|
|
@@ -687,6 +727,7 @@ export class ExecutionContext {
|
|
|
687
727
|
const { currentComponent, currentPin, currentWireId } = this.scope;
|
|
688
728
|
const tmpInstances = childScope.instances;
|
|
689
729
|
const tmpNets = childScope.getNets();
|
|
730
|
+
const mergedInstances = [];
|
|
690
731
|
for (const [instanceName, component] of tmpInstances) {
|
|
691
732
|
const newInstanceName = `${namespace}.${instanceName}`;
|
|
692
733
|
component.instanceName = newInstanceName;
|
|
@@ -699,6 +740,7 @@ export class ExecutionContext {
|
|
|
699
740
|
else {
|
|
700
741
|
throw "Invalid instance name to merge into parent scope!";
|
|
701
742
|
}
|
|
743
|
+
mergedInstances.push(component);
|
|
702
744
|
}
|
|
703
745
|
const childScopeUniqueNets = new Set(tmpNets.map(([, , net]) => net));
|
|
704
746
|
childScopeUniqueNets.forEach(net => {
|
|
@@ -772,6 +814,7 @@ export class ExecutionContext {
|
|
|
772
814
|
return accum;
|
|
773
815
|
}, []);
|
|
774
816
|
this.log('-- done merging scope --');
|
|
817
|
+
return mergedInstances;
|
|
775
818
|
}
|
|
776
819
|
addWire(segments) {
|
|
777
820
|
if (this.scope.currentComponent === null) {
|
|
@@ -895,7 +938,7 @@ export class ExecutionContext {
|
|
|
895
938
|
idName = this.scope.currentComponent.instanceName;
|
|
896
939
|
if (this.scope.instances.has(idName)) {
|
|
897
940
|
const component = this.scope.instances.get(idName);
|
|
898
|
-
component.
|
|
941
|
+
component.setParam(paramName, value);
|
|
899
942
|
}
|
|
900
943
|
else if (this.scope.variables.has(idName)) {
|
|
901
944
|
throw "Not implemented yet!";
|
package/dist/esm/helpers.js
CHANGED
|
@@ -18,6 +18,7 @@ import { FrameParamKeys } from "./objects/Frame.js";
|
|
|
18
18
|
import Big from "big.js";
|
|
19
19
|
import { Logger } from "./logger.js";
|
|
20
20
|
import { NetGraph } from "./graph.js";
|
|
21
|
+
import { RefdesAnnotationVisitor } from "./RefdesAnnotationVisitor.js";
|
|
21
22
|
export var JSModuleType;
|
|
22
23
|
(function (JSModuleType) {
|
|
23
24
|
JSModuleType["CommonJs"] = "cjs";
|
|
@@ -154,7 +155,7 @@ export async function renderScript(scriptData, outputPath, options) {
|
|
|
154
155
|
return renderScriptCustom(scriptData, outputPath, options, parseHandlers);
|
|
155
156
|
}
|
|
156
157
|
export async function renderScriptCustom(scriptData, outputPath, options, parseHandlers) {
|
|
157
|
-
const { dumpNets = false, dumpData = false, showStats = false, environment } = options;
|
|
158
|
+
const { dumpNets = false, dumpData = false, showStats = false, environment, inputPath = null, updateSource = false, saveAnnotatedCopy = undefined, } = options;
|
|
158
159
|
const errors = [];
|
|
159
160
|
const onErrorHandler = (message, context, error) => {
|
|
160
161
|
if (error && error instanceof RuntimeExecutionError) {
|
|
@@ -198,7 +199,7 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
|
|
|
198
199
|
mkdirSync(dumpDirectory);
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
|
-
const { tree, parser, parserTimeTaken, lexerTimeTaken, throwError } = await parseFileWithVisitor(visitor, scriptData);
|
|
202
|
+
const { tree, parser, tokens, parserTimeTaken, lexerTimeTaken, throwError } = await parseFileWithVisitor(visitor, scriptData);
|
|
202
203
|
printWarnings(visitor.getWarnings());
|
|
203
204
|
showStats && console.log('Lexing took:', lexerTimeTaken);
|
|
204
205
|
showStats && console.log('Parsing took:', parserTimeTaken);
|
|
@@ -208,6 +209,23 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
|
|
|
208
209
|
catch (err) {
|
|
209
210
|
throw new RenderError(`Error during component annotation: ${err}`, 'annotation');
|
|
210
211
|
}
|
|
212
|
+
const componentLinks = visitor.getComponentCtxLinks();
|
|
213
|
+
const refdesVisitor = new RefdesAnnotationVisitor(true, scriptData, tokens, componentLinks);
|
|
214
|
+
await refdesVisitor.visitAsync(tree);
|
|
215
|
+
if (inputPath && (updateSource || saveAnnotatedCopy !== undefined)) {
|
|
216
|
+
let usePath = inputPath;
|
|
217
|
+
if (saveAnnotatedCopy === true) {
|
|
218
|
+
const dir = path.dirname(inputPath);
|
|
219
|
+
const ext = path.extname(inputPath);
|
|
220
|
+
const basename = path.basename(inputPath, ext);
|
|
221
|
+
usePath = path.join(dir, `${basename}.annotated${ext}`);
|
|
222
|
+
}
|
|
223
|
+
else if (typeof saveAnnotatedCopy === 'string') {
|
|
224
|
+
usePath = saveAnnotatedCopy;
|
|
225
|
+
}
|
|
226
|
+
console.log('Annotations saved to ' + usePath);
|
|
227
|
+
writeFileSync(usePath, refdesVisitor.getOutput());
|
|
228
|
+
}
|
|
211
229
|
if (dumpNets) {
|
|
212
230
|
const nets = visitor.dumpNets();
|
|
213
231
|
nets.forEach(item => console.log(item.join(" | ")));
|
package/dist/esm/lexer.js
CHANGED
|
@@ -26,12 +26,14 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
26
26
|
this.tokens = this.tokens.filter(function (val) {
|
|
27
27
|
return val.type !== CircuitScriptParser.EOF;
|
|
28
28
|
});
|
|
29
|
-
this.
|
|
29
|
+
const fillerNewLine = this.commonToken(CircuitScriptParser.NEWLINE, "");
|
|
30
|
+
this.emitToken(fillerNewLine);
|
|
31
|
+
fillerNewLine.__skip = true;
|
|
30
32
|
while (this.indents.length) {
|
|
31
33
|
this.emitToken(this.createDedent());
|
|
32
34
|
this.indents.pop();
|
|
33
35
|
}
|
|
34
|
-
this.emitToken(this.commonToken(CircuitScriptParser.EOF, "
|
|
36
|
+
this.emitToken(this.commonToken(CircuitScriptParser.EOF, ""));
|
|
35
37
|
}
|
|
36
38
|
const next = super.nextToken();
|
|
37
39
|
return this.tokens.length ? this.tokens.shift() : next;
|
|
@@ -42,16 +44,24 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
42
44
|
getCharIndex() {
|
|
43
45
|
return this.inputStream.index;
|
|
44
46
|
}
|
|
45
|
-
commonToken(type, text) {
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
commonToken(type, text, start = -1, stop = -1) {
|
|
48
|
+
if (start === -1 && stop === -1) {
|
|
49
|
+
stop = this.getCharIndex() - 1;
|
|
50
|
+
start = text.length ? stop - text.length + 1 : stop;
|
|
51
|
+
}
|
|
48
52
|
const token = CommonToken.fromSource([this, this.inputStream], type, 0, start, stop);
|
|
49
53
|
let tokenTypeString = null;
|
|
50
54
|
if (type === CircuitScriptParser.INDENT) {
|
|
51
|
-
tokenTypeString =
|
|
55
|
+
tokenTypeString = 'indent';
|
|
52
56
|
}
|
|
53
57
|
else if (type === CircuitScriptParser.DEDENT) {
|
|
54
|
-
tokenTypeString =
|
|
58
|
+
tokenTypeString = 'dedent';
|
|
59
|
+
}
|
|
60
|
+
else if (type === CircuitScriptParser.NEWLINE) {
|
|
61
|
+
tokenTypeString = 'newline';
|
|
62
|
+
}
|
|
63
|
+
else if (type === CircuitScriptParser.EOF) {
|
|
64
|
+
tokenTypeString = 'EOF';
|
|
55
65
|
}
|
|
56
66
|
if (tokenTypeString !== null) {
|
|
57
67
|
token.text = tokenTypeString;
|
|
@@ -89,7 +99,9 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
89
99
|
this.skip();
|
|
90
100
|
}
|
|
91
101
|
else {
|
|
92
|
-
this.
|
|
102
|
+
const start = this.getCharIndex() - this.text.length;
|
|
103
|
+
const stop = this.getCharIndex() - 1;
|
|
104
|
+
this.emitToken(this.commonToken(CircuitScriptParser.NEWLINE, newLine, start, start));
|
|
93
105
|
const indent = this.getIndentationCount(spaces);
|
|
94
106
|
const previous = this.indents.length ? this.indents[this.indents.length - 1] : 0;
|
|
95
107
|
if (indent === previous) {
|
|
@@ -97,7 +109,7 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
97
109
|
}
|
|
98
110
|
else if (indent > previous) {
|
|
99
111
|
this.indents.push(indent);
|
|
100
|
-
this.emitToken(this.commonToken(CircuitScriptParser.INDENT, spaces));
|
|
112
|
+
this.emitToken(this.commonToken(CircuitScriptParser.INDENT, spaces, start + 1, stop));
|
|
101
113
|
}
|
|
102
114
|
else {
|
|
103
115
|
while (this.indents.length && this.indents[this.indents.length - 1] > indent) {
|
package/dist/esm/main.js
CHANGED
|
@@ -15,6 +15,8 @@ export default async function main() {
|
|
|
15
15
|
.argument('[output path]', 'Output path')
|
|
16
16
|
.option('-i, --input text <input text>', 'Input text directly')
|
|
17
17
|
.option('-c, --current-directory <path>', 'Set current directory')
|
|
18
|
+
.option('-u, --update-source', 'Update source file with refdes annotation')
|
|
19
|
+
.option('-j, --annotated-path [file-path]', 'Save annotated source file at given path')
|
|
18
20
|
.option('-w, --watch', 'Watch for file changes')
|
|
19
21
|
.option('-n, --dump-nets', 'Dump out net information')
|
|
20
22
|
.option('-d, --dump-data', 'Dump data during parsing')
|
|
@@ -62,11 +64,22 @@ export default async function main() {
|
|
|
62
64
|
console.error("Error: No input provided");
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
67
|
+
let updateSource = false;
|
|
68
|
+
if (options.updateSource !== undefined) {
|
|
69
|
+
updateSource = options.updateSource;
|
|
70
|
+
}
|
|
71
|
+
let saveAnnotatedCopyPath = undefined;
|
|
72
|
+
if (options.annotatedPath !== undefined) {
|
|
73
|
+
saveAnnotatedCopyPath = options.annotatedPath;
|
|
74
|
+
}
|
|
65
75
|
const scriptOptions = {
|
|
66
76
|
dumpNets,
|
|
67
77
|
dumpData,
|
|
68
78
|
showStats: options.stats,
|
|
69
79
|
environment: env,
|
|
80
|
+
inputPath: inputFilePath,
|
|
81
|
+
updateSource,
|
|
82
|
+
saveAnnotatedCopy: saveAnnotatedCopyPath,
|
|
70
83
|
};
|
|
71
84
|
let outputPath = null;
|
|
72
85
|
if (args.length > 0 && args[1]) {
|
|
@@ -29,6 +29,9 @@ export class ClassComponent {
|
|
|
29
29
|
useWireOrientationAngle = true;
|
|
30
30
|
didSetWireOrientationAngle = false;
|
|
31
31
|
assignedRefDes = null;
|
|
32
|
+
placeHolderRefDes = null;
|
|
33
|
+
ctxReferences = [];
|
|
34
|
+
_creationIndex = -1;
|
|
32
35
|
constructor(instanceName, numPins) {
|
|
33
36
|
this.instanceName = instanceName;
|
|
34
37
|
this.numPins = numPins;
|
|
@@ -108,7 +111,7 @@ export class ClassComponent {
|
|
|
108
111
|
return this.parameters.get(key);
|
|
109
112
|
}
|
|
110
113
|
else {
|
|
111
|
-
throw 'Invalid parameter key';
|
|
114
|
+
throw 'Invalid parameter key: ' + key;
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
toString() {
|
package/dist/esm/parser.js
CHANGED
package/dist/esm/visitor.js
CHANGED
|
@@ -10,7 +10,9 @@ import { BaseVisitor } from './BaseVisitor.js';
|
|
|
10
10
|
import { getPortType, RuntimeExecutionError } from './utils.js';
|
|
11
11
|
import { UnitDimension } from './helpers.js';
|
|
12
12
|
import { FrameParamKeys } from './objects/Frame.js';
|
|
13
|
+
import { ComponentAnnotater } from './ComponentAnnotater.js';
|
|
13
14
|
export class ParserVisitor extends BaseVisitor {
|
|
15
|
+
componentCreationIndex = 0;
|
|
14
16
|
visitKeyword_assignment_expr = (ctx) => {
|
|
15
17
|
const id = ctx.ID().getText();
|
|
16
18
|
const value = this.visitResult(ctx.data_expr());
|
|
@@ -35,28 +37,53 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
35
37
|
}
|
|
36
38
|
this.setResult(ctx, pinId);
|
|
37
39
|
};
|
|
40
|
+
trackNewComponentCreated = (callback) => {
|
|
41
|
+
const preCreatedIndex = this.componentCreationIndex;
|
|
42
|
+
callback();
|
|
43
|
+
const postCreatedIndex = this.componentCreationIndex;
|
|
44
|
+
let creationFlag = false;
|
|
45
|
+
if (postCreatedIndex > preCreatedIndex) {
|
|
46
|
+
creationFlag = true;
|
|
47
|
+
}
|
|
48
|
+
return creationFlag;
|
|
49
|
+
};
|
|
38
50
|
visitAdd_component_expr = (ctx) => {
|
|
39
|
-
|
|
40
|
-
this.
|
|
51
|
+
let refComponent;
|
|
52
|
+
const creationFlag = this.trackNewComponentCreated(() => {
|
|
53
|
+
const [component, pinValue] = this.visitResult(ctx.data_expr_with_assignment());
|
|
54
|
+
this.getExecutor().addComponentExisting(component, pinValue);
|
|
55
|
+
refComponent = component;
|
|
56
|
+
});
|
|
57
|
+
this.linkComponentToCtx(ctx, refComponent, creationFlag);
|
|
41
58
|
};
|
|
42
59
|
visitAt_component_expr = (ctx) => {
|
|
43
|
-
|
|
44
|
-
this.
|
|
45
|
-
|
|
60
|
+
let refComponent;
|
|
61
|
+
const creationFlag = this.trackNewComponentCreated(() => {
|
|
62
|
+
const [component, pin] = this.visitResult(ctx.component_select_expr());
|
|
63
|
+
this.getExecutor().atComponent(component, pin, {
|
|
64
|
+
addSequence: true
|
|
65
|
+
});
|
|
66
|
+
refComponent = component;
|
|
46
67
|
});
|
|
68
|
+
this.linkComponentToCtx(ctx, refComponent, creationFlag);
|
|
47
69
|
return this.getExecutor().getCurrentPoint();
|
|
48
70
|
};
|
|
49
71
|
visitTo_component_expr = (ctx) => {
|
|
50
72
|
ctx.component_select_expr().forEach(item => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
73
|
+
let refComponent;
|
|
74
|
+
const creationFlag = this.trackNewComponentCreated(() => {
|
|
75
|
+
const [component, pin] = this.visitResult(item);
|
|
76
|
+
try {
|
|
77
|
+
this.getExecutor().toComponent(component, pin, {
|
|
78
|
+
addSequence: true
|
|
79
|
+
});
|
|
80
|
+
refComponent = component;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
throw new RuntimeExecutionError(err.message, ctx);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
this.linkComponentToCtx(item, refComponent, creationFlag);
|
|
60
87
|
});
|
|
61
88
|
return this.getExecutor().getCurrentPoint();
|
|
62
89
|
};
|
|
@@ -327,6 +354,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
327
354
|
try {
|
|
328
355
|
const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
|
|
329
356
|
this.setResult(ctx, createdComponent);
|
|
357
|
+
createdComponent._creationIndex = this.componentCreationIndex++;
|
|
330
358
|
}
|
|
331
359
|
catch (error) {
|
|
332
360
|
this.throwWithContext(ctx, error.message);
|
|
@@ -867,7 +895,28 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
867
895
|
const resolveNet = this.createNetResolver(this.executionStack);
|
|
868
896
|
const resolveComponentPinNet = this.createComponentPinNetResolver(this.executionStack);
|
|
869
897
|
const __runFunc = (passedInParameters, options) => {
|
|
870
|
-
const
|
|
898
|
+
const executor = this.getExecutor();
|
|
899
|
+
const parentBreakContext = executor.getParentBreakContext();
|
|
900
|
+
executor.addBreakContext(ctx);
|
|
901
|
+
let useIndex = -1;
|
|
902
|
+
if (parentBreakContext === null) {
|
|
903
|
+
useIndex = options.functionCallIndex;
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
const parentEntry = executor.indexedStack.get(parentBreakContext);
|
|
907
|
+
const { funcCallIndex } = parentEntry;
|
|
908
|
+
if (!funcCallIndex.has(ctx)) {
|
|
909
|
+
funcCallIndex.set(ctx, 0);
|
|
910
|
+
useIndex = 0;
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
useIndex = funcCallIndex.get(ctx) + 1;
|
|
914
|
+
funcCallIndex.set(ctx, useIndex);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
executor.setBreakContextIndex(useIndex);
|
|
918
|
+
const functionCounterIndex = functionCounter['counter'];
|
|
919
|
+
const executionContextName = `${functionName}-${functionCounterIndex}`;
|
|
871
920
|
const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, options, funcDefinedParameters, passedInParameters);
|
|
872
921
|
functionCounter['counter'] += 1;
|
|
873
922
|
newExecutor.resolveNet = resolveNet;
|
|
@@ -875,7 +924,23 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
875
924
|
const returnValue = this.runExpressions(newExecutor, ctx.function_expr());
|
|
876
925
|
const lastExecution = executionStack.pop();
|
|
877
926
|
const nextLastExecution = executionStack[executionStack.length - 1];
|
|
878
|
-
nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
|
|
927
|
+
const mergedComponents = nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
|
|
928
|
+
const scope = this.getScope();
|
|
929
|
+
const indexedStack = [];
|
|
930
|
+
if (scope.breakStack.length > 0) {
|
|
931
|
+
const executor = this.getExecutor();
|
|
932
|
+
scope.breakStack.forEach(stackCtx => {
|
|
933
|
+
const entry = executor.indexedStack.get(stackCtx);
|
|
934
|
+
const { index } = entry;
|
|
935
|
+
indexedStack.push([stackCtx, index]);
|
|
936
|
+
});
|
|
937
|
+
mergedComponents.forEach(component => {
|
|
938
|
+
component.ctxReferences.forEach(ref => {
|
|
939
|
+
ref.indexedStack = [...indexedStack, ...ref.indexedStack];
|
|
940
|
+
});
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
executor.popBreakContext();
|
|
879
944
|
return [lastExecution, returnValue];
|
|
880
945
|
};
|
|
881
946
|
this.getExecutor().createFunction(functionName, __runFunc, ctx, uniqueFunctionID);
|
|
@@ -919,10 +984,21 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
919
984
|
executor.log('end at block pin expressions');
|
|
920
985
|
executor.atComponent(currentComponent, currentPin);
|
|
921
986
|
};
|
|
987
|
+
visitAt_block_header = (ctx) => {
|
|
988
|
+
const ctxAtComponent = ctx.at_component_expr();
|
|
989
|
+
this.visit(ctxAtComponent);
|
|
990
|
+
const [currentComponent,] = this.getExecutor().getCurrentPoint();
|
|
991
|
+
this.componentCtxLinks.delete(ctxAtComponent);
|
|
992
|
+
this.componentCtxLinks.set(ctx, currentComponent);
|
|
993
|
+
ctx.annotation_comment_expr().forEach(ctx => {
|
|
994
|
+
this.visit(ctx);
|
|
995
|
+
});
|
|
996
|
+
};
|
|
922
997
|
visitAt_block = (ctx) => {
|
|
923
998
|
const executor = this.getExecutor();
|
|
924
999
|
executor.log('entering at block');
|
|
925
|
-
|
|
1000
|
+
const ctxAtBlockComponent = ctx.at_block_header();
|
|
1001
|
+
this.visit(ctxAtBlockComponent);
|
|
926
1002
|
const [currentComponent, currentPin] = executor.getCurrentPoint();
|
|
927
1003
|
executor.scope.scopeLevel += 1;
|
|
928
1004
|
ctx.at_block_expressions().forEach(expression => {
|
|
@@ -1082,10 +1158,14 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1082
1158
|
const dataExpr = ctx.data_expr();
|
|
1083
1159
|
let keepLooping = true;
|
|
1084
1160
|
this.log('enter while loop');
|
|
1085
|
-
this.getExecutor()
|
|
1161
|
+
const executor = this.getExecutor();
|
|
1162
|
+
executor.addBreakContext(ctx);
|
|
1163
|
+
let counter = 0;
|
|
1086
1164
|
while (keepLooping) {
|
|
1087
1165
|
const result = this.visitResult(dataExpr);
|
|
1088
1166
|
if (result) {
|
|
1167
|
+
executor.setBreakContextIndex(counter);
|
|
1168
|
+
executor.resetBreakContextFunctionCalls();
|
|
1089
1169
|
this.visit(ctx.expressions_block());
|
|
1090
1170
|
keepLooping = true;
|
|
1091
1171
|
const currentResult = this.getResult(ctx) ?? {};
|
|
@@ -1100,6 +1180,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1100
1180
|
continueSignal: false
|
|
1101
1181
|
});
|
|
1102
1182
|
}
|
|
1183
|
+
counter++;
|
|
1103
1184
|
}
|
|
1104
1185
|
else {
|
|
1105
1186
|
keepLooping = false;
|
|
@@ -1113,7 +1194,8 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1113
1194
|
const forVariableNames = ctx.ID().map(item => item.getText());
|
|
1114
1195
|
let listItems = this.visitResult(ctx.data_expr());
|
|
1115
1196
|
listItems = unwrapValue(listItems);
|
|
1116
|
-
this.getExecutor()
|
|
1197
|
+
const executor = this.getExecutor();
|
|
1198
|
+
executor.addBreakContext(ctx);
|
|
1117
1199
|
let keepLooping = true;
|
|
1118
1200
|
let counter = 0;
|
|
1119
1201
|
while (keepLooping) {
|
|
@@ -1125,6 +1207,8 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1125
1207
|
useValueArray.forEach((value, index) => {
|
|
1126
1208
|
this.getScope().setVariable(forVariableNames[index], value);
|
|
1127
1209
|
});
|
|
1210
|
+
executor.setBreakContextIndex(counter);
|
|
1211
|
+
executor.resetBreakContextFunctionCalls();
|
|
1128
1212
|
this.visit(ctx.expressions_block());
|
|
1129
1213
|
keepLooping = true;
|
|
1130
1214
|
const currentResult = this.getResult(ctx) ?? {};
|
|
@@ -1146,7 +1230,19 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1146
1230
|
keepLooping = false;
|
|
1147
1231
|
}
|
|
1148
1232
|
}
|
|
1149
|
-
|
|
1233
|
+
executor.popBreakContext();
|
|
1234
|
+
};
|
|
1235
|
+
visitAnnotation_comment_expr = (ctx) => {
|
|
1236
|
+
const refdesID = ctx.ID().getText();
|
|
1237
|
+
const currentComponent = this.getScope().currentComponent;
|
|
1238
|
+
if (currentComponent !== null) {
|
|
1239
|
+
if (refdesID.indexOf('_') === -1) {
|
|
1240
|
+
currentComponent.setParam('refdes', refdesID);
|
|
1241
|
+
}
|
|
1242
|
+
else {
|
|
1243
|
+
currentComponent.placeHolderRefDes = refdesID;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1150
1246
|
};
|
|
1151
1247
|
resolveDataExpr(data_expr) {
|
|
1152
1248
|
const value = this.visitResult(data_expr);
|
|
@@ -1349,8 +1445,8 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1349
1445
|
continue;
|
|
1350
1446
|
}
|
|
1351
1447
|
if (instance.assignedRefDes === null) {
|
|
1352
|
-
if (instance.
|
|
1353
|
-
const refdes = instance.
|
|
1448
|
+
if (instance.hasParam('refdes')) {
|
|
1449
|
+
const refdes = instance.getParam('refdes');
|
|
1354
1450
|
if (refdes) {
|
|
1355
1451
|
instance.assignedRefDes = refdes;
|
|
1356
1452
|
annotater.trackRefDes(refdes);
|
|
@@ -1362,10 +1458,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1362
1458
|
}
|
|
1363
1459
|
}
|
|
1364
1460
|
toAnnotate.forEach(instance => {
|
|
1365
|
-
const
|
|
1366
|
-
instance.typeProp === null
|
|
1367
|
-
&& this.log('Instance has no type:', instance.instanceName, ' assuming connector');
|
|
1368
|
-
const newRefDes = annotater.getAnnotation(useTypeProp);
|
|
1461
|
+
const newRefDes = annotater.getAnnotation(instance);
|
|
1369
1462
|
if (newRefDes !== null) {
|
|
1370
1463
|
instance.assignedRefDes = newRefDes;
|
|
1371
1464
|
this.log(newRefDes, '-', instance.instanceName);
|
|
@@ -1449,7 +1542,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
1449
1542
|
return this.warnings;
|
|
1450
1543
|
}
|
|
1451
1544
|
}
|
|
1452
|
-
const ComponentRefDesPrefixes = {
|
|
1545
|
+
export const ComponentRefDesPrefixes = {
|
|
1453
1546
|
res: 'R',
|
|
1454
1547
|
cap: 'C',
|
|
1455
1548
|
ind: 'L',
|
|
@@ -1460,48 +1553,6 @@ const ComponentRefDesPrefixes = {
|
|
|
1460
1553
|
ic: 'U',
|
|
1461
1554
|
'?': '?',
|
|
1462
1555
|
};
|
|
1463
|
-
class ComponentAnnotater {
|
|
1464
|
-
counter = {};
|
|
1465
|
-
existingRefDes = [];
|
|
1466
|
-
constructor() {
|
|
1467
|
-
for (const key in ComponentRefDesPrefixes) {
|
|
1468
|
-
this.counter[key] = 1;
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
getAnnotation(type) {
|
|
1472
|
-
if (this.counter[type] === undefined && type.length <= 2) {
|
|
1473
|
-
for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
|
|
1474
|
-
if (value === type) {
|
|
1475
|
-
throw "Refdes prefix is already in use!";
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
if (ComponentRefDesPrefixes[type] === undefined) {
|
|
1479
|
-
ComponentRefDesPrefixes[type] = type;
|
|
1480
|
-
this.counter[type] = 1;
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
if (ComponentRefDesPrefixes[type] === undefined) {
|
|
1484
|
-
return null;
|
|
1485
|
-
}
|
|
1486
|
-
let attempts = 100;
|
|
1487
|
-
let proposedName = "";
|
|
1488
|
-
while (attempts >= 0) {
|
|
1489
|
-
proposedName = ComponentRefDesPrefixes[type] + this.counter[type];
|
|
1490
|
-
this.counter[type]++;
|
|
1491
|
-
if (this.existingRefDes.indexOf(proposedName) === -1) {
|
|
1492
|
-
break;
|
|
1493
|
-
}
|
|
1494
|
-
attempts--;
|
|
1495
|
-
}
|
|
1496
|
-
if (attempts === 0) {
|
|
1497
|
-
throw "Annotation failed!";
|
|
1498
|
-
}
|
|
1499
|
-
return proposedName;
|
|
1500
|
-
}
|
|
1501
|
-
trackRefDes(name) {
|
|
1502
|
-
this.existingRefDes.push(name);
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
1556
|
export class VisitorExecutionException {
|
|
1506
1557
|
errorMessage;
|
|
1507
1558
|
context;
|
|
@@ -21,6 +21,7 @@ export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyR
|
|
|
21
21
|
printToConsole: boolean;
|
|
22
22
|
acceptedDirections: Direction[];
|
|
23
23
|
protected resultData: Map<ParserRuleContext, any>;
|
|
24
|
+
protected componentCtxLinks: Map<ParserRuleContext, ClassComponent>;
|
|
24
25
|
pinTypesList: string[];
|
|
25
26
|
onErrorHandler: OnErrorHandler | null;
|
|
26
27
|
environment: NodeScriptEnvironment;
|
|
@@ -64,6 +65,8 @@ export declare class BaseVisitor extends CircuitScriptVisitor<ComplexType | AnyR
|
|
|
64
65
|
visitArrayIndexExpr: (ctx: ArrayIndexExprContext) => void;
|
|
65
66
|
protected setResult(ctx: ParserRuleContext, value: any): void;
|
|
66
67
|
protected getResult(ctx: ParserRuleContext): any;
|
|
68
|
+
protected linkComponentToCtx(ctx: ParserRuleContext, instance: ClassComponent, creationFlag?: boolean): void;
|
|
69
|
+
getComponentCtxLinks(): Map<ParserRuleContext, ClassComponent>;
|
|
67
70
|
visitResult(ctx: ParserRuleContext): any;
|
|
68
71
|
protected handleImportFile(name: string, throwErrors?: boolean, ctx?: ParserRuleContext | null): Promise<ImportFile>;
|
|
69
72
|
visitRoundedBracketsExpr: (ctx: RoundedBracketsExprContext) => void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ParserRuleContext } from 'antlr4ng';
|
|
2
|
+
import { ClassComponent } from './objects/ClassComponent.js';
|
|
3
|
+
export declare class ComponentAnnotater {
|
|
4
|
+
counter: {
|
|
5
|
+
[key: string]: number;
|
|
6
|
+
};
|
|
7
|
+
indexedContextPrefix: Map<ParserRuleContext, string>;
|
|
8
|
+
existingRefDes: string[];
|
|
9
|
+
constructor();
|
|
10
|
+
getAnnotation(instance: ClassComponent): string | null;
|
|
11
|
+
getNextRefdesCounter(prefix: string, startingIndex: number): {
|
|
12
|
+
index: number;
|
|
13
|
+
proposedName: string;
|
|
14
|
+
};
|
|
15
|
+
trackRefDes(name: string): void;
|
|
16
|
+
}
|