circuitscript 0.1.5 → 0.1.8
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 +127 -73
- package/dist/cjs/SemanticTokenVisitor.js +19 -13
- package/dist/cjs/antlr/CircuitScriptParser.js +711 -671
- package/dist/cjs/builtinMethods.js +29 -25
- package/dist/cjs/environment.js +118 -0
- package/dist/cjs/execute.js +53 -12
- package/dist/cjs/export.js +0 -5
- package/dist/cjs/geometry.js +1 -0
- package/dist/cjs/globals.js +11 -6
- package/dist/cjs/helpers.js +152 -127
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/layout.js +86 -44
- package/dist/cjs/main.js +31 -19
- package/dist/cjs/objects/ExecutionScope.js +33 -0
- package/dist/cjs/objects/ParamDefinition.js +15 -15
- package/dist/cjs/parser.js +27 -21
- package/dist/cjs/regenerate-tests.js +14 -10
- package/dist/cjs/render.js +3 -1
- package/dist/cjs/sizing.js +5 -58
- package/dist/cjs/utils.js +85 -30
- package/dist/cjs/validate/SymbolTable.js +96 -0
- package/dist/cjs/validate/SymbolValidatorResolveVisitor.js +14 -0
- package/dist/cjs/validate/SymbolValidatorVisitor.js +170 -0
- package/dist/cjs/validate.js +71 -44
- package/dist/cjs/visitor.js +140 -24
- package/dist/esm/{BaseVisitor.mjs → BaseVisitor.js} +98 -45
- package/dist/esm/{SemanticTokenVisitor.mjs → SemanticTokenVisitor.js} +17 -11
- package/dist/esm/antlr/{CircuitScriptParser.mjs → CircuitScriptParser.js} +711 -671
- package/dist/esm/{builtinMethods.mjs → builtinMethods.js} +20 -16
- package/dist/esm/{draw_symbols.mjs → draw_symbols.js} +7 -7
- package/dist/esm/environment.js +110 -0
- package/dist/esm/{execute.mjs → execute.js} +66 -25
- package/dist/esm/{export.mjs → export.js} +2 -7
- package/dist/esm/{geometry.mjs → geometry.js} +6 -5
- package/dist/esm/{globals.mjs → globals.js} +6 -1
- package/dist/esm/helpers.js +394 -0
- package/dist/esm/index.js +20 -0
- package/dist/esm/{layout.mjs → layout.js} +72 -53
- package/dist/esm/{lexer.mjs → lexer.js} +2 -2
- package/dist/esm/{main.mjs → main.js} +33 -21
- package/dist/esm/objects/{ClassComponent.mjs → ClassComponent.js} +5 -4
- package/dist/esm/objects/{ExecutionScope.mjs → ExecutionScope.js} +33 -0
- package/dist/esm/objects/{Frame.mjs → Frame.js} +1 -1
- package/dist/esm/objects/{ParamDefinition.mjs → ParamDefinition.js} +1 -1
- package/dist/esm/objects/{PinDefinition.mjs → PinDefinition.js} +1 -1
- package/dist/esm/parser.js +71 -0
- package/dist/esm/{regenerate-tests.mjs → regenerate-tests.js} +15 -11
- package/dist/esm/{render.mjs → render.js} +11 -9
- package/dist/esm/{sizing.mjs → sizing.js} +6 -34
- package/dist/esm/{utils.mjs → utils.js} +61 -17
- package/dist/esm/validate/SymbolTable.js +90 -0
- package/dist/esm/validate/SymbolValidatorResolveVisitor.js +10 -0
- package/dist/esm/validate/SymbolValidatorVisitor.js +163 -0
- package/dist/esm/validate.js +105 -0
- package/dist/esm/{visitor.mjs → visitor.js} +151 -35
- package/dist/fonts/Arial.ttf +0 -0
- package/dist/fonts/Inter-Bold.ttf +0 -0
- package/dist/fonts/Inter-Regular.ttf +0 -0
- package/dist/fonts/OpenSans-Regular.ttf +0 -0
- package/dist/fonts/Roboto-Regular.ttf +0 -0
- package/dist/libs/lib.cst +423 -0
- package/dist/types/BaseVisitor.d.ts +34 -21
- package/dist/types/SemanticTokenVisitor.d.ts +6 -5
- package/dist/types/antlr/CircuitScriptParser.d.ts +4 -2
- package/dist/types/builtinMethods.d.ts +3 -2
- package/dist/types/environment.d.ts +31 -0
- package/dist/types/globals.d.ts +4 -1
- package/dist/types/helpers.d.ts +12 -14
- package/dist/types/index.d.ts +5 -0
- package/dist/types/layout.d.ts +2 -2
- package/dist/types/objects/ClassComponent.d.ts +1 -0
- package/dist/types/objects/ExecutionScope.d.ts +11 -0
- package/dist/types/objects/types.d.ts +6 -1
- package/dist/types/parser.d.ts +7 -11
- package/dist/types/sizing.d.ts +0 -3
- package/dist/types/utils.d.ts +30 -6
- package/dist/types/validate/SymbolTable.d.ts +40 -0
- package/dist/types/validate/SymbolValidatorResolveVisitor.d.ts +7 -0
- package/dist/types/validate/SymbolValidatorVisitor.d.ts +32 -0
- package/dist/types/validate.d.ts +1 -1
- package/package.json +15 -14
- package/dist/cjs/SymbolValidatorVisitor.js +0 -233
- package/dist/esm/SymbolValidatorVisitor.mjs +0 -222
- package/dist/esm/helpers.mjs +0 -364
- package/dist/esm/index.mjs +0 -15
- package/dist/esm/parser.mjs +0 -64
- package/dist/esm/validate.mjs +0 -74
- package/dist/types/SymbolValidatorVisitor.d.ts +0 -61
- /package/dist/esm/antlr/{CircuitScriptLexer.mjs → CircuitScriptLexer.js} +0 -0
- /package/dist/esm/antlr/{CircuitScriptVisitor.mjs → CircuitScriptVisitor.js} +0 -0
- /package/dist/esm/{fonts.mjs → fonts.js} +0 -0
- /package/dist/esm/{logger.mjs → logger.js} +0 -0
- /package/dist/esm/objects/{Net.mjs → Net.js} +0 -0
- /package/dist/esm/objects/{PinTypes.mjs → PinTypes.js} +0 -0
- /package/dist/esm/objects/{Wire.mjs → Wire.js} +0 -0
- /package/dist/esm/objects/{types.mjs → types.js} +0 -0
- /package/dist/esm/{server.mjs → server.js} +0 -0
package/dist/cjs/visitor.js
CHANGED
|
@@ -46,9 +46,14 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
46
46
|
this.visitTo_component_expr = (ctx) => {
|
|
47
47
|
ctx.component_select_expr().forEach(item => {
|
|
48
48
|
const [component, pin] = this.visitResult(item);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
try {
|
|
50
|
+
this.getExecutor().toComponent(component, pin, {
|
|
51
|
+
addSequence: true
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
throw new utils_js_1.RuntimeExecutionError(err.message, ctx.start, ctx.stop);
|
|
56
|
+
}
|
|
52
57
|
});
|
|
53
58
|
return this.getExecutor().getCurrentPoint();
|
|
54
59
|
};
|
|
@@ -63,7 +68,10 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
63
68
|
componentPin = this.visitResult(ctxDataExprWithAssigment);
|
|
64
69
|
}
|
|
65
70
|
else {
|
|
66
|
-
|
|
71
|
+
let component = this.getScope().currentComponent;
|
|
72
|
+
if (component._pointLinkComponent) {
|
|
73
|
+
component = component._pointLinkComponent;
|
|
74
|
+
}
|
|
67
75
|
let pinId = null;
|
|
68
76
|
const ctxPinSelectExpr = ctx.pin_select_expr();
|
|
69
77
|
if (ctxPinSelectExpr) {
|
|
@@ -111,6 +119,92 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
111
119
|
return this.getExecutor().getCurrentPoint();
|
|
112
120
|
};
|
|
113
121
|
this.visitCreate_component_expr = (ctx) => {
|
|
122
|
+
const scope = this.getScope();
|
|
123
|
+
scope.setOnPropertyHandler((path, value, ctx) => {
|
|
124
|
+
if (path.length === 1) {
|
|
125
|
+
const [, keyName] = path[0];
|
|
126
|
+
switch (keyName) {
|
|
127
|
+
case 'type':
|
|
128
|
+
this.validateString(value, ctx);
|
|
129
|
+
break;
|
|
130
|
+
case 'angle':
|
|
131
|
+
case 'width':
|
|
132
|
+
case 'height':
|
|
133
|
+
this.validateNumeric(value, ctx);
|
|
134
|
+
break;
|
|
135
|
+
case 'pins':
|
|
136
|
+
if (!(value instanceof Map)) {
|
|
137
|
+
this.validateNumeric(value, ctx);
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
case 'copy':
|
|
141
|
+
if (value instanceof ParamDefinition_js_1.NumericValue) {
|
|
142
|
+
this.validateNumeric(value, ctx);
|
|
143
|
+
}
|
|
144
|
+
else if (typeof value === 'boolean') {
|
|
145
|
+
this.validateBoolean(value, ctx);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
throw new utils_js_1.RuntimeExecutionError("Invalid value for 'copy' property", ctx.start, ctx.end);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const [, keyName] = path[0];
|
|
155
|
+
if (keyName === 'arrange') {
|
|
156
|
+
const [sideKeyCtx, sideKeyName] = path[1];
|
|
157
|
+
if (globals_js_1.ValidPinSides.indexOf(sideKeyName) === -1) {
|
|
158
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx.start, sideKeyCtx.stop);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
if (path.length > 2 && path[2][0] === 'index') {
|
|
162
|
+
if (Array.isArray(value)) {
|
|
163
|
+
const goodBlank = value.length === 1 &&
|
|
164
|
+
value[0] instanceof ParamDefinition_js_1.NumericValue;
|
|
165
|
+
if (!goodBlank) {
|
|
166
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid blank specifier`, ctx.start, ctx.stop);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
if (!(value instanceof ParamDefinition_js_1.NumericValue)) {
|
|
171
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx.start, ctx.stop);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else if (keyName === 'params') {
|
|
178
|
+
const [, subKeyName] = path[1];
|
|
179
|
+
switch (subKeyName) {
|
|
180
|
+
case 'mpn':
|
|
181
|
+
case 'refdes':
|
|
182
|
+
case 'footprint':
|
|
183
|
+
this.validateString(value, ctx);
|
|
184
|
+
break;
|
|
185
|
+
case 'place':
|
|
186
|
+
this.validateBoolean(value, ctx);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else if (keyName === 'pins') {
|
|
191
|
+
if (path.length === 2) {
|
|
192
|
+
if (value.length === 2) {
|
|
193
|
+
const [pinType,] = value;
|
|
194
|
+
if (pinType instanceof types_js_1.UndeclaredReference) {
|
|
195
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx.start, ctx.end);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
scope.enterContext(ctx);
|
|
203
|
+
ctx.property_expr().forEach(item => {
|
|
204
|
+
this.visitResult(item);
|
|
205
|
+
});
|
|
206
|
+
scope.exitContext();
|
|
207
|
+
scope.popOnPropertyHandler();
|
|
114
208
|
const properties = this.getPropertyExprList(ctx.property_expr());
|
|
115
209
|
const pins = this.parseCreateComponentPins(properties.get('pins'));
|
|
116
210
|
let instanceName = this.getExecutor().getUniqueInstanceName();
|
|
@@ -145,8 +239,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
145
239
|
arrange, display, type, width, height, copy,
|
|
146
240
|
angle, followWireOrientation
|
|
147
241
|
};
|
|
148
|
-
|
|
149
|
-
|
|
242
|
+
try {
|
|
243
|
+
const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
|
|
244
|
+
this.setResult(ctx, createdComponent);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
this.throwWithContext(ctx, error.message);
|
|
248
|
+
}
|
|
150
249
|
};
|
|
151
250
|
this.visitCreate_graphic_expr = (ctx) => {
|
|
152
251
|
const ctxId = ctx.ID();
|
|
@@ -154,7 +253,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
154
253
|
if (ctxId !== null) {
|
|
155
254
|
const varName = ctxId.getText();
|
|
156
255
|
paramIds.push(varName);
|
|
157
|
-
this.
|
|
256
|
+
this.getScope().variables.set(varName, {});
|
|
158
257
|
}
|
|
159
258
|
const executor = this.getExecutor();
|
|
160
259
|
const stack = [...this.executionStack];
|
|
@@ -256,7 +355,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
256
355
|
useValueArray = [useValueArray];
|
|
257
356
|
}
|
|
258
357
|
useValueArray.forEach((value, index) => {
|
|
259
|
-
this.
|
|
358
|
+
this.getScope().variables.set(forVariableNames[index], value);
|
|
260
359
|
});
|
|
261
360
|
const commands = this.visitResult(ctx.graphic_expressions_block());
|
|
262
361
|
allCommands = allCommands.concat(commands);
|
|
@@ -315,8 +414,16 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
315
414
|
this.setResult(ctx, [keyName, expressionsBlock]);
|
|
316
415
|
};
|
|
317
416
|
this.visitProperty_expr = (ctx) => {
|
|
318
|
-
const
|
|
319
|
-
const
|
|
417
|
+
const ctxKey = ctx.property_key_expr();
|
|
418
|
+
const ctxValue = ctx.property_value_expr();
|
|
419
|
+
const scope = this.getScope();
|
|
420
|
+
this.getScope().enterContext(ctxKey);
|
|
421
|
+
this.getScope().enterContext(ctxValue);
|
|
422
|
+
const keyName = this.visitResult(ctxKey);
|
|
423
|
+
const value = this.visitResult(ctxValue);
|
|
424
|
+
scope.triggerPropertyHandler(value, ctxValue);
|
|
425
|
+
this.getScope().exitContext();
|
|
426
|
+
this.getScope().exitContext();
|
|
320
427
|
if (value instanceof types_js_1.UndeclaredReference && (value.reference.parentValue === undefined
|
|
321
428
|
&& value.reference.value === undefined)) {
|
|
322
429
|
throw value.throwMessage();
|
|
@@ -326,15 +433,21 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
326
433
|
this.setResult(ctx, map);
|
|
327
434
|
};
|
|
328
435
|
this.visitSingle_line_property = (ctx) => {
|
|
436
|
+
this.getScope().enterContext(ctx);
|
|
329
437
|
let value;
|
|
330
438
|
if (ctx.data_expr().length === 1) {
|
|
331
439
|
value = this.visitResult(ctx.data_expr(0));
|
|
332
440
|
}
|
|
333
441
|
else {
|
|
334
|
-
value = ctx.data_expr().map(item => {
|
|
335
|
-
|
|
442
|
+
value = ctx.data_expr().map((item, index) => {
|
|
443
|
+
this.getScope().enterContext(index);
|
|
444
|
+
const result = this.visitResult(item);
|
|
445
|
+
this.getScope().triggerPropertyHandler(result, item);
|
|
446
|
+
this.getScope().exitContext();
|
|
447
|
+
return result;
|
|
336
448
|
});
|
|
337
449
|
}
|
|
450
|
+
this.getScope().exitContext();
|
|
338
451
|
this.setResult(ctx, value);
|
|
339
452
|
};
|
|
340
453
|
this.visitNested_properties_inner = (ctx) => {
|
|
@@ -707,6 +820,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
707
820
|
}
|
|
708
821
|
else if (ctxDataExpr) {
|
|
709
822
|
useValue = this.visitResult(ctxDataExpr);
|
|
823
|
+
if (useValue instanceof ParamDefinition_js_1.NumericValue) {
|
|
824
|
+
useValue = useValue.toNumber();
|
|
825
|
+
}
|
|
710
826
|
}
|
|
711
827
|
if (useValue !== null) {
|
|
712
828
|
this.setResult(ctx, [direction, new helpers_js_1.UnitDimension(useValue)]);
|
|
@@ -848,7 +964,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
848
964
|
useValueArray = [useValueArray];
|
|
849
965
|
}
|
|
850
966
|
useValueArray.forEach((value, index) => {
|
|
851
|
-
this.
|
|
967
|
+
this.getScope().variables.set(forVariableNames[index], value);
|
|
852
968
|
});
|
|
853
969
|
this.visit(ctx.expressions_block());
|
|
854
970
|
keepLooping = true;
|
|
@@ -1043,32 +1159,32 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1043
1159
|
return result;
|
|
1044
1160
|
}
|
|
1045
1161
|
printNets() {
|
|
1046
|
-
this.
|
|
1162
|
+
this.getScope().printNets();
|
|
1047
1163
|
}
|
|
1048
1164
|
dumpNets() {
|
|
1049
|
-
return this.
|
|
1165
|
+
return this.getScope().dumpNets();
|
|
1050
1166
|
}
|
|
1051
1167
|
dumpUniqueNets() {
|
|
1052
|
-
const nets = this.
|
|
1168
|
+
const nets = this.getScope().getNets();
|
|
1053
1169
|
return nets.reduce((accum, [, , net]) => {
|
|
1054
1170
|
accum.push(net);
|
|
1055
1171
|
return accum;
|
|
1056
1172
|
}, []);
|
|
1057
1173
|
}
|
|
1058
1174
|
dumpVariables() {
|
|
1059
|
-
return this.
|
|
1175
|
+
return this.getScope().variables;
|
|
1060
1176
|
}
|
|
1061
1177
|
dumpInstances() {
|
|
1062
|
-
return this.
|
|
1178
|
+
return this.getScope().instances;
|
|
1063
1179
|
}
|
|
1064
1180
|
dump2() {
|
|
1065
|
-
const instances = this.
|
|
1181
|
+
const instances = this.getScope().instances;
|
|
1066
1182
|
const items = [];
|
|
1067
1183
|
for (const [instanceName, instance] of instances) {
|
|
1068
1184
|
if (instance.assignedRefDes === null) {
|
|
1069
1185
|
continue;
|
|
1070
1186
|
}
|
|
1071
|
-
const pinNets = this.resolveNets(this.
|
|
1187
|
+
const pinNets = this.resolveNets(this.getScope(), instance);
|
|
1072
1188
|
const componentItem = {
|
|
1073
1189
|
name: instanceName,
|
|
1074
1190
|
refdes: instance.assignedRefDes,
|
|
@@ -1083,9 +1199,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1083
1199
|
}
|
|
1084
1200
|
getNetList() {
|
|
1085
1201
|
const netlist = [];
|
|
1086
|
-
const instances = this.
|
|
1202
|
+
const instances = this.getScope().instances;
|
|
1087
1203
|
for (const [instanceName, instance] of instances) {
|
|
1088
|
-
const pinNets = this.resolveNets(this.
|
|
1204
|
+
const pinNets = this.resolveNets(this.getScope(), instance);
|
|
1089
1205
|
const componentItem = {
|
|
1090
1206
|
instanceName,
|
|
1091
1207
|
instance,
|
|
@@ -1116,7 +1232,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1116
1232
|
annotateComponents() {
|
|
1117
1233
|
this.log('===== annotate components =====');
|
|
1118
1234
|
const annotater = new ComponentAnnotater();
|
|
1119
|
-
const instances = this.
|
|
1235
|
+
const instances = this.getScope().instances;
|
|
1120
1236
|
const toAnnotate = [];
|
|
1121
1237
|
for (const [, instance] of instances) {
|
|
1122
1238
|
if (instance.typeProp === globals_js_1.ComponentTypes.net
|
|
@@ -1153,7 +1269,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1153
1269
|
this.log('');
|
|
1154
1270
|
}
|
|
1155
1271
|
applySheetFrameComponent() {
|
|
1156
|
-
const baseScope = this.
|
|
1272
|
+
const baseScope = this.getScope();
|
|
1157
1273
|
const document = baseScope.variables.get(globals_js_1.GlobalDocumentName);
|
|
1158
1274
|
let frameComponent = null;
|
|
1159
1275
|
if (document && document[Frame_js_1.FrameParamKeys.SheetType]) {
|
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
1
|
import { Big } from 'big.js';
|
|
4
|
-
import { ExpressionContext } from "./antlr/CircuitScriptParser";
|
|
5
|
-
import { CircuitScriptVisitor } from "./antlr/CircuitScriptVisitor";
|
|
6
|
-
import { ExecutionContext } from "./execute";
|
|
7
|
-
import { Logger } from "./logger";
|
|
8
|
-
import { ClassComponent } from "./objects/ClassComponent";
|
|
9
|
-
import { NumberOperator, NumericValue, PercentageValue } from "./objects/ParamDefinition";
|
|
10
|
-
import { PinTypes } from "./objects/PinTypes";
|
|
11
|
-
import { Direction, UndeclaredReference } from "./objects/types";
|
|
12
|
-
import { DoubleDelimiter1, GlobalDocumentName, ReferenceTypes } from './globals';
|
|
13
|
-
import { linkBuiltInMethods } from './builtinMethods';
|
|
14
|
-
import { resolveToNumericValue, throwWithContext } from './utils';
|
|
15
|
-
import { SequenceAction } from './objects/ExecutionScope';
|
|
2
|
+
import { ExpressionContext } from "./antlr/CircuitScriptParser.js";
|
|
3
|
+
import { CircuitScriptVisitor } from "./antlr/CircuitScriptVisitor.js";
|
|
4
|
+
import { ExecutionContext } from "./execute.js";
|
|
5
|
+
import { Logger } from "./logger.js";
|
|
6
|
+
import { ClassComponent } from "./objects/ClassComponent.js";
|
|
7
|
+
import { NumberOperator, NumericValue, PercentageValue } from "./objects/ParamDefinition.js";
|
|
8
|
+
import { PinTypes } from "./objects/PinTypes.js";
|
|
9
|
+
import { Direction, UndeclaredReference } from "./objects/types.js";
|
|
10
|
+
import { DoubleDelimiter1, GlobalDocumentName, ReferenceTypes } from './globals.js';
|
|
11
|
+
import { linkBuiltInMethods } from './builtinMethods.js';
|
|
12
|
+
import { resolveToNumericValue, RuntimeExecutionError, throwWithContext } from './utils.js';
|
|
13
|
+
import { SequenceAction } from './objects/ExecutionScope.js';
|
|
16
14
|
export class BaseVisitor extends CircuitScriptVisitor {
|
|
17
15
|
indentLevel = 0;
|
|
18
16
|
startingContext;
|
|
19
17
|
executionStack;
|
|
20
18
|
silent = false;
|
|
21
19
|
logger;
|
|
22
|
-
currentDirectory;
|
|
23
|
-
defaultLibsPath;
|
|
24
20
|
printStream = [];
|
|
25
21
|
printToConsole = true;
|
|
26
22
|
acceptedDirections = [Direction.Up, Direction.Down,
|
|
@@ -34,14 +30,17 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
34
30
|
PinTypes.IO,
|
|
35
31
|
PinTypes.Power,
|
|
36
32
|
];
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
onErrorHandler = null;
|
|
34
|
+
environment;
|
|
35
|
+
importedFiles = [];
|
|
36
|
+
onImportFile = async (visitor, filePath, fileData, onErrorHandler) => {
|
|
39
37
|
throw "Import file not implemented";
|
|
40
38
|
};
|
|
41
|
-
constructor(silent = false, onErrorHandler = null,
|
|
39
|
+
constructor(silent = false, onErrorHandler = null, environment) {
|
|
42
40
|
super();
|
|
43
41
|
this.logger = new Logger();
|
|
44
|
-
this.
|
|
42
|
+
this.onErrorHandler = onErrorHandler;
|
|
43
|
+
this.environment = environment;
|
|
45
44
|
this.startingContext = new ExecutionContext(DoubleDelimiter1, `${DoubleDelimiter1}.`, '/', 0, 0, silent, this.logger, null);
|
|
46
45
|
const scope = this.startingContext.scope;
|
|
47
46
|
scope.sequence.push([
|
|
@@ -55,12 +54,16 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
55
54
|
this.startingContext.resolveComponentPinNet =
|
|
56
55
|
this.createComponentPinNetResolver(this.executionStack);
|
|
57
56
|
this.silent = silent;
|
|
58
|
-
this.currentDirectory = currentDirectory;
|
|
59
|
-
this.defaultLibsPath = defaultLibsPath;
|
|
60
57
|
}
|
|
61
58
|
getExecutor() {
|
|
62
59
|
return this.executionStack[this.executionStack.length - 1];
|
|
63
60
|
}
|
|
61
|
+
getScope() {
|
|
62
|
+
return this.getExecutor().scope;
|
|
63
|
+
}
|
|
64
|
+
getRootExecutor() {
|
|
65
|
+
return this.executionStack[0];
|
|
66
|
+
}
|
|
64
67
|
setupBuiltInFunctions(context) {
|
|
65
68
|
linkBuiltInMethods(context, this);
|
|
66
69
|
}
|
|
@@ -109,11 +112,21 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
109
112
|
log2(message) {
|
|
110
113
|
this.getExecutor().log(message);
|
|
111
114
|
}
|
|
112
|
-
|
|
115
|
+
async visitAsync(ctx) {
|
|
116
|
+
const result = await ctx.accept(this);
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
visitScript = async (ctx) => {
|
|
113
120
|
this.log('===', 'start', '===');
|
|
114
|
-
const
|
|
121
|
+
const imports = ctx.import_expr();
|
|
122
|
+
for (let i = 0; i < imports.length; i++) {
|
|
123
|
+
const ctxImport = imports[i];
|
|
124
|
+
const ID = ctxImport.ID().toString();
|
|
125
|
+
await this.handleImportFile(ID, true, ctxImport);
|
|
126
|
+
}
|
|
127
|
+
const result = this.runExpressions(this.getExecutor(), ctx.expression());
|
|
128
|
+
this.setResult(ctx, result);
|
|
115
129
|
this.log('===', 'end', '===');
|
|
116
|
-
return result;
|
|
117
130
|
};
|
|
118
131
|
visitAssignment_expr = (ctx) => {
|
|
119
132
|
const reference = this.getReference(ctx.atom_expr());
|
|
@@ -385,10 +398,10 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
385
398
|
const tmpCtx = defaultValuesProvided[index - boundary];
|
|
386
399
|
this.visit(tmpCtx);
|
|
387
400
|
const defaultValue = this.getResult(tmpCtx);
|
|
388
|
-
return [idText, defaultValue];
|
|
401
|
+
return [idText, tmpCtx.start, defaultValue];
|
|
389
402
|
}
|
|
390
403
|
else {
|
|
391
|
-
return [idText];
|
|
404
|
+
return [idText, id.getSymbol()];
|
|
392
405
|
}
|
|
393
406
|
});
|
|
394
407
|
this.setResult(ctx, result);
|
|
@@ -410,10 +423,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
410
423
|
this.setResult(ctx, returnList);
|
|
411
424
|
};
|
|
412
425
|
visitImport_expr = (ctx) => {
|
|
413
|
-
|
|
414
|
-
this.log('import', ID);
|
|
415
|
-
this.handleImportFile(ID, true, ctx);
|
|
416
|
-
this.log('done import', ID);
|
|
426
|
+
throw new RuntimeExecutionError("Cannot parse imports here", ctx.start, ctx.stop);
|
|
417
427
|
};
|
|
418
428
|
visitFunction_return_expr = (ctx) => {
|
|
419
429
|
const executor = this.getExecutor();
|
|
@@ -463,15 +473,24 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
463
473
|
this.visit(ctx);
|
|
464
474
|
return this.getResult(ctx);
|
|
465
475
|
}
|
|
466
|
-
handleImportFile(name, throwErrors = true, ctx = null) {
|
|
476
|
+
async handleImportFile(name, throwErrors = true, ctx = null) {
|
|
477
|
+
name = name.trim();
|
|
478
|
+
const importAlready = this.importedFiles.find(item => {
|
|
479
|
+
return item.id === name;
|
|
480
|
+
});
|
|
481
|
+
if (importAlready) {
|
|
482
|
+
return importAlready;
|
|
483
|
+
}
|
|
467
484
|
let hasError = false;
|
|
468
485
|
let hasParseError = false;
|
|
469
486
|
let pathExists = false;
|
|
470
|
-
const tmpFilePath =
|
|
487
|
+
const tmpFilePath = this.environment.getRelativeToModule(name + ".cst");
|
|
471
488
|
this.log('importing path:', tmpFilePath);
|
|
472
489
|
let fileData = null;
|
|
490
|
+
let filePathUsed = null;
|
|
473
491
|
try {
|
|
474
|
-
|
|
492
|
+
filePathUsed = tmpFilePath;
|
|
493
|
+
fileData = await this.environment.readFile(tmpFilePath, { encoding: 'utf8' });
|
|
475
494
|
pathExists = true;
|
|
476
495
|
}
|
|
477
496
|
catch (err) {
|
|
@@ -479,8 +498,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
479
498
|
}
|
|
480
499
|
if (!pathExists) {
|
|
481
500
|
try {
|
|
482
|
-
const tmpFilePath2 =
|
|
483
|
-
|
|
501
|
+
const tmpFilePath2 = this.environment.getRelativeToDefaultLibs(name + ".cst");
|
|
502
|
+
filePathUsed = tmpFilePath2;
|
|
503
|
+
fileData = await this.environment.readFile(tmpFilePath2, { encoding: 'utf8' });
|
|
484
504
|
pathExists = true;
|
|
485
505
|
}
|
|
486
506
|
catch (err) {
|
|
@@ -490,31 +510,39 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
490
510
|
try {
|
|
491
511
|
if (pathExists) {
|
|
492
512
|
this.log('done reading imported file data');
|
|
493
|
-
const importResult = this.onImportFile(this, fileData, this.
|
|
513
|
+
const importResult = await this.onImportFile(this, filePathUsed, fileData, this.onErrorHandler);
|
|
494
514
|
hasError = importResult.hasError;
|
|
495
515
|
hasParseError = importResult.hasParseError;
|
|
496
516
|
}
|
|
497
517
|
}
|
|
498
518
|
catch (err) {
|
|
499
|
-
|
|
519
|
+
if (ctx != null) {
|
|
520
|
+
throw new RuntimeExecutionError("An error occurred while importing file", ctx.start, ctx.stop);
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
this.log('An error occurred while importing file:', err.message);
|
|
524
|
+
}
|
|
500
525
|
}
|
|
501
526
|
let errorMessage = null;
|
|
502
527
|
if (throwErrors && (hasError || hasParseError || !pathExists)) {
|
|
503
528
|
if (!pathExists) {
|
|
504
|
-
errorMessage = `File does not exist: ${name}`;
|
|
529
|
+
errorMessage = `File does not exist: ${name} (${filePathUsed})`;
|
|
505
530
|
}
|
|
506
531
|
else {
|
|
507
532
|
errorMessage = `Failed to import: ${name}`;
|
|
508
533
|
}
|
|
509
534
|
}
|
|
510
535
|
if (errorMessage !== null && ctx) {
|
|
511
|
-
|
|
536
|
+
throw new RuntimeExecutionError(errorMessage, ctx.start, ctx.end);
|
|
512
537
|
}
|
|
513
|
-
|
|
538
|
+
const newImportedFile = {
|
|
539
|
+
id: name.trim(),
|
|
514
540
|
hasError,
|
|
515
541
|
hasParseError,
|
|
516
542
|
pathExists,
|
|
517
543
|
};
|
|
544
|
+
this.importedFiles.push(newImportedFile);
|
|
545
|
+
return newImportedFile;
|
|
518
546
|
}
|
|
519
547
|
visitRoundedBracketsExpr = (ctx) => {
|
|
520
548
|
const ctxDataExpr = ctx.data_expr();
|
|
@@ -544,9 +572,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
544
572
|
executor.scope.variables.set(variableName, tmpPassedInArgs[2]);
|
|
545
573
|
}
|
|
546
574
|
}
|
|
547
|
-
else if (tmpFuncArg.length ===
|
|
575
|
+
else if (tmpFuncArg.length === 3) {
|
|
548
576
|
const variableName = tmpFuncArg[0];
|
|
549
|
-
const defaultValue = tmpFuncArg[
|
|
577
|
+
const defaultValue = tmpFuncArg[2];
|
|
550
578
|
executor.log('set variable in scope, var name: ', variableName);
|
|
551
579
|
executor.scope.variables.set(variableName, defaultValue);
|
|
552
580
|
}
|
|
@@ -617,7 +645,32 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
617
645
|
prepareStringValue(value) {
|
|
618
646
|
return value.slice(1, value.length - 1);
|
|
619
647
|
}
|
|
620
|
-
throwWithContext(context,
|
|
621
|
-
throwWithContext(context,
|
|
648
|
+
throwWithContext(context, messageOrError) {
|
|
649
|
+
throwWithContext(context, messageOrError);
|
|
650
|
+
}
|
|
651
|
+
validateType(value, context, validateFunction, expectedType) {
|
|
652
|
+
if (value === undefined) {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
const result = validateFunction(value);
|
|
656
|
+
if (!result) {
|
|
657
|
+
throw new RuntimeExecutionError(`Invalid ${expectedType}`, context.start, context.stop);
|
|
658
|
+
}
|
|
659
|
+
return result;
|
|
660
|
+
}
|
|
661
|
+
validateString(value, context) {
|
|
662
|
+
this.validateType(value, context, (val) => {
|
|
663
|
+
return typeof val === 'string';
|
|
664
|
+
}, 'string');
|
|
665
|
+
}
|
|
666
|
+
validateBoolean(value, context) {
|
|
667
|
+
this.validateType(value, context, (val) => {
|
|
668
|
+
return typeof val === 'boolean';
|
|
669
|
+
}, 'boolean');
|
|
670
|
+
}
|
|
671
|
+
validateNumeric(value, context) {
|
|
672
|
+
this.validateType(value, context, (val) => {
|
|
673
|
+
return (val instanceof NumericValue);
|
|
674
|
+
}, 'numeric value');
|
|
622
675
|
}
|
|
623
676
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { Assignment_exprContext } from "./antlr/CircuitScriptParser";
|
|
2
|
-
import { BaseVisitor } from "./BaseVisitor";
|
|
1
|
+
import { Assignment_exprContext } from "./antlr/CircuitScriptParser.js";
|
|
2
|
+
import { BaseVisitor } from "./BaseVisitor.js";
|
|
3
|
+
import { buildInMethodNamesList } from "./builtinMethods.js";
|
|
4
|
+
import { SymbolValidatorContext } from "./globals.js";
|
|
3
5
|
export class SemanticTokensVisitor extends BaseVisitor {
|
|
4
6
|
parsedTokens = [];
|
|
5
7
|
lexer;
|
|
6
8
|
script;
|
|
7
9
|
semanticTokens = new Map();
|
|
8
|
-
constructor(silent = false, onErrorHandler = null,
|
|
9
|
-
super(silent, onErrorHandler,
|
|
10
|
+
constructor(silent = false, onErrorHandler = null, environment, lexer, script) {
|
|
11
|
+
super(silent, onErrorHandler, environment);
|
|
10
12
|
this.lexer = lexer;
|
|
11
13
|
this.script = script;
|
|
12
14
|
}
|
|
@@ -17,7 +19,11 @@ export class SemanticTokensVisitor extends BaseVisitor {
|
|
|
17
19
|
});
|
|
18
20
|
};
|
|
19
21
|
visitFunction_call_expr = (ctx) => {
|
|
20
|
-
|
|
22
|
+
const modifiers = [];
|
|
23
|
+
if (buildInMethodNamesList.indexOf(ctx.ID().getText()) !== -1) {
|
|
24
|
+
modifiers.push('defaultLibrary');
|
|
25
|
+
}
|
|
26
|
+
this.addSemanticToken(ctx.ID(), modifiers, 'function');
|
|
21
27
|
};
|
|
22
28
|
visitFunction_def_expr = (ctx) => {
|
|
23
29
|
const functionName = ctx.ID().getText();
|
|
@@ -26,7 +32,7 @@ export class SemanticTokensVisitor extends BaseVisitor {
|
|
|
26
32
|
if (ctxFunctionArgsExpr) {
|
|
27
33
|
this.visit(ctxFunctionArgsExpr);
|
|
28
34
|
}
|
|
29
|
-
const executionContextName = functionName +
|
|
35
|
+
const executionContextName = functionName + SymbolValidatorContext;
|
|
30
36
|
const newExecutor = this.enterNewChildContext(this.executionStack, this.getExecutor(), executionContextName, { netNamespace: "" }, [], []);
|
|
31
37
|
this.runExpressions(newExecutor, ctx.function_expr());
|
|
32
38
|
this.executionStack.pop();
|
|
@@ -39,9 +45,8 @@ export class SemanticTokensVisitor extends BaseVisitor {
|
|
|
39
45
|
};
|
|
40
46
|
visitCreate_graphic_expr = (ctx) => {
|
|
41
47
|
this.addSemanticToken(ctx.Create(), ['defaultLibrary'], 'function');
|
|
42
|
-
ctx.
|
|
43
|
-
|
|
44
|
-
});
|
|
48
|
+
const graphicsExpressionsCtx = ctx.graphic_expressions_block();
|
|
49
|
+
this.visitResult(graphicsExpressionsCtx);
|
|
45
50
|
};
|
|
46
51
|
visitProperty_key_expr = (ctx) => {
|
|
47
52
|
let useValue = null;
|
|
@@ -61,7 +66,7 @@ export class SemanticTokensVisitor extends BaseVisitor {
|
|
|
61
66
|
this.addSemanticToken(useValue, [], 'property');
|
|
62
67
|
}
|
|
63
68
|
};
|
|
64
|
-
|
|
69
|
+
visitGraphicCommandExpr = (ctx) => {
|
|
65
70
|
let useValue = null;
|
|
66
71
|
const ctxId = ctx.ID();
|
|
67
72
|
const ctxPin = ctx.Pin();
|
|
@@ -179,7 +184,7 @@ const languageKeywords = [
|
|
|
179
184
|
'break', 'branch', 'create', 'component',
|
|
180
185
|
'graphic', 'wire', 'pin', 'add', 'at', 'to',
|
|
181
186
|
'point', 'join', 'parallel', 'return', 'def', 'import',
|
|
182
|
-
'true', 'false', 'nc', 'frame',
|
|
187
|
+
'true', 'false', 'nc', 'sheet', 'frame', 'if', 'for',
|
|
183
188
|
];
|
|
184
189
|
const operatorKeywords = [
|
|
185
190
|
'at', 'to', 'wire', 'add', 'frame', 'join', 'parallel', 'point'
|
|
@@ -203,6 +208,7 @@ function resolveTokenType(tokenType) {
|
|
|
203
208
|
case 'ID':
|
|
204
209
|
return 'variable';
|
|
205
210
|
case 'Define':
|
|
211
|
+
case 'BOOLEAN_VALUE':
|
|
206
212
|
return 'keyword';
|
|
207
213
|
case 'COMMENT':
|
|
208
214
|
return 'comment';
|