circuitscript 0.1.31 → 0.1.33

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 (58) hide show
  1. package/dist/cjs/BaseVisitor.js +37 -3
  2. package/dist/cjs/RefdesAnnotationVisitor.js +27 -10
  3. package/dist/cjs/antlr/CircuitScriptParser.js +990 -831
  4. package/dist/cjs/draw_symbols.js +38 -34
  5. package/dist/cjs/environment.js +24 -4
  6. package/dist/cjs/execute.js +107 -68
  7. package/dist/cjs/globals.js +4 -2
  8. package/dist/cjs/graph.js +14 -12
  9. package/dist/cjs/helpers.js +85 -16
  10. package/dist/cjs/layout.js +50 -25
  11. package/dist/cjs/main.js +16 -18
  12. package/dist/cjs/objects/ClassComponent.js +199 -30
  13. package/dist/cjs/objects/types.js +5 -1
  14. package/dist/cjs/regenerate-tests.js +3 -3
  15. package/dist/cjs/render.js +5 -3
  16. package/dist/cjs/rules-check/no-connect-on-connected-pin.js +9 -8
  17. package/dist/cjs/rules-check/rules.js +7 -2
  18. package/dist/cjs/rules-check/unconnected-pins.js +10 -8
  19. package/dist/cjs/utils.js +2 -1
  20. package/dist/cjs/validate/SymbolValidatorVisitor.js +0 -10
  21. package/dist/cjs/visitor.js +284 -191
  22. package/dist/esm/BaseVisitor.js +37 -3
  23. package/dist/esm/RefdesAnnotationVisitor.js +27 -10
  24. package/dist/esm/antlr/CircuitScriptParser.js +989 -830
  25. package/dist/esm/antlr/CircuitScriptVisitor.js +1 -0
  26. package/dist/esm/draw_symbols.js +38 -34
  27. package/dist/esm/environment.js +21 -1
  28. package/dist/esm/execute.js +108 -69
  29. package/dist/esm/globals.js +2 -0
  30. package/dist/esm/graph.js +14 -12
  31. package/dist/esm/helpers.js +86 -17
  32. package/dist/esm/layout.js +51 -26
  33. package/dist/esm/main.js +16 -18
  34. package/dist/esm/objects/ClassComponent.js +201 -30
  35. package/dist/esm/objects/types.js +7 -1
  36. package/dist/esm/regenerate-tests.js +3 -3
  37. package/dist/esm/render.js +5 -3
  38. package/dist/esm/rules-check/no-connect-on-connected-pin.js +9 -8
  39. package/dist/esm/rules-check/rules.js +7 -2
  40. package/dist/esm/rules-check/unconnected-pins.js +10 -8
  41. package/dist/esm/utils.js +2 -1
  42. package/dist/esm/validate/SymbolValidatorVisitor.js +0 -10
  43. package/dist/esm/visitor.js +185 -92
  44. package/dist/types/BaseVisitor.d.ts +15 -5
  45. package/dist/types/RefdesAnnotationVisitor.d.ts +2 -0
  46. package/dist/types/antlr/CircuitScriptParser.d.ts +32 -14
  47. package/dist/types/antlr/CircuitScriptVisitor.d.ts +2 -0
  48. package/dist/types/environment.d.ts +7 -1
  49. package/dist/types/execute.d.ts +4 -1
  50. package/dist/types/globals.d.ts +2 -0
  51. package/dist/types/graph.d.ts +2 -2
  52. package/dist/types/helpers.d.ts +2 -1
  53. package/dist/types/layout.d.ts +5 -4
  54. package/dist/types/objects/ClassComponent.d.ts +34 -9
  55. package/dist/types/objects/types.d.ts +19 -3
  56. package/dist/types/validate/SymbolValidatorVisitor.d.ts +0 -4
  57. package/dist/types/visitor.d.ts +7 -1
  58. package/package.json +1 -1
