circuitscript 0.1.19 → 0.1.22
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 +964 -831
- package/dist/cjs/environment.js +15 -1
- package/dist/cjs/execute.js +45 -2
- package/dist/cjs/graph.js +23 -2
- package/dist/cjs/helpers.js +21 -4
- package/dist/cjs/layout.js +3 -0
- 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 +119 -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 +960 -829
- 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/graph.js +23 -2
- package/dist/esm/helpers.js +21 -4
- package/dist/esm/layout.js +4 -0
- 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 +117 -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 +80 -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 +6 -3
- package/dist/types/layout.d.ts +2 -0
- 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
package/dist/cjs/visitor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VisitorExecutionException = exports.ParserVisitor = void 0;
|
|
3
|
+
exports.VisitorExecutionException = exports.ComponentRefDesPrefixes = exports.ParserVisitor = void 0;
|
|
4
4
|
const ClassComponent_js_1 = require("./objects/ClassComponent.js");
|
|
5
5
|
const ParamDefinition_js_1 = require("./objects/ParamDefinition.js");
|
|
6
6
|
const PinDefinition_js_1 = require("./objects/PinDefinition.js");
|
|
@@ -13,9 +13,11 @@ const BaseVisitor_js_1 = require("./BaseVisitor.js");
|
|
|
13
13
|
const utils_js_2 = require("./utils.js");
|
|
14
14
|
const helpers_js_1 = require("./helpers.js");
|
|
15
15
|
const Frame_js_1 = require("./objects/Frame.js");
|
|
16
|
+
const ComponentAnnotater_js_1 = require("./ComponentAnnotater.js");
|
|
16
17
|
class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
17
18
|
constructor() {
|
|
18
19
|
super(...arguments);
|
|
20
|
+
this.componentCreationIndex = 0;
|
|
19
21
|
this.visitKeyword_assignment_expr = (ctx) => {
|
|
20
22
|
const id = ctx.ID().getText();
|
|
21
23
|
const value = this.visitResult(ctx.data_expr());
|
|
@@ -40,28 +42,53 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
40
42
|
}
|
|
41
43
|
this.setResult(ctx, pinId);
|
|
42
44
|
};
|
|
45
|
+
this.trackNewComponentCreated = (callback) => {
|
|
46
|
+
const preCreatedIndex = this.componentCreationIndex;
|
|
47
|
+
callback();
|
|
48
|
+
const postCreatedIndex = this.componentCreationIndex;
|
|
49
|
+
let creationFlag = false;
|
|
50
|
+
if (postCreatedIndex > preCreatedIndex) {
|
|
51
|
+
creationFlag = true;
|
|
52
|
+
}
|
|
53
|
+
return creationFlag;
|
|
54
|
+
};
|
|
43
55
|
this.visitAdd_component_expr = (ctx) => {
|
|
44
|
-
|
|
45
|
-
this.
|
|
56
|
+
let refComponent;
|
|
57
|
+
const creationFlag = this.trackNewComponentCreated(() => {
|
|
58
|
+
const [component, pinValue] = this.visitResult(ctx.data_expr_with_assignment());
|
|
59
|
+
this.getExecutor().addComponentExisting(component, pinValue);
|
|
60
|
+
refComponent = component;
|
|
61
|
+
});
|
|
62
|
+
this.linkComponentToCtx(ctx, refComponent, creationFlag);
|
|
46
63
|
};
|
|
47
64
|
this.visitAt_component_expr = (ctx) => {
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
|
|
65
|
+
let refComponent;
|
|
66
|
+
const creationFlag = this.trackNewComponentCreated(() => {
|
|
67
|
+
const [component, pin] = this.visitResult(ctx.component_select_expr());
|
|
68
|
+
this.getExecutor().atComponent(component, pin, {
|
|
69
|
+
addSequence: true
|
|
70
|
+
});
|
|
71
|
+
refComponent = component;
|
|
51
72
|
});
|
|
73
|
+
this.linkComponentToCtx(ctx, refComponent, creationFlag);
|
|
52
74
|
return this.getExecutor().getCurrentPoint();
|
|
53
75
|
};
|
|
54
76
|
this.visitTo_component_expr = (ctx) => {
|
|
55
77
|
ctx.component_select_expr().forEach(item => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
let refComponent;
|
|
79
|
+
const creationFlag = this.trackNewComponentCreated(() => {
|
|
80
|
+
const [component, pin] = this.visitResult(item);
|
|
81
|
+
try {
|
|
82
|
+
this.getExecutor().toComponent(component, pin, {
|
|
83
|
+
addSequence: true
|
|
84
|
+
});
|
|
85
|
+
refComponent = component;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
throw new utils_js_2.RuntimeExecutionError(err.message, ctx);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
this.linkComponentToCtx(item, refComponent, creationFlag);
|
|
65
92
|
});
|
|
66
93
|
return this.getExecutor().getCurrentPoint();
|
|
67
94
|
};
|
|
@@ -332,6 +359,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
332
359
|
try {
|
|
333
360
|
const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
|
|
334
361
|
this.setResult(ctx, createdComponent);
|
|
362
|
+
createdComponent._creationIndex = this.componentCreationIndex++;
|
|
335
363
|
}
|
|
336
364
|
catch (error) {
|
|
337
365
|
this.throwWithContext(ctx, error.message);
|
|
@@ -822,7 +850,28 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
822
850
|
const resolveNet = this.createNetResolver(this.executionStack);
|
|
823
851
|
const resolveComponentPinNet = this.createComponentPinNetResolver(this.executionStack);
|
|
824
852
|
const __runFunc = (passedInParameters, options) => {
|
|
825
|
-
const
|
|
853
|
+
const executor = this.getExecutor();
|
|
854
|
+
const parentBreakContext = executor.getParentBreakContext();
|
|
855
|
+
executor.addBreakContext(ctx);
|
|
856
|
+
let useIndex = -1;
|
|
857
|
+
if (parentBreakContext === null) {
|
|
858
|
+
useIndex = options.functionCallIndex;
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
const parentEntry = executor.indexedStack.get(parentBreakContext);
|
|
862
|
+
const { funcCallIndex } = parentEntry;
|
|
863
|
+
if (!funcCallIndex.has(ctx)) {
|
|
864
|
+
funcCallIndex.set(ctx, 0);
|
|
865
|
+
useIndex = 0;
|
|
866
|
+
}
|
|
867
|
+
else {
|
|
868
|
+
useIndex = funcCallIndex.get(ctx) + 1;
|
|
869
|
+
funcCallIndex.set(ctx, useIndex);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
executor.setBreakContextIndex(useIndex);
|
|
873
|
+
const functionCounterIndex = functionCounter['counter'];
|
|
874
|
+
const executionContextName = `${functionName}-${functionCounterIndex}`;
|
|
826
875
|
const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, options, funcDefinedParameters, passedInParameters);
|
|
827
876
|
functionCounter['counter'] += 1;
|
|
828
877
|
newExecutor.resolveNet = resolveNet;
|
|
@@ -830,7 +879,23 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
830
879
|
const returnValue = this.runExpressions(newExecutor, ctx.function_expr());
|
|
831
880
|
const lastExecution = executionStack.pop();
|
|
832
881
|
const nextLastExecution = executionStack[executionStack.length - 1];
|
|
833
|
-
nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
|
|
882
|
+
const mergedComponents = nextLastExecution.mergeScope(lastExecution.scope, executionContextName);
|
|
883
|
+
const scope = this.getScope();
|
|
884
|
+
const indexedStack = [];
|
|
885
|
+
if (scope.breakStack.length > 0) {
|
|
886
|
+
const executor = this.getExecutor();
|
|
887
|
+
scope.breakStack.forEach(stackCtx => {
|
|
888
|
+
const entry = executor.indexedStack.get(stackCtx);
|
|
889
|
+
const { index } = entry;
|
|
890
|
+
indexedStack.push([stackCtx, index]);
|
|
891
|
+
});
|
|
892
|
+
mergedComponents.forEach(component => {
|
|
893
|
+
component.ctxReferences.forEach(ref => {
|
|
894
|
+
ref.indexedStack = [...indexedStack, ...ref.indexedStack];
|
|
895
|
+
});
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
executor.popBreakContext();
|
|
834
899
|
return [lastExecution, returnValue];
|
|
835
900
|
};
|
|
836
901
|
this.getExecutor().createFunction(functionName, __runFunc, ctx, uniqueFunctionID);
|
|
@@ -874,10 +939,18 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
874
939
|
executor.log('end at block pin expressions');
|
|
875
940
|
executor.atComponent(currentComponent, currentPin);
|
|
876
941
|
};
|
|
942
|
+
this.visitAt_block_header = (ctx) => {
|
|
943
|
+
const ctxAtComponent = ctx.at_component_expr();
|
|
944
|
+
this.visit(ctxAtComponent);
|
|
945
|
+
const [currentComponent,] = this.getExecutor().getCurrentPoint();
|
|
946
|
+
this.componentCtxLinks.delete(ctxAtComponent);
|
|
947
|
+
this.componentCtxLinks.set(ctx, currentComponent);
|
|
948
|
+
};
|
|
877
949
|
this.visitAt_block = (ctx) => {
|
|
878
950
|
const executor = this.getExecutor();
|
|
879
951
|
executor.log('entering at block');
|
|
880
|
-
|
|
952
|
+
const ctxAtBlockComponent = ctx.at_block_header();
|
|
953
|
+
this.visit(ctxAtBlockComponent);
|
|
881
954
|
const [currentComponent, currentPin] = executor.getCurrentPoint();
|
|
882
955
|
executor.scope.scopeLevel += 1;
|
|
883
956
|
ctx.at_block_expressions().forEach(expression => {
|
|
@@ -1037,10 +1110,14 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1037
1110
|
const dataExpr = ctx.data_expr();
|
|
1038
1111
|
let keepLooping = true;
|
|
1039
1112
|
this.log('enter while loop');
|
|
1040
|
-
this.getExecutor()
|
|
1113
|
+
const executor = this.getExecutor();
|
|
1114
|
+
executor.addBreakContext(ctx);
|
|
1115
|
+
let counter = 0;
|
|
1041
1116
|
while (keepLooping) {
|
|
1042
1117
|
const result = this.visitResult(dataExpr);
|
|
1043
1118
|
if (result) {
|
|
1119
|
+
executor.setBreakContextIndex(counter);
|
|
1120
|
+
executor.resetBreakContextFunctionCalls();
|
|
1044
1121
|
this.visit(ctx.expressions_block());
|
|
1045
1122
|
keepLooping = true;
|
|
1046
1123
|
const currentResult = this.getResult(ctx) ?? {};
|
|
@@ -1055,6 +1132,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1055
1132
|
continueSignal: false
|
|
1056
1133
|
});
|
|
1057
1134
|
}
|
|
1135
|
+
counter++;
|
|
1058
1136
|
}
|
|
1059
1137
|
else {
|
|
1060
1138
|
keepLooping = false;
|
|
@@ -1068,7 +1146,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1068
1146
|
const forVariableNames = ctx.ID().map(item => item.getText());
|
|
1069
1147
|
let listItems = this.visitResult(ctx.data_expr());
|
|
1070
1148
|
listItems = (0, utils_js_1.unwrapValue)(listItems);
|
|
1071
|
-
this.getExecutor()
|
|
1149
|
+
const executor = this.getExecutor();
|
|
1150
|
+
executor.addBreakContext(ctx);
|
|
1072
1151
|
let keepLooping = true;
|
|
1073
1152
|
let counter = 0;
|
|
1074
1153
|
while (keepLooping) {
|
|
@@ -1080,6 +1159,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1080
1159
|
useValueArray.forEach((value, index) => {
|
|
1081
1160
|
this.getScope().setVariable(forVariableNames[index], value);
|
|
1082
1161
|
});
|
|
1162
|
+
executor.setBreakContextIndex(counter);
|
|
1163
|
+
executor.resetBreakContextFunctionCalls();
|
|
1083
1164
|
this.visit(ctx.expressions_block());
|
|
1084
1165
|
keepLooping = true;
|
|
1085
1166
|
const currentResult = this.getResult(ctx) ?? {};
|
|
@@ -1101,7 +1182,19 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1101
1182
|
keepLooping = false;
|
|
1102
1183
|
}
|
|
1103
1184
|
}
|
|
1104
|
-
|
|
1185
|
+
executor.popBreakContext();
|
|
1186
|
+
};
|
|
1187
|
+
this.visitAnnotation_comment_expr = (ctx) => {
|
|
1188
|
+
const refdesID = ctx.ID().getText();
|
|
1189
|
+
const currentComponent = this.getScope().currentComponent;
|
|
1190
|
+
if (currentComponent !== null) {
|
|
1191
|
+
if (refdesID.indexOf('_') === -1) {
|
|
1192
|
+
currentComponent.setParam('refdes', refdesID);
|
|
1193
|
+
}
|
|
1194
|
+
else {
|
|
1195
|
+
currentComponent.placeHolderRefDes = refdesID;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1105
1198
|
};
|
|
1106
1199
|
this.pinTypes = [
|
|
1107
1200
|
PinTypes_js_1.PinTypes.Any,
|
|
@@ -1346,7 +1439,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1346
1439
|
}
|
|
1347
1440
|
annotateComponents() {
|
|
1348
1441
|
this.log('===== annotate components =====');
|
|
1349
|
-
const annotater = new ComponentAnnotater();
|
|
1442
|
+
const annotater = new ComponentAnnotater_js_1.ComponentAnnotater();
|
|
1350
1443
|
const instances = this.getScope().instances;
|
|
1351
1444
|
const toAnnotate = [];
|
|
1352
1445
|
for (const [, instance] of instances) {
|
|
@@ -1355,8 +1448,8 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1355
1448
|
continue;
|
|
1356
1449
|
}
|
|
1357
1450
|
if (instance.assignedRefDes === null) {
|
|
1358
|
-
if (instance.
|
|
1359
|
-
const refdes = instance.
|
|
1451
|
+
if (instance.hasParam('refdes')) {
|
|
1452
|
+
const refdes = instance.getParam('refdes');
|
|
1360
1453
|
if (refdes) {
|
|
1361
1454
|
instance.assignedRefDes = refdes;
|
|
1362
1455
|
annotater.trackRefDes(refdes);
|
|
@@ -1368,10 +1461,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1368
1461
|
}
|
|
1369
1462
|
}
|
|
1370
1463
|
toAnnotate.forEach(instance => {
|
|
1371
|
-
const
|
|
1372
|
-
instance.typeProp === null
|
|
1373
|
-
&& this.log('Instance has no type:', instance.instanceName, ' assuming connector');
|
|
1374
|
-
const newRefDes = annotater.getAnnotation(useTypeProp);
|
|
1464
|
+
const newRefDes = annotater.getAnnotation(instance);
|
|
1375
1465
|
if (newRefDes !== null) {
|
|
1376
1466
|
instance.assignedRefDes = newRefDes;
|
|
1377
1467
|
this.log(newRefDes, '-', instance.instanceName);
|
|
@@ -1456,7 +1546,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1456
1546
|
}
|
|
1457
1547
|
}
|
|
1458
1548
|
exports.ParserVisitor = ParserVisitor;
|
|
1459
|
-
|
|
1549
|
+
exports.ComponentRefDesPrefixes = {
|
|
1460
1550
|
res: 'R',
|
|
1461
1551
|
cap: 'C',
|
|
1462
1552
|
ind: 'L',
|
|
@@ -1467,48 +1557,6 @@ const ComponentRefDesPrefixes = {
|
|
|
1467
1557
|
ic: 'U',
|
|
1468
1558
|
'?': '?',
|
|
1469
1559
|
};
|
|
1470
|
-
class ComponentAnnotater {
|
|
1471
|
-
constructor() {
|
|
1472
|
-
this.counter = {};
|
|
1473
|
-
this.existingRefDes = [];
|
|
1474
|
-
for (const key in ComponentRefDesPrefixes) {
|
|
1475
|
-
this.counter[key] = 1;
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
getAnnotation(type) {
|
|
1479
|
-
if (this.counter[type] === undefined && type.length <= 2) {
|
|
1480
|
-
for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
|
|
1481
|
-
if (value === type) {
|
|
1482
|
-
throw "Refdes prefix is already in use!";
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
if (ComponentRefDesPrefixes[type] === undefined) {
|
|
1486
|
-
ComponentRefDesPrefixes[type] = type;
|
|
1487
|
-
this.counter[type] = 1;
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
if (ComponentRefDesPrefixes[type] === undefined) {
|
|
1491
|
-
return null;
|
|
1492
|
-
}
|
|
1493
|
-
let attempts = 100;
|
|
1494
|
-
let proposedName = "";
|
|
1495
|
-
while (attempts >= 0) {
|
|
1496
|
-
proposedName = ComponentRefDesPrefixes[type] + this.counter[type];
|
|
1497
|
-
this.counter[type]++;
|
|
1498
|
-
if (this.existingRefDes.indexOf(proposedName) === -1) {
|
|
1499
|
-
break;
|
|
1500
|
-
}
|
|
1501
|
-
attempts--;
|
|
1502
|
-
}
|
|
1503
|
-
if (attempts === 0) {
|
|
1504
|
-
throw "Annotation failed!";
|
|
1505
|
-
}
|
|
1506
|
-
return proposedName;
|
|
1507
|
-
}
|
|
1508
|
-
trackRefDes(name) {
|
|
1509
|
-
this.existingRefDes.push(name);
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
1560
|
class VisitorExecutionException {
|
|
1513
1561
|
constructor(context, errorMessage) {
|
|
1514
1562
|
this.errorMessage = errorMessage;
|
package/dist/esm/BaseVisitor.js
CHANGED
|
@@ -23,6 +23,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
23
23
|
acceptedDirections = [Direction.Up, Direction.Down,
|
|
24
24
|
Direction.Right, Direction.Left];
|
|
25
25
|
resultData = new Map;
|
|
26
|
+
componentCtxLinks = new Map;
|
|
26
27
|
pinTypesList = [
|
|
27
28
|
PinTypes.Any,
|
|
28
29
|
PinTypes.Input,
|
|
@@ -564,6 +565,27 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
564
565
|
getResult(ctx) {
|
|
565
566
|
return this.resultData.get(ctx);
|
|
566
567
|
}
|
|
568
|
+
linkComponentToCtx(ctx, instance, creationFlag = true) {
|
|
569
|
+
const scope = this.getScope();
|
|
570
|
+
const indexedStack = [];
|
|
571
|
+
if (scope.breakStack.length > 0) {
|
|
572
|
+
const executor = this.getExecutor();
|
|
573
|
+
scope.breakStack.forEach(stackCtx => {
|
|
574
|
+
const entry = executor.indexedStack.get(stackCtx);
|
|
575
|
+
const { index } = entry;
|
|
576
|
+
indexedStack.push([stackCtx, index]);
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
instance.ctxReferences.push({
|
|
580
|
+
ctx,
|
|
581
|
+
indexedStack,
|
|
582
|
+
creationFlag
|
|
583
|
+
});
|
|
584
|
+
this.componentCtxLinks.set(ctx, instance);
|
|
585
|
+
}
|
|
586
|
+
getComponentCtxLinks() {
|
|
587
|
+
return this.componentCtxLinks;
|
|
588
|
+
}
|
|
567
589
|
visitResult(ctx) {
|
|
568
590
|
this.visit(ctx);
|
|
569
591
|
return this.getResult(ctx);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { ComponentRefDesPrefixes } from './visitor.js';
|
|
2
|
+
export class ComponentAnnotater {
|
|
3
|
+
counter = {};
|
|
4
|
+
indexedContextPrefix = new Map();
|
|
5
|
+
existingRefDes = [];
|
|
6
|
+
constructor() {
|
|
7
|
+
for (const key in ComponentRefDesPrefixes) {
|
|
8
|
+
this.counter[key] = 1;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
getAnnotation(instance) {
|
|
12
|
+
const type = instance.typeProp ?? 'conn';
|
|
13
|
+
if (this.counter[type] === undefined && type.length <= 2) {
|
|
14
|
+
for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
|
|
15
|
+
if (value === type) {
|
|
16
|
+
throw "Refdes prefix is already in use!";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (ComponentRefDesPrefixes[type] === undefined) {
|
|
20
|
+
ComponentRefDesPrefixes[type] = type;
|
|
21
|
+
this.counter[type] = 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (ComponentRefDesPrefixes[type] === undefined) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
let prefix = '';
|
|
28
|
+
let resultRefdes = '';
|
|
29
|
+
const { ctxReferences } = instance;
|
|
30
|
+
if (ctxReferences.length > 0) {
|
|
31
|
+
const firstReference = ctxReferences[0];
|
|
32
|
+
const { ctx: useCtx, indexedStack, creationFlag } = firstReference;
|
|
33
|
+
if (indexedStack.length > 0 && creationFlag) {
|
|
34
|
+
const indexes = indexedStack.map(item => {
|
|
35
|
+
return item[1] + 1;
|
|
36
|
+
});
|
|
37
|
+
if (!this.indexedContextPrefix.has(useCtx)) {
|
|
38
|
+
if (instance.placeHolderRefDes) {
|
|
39
|
+
prefix = instance.placeHolderRefDes.replaceAll('_', '');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const { index: nextIndex, proposedName } = this.getNextRefdesCounter(ComponentRefDesPrefixes[type], this.counter[type]);
|
|
43
|
+
this.counter[type] = nextIndex;
|
|
44
|
+
prefix = proposedName;
|
|
45
|
+
}
|
|
46
|
+
this.existingRefDes.push(prefix);
|
|
47
|
+
this.indexedContextPrefix.set(useCtx, prefix);
|
|
48
|
+
}
|
|
49
|
+
const prefixParts = [this.indexedContextPrefix.get(useCtx), ...indexes];
|
|
50
|
+
resultRefdes = prefixParts.join('_');
|
|
51
|
+
if (this.existingRefDes.indexOf(resultRefdes) !== -1) {
|
|
52
|
+
console.log('Warning: Refdes already used:', resultRefdes);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const refdesCounter = this.getNextRefdesCounter(ComponentRefDesPrefixes[type], this.counter[type]);
|
|
57
|
+
this.counter[type] = refdesCounter.index;
|
|
58
|
+
resultRefdes = refdesCounter.proposedName;
|
|
59
|
+
}
|
|
60
|
+
this.existingRefDes.push(resultRefdes);
|
|
61
|
+
return resultRefdes;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
getNextRefdesCounter(prefix, startingIndex) {
|
|
65
|
+
let attempts = 100;
|
|
66
|
+
let proposedName = "";
|
|
67
|
+
let index = startingIndex;
|
|
68
|
+
while (attempts >= 0) {
|
|
69
|
+
proposedName = prefix + index;
|
|
70
|
+
index++;
|
|
71
|
+
if (this.existingRefDes.indexOf(proposedName) === -1) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
attempts--;
|
|
75
|
+
}
|
|
76
|
+
if (attempts === 0) {
|
|
77
|
+
throw "Annotation failed";
|
|
78
|
+
}
|
|
79
|
+
return { index, proposedName };
|
|
80
|
+
}
|
|
81
|
+
trackRefDes(name) {
|
|
82
|
+
this.existingRefDes.push(name);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { CircuitScriptParser } from './antlr/CircuitScriptParser.js';
|
|
2
|
+
import { BaseVisitor } from './BaseVisitor.js';
|
|
3
|
+
export class RefdesAnnotationVisitor extends BaseVisitor {
|
|
4
|
+
sourceText;
|
|
5
|
+
tokenStream;
|
|
6
|
+
modifications = new Map();
|
|
7
|
+
resultText = '';
|
|
8
|
+
debug = false;
|
|
9
|
+
componentCtxLinks;
|
|
10
|
+
constructor(silent, sourceText, tokenStream, componentCtxLinks) {
|
|
11
|
+
super(true);
|
|
12
|
+
this.sourceText = sourceText;
|
|
13
|
+
this.tokenStream = tokenStream;
|
|
14
|
+
this.componentCtxLinks = componentCtxLinks;
|
|
15
|
+
}
|
|
16
|
+
getOriginalText(ctx) {
|
|
17
|
+
if (!ctx.start || !ctx.stop) {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
const startIndex = ctx.start.start;
|
|
21
|
+
const stopIndex = ctx.stop.stop;
|
|
22
|
+
return this.sourceText.substring(startIndex, stopIndex + 1);
|
|
23
|
+
}
|
|
24
|
+
visitScript = async (ctx) => {
|
|
25
|
+
const result = this.runExpressions(this.getExecutor(), ctx.expression());
|
|
26
|
+
this.setResult(ctx, result);
|
|
27
|
+
this.getExecutor().closeOpenPathBlocks();
|
|
28
|
+
this.resultText = this.generateModifiedText();
|
|
29
|
+
};
|
|
30
|
+
visitAdd_component_expr = (ctx) => {
|
|
31
|
+
this.addRefdesAnnotationComment(ctx);
|
|
32
|
+
};
|
|
33
|
+
visitAt_component_expr = (ctx) => {
|
|
34
|
+
this.addRefdesAnnotationComment(ctx);
|
|
35
|
+
};
|
|
36
|
+
visitComponent_select_expr = (ctx) => {
|
|
37
|
+
this.addRefdesAnnotationComment(ctx);
|
|
38
|
+
};
|
|
39
|
+
visitAt_block_header = (ctx) => {
|
|
40
|
+
this.addRefdesAnnotationComment(ctx);
|
|
41
|
+
};
|
|
42
|
+
visitAt_block = (ctx) => {
|
|
43
|
+
this.visit(ctx.at_block_header());
|
|
44
|
+
ctx.at_block_expressions().forEach(expression => {
|
|
45
|
+
this.visit(expression);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
visitTo_component_expr = (ctx) => {
|
|
49
|
+
const allRefdes = [];
|
|
50
|
+
ctx.component_select_expr().forEach(itemCtx => {
|
|
51
|
+
const tmpRefdes = this.generateRefdesAnnotationComment(itemCtx);
|
|
52
|
+
if (tmpRefdes !== null) {
|
|
53
|
+
allRefdes.push(tmpRefdes);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (allRefdes.length > 0) {
|
|
57
|
+
const originalText = this.getOriginalText(ctx);
|
|
58
|
+
const annotation = ' #= ' + allRefdes.join(',');
|
|
59
|
+
this.modifications.set(ctx, originalText + annotation);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
visitFunction_def_expr = (ctx) => {
|
|
63
|
+
this.runExpressions(this.getExecutor(), ctx.function_expr());
|
|
64
|
+
};
|
|
65
|
+
visitFunction_return_expr = (ctx) => {
|
|
66
|
+
};
|
|
67
|
+
visitFrame_expr = (ctx) => {
|
|
68
|
+
this.visit(ctx.expressions_block());
|
|
69
|
+
};
|
|
70
|
+
visitFunction_call_expr = (ctx) => {
|
|
71
|
+
};
|
|
72
|
+
visitParameters = (ctx) => {
|
|
73
|
+
};
|
|
74
|
+
addedRefdesAnnotations = [];
|
|
75
|
+
generateRefdesAnnotationComment(ctx) {
|
|
76
|
+
if (this.componentCtxLinks.has(ctx)) {
|
|
77
|
+
const instance = this.componentCtxLinks.get(ctx);
|
|
78
|
+
const alreadyHaveRefdesAnnotation = instance.assignedRefDes !== null ?
|
|
79
|
+
(this.addedRefdesAnnotations.indexOf(instance.assignedRefDes) !== -1) : false;
|
|
80
|
+
if (!instance.hasParam('refdes')
|
|
81
|
+
&& instance.placeHolderRefDes === null
|
|
82
|
+
&& instance.assignedRefDes
|
|
83
|
+
&& !alreadyHaveRefdesAnnotation) {
|
|
84
|
+
let useRefDes = instance.assignedRefDes;
|
|
85
|
+
let isPlaceholderRefdes = false;
|
|
86
|
+
const { ctxReferences } = instance;
|
|
87
|
+
if (ctxReferences.length > 0) {
|
|
88
|
+
const firstReference = ctxReferences[0];
|
|
89
|
+
const { indexedStack: loopStack = [] } = firstReference;
|
|
90
|
+
if (loopStack.length > 0) {
|
|
91
|
+
isPlaceholderRefdes = true;
|
|
92
|
+
const parts = instance.assignedRefDes.split('_');
|
|
93
|
+
useRefDes = parts[0] + '_';
|
|
94
|
+
}
|
|
95
|
+
if (this.addedRefdesAnnotations.indexOf(instance.assignedRefDes) === -1
|
|
96
|
+
&& !isPlaceholderRefdes) {
|
|
97
|
+
this.addedRefdesAnnotations.push(instance.assignedRefDes);
|
|
98
|
+
}
|
|
99
|
+
return useRefDes;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
addRefdesAnnotationComment(ctx) {
|
|
106
|
+
const refdes = this.generateRefdesAnnotationComment(ctx);
|
|
107
|
+
if (refdes !== null) {
|
|
108
|
+
const originalText = this.getOriginalText(ctx);
|
|
109
|
+
const annotation = ' #= ' + refdes;
|
|
110
|
+
this.modifications.set(ctx, originalText + annotation);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
getOutput() {
|
|
114
|
+
return this.resultText;
|
|
115
|
+
}
|
|
116
|
+
generateModifiedText() {
|
|
117
|
+
const output = [];
|
|
118
|
+
const allTokens = this.tokenStream.getTokens();
|
|
119
|
+
const processedTokens = new Set();
|
|
120
|
+
let lastSourcePos = 0;
|
|
121
|
+
const contextTokenRanges = this.buildContextTokenRanges();
|
|
122
|
+
for (let i = 0; i < allTokens.length; i++) {
|
|
123
|
+
const token = allTokens[i];
|
|
124
|
+
if (processedTokens.has(i)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const tokenText = this.sourceText.substring(token.start, token.stop + 1);
|
|
128
|
+
this.log(i, `token: [${tokenText}], length: ${tokenText.length}, text: [${token.text}]`);
|
|
129
|
+
if (token.type === CircuitScriptParser.DEDENT
|
|
130
|
+
|| token.type === CircuitScriptParser.EOF
|
|
131
|
+
|| (token.type === CircuitScriptParser.NEWLINE && token.__skip)) {
|
|
132
|
+
this.log('--skip dedent/EOF token');
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const ctx = this.findContextForToken(token, contextTokenRanges);
|
|
136
|
+
if (ctx) {
|
|
137
|
+
const isFirstTokenInContext = token.tokenIndex === ctx.start?.tokenIndex;
|
|
138
|
+
if (isFirstTokenInContext) {
|
|
139
|
+
if (token.start > lastSourcePos) {
|
|
140
|
+
output.push(this.sourceText.substring(lastSourcePos, token.start));
|
|
141
|
+
}
|
|
142
|
+
if (this.modifications.has(ctx)) {
|
|
143
|
+
output.push(this.modifications.get(ctx));
|
|
144
|
+
this.markTokensAsProcessed(ctx, processedTokens);
|
|
145
|
+
if (ctx.stop) {
|
|
146
|
+
lastSourcePos = ctx.stop.stop + 1;
|
|
147
|
+
}
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (token.start > lastSourcePos) {
|
|
153
|
+
output.push(this.sourceText.substring(lastSourcePos, token.start));
|
|
154
|
+
}
|
|
155
|
+
if (tokenText.length > 0) {
|
|
156
|
+
output.push(tokenText);
|
|
157
|
+
}
|
|
158
|
+
processedTokens.add(i);
|
|
159
|
+
lastSourcePos = token.stop + 1;
|
|
160
|
+
}
|
|
161
|
+
if (lastSourcePos < this.sourceText.length) {
|
|
162
|
+
output.push(this.sourceText.substring(lastSourcePos));
|
|
163
|
+
}
|
|
164
|
+
return output.join('');
|
|
165
|
+
}
|
|
166
|
+
buildContextTokenRanges() {
|
|
167
|
+
const ranges = new Map();
|
|
168
|
+
for (const ctx of this.modifications.keys()) {
|
|
169
|
+
if (ctx.start && ctx.stop) {
|
|
170
|
+
ranges.set(ctx, [ctx.start.tokenIndex, ctx.stop.tokenIndex]);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return ranges;
|
|
174
|
+
}
|
|
175
|
+
findContextForToken(token, contextRanges) {
|
|
176
|
+
for (const [ctx, [start, end]] of contextRanges) {
|
|
177
|
+
if (token.tokenIndex >= start && token.tokenIndex <= end) {
|
|
178
|
+
return ctx;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
markTokensAsProcessed(ctx, processedTokens) {
|
|
184
|
+
if (!ctx.start || !ctx.stop) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
for (let i = ctx.start.tokenIndex; i <= ctx.stop.tokenIndex; i++) {
|
|
188
|
+
processedTokens.add(i);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
log(...message) {
|
|
192
|
+
if (this.debug) {
|
|
193
|
+
console.log(...message);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|