circuitscript 0.1.4 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/cjs/BaseVisitor.js +149 -80
  2. package/dist/cjs/SemanticTokenVisitor.js +19 -13
  3. package/dist/cjs/antlr/CircuitScriptParser.js +711 -671
  4. package/dist/cjs/builtinMethods.js +48 -22
  5. package/dist/cjs/draw_symbols.js +4 -1
  6. package/dist/cjs/environment.js +118 -0
  7. package/dist/cjs/execute.js +98 -46
  8. package/dist/cjs/geometry.js +1 -0
  9. package/dist/cjs/globals.js +14 -7
  10. package/dist/cjs/helpers.js +142 -150
  11. package/dist/cjs/index.js +5 -0
  12. package/dist/cjs/layout.js +39 -14
  13. package/dist/cjs/main.js +34 -21
  14. package/dist/cjs/objects/ClassComponent.js +4 -1
  15. package/dist/cjs/objects/ExecutionScope.js +40 -2
  16. package/dist/cjs/objects/ParamDefinition.js +15 -15
  17. package/dist/cjs/parser.js +27 -21
  18. package/dist/cjs/regenerate-tests.js +9 -6
  19. package/dist/cjs/render.js +3 -1
  20. package/dist/cjs/sizing.js +10 -60
  21. package/dist/cjs/utils.js +148 -17
  22. package/dist/cjs/validate/SymbolTable.js +96 -0
  23. package/dist/cjs/validate/SymbolValidatorResolveVisitor.js +14 -0
  24. package/dist/cjs/validate/SymbolValidatorVisitor.js +170 -0
  25. package/dist/cjs/validate.js +52 -44
  26. package/dist/cjs/visitor.js +149 -31
  27. package/dist/esm/{BaseVisitor.mjs → BaseVisitor.js} +124 -56
  28. package/dist/esm/{SemanticTokenVisitor.mjs → SemanticTokenVisitor.js} +17 -11
  29. package/dist/esm/antlr/{CircuitScriptParser.mjs → CircuitScriptParser.js} +711 -671
  30. package/dist/esm/{builtinMethods.mjs → builtinMethods.js} +40 -14
  31. package/dist/esm/{draw_symbols.mjs → draw_symbols.js} +11 -8
  32. package/dist/esm/environment.js +110 -0
  33. package/dist/esm/{execute.mjs → execute.js} +111 -58
  34. package/dist/esm/{export.mjs → export.js} +2 -2
  35. package/dist/esm/{geometry.mjs → geometry.js} +6 -5
  36. package/dist/esm/{globals.mjs → globals.js} +9 -2
  37. package/dist/esm/helpers.js +377 -0
  38. package/dist/esm/index.js +20 -0
  39. package/dist/esm/{layout.mjs → layout.js} +44 -22
  40. package/dist/esm/{lexer.mjs → lexer.js} +2 -2
  41. package/dist/esm/{main.mjs → main.js} +36 -23
  42. package/dist/esm/objects/{ClassComponent.mjs → ClassComponent.js} +9 -5
  43. package/dist/esm/objects/{ExecutionScope.mjs → ExecutionScope.js} +40 -2
  44. package/dist/esm/objects/{Frame.mjs → Frame.js} +1 -1
  45. package/dist/esm/objects/{ParamDefinition.mjs → ParamDefinition.js} +1 -1
  46. package/dist/esm/objects/{PinDefinition.mjs → PinDefinition.js} +1 -1
  47. package/dist/esm/parser.js +71 -0
  48. package/dist/esm/{regenerate-tests.mjs → regenerate-tests.js} +10 -7
  49. package/dist/esm/{render.mjs → render.js} +11 -9
  50. package/dist/esm/{sizing.mjs → sizing.js} +11 -36
  51. package/dist/esm/utils.js +286 -0
  52. package/dist/esm/validate/SymbolTable.js +90 -0
  53. package/dist/esm/validate/SymbolValidatorResolveVisitor.js +10 -0
  54. package/dist/esm/validate/SymbolValidatorVisitor.js +163 -0
  55. package/dist/esm/validate.js +86 -0
  56. package/dist/esm/{visitor.mjs → visitor.js} +160 -42
  57. package/dist/fonts/Arial.ttf +0 -0
  58. package/dist/fonts/Inter-Bold.ttf +0 -0
  59. package/dist/fonts/Inter-Regular.ttf +0 -0
  60. package/dist/fonts/OpenSans-Regular.ttf +0 -0
  61. package/dist/fonts/Roboto-Regular.ttf +0 -0
  62. package/dist/libs/lib.cst +423 -0
  63. package/dist/types/BaseVisitor.d.ts +36 -22
  64. package/dist/types/SemanticTokenVisitor.d.ts +6 -5
  65. package/dist/types/antlr/CircuitScriptParser.d.ts +4 -2
  66. package/dist/types/builtinMethods.d.ts +3 -2
  67. package/dist/types/draw_symbols.d.ts +2 -6
  68. package/dist/types/environment.d.ts +31 -0
  69. package/dist/types/execute.d.ts +2 -3
  70. package/dist/types/globals.d.ts +7 -2
  71. package/dist/types/helpers.d.ts +12 -14
  72. package/dist/types/index.d.ts +5 -0
  73. package/dist/types/objects/ClassComponent.d.ts +2 -3
  74. package/dist/types/objects/ExecutionScope.d.ts +20 -6
  75. package/dist/types/objects/types.d.ts +6 -1
  76. package/dist/types/parser.d.ts +7 -11
  77. package/dist/types/sizing.d.ts +0 -3
  78. package/dist/types/utils.d.ts +33 -4
  79. package/dist/types/validate/SymbolTable.d.ts +40 -0
  80. package/dist/types/validate/SymbolValidatorResolveVisitor.d.ts +7 -0
  81. package/dist/types/validate/SymbolValidatorVisitor.d.ts +32 -0
  82. package/dist/types/validate.d.ts +1 -1
  83. package/libs/lib.cst +12 -22
  84. package/package.json +14 -13
  85. package/dist/cjs/SymbolValidatorVisitor.js +0 -233
  86. package/dist/esm/SymbolValidatorVisitor.mjs +0 -222
  87. package/dist/esm/helpers.mjs +0 -380
  88. package/dist/esm/index.mjs +0 -15
  89. package/dist/esm/parser.mjs +0 -64
  90. package/dist/esm/utils.mjs +0 -169
  91. package/dist/esm/validate.mjs +0 -74
  92. package/dist/types/SymbolValidatorVisitor.d.ts +0 -61
  93. package/dist/types/layout.d.ts +0 -148
  94. /package/dist/esm/antlr/{CircuitScriptLexer.mjs → CircuitScriptLexer.js} +0 -0
  95. /package/dist/esm/antlr/{CircuitScriptVisitor.mjs → CircuitScriptVisitor.js} +0 -0
  96. /package/dist/esm/{fonts.mjs → fonts.js} +0 -0
  97. /package/dist/esm/{logger.mjs → logger.js} +0 -0
  98. /package/dist/esm/objects/{Net.mjs → Net.js} +0 -0
  99. /package/dist/esm/objects/{PinTypes.mjs → PinTypes.js} +0 -0
  100. /package/dist/esm/objects/{Wire.mjs → Wire.js} +0 -0
  101. /package/dist/esm/objects/{types.mjs → types.js} +0 -0
  102. /package/dist/esm/{server.mjs → server.js} +0 -0
