circuitscript 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/cjs/BaseVisitor.js +127 -73
  2. package/dist/cjs/SemanticTokenVisitor.js +19 -13
  3. package/dist/cjs/antlr/CircuitScriptParser.js +711 -671
  4. package/dist/cjs/builtinMethods.js +29 -25
  5. package/dist/cjs/environment.js +118 -0
  6. package/dist/cjs/execute.js +53 -12
  7. package/dist/cjs/geometry.js +1 -0
  8. package/dist/cjs/globals.js +11 -6
  9. package/dist/cjs/helpers.js +135 -127
  10. package/dist/cjs/index.js +5 -0
  11. package/dist/cjs/layout.js +37 -12
  12. package/dist/cjs/main.js +31 -19
  13. package/dist/cjs/objects/ExecutionScope.js +33 -0
  14. package/dist/cjs/objects/ParamDefinition.js +15 -15
  15. package/dist/cjs/parser.js +27 -21
  16. package/dist/cjs/regenerate-tests.js +9 -6
  17. package/dist/cjs/render.js +3 -1
  18. package/dist/cjs/sizing.js +5 -58
  19. package/dist/cjs/utils.js +85 -30
  20. package/dist/cjs/validate/SymbolTable.js +96 -0
  21. package/dist/cjs/validate/SymbolValidatorResolveVisitor.js +14 -0
  22. package/dist/cjs/validate/SymbolValidatorVisitor.js +170 -0
  23. package/dist/cjs/validate.js +52 -44
  24. package/dist/cjs/visitor.js +140 -24
  25. package/dist/esm/{BaseVisitor.mjs → BaseVisitor.js} +98 -45
  26. package/dist/esm/{SemanticTokenVisitor.mjs → SemanticTokenVisitor.js} +17 -11
  27. package/dist/esm/antlr/{CircuitScriptParser.mjs → CircuitScriptParser.js} +711 -671
  28. package/dist/esm/{builtinMethods.mjs → builtinMethods.js} +20 -16
  29. package/dist/esm/{draw_symbols.mjs → draw_symbols.js} +7 -7
  30. package/dist/esm/environment.js +110 -0
  31. package/dist/esm/{execute.mjs → execute.js} +66 -25
  32. package/dist/esm/{export.mjs → export.js} +2 -2
  33. package/dist/esm/{geometry.mjs → geometry.js} +6 -5
  34. package/dist/esm/{globals.mjs → globals.js} +6 -1
  35. package/dist/esm/helpers.js +377 -0
  36. package/dist/esm/index.js +20 -0
  37. package/dist/esm/{layout.mjs → layout.js} +42 -20
  38. package/dist/esm/{lexer.mjs → lexer.js} +2 -2
  39. package/dist/esm/{main.mjs → main.js} +33 -21
  40. package/dist/esm/objects/{ClassComponent.mjs → ClassComponent.js} +5 -4
  41. package/dist/esm/objects/{ExecutionScope.mjs → ExecutionScope.js} +33 -0
  42. package/dist/esm/objects/{Frame.mjs → Frame.js} +1 -1
  43. package/dist/esm/objects/{ParamDefinition.mjs → ParamDefinition.js} +1 -1
  44. package/dist/esm/objects/{PinDefinition.mjs → PinDefinition.js} +1 -1
  45. package/dist/esm/parser.js +71 -0
  46. package/dist/esm/{regenerate-tests.mjs → regenerate-tests.js} +10 -7
  47. package/dist/esm/{render.mjs → render.js} +11 -9
  48. package/dist/esm/{sizing.mjs → sizing.js} +6 -34
  49. package/dist/esm/{utils.mjs → utils.js} +61 -17
  50. package/dist/esm/validate/SymbolTable.js +90 -0
  51. package/dist/esm/validate/SymbolValidatorResolveVisitor.js +10 -0
  52. package/dist/esm/validate/SymbolValidatorVisitor.js +163 -0
  53. package/dist/esm/validate.js +86 -0
  54. package/dist/esm/{visitor.mjs → visitor.js} +151 -35
  55. package/dist/fonts/Arial.ttf +0 -0
  56. package/dist/fonts/Inter-Bold.ttf +0 -0
  57. package/dist/fonts/Inter-Regular.ttf +0 -0
  58. package/dist/fonts/OpenSans-Regular.ttf +0 -0
  59. package/dist/fonts/Roboto-Regular.ttf +0 -0
  60. package/dist/libs/lib.cst +423 -0
  61. package/dist/types/BaseVisitor.d.ts +34 -21
  62. package/dist/types/SemanticTokenVisitor.d.ts +6 -5
  63. package/dist/types/antlr/CircuitScriptParser.d.ts +4 -2
  64. package/dist/types/builtinMethods.d.ts +3 -2
  65. package/dist/types/environment.d.ts +31 -0
  66. package/dist/types/globals.d.ts +4 -1
  67. package/dist/types/helpers.d.ts +12 -14
  68. package/dist/types/index.d.ts +5 -0
  69. package/dist/types/objects/ClassComponent.d.ts +1 -0
  70. package/dist/types/objects/ExecutionScope.d.ts +11 -0
  71. package/dist/types/objects/types.d.ts +6 -1
  72. package/dist/types/parser.d.ts +7 -11
  73. package/dist/types/sizing.d.ts +0 -3
  74. package/dist/types/utils.d.ts +30 -6
  75. package/dist/types/validate/SymbolTable.d.ts +40 -0
  76. package/dist/types/validate/SymbolValidatorResolveVisitor.d.ts +7 -0
  77. package/dist/types/validate/SymbolValidatorVisitor.d.ts +32 -0
  78. package/dist/types/validate.d.ts +1 -1
  79. package/package.json +14 -13
  80. package/dist/cjs/SymbolValidatorVisitor.js +0 -233
  81. package/dist/esm/SymbolValidatorVisitor.mjs +0 -222
  82. package/dist/esm/helpers.mjs +0 -364
  83. package/dist/esm/index.mjs +0 -15
  84. package/dist/esm/parser.mjs +0 -64
  85. package/dist/esm/validate.mjs +0 -74
  86. package/dist/types/SymbolValidatorVisitor.d.ts +0 -61
  87. package/dist/types/layout.d.ts +0 -148
  88. /package/dist/esm/antlr/{CircuitScriptLexer.mjs → CircuitScriptLexer.js} +0 -0
  89. /package/dist/esm/antlr/{CircuitScriptVisitor.mjs → CircuitScriptVisitor.js} +0 -0
  90. /package/dist/esm/{fonts.mjs → fonts.js} +0 -0
  91. /package/dist/esm/{logger.mjs → logger.js} +0 -0
  92. /package/dist/esm/objects/{Net.mjs → Net.js} +0 -0
  93. /package/dist/esm/objects/{PinTypes.mjs → PinTypes.js} +0 -0
  94. /package/dist/esm/objects/{Wire.mjs → Wire.js} +0 -0
  95. /package/dist/esm/objects/{types.mjs → types.js} +0 -0
  96. /package/dist/esm/{server.mjs → server.js} +0 -0
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SymbolValidatorVisitor = void 0;
4
+ const builtinMethods_js_1 = require("../builtinMethods.js");
5
+ const types_js_1 = require("../objects/types.js");
6
+ const SymbolTable_js_1 = require("./SymbolTable.js");
7
+ const BaseVisitor_js_1 = require("../BaseVisitor.js");
8
+ const globals_js_1 = require("../globals.js");
9
+ class SymbolValidatorVisitor extends BaseVisitor_js_1.BaseVisitor {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.symbolTable = new SymbolTable_js_1.SymbolTable();
13
+ this.filePathStack = [];
14
+ this.visitImport_expr = (ctx) => {
15
+ const ID = ctx.ID().toString();
16
+ const { pathExists } = this.handleImportFile(ID, false, ctx);
17
+ if (!pathExists) {
18
+ this.symbolTable.addUndefined(this.getCurrentFile(), this.getExecutor(), ID, ctx.ID().getSymbol());
19
+ }
20
+ };
21
+ this.visitAssignment_expr = (ctx) => {
22
+ const ctxDataExpr = ctx.data_expr();
23
+ this.visit(ctxDataExpr);
24
+ const value = this.getResult(ctxDataExpr);
25
+ const atomId = ctx.atom_expr().ID(0);
26
+ const atomText = atomId.getText();
27
+ const executor = this.getExecutor();
28
+ if (!this.symbolTable.exists(executor, atomText)) {
29
+ this.addSymbolVariable(atomId.getSymbol(), atomId.getText(), value);
30
+ }
31
+ else {
32
+ const tmpSymbol = this.symbolTable.get(executor, atomText);
33
+ this.addSymbolInstance(tmpSymbol, atomId.getSymbol());
34
+ }
35
+ return null;
36
+ };
37
+ this.visitAtom_expr = (ctx) => {
38
+ const tmpSymbol = this.handleAtomSymbol(ctx.ID(0));
39
+ this.setResult(ctx, tmpSymbol);
40
+ };
41
+ this.visitFunction_call_expr = (ctx) => {
42
+ this.handleAtomSymbol(ctx.ID());
43
+ if (ctx.trailer_expr().length > 0) {
44
+ ctx.trailer_expr().forEach(item => {
45
+ if (item.OPEN_PAREN() && item.CLOSE_PAREN()) {
46
+ const params = item.parameters();
47
+ if (params) {
48
+ this.visit(params);
49
+ }
50
+ }
51
+ });
52
+ }
53
+ };
54
+ this.visitValueAtomExpr = (ctx) => {
55
+ let value = null;
56
+ const ctxValueExpr = ctx.value_expr();
57
+ const cxtAtomExpr = ctx.atom_expr();
58
+ if (ctxValueExpr) {
59
+ this.visit(ctxValueExpr);
60
+ value = this.getResult(ctxValueExpr);
61
+ }
62
+ else if (cxtAtomExpr) {
63
+ this.visit(cxtAtomExpr);
64
+ value = this.getResult(cxtAtomExpr);
65
+ }
66
+ this.setResult(ctx, value);
67
+ };
68
+ this.visitUnaryOperatorExpr = (ctx) => {
69
+ this.visit(ctx.data_expr());
70
+ };
71
+ this.visitMultiplyExpr = (ctx) => {
72
+ this.visit(ctx.data_expr(0));
73
+ this.visit(ctx.data_expr(1));
74
+ };
75
+ this.visitAdditionExpr = (ctx) => {
76
+ this.visit(ctx.data_expr(0));
77
+ this.visit(ctx.data_expr(1));
78
+ };
79
+ this.visitBinaryOperatorExpr = (ctx) => {
80
+ this.visit(ctx.data_expr(0));
81
+ this.visit(ctx.data_expr(1));
82
+ };
83
+ this.visitDataExpr = (ctx) => {
84
+ return;
85
+ };
86
+ this.visitFunction_def_expr = (ctx) => {
87
+ const functionName = ctx.ID().getText();
88
+ let funcDefinedParameters = [];
89
+ const ctxFunctionArgsExpr = ctx.function_args_expr();
90
+ if (ctxFunctionArgsExpr) {
91
+ this.visit(ctxFunctionArgsExpr);
92
+ funcDefinedParameters = this.getResult(ctxFunctionArgsExpr);
93
+ }
94
+ this.addSymbolFunction(ctx.ID().getSymbol(), functionName, funcDefinedParameters);
95
+ const executionContextName = functionName + globals_js_1.SymbolValidatorContext;
96
+ const passedInParamsNull = funcDefinedParameters.map((param, index) => {
97
+ return ['position', index, null];
98
+ });
99
+ const newExecutor = this.enterNewChildContext(this.executionStack, this.getExecutor(), executionContextName, { netNamespace: "" }, funcDefinedParameters, passedInParamsNull);
100
+ funcDefinedParameters.forEach(param => {
101
+ this.addSymbolVariable(param[1], param[0], null, newExecutor);
102
+ });
103
+ this.runExpressions(newExecutor, ctx.function_expr());
104
+ this.executionStack.pop();
105
+ };
106
+ }
107
+ enterFile(filePath) {
108
+ this.filePathStack.push(filePath);
109
+ }
110
+ exitFile() {
111
+ this.filePathStack.pop();
112
+ }
113
+ getCurrentFile() {
114
+ return this.filePathStack[this.filePathStack.length - 1];
115
+ }
116
+ addSymbolVariable(token, name, value, executor = null) {
117
+ const useExecutor = executor === null ? this.getExecutor() : executor;
118
+ this.symbolTable.addVariable(token, this.getCurrentFile(), useExecutor, name, value);
119
+ this.log2('add symbol variable: ' + name);
120
+ }
121
+ addSymbolFunction(token, functionName, funcDefinedParameters) {
122
+ if (!this.symbolTable.exists(this.getExecutor(), functionName)) {
123
+ this.symbolTable.addFunction(token, this.getCurrentFile(), this.getExecutor(), functionName, funcDefinedParameters);
124
+ this.log2('add symbol function: ' + functionName);
125
+ }
126
+ }
127
+ handleAtomSymbol(atom) {
128
+ const atomId = atom.getText();
129
+ const executor = this.getExecutor();
130
+ let tmpSymbol;
131
+ if (this.symbolTable.exists(executor, atomId)) {
132
+ tmpSymbol = this.symbolTable.get(executor, atomId);
133
+ }
134
+ else {
135
+ if (builtinMethods_js_1.buildInMethodNamesList.indexOf(atomId) !== -1) {
136
+ tmpSymbol = this.symbolTable.addFunction(null, "<builtIn>", this.getRootExecutor(), atomId, {});
137
+ }
138
+ else {
139
+ const foundContext = this.symbolTable.searchParentContext(executor, atomId);
140
+ if (foundContext === null) {
141
+ tmpSymbol = this.symbolTable.addUndefined(this.getCurrentFile(), executor, atomId, atom.getSymbol());
142
+ this.log2('symbol not found: ' + atomId);
143
+ }
144
+ else {
145
+ tmpSymbol = this.symbolTable.get(foundContext, atomId);
146
+ }
147
+ }
148
+ }
149
+ if (tmpSymbol.type !== types_js_1.ParseSymbolType.Undefined) {
150
+ this.addSymbolInstance(tmpSymbol, atom.getSymbol());
151
+ }
152
+ return tmpSymbol;
153
+ }
154
+ addSymbolInstance(symbol, token) {
155
+ symbol = symbol;
156
+ if (symbol.instances.indexOf(token) == -1) {
157
+ symbol.instances.push(token);
158
+ }
159
+ }
160
+ setSymbols(symbolTable) {
161
+ this.symbolTable = symbolTable;
162
+ }
163
+ getSymbols() {
164
+ return this.symbolTable;
165
+ }
166
+ dumpSymbols() {
167
+ this.symbolTable.dumpSymbols();
168
+ }
169
+ }
170
+ exports.SymbolValidatorVisitor = SymbolValidatorVisitor;
@@ -1,81 +1,89 @@
1
1
  #! /usr/bin/env node
