circuitscript 0.0.22 → 0.0.25

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 (180) hide show
  1. package/dist/cjs/BaseVisitor.js +487 -0
  2. package/dist/cjs/SemanticTokenVisitor.js +218 -0
  3. package/dist/cjs/SymbolValidatorVisitor.js +233 -0
  4. package/dist/cjs/antlr/CircuitScriptLexer.js +302 -0
  5. package/dist/cjs/antlr/CircuitScriptParser.js +5128 -0
  6. package/dist/cjs/antlr/CircuitScriptVisitor.js +7 -0
  7. package/dist/cjs/draw_symbols.js +819 -0
  8. package/dist/cjs/execute.js +778 -0
  9. package/{src/export.ts → dist/cjs/export.js} +34 -56
  10. package/dist/cjs/fonts.js +4 -0
  11. package/dist/cjs/geometry.js +450 -0
  12. package/dist/cjs/globals.js +60 -0
  13. package/dist/cjs/helpers.js +269 -0
  14. package/dist/cjs/index.js +31 -0
  15. package/{src/layout.ts → dist/cjs/layout.js} +421 -1002
  16. package/dist/cjs/lexer.js +111 -0
  17. package/dist/cjs/logger.js +17 -0
  18. package/dist/cjs/main.js +82 -0
  19. package/dist/cjs/objects/ClassComponent.js +145 -0
  20. package/dist/cjs/objects/ExecutionScope.js +135 -0
  21. package/dist/cjs/objects/Frame.js +22 -0
  22. package/{src/objects/Net.ts → dist/cjs/objects/Net.js} +9 -24
  23. package/dist/cjs/objects/ParamDefinition.js +42 -0
  24. package/dist/cjs/objects/PinDefinition.js +31 -0
  25. package/dist/cjs/objects/PinTypes.js +11 -0
  26. package/dist/cjs/objects/Wire.js +9 -0
  27. package/dist/cjs/objects/types.js +15 -0
  28. package/dist/cjs/parser.js +70 -0
  29. package/dist/cjs/regenerate-tests.js +23 -0
  30. package/dist/cjs/render.js +155 -0
  31. package/{src/server.ts → dist/cjs/server.js} +15 -21
  32. package/dist/cjs/sizing.js +105 -0
  33. package/{src/utils.ts → dist/cjs/utils.js} +25 -35
  34. package/dist/cjs/validate.js +81 -0
  35. package/dist/cjs/visitor.js +844 -0
  36. package/dist/esm/BaseVisitor.mjs +488 -0
  37. package/dist/esm/SemanticTokenVisitor.mjs +215 -0
  38. package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
  39. package/dist/esm/antlr/CircuitScriptLexer.mjs +276 -0
  40. package/dist/esm/antlr/CircuitScriptParser.mjs +5038 -0
  41. package/{build/src/antlr/CircuitScriptVisitor.js → dist/esm/antlr/CircuitScriptVisitor.mjs} +8 -3
  42. package/{build/src/draw_symbols.js → dist/esm/draw_symbols.mjs} +78 -33
  43. package/{build/src/execute.js → dist/esm/execute.mjs} +59 -60
  44. package/{build/src/export.js → dist/esm/export.mjs} +2 -2
  45. package/{build/src/geometry.js → dist/esm/geometry.mjs} +31 -15
  46. package/dist/esm/helpers.mjs +252 -0
  47. package/dist/esm/index.mjs +15 -0
  48. package/{build/src/layout.js → dist/esm/layout.mjs} +19 -11
  49. package/{build/src/lexer.js → dist/esm/lexer.mjs} +10 -10
  50. package/{build/src/main.js → dist/esm/main.mjs} +9 -14
  51. package/{build/src/objects/ClassComponent.js → dist/esm/objects/ClassComponent.mjs} +6 -3
  52. package/{build/src/objects/ExecutionScope.js → dist/esm/objects/ExecutionScope.mjs} +1 -0
  53. package/{build/src/objects/PinDefinition.js → dist/esm/objects/PinDefinition.mjs} +1 -1
  54. package/dist/esm/objects/types.mjs +12 -0
  55. package/dist/esm/parser.mjs +64 -0
  56. package/{build/src/regenerate-tests.js → dist/esm/regenerate-tests.mjs} +1 -1
  57. package/{build/src/render.js → dist/esm/render.mjs} +7 -24
  58. package/{build/src/sizing.js → dist/esm/sizing.mjs} +22 -8
  59. package/{src/main.ts → dist/esm/validate.mjs} +31 -62
  60. package/dist/esm/visitor.mjs +838 -0
  61. package/dist/types/BaseVisitor.d.ts +69 -0
  62. package/dist/types/SemanticTokenVisitor.d.ts +36 -0
  63. package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
  64. package/{build/src → dist/types}/antlr/CircuitScriptLexer.d.ts +28 -27
  65. package/dist/types/antlr/CircuitScriptParser.d.ts +719 -0
  66. package/{build/src → dist/types}/antlr/CircuitScriptVisitor.d.ts +69 -59
  67. package/{build/src → dist/types}/draw_symbols.d.ts +11 -2
  68. package/{build/src → dist/types}/execute.d.ts +6 -9
  69. package/{build/src → dist/types}/geometry.d.ts +5 -1
  70. package/dist/types/helpers.d.ts +40 -0
  71. package/dist/types/index.d.ts +15 -0
  72. package/{build/src → dist/types}/layout.d.ts +10 -10
  73. package/{build/src → dist/types}/lexer.d.ts +2 -2
  74. package/{build/src → dist/types}/objects/ClassComponent.d.ts +2 -2
  75. package/{build/src → dist/types}/objects/ExecutionScope.d.ts +4 -1
  76. package/{build/src → dist/types}/objects/PinDefinition.d.ts +1 -1
  77. package/{build/src → dist/types}/objects/types.d.ts +5 -0
  78. package/dist/types/parser.d.ts +25 -0
  79. package/{build/src → dist/types}/render.d.ts +1 -1
  80. package/{build/src → dist/types}/sizing.d.ts +3 -1
  81. package/dist/types/validate.d.ts +2 -0
  82. package/dist/types/visitor.d.ts +80 -0
  83. package/libs/lib.cst +0 -2
  84. package/package.json +38 -15
  85. package/.editorconfig +0 -15
  86. package/.eslintignore +0 -1
  87. package/.eslintrc.json +0 -27
  88. package/.gitlab-ci.yml +0 -81
  89. package/.prettierignore +0 -8
  90. package/.prettierrc +0 -16
  91. package/__tests__/expectedResults.ts +0 -657
  92. package/__tests__/helpers.ts +0 -82
  93. package/__tests__/parseScripts.ts +0 -593
  94. package/__tests__/renderData/script1.cst +0 -58
  95. package/__tests__/renderData/script1.cst.svg +0 -1
  96. package/__tests__/renderData/script2.cst +0 -16
  97. package/__tests__/renderData/script2.cst.svg +0 -1
  98. package/__tests__/renderData/script3.cst +0 -30
  99. package/__tests__/renderData/script3.cst.svg +0 -1
  100. package/__tests__/renderData/script4.cst +0 -54
  101. package/__tests__/renderData/script4.cst.svg +0 -1
  102. package/__tests__/renderData/script5.cst +0 -23
  103. package/__tests__/renderData/script5.cst.svg +0 -1
  104. package/__tests__/renderData/script6.cst +0 -28
  105. package/__tests__/renderData/script6.cst.svg +0 -1
  106. package/__tests__/renderData/script7.cst +0 -26
  107. package/__tests__/renderData/script7.cst.svg +0 -1
  108. package/__tests__/renderData/script8.cst +0 -37
  109. package/__tests__/renderData/script8.cst.svg +0 -1
  110. package/__tests__/testCLI.ts +0 -68
  111. package/__tests__/testMathOps.ts +0 -36
  112. package/__tests__/testMergeWires.ts +0 -141
  113. package/__tests__/testParse.ts +0 -263
  114. package/__tests__/testRender.ts +0 -38
  115. package/build/src/antlr/CircuitScriptLexer.js +0 -287
  116. package/build/src/antlr/CircuitScriptParser.d.ts +0 -674
  117. package/build/src/antlr/CircuitScriptParser.js +0 -4841
  118. package/build/src/helpers.d.ts +0 -1
  119. package/build/src/helpers.js +0 -73
  120. package/build/src/objects/types.js +0 -6
  121. package/build/src/parser.js +0 -69
  122. package/build/src/visitor.d.ts +0 -133
  123. package/build/src/visitor.js +0 -1154
  124. package/documentation.md +0 -238
  125. package/examples/example_arduino_uno.cst +0 -1146
  126. package/examples/example_garden_pump.cst +0 -567
  127. package/examples/lib.cst +0 -185
  128. package/jest.config.js +0 -23
  129. package/refresh.html +0 -42
  130. package/server.cjs +0 -50
  131. package/src/antlr/CircuitScript.g4 +0 -209
  132. package/src/antlr/CircuitScriptLexer.ts +0 -317
  133. package/src/antlr/CircuitScriptParser.ts +0 -4979
  134. package/src/antlr/CircuitScriptVisitor.ts +0 -420
  135. package/src/draw_symbols.ts +0 -1085
  136. package/src/execute.ts +0 -1227
  137. package/src/fonts.ts +0 -1
  138. package/src/geometry.ts +0 -638
  139. package/src/globals.ts +0 -67
  140. package/src/helpers.ts +0 -114
  141. package/src/lexer.ts +0 -151
  142. package/src/logger.ts +0 -17
  143. package/src/objects/ClassComponent.ts +0 -223
  144. package/src/objects/ExecutionScope.ts +0 -201
  145. package/src/objects/Frame.ts +0 -20
  146. package/src/objects/ParamDefinition.ts +0 -49
  147. package/src/objects/PinDefinition.ts +0 -49
  148. package/src/objects/PinTypes.ts +0 -7
  149. package/src/objects/Wire.ts +0 -19
  150. package/src/objects/types.ts +0 -66
  151. package/src/parser.ts +0 -106
  152. package/src/regenerate-tests.ts +0 -25
  153. package/src/render.ts +0 -260
  154. package/src/sizing.ts +0 -96
  155. package/src/visitor.ts +0 -1691
  156. package/tsconfig.json +0 -27
  157. package/tsconfig.release.json +0 -8
  158. /package/{build/src/fonts.js → dist/esm/fonts.mjs} +0 -0
  159. /package/{build/src/globals.js → dist/esm/globals.mjs} +0 -0
  160. /package/{build/src/logger.js → dist/esm/logger.mjs} +0 -0
  161. /package/{build/src/objects/Frame.js → dist/esm/objects/Frame.mjs} +0 -0
  162. /package/{build/src/objects/Net.js → dist/esm/objects/Net.mjs} +0 -0
  163. /package/{build/src/objects/ParamDefinition.js → dist/esm/objects/ParamDefinition.mjs} +0 -0
  164. /package/{build/src/objects/PinTypes.js → dist/esm/objects/PinTypes.mjs} +0 -0
  165. /package/{build/src/objects/Wire.js → dist/esm/objects/Wire.mjs} +0 -0
  166. /package/{build/src/server.js → dist/esm/server.mjs} +0 -0
  167. /package/{build/src/utils.js → dist/esm/utils.mjs} +0 -0
  168. /package/{build/src → dist/types}/export.d.ts +0 -0
  169. /package/{build/src → dist/types}/fonts.d.ts +0 -0
  170. /package/{build/src → dist/types}/globals.d.ts +0 -0
  171. /package/{build/src → dist/types}/logger.d.ts +0 -0
  172. /package/{build/src → dist/types}/main.d.ts +0 -0
  173. /package/{build/src → dist/types}/objects/Frame.d.ts +0 -0
  174. /package/{build/src → dist/types}/objects/Net.d.ts +0 -0
  175. /package/{build/src → dist/types}/objects/ParamDefinition.d.ts +0 -0
  176. /package/{build/src → dist/types}/objects/PinTypes.d.ts +0 -0
  177. /package/{build/src → dist/types}/objects/Wire.d.ts +0 -0
  178. /package/{build/src → dist/types}/regenerate-tests.d.ts +0 -0
  179. /package/{build/src → dist/types}/server.d.ts +0 -0
  180. /package/{build/src → dist/types}/utils.d.ts +0 -0