@@ -13,7 +13,7 @@ import { BaseErrorListener, CharStream, CommonTokenStream, DefaultErrorStrategy,
13
13
  import { MainLexer } from "./lexer.js";
14
14
  import { CircuitScriptParser } from "./antlr/CircuitScriptParser.js";
15
15
  import { prepareTokens, SemanticTokensVisitor } from "./SemanticTokenVisitor.js";
16
- import { defaultPageMarginMM, defaultZoomScale, LengthUnit, MilsToMM, PxToMM } from "./globals.js";
16
+ import { defaultPageMarginMM, defaultZoomScale, LengthUnit, MilsToMM, PxToMM, RefdesFileSuffix } from "./globals.js";
17
17
  import { FrameParamKeys } from "./objects/Frame.js";
18
18
  import Big from "big.js";
19
19
  import { Logger } from "./logger.js";
@@ -150,25 +150,85 @@ export async function validateScript(filePath, scriptData, options) {
150
150
  await visitorResolver.visitAsync(tree);
151
151
  return visitorResolver;
152
152
  }
153
- async function DefaultPostAnnotationCallback(options, scriptData, tree, tokens, componentLinks) {
153
+ async function DefaultPostAnnotationCallback(options, scriptData, tree, tokens, componentLinks, importedModules, environment) {
154
154
  const { inputPath = null, updateSource = false, saveAnnotatedCopy = undefined, } = options;
155
155
  if (inputPath && (updateSource || saveAnnotatedCopy !== undefined)) {
156
- const refdesVisitor = new RefdesAnnotationVisitor(true, scriptData, tokens, componentLinks);
157
- await refdesVisitor.visitAsync(tree);
158
- let usePath = inputPath;
159
- if (saveAnnotatedCopy === true) {
160
- const dir = path.dirname(inputPath);
161
- const ext = path.extname(inputPath);
162
- const basename = path.basename(inputPath, ext);
163
- usePath = path.join(dir, `${basename}.annotated${ext}`);
156
+ const annotatedFiles = [{
157
+ isMainFile: true,
158
+ scriptData,
159
+ tokens,
160
+ tree,
161
+ filePath: inputPath,
162
+ outputType: RefdesOutputType.WithSource
163
+ }];
164
+ for (const module of importedModules) {
165
+ let outputType = RefdesOutputType.None;
166
+ if (module.enableRefdesAnnotation) {
167
+ outputType = RefdesOutputType.WithSource;
168
+ }
169
+ else if (module.enableRefdesAnnotationFile) {
170
+ outputType = RefdesOutputType.CreateExternalFile;
171
+ }
172
+ if (outputType !== RefdesOutputType.None) {
173
+ const { moduleFilePath, moduleName, tokens: moduleTokens, tree: moduleTree } = module;
174
+ const moduleScriptData = await environment.readFile(moduleFilePath, { encoding: 'utf8' });
175
+ annotatedFiles.push({
176
+ tokens: moduleTokens,
177
+ tree: moduleTree,
178
+ filePath: moduleFilePath,
179
+ scriptData: moduleScriptData,
180
+ moduleName,
181
+ outputType
182
+ });
183
+ }
164
184
  }
165
- else if (typeof saveAnnotatedCopy === 'string') {
166
- usePath = saveAnnotatedCopy;
185
+ for (const item of annotatedFiles) {
186
+ const { scriptData, tokens, tree, filePath, moduleName, isMainFile = false } = item;
187
+ const tmpVisitor = new RefdesAnnotationVisitor(true, scriptData, tokens, componentLinks);
188
+ await tmpVisitor.visit(tree);
189
+ let usePath = filePath;
190
+ if (isMainFile && saveAnnotatedCopy === true) {
191
+ const dir = environment.dirname(filePath);
192
+ const ext = environment.extname(filePath);
193
+ const basename = environment.basename(filePath, ext);
194
+ usePath = environment.join(dir, `${basename}.annotated${ext}`);
195
+ }
196
+ else if (isMainFile && typeof saveAnnotatedCopy === 'string') {
197
+ usePath = saveAnnotatedCopy;
198
+ }
199
+ if (item.outputType === RefdesOutputType.WithSource) {
200
+ environment.writeFileSync(usePath, tmpVisitor.getOutput());
201
+ }
202
+ else if (item.outputType === RefdesOutputType.CreateExternalFile) {
203
+ const dir = environment.dirname(usePath);
204
+ const ext = environment.extname(usePath);
205
+ const basename = environment.basename(filePath, ext);
206
+ usePath = environment.join(dir, `${basename}${RefdesFileSuffix}`);
207
+ const output = tmpVisitor.getOutputForExternalRefdesFile();
208
+ const inputDir = environment.dirname(inputPath);
209
+ const relativeFilePath = environment.relative(inputDir, filePath);
210
+ const jsonFile = {
211
+ format: 'v1',
212
+ module: moduleName,
213
+ file: relativeFilePath,
214
+ items: output,
215
+ };
216
+ environment.writeFileSync(usePath, JSON.stringify(jsonFile, null, 4));
217
+ }
218
+ let display = 'Refdes annotations';
219
+ if (moduleName) {
220
+ display += ` for module ${moduleName}`;
221
+ }
222
+ console.log(`${display} saved to ${usePath}`);
167
223
  }
168
- console.log('Annotations saved to ' + usePath);
169
- writeFileSync(usePath, refdesVisitor.getOutput());
170
224
  }
171
225
  }
226
+ var RefdesOutputType;
227
+ (function (RefdesOutputType) {
228
+ RefdesOutputType["None"] = "none";
229
+ RefdesOutputType["WithSource"] = "with-source";
230
+ RefdesOutputType["CreateExternalFile"] = "create-external-file";
231
+ })(RefdesOutputType || (RefdesOutputType = {}));
172
232
  export async function renderScript(scriptData, outputPath, options) {
173
233
  const parseHandlers = [
174
234
  new KiCadNetListOutputHandler(),
@@ -206,7 +266,9 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
206
266
  environment.setCurrentFile(inputPath);
207
267
  const visitor = new ParserVisitor(true, onErrorHandler, environment);
208
268
  visitor.onImportFile = async (visitor, filePath, fileData) => {
209
- const { hasError, hasParseError, throwError } = await parseFileWithVisitor(visitor, fileData);
269
+ visitor.enterFile(filePath);
270
+ const { hasError, hasParseError, throwError, tree, tokens } = await parseFileWithVisitor(visitor, fileData);
271
+ visitor.exitFile();
210
272
  if (hasError || hasParseError) {
211
273
  let importErrorMsg = "";
212
274
  if (throwError) {
@@ -214,7 +276,7 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
214
276
  }
215
277
  throw new ParseError(`Error parsing imported file: ${filePath}${importErrorMsg}`, undefined, undefined, filePath);
216
278
  }
217
- return { hasError, hasParseError };
279
+ return { hasError, hasParseError, tree, tokens };
218
280
  };
219
281
  visitor.log('reading file');
220
282
  visitor.log('done reading file');
@@ -225,6 +287,9 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
225
287
  mkdirSync(dumpDirectory);
226
288
  }
227
289
  }
290
+ if (inputPath !== '') {
291
+ visitor.enterFile(inputPath);
292
+ }
228
293
  const { tree, parser, tokens, parserTimeTaken, lexerTimeTaken, throwError } = await parseFileWithVisitor(visitor, scriptData);
229
294
  printWarnings(visitor.getWarnings());
230
295
  showStats && console.log('Lexing took:', lexerTimeTaken);
@@ -236,8 +301,9 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
236
301
  throw new RenderError(`Error during component annotation: ${err}`, 'annotation');
237
302
  }
238
303
  const componentLinks = visitor.getComponentCtxLinks();
304
+ const importedModules = Array.from(visitor.getScope().modules.values());
239
305
  for (let i = 0; i < postAnnotationCallbacks.length; i++) {
240
- await postAnnotationCallbacks[i](options, scriptData, tree, tokens, componentLinks);
306
+ await postAnnotationCallbacks[i](options, scriptData, tree, tokens, componentLinks, importedModules, environment);
241
307
  }
242
308
  if (dumpNets) {
243
309
  const nets = visitor.dumpNets();
@@ -296,6 +362,9 @@ export async function renderScriptCustom(scriptData, outputPath, options, parseH
296
362
  console.log(`${(index + 1).toString().padStart(3)}. line ${item.start.line}, column ${item.start.column}: ${item.type} - ${item.message}`);
297
363
  });
298
364
  }
365
+ else {
366
+ console.log('No ERC issues found');
367
+ }
299
368
  }
300
369
  }
