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.
- package/dist/cjs/BaseVisitor.js +487 -0
- package/dist/cjs/SemanticTokenVisitor.js +218 -0
- package/dist/cjs/SymbolValidatorVisitor.js +233 -0
- package/dist/cjs/antlr/CircuitScriptLexer.js +302 -0
- package/dist/cjs/antlr/CircuitScriptParser.js +5128 -0
- package/dist/cjs/antlr/CircuitScriptVisitor.js +7 -0
- package/dist/cjs/draw_symbols.js +819 -0
- package/dist/cjs/execute.js +778 -0
- package/{src/export.ts → dist/cjs/export.js} +34 -56
- package/dist/cjs/fonts.js +4 -0
- package/dist/cjs/geometry.js +450 -0
- package/dist/cjs/globals.js +60 -0
- package/dist/cjs/helpers.js +269 -0
- package/dist/cjs/index.js +31 -0
- package/{src/layout.ts → dist/cjs/layout.js} +421 -1002
- package/dist/cjs/lexer.js +111 -0
- package/dist/cjs/logger.js +17 -0
- package/dist/cjs/main.js +82 -0
- package/dist/cjs/objects/ClassComponent.js +145 -0
- package/dist/cjs/objects/ExecutionScope.js +135 -0
- package/dist/cjs/objects/Frame.js +22 -0
- package/{src/objects/Net.ts → dist/cjs/objects/Net.js} +9 -24
- package/dist/cjs/objects/ParamDefinition.js +42 -0
- package/dist/cjs/objects/PinDefinition.js +31 -0
- package/dist/cjs/objects/PinTypes.js +11 -0
- package/dist/cjs/objects/Wire.js +9 -0
- package/dist/cjs/objects/types.js +15 -0
- package/dist/cjs/parser.js +70 -0
- package/dist/cjs/regenerate-tests.js +23 -0
- package/dist/cjs/render.js +155 -0
- package/{src/server.ts → dist/cjs/server.js} +15 -21
- package/dist/cjs/sizing.js +105 -0
- package/{src/utils.ts → dist/cjs/utils.js} +25 -35
- package/dist/cjs/validate.js +81 -0
- package/dist/cjs/visitor.js +844 -0
- package/dist/esm/BaseVisitor.mjs +488 -0
- package/dist/esm/SemanticTokenVisitor.mjs +215 -0
- package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
- package/dist/esm/antlr/CircuitScriptLexer.mjs +276 -0
- package/dist/esm/antlr/CircuitScriptParser.mjs +5038 -0
- package/{build/src/antlr/CircuitScriptVisitor.js → dist/esm/antlr/CircuitScriptVisitor.mjs} +8 -3
- package/{build/src/draw_symbols.js → dist/esm/draw_symbols.mjs} +78 -33
- package/{build/src/execute.js → dist/esm/execute.mjs} +59 -60
- package/{build/src/export.js → dist/esm/export.mjs} +2 -2
- package/{build/src/geometry.js → dist/esm/geometry.mjs} +31 -15
- package/dist/esm/helpers.mjs +252 -0
- package/dist/esm/index.mjs +15 -0
- package/{build/src/layout.js → dist/esm/layout.mjs} +19 -11
- package/{build/src/lexer.js → dist/esm/lexer.mjs} +10 -10
- package/{build/src/main.js → dist/esm/main.mjs} +9 -14
- package/{build/src/objects/ClassComponent.js → dist/esm/objects/ClassComponent.mjs} +6 -3
- package/{build/src/objects/ExecutionScope.js → dist/esm/objects/ExecutionScope.mjs} +1 -0
- package/{build/src/objects/PinDefinition.js → dist/esm/objects/PinDefinition.mjs} +1 -1
- package/dist/esm/objects/types.mjs +12 -0
- package/dist/esm/parser.mjs +64 -0
- package/{build/src/regenerate-tests.js → dist/esm/regenerate-tests.mjs} +1 -1
- package/{build/src/render.js → dist/esm/render.mjs} +7 -24
- package/{build/src/sizing.js → dist/esm/sizing.mjs} +22 -8
- package/{src/main.ts → dist/esm/validate.mjs} +31 -62
- package/dist/esm/visitor.mjs +838 -0
- package/dist/types/BaseVisitor.d.ts +69 -0
- package/dist/types/SemanticTokenVisitor.d.ts +36 -0
- package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
- package/{build/src → dist/types}/antlr/CircuitScriptLexer.d.ts +28 -27
- package/dist/types/antlr/CircuitScriptParser.d.ts +719 -0
- package/{build/src → dist/types}/antlr/CircuitScriptVisitor.d.ts +69 -59
- package/{build/src → dist/types}/draw_symbols.d.ts +11 -2
- package/{build/src → dist/types}/execute.d.ts +6 -9
- package/{build/src → dist/types}/geometry.d.ts +5 -1
- package/dist/types/helpers.d.ts +40 -0
- package/dist/types/index.d.ts +15 -0
- package/{build/src → dist/types}/layout.d.ts +10 -10
- package/{build/src → dist/types}/lexer.d.ts +2 -2
- package/{build/src → dist/types}/objects/ClassComponent.d.ts +2 -2
- package/{build/src → dist/types}/objects/ExecutionScope.d.ts +4 -1
- package/{build/src → dist/types}/objects/PinDefinition.d.ts +1 -1
- package/{build/src → dist/types}/objects/types.d.ts +5 -0
- package/dist/types/parser.d.ts +25 -0
- package/{build/src → dist/types}/render.d.ts +1 -1
- package/{build/src → dist/types}/sizing.d.ts +3 -1
- package/dist/types/validate.d.ts +2 -0
- package/dist/types/visitor.d.ts +80 -0
- package/libs/lib.cst +0 -2
- package/package.json +38 -15
- package/.editorconfig +0 -15
- package/.eslintignore +0 -1
- package/.eslintrc.json +0 -27
- package/.gitlab-ci.yml +0 -81
- package/.prettierignore +0 -8
- package/.prettierrc +0 -16
- package/__tests__/expectedResults.ts +0 -657
- package/__tests__/helpers.ts +0 -82
- package/__tests__/parseScripts.ts +0 -593
- package/__tests__/renderData/script1.cst +0 -58
- package/__tests__/renderData/script1.cst.svg +0 -1
- package/__tests__/renderData/script2.cst +0 -16
- package/__tests__/renderData/script2.cst.svg +0 -1
- package/__tests__/renderData/script3.cst +0 -30
- package/__tests__/renderData/script3.cst.svg +0 -1
- package/__tests__/renderData/script4.cst +0 -54
- package/__tests__/renderData/script4.cst.svg +0 -1
- package/__tests__/renderData/script5.cst +0 -23
- package/__tests__/renderData/script5.cst.svg +0 -1
- package/__tests__/renderData/script6.cst +0 -28
- package/__tests__/renderData/script6.cst.svg +0 -1
- package/__tests__/renderData/script7.cst +0 -26
- package/__tests__/renderData/script7.cst.svg +0 -1
- package/__tests__/renderData/script8.cst +0 -37
- package/__tests__/renderData/script8.cst.svg +0 -1
- package/__tests__/testCLI.ts +0 -68
- package/__tests__/testMathOps.ts +0 -36
- package/__tests__/testMergeWires.ts +0 -141
- package/__tests__/testParse.ts +0 -263
- package/__tests__/testRender.ts +0 -38
- package/build/src/antlr/CircuitScriptLexer.js +0 -287
- package/build/src/antlr/CircuitScriptParser.d.ts +0 -674
- package/build/src/antlr/CircuitScriptParser.js +0 -4841
- package/build/src/helpers.d.ts +0 -1
- package/build/src/helpers.js +0 -73
- package/build/src/objects/types.js +0 -6
- package/build/src/parser.js +0 -69
- package/build/src/visitor.d.ts +0 -133
- package/build/src/visitor.js +0 -1154
- package/documentation.md +0 -238
- package/examples/example_arduino_uno.cst +0 -1146
- package/examples/example_garden_pump.cst +0 -567
- package/examples/lib.cst +0 -185
- package/jest.config.js +0 -23
- package/refresh.html +0 -42
- package/server.cjs +0 -50
- package/src/antlr/CircuitScript.g4 +0 -209
- package/src/antlr/CircuitScriptLexer.ts +0 -317
- package/src/antlr/CircuitScriptParser.ts +0 -4979
- package/src/antlr/CircuitScriptVisitor.ts +0 -420
- package/src/draw_symbols.ts +0 -1085
- package/src/execute.ts +0 -1227
- package/src/fonts.ts +0 -1
- package/src/geometry.ts +0 -638
- package/src/globals.ts +0 -67
- package/src/helpers.ts +0 -114
- package/src/lexer.ts +0 -151
- package/src/logger.ts +0 -17
- package/src/objects/ClassComponent.ts +0 -223
- package/src/objects/ExecutionScope.ts +0 -201
- package/src/objects/Frame.ts +0 -20
- package/src/objects/ParamDefinition.ts +0 -49
- package/src/objects/PinDefinition.ts +0 -49
- package/src/objects/PinTypes.ts +0 -7
- package/src/objects/Wire.ts +0 -19
- package/src/objects/types.ts +0 -66
- package/src/parser.ts +0 -106
- package/src/regenerate-tests.ts +0 -25
- package/src/render.ts +0 -260
- package/src/sizing.ts +0 -96
- package/src/visitor.ts +0 -1691
- package/tsconfig.json +0 -27
- package/tsconfig.release.json +0 -8
- /package/{build/src/fonts.js → dist/esm/fonts.mjs} +0 -0
- /package/{build/src/globals.js → dist/esm/globals.mjs} +0 -0
- /package/{build/src/logger.js → dist/esm/logger.mjs} +0 -0
- /package/{build/src/objects/Frame.js → dist/esm/objects/Frame.mjs} +0 -0
- /package/{build/src/objects/Net.js → dist/esm/objects/Net.mjs} +0 -0
- /package/{build/src/objects/ParamDefinition.js → dist/esm/objects/ParamDefinition.mjs} +0 -0
- /package/{build/src/objects/PinTypes.js → dist/esm/objects/PinTypes.mjs} +0 -0
- /package/{build/src/objects/Wire.js → dist/esm/objects/Wire.mjs} +0 -0
- /package/{build/src/server.js → dist/esm/server.mjs} +0 -0
- /package/{build/src/utils.js → dist/esm/utils.mjs} +0 -0
- /package/{build/src → dist/types}/export.d.ts +0 -0
- /package/{build/src → dist/types}/fonts.d.ts +0 -0
- /package/{build/src → dist/types}/globals.d.ts +0 -0
- /package/{build/src → dist/types}/logger.d.ts +0 -0
- /package/{build/src → dist/types}/main.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Frame.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Net.d.ts +0 -0
- /package/{build/src → dist/types}/objects/ParamDefinition.d.ts +0 -0
- /package/{build/src → dist/types}/objects/PinTypes.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Wire.d.ts +0 -0
- /package/{build/src → dist/types}/regenerate-tests.d.ts +0 -0
- /package/{build/src → dist/types}/server.d.ts +0 -0
- /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
|
-
}
|