package/src/visitor.ts DELETED
@@ -1,1691 +0,0 @@
1
- import { ParseTreeVisitor, ParserRuleContext } from 'antlr4';
2
-
3
- import { readFileSync } from 'fs';
4
- import { join } from 'path';
5
-
6
- import {
7
- Add_component_exprContext,
8
- AdditionExprContext,
9
- Assignment_exprContext,
10
- At_blockContext,
11
- At_block_pin_exprContext,
12
- At_block_pin_expression_complexContext,
13
- At_block_pin_expression_simpleContext,
14
- At_component_exprContext,
15
- Atom_exprContext,
16
- BinaryOperatorExprContext,
17
- Blank_exprContext,
18
- Path_blocksContext,
19
- Component_select_exprContext,
20
- Create_component_exprContext,
21
- Create_graphic_exprContext,
22
- DataExprContext,
23
- Data_expr_with_assignmentContext,
24
- Double_dot_property_set_exprContext,
25
- ExpressionContext,
26
- Frame_exprContext,
27
- Function_args_exprContext,
28
- Function_def_exprContext,
29
- Function_exprContext,
30
- Function_return_exprContext,
31
- Import_exprContext,
32
- Keyword_assignment_exprContext,
33
- MultiplyExprContext,
34
- Nested_propertiesContext,
35
- Net_namespace_exprContext,
36
- ParametersContext,
37
- Pin_select_expr2Context,
38
- Pin_select_exprContext,
39
- Point_exprContext,
40
- Property_exprContext,
41
- Property_key_exprContext,
42
- Property_set_exprContext,
43
- RoundedBracketsExprContext,
44
- ScriptContext,
45
- Single_line_propertyContext,
46
- Sub_exprContext,
47
- To_component_exprContext,
48
- Value_exprContext,
49
- Wire_exprContext,
50
- ValueAtomExprContext,
51
- UnaryOperatorExprContext,
52
- } from './antlr/CircuitScriptParser.js';
53
- import { ExecutionContext } from './execute.js';
54
- import { ClassComponent } from './objects/ClassComponent.js';
55
- import {
56
- NumericValue,
57
- ParamDefinition,
58
- PercentageValue,
59
- PinBlankValue,
60
- } from './objects/ParamDefinition.js';
61
- import { PinDefinition, PinIdType } from './objects/PinDefinition.js';
62
- import { PinTypes } from './objects/PinTypes.js';
63
- import { ExecutionScope } from './objects/ExecutionScope.js';
64
- import { CFunctionOptions, CallableParameter, ComplexType, ComponentPin,
65
- ComponentPinNet, FunctionDefinedParameter, ReferenceType, UndeclaredReference, ValueType } from './objects/types.js';
66
- import { Logger } from './logger.js';
67
- import { BlockTypes, ComponentTypes, NoNetText } from './globals.js';
68
- import { Net } from './objects/Net.js';
69
- import { SubExpressionCommand, SymbolDrawingCommands } from './draw_symbols.js';
70
- import { parseFileWithVisitor } from './parser.js';
71
-
72
- export class MainVisitor extends ParseTreeVisitor<any> {
73
- // See class CircuitScriptVisitor (generated by antlr4) to find method names
74
-
75
- // Contains the methods here, so that it is function based instead
76
- // of just lambdas/callbacks...
77
-
78
- indentLevel = 0;
79
- startingContext: ExecutionContext;
80
- executionStack: ExecutionContext[];
81
-
82
- // If true, then do not print out anything
83
- silent = false;
84
-
85
- logger: Logger;
86
-
87
- printStream: string[] = [];
88
- printToConsole = true;
89
-
90
- acceptedDirections = ['left', 'right', 'up', 'down'];
91
-
92
- pinTypesList: string[] = [
93
- PinTypes.Any,
94
- PinTypes.Input,
95
- PinTypes.Output,
96
- PinTypes.IO,
97
- PinTypes.Power,
98
- ];
99
-
100
- onImportFile = (visitor: MainVisitor, filePath:string): {hasError:boolean, hasParseError: boolean} => {
101
- throw "Import file not implemented"
102
- }
103
-
104
- constructor(silent = false) {
105
- super();
106
- this.logger = new Logger();
107
-
108
- this.startingContext = new ExecutionContext(
109
- '__',
110
- '__.',
111
- '/',
112
- 0, 0, silent,
113
- this.logger);
114
-
115
- this.setupPrintFunction(this.startingContext);
116
-
117
- this.executionStack = [this.startingContext];
118
- this.startingContext.resolveNet =
119
- this.createNetResolver(this.executionStack);
120
-
121
- this.silent = silent;
122
- }
123
-
124
- getExecutor(): ExecutionContext {
125
- return this.executionStack[this.executionStack.length - 1];
126
- }
127
-
128
- visit(ctx: ParserRuleContext): any {
129
- if (Array.isArray(ctx)) {
130
- return ctx.map(function (child) {
131
- try {
132
- return child.accept(this);
133
- } catch (err) {
134
- this.handleError(child, err);
135
- }
136
- }, this);
137
- } else {
138
- try {
139
- return ctx.accept(this);
140
- } catch (err) {
141
- this.handleError(ctx, err);
142
- }
143
- }
144
- }
145
-
146
- handleError(ctx: ParserRuleContext, err: string | VisitorExecutionException): void {
147
- if (!(err instanceof VisitorExecutionException)) {
148
- throw new VisitorExecutionException(ctx, err);
149
- } else {
150
- throw err;
151
- }
152
- }
153
-
154
- visitScript(ctx: ScriptContext): any {
155
- this.print('===', 'start', '===');
156
- const result = this.visitChildren(ctx);
157
- this.print('===', 'end', '===');
158
- return result;
159
- }
160
-
161
- visitParameters(ctx: ParametersContext): CallableParameter[] {
162
- const dataExpressions = ctx.data_expr_list();
163
- const keywordAssignmentExpressions = ctx.keyword_assignment_expr_list();
164
-
165
- const returnList: CallableParameter[] = [];
166
-
167
- dataExpressions.forEach((item, index) => {
168
- const value = this.visit(item);
169
- returnList.push(['position', index, value]);
170
- });
171
-
172
- keywordAssignmentExpressions.forEach((item) => {
173
- const [key, value] = this.visit(item);
174
- returnList.push(['keyword', key, value]);
175
- });
176
-
177
- return returnList;
178
- }
179
-
180
- visitKeyword_assignment_expr(ctx: Keyword_assignment_exprContext):
181
- [key: string, value: any] {
182
- const id = ctx.ID().getText();
183
- const value = this.visit(ctx.data_expr());
184
- return [id, value];
185
- }
186
-
187
- visitAssignment_expr(ctx: Assignment_exprContext): ComplexType {
188
- const atomStr = ctx.atom_expr().getText();
189
-
190
- // Do not allow the atom to have any parentheses in the assignment
191
- if (atomStr.indexOf('(') !== -1 || atomStr.indexOf(')') !== -1) {
192
- throw "Invalid assignment expression!";
193
- }
194
-
195
- const reference = this.visit(ctx.atom_expr());
196
- const value = this.visit(ctx.data_expr()) as ComplexType;
197
-
198
- if (value instanceof ClassComponent) {
199
- // If value is a class component, then update the instance name
200
- const instances = this.getExecutor().scope.instances;
201
- const tmpComponent: ClassComponent = value;
202
-
203
- const oldName = tmpComponent.instanceName;
204
-
205
- // Rename to new name
206
- tmpComponent.instanceName = reference.name;
207
-
208
- instances.delete(oldName);
209
- instances.set(reference.name, tmpComponent);
210
-
211
- this.getExecutor().print(
212
- `assigned '${reference.name}' to ClassComponent`,
213
- );
214
- } else {
215
- // Otherwise, assign variable name to value
216
- const trailers = reference.trailers ?? [];
217
-
218
- if (trailers.length === 0){
219
- // No trailers, directly assign the reference name
220
- this.getExecutor().scope.variables.set(reference.name, value);
221
-
222
- } else if (reference.value instanceof ClassComponent) {
223
- this.setInstanceParam(reference.value, trailers, value);
224
- }
225
- }
226
-
227
- return value;
228
- }
229
-
230
- setInstanceParam(object: ClassComponent, trailers: string[], value: any): void {
231
- const paramName = trailers[0].slice(1);
232
- object.setParam(paramName, value);
233
-
234
- this.getExecutor().print(
235
- `set instance ${object.instanceName} param ${paramName} to ${value}`);
236
- }
237
-
238
- visitValue_expr(ctx: Value_exprContext): ValueType {
239
- const sign = ctx.Minus() ? -1 : 1;
240
-
241
- if (ctx.INTEGER_VALUE() || ctx.DECIMAL_VALUE() || ctx.NUMERIC_VALUE()) {
242
- if (ctx.INTEGER_VALUE()) {
243
- return sign * Number(ctx.INTEGER_VALUE().getText());
244
-
245
- } else if (ctx.DECIMAL_VALUE()) {
246
- return sign * Number(ctx.DECIMAL_VALUE().getText());
247
-
248
- } else if (ctx.NUMERIC_VALUE()) {
249
- const textExtra = ctx.Minus() ? '-' : '';
250
- return new NumericValue(textExtra + ctx.NUMERIC_VALUE().getText());
251
-
252
- }
253
- } else {
254
- if (sign === -1) {
255
- throw "Invalid value!";
256
- }
257
- }
258
-
259
- if (ctx.BOOLEAN_VALUE()) {
260
- const stringValue = ctx.BOOLEAN_VALUE().getText();
261
- if (stringValue === 'true') {
262
- return true;
263
- } else if (stringValue === 'false') {
264
- return false;
265
- }
266
-
267
- } else if (ctx.STRING_VALUE()) {
268
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
269
-
270
- } else if (ctx.PERCENTAGE_VALUE()) {
271
- return new PercentageValue(ctx.PERCENTAGE_VALUE().getText());
272
-
273
- } else if (ctx.blank_expr()) {
274
- return this.visit(ctx.blank_expr());
275
- }
276
- }
277
-
278
- visitBlank_expr(ctx: Blank_exprContext): PinBlankValue {
279
- // There must be an integer value, otherwise the rule wouldn't match.
280
- return new PinBlankValue(Number(ctx.INTEGER_VALUE().getText()));
281
- }
282
-
283
- visitPin_select_expr(ctx: Pin_select_exprContext): string | number | null {
284
- if (ctx.INTEGER_VALUE()) {
285
- return Number(ctx.INTEGER_VALUE().getText());
286
-
287
- } else if (ctx.STRING_VALUE()) {
288
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
289
- }
290
-
291
- return null;
292
- }
293
-
294
- visitAdd_component_expr(ctx: Add_component_exprContext): ComponentPin {
295
- // The component is always the last item
296
- const [component, pinValue] =
297
- this.visit(ctx.data_expr_with_assignment());
298
-
299
- if (ctx.ID()){
300
- this.setComponentOrientation(
301
- component, pinValue, ctx.ID().getText());
302
- }
303
-
304
- return this.getExecutor().addComponentExisting(component, pinValue);
305
- }
306
-
307
- visitAt_component_expr(ctx: At_component_exprContext): ComponentPin {
308
- if (ctx.Point()) {
309
- this.getExecutor().atPointBlock();
310
-
311
- } else {
312
- const [component, pin] = this.visit(ctx.component_select_expr());
313
-
314
- const currentPoint = this.getExecutor().atComponent(component, pin, {
315
- addSequence: true,
316
- cloneNetComponent: true
317
- });
318
-
319
- if (ctx.ID()) {
320
- // If there is ID specified, then it can only be for the
321
- // component orientation.
322
- this.setComponentOrientation(currentPoint[0],
323
- currentPoint[1], ctx.ID().getText())
324
- }
325
- }
326
-
327
- return this.getExecutor().getCurrentPoint();
328
- }
329
-
330
- visitTo_component_expr(ctx: To_component_exprContext): ComponentPin {
331
- let currentPoint: ComponentPin;
332
-
333
- if (ctx.Point()) {
334
- this.getExecutor().toPointBlock();
335
-
336
- } else {
337
- ctx.component_select_expr_list().forEach((item) => {
338
- const [component, pin] = this.visit(item);
339
- currentPoint = this.getExecutor().toComponent(component, pin, {
340
- addSequence: true, cloneNetComponent: true
341
- });
342
- });
343
-
344
- if (ctx.ID()) {
345
- // If there is ID specified, then it can only be for the
346
- // component orientation.
347
- this.setComponentOrientation(currentPoint[0],
348
- currentPoint[1], ctx.ID().getText())
349
- }
350
- }
351
-
352
- return this.getExecutor().getCurrentPoint();
353
- }
354
-
355
- visitComponent_select_expr(ctx: Component_select_exprContext): ComponentPin {
356
- if (ctx.data_expr_with_assignment()) {
357
- return this.visit(ctx.data_expr_with_assignment());
358
- } else {
359
- const component = this.getExecutor().scope.currentComponent;
360
- let pinId: number | string | null = null;
361
-
362
- if (ctx.pin_select_expr()) {
363
- pinId = this.visit(ctx.pin_select_expr());
364
- }
365
- return [component, pinId];
366
- }
367
- }
368
-
369
- visitPath_blocks(ctx: Path_blocksContext): ComponentPin {
370
- const blocks = ctx.path_block_inner_list();
371
-
372
- let blockIndex = 0; // Tracks the index of the block with the given type
373
- let blockType = BlockTypes.Branch;
374
- let prevBlockType = null;
375
-
376
- blocks.forEach((block, index) => {
377
- if (block.Branch()) {
378
- blockType = BlockTypes.Branch
379
- } else if (block.Join()) {
380
- blockType = BlockTypes.Join;
381
- } else if (block.Parallel()) {
382
- blockType = BlockTypes.Parallel;
383
- } else if (block.Point()) {
384
- blockType = BlockTypes.Point;
385
- }
386
-
387
- if (prevBlockType !== blockType) {
388
- if (index > 0) {
389
- // If not the first block, then exit the
390
- // group of blocks.
391
- this.getExecutor().exitBlocks();
392
- }
393
-
394
- this.getExecutor().enterBlocks(blockType);
395
- blockIndex = 0; // Reset counter.
396
- }
397
-
398
- this.getExecutor().enterBlock(blockIndex);
399
- this.visit(block);
400
- this.getExecutor().exitBlock(blockIndex);
401
- blockIndex += 1;
402
-
403
- prevBlockType = blockType;
404
- });
405
-
406
- this.getExecutor().exitBlocks();
407
- return this.getExecutor().getCurrentPoint();
408
- }
409
-
410
- visitBreak_keyword(): number {
411
- // When the break keyword is encountered inside a branch, then leave the branch
412
- // without storing the final state. If used, the break should be
413
- // the last expression in the branch, any expressions after the break
414
- // will be skipped
415
-
416
- this.getExecutor().breakBranch();
417
- return -1;
418
- }
419
-
420
- visitCreate_component_expr(ctx: Create_component_exprContext): ClassComponent {
421
- const properties = this.getPropertyExprList(ctx.property_expr_list());
422
-
423
- const pins: PinDefinition[] = this.parseCreateComponentPins(
424
- properties.get('pins'),
425
- );
426
-
427
- // Use a unique instance name in the context for now
428
- let instanceName = this.getExecutor().getUniqueInstanceName('');
429
-
430
- const propParams = properties.get('params');
431
- const params: ParamDefinition[] =
432
- this.parseCreateComponentParams(propParams);
433
-
434
- if (params.length > 0) {
435
- // Always append the first value
436
- // to the generated name.
437
- const firstParam = params[0];
438
- const paramValue = firstParam.paramValue;
439
- let appendValue = paramValue.toString();
440
-
441
- if (paramValue instanceof NumericValue) {
442
- appendValue = paramValue.value;
443
- }
444
-
445
- instanceName += '_' + appendValue;
446
- }
447
-
448
- const arrange = properties.has('arrange') ?
449
- properties.get('arrange') : null;
450
-
451
- const display = properties.has('display') ?
452
- properties.get('display') : null;
453
-
454
- const type = properties.has('type') ?
455
- properties.get('type') : null;
456
-
457
- const width = properties.has('width') ?
458
- properties.get('width') : null;
459
-
460
- const props = {
461
- arrange,
462
- display,
463
- type,
464
- width,
465
- }
466
-
467
- return this.getExecutor().createComponent(instanceName,
468
- pins, params, props);
469
- }
470
-
471
- visitCreate_graphic_expr(ctx: Create_graphic_exprContext):
472
- SymbolDrawingCommands {
473
-
474
- const commands = ctx.sub_expr_list().reduce((accum, item) => {
475
- const [commandName, parameters] = this.visit(item);
476
-
477
- const keywordParams = new Map<string, any>();
478
- const positionParams = parameters.reduce(
479
- (accum, [argType, name, value]) => {
480
- if (argType === 'position') {
481
- accum.push(value);
482
- } else {
483
- keywordParams.set(name, value);
484
- }
485
- return accum;
486
- }, [] as any[]);
487
-
488
- accum.push([commandName, positionParams, keywordParams]);
489
- return accum;
490
- }, [] as SubExpressionCommand[]);
491
-
492
- return new SymbolDrawingCommands(commands);
493
- }
494
-
495
- visitSub_expr(ctx: Sub_exprContext):
496
- [id: string, parameters: CallableParameter[]] {
497
- let commandName: string = null;
498
- if (ctx.ID()) {
499
- commandName = ctx.ID().getText();
500
- } else if (ctx.Pin()) {
501
- commandName = ctx.Pin().getText();
502
- } else {
503
- throw "Invalid command!";
504
- }
505
-
506
- const parameters: CallableParameter[] = this.visit(ctx.parameters());
507
- return [commandName, parameters];
508
- }
509
-
510
- visitProperty_expr(ctx: Property_exprContext): Map<string, any> {
511
- const keyName = this.visit(ctx.property_key_expr());
512
- const value = this.visit(ctx.property_value_expr());
513
-
514
- const map = new Map<string, any>();
515
- map.set(keyName, value);
516
-
517
- return map;
518
- }
519
-
520
- visitSingle_line_property(ctx: Single_line_propertyContext): any | any[] {
521
- let value;
522
- if (ctx.data_expr_list().length === 1) {
523
- value = this.visit(ctx.data_expr(0));
524
- } else {
525
- value = ctx.data_expr_list().map(item => {
526
- return this.visit(item);
527
- });
528
- }
529
- return value;
530
- }
531
-
532
- visitNested_properties(ctx: Nested_propertiesContext): Map<string, any> {
533
- const result = new Map<string, any>();
534
- ctx.property_expr_list().forEach((item) => {
535
- const property: Map<string, any> = this.visit(item);
536
-
537
- // Get out all items, by default
538
- for (const [key, value] of property) {
539
- result.set(key, value);
540
- }
541
- });
542
-
543
- return result;
544
- }
545
-
546
- visitProperty_key_expr(ctx: Property_key_exprContext): string | number {
547
- if (ctx.ID()) {
548
- return ctx.ID().getText();
549
- } else if (ctx.INTEGER_VALUE()) {
550
- return Number(ctx.INTEGER_VALUE().getText());
551
- } else if (ctx.STRING_VALUE()) {
552
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
553
- }
554
- }
555
-
556
- visitData_expr_with_assignment(ctx: Data_expr_with_assignmentContext):
557
- [component: ComplexType, pin: string | number | null] {
558
-
559
- let component: ComplexType;
560
- if (ctx.data_expr()) {
561
- component = this.visit(ctx.data_expr());
562
-
563
- if (component === null || component === undefined) {
564
- throw "Could not find component: " + ctx.data_expr().getText();
565
- }
566
-
567
- } else if (ctx.assignment_expr()) {
568
- component = this.visit(ctx.assignment_expr())
569
- }
570
-
571
- let pinValue: number | string = null;
572
- if (ctx.pin_select_expr()) {
573
- pinValue = this.visit(ctx.pin_select_expr());
574
- } else {
575
- pinValue = (component as ClassComponent).getDefaultPin();
576
- }
577
-
578
- return [component, pinValue];
579
- }
580
-
581
- visitValueAtomExpr(ctx: ValueAtomExprContext): ComplexType {
582
- let value: ComplexType;
583
-
584
- if (ctx.value_expr()) {
585
- value = this.visit(ctx.value_expr()) as ValueType;
586
-
587
- } else if (ctx.atom_expr()) {
588
- const reference = this.visit(ctx.atom_expr());
589
-
590
- if (!reference.found) {
591
- value = new UndeclaredReference(reference);
592
- } else {
593
- // This is the returned component from the function call
594
- value = reference.value;
595
- }
596
- }
597
-
598
- return value;
599
- }
600
-
601
- visitUnaryOperatorExpr(ctx: UnaryOperatorExprContext): ComplexType {
602
- const value = this.visit(ctx.data_expr());
603
-
604
- const unaryOp = ctx.unary_operator();
605
- if (unaryOp) {
606
- if (unaryOp.Not()) {
607
- if (typeof value === "boolean") {
608
- value = !value;
609
- } else {
610
- throw "Failed to do Not operator";
611
- }
612
- } else if (unaryOp.Minus()) {
613
- if (typeof value === 'number') {
614
- return -value;
615
- } else {
616
- throw "Failed to do Negation operator";
617
- }
618
- }
619
- }
620
-
621
- return value;
622
- }
623
-
624
- visitDataExpr(ctx: DataExprContext): ComplexType {
625
- let value: ComplexType;
626
-
627
- if (ctx.create_component_expr()) {
628
- value = this.visit(ctx.create_component_expr()) as ClassComponent;
629
-
630
- } else if (ctx.create_graphic_expr()) {
631
- value = this.visit(ctx.create_graphic_expr()) as ClassComponent;
632
- }
633
-
634
- return value;
635
- }
636
-
637
- visitBinaryOperatorExpr(ctx: BinaryOperatorExprContext): boolean | number {
638
- const value1 = this.visit(ctx.data_expr(0));
639
- const value2 = this.visit(ctx.data_expr(1));
640
-
641
- const binaryOperatorType = ctx.binary_operator();
642
-
643
- if (binaryOperatorType.Equals()) {
644
- return value1 == value2; // Boolean result
645
- } else if (binaryOperatorType.NotEquals()) {
646
- return value1 != value2;
647
- }
648
- }
649
-
650
- visitMultiplyExpr(ctx: MultiplyExprContext): number {
651
- const value1 = this.visit(ctx.data_expr(0)) as number;
652
- const value2 = this.visit(ctx.data_expr(1)) as number;
653
-
654
- if (ctx.Multiply()) {
655
- return value1 * value2;
656
- } else if (ctx.Divide()) {
657
- return value1 / value2;
658
- }
659
- }
660
-
661
- visitAdditionExpr(ctx: AdditionExprContext): number {
662
- const value1 = this.visit(ctx.data_expr(0)) as number;
663
- const value2 = this.visit(ctx.data_expr(1)) as number;
664
-
665
- if (ctx.Addition()) {
666
- return value1 + value2;
667
- } else if (ctx.Minus()) {
668
- return value1 - value2;
669
- }
670
- }
671
-
672
- visitFunction_args_expr(ctx: Function_args_exprContext):
673
- FunctionDefinedParameter[] {
674
-
675
- const defaultValuesProvided = ctx.value_expr_list();
676
- // The last <defaultValuesProvided> IDs have default values
677
- const IDs = ctx.ID_list(); // Do in reverse
678
-
679
- const boundary = IDs.length - defaultValuesProvided.length;
680
-
681
- return IDs.map((id, index) => {
682
- if (index >= boundary) {
683
- const defaultValue =
684
- this.visit(defaultValuesProvided[index - boundary]);
685
- return [id.getText(), defaultValue];
686
- } else {
687
- return [id.getText()];
688
- }
689
- });
690
- }
691
-
692
- createNetResolver(executionStack: ExecutionContext[]):
693
- (netName: string, netNamespace: string) => {found: boolean, net?: Net} {
694
- const resolveNet = (netName: string, netNamespace: string):
695
- {found: boolean, net?: Net} => {
696
- // netNamespace is the current netNamespace where the net name is
697
- // searching from.
698
-
699
- this.print('find net', netNamespace, netName);
700
- const reversed = [...executionStack].reverse();
701
-
702
- for (let i = 0; i < reversed.length; i++) {
703
- const context = reversed[i];
704
- const net = context.scope.getNetWithName(netName);
705
-
706
- if (net !== null && net.namespace === netNamespace) {
707
- return {
708
- found: true,
709
- net,
710
- }
711
- }
712
- }
713
-
714
- return {
715
- found: false
716
- }
717
- }
718
-
719
- return resolveNet;
720
- }
721
-
722
- visitFunction_def_expr(ctx: Function_def_exprContext): void {
723
- const functionName = ctx.ID().getText();
724
-
725
- // These are the defined arguments for the function
726
- let funcDefinedParameters: FunctionDefinedParameter[] = [];
727
- if (ctx.function_args_expr()) {
728
- funcDefinedParameters = this.visit(ctx.function_args_expr());
729
- }
730
-
731
- const executionStack = this.executionStack;
732
- const functionCounter = { counter: 0 };
733
-
734
- const resolveNet = this.createNetResolver(this.executionStack);
735
-
736
- const __runFunc = (passedInParameters:CallableParameter[],
737
- options: CFunctionOptions): [
738
- executionContext: ExecutionContext,
739
- result: ComplexType | null] => {
740
-
741
- const {netNamespace = ""} = options;
742
-
743
- // Create a new execution context, so that the commands are executed only
744
- // within this context. Components and nets will be local to this context for now.
745
- const currentExecutionContext =
746
- executionStack[executionStack.length - 1];
747
- const executionLevel = currentExecutionContext.executionLevel;
748
-
749
- const executionContextName =
750
- functionName + '_' + functionCounter['counter'];
751
- const executionContextNamespace = currentExecutionContext.namespace
752
- + executionContextName + ".";
753
-
754
- functionCounter['counter'] += 1;
755
-
756
- const newExecutor = new ExecutionContext(
757
- executionContextName,
758
- executionContextNamespace,
759
- netNamespace,
760
- executionLevel + 1,
761
- this.getExecutor().scope.indentLevel + 1,
762
- currentExecutionContext.silent,
763
- currentExecutionContext.logger,
764
- );
765
-
766
- this.setupPrintFunction(newExecutor);
767
-
768
- newExecutor.resolveNet = resolveNet;
769
-
770
- // Add the execution context to the end of the execution stack
771
- executionStack.push(newExecutor);
772
-
773
- // Setup the params in the execution scope if there
774
- // are any function parameters
775
-
776
- this.setupDefinedParameters(
777
- functionName,
778
- funcDefinedParameters,
779
- passedInParameters,
780
- newExecutor
781
- );
782
-
783
- const returnValue = this.runExpressions(newExecutor,
784
- ctx.function_expr_list());
785
-
786
- // Function execution is completed, get the last executor
787
- const lastExecution = executionStack.pop();
788
-
789
- // Merge what ever was created in the scope with the outer scope
790
- const nextLastExecution = executionStack[executionStack.length - 1];
791
- nextLastExecution.mergeScope(
792
- lastExecution.scope,
793
- executionContextName,
794
- );
795
-
796
- // Return the last execution context and the final return value of the function
797
- return [lastExecution, returnValue];
798
- };
799
-
800
- this.getExecutor().createFunction(functionName, __runFunc);
801
- }
802
-
803
- private setupDefinedParameters(
804
- functionName: string,
805
- funcDefinedParameters: FunctionDefinedParameter[],
806
- passedInParameters: CallableParameter[],
807
- executor: ExecutionContext): void {
808
-
809
- // Check if the arguments match up
810
- for (let i = 0; i < funcDefinedParameters.length; i++) {
811
- const tmpFuncArg = funcDefinedParameters[i];
812
-
813
- if (i < passedInParameters.length) {
814
- const tmpPassedInArgs = passedInParameters[i];
815
-
816
- if (tmpPassedInArgs[0] === 'position') {
817
- // If value is passed in as function parameter, then
818
- // use it in the scope.
819
- const variableName = tmpFuncArg[0];
820
- executor.print(
821
- 'set variable in scope, var name: ',
822
- variableName,
823
- );
824
- executor.scope.variables.set(
825
- variableName,
826
- tmpPassedInArgs[2],
827
- );
828
-
829
- if (tmpPassedInArgs[2] instanceof ClassComponent) {
830
- const component = tmpPassedInArgs[2];
831
-
832
- // Add the component nets into the local scope
833
- for(const [pinNumber, net] of component.pinNets){
834
- executor.scope.setNet(component, pinNumber, net);
835
- }
836
- }
837
- }
838
- } else if (tmpFuncArg.length === 2) {
839
- // Value was not provided to function, but a default
840
- // value is provided.
841
- const variableName = tmpFuncArg[0];
842
- const defaultValue = tmpFuncArg[1];
843
- executor.print(
844
- 'set variable in scope, var name: ',
845
- variableName,
846
- );
847
- executor.scope.variables.set(
848
- variableName, defaultValue,
849
- );
850
- } else {
851
- throw `Invalid arguments for function '${functionName}', got: `
852
- + passedInParameters;
853
- }
854
- }
855
- }
856
-
857
- visitFunction_return_expr(ctx: Function_return_exprContext): ComplexType {
858
- const executor = this.getExecutor();
859
- executor.print('return from function');
860
- const returnValue = this.visit(ctx.data_expr()) as ComplexType;
861
-
862
- executor.stopFurtherExpressions = true;
863
- executor.returnValue = returnValue;
864
-
865
- return returnValue;
866
- }
867
-
868
- visitAtom_expr(ctx: Atom_exprContext): ReferenceType {
869
- const executor = this.getExecutor();
870
-
871
- const atomId = ctx.ID().getText();
872
-
873
- let passedNetNamespace = null; // Assumed empty by default
874
-
875
- if (ctx.net_namespace_expr()){
876
- passedNetNamespace = this.visit(ctx.net_namespace_expr());
877
- }
878
-
879
- let currentReference: ReferenceType;
880
-
881
- // Check if it is hardcoded values, like the pin types.
882
- if (this.pinTypesList.indexOf(atomId) !== -1) {
883
- // Not sure if just returning the string is enough...
884
- currentReference = {
885
- found: true,
886
- value: atomId
887
- }
888
- } else {
889
- currentReference = executor.resolveVariable(
890
- this.executionStack, atomId);
891
- }
892
-
893
- if (currentReference.found && currentReference.type === 'instance') {
894
- const tmpComponent = currentReference.value as ClassComponent;
895
-
896
- // Copy the nets into the local net
897
- for (const [pinId, net] of tmpComponent.pinNets) {
898
- executor.scope.setNet(tmpComponent, pinId, net);
899
- }
900
- }
901
-
902
- if (ctx.trailer_expr_list().length > 0) {
903
- // Resolve all elements in the trailer expression list
904
-
905
- if (!currentReference.found) {
906
- throw "Could not find reference! " + atomId;
907
- }
908
-
909
- currentReference.trailers = [];
910
-
911
- ctx.trailer_expr_list().forEach(item => {
912
- const itemValue = item.getText();
913
- if (item.OPEN_PAREN() && item.CLOSE_PAREN()) {
914
- let parameters: CallableParameter[] = [];
915
- if (item.parameters()) {
916
- parameters = this.visit(item.parameters());
917
- }
918
-
919
- const useNetNamespace = this.getNetNamespace(
920
- executor.netNamespace,
921
- passedNetNamespace,
922
- )
923
-
924
- const [, functionResult] =
925
- executor.callFunction(
926
- currentReference.name,
927
- parameters,
928
- this.executionStack,
929
- useNetNamespace);
930
-
931
- currentReference = {
932
- found: true,
933
- value: functionResult,
934
- type: (functionResult instanceof ClassComponent) ?
935
- 'instance' : 'value',
936
- }
937
-
938
- } else {
939
- currentReference.trailers.push(itemValue);
940
- }
941
- });
942
- }
943
-
944
- return currentReference;
945
- }
946
-
947
- visitPin_select_expr2(ctx: Pin_select_expr2Context): string | number {
948
- if (ctx.STRING_VALUE()) {
949
- return this.prepareStringValue(ctx.STRING_VALUE().getText());
950
- } else if (ctx.INTEGER_VALUE()) {
951
- return Number(ctx.INTEGER_VALUE().getText());
952
- }
953
- }
954
-
955
- visitAt_block_pin_expr(ctx: At_block_pin_exprContext): ComponentPin {
956
- const atPin: number | string = this.visit(ctx.pin_select_expr2());
957
-
958
- const executor = this.getExecutor();
959
-
960
- const currentComponent = executor.scope.currentComponent;
961
- const currentPin = executor.scope.currentPin;
962
-
963
- executor.atComponent(currentComponent, atPin, {
964
- addSequence: true
965
- });
966
-
967
- executor.print('at block pin expressions');
968
-
969
- if (ctx.at_block_pin_expression_simple()) {
970
- this.visit(ctx.at_block_pin_expression_simple());
971
- } else if (ctx.at_block_pin_expression_complex()) {
972
- this.visit(ctx.at_block_pin_expression_complex());
973
- }
974
-
975
- executor.print('end at block pin expressions');
976
-
977
- // Go back to the original position
978
- return executor.atComponent(currentComponent, currentPin);
979
- }
980
-
981
- visitAt_block(ctx: At_blockContext): ComponentPin {
982
- const executor = this.getExecutor();
983
- executor.print('entering at block');
984
-
985
- this.visit(ctx.at_component_expr());
986
-
987
- const currentComponent = executor.scope.currentComponent;
988
- const currentPin = executor.scope.currentPin;
989
-
990
- executor.scope.indentLevel += 1;
991
-
992
- ctx.at_block_expressions_list().forEach(expression => {
993
- this.visit(expression);
994
- });
995
-
996
- executor.scope.indentLevel -= 1;
997
-
998
- // Once all done, then restore
999
- executor.scope.currentComponent = currentComponent;
1000
- executor.scope.currentPin = currentPin;
1001
-
1002
- executor.print('leaving at block');
1003
-
1004
- return executor.getCurrentPoint();
1005
- }
1006
-
1007
- visitAt_block_pin_expression_simple(ctx: At_block_pin_expression_simpleContext): void {
1008
- if (ctx.expression()) {
1009
- // Handle any expressions within
1010
- this.visit(ctx.expression());
1011
- } else if (ctx.NOT_CONNECTED()) {
1012
- // Do nothing
1013
- return;
1014
- }
1015
- }
1016
-
1017
- visitAt_block_pin_expression_complex(ctx: At_block_pin_expression_complexContext): ComponentPin {
1018
- ctx.expression_list().forEach(item => {
1019
- this.visit(item);
1020
- })
1021
-
1022
- return this.getExecutor().getCurrentPoint();
1023
- }
1024
-
1025
- visitWire_expr(ctx: Wire_exprContext): void {
1026
- const segments: [string, number?][] = [];
1027
-
1028
- // Ignore 'wire'
1029
- const parts = ctx.children.slice(1);
1030
-
1031
- for (let i = 0; i < parts.length; i++) {
1032
- const textValue = parts[i].getText();
1033
-
1034
- if (this.acceptedDirections.indexOf(textValue) !== -1) {
1035
- // If a direction is specified, then the value
1036
- // must also be specified, otherwise throw an error
1037
- const segment: [string, number?] = [textValue];
1038
-
1039
- let skipNext = false;
1040
- let invalidValue = true;
1041
-
1042
- if (i + 1 < parts.length) {
1043
- const nextValue = parts[i + 1].getText();
1044
- const nextValueNumber = Number(nextValue);
1045
- if (!isNaN(nextValueNumber)) {
1046
- invalidValue = false;
1047
- segment.push(nextValueNumber);
1048
- skipNext = true;
1049
- }
1050
- }
1051
-
1052
- if (invalidValue) {
1053
- throw `Invalid value provided for direction ${textValue} in wire`;
1054
- }
1055
-
1056
- segments.push(segment);
1057
-
1058
- if (skipNext) {
1059
- i += 1;
1060
- }
1061
- } else if (textValue === "auto" || textValue === "auto_") {
1062
- // Two different auto modes to decide how to form the
1063
- // connecting wire
1064
- segments.push([textValue]);
1065
- }
1066
- }
1067
-
1068
- this.getExecutor().addWire(segments);
1069
- }
1070
-
1071
- visitPoint_expr(ctx: Point_exprContext): ComponentPin {
1072
- const ID = ctx.ID();
1073
- return this.getExecutor().addPoint(ID.getText());
1074
- }
1075
-
1076
- visitImport_expr(ctx: Import_exprContext): void {
1077
- const ID = ctx.ID().toString(); // filename
1078
- this.print('import', ID);
1079
- const {hasError,hasParseError} = this.onImportFile(this, ID);
1080
-
1081
- if (hasError || hasParseError){
1082
- this.print('import', ID, 'failed');
1083
- throw `import ${ID} failed`;
1084
- }
1085
-
1086
- this.print('done import', ID);
1087
- }
1088
-
1089
- visitProperty_set_expr(ctx: Property_set_exprContext): void {
1090
- const result = this.visit(ctx.data_expr());
1091
-
1092
- // To check if this works
1093
- const resolvedProperty = this.visit(ctx.atom_expr());
1094
-
1095
- // TODO: check if this works correctly
1096
- this.getExecutor().setProperty(resolvedProperty, result);
1097
- }
1098
-
1099
- visitDouble_dot_property_set_expr(ctx: Double_dot_property_set_exprContext) {
1100
- const result = this.visit(ctx.data_expr());
1101
- const propertyName = ctx.ID().getText();
1102
- this.getExecutor().setProperty('..' + propertyName, result);
1103
- }
1104
-
1105
- visitRoundedBracketsExpr(ctx: RoundedBracketsExprContext) {
1106
- return this.visit(ctx.data_expr());
1107
- }
1108
-
1109
- visitFrame_expr(ctx: Frame_exprContext): void {
1110
- const frameId = this.getExecutor().enterFrame();
1111
- this.runExpressions(this.getExecutor(), ctx.expression_list());
1112
- this.getExecutor().exitFrame(frameId);
1113
- }
1114
-
1115
- visitNet_namespace_expr(ctx: Net_namespace_exprContext): string {
1116
- let dataValue: ComplexType = null;
1117
-
1118
- let netNamespace = null;
1119
- const hasPlus = ctx.Addition();
1120
-
1121
- if (ctx.data_expr()) {
1122
- dataValue = this.visit(ctx.data_expr()) as ComplexType;
1123
-
1124
- if (dataValue instanceof UndeclaredReference) {
1125
- netNamespace = "/" + dataValue.reference.name;
1126
- } else if (typeof dataValue === "string") {
1127
- netNamespace = "/" + dataValue;
1128
- } else {
1129
- throw "Failed to resolve net namespace value";
1130
- }
1131
-
1132
- } else {
1133
- // If no net namespace specified, then the global namespace
1134
- // is assumed.
1135
- netNamespace = "/";
1136
- }
1137
-
1138
- return (hasPlus ? "+" : "") + netNamespace;
1139
- }
1140
-
1141
- pinTypes = [
1142
- PinTypes.Any,
1143
- PinTypes.IO,
1144
- PinTypes.Input,
1145
- PinTypes.Output,
1146
- PinTypes.Power,
1147
- ];
1148
-
1149
- createImportFileHandler(directory: string, defaultLibsPath: string):
1150
- ((visitor: MainVisitor, importPath: string) =>
1151
- { hasError: boolean, hasParseError: boolean, pathExists: boolean }) {
1152
-
1153
- return (visitor: MainVisitor, importPath: string) => {
1154
- // Check if different files exist first
1155
- let importResult: {
1156
- hasError: boolean,
1157
- hasParseError: boolean,
1158
- pathExists: boolean,
1159
- };
1160
-
1161
- importResult = this.importLib(visitor, directory, importPath);
1162
-
1163
- if (!importResult.pathExists && importPath == 'lib') {
1164
- // Load default path
1165
- importResult = this.importLib(visitor, defaultLibsPath, importPath);
1166
- }
1167
-
1168
- return importResult;
1169
- }
1170
- }
1171
-
1172
- private importLib(visitor: MainVisitor, directory: string, filename: string): {hasError: boolean, hasParseError: boolean, pathExists: boolean} {
1173
- const tmpFilePath = join(directory, filename + ".cst");
1174
- visitor.print('importing path:', tmpFilePath);
1175
- let pathExists = false;
1176
-
1177
- let fileData: string = null;
1178
-
1179
- try {
1180
- fileData = readFileSync(tmpFilePath, { encoding: 'utf8' });
1181
- pathExists = true;
1182
- } catch (err) {
1183
- pathExists = false;
1184
- }
1185
-
1186
- try {
1187
- if (pathExists){
1188
- visitor.print('done reading imported file data');
1189
-
1190
- const { hasError, hasParseError } =
1191
- parseFileWithVisitor(visitor, fileData);
1192
-
1193
- return { hasError, hasParseError, pathExists }
1194
- }
1195
- } catch (err) {
1196
- visitor.print('Failed to import file: ', err.message);
1197
- }
1198
-
1199
- return {
1200
- hasError: true,
1201
- hasParseError: true,
1202
- pathExists,
1203
- }
1204
- }
1205
-
1206
- private parseCreateComponentPins(
1207
- pinData: number | Map<string, any>,
1208
- ): PinDefinition[] {
1209
- const pins: PinDefinition[] = [];
1210
-
1211
- if (typeof pinData === 'number') {
1212
- const lastPin = pinData;
1213
- for (let i = 0; i < lastPin; i++) {
1214
- const pinId = i + 1;
1215
- pins.push(
1216
- new PinDefinition(pinId, PinIdType.Int, pinId.toString()),
1217
- );
1218
- }
1219
- } else if (pinData instanceof Map) {
1220
- for (const [pinId, pinDef] of pinData) {
1221
- let pinIdType = PinIdType.Int;
1222
- let pinType = PinTypes.Any;
1223
- let pinName: string | null = null;
1224
- let altPinNames: string[] = [];
1225
-
1226
- if (typeof pinId === 'string') {
1227
- pinIdType = PinIdType.Str;
1228
- }
1229
-
1230
- if (Array.isArray(pinDef)) {
1231
- const firstValue = pinDef[0];
1232
-
1233
- // Check if firstValue matches a pin type
1234
- if (this.pinTypes.indexOf(firstValue) !== -1) {
1235
- // First value matches a pin type
1236
- pinType = firstValue;
1237
- pinName = pinDef[1];
1238
-
1239
- if (pinDef.length > 2) {
1240
- altPinNames = pinDef.slice(2);
1241
- }
1242
- } else {
1243
- pinName = pinDef[0];
1244
- if (pinDef.length > 1) {
1245
- altPinNames = pinDef.slice(1);
1246
- }
1247
- }
1248
- } else {
1249
- pinName = pinDef;
1250
- }
1251
-
1252
- pins.push(
1253
- new PinDefinition(
1254
- pinId,
1255
- pinIdType,
1256
- pinName,
1257
- pinType,
1258
- altPinNames,
1259
- ),
1260
- );
1261
- }
1262
- }
1263
-
1264
- return pins;
1265
- }
1266
-
1267
- private parseCreateComponentParams(
1268
- params: Map<string, any>,
1269
- ): ParamDefinition[] {
1270
- const result = [];
1271
- if (params) {
1272
- for (const [key, value] of params) {
1273
- result.push(new ParamDefinition(key, value));
1274
- }
1275
- }
1276
-
1277
- return result;
1278
- }
1279
-
1280
- private prepareStringValue(value: string): string {
1281
- return value.slice(1, value.length - 1);
1282
- }
1283
-
1284
- print(...params: any[]): void {
1285
- const indentOutput = ''.padStart(this.indentLevel * 4, ' ');
1286
- const indentLevelText = this.indentLevel.toString().padStart(3, ' ');
1287
-
1288
- const args = ['[' + indentLevelText + ']', indentOutput, ...params];
1289
-
1290
- this.logger.add(args.join(' '));
1291
-
1292
- if (!this.silent){
1293
- console.log.apply(null, args);
1294
- }
1295
- }
1296
-
1297
- printNets(): void {
1298
- this.getExecutor().scope.printNets();
1299
- }
1300
-
1301
- dumpNets(): ComponentPinNet[] {
1302
- return this.getExecutor().scope.dumpNets();
1303
- }
1304
-
1305
- dumpUniqueNets(): Net[] {
1306
- const nets = this.getExecutor().scope.getNets();
1307
- return nets.reduce((accum, [, , net]) => {
1308
- accum.push(net);
1309
- return accum;
1310
- }, [] as Net[])
1311
- }
1312
-
1313
- dumpVariables(): Map<string, any> {
1314
- return this.getExecutor().scope.variables;
1315
- }
1316
-
1317
- dumpInstances(): Map<string, ClassComponent> {
1318
- return this.getExecutor().scope.instances;
1319
- }
1320
-
1321
- dump2() {
1322
- const instances = this.getExecutor().scope.instances;
1323
- const items = [];
1324
-
1325
- for (const [instanceName, instance] of instances) {
1326
- if (instance.assignedRefDes === null) {
1327
- continue;
1328
- }
1329
-
1330
- const pinNets = this.resolveNets(
1331
- this.getExecutor().scope,
1332
- instance,
1333
- );
1334
-
1335
- const componentItem = {
1336
- name: instanceName,
1337
- refdes: instance.assignedRefDes,
1338
- pins: {},
1339
- };
1340
-
1341
- pinNets.forEach((item) => {
1342
- componentItem.pins[item.pin.id] = item.netName;
1343
- });
1344
-
1345
- items.push(componentItem);
1346
- }
1347
-
1348
- return items;
1349
- }
1350
-
1351
- getNetList(): NetListItem[] {
1352
- const netlist: NetListItem[] = [];
1353
-
1354
- const instances = this.getExecutor().scope.instances;
1355
- for (const [instanceName, instance] of instances) {
1356
- const pinNets = this.resolveNets(
1357
- this.getExecutor().scope,
1358
- instance,
1359
- );
1360
-
1361
- const componentItem = {
1362
- instanceName,
1363
- instance,
1364
- pins: {},
1365
- };
1366
- pinNets.forEach((item) => {
1367
- componentItem.pins[item.pin.id] = {
1368
- netName: item.netName,
1369
- netBaseName: item.netBaseName
1370
- }
1371
- });
1372
-
1373
- netlist.push(componentItem)
1374
- }
1375
-
1376
- return netlist;
1377
- }
1378
-
1379
- getGraph() {
1380
- const executor = this.getExecutor();
1381
- const sequence = executor.scope.sequence;
1382
- const nets = executor.scope.getNets();
1383
-
1384
- return {
1385
- sequence,
1386
- nets,
1387
- components: Array.from(executor.scope.instances.values())
1388
- };
1389
- }
1390
-
1391
- annotateComponents(): void {
1392
- this.print('===== annotate components =====');
1393
-
1394
- const annotater = new ComponentAnnotater();
1395
- const instances = this.getExecutor().scope.instances;
1396
-
1397
- const toAnnotate:ClassComponent[] = [];
1398
-
1399
- for (const [, instance] of instances) {
1400
- if (instance.assignedRefDes === null) {
1401
- if (instance.typeProp === ComponentTypes.label ||
1402
- instance.typeProp === ComponentTypes.net ||
1403
- instance.typeProp === ComponentTypes.point) {
1404
- continue;
1405
- }
1406
-
1407
- if (instance.typeProp === null){
1408
- this.print('Instance has no type:', instance.instanceName, ' assuming connector');
1409
- instance.typeProp = 'conn';
1410
- }
1411
-
1412
- if (instance.parameters.has('refdes')) {
1413
- const refdes = instance.parameters.get('refdes') as string;
1414
-
1415
- if (refdes) {
1416
- instance.assignedRefDes = refdes;
1417
- annotater.trackRefDes(refdes);
1418
- this.print(refdes, '-', instance.instanceName);
1419
- continue;
1420
- }
1421
- }
1422
-
1423
- toAnnotate.push(instance);
1424
- }
1425
- }
1426
-
1427
- toAnnotate.forEach(instance => {
1428
- const newRefDes = annotater.getAnnotation(instance.typeProp);
1429
-
1430
- if (newRefDes !== null) {
1431
- instance.assignedRefDes = newRefDes;
1432
- this.print(newRefDes, '-', instance.instanceName);
1433
- } else {
1434
- this.print('Failed to annotate:', instance.instanceName);
1435
- }
1436
- });
1437
-
1438
- this.print('===== annotate done =====');
1439
- this.print('');
1440
- }
1441
-
1442
- private resolveNets(
1443
- scope: ExecutionScope,
1444
- instance: ClassComponent,
1445
- ): { pin: PinDefinition; netName: string, netBaseName: string }[] {
1446
- // Returns the list of nets that the component pins are
1447
- // connected to.
1448
-
1449
- const result = [];
1450
-
1451
- for (const [pinId, pin] of instance.pins) {
1452
- let netName = NoNetText;
1453
- let netBaseName = NoNetText;
1454
-
1455
- if (scope.hasNet(instance, pinId)) {
1456
- const netObject = scope.getNet(instance, pinId);
1457
- netName = netObject.namespace + netObject.name;
1458
- netBaseName = netObject.baseName;
1459
- }
1460
-
1461
- result.push({
1462
- pin: pin,
1463
- netName: netName,
1464
- netBaseName,
1465
- });
1466
- }
1467
-
1468
- return result;
1469
- }
1470
-
1471
- private setComponentOrientation(component: ClassComponent, pin: number,
1472
- orientation: string): void {
1473
-
1474
- // This can be used to modify the orientation of the component.
1475
- if (this.acceptedDirections.indexOf(orientation) !== -1) {
1476
- // a valid direction
1477
- component.setParam('_addDirection', orientation);
1478
- component.setParam('_addPin', pin);
1479
- } else {
1480
- throw "Invalid modifier for orientation";
1481
- }
1482
- }
1483
-
1484
- private getPropertyExprList(items: Property_exprContext[]): Map<string, any>{
1485
- const properties = new Map<string, any>();
1486
-
1487
- items.forEach((item) => {
1488
- const result: Map<string, any> = this.visit(item); // Map should be returned
1489
-
1490
- for (const [key, value] of result) {
1491
- properties.set(key, value);
1492
- }
1493
- });
1494
-
1495
- return properties;
1496
- }
1497
-
1498
- private runExpressions(executor: ExecutionContext,
1499
- expressions: ExpressionContext[] | Function_exprContext[]): ComplexType {
1500
-
1501
- let returnValue: ComplexType | null = null;
1502
-
1503
- // Execute the expressions within the context
1504
- for (let i = 0; i < expressions.length; i++) {
1505
- const expr = expressions[i];
1506
-
1507
- // The correct executor MUST be on the top/end of the stack!
1508
- this.visit(expr);
1509
-
1510
- // If this flag is set, then do not parse anything further!
1511
- if (executor.stopFurtherExpressions) {
1512
- returnValue = executor.returnValue;
1513
- break;
1514
- }
1515
- }
1516
-
1517
- return returnValue;
1518
- }
1519
-
1520
- private checkNetNamespaceIncludes(
1521
- targetNetName: string, targetNamespaceParts: string[], net: Net): boolean {
1522
-
1523
- // Returns true if the namespace of <net> is a fit for
1524
- // the target namespace supplied
1525
-
1526
- if (net.name === targetNetName) {
1527
- // split the net namespace into parts for comparison.
1528
- // For true to be returned, all parts in net must also be in
1529
- // targetNamespaceParts.
1530
- const netNamespaceParts = this.getNamespaceParts(net.namespace);
1531
- this.print('check namespace', targetNetName,
1532
- targetNamespaceParts, netNamespaceParts);
1533
-
1534
- let matches = 0;
1535
- for (let i = 0; i < netNamespaceParts.length; i++) {
1536
- if (netNamespaceParts[i] === targetNamespaceParts[i]) {
1537
- matches++;
1538
- }
1539
- }
1540
-
1541
- if (matches === netNamespaceParts.length) {
1542
- return true;
1543
- }
1544
- }
1545
-
1546
- return false;
1547
- }
1548
-
1549
- private getNamespaceParts(namespace: string): string[] {
1550
- return namespace.split(".").slice(0, -2);
1551
- }
1552
-
1553
- private setupPrintFunction(context: ExecutionContext): void {
1554
- context.createFunction('print', (params) => {
1555
- // Only accept position params
1556
- const items = params.map(([, , value]) => {
1557
- return value
1558
- });
1559
-
1560
- if (this.printToConsole) {
1561
- console.log('::', ...items);
1562
- }
1563
- this.printStream.push(...items);
1564
-
1565
- return [this, null];
1566
- });
1567
- }
1568
-
1569
- private getNetNamespace(executorNetNamespace: string,
1570
- passedNetNamespace: string | null): string {
1571
-
1572
- let result = executorNetNamespace;
1573
-
1574
- if (passedNetNamespace !== null && passedNetNamespace.length > 0) {
1575
- // Either user specified '/' or '/_' to indicate the global
1576
- // net namespace
1577
- if (passedNetNamespace === '/' || passedNetNamespace === '_') {
1578
- result = '';
1579
- } else if (passedNetNamespace[0] === '+') {
1580
- if (executorNetNamespace === '/') {
1581
- result = passedNetNamespace.slice(1)
1582
- } else {
1583
- result = executorNetNamespace + passedNetNamespace.slice(2);
1584
- }
1585
- } else {
1586
- result = passedNetNamespace;
1587
- }
1588
-
1589
- result = result + '/';
1590
- }
1591
-
1592
- return result;
1593
- }
1594
- }
1595
-
1596
-
1597
- const ComponentRefDesPrefixes = {
1598
- 'res': 'R',
1599
- 'cap': 'C',
1600
- 'ind': 'L',
1601
- 'diode': 'D',
1602
- 'conn': 'J',
1603
- 'transistor': 'Q',
1604
- 'relay': 'K',
1605
- 'ic': 'U',
1606
-
1607
- '?': '?',
1608
- }
1609
-
1610
- class ComponentAnnotater {
1611
-
1612
- counter = {};
1613
-
1614
- existingRefDes: string[] = [];
1615
-
1616
- constructor(){
1617
- for(const key in ComponentRefDesPrefixes){
1618
- this.counter[key] = 1;
1619
- }
1620
-
1621
- this.counter['?'] = 1;
1622
- }
1623
-
1624
- getAnnotation(type: string): string | null {
1625
-
1626
- // If type is unknown, then allow it to define a new range
1627
- if (this.counter[type] === undefined && type.length <= 2) {
1628
- for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
1629
- if (value === type) {
1630
- throw "Refdes prefix is already in use!";
1631
- }
1632
- }
1633
-
1634
- if (ComponentRefDesPrefixes[type] === undefined) {
1635
- // Define new type and start counting
1636
- ComponentRefDesPrefixes[type] = type;
1637
- this.counter[type] = 1;
1638
- }
1639
- }
1640
-
1641
- let attempts = 100;
1642
- let proposedName: string;
1643
-
1644
- while (attempts >= 0) {
1645
- proposedName = ComponentRefDesPrefixes[type] + this.counter[type];
1646
- this.counter[type]++;
1647
-
1648
- if (this.existingRefDes.indexOf(proposedName) === -1) {
1649
- break;
1650
- }
1651
- attempts--;
1652
- }
1653
-
1654
- if (attempts === 0) {
1655
- throw "Annotation failed!";
1656
- }
1657
-
1658
- return proposedName;
1659
- }
1660
-
1661
- trackRefDes(name: string): void {
1662
- this.existingRefDes.push(name);
1663
- }
1664
- }
1665
-
1666
- export type NetListItem = {
1667
- instanceName: string,
1668
- instance: ClassComponent,
1669
- pins: { [key: string | number]: string },
1670
- }
1671
-
1672
- export class VisitorExecutionException {
1673
-
1674
- errorMessage: string;
1675
- context: ParserRuleContext;
1676
-
1677
- constructor(context: ParserRuleContext, errorMessage: string){
1678
- this.errorMessage = errorMessage;
1679
- this.context = context;
1680
- }
1681
-
1682
- print(scriptData: string): void {
1683
- const startPoint = this.context.start.start;
1684
- const endPoint = this.context.stop.stop + 1;
1685
-
1686
- console.log('Error at line ' +
1687
- this.context.start.line + "," + this.context.start.column + ": "
1688
- + scriptData.slice(startPoint, endPoint) + " - " + this.errorMessage);
1689
-
1690
- }
1691
- }