301
370
  catch (err) {
@@ -1,7 +1,7 @@
1
1
  import graphlib from '@dagrejs/graphlib';
2
2
  const { alg } = graphlib;
3
3
  import { SymbolCustom, SymbolDrawing, SymbolPlaceholder, SymbolText, PlaceHolderCommands } from "./draw_symbols.js";
4
- import { defaultFrameTitleTextSize, defaultGridSizeUnits, FrameType, NetGraphicsParams, ParamKeys, WireAutoDirection } from './globals.js';
4
+ import { DefaultComponentUnit, defaultFrameTitleTextSize, defaultGridSizeUnits, FrameType, NetGraphicsParams, ParamKeys, WireAutoDirection } from './globals.js';
5
5
  import { Geometry, HorizontalAlign, VerticalAlign } from './geometry.js';
6
6
  import { FixedFrameIds, Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.js';
7
7
  import { areasOverlap, combineMaps, getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, roundValue, toNearestGrid } from './utils.js';
@@ -301,7 +301,8 @@ export class LayoutEngine {
301
301
  const avoidAreas = [];
302
302
  if (frameParams.has(FrameParamKeys.SheetType)) {
303
303
  const frameComponent = frameParams.get(FrameParamKeys.SheetType);
304
- const frameDrawing = frameComponent.displayProp;
304
+ const frameComponentUnit = frameComponent.getUnit();
305
+ const frameDrawing = frameComponentUnit.displayProp;
305
306
  frameDrawing.variables = combineMaps(frameComponent.parameters, frameParams);
306
307
  const rects = ExtractDrawingRects(frameDrawing);
307
308
  const drawableRect = rects.find(rect => rect.className === 'plot-area');
@@ -560,7 +561,7 @@ export class LayoutEngine {
560
561
  accum.push(item);
561
562
  }
562
563
  else if (item instanceof RenderComponent) {
563
- const { instanceName } = item.component;
564
+ const { instanceName } = item.component.getUnit(item.unitId);
564
565
  if (ignoreItems.indexOf(instanceName) === -1) {
565
566
  const withinSubgraph = subgraphInfo.find(subgraphInfo => {
566
567
  return subgraphInfo.components.indexOf(instanceName) !== -1;
@@ -692,7 +693,9 @@ export class LayoutEngine {
692
693
  const [, node1] = graph.node(firstNodeId);
693
694
  let defaultPin = new PinId(1);
694
695
  if (node1 instanceof RenderComponent) {
695
- defaultPin = node1.component.getDefaultPin();
696
+ const unitId = node1.unitId;
697
+ const componentUnit = node1.component.getUnit(unitId);
698
+ defaultPin = componentUnit.pinsFlat[0].id;
696
699
  }
697
700
  this.placeNodeAtPosition(numeric(0), numeric(0), node1, defaultPin);
698
701
  return;
@@ -766,7 +769,8 @@ export class LayoutEngine {
766
769
  }
767
770
  [node1, node2].forEach(item => {
768
771
  if (item instanceof RenderWire && item.isEndAutoLength()) {
769
- const [instance, pin] = item.getEndAuto();
772
+ const [component, pin] = item.getEndAuto();
773
+ const instance = component.getUnitForPin(pin);
770
774
  const [, targetNode] = graph.node(instance.instanceName);
771
775
  this.print('wire', item, 'auto length to target:', instance, pin);
772
776
  if (targetNode.isFloating) {
@@ -922,24 +926,43 @@ function getNeighbours(graph, nodeIds) {
922
926
  return accum;
923
927
  }, []);
924
928
  }
925
- export function applyComponentParamsToSymbol(component, symbol) {
926
- const { widthProp = null, heightProp = null } = component;
927
- const newMap = new Map(component.parameters);
928
- if (!newMap.has('refdes')) {
929
- newMap.set('refdes', component.assignedRefDes ?? "?");
929
+ export function applyComponentParamsToSymbol(componentUnit, symbol) {
930
+ const { widthProp = null, heightProp = null } = componentUnit;
931
+ const newMap = new Map(componentUnit.parameters);
932
+ const ignoreParams = [
933
+ ParamKeys.angle,
934
+ ParamKeys.flip,
935
+ ParamKeys.flipX,
936
+ ParamKeys.flipY,
937
+ ];
938
+ const parentParams = componentUnit.parent.parameters;
939
+ parentParams.forEach((value, key) => {
940
+ if (ignoreParams.indexOf(key) === -1) {
941
+ newMap.set(key, value);
942
+ }
943
+ });
944
+ const refdesKey = 'refdes';
945
+ if (!newMap.has(refdesKey)) {
946
+ newMap.set(refdesKey, componentUnit.parent.assignedRefDes ?? "?");
947
+ }
948
+ if (componentUnit.refdesSuffix !== "") {
949
+ const tmpRefdes = newMap.get(refdesKey);
950
+ newMap.set(refdesKey, `${tmpRefdes}${componentUnit.refdesSuffix}`);
930
951
  }
931
952
  symbol.drawing.variables = newMap;
932
- if (component.parameters.has(ParamKeys.angle)) {
933
- const value = component.parameters.get(ParamKeys.angle).toNumber();
953
+ if (componentUnit.parameters.has(ParamKeys.angle)) {
954
+ const value = componentUnit.parameters.get(ParamKeys.angle).toNumber();
934
955
  symbol.angle = value;
935
956
  }
936
- if (component.parameters.has(ParamKeys.flipX)) {
957
+ if (componentUnit.parameters.has(ParamKeys.flipX)) {
937
958
  symbol.flipX =
938
- component.parameters.get(ParamKeys.flipX);
959
+ componentUnit.parameters.get(ParamKeys.flipX)
960
+ .toNumber();
939
961
  }
940
- if (component.parameters.has(ParamKeys.flipY)) {
962
+ if (componentUnit.parameters.has(ParamKeys.flipY)) {
941
963
  symbol.flipY =
942
- component.parameters.get(ParamKeys.flipY);
964
+ componentUnit.parameters.get(ParamKeys.flipY)
965
+ .toNumber();
943
966
  }
944
967
  if (symbol instanceof SymbolCustom) {
945
968
  if (widthProp) {
@@ -1176,13 +1199,15 @@ export class RenderWire extends RenderObject {
1176
1199
  }
1177
1200
  export class RenderComponent extends RenderObject {
1178
1201
  component;
1202
+ unitId = DefaultComponentUnit;
1179
1203
  symbol;
1180
1204
  width;
1181
1205
  height;
1182
1206
  displaySymbol = null;
1183
- constructor(component, width, height) {
1207
+ constructor(component, unitId, width, height) {
1184
1208
  super();
1185
1209
  this.component = component;
1210
+ this.unitId = unitId;
1186
1211
  this.width = width;
1187
1212
  this.height = height;
1188
1213
  }
@@ -1271,22 +1296,22 @@ export class RenderJunction {
1271
1296
  this.net = net;
1272
1297
  }
1273
1298
  }
1274
- export function CalculatePinPositions(component) {
1299
+ export function CalculatePinPositions(unit) {
1275
1300
  const pinPositionMapping = new Map();
1276
1301
  let tmpSymbol;
1277
- if (component.displayProp !== null
1278
- && component.displayProp instanceof SymbolDrawing) {
1279
- tmpSymbol = new SymbolPlaceholder(component.displayProp);
1302
+ if (unit.displayProp !== null
1303
+ && unit.displayProp instanceof SymbolDrawing) {
1304
+ tmpSymbol = new SymbolPlaceholder(unit.displayProp);
1280
1305
  }
1281
1306
  else {
1282
- const symbolPinDefinitions = generateLayoutPinDefinition(component);
1283
- tmpSymbol = new SymbolCustom(symbolPinDefinitions, component.pinsMaxPositions);
1307
+ const symbolPinDefinitions = generateLayoutPinDefinition(unit);
1308
+ tmpSymbol = new SymbolCustom(symbolPinDefinitions, unit.pinsMaxPositions);
1284
1309
  }
1285
- applyComponentParamsToSymbol(component, tmpSymbol);
1310
+ applyComponentParamsToSymbol(unit, tmpSymbol);
1286
1311
  tmpSymbol.refreshDrawing();
1287
- const pins = component.pins;
1312
+ const pins = unit.pins;
1288
1313
  pins.forEach((value, key) => {
1289
- if (component._unplacedPins.indexOf(key) === -1) {
1314
+ if (unit._unplacedPins.indexOf(key) === -1) {
1290
1315
  pinPositionMapping.set(key, tmpSymbol.pinPosition(key));
1291
1316
  }
1292
1317
  });
package/dist/esm/main.js CHANGED
@@ -14,7 +14,6 @@ export default async function main() {
14
14
  .argument('[input path]', 'Input path')
15
15
  .argument('[output path]', 'Output path')
16
16
  .option('-i, --input text <input text>', 'Input text directly')
17
- .option('-c, --current-directory <path>', 'Set current directory')
18
17
  .option('-u, --update-source', 'Update source file with refdes annotation')
19
18
  .option('-j, --annotated-path [file-path]', 'Save annotated source file at given path')
20
19
  .option('-w, --watch', 'Watch for file changes')
@@ -39,9 +38,6 @@ export default async function main() {
39
38
  const enableErc = options.erc;
40
39
  const enableBom = options.bom !== undefined;
41
40
  let bomOutputPath = options.bom;
42
- if (options.currentDirectory) {
43
- throw "Parameter not supported yet";
44
- }
45
41
  if (watchFileChanges) {
46
42
  console.log('watching for file changes...');
47
43
  }
@@ -52,22 +48,20 @@ export default async function main() {
52
48
  return;
53
49
  }
54
50
  let scriptData;
55
- if (args.length > 0 && args[0]) {
56
- inputFilePath = args[0];
57
- if ((await env.exists(inputFilePath))) {
58
- scriptData = await env.readFile(inputFilePath, { encoding: 'utf-8' });
59
- }
60
- else {
61
- console.error("Error: File could not be found");
62
- return;
63
- }
64
- }
65
- else if (options.input) {
51
+ if (options.input) {
66
52
  scriptData = options.input;
67
53
  }
68
54
  else {
69
- console.error("Error: No input provided");
70
- return;
55
+ if (args.length > 0 && args[0]) {
56
+ inputFilePath = args[0];
57
+ if ((await env.exists(inputFilePath))) {
58
+ scriptData = await env.readFile(inputFilePath, { encoding: 'utf-8' });
59
+ }
60
+ else {
61
+ console.error("Error: File could not be found");
62
+ return;
63
+ }
64
+ }
71
65
  }
72
66
  let updateSource = false;
73
67
  if (options.updateSource !== undefined) {
@@ -98,7 +92,10 @@ export default async function main() {
98
92
  saveAnnotatedCopy: saveAnnotatedCopyPath,
99
93
  };
100
94
  let outputPath = null;
101
- if (args.length > 0 && args[1]) {
95
+ if (options.input && args.length > 0 && args[0]) {
96
+ outputPath = args[0];
97
+ }
98
+ else if (args.length > 0 && args[1]) {
102
99
  outputPath = args[1];
103
100
  }
104
101
  const output = await parseFile(scriptData, outputPath, scriptOptions);
@@ -127,6 +124,7 @@ async function parseFile(scriptData, outputPath, scriptOptions) {
127
124
  }
128
125
  catch (error) {
129
126
  console.error(`Unexpected Error: ${error}`);
127
+ console.log(error.stack);
130
128
  }
131
129
  return null;
132
130
  }
@@ -1,8 +1,133 @@
1
1
  import { SymbolDrawingCommands } from '../draw_symbols.js';
2
2
  import { PinDefinition, PinId, PinIdType } from './PinDefinition.js';
3
3
  import { PinTypes } from './PinTypes.js';
4
- import { ParamKeys } from '../globals.js';
4
+ import { DefaultComponentUnit, ParamKeys } from '../globals.js';
5
5
  import { RuntimeExecutionError } from '../utils.js';
6
+ export class ComponentUnit {
7
+ parent;
8
+ unitId;
9
+ refdesSuffix = "A";
10
+ suffix = null;
11
+ get instanceName() {
12
+ return `${this.parent.instanceName},${this.unitId}`;
13
+ }
14
+ parameters = new Map();
15
+ numPins;
16
+ pins = new Map();
17
+ pinsFlat = [];
18
+ pinsMaxPositions = new Map();
19
+ arrangeProps = null;
20
+ displayProp = null;
21
+ widthProp = null;
22
+ heightProp = null;
23
+ angleProp = 0;
24
+ followWireOrientationProp = true;
25
+ wireOrientationAngle = 0;
26
+ useWireOrientationAngle = true;
27
+ didSetWireOrientationAngle = false;
28
+ _unplacedPins = [];
29
+ constructor(unitId, parent) {
30
+ this.unitId = unitId;
31
+ this.parent = parent;
32
+ }
33
+ clone() {
34
+ const unit = new ComponentUnit(this.unitId, this.parent);
35
+ unit.numPins = this.numPins;
36
+ unit.angleProp = this.angleProp;
37
+ unit.widthProp = this.widthProp;
38
+ unit.heightProp = this.heightProp;
39
+ if (this.displayProp instanceof SymbolDrawingCommands) {
40
+ unit.displayProp = this.displayProp.clone();
41
+ }
42
+ if (this.arrangeProps !== null) {
43
+ unit.arrangeProps = new Map(this.arrangeProps);
44
+ }
45
+ for (const [key, value] of this.pins) {
46
+ unit.pins.set(key, value);
47
+ }
48
+ unit.pinsFlat = [...this.pinsFlat];
49
+ for (const [key, value] of this.pinsMaxPositions) {
50
+ unit.pinsMaxPositions.set(key, value);
51
+ }
52
+ unit._unplacedPins = [...this._unplacedPins];
53
+ unit.followWireOrientationProp = this.followWireOrientationProp;
54
+ unit.wireOrientationAngle = this.wireOrientationAngle;
55
+ unit.useWireOrientationAngle = this.useWireOrientationAngle;
56
+ unit.didSetWireOrientationAngle = this.didSetWireOrientationAngle;
57
+ return unit;
58
+ }
59
+ setParam(key, value) {
60
+ this.parameters.set(key, value);
61
+ }
62
+ isEqual(other) {
63
+ if (this === other)
64
+ return true;
65
+ if (this.unitId !== other.unitId)
66
+ return false;
67
+ if (this.numPins !== other.numPins)
68
+ return false;
69
+ if (this.angleProp !== other.angleProp)
70
+ return false;
71
+ if (this.widthProp !== other.widthProp)
72
+ return false;
73
+ if (this.heightProp !== other.heightProp)
74
+ return false;
75
+ if (this.followWireOrientationProp !== other.followWireOrientationProp)
76
+ return false;
77
+ if (this.wireOrientationAngle !== other.wireOrientationAngle)
78
+ return false;
79
+ if (this.useWireOrientationAngle !== other.useWireOrientationAngle)
80
+ return false;
81
+ if (this.didSetWireOrientationAngle !== other.didSetWireOrientationAngle)
82
+ return false;
83
+ if (this.displayProp === null && other.displayProp !== null)
84
+ return false;
85
+ if (this.displayProp !== null && other.displayProp === null)
86
+ return false;
87
+ if (this.displayProp !== null && other.displayProp !== null && !this.displayProp.eq(other.displayProp))
88
+ return false;
89
+ if (this.arrangeProps === null && other.arrangeProps !== null)
90
+ return false;
91
+ if (this.arrangeProps !== null && other.arrangeProps === null)
92
+ return false;
93
+ if (this.arrangeProps !== null && other.arrangeProps !== null) {
94
+ if (this.arrangeProps.size !== other.arrangeProps.size)
95
+ return false;
96
+ for (const [key, value] of this.arrangeProps) {
97
+ const otherValue = other.arrangeProps.get(key);
98
+ if (!otherValue || value.length !== otherValue.length)
99
+ return false;
100
+ for (let i = 0; i < value.length; i++) {
101
+ if (!value[i].equals(otherValue[i]))
102
+ return false;
103
+ }
104
+ }
105
+ }
106
+ if (this.parameters.size !== other.parameters.size)
107
+ return false;
108
+ for (const [key, value] of this.parameters) {
109
+ if (!other.parameters.has(key) || other.parameters.get(key) !== value)
110
+ return false;
111
+ }
112
+ if (this.pins.size !== other.pins.size)
113
+ return false;
114
+ for (const [key, value] of this.pins) {
115
+ let found = false;
116
+ for (const [otherKey, otherValue] of other.pins) {
117
+ if (key.equals(otherKey) && value === otherValue) {
118
+ found = true;
119
+ break;
120
+ }
121
+ }
122
+ if (!found)
123
+ return false;
124
+ }
125
+ if (this.parent !== other.parent) {
126
+ return false;
127
+ }
128
+ return true;
129
+ }
130
+ }
6
131
  export class ClassComponent {
7
132
  instanceName;
8
133
  numPins;
@@ -11,27 +136,21 @@ export class ClassComponent {
11
136
  pinNets = new Map();
12
137
  pinWires = new Map();
13
138
  pinsMaxPositions = new Map();
139
+ units = [];
14
140
  _cachedPins;
15
141
  _cachedParams;
16
142
  _copyID = null;
17
143
  _copyFrom = null;
18
144
  _pointLinkComponent;
19
145
  _unplacedPins = [];
20
- arrangeProps = null;
21
- displayProp = null;
22
- widthProp = null;
23
- heightProp = null;
24
146
  typeProp = null;
25
147
  copyProp = false;
26
- angleProp = 0;
27
- followWireOrientationProp = true;
28
- wireOrientationAngle = 0;
29
- useWireOrientationAngle = true;
30
- didSetWireOrientationAngle = false;
31
148
  assignedRefDes = null;
32
149
  placeHolderRefDes = null;
150
+ forceSaveRefdesAnnotation = false;
33
151
  ctxReferences = [];
34
152
  _creationIndex = -1;
153
+ pinUnitMap = new Map();
35
154
  constructor(instanceName, numPins) {
36
155
  this.instanceName = instanceName;
37
156
  this.numPins = numPins;
@@ -123,31 +242,32 @@ export class ClassComponent {
123
242
  return component;
124
243
  }
125
244
  isEqual(other) {
126
- return this.instanceName === other.instanceName
127
- && this.numPins === other.numPins
128
- && this._copyID === other._copyID
129
- && this.arrangeProps === other.arrangeProps
130
- && ((this.displayProp === null && other.displayProp === null)
131
- ||
132
- (this.displayProp !== null && other.displayProp !== null && this.displayProp.eq(other.displayProp)))
133
- && this.widthProp === other.widthProp
134
- && this.typeProp === other.typeProp
135
- && this._cachedPins === other._cachedPins
136
- && this._cachedParams === other._cachedParams;
245
+ if (this === other)
246
+ return true;
247
+ if (this.instanceName !== other.instanceName)
248
+ return false;
249
+ if (this._copyID !== other._copyID)
250
+ return false;
251
+ if (this.typeProp !== other.typeProp)
252
+ return false;
253
+ if (this._cachedPins !== other._cachedPins)
254
+ return false;
255
+ if (this._cachedParams !== other._cachedParams)
256
+ return false;
257
+ for (let i = 0; i < this.units.length; i++) {
258
+ if (other.units[i] === undefined) {
259
+ return false;
260
+ }
261
+ if (!other.units[i].isEqual(this.units[i])) {
262
+ return false;
263
+ }
264
+ }
265
+ return true;
137
266
  }
138
267
  clone() {
139
268
  const component = new ClassComponent(this.instanceName, this.numPins);
140
269
  component._copyID = this._copyID;
141
- component.arrangeProps = this.arrangeProps;
142
- component.widthProp = this.widthProp;
143
270
  component.typeProp = this.typeProp;
144
- component.angleProp = this.angleProp;
145
- component.followWireOrientationProp = this.followWireOrientationProp;
146
- component.useWireOrientationAngle = this.useWireOrientationAngle;
147
- if (this.displayProp instanceof SymbolDrawingCommands) {
148
- component.displayProp =
149
- this.displayProp.clone();
150
- }
151
271
  for (const [key, value] of this.parameters) {
152
272
  if (key === ParamKeys.flipX || key === ParamKeys.flipY || key === ParamKeys.angle) {
153
273
  continue;
@@ -160,9 +280,60 @@ export class ClassComponent {
160
280
  for (const [key, value] of this.pinsMaxPositions) {
161
281
  component.pinsMaxPositions.set(key, value);
162
282
  }
283
+ component.units = this.units.map(unit => {
284
+ const tmpUnit = unit.clone();
285
+ tmpUnit.parent = component;
286
+ return tmpUnit;
287
+ });
163
288
  component.refreshCache();
289
+ component.refreshPinUnitMap();
164
290
  return component;
165
291
  }
292
+ getUnit(unitId = null) {
293
+ if (unitId === null) {
294
+ return this.units[0];
295
+ }
296
+ else {
297
+ return this.units.find(item => {
298
+ return item.unitId === unitId;
299
+ });
300
+ }
301
+ }
302
+ addDefaultUnit(displayProp) {
303
+ const tmpUnit = new ComponentUnit(DefaultComponentUnit, this);
304
+ tmpUnit.pins = this.pins;
305
+ const pinsFlat = [];
306
+ this.pins.forEach(pin => {
307
+ pinsFlat.push(pin);
308
+ });
309
+ tmpUnit.pinsFlat = pinsFlat;
310
+ tmpUnit.numPins = this.numPins;
311
+ tmpUnit.pinsMaxPositions = new Map();
312
+ tmpUnit.displayProp = displayProp;
313
+ tmpUnit.angleProp = 0;
314
+ tmpUnit.followWireOrientationProp = true;
315
+ this.units.push(tmpUnit);
316
+ this.refreshPinUnitMap();
317
+ }
318
+ refreshPinUnitMap() {
319
+ for (const unit of this.units) {
320
+ const { pinsFlat } = unit;
321
+ for (const pin of pinsFlat) {
322
+ this.pinUnitMap.set(pin.id, unit);
323
+ }
324
+ }
325
+ }
326
+ getUnitForPin(pinId) {
327
+ if (typeof pinId === "number") {
328
+ throw new RuntimeExecutionError("Invalid pin id");
329
+ }
330
+ for (const [tmpPin, componentUnit] of this.pinUnitMap) {
331
+ if (tmpPin.equals(pinId)) {
332
+ return componentUnit;
333
+ }
334
+ }
335
+ throw new RuntimeExecutionError("Could not find unit for pin: " + pinId);
336
+ }
166
337
  }
167
338
  export class ModuleComponent extends ClassComponent {
168
339
  moduleContainsExpressions;
@@ -135,10 +135,16 @@ export class ImportedModule {
135
135
  specifiedImports;
136
136
  moduleNamespace;
137
137
  moduleFilePath;
138
- constructor(moduleName, moduleNamespace, moduleFilePath, context, flag, specifiedImports) {
138
+ enableRefdesAnnotation = false;
139
+ enableRefdesAnnotationFile = false;
140
+ tree;
141
+ tokens;
142
+ constructor(moduleName, moduleNamespace, moduleFilePath, tree, tokens, context, flag, specifiedImports) {
139
143
  this.moduleName = moduleName;
140
144
  this.moduleNamespace = moduleNamespace;
141
145
  this.moduleFilePath = moduleFilePath;
146
+ this.tree = tree;
147
+ this.tokens = tokens;
142
148
  this.context = context;
143
149
  this.importHandlingFlag = flag;
144
150
  this.specifiedImports = specifiedImports;