circuitscript 0.1.7 → 0.1.9
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 +7 -6
- package/dist/cjs/draw_symbols.js +3 -0
- package/dist/cjs/execute.js +90 -2
- package/dist/cjs/export.js +0 -5
- package/dist/cjs/helpers.js +20 -2
- package/dist/cjs/layout.js +88 -82
- package/dist/cjs/objects/ClassComponent.js +1 -0
- package/dist/cjs/objects/ExecutionScope.js +5 -4
- package/dist/cjs/regenerate-tests.js +6 -5
- package/dist/cjs/utils.js +57 -14
- package/dist/cjs/validate.js +19 -0
- package/dist/cjs/visitor.js +84 -38
- package/dist/esm/BaseVisitor.js +7 -6
- package/dist/esm/draw_symbols.js +4 -1
- package/dist/esm/execute.js +91 -3
- package/dist/esm/export.js +1 -6
- package/dist/esm/helpers.js +21 -3
- package/dist/esm/layout.js +66 -80
- package/dist/esm/objects/ClassComponent.js +1 -0
- package/dist/esm/objects/ExecutionScope.js +5 -4
- package/dist/esm/regenerate-tests.js +6 -5
- package/dist/esm/utils.js +54 -13
- package/dist/esm/validate.js +19 -0
- package/dist/esm/visitor.js +85 -39
- package/dist/types/BaseVisitor.d.ts +3 -1
- package/dist/types/execute.d.ts +6 -1
- package/dist/types/layout.d.ts +148 -0
- package/dist/types/objects/ClassComponent.d.ts +1 -0
- package/dist/types/objects/ExecutionScope.d.ts +3 -2
- package/dist/types/utils.d.ts +9 -1
- package/dist/types/visitor.d.ts +2 -0
- package/package.json +2 -2
package/dist/cjs/utils.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RenderError = exports.RuntimeExecutionError = exports.ParseError = exports.ParseSyntaxError = exports.BaseError = exports.getBlockTypeString = exports.generateDebugSequenceAction = exports.sequenceActionString = exports.areasOverlap = exports.isPointWithinArea = exports.resolveToNumericValue = exports.getNumberExponentialText = exports.getNumberExponential = exports.combineMaps = exports.throwWithTokenRange = exports.throwWithToken = exports.throwWithContext = exports.roundValue = exports.getPortType = exports.getBoundsSize = exports.toNearestGrid = exports.resizeToNearestGrid = exports.printBounds = exports.resizeBounds = exports.SimpleStopwatch = void 0;
|
|
3
|
+
exports.printWarnings = exports.RenderError = exports.RuntimeExecutionError = exports.ParseError = exports.ParseSyntaxError = exports.getLinePositionAsString = exports.BaseError = exports.getBlockTypeString = exports.generateDebugSequenceAction = exports.sequenceActionString = exports.areasOverlap = exports.isPointWithinArea = exports.resolveToNumericValue = exports.getNumberExponentialText = exports.getNumberExponential = exports.combineMaps = exports.throwWithTokenRange = exports.throwWithToken = exports.throwWithContext = exports.roundValue = exports.getPortType = exports.getBoundsSize = exports.toNearestGrid = exports.resizeToNearestGrid = exports.printBounds = exports.resizeBounds = exports.SimpleStopwatch = void 0;
|
|
4
4
|
const big_js_1 = require("big.js");
|
|
5
|
+
const antlr4ng_1 = require("antlr4ng");
|
|
5
6
|
const ClassComponent_js_1 = require("./objects/ClassComponent.js");
|
|
6
7
|
const ParamDefinition_js_1 = require("./objects/ParamDefinition.js");
|
|
7
8
|
const ExecutionScope_js_1 = require("./objects/ExecutionScope.js");
|
|
@@ -260,32 +261,55 @@ function getBlockTypeString(type) {
|
|
|
260
261
|
}
|
|
261
262
|
exports.getBlockTypeString = getBlockTypeString;
|
|
262
263
|
class BaseError extends Error {
|
|
263
|
-
constructor(message,
|
|
264
|
+
constructor(message, startTokenOrCtx, endToken, filePath) {
|
|
264
265
|
super(message);
|
|
265
266
|
this.name = 'BaseError';
|
|
266
267
|
this.message = message;
|
|
267
|
-
|
|
268
|
-
|
|
268
|
+
if (startTokenOrCtx instanceof antlr4ng_1.ParserRuleContext) {
|
|
269
|
+
this.startToken = startTokenOrCtx.start;
|
|
270
|
+
this.endToken = startTokenOrCtx.stop;
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
this.startToken = startTokenOrCtx;
|
|
274
|
+
this.endToken = endToken;
|
|
275
|
+
}
|
|
269
276
|
this.filePath = filePath;
|
|
270
277
|
}
|
|
271
278
|
toString() {
|
|
272
279
|
const parts = [this.name];
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
else {
|
|
281
|
-
parts.push(` at ${line}:${column}`);
|
|
282
|
-
}
|
|
280
|
+
const linePosition = getLinePositionAsString({
|
|
281
|
+
start: this.startToken,
|
|
282
|
+
stop: this.endToken
|
|
283
|
+
});
|
|
284
|
+
if (linePosition !== null) {
|
|
285
|
+
parts.push(linePosition);
|
|
283
286
|
}
|
|
284
287
|
parts.push(`: ${this.message}`);
|
|
285
288
|
return parts.join('');
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
291
|
exports.BaseError = BaseError;
|
|
292
|
+
function getLinePositionAsString(ctx) {
|
|
293
|
+
if (ctx === null || ctx === undefined) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
const startToken = ctx.start;
|
|
297
|
+
const endToken = ctx.stop;
|
|
298
|
+
let result = null;
|
|
299
|
+
if (startToken) {
|
|
300
|
+
const { line, column } = startToken;
|
|
301
|
+
if (endToken && (endToken.line !== startToken.line || endToken.column !== startToken.column)) {
|
|
302
|
+
const endLine = endToken.line;
|
|
303
|
+
const endColumn = endToken.column + (endToken.stop - endToken.start);
|
|
304
|
+
result = ` at ${line}:${column}-${endLine}:${endColumn}`;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
result = ` at ${line}:${column}`;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return result;
|
|
311
|
+
}
|
|
312
|
+
exports.getLinePositionAsString = getLinePositionAsString;
|
|
289
313
|
class ParseSyntaxError extends BaseError {
|
|
290
314
|
constructor() {
|
|
291
315
|
super(...arguments);
|
|
@@ -315,3 +339,22 @@ class RenderError extends Error {
|
|
|
315
339
|
}
|
|
316
340
|
}
|
|
317
341
|
exports.RenderError = RenderError;
|
|
342
|
+
function printWarnings(warnings) {
|
|
343
|
+
const warningMessages = [];
|
|
344
|
+
warnings.forEach(item => {
|
|
345
|
+
const { message } = item;
|
|
346
|
+
const linePosition = getLinePositionAsString(item.ctx);
|
|
347
|
+
const parts = [message];
|
|
348
|
+
if (linePosition !== null) {
|
|
349
|
+
parts.push(linePosition);
|
|
350
|
+
}
|
|
351
|
+
const finalMessage = parts.join('');
|
|
352
|
+
if (warningMessages.indexOf(finalMessage) === -1) {
|
|
353
|
+
warningMessages.push(finalMessage);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
warningMessages.forEach(message => {
|
|
357
|
+
console.log(`Warning: ${message}`);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
exports.printWarnings = printWarnings;
|
package/dist/cjs/validate.js
CHANGED
|
@@ -69,6 +69,7 @@ async function validate() {
|
|
|
69
69
|
};
|
|
70
70
|
const visitor = await (0, helpers_js_1.validateScript)(inputFilePath, scriptData, scriptOptions);
|
|
71
71
|
const symbols = visitor.getSymbols().getSymbols();
|
|
72
|
+
const undefinedSymbols = [];
|
|
72
73
|
symbols.forEach((value, key) => {
|
|
73
74
|
if (value.type !== types_js_1.ParseSymbolType.Undefined) {
|
|
74
75
|
value = value;
|
|
@@ -78,12 +79,30 @@ async function validate() {
|
|
|
78
79
|
console.log(" " + instance.line + ":" + instance.column + " " + instance.start);
|
|
79
80
|
});
|
|
80
81
|
}
|
|
82
|
+
else {
|
|
83
|
+
undefinedSymbols.push(value);
|
|
84
|
+
}
|
|
81
85
|
});
|
|
82
86
|
const { parsedTokens } = await (0, helpers_js_1.getSemanticTokens)(scriptData, scriptOptions);
|
|
83
87
|
parsedTokens.forEach(item => {
|
|
84
88
|
const { line, column, tokenType, tokenModifiers, textValue } = item;
|
|
85
89
|
console.log(`${line}:${column} - ${textValue} - ${tokenType} | ${tokenModifiers.join(',')}`);
|
|
86
90
|
});
|
|
91
|
+
console.log('--- undefined ---');
|
|
92
|
+
undefinedSymbols.forEach(symbol => {
|
|
93
|
+
const { token } = symbol;
|
|
94
|
+
const info = {
|
|
95
|
+
start: {
|
|
96
|
+
line: (token?.line || 1),
|
|
97
|
+
character: token?.column || 0
|
|
98
|
+
},
|
|
99
|
+
end: {
|
|
100
|
+
line: (token?.line || 1),
|
|
101
|
+
character: (token?.column || 0) + ((token?.stop || 0) - (token?.start || 0) + 1)
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
console.log(token.text, info);
|
|
105
|
+
});
|
|
87
106
|
}
|
|
88
107
|
exports.default = validate;
|
|
89
108
|
validate();
|
package/dist/cjs/visitor.js
CHANGED
|
@@ -52,7 +52,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
catch (err) {
|
|
55
|
-
throw new utils_js_1.RuntimeExecutionError(err.message, ctx
|
|
55
|
+
throw new utils_js_1.RuntimeExecutionError(err.message, ctx);
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
return this.getExecutor().getCurrentPoint();
|
|
@@ -120,6 +120,24 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
120
120
|
};
|
|
121
121
|
this.visitCreate_component_expr = (ctx) => {
|
|
122
122
|
const scope = this.getScope();
|
|
123
|
+
const definedPinIds = [];
|
|
124
|
+
const arrangedPinIds = [];
|
|
125
|
+
const checkPinExistsAndNotDuplicated = (pinId, ctx) => {
|
|
126
|
+
if (definedPinIds.indexOf(pinId) === -1) {
|
|
127
|
+
this.warnings.push({
|
|
128
|
+
message: `Invalid pin ${pinId}`, ctx
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (arrangedPinIds.indexOf(pinId) !== -1) {
|
|
132
|
+
this.warnings.push({
|
|
133
|
+
message: `Pin ${pinId} specified more than once`,
|
|
134
|
+
ctx,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
arrangedPinIds.push(pinId);
|
|
138
|
+
};
|
|
139
|
+
let didDefineArrangeProp = false;
|
|
140
|
+
let didDefineDisplayProp = false;
|
|
123
141
|
scope.setOnPropertyHandler((path, value, ctx) => {
|
|
124
142
|
if (path.length === 1) {
|
|
125
143
|
const [, keyName] = path[0];
|
|
@@ -132,9 +150,25 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
132
150
|
case 'height':
|
|
133
151
|
this.validateNumeric(value, ctx);
|
|
134
152
|
break;
|
|
153
|
+
case 'display':
|
|
154
|
+
if (didDefineArrangeProp) {
|
|
155
|
+
throw new utils_js_1.RuntimeExecutionError("arrange property has already been defined", ctx);
|
|
156
|
+
}
|
|
157
|
+
didDefineDisplayProp = true;
|
|
158
|
+
break;
|
|
159
|
+
case 'arrange':
|
|
160
|
+
if (didDefineDisplayProp) {
|
|
161
|
+
throw new utils_js_1.RuntimeExecutionError("display property already defined", ctx);
|
|
162
|
+
}
|
|
163
|
+
didDefineArrangeProp = true;
|
|
164
|
+
break;
|
|
135
165
|
case 'pins':
|
|
136
166
|
if (!(value instanceof Map)) {
|
|
137
167
|
this.validateNumeric(value, ctx);
|
|
168
|
+
const numPins = value.toNumber();
|
|
169
|
+
for (let i = 0; i < numPins; i++) {
|
|
170
|
+
definedPinIds.push(i + 1);
|
|
171
|
+
}
|
|
138
172
|
}
|
|
139
173
|
break;
|
|
140
174
|
case 'copy':
|
|
@@ -145,7 +179,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
145
179
|
this.validateBoolean(value, ctx);
|
|
146
180
|
}
|
|
147
181
|
else {
|
|
148
|
-
throw new utils_js_1.RuntimeExecutionError("Invalid value for 'copy' property", ctx
|
|
182
|
+
throw new utils_js_1.RuntimeExecutionError("Invalid value for 'copy' property", ctx);
|
|
149
183
|
}
|
|
150
184
|
break;
|
|
151
185
|
}
|
|
@@ -155,20 +189,26 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
155
189
|
if (keyName === 'arrange') {
|
|
156
190
|
const [sideKeyCtx, sideKeyName] = path[1];
|
|
157
191
|
if (globals_js_1.ValidPinSides.indexOf(sideKeyName) === -1) {
|
|
158
|
-
throw new utils_js_1.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx
|
|
192
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx);
|
|
159
193
|
}
|
|
160
194
|
else {
|
|
161
|
-
if (path.length
|
|
195
|
+
if (path.length === 2 && value instanceof ParamDefinition_js_1.NumericValue) {
|
|
196
|
+
checkPinExistsAndNotDuplicated(value.toNumber(), ctx);
|
|
197
|
+
}
|
|
198
|
+
else if (path.length > 2 && path[2][0] === 'index') {
|
|
162
199
|
if (Array.isArray(value)) {
|
|
163
200
|
const goodBlank = value.length === 1 &&
|
|
164
201
|
value[0] instanceof ParamDefinition_js_1.NumericValue;
|
|
165
202
|
if (!goodBlank) {
|
|
166
|
-
throw new utils_js_1.RuntimeExecutionError(`Invalid blank specifier`, ctx
|
|
203
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid blank specifier`, ctx);
|
|
167
204
|
}
|
|
168
205
|
}
|
|
169
206
|
else {
|
|
170
207
|
if (!(value instanceof ParamDefinition_js_1.NumericValue)) {
|
|
171
|
-
throw new utils_js_1.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx
|
|
208
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
checkPinExistsAndNotDuplicated(value.toNumber(), ctx);
|
|
172
212
|
}
|
|
173
213
|
}
|
|
174
214
|
}
|
|
@@ -189,10 +229,12 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
189
229
|
}
|
|
190
230
|
else if (keyName === 'pins') {
|
|
191
231
|
if (path.length === 2) {
|
|
232
|
+
const idName = path[1][1];
|
|
233
|
+
definedPinIds.push(idName);
|
|
192
234
|
if (value.length === 2) {
|
|
193
235
|
const [pinType,] = value;
|
|
194
236
|
if (pinType instanceof types_js_1.UndeclaredReference) {
|
|
195
|
-
throw new utils_js_1.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx
|
|
237
|
+
throw new utils_js_1.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx);
|
|
196
238
|
}
|
|
197
239
|
}
|
|
198
240
|
}
|
|
@@ -421,7 +463,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
421
463
|
this.getScope().enterContext(ctxValue);
|
|
422
464
|
const keyName = this.visitResult(ctxKey);
|
|
423
465
|
const value = this.visitResult(ctxValue);
|
|
424
|
-
scope.triggerPropertyHandler(value, ctxValue);
|
|
466
|
+
scope.triggerPropertyHandler(this, value, ctxValue);
|
|
425
467
|
this.getScope().exitContext();
|
|
426
468
|
this.getScope().exitContext();
|
|
427
469
|
if (value instanceof types_js_1.UndeclaredReference && (value.reference.parentValue === undefined
|
|
@@ -442,7 +484,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
442
484
|
value = ctx.data_expr().map((item, index) => {
|
|
443
485
|
this.getScope().enterContext(index);
|
|
444
486
|
const result = this.visitResult(item);
|
|
445
|
-
this.getScope().triggerPropertyHandler(result, item);
|
|
487
|
+
this.getScope().triggerPropertyHandler(this, result, item);
|
|
446
488
|
this.getScope().exitContext();
|
|
447
489
|
return result;
|
|
448
490
|
});
|
|
@@ -1069,45 +1111,46 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1069
1111
|
parseCreateComponentPins(pinData) {
|
|
1070
1112
|
const pins = [];
|
|
1071
1113
|
if (pinData instanceof ParamDefinition_js_1.NumericValue) {
|
|
1114
|
+
const tmpMap = new Map();
|
|
1072
1115
|
const lastPin = pinData.toNumber();
|
|
1073
1116
|
for (let i = 0; i < lastPin; i++) {
|
|
1074
1117
|
const pinId = i + 1;
|
|
1075
|
-
|
|
1118
|
+
tmpMap.set(pinId, (0, ParamDefinition_js_1.numeric)(pinId));
|
|
1076
1119
|
}
|
|
1120
|
+
pinData = tmpMap;
|
|
1077
1121
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
else {
|
|
1099
|
-
pinName = pinDef[0];
|
|
1100
|
-
if (pinDef.length > 1) {
|
|
1101
|
-
altPinNames = pinDef.slice(1);
|
|
1102
|
-
}
|
|
1122
|
+
pinData = pinData ?? [];
|
|
1123
|
+
for (const [pinId, pinDef] of pinData) {
|
|
1124
|
+
let pinIdType = PinDefinition_js_1.PinIdType.Int;
|
|
1125
|
+
let pinType = PinTypes_js_1.PinTypes.Any;
|
|
1126
|
+
let pinName = null;
|
|
1127
|
+
let altPinNames = [];
|
|
1128
|
+
if (typeof pinId === 'string') {
|
|
1129
|
+
pinIdType = PinDefinition_js_1.PinIdType.Str;
|
|
1130
|
+
}
|
|
1131
|
+
if (Array.isArray(pinDef)) {
|
|
1132
|
+
const firstValue = pinDef[0];
|
|
1133
|
+
if (firstValue.type
|
|
1134
|
+
&& firstValue.type === globals_js_1.ReferenceTypes.pinType
|
|
1135
|
+
&& this.pinTypes.indexOf(firstValue.value) !== -1) {
|
|
1136
|
+
pinType = firstValue.value;
|
|
1137
|
+
pinName = pinDef[1];
|
|
1138
|
+
if (pinDef.length > 2) {
|
|
1139
|
+
altPinNames = pinDef.slice(2);
|
|
1103
1140
|
}
|
|
1104
1141
|
}
|
|
1105
1142
|
else {
|
|
1106
|
-
pinName = pinDef;
|
|
1143
|
+
pinName = pinDef[0];
|
|
1144
|
+
if (pinDef.length > 1) {
|
|
1145
|
+
altPinNames = pinDef.slice(1);
|
|
1146
|
+
}
|
|
1107
1147
|
}
|
|
1108
|
-
this.log('pins', pinId, pinIdType, pinName, pinType, altPinNames);
|
|
1109
|
-
pins.push(new PinDefinition_js_1.PinDefinition(pinId, pinIdType, pinName, pinType, altPinNames));
|
|
1110
1148
|
}
|
|
1149
|
+
else {
|
|
1150
|
+
pinName = pinDef;
|
|
1151
|
+
}
|
|
1152
|
+
this.log('pins', pinId, pinIdType, pinName, pinType, altPinNames);
|
|
1153
|
+
pins.push(new PinDefinition_js_1.PinDefinition(pinId, pinIdType, pinName, pinType, altPinNames));
|
|
1111
1154
|
}
|
|
1112
1155
|
return pins;
|
|
1113
1156
|
}
|
|
@@ -1316,6 +1359,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
|
|
|
1316
1359
|
});
|
|
1317
1360
|
return properties;
|
|
1318
1361
|
}
|
|
1362
|
+
getWarnings() {
|
|
1363
|
+
return this.warnings;
|
|
1364
|
+
}
|
|
1319
1365
|
}
|
|
1320
1366
|
exports.ParserVisitor = ParserVisitor;
|
|
1321
1367
|
const ComponentRefDesPrefixes = {
|
package/dist/esm/BaseVisitor.js
CHANGED
|
@@ -33,6 +33,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
33
33
|
onErrorHandler = null;
|
|
34
34
|
environment;
|
|
35
35
|
importedFiles = [];
|
|
36
|
+
warnings = [];
|
|
36
37
|
onImportFile = async (visitor, filePath, fileData, onErrorHandler) => {
|
|
37
38
|
throw "Import file not implemented";
|
|
38
39
|
};
|
|
@@ -41,7 +42,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
41
42
|
this.logger = new Logger();
|
|
42
43
|
this.onErrorHandler = onErrorHandler;
|
|
43
44
|
this.environment = environment;
|
|
44
|
-
this.startingContext = new ExecutionContext(DoubleDelimiter1, `${DoubleDelimiter1}.`, '/', 0, 0, silent, this.logger, null);
|
|
45
|
+
this.startingContext = new ExecutionContext(DoubleDelimiter1, `${DoubleDelimiter1}.`, '/', 0, 0, silent, this.logger, this.warnings, null);
|
|
45
46
|
const scope = this.startingContext.scope;
|
|
46
47
|
scope.sequence.push([
|
|
47
48
|
SequenceAction.At, scope.componentRoot, scope.currentPin
|
|
@@ -423,7 +424,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
423
424
|
this.setResult(ctx, returnList);
|
|
424
425
|
};
|
|
425
426
|
visitImport_expr = (ctx) => {
|
|
426
|
-
throw new RuntimeExecutionError("Cannot parse imports here", ctx
|
|
427
|
+
throw new RuntimeExecutionError("Cannot parse imports here", ctx);
|
|
427
428
|
};
|
|
428
429
|
visitFunction_return_expr = (ctx) => {
|
|
429
430
|
const executor = this.getExecutor();
|
|
@@ -517,7 +518,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
517
518
|
}
|
|
518
519
|
catch (err) {
|
|
519
520
|
if (ctx != null) {
|
|
520
|
-
throw new RuntimeExecutionError("An error occurred while importing file", ctx
|
|
521
|
+
throw new RuntimeExecutionError("An error occurred while importing file", ctx);
|
|
521
522
|
}
|
|
522
523
|
else {
|
|
523
524
|
this.log('An error occurred while importing file:', err.message);
|
|
@@ -533,7 +534,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
533
534
|
}
|
|
534
535
|
}
|
|
535
536
|
if (errorMessage !== null && ctx) {
|
|
536
|
-
throw new RuntimeExecutionError(errorMessage, ctx
|
|
537
|
+
throw new RuntimeExecutionError(errorMessage, ctx);
|
|
537
538
|
}
|
|
538
539
|
const newImportedFile = {
|
|
539
540
|
id: name.trim(),
|
|
@@ -637,7 +638,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
637
638
|
const executionLevel = currentExecutionContext.executionLevel;
|
|
638
639
|
const executionContextNamespace = currentExecutionContext.namespace
|
|
639
640
|
+ executionContextName + ".";
|
|
640
|
-
const newExecutor = new ExecutionContext(executionContextName, executionContextNamespace, netNamespace, executionLevel + 1, this.getExecutor().scope.indentLevel + 1, currentExecutionContext.silent, currentExecutionContext.logger, parentContext);
|
|
641
|
+
const newExecutor = new ExecutionContext(executionContextName, executionContextNamespace, netNamespace, executionLevel + 1, this.getExecutor().scope.indentLevel + 1, currentExecutionContext.silent, currentExecutionContext.logger, currentExecutionContext.warnings, parentContext);
|
|
641
642
|
executionStack.push(newExecutor);
|
|
642
643
|
this.setupDefinedParameters(funcDefinedParameters, passedInParameters, newExecutor);
|
|
643
644
|
return newExecutor;
|
|
@@ -654,7 +655,7 @@ export class BaseVisitor extends CircuitScriptVisitor {
|
|
|
654
655
|
}
|
|
655
656
|
const result = validateFunction(value);
|
|
656
657
|
if (!result) {
|
|
657
|
-
throw new RuntimeExecutionError(`Invalid ${expectedType}`, context
|
|
658
|
+
throw new RuntimeExecutionError(`Invalid ${expectedType}`, context);
|
|
658
659
|
}
|
|
659
660
|
return result;
|
|
660
661
|
}
|
package/dist/esm/draw_symbols.js
CHANGED
|
@@ -2,7 +2,7 @@ import { milsToMM } from "./helpers.js";
|
|
|
2
2
|
import { ColorScheme, CustomSymbolParamTextSize, CustomSymbolPinIdSize, CustomSymbolPinTextSize, CustomSymbolRefDesSize, PortArrowSize, PortPaddingHorizontal, PortPaddingVertical, ReferenceTypes, RenderFlags, SymbolPinSide, defaultFont, defaultPinIdTextSize, defaultPinNameTextSize, defaultSymbolLineWidth, fontDisplayScale } from "./globals.js";
|
|
3
3
|
import { Geometry, GeometryProp, HorizontalAlign, HorizontalAlignProp, Textbox, VerticalAlign, VerticalAlignProp } from "./geometry.js";
|
|
4
4
|
import { PinTypes } from "./objects/PinTypes.js";
|
|
5
|
-
import { roundValue, throwWithContext } from "./utils.js";
|
|
5
|
+
import { roundValue, RuntimeExecutionError, throwWithContext } from "./utils.js";
|
|
6
6
|
import { DeclaredReference, UndeclaredReference } from "./objects/types.js";
|
|
7
7
|
import { numeric, NumericValue } from "./objects/ParamDefinition.js";
|
|
8
8
|
export class SymbolGraphic {
|
|
@@ -81,6 +81,9 @@ export class SymbolGraphic {
|
|
|
81
81
|
}
|
|
82
82
|
pinPosition(id) {
|
|
83
83
|
const pin = this.drawing.getPinPosition(id);
|
|
84
|
+
if (pin === null) {
|
|
85
|
+
throw new RuntimeExecutionError(`Could not determine pin ${id} position`);
|
|
86
|
+
}
|
|
84
87
|
const [x, y] = pin.start;
|
|
85
88
|
const useX = roundValue(x);
|
|
86
89
|
const useY = roundValue(y);
|
package/dist/esm/execute.js
CHANGED
|
@@ -2,7 +2,7 @@ import { BlockTypes, ComponentTypes, Delimiter1, GlobalNames, NoNetText, ParamKe
|
|
|
2
2
|
import { ClassComponent, ModuleComponent } from './objects/ClassComponent.js';
|
|
3
3
|
import { ActiveObject, ExecutionScope, FrameAction, SequenceAction } from './objects/ExecutionScope.js';
|
|
4
4
|
import { Net } from './objects/Net.js';
|
|
5
|
-
import { numeric } from './objects/ParamDefinition.js';
|
|
5
|
+
import { numeric, NumericValue } from './objects/ParamDefinition.js';
|
|
6
6
|
import { PortSide } from './objects/PinDefinition.js';
|
|
7
7
|
import { DeclaredReference, Direction } from './objects/types.js';
|
|
8
8
|
import { Wire } from './objects/Wire.js';
|
|
@@ -27,7 +27,8 @@ export class ExecutionContext {
|
|
|
27
27
|
__functionCache = {};
|
|
28
28
|
parentContext;
|
|
29
29
|
componentAngleFollowsWire = true;
|
|
30
|
-
|
|
30
|
+
warnings = [];
|
|
31
|
+
constructor(name, namespace, netNamespace, executionLevel = 0, indentLevel = 0, silent = false, logger, warnings, parent) {
|
|
31
32
|
this.name = name;
|
|
32
33
|
this.namespace = namespace;
|
|
33
34
|
this.netNamespace = netNamespace;
|
|
@@ -39,6 +40,14 @@ export class ExecutionContext {
|
|
|
39
40
|
this.silent = silent;
|
|
40
41
|
this.log('create new execution context', this.namespace, this.name, this.scope.indentLevel);
|
|
41
42
|
this.parentContext = parent;
|
|
43
|
+
this.warnings = warnings;
|
|
44
|
+
}
|
|
45
|
+
logWarning(message, context, fileName) {
|
|
46
|
+
this.warnings.push({
|
|
47
|
+
message,
|
|
48
|
+
ctx: context,
|
|
49
|
+
fileName,
|
|
50
|
+
});
|
|
42
51
|
}
|
|
43
52
|
log(...params) {
|
|
44
53
|
const indentOutput = ''.padStart(this.scope.indentLevel * 4, ' ');
|
|
@@ -125,7 +134,6 @@ export class ExecutionContext {
|
|
|
125
134
|
pins.forEach((pin) => {
|
|
126
135
|
component.pins.set(pin.id, pin);
|
|
127
136
|
});
|
|
128
|
-
component.arrangeProps = props.arrange ?? null;
|
|
129
137
|
component.displayProp = props.display ?? null;
|
|
130
138
|
component.widthProp = props.width ?? null;
|
|
131
139
|
component.heightProp = props.height ?? null;
|
|
@@ -138,6 +146,33 @@ export class ExecutionContext {
|
|
|
138
146
|
useAngle += 360;
|
|
139
147
|
}
|
|
140
148
|
}
|
|
149
|
+
if (props.display === null && props.arrange === null) {
|
|
150
|
+
const tmpArrangeLeft = [];
|
|
151
|
+
const tmpArrangeRight = [];
|
|
152
|
+
pins.forEach((pin, index) => {
|
|
153
|
+
const useArray = (index % 2 === 0) ? tmpArrangeLeft : tmpArrangeRight;
|
|
154
|
+
useArray.push(numeric(pin.id));
|
|
155
|
+
});
|
|
156
|
+
const arrangeProp = new Map([
|
|
157
|
+
[SymbolPinSide.Left, tmpArrangeLeft],
|
|
158
|
+
[SymbolPinSide.Right, tmpArrangeRight]
|
|
159
|
+
]);
|
|
160
|
+
props.arrange = arrangeProp;
|
|
161
|
+
}
|
|
162
|
+
if (props.arrange !== null) {
|
|
163
|
+
component.arrangeProps = this.removeArrangePropDuplicates(props.arrange);
|
|
164
|
+
const arrangePropPins = this.getArrangePropPins(component.arrangeProps).map(item => {
|
|
165
|
+
return item.toNumber();
|
|
166
|
+
});
|
|
167
|
+
pins.forEach(pin => {
|
|
168
|
+
if (arrangePropPins.indexOf(pin.id) === -1) {
|
|
169
|
+
this.logWarning(`Pin ${pin.id} is not specified in arrange property`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
component.arrangeProps = null;
|
|
175
|
+
}
|
|
141
176
|
component.angleProp = useAngle ?? 0;
|
|
142
177
|
component.followWireOrientationProp = props.followWireOrientation;
|
|
143
178
|
const paramsMap = new Map();
|
|
@@ -181,6 +216,59 @@ export class ExecutionContext {
|
|
|
181
216
|
this.log('add symbol', instanceName, '[' + pinsOutput.join(', ') + ']');
|
|
182
217
|
return component;
|
|
183
218
|
}
|
|
219
|
+
removeArrangePropDuplicates(arrangeProp) {
|
|
220
|
+
const sides = [
|
|
221
|
+
SymbolPinSide.Left,
|
|
222
|
+
SymbolPinSide.Right,
|
|
223
|
+
SymbolPinSide.Top,
|
|
224
|
+
SymbolPinSide.Bottom
|
|
225
|
+
];
|
|
226
|
+
const result = new Map();
|
|
227
|
+
const seenIds = [];
|
|
228
|
+
sides.forEach(side => {
|
|
229
|
+
let items = arrangeProp.get(side) ?? [];
|
|
230
|
+
if (!Array.isArray(items)) {
|
|
231
|
+
items = [items];
|
|
232
|
+
}
|
|
233
|
+
const uniqueItems = [];
|
|
234
|
+
items.forEach(item => {
|
|
235
|
+
if (item instanceof NumericValue) {
|
|
236
|
+
if (seenIds.indexOf(item.toNumber()) === -1) {
|
|
237
|
+
seenIds.push(item.toNumber());
|
|
238
|
+
uniqueItems.push(item);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
this.logWarning(`Pin ${item.toNumber()} specified more than once in arrange property`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
uniqueItems.push(item);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
result.set(side, uniqueItems);
|
|
249
|
+
});
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
getArrangePropPins(arrangeProps) {
|
|
253
|
+
const pins = [];
|
|
254
|
+
const sides = [
|
|
255
|
+
SymbolPinSide.Left,
|
|
256
|
+
SymbolPinSide.Right,
|
|
257
|
+
SymbolPinSide.Top,
|
|
258
|
+
SymbolPinSide.Bottom
|
|
259
|
+
];
|
|
260
|
+
sides.forEach(side => {
|
|
261
|
+
const items = arrangeProps.get(side);
|
|
262
|
+
if (items) {
|
|
263
|
+
items.forEach(item => {
|
|
264
|
+
if (item instanceof NumericValue) {
|
|
265
|
+
pins.push(item);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
return pins;
|
|
271
|
+
}
|
|
184
272
|
printPoint(extra = '') {
|
|
185
273
|
let netString = NoNetText;
|
|
186
274
|
if (this.scope.currentComponent === null || this.scope.currentPin === null) {
|
package/dist/esm/export.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NoNetText } from "./globals.js";
|
|
2
2
|
import { NumericValue } from "./objects/ParamDefinition.js";
|
|
3
3
|
export function generateKiCADNetList(netlist) {
|
|
4
4
|
const componentsList = [];
|
|
@@ -47,11 +47,6 @@ export function generateKiCADNetList(netlist) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
else {
|
|
50
|
-
if (instance.typeProp !== ComponentTypes.net &&
|
|
51
|
-
instance.typeProp !== ComponentTypes.graphic &&
|
|
52
|
-
instance.typeProp !== null) {
|
|
53
|
-
console.log('Skipping', instance.instanceName);
|
|
54
|
-
}
|
|
55
50
|
}
|
|
56
51
|
});
|
|
57
52
|
const netItems = [];
|
package/dist/esm/helpers.js
CHANGED
|
@@ -5,7 +5,7 @@ import { generateKiCADNetList, printTree } from "./export.js";
|
|
|
5
5
|
import { LayoutEngine } from "./layout.js";
|
|
6
6
|
import { parseFileWithVisitor } from "./parser.js";
|
|
7
7
|
import { generatePdfOutput, generateSvgOutput, renderSheetsToSVG } from "./render.js";
|
|
8
|
-
import { generateDebugSequenceAction, ParseError, ParseSyntaxError, RenderError, resolveToNumericValue, RuntimeExecutionError, sequenceActionString, SimpleStopwatch } from "./utils.js";
|
|
8
|
+
import { generateDebugSequenceAction, ParseError, ParseSyntaxError, printWarnings, RenderError, resolveToNumericValue, RuntimeExecutionError, sequenceActionString, SimpleStopwatch } from "./utils.js";
|
|
9
9
|
import { ParserVisitor } from "./visitor.js";
|
|
10
10
|
import { SymbolValidatorVisitor } from "./validate/SymbolValidatorVisitor.js";
|
|
11
11
|
import { SymbolValidatorResolveVisitor } from "./validate/SymbolValidatorResolveVisitor.js";
|
|
@@ -154,7 +154,21 @@ export async function renderScript(scriptData, outputPath, options) {
|
|
|
154
154
|
errors.push(error);
|
|
155
155
|
}
|
|
156
156
|
else if (error && error instanceof RecognitionException) {
|
|
157
|
-
|
|
157
|
+
if (context !== null) {
|
|
158
|
+
errors.push(new ParseSyntaxError(message, context.start, context.stop));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
if (error.recognizer) {
|
|
162
|
+
const recognizer = error.recognizer;
|
|
163
|
+
errors.push(new ParseSyntaxError(message, {
|
|
164
|
+
line: recognizer.currentTokenStartLine,
|
|
165
|
+
column: recognizer.currentTokenColumn
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
errors.push(new ParseSyntaxError(message));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
158
172
|
}
|
|
159
173
|
else {
|
|
160
174
|
errors.push(new ParseError(message, context.start, context.stop));
|
|
@@ -171,6 +185,7 @@ export async function renderScript(scriptData, outputPath, options) {
|
|
|
171
185
|
visitor.log('reading file');
|
|
172
186
|
visitor.log('done reading file');
|
|
173
187
|
const { tree, parser, parserTimeTaken, lexerTimeTaken } = await parseFileWithVisitor(visitor, scriptData);
|
|
188
|
+
printWarnings(visitor.getWarnings());
|
|
174
189
|
showStats && console.log('Lexing took:', lexerTimeTaken);
|
|
175
190
|
showStats && console.log('Parsing took:', parserTimeTaken);
|
|
176
191
|
if (dumpNets) {
|
|
@@ -214,7 +229,10 @@ export async function renderScript(scriptData, outputPath, options) {
|
|
|
214
229
|
});
|
|
215
230
|
writeFileSync(outputPath, printTree(kicadNetList));
|
|
216
231
|
console.log('Generated file', outputPath);
|
|
217
|
-
return
|
|
232
|
+
return {
|
|
233
|
+
svgOutput: null,
|
|
234
|
+
errors,
|
|
235
|
+
};
|
|
218
236
|
}
|
|
219
237
|
const layoutEngine = new LayoutEngine();
|
|
220
238
|
const layoutTimer = new SimpleStopwatch();
|