@@ -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
- this.getExecutor().toComponent(component, pin, {
50
- addSequence: true
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
- const component = this.getExecutor().scope.currentComponent;
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();
@@ -123,7 +217,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
123
217
  if (paramValue instanceof ParamDefinition_js_1.NumericValue) {
124
218
  appendValue = paramValue.value;
125
219
  }
126
- instanceName += '_' + appendValue;
220
+ instanceName += `${globals_js_1.Delimiter1}${appendValue}`;
127
221
  }
128
222
  const arrange = properties.has('arrange') ?
129
223
  properties.get('arrange') : null;
@@ -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
- const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
149
- this.setResult(ctx, createdComponent);
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.getExecutor().scope.variables.set(varName, {});
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.getExecutor().scope.variables.set(forVariableNames[index], value);
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 keyName = this.visitResult(ctx.property_key_expr());
319
- const value = this.visitResult(ctx.property_value_expr());
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
- return this.visitResult(item);
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) => {
@@ -614,11 +727,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
614
727
  const executionStack = this.executionStack;
615
728
  const functionCounter = { counter: 0 };
616
729
  const resolveNet = this.createNetResolver(this.executionStack);
730
+ const resolveComponentPinNet = this.createComponentPinNetResolver(this.executionStack);
617
731
  const __runFunc = (passedInParameters, options) => {
618
- const executionContextName = functionName + '_' + functionCounter['counter'];
732
+ const executionContextName = `${functionName}-${functionCounter['counter']}`;
619
733
  const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, options, funcDefinedParameters, passedInParameters);
620
734
  functionCounter['counter'] += 1;
621
735
  newExecutor.resolveNet = resolveNet;
736
+ newExecutor.resolveComponentPinNet = resolveComponentPinNet;
622
737
  const returnValue = this.runExpressions(newExecutor, ctx.function_expr());
623
738
  const lastExecution = executionStack.pop();
624
739
  const nextLastExecution = executionStack[executionStack.length - 1];
@@ -705,6 +820,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
705
820
  }