2
2
  "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
3
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.validate = void 0;
8
4
  const commander_1 = require("commander");
9
- const figlet_1 = __importDefault(require("figlet"));
10
- const path_1 = __importDefault(require("path"));
11
5
  const fs_1 = require("fs");
12
- const sizing_js_1 = require("./sizing.js");
13
6
  const helpers_js_1 = require("./helpers.js");
7
+ const environment_js_1 = require("./environment.js");
8
+ const types_js_1 = require("./objects/types.js");
14
9
  async function validate() {
15
- const { filePath } = (0, helpers_js_1.getCurrentPath)();
16
- const toolSrcPath = filePath;
17
- const toolDirectory = path_1.default.dirname(toolSrcPath) + '/../../';
18
- const fontsPath = toolDirectory + '/fonts';
19
- const defaultLibsPath = toolDirectory + '/libs';
20
- const packageJson = JSON.parse((0, fs_1.readFileSync)(toolDirectory + 'package.json').toString());
21
- ;
22
- const { version } = packageJson;
10
+ const env = new environment_js_1.NodeScriptEnvironment();
11
+ environment_js_1.NodeScriptEnvironment.setInstance(env);
12
+ const version = env.getPackageVersion();
23
13
  commander_1.program
24
- .description('generate graphical output from circuitscript files')
14
+ .description('generate validation output circuitscript files')
25
15
  .version(version)
16
+ .argument('[input path]', 'Input path')
17
+ .argument('[output path]', 'Output path')
26
18
  .option('-i, --input text <input text>', 'Input text directly')
27
- .option('-f, --input-file <path>', 'Input file')
28
- .option('-o, --output <path>', 'Output path')
29
19
  .option('-c, --current-directory <path>', 'Set current directory')
30
- .option('-k, --kicad-netlist <filename>', 'Create KiCad netlist')
31
20
  .option('-w, --watch', 'Watch for file changes')
32
21
  .option('-n, --dump-nets', 'Dump out net information')
33
22
  .option('-d, --dump-data', 'Dump data during parsing')
34
- .option('-s, --stats', 'Show stats during generation');
35
- commander_1.program.addHelpText('before', figlet_1.default.textSync('circuitscript', {
36
- font: 'Small Slant'
37
- }));
23
+ .option('-s, --stats', 'Show stats during generation')
24
+ .option('-x, --skip-output', 'Skip output generation');
38
25
  if (process.argv.length < 3) {
39
26
  commander_1.program.help();
40
27
  }
41
28
  commander_1.program.parse();
42
29
  const options = commander_1.program.opts();
30
+ const args = commander_1.program.args;
43
31
  const watchFileChanges = options.watch;
44
- const outputPath = options.output ?? null;
45
32
  const dumpNets = options.dumpNets;
46
33
  const dumpData = options.dumpData;
47
- const kicadNetlist = options.kicadNetlist;
48
- let currentDirectory = options.currentDirectory ?? null;
34
+ if (options.currentDirectory) {
35
+ env.setModuleDirectory(options.currentDirectory);
36
+ }
49
37
  if (watchFileChanges) {
50
38
  console.log('watching for file changes...');
51
39
  }
52
- await (0, sizing_js_1.prepareSVGEnvironment)(fontsPath);
53
- let inputFilePath = null;
40
+ await env.prepareSVGEnvironment();
41
+ let inputFilePath = "";
42
+ if (args.length > 2) {
43
+ console.log("Error: Extra arguments passed");
44
+ return;
45
+ }
54
46
  let scriptData;
55
- if (options.input) {
47
+ if (args.length > 0 && args[0]) {
48
+ inputFilePath = args[0];
49
+ if ((0, fs_1.existsSync)(inputFilePath)) {
50
+ scriptData = (0, fs_1.readFileSync)(inputFilePath, { encoding: 'utf-8' });
51
+ }
52
+ else {
53
+ console.error("Error: File could not be found");
54
+ return;
55
+ }
56
+ }
57
+ else if (options.input) {
56
58
  scriptData = options.input;
57
59
  }
58
60
  else {
59
- inputFilePath = options.inputFile;
60
- const tmpScriptData = (0, helpers_js_1.getScriptText)(inputFilePath);
61
- if (tmpScriptData === null) {
62
- throw "File does not exists";
63
- }
64
- scriptData = tmpScriptData;
65
- if (currentDirectory === null) {
66
- currentDirectory = path_1.default.dirname(inputFilePath);
67
- }
61
+ console.error("Error: No input provided");
62
+ return;
68
63
  }
69
64
  const scriptOptions = {
70
- currentDirectory,
71
- defaultLibsPath,
72
65
  dumpNets,
73
66
  dumpData,
74
- kicadNetlistPath: kicadNetlist,
75
67
  showStats: options.stats,
68
+ environment: env,
76
69
  };
77
- const visitor = (0, helpers_js_1.validateScript)(scriptData, scriptOptions);
78
- const semanticTokensVisitor = (0, helpers_js_1.getSemanticTokens)(scriptData, scriptOptions);
70
+ const visitor = await (0, helpers_js_1.validateScript)(inputFilePath, scriptData, scriptOptions);
71
+ const symbols = visitor.getSymbols().getSymbols();
72
+ symbols.forEach((value, key) => {
73
+ if (value.type !== types_js_1.ParseSymbolType.Undefined) {
74
+ value = value;
75
+ const token = value.token;
76
+ console.log(key, value.fileName, token !== null ? (token.line + ":" + token.column) : "");
77
+ value.instances.forEach(instance => {
78
+ console.log(" " + instance.line + ":" + instance.column + " " + instance.start);
79
+ });
80
+ }
81
+ });
82
+ const { parsedTokens } = await (0, helpers_js_1.getSemanticTokens)(scriptData, scriptOptions);
83
+ parsedTokens.forEach(item => {
84
+ const { line, column, tokenType, tokenModifiers, textValue } = item;
85
+ console.log(`${line}:${column} - ${textValue} - ${tokenType} | ${tokenModifiers.join(',')}`);
86
+ });
79
87
  }
80
- exports.validate = validate;
88
+ exports.default = validate;
81
89
  validate();
@@ -46,9 +46,14 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
46
46
  this.visitTo_component_expr = (ctx) => {
47
47
  ctx.component_select_expr().forEach(item => {
48
48
  const [component, pin] = this.visitResult(item);
49
- this.getExecutor().toComponent(component, pin, {
50
- addSequence: true
51
- });
49
+ try {
50
+ this.getExecutor().toComponent(component, pin, {
51
+ addSequence: true
52
+ });
53
+ }
54
+ catch (err) {
55
+ throw new utils_js_1.RuntimeExecutionError(err.message, ctx.start, ctx.stop);
56
+ }
52
57
  });
53
58
  return this.getExecutor().getCurrentPoint();
54
59
  };
@@ -63,7 +68,10 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
63
68
  componentPin = this.visitResult(ctxDataExprWithAssigment);
64
69
  }
65
70
  else {
66
- const component = this.getExecutor().scope.currentComponent;
71
+ let component = this.getScope().currentComponent;
72
+ if (component._pointLinkComponent) {
73
+ component = component._pointLinkComponent;
74
+ }
67
75
  let pinId = null;
68
76
  const ctxPinSelectExpr = ctx.pin_select_expr();
69
77
  if (ctxPinSelectExpr) {
@@ -111,6 +119,92 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
111
119
  return this.getExecutor().getCurrentPoint();
112
120
  };
113
121
  this.visitCreate_component_expr = (ctx) => {
122
+ const scope = this.getScope();
123
+ scope.setOnPropertyHandler((path, value, ctx) => {
124
+ if (path.length === 1) {
125
+ const [, keyName] = path[0];
126
+ switch (keyName) {
127
+ case 'type':
128
+ this.validateString(value, ctx);
129
+ break;
130
+ case 'angle':
131
+ case 'width':
132
+ case 'height':
133
+ this.validateNumeric(value, ctx);
134
+ break;
135
+ case 'pins':
136
+ if (!(value instanceof Map)) {
137
+ this.validateNumeric(value, ctx);
138
+ }
139
+ break;
140
+ case 'copy':
141
+ if (value instanceof ParamDefinition_js_1.NumericValue) {
142
+ this.validateNumeric(value, ctx);
143
+ }
144
+ else if (typeof value === 'boolean') {
145
+ this.validateBoolean(value, ctx);
146
+ }
147
+ else {
148
+ throw new utils_js_1.RuntimeExecutionError("Invalid value for 'copy' property", ctx.start, ctx.end);
149
+ }
150
+ break;
151
+ }
152
+ }
153
+ else {
154
+ const [, keyName] = path[0];
155
+ if (keyName === 'arrange') {
156
+ const [sideKeyCtx, sideKeyName] = path[1];
157
+ if (globals_js_1.ValidPinSides.indexOf(sideKeyName) === -1) {
158
+ throw new utils_js_1.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx.start, sideKeyCtx.stop);
159
+ }
160
+ else {
161
+ if (path.length > 2 && path[2][0] === 'index') {
162
+ if (Array.isArray(value)) {
163
+ const goodBlank = value.length === 1 &&
164
+ value[0] instanceof ParamDefinition_js_1.NumericValue;
165
+ if (!goodBlank) {
166
+ throw new utils_js_1.RuntimeExecutionError(`Invalid blank specifier`, ctx.start, ctx.stop);
167
+ }
168
+ }
169
+ else {
170
+ if (!(value instanceof ParamDefinition_js_1.NumericValue)) {
171
+ throw new utils_js_1.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx.start, ctx.stop);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ }
177
+ else if (keyName === 'params') {
178
+ const [, subKeyName] = path[1];
179
+ switch (subKeyName) {
180
+ case 'mpn':
181
+ case 'refdes':
182
+ case 'footprint':
183
+ this.validateString(value, ctx);
184
+ break;
185
+ case 'place':
186
+ this.validateBoolean(value, ctx);
187
+ break;
188
+ }
189
+ }
190
+ else if (keyName === 'pins') {
191
+ if (path.length === 2) {
192
+ if (value.length === 2) {
193
+ const [pinType,] = value;
194
+ if (pinType instanceof types_js_1.UndeclaredReference) {
195
+ throw new utils_js_1.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx.start, ctx.end);
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ });
202
+ scope.enterContext(ctx);
203
+ ctx.property_expr().forEach(item => {
204
+ this.visitResult(item);
205
+ });
206
+ scope.exitContext();
207
+ scope.popOnPropertyHandler();
114
208
  const properties = this.getPropertyExprList(ctx.property_expr());
115
209
  const pins = this.parseCreateComponentPins(properties.get('pins'));
116
210
  let instanceName = this.getExecutor().getUniqueInstanceName();
@@ -145,8 +239,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
145
239
  arrange, display, type, width, height, copy,
146
240
  angle, followWireOrientation
147
241
  };
148
- const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
149
- this.setResult(ctx, createdComponent);
242
+ try {
243
+ const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
244
+ this.setResult(ctx, createdComponent);
245
+ }
246
+ catch (error) {
247
+ this.throwWithContext(ctx, error.message);
248
+ }
150
249
  };
151
250
  this.visitCreate_graphic_expr = (ctx) => {
152
251
  const ctxId = ctx.ID();
@@ -154,7 +253,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
154
253
  if (ctxId !== null) {
155
254
  const varName = ctxId.getText();
156
255
  paramIds.push(varName);
157
- this.getExecutor().scope.variables.set(varName, {});
256
+ this.getScope().variables.set(varName, {});
158
257
  }
159
258
  const executor = this.getExecutor();
160
259
  const stack = [...this.executionStack];
@@ -256,7 +355,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
256
355
  useValueArray = [useValueArray];
257
356
  }
258
357
  useValueArray.forEach((value, index) => {
259
- this.getExecutor().scope.variables.set(forVariableNames[index], value);
358
+ this.getScope().variables.set(forVariableNames[index], value);
260
359
  });
261
360
  const commands = this.visitResult(ctx.graphic_expressions_block());
262
361
  allCommands = allCommands.concat(commands);
@@ -315,8 +414,16 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
315
414
  this.setResult(ctx, [keyName, expressionsBlock]);
316
415
  };
317
416
  this.visitProperty_expr = (ctx) => {
318
- const keyName = this.visitResult(ctx.property_key_expr());
319
- const value = this.visitResult(ctx.property_value_expr());
417
+ const ctxKey = ctx.property_key_expr();
418
+ const ctxValue = ctx.property_value_expr();
419
+ const scope = this.getScope();
420
+ this.getScope().enterContext(ctxKey);
421
+ this.getScope().enterContext(ctxValue);
422
+ const keyName = this.visitResult(ctxKey);
423
+ const value = this.visitResult(ctxValue);
424
+ scope.triggerPropertyHandler(value, ctxValue);
425
+ this.getScope().exitContext();
426
+ this.getScope().exitContext();
320
427
  if (value instanceof types_js_1.UndeclaredReference && (value.reference.parentValue === undefined
321
428
  && value.reference.value === undefined)) {
322
429
  throw value.throwMessage();
@@ -326,15 +433,21 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
326
433
  this.setResult(ctx, map);
327
434
  };
328
435
  this.visitSingle_line_property = (ctx) => {
436
+ this.getScope().enterContext(ctx);
329
437
  let value;
330
438
  if (ctx.data_expr().length === 1) {
331
439
  value = this.visitResult(ctx.data_expr(0));
332
440
  }
333
441
  else {
334
- value = ctx.data_expr().map(item => {
335
- return this.visitResult(item);
442
+ value = ctx.data_expr().map((item, index) => {
443
+ this.getScope().enterContext(index);
444
+ const result = this.visitResult(item);
445
+ this.getScope().triggerPropertyHandler(result, item);
446
+ this.getScope().exitContext();
447
+ return result;
336
448
  });
337
449
  }
450
+ this.getScope().exitContext();
338
451
  this.setResult(ctx, value);
339
452
  };
340
453
  this.visitNested_properties_inner = (ctx) => {
@@ -707,6 +820,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
707
820
  }
708
821
  else if (ctxDataExpr) {
709
822
  useValue = this.visitResult(ctxDataExpr);
823
+ if (useValue instanceof ParamDefinition_js_1.NumericValue) {
824
+ useValue = useValue.toNumber();
825
+ }
710
826
  }
711
827
  if (useValue !== null) {
712
828
  this.setResult(ctx, [direction, new helpers_js_1.UnitDimension(useValue)]);
@@ -848,7 +964,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
848
964
  useValueArray = [useValueArray];
849
965
  }
850
966
  useValueArray.forEach((value, index) => {
851
- this.getExecutor().scope.variables.set(forVariableNames[index], value);
967
+ this.getScope().variables.set(forVariableNames[index], value);
852
968
  });
853
969
  this.visit(ctx.expressions_block());
854
970
  keepLooping = true;
@@ -1043,32 +1159,32 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1043
1159
  return result;
1044
1160
  }
1045
1161
  printNets() {
1046
- this.getExecutor().scope.printNets();
1162
+ this.getScope().printNets();
1047
1163
  }
1048
1164
  dumpNets() {
1049
- return this.getExecutor().scope.dumpNets();
1165
+ return this.getScope().dumpNets();
1050
1166
  }
1051
1167
  dumpUniqueNets() {
1052
- const nets = this.getExecutor().scope.getNets();
1168
+ const nets = this.getScope().getNets();
1053
1169
  return nets.reduce((accum, [, , net]) => {
1054
1170
  accum.push(net);
1055
1171
  return accum;
1056
1172
  }, []);
1057
1173
  }
1058
1174
  dumpVariables() {
1059
- return this.getExecutor().scope.variables;
1175
+ return this.getScope().variables;
1060
1176
  }
1061
1177
  dumpInstances() {
1062
- return this.getExecutor().scope.instances;
1178
+ return this.getScope().instances;
1063
1179
  }
1064
1180
  dump2() {
1065
- const instances = this.getExecutor().scope.instances;
1181
+ const instances = this.getScope().instances;
1066
1182
  const items = [];
1067
1183
  for (const [instanceName, instance] of instances) {
1068
1184
  if (instance.assignedRefDes === null) {
1069
1185
  continue;
1070
1186
  }
1071
- const pinNets = this.resolveNets(this.getExecutor().scope, instance);
1187
+ const pinNets = this.resolveNets(this.getScope(), instance);
1072
1188
  const componentItem = {
1073
1189
  name: instanceName,
1074
1190
  refdes: instance.assignedRefDes,
@@ -1083,9 +1199,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1083
1199
  }
1084
1200
  getNetList() {
1085
1201
  const netlist = [];
1086
- const instances = this.getExecutor().scope.instances;
1202
+ const instances = this.getScope().instances;
1087
1203
  for (const [instanceName, instance] of instances) {
1088
- const pinNets = this.resolveNets(this.getExecutor().scope, instance);
1204
+ const pinNets = this.resolveNets(this.getScope(), instance);
1089
1205
  const componentItem = {
1090
1206
  instanceName,
1091
1207
  instance,
@@ -1116,7 +1232,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1116
1232
  annotateComponents() {
1117
1233
  this.log('===== annotate components =====');
1118
1234
  const annotater = new ComponentAnnotater();
1119
- const instances = this.getExecutor().scope.instances;
1235
+ const instances = this.getScope().instances;
1120
1236
  const toAnnotate = [];
1121
1237
  for (const [, instance] of instances) {
1122
1238
  if (instance.typeProp === globals_js_1.ComponentTypes.net
@@ -1153,7 +1269,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1153
1269
  this.log('');
1154
1270
  }
1155
1271
  applySheetFrameComponent() {
1156
- const baseScope = this.getExecutor().scope;
1272
+ const baseScope = this.getScope();
1157
1273
  const document = baseScope.variables.get(globals_js_1.GlobalDocumentName);
1158
1274
  let frameComponent = null;
1159
1275
  if (document && document[Frame_js_1.FrameParamKeys.SheetType]) {