706
821
  else if (ctxDataExpr) {
707
822
  useValue = this.visitResult(ctxDataExpr);
823
+ if (useValue instanceof ParamDefinition_js_1.NumericValue) {
824
+ useValue = useValue.toNumber();
825
+ }
708
826
  }
709
827
  if (useValue !== null) {
710
828
  this.setResult(ctx, [direction, new helpers_js_1.UnitDimension(useValue)]);
@@ -846,7 +964,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
846
964
  useValueArray = [useValueArray];
847
965
  }
848
966
  useValueArray.forEach((value, index) => {
849
- this.getExecutor().scope.variables.set(forVariableNames[index], value);
967
+ this.getScope().variables.set(forVariableNames[index], value);
850
968
  });
851
969
  this.visit(ctx.expressions_block());
852
970
  keepLooping = true;
@@ -882,15 +1000,15 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
882
1000
  expandModuleContains(component, netNamespace) {
883
1001
  this.getExecutor().log('expanding module `contains`');
884
1002
  const executionStack = this.executionStack;
885
- const resolveNet = this.createNetResolver(executionStack);
886
1003
  const executor = this.getExecutor();
887
- const executionContextName = executor.namespace + "_"
1004
+ const executionContextName = executor.namespace + globals_js_1.Delimiter1
888
1005
  + component.instanceName
889
- + '_' + component.moduleCounter;
890
- const tmpNamespace = this.getNetNamespace(netNamespace, "+/" + component.instanceName + "_" + component.moduleCounter);
1006
+ + globals_js_1.Delimiter1 + component.moduleCounter;
1007
+ const tmpNamespace = this.getNetNamespace(netNamespace, "+/" + component.instanceName + globals_js_1.Delimiter1 + component.moduleCounter);
891
1008
  const newExecutor = this.enterNewChildContext(executionStack, executor, executionContextName, { netNamespace: tmpNamespace }, [], []);
892
1009
  component.moduleCounter += 1;
893
- newExecutor.resolveNet = resolveNet;
1010
+ newExecutor.resolveNet = this.createNetResolver(executionStack);
1011
+ newExecutor.resolveComponentPinNet = this.createComponentPinNetResolver(executionStack);
894
1012
  this.visit(component.moduleContainsExpressions);
895
1013
  const executionContext = executionStack.pop();
896
1014
  component.moduleExecutionContext = executionContext;
@@ -1041,32 +1159,32 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1041
1159
  return result;
1042
1160
  }
1043
1161
  printNets() {
1044
- this.getExecutor().scope.printNets();
1162
+ this.getScope().printNets();
1045
1163
  }
1046
1164
  dumpNets() {
1047
- return this.getExecutor().scope.dumpNets();
1165
+ return this.getScope().dumpNets();
1048
1166
  }
1049
1167
  dumpUniqueNets() {
1050
- const nets = this.getExecutor().scope.getNets();
1168
+ const nets = this.getScope().getNets();
1051
1169
  return nets.reduce((accum, [, , net]) => {
1052
1170
  accum.push(net);
1053
1171
  return accum;
1054
1172
  }, []);
1055
1173
  }
1056
1174
  dumpVariables() {
1057
- return this.getExecutor().scope.variables;
1175
+ return this.getScope().variables;
1058
1176
  }
1059
1177
  dumpInstances() {
1060
- return this.getExecutor().scope.instances;
1178
+ return this.getScope().instances;
1061
1179
  }
1062
1180
  dump2() {
1063
- const instances = this.getExecutor().scope.instances;
1181
+ const instances = this.getScope().instances;
1064
1182
  const items = [];
1065
1183
  for (const [instanceName, instance] of instances) {
1066
1184
  if (instance.assignedRefDes === null) {
1067
1185
  continue;
1068
1186
  }
1069
- const pinNets = this.resolveNets(this.getExecutor().scope, instance);
1187
+ const pinNets = this.resolveNets(this.getScope(), instance);
1070
1188
  const componentItem = {
1071
1189
  name: instanceName,
1072
1190
  refdes: instance.assignedRefDes,
@@ -1081,9 +1199,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1081
1199
  }
1082
1200
  getNetList() {
1083
1201
  const netlist = [];
1084
- const instances = this.getExecutor().scope.instances;
1202
+ const instances = this.getScope().instances;
1085
1203
  for (const [instanceName, instance] of instances) {
1086
- const pinNets = this.resolveNets(this.getExecutor().scope, instance);
1204
+ const pinNets = this.resolveNets(this.getScope(), instance);
1087
1205
  const componentItem = {
1088
1206
  instanceName,
1089
1207
  instance,
@@ -1114,7 +1232,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1114
1232
  annotateComponents() {
1115
1233
  this.log('===== annotate components =====');
1116
1234
  const annotater = new ComponentAnnotater();
1117
- const instances = this.getExecutor().scope.instances;
1235
+ const instances = this.getScope().instances;
1118
1236
  const toAnnotate = [];
1119
1237
  for (const [, instance] of instances) {
1120
1238
  if (instance.typeProp === globals_js_1.ComponentTypes.net
@@ -1151,7 +1269,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1151
1269
  this.log('');
1152
1270
  }
1153
1271
  applySheetFrameComponent() {
1154
- const baseScope = this.getExecutor().scope;
1272
+ const baseScope = this.getScope();
1155
1273
  const document = baseScope.variables.get(globals_js_1.GlobalDocumentName);
1156
1274
  let frameComponent = null;
1157
1275
  if (document && document[Frame_js_1.FrameParamKeys.SheetType]) {
@@ -1,25 +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 { GlobalDocumentName, ReferenceTypes } from './globals';
13
- import { linkBuiltInMethods } from './builtinMethods';
14
- import { resolveToNumericValue, throwWithContext } from './utils';
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';
15
14
  export class BaseVisitor extends CircuitScriptVisitor {
16
15
  indentLevel = 0;
17
16
  startingContext;
18
17
  executionStack;
19
18
  silent = false;
20
19
  logger;
21
- currentDirectory;
22
- defaultLibsPath;
23
20
  printStream = [];
24
21
  printToConsole = true;
25
22
  acceptedDirections = [Direction.Up, Direction.Down,
@@ -33,28 +30,41 @@ export class BaseVisitor extends CircuitScriptVisitor {
33
30
  PinTypes.IO,
34
31
  PinTypes.Power,
35
32
  ];
36
- onErrorCallbackHandler = null;
37
- onImportFile = (visitor, filePath) => {
33
+ onErrorHandler = null;
34
+ environment;
35
+ importedFiles = [];
36
+ onImportFile = async (visitor, filePath, fileData, onErrorHandler) => {
38
37
  throw "Import file not implemented";
39
38
  };
40
- constructor(silent = false, onErrorHandler = null, currentDirectory, defaultLibsPath) {
39
+ constructor(silent = false, onErrorHandler = null, environment) {
41
40
  super();
42
41
  this.logger = new Logger();
43
- this.onErrorCallbackHandler = onErrorHandler;
44
- this.startingContext = new ExecutionContext('__', '__.', '/', 0, 0, silent, this.logger, null);
45
- this.startingContext.scope.variables.set(GlobalDocumentName, {});
46
- this.setupPrintFunction(this.startingContext);
42
+ this.onErrorHandler = onErrorHandler;
43
+ this.environment = environment;
44
+ this.startingContext = new ExecutionContext(DoubleDelimiter1, `${DoubleDelimiter1}.`, '/', 0, 0, silent, this.logger, null);
45
+ const scope = this.startingContext.scope;
46
+ scope.sequence.push([
47
+ SequenceAction.At, scope.componentRoot, scope.currentPin
48
+ ]);
49
+ scope.variables.set(GlobalDocumentName, {});
50
+ this.setupBuiltInFunctions(this.startingContext);
47
51
  this.executionStack = [this.startingContext];
48
52
  this.startingContext.resolveNet =
49
53
  this.createNetResolver(this.executionStack);
54
+ this.startingContext.resolveComponentPinNet =
55
+ this.createComponentPinNetResolver(this.executionStack);
50
56
  this.silent = silent;
51
- this.currentDirectory = currentDirectory;
52
- this.defaultLibsPath = defaultLibsPath;
53
57
  }
54
58
  getExecutor() {
55
59
  return this.executionStack[this.executionStack.length - 1];
56
60
  }
57
- setupPrintFunction(context) {
61
+ getScope() {
62
+ return this.getExecutor().scope;
63
+ }
64
+ getRootExecutor() {
65
+ return this.executionStack[0];
66
+ }
67
+ setupBuiltInFunctions(context) {
58
68
  linkBuiltInMethods(context, this);
59
69
  }
60
70
  createNetResolver(executionStack) {
@@ -77,6 +87,19 @@ export class BaseVisitor extends CircuitScriptVisitor {
77
87
  };
78
88
  return resolveNet;
79
89
  }
90
+ createComponentPinNetResolver(executionStack) {
91
+ return (component, pin) => {
92
+ const reversed = [...executionStack].reverse();
93
+ for (let i = 0; i < reversed.length; i++) {
94
+ const context = reversed[i];
95
+ const net = context.scope.getNet(component, pin);
96
+ if (net !== null) {
97
+ return net;
98
+ }
99
+ }
100
+ return null;
101
+ };
102
+ }
80
103
  log(...params) {
81
104
  const indentOutput = ''.padStart(this.indentLevel * 4, ' ');
82
105
  const indentLevelText = this.indentLevel.toString().padStart(3, ' ');
@@ -89,11 +112,21 @@ export class BaseVisitor extends CircuitScriptVisitor {
89
112
  log2(message) {
90
113
  this.getExecutor().log(message);
91
114
  }
92
- visitScript = (ctx) => {
115
+ async visitAsync(ctx) {
116
+ const result = await ctx.accept(this);
117
+ return result;
118
+ }
119
+ visitScript = async (ctx) => {
93
120
  this.log('===', 'start', '===');
94
- const result = this.visitChildren(ctx);
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);
95
129
  this.log('===', 'end', '===');
96
- return result;
97
130
  };
98
131
  visitAssignment_expr = (ctx) => {
99
132
  const reference = this.getReference(ctx.atom_expr());
@@ -103,12 +136,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
103
136
  const trailers = reference.trailers ?? [];
104
137
  if (trailers.length === 0) {
105
138
  if (value instanceof ClassComponent) {
106
- const instances = this.getExecutor().scope.instances;
107
- const tmpComponent = value;
108
- const oldName = tmpComponent.instanceName;
109
- tmpComponent.instanceName = reference.name;
110
- instances.delete(oldName);
111
- instances.set(reference.name, tmpComponent);
139
+ const variables = this.getExecutor().scope.variables;
140
+ variables.set(reference.name, value);
141
+ this.getExecutor().scope.sequence.push([SequenceAction.Assign, reference.name, value]);
112
142
  this.log2(`assigned '${reference.name}' to ClassComponent`);
113
143
  }
114
144
  else {
@@ -229,7 +259,6 @@ export class BaseVisitor extends CircuitScriptVisitor {
229
259
  executor.scope.setNet(tmpComponent, pinId, net);
230
260
  }
231
261
  }
232
- this.log2(`atomId: ${atomId} ${currentReference}`);
233
262
  if (ctx.parent instanceof ExpressionContext && !currentReference.found) {
234
263
  this.throwWithContext(ctx, "Unknown symbol: " + atomId);
235
264
  }
@@ -369,10 +398,10 @@ export class BaseVisitor extends CircuitScriptVisitor {
369
398
  const tmpCtx = defaultValuesProvided[index - boundary];
370
399
  this.visit(tmpCtx);
371
400
  const defaultValue = this.getResult(tmpCtx);
372
- return [idText, defaultValue];
401
+ return [idText, tmpCtx.start, defaultValue];
373
402
  }
374
403
  else {
375
- return [idText];
404
+ return [idText, id.getSymbol()];
376
405
  }
377
406
  });
378
407
  this.setResult(ctx, result);
@@ -394,10 +423,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
394
423
  this.setResult(ctx, returnList);
395
424
  };
396
425
  visitImport_expr = (ctx) => {
397
- const ID = ctx.ID().toString();
398
- this.log('import', ID);
399
- this.handleImportFile(ID, true, ctx);
400
- this.log('done import', ID);
426
+ throw new RuntimeExecutionError("Cannot parse imports here", ctx.start, ctx.stop);
401
427
  };
402
428
  visitFunction_return_expr = (ctx) => {
403
429
  const executor = this.getExecutor();
@@ -447,15 +473,24 @@ export class BaseVisitor extends CircuitScriptVisitor {
447
473
  this.visit(ctx);
448
474
  return this.getResult(ctx);
449
475
  }
450
- 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
+ }
451
484
  let hasError = false;
452
485
  let hasParseError = false;
453
486
  let pathExists = false;
454
- const tmpFilePath = join(this.currentDirectory, name + ".cst");
487
+ const tmpFilePath = this.environment.getRelativeToModule(name + ".cst");
455
488
  this.log('importing path:', tmpFilePath);
456
489
  let fileData = null;
490
+ let filePathUsed = null;
457
491
  try {
458
- fileData = readFileSync(tmpFilePath, { encoding: 'utf8' });
492
+ filePathUsed = tmpFilePath;
493
+ fileData = await this.environment.readFile(tmpFilePath, { encoding: 'utf8' });
459
494
  pathExists = true;
460
495
  }
461
496
  catch (err) {
@@ -463,8 +498,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
463
498
  }
464
499
  if (!pathExists) {
465
500
  try {
466
- const tmpFilePath2 = join(this.defaultLibsPath, name + ".cst");
467
- fileData = readFileSync(tmpFilePath2, { encoding: 'utf8' });
501
+ const tmpFilePath2 = this.environment.getRelativeToDefaultLibs(name + ".cst");
502
+ filePathUsed = tmpFilePath2;
503
+ fileData = await this.environment.readFile(tmpFilePath2, { encoding: 'utf8' });
468
504
  pathExists = true;
469
505
  }
470
506
  catch (err) {
@@ -474,31 +510,39 @@ export class BaseVisitor extends CircuitScriptVisitor {
474
510
  try {
475
511
  if (pathExists) {
476
512
  this.log('done reading imported file data');
477
- const importResult = this.onImportFile(this, fileData, this.onErrorCallbackHandler);
513
+ const importResult = await this.onImportFile(this, filePathUsed, fileData, this.onErrorHandler);
478
514
  hasError = importResult.hasError;
479
515
  hasParseError = importResult.hasParseError;
480
516
  }
481
517
  }
482
518
  catch (err) {
483
- this.log('Failed to import file: ', err.message);
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
+ }
484
525
  }
485
526
  let errorMessage = null;
486
527
  if (throwErrors && (hasError || hasParseError || !pathExists)) {
487
528
  if (!pathExists) {
488
- errorMessage = `File does not exist: ${name}`;
529
+ errorMessage = `File does not exist: ${name} (${filePathUsed})`;
489
530
  }
490
531
  else {
491
532
  errorMessage = `Failed to import: ${name}`;
492
533
  }
493
534
  }
494
535
  if (errorMessage !== null && ctx) {
495
- this.throwWithContext(ctx, errorMessage);
536
+ throw new RuntimeExecutionError(errorMessage, ctx.start, ctx.end);
496
537
  }
497
- return {
538
+ const newImportedFile = {
539
+ id: name.trim(),
498
540
  hasError,
499
541
  hasParseError,
500
542
  pathExists,
501
543
  };
544
+ this.importedFiles.push(newImportedFile);
545
+ return newImportedFile;
502
546
  }
503
547
  visitRoundedBracketsExpr = (ctx) => {
504
548
  const ctxDataExpr = ctx.data_expr();
@@ -528,9 +572,9 @@ export class BaseVisitor extends CircuitScriptVisitor {
528
572
  executor.scope.variables.set(variableName, tmpPassedInArgs[2]);
529
573
  }
530
574
  }
531
- else if (tmpFuncArg.length === 2) {
575
+ else if (tmpFuncArg.length === 3) {
532
576
  const variableName = tmpFuncArg[0];
533
- const defaultValue = tmpFuncArg[1];
577
+ const defaultValue = tmpFuncArg[2];
534
578
  executor.log('set variable in scope, var name: ', variableName);
535
579
  executor.scope.variables.set(variableName, defaultValue);
536
580
  }
@@ -594,7 +638,6 @@ export class BaseVisitor extends CircuitScriptVisitor {
594
638
  const executionContextNamespace = currentExecutionContext.namespace
595
639
  + executionContextName + ".";
596
640
  const newExecutor = new ExecutionContext(executionContextName, executionContextNamespace, netNamespace, executionLevel + 1, this.getExecutor().scope.indentLevel + 1, currentExecutionContext.silent, currentExecutionContext.logger, parentContext);
597
- this.setupPrintFunction(newExecutor);
598
641
  executionStack.push(newExecutor);
599
642
  this.setupDefinedParameters(funcDefinedParameters, passedInParameters, newExecutor);
600
643
  return newExecutor;
@@ -602,7 +645,32 @@ export class BaseVisitor extends CircuitScriptVisitor {
602
645
  prepareStringValue(value) {
603
646
  return value.slice(1, value.length - 1);
604
647
  }
605
- throwWithContext(context, message) {
606
- throwWithContext(context, message);
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');
607
675
  }
608
676
  }