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
@@ -75,6 +75,7 @@ export class CircuitScriptVisitor extends AbstractParseTreeVisitor {
75
75
  visitImport_simple;
76
76
  visitImport_all_simple;
77
77
  visitImport_specific;
78
+ visitImport_annotation_expr;
78
79
  visitFrame_expr;
79
80
  visitIf_expr;
80
81
  visitIf_inner_expr;
@@ -133,7 +133,7 @@ export class SymbolGraphic {
133
133
  }
134
134
  drawLabels(group) {
135
135
  const labels = this.drawing.getLabels();
136
- labels.forEach(label => {
136
+ for (const label of labels) {
137
137
  const tmpLabel = label;
138
138
  const { fontSize = numeric(50), anchor = HorizontalAlign.Left, vanchor = VerticalAlign.Bottom, fontWeight = 'regular', angle: tmpLabelAngle = numeric(0), textColor = "#333", } = tmpLabel.style ?? {};
139
139
  const labelAngle = tmpLabelAngle.toNumber();
@@ -146,31 +146,35 @@ export class SymbolGraphic {
146
146
  useAnchor = this.flipTextAnchor(anchor);
147
147
  useDominantBaseline = this.flipDominantBaseline(vanchor);
148
148
  }
149
- switch (useAnchor) {
150
- case HorizontalAlign.Left:
151
- anchorStyle = (this.flipX === 0)
152
- ? HorizontalAlignProp.Start : HorizontalAlignProp.End;
153
- break;
154
- case HorizontalAlign.Middle:
155
- anchorStyle = HorizontalAlignProp.Middle;
156
- break;
157
- case HorizontalAlign.Right:
158
- anchorStyle = (this.flipX === 0)
159
- ? HorizontalAlignProp.End : HorizontalAlignProp.Start;
160
- break;
149
+ const isHorizontalLabel = labelAngle === 0 || labelAngle === 180;
150
+ const isVerticalLabel = labelAngle === 90 || labelAngle === -90;
151
+ if (useAnchor === HorizontalAlign.Middle) {
152
+ anchorStyle = HorizontalAlignProp.Middle;
161
153
  }
162
- switch (useDominantBaseline) {
163
- case VerticalAlign.Top:
164
- dominantBaseline = (this.flipY === 0)
165
- ? VerticalAlignProp.Hanging : VerticalAlignProp.TextTop;
166
- break;
167
- case VerticalAlign.Middle:
168
- dominantBaseline = VerticalAlignProp.Central;
169
- break;
170
- case VerticalAlign.Bottom:
171
- dominantBaseline = (this.flipY === 0)
172
- ? VerticalAlignProp.TextTop : VerticalAlignProp.Hanging;
173
- break;
154
+ else if (useAnchor === HorizontalAlign.Left) {
155
+ anchorStyle = HorizontalAlignProp.Start;
156
+ }
157
+ else if (useAnchor === HorizontalAlign.Right) {
158
+ anchorStyle = HorizontalAlignProp.End;
159
+ }
160
+ if (useDominantBaseline === VerticalAlign.Middle) {
161
+ dominantBaseline = VerticalAlignProp.Central;
162
+ }
163
+ else if (useDominantBaseline === VerticalAlign.Top) {
164
+ dominantBaseline = VerticalAlignProp.Hanging;
165
+ }
166
+ else if (useDominantBaseline === VerticalAlign.Bottom) {
167
+ dominantBaseline = VerticalAlignProp.TextTop;
168
+ }
169
+ if (anchorStyle !== HorizontalAlignProp.Middle &&
170
+ ((isHorizontalLabel && this.flipX === 1) || (isVerticalLabel && this.flipY === 1))) {
171
+ anchorStyle = (anchorStyle === HorizontalAlignProp.Start)
172
+ ? HorizontalAlignProp.End : HorizontalAlignProp.Start;
173
+ }
174
+ if (dominantBaseline !== VerticalAlignProp.Central &&
175
+ ((isHorizontalLabel && this.flipY === 1) || (isVerticalLabel && this.flipX === 1))) {
176
+ dominantBaseline = (dominantBaseline === VerticalAlignProp.Hanging)
177
+ ? VerticalAlignProp.TextTop : VerticalAlignProp.Hanging;
174
178
  }
175
179
  const position = tmpLabel.getLabelPosition();
176
180
  if (this.flipX !== 0) {
@@ -314,7 +318,7 @@ export class SymbolGraphic {
314
318
  .translate(-originSize / 2, -originSize / 2)
315
319
  .fill('green');
316
320
  }
317
- });
321
+ }
318
322
  }
319
323
  flipTextAnchor(value) {
320
324
  if (value === HorizontalAlign.Left) {
@@ -709,7 +713,7 @@ export class SymbolCustom extends SymbolGraphic {
709
713
  const pinStartY = bodyHeightMM.neg().half();
710
714
  const pinStartX = bodyWidthMM.neg().half();
711
715
  const tmpPinSpacing = this.pinSpacing.toNumber();
712
- leftPins.forEach(pin => {
716
+ for (const pin of leftPins) {
713
717
  const position = pin.position;
714
718
  const pinY = pinStartY.add((position + 1) * tmpPinSpacing);
715
719
  drawing.addPinMM(pin.pinId, leftPinStart.sub(this.pinLength), pinY, leftPinStart, pinY, defaultLineColor);
@@ -725,8 +729,8 @@ export class SymbolCustom extends SymbolGraphic {
725
729
  vanchor: VerticalAlign.Bottom,
726
730
  textColor: defaultLineColor
727
731
  });
728
- });
729
- rightPins.forEach(pin => {
732
+ }
733
+ for (const pin of rightPins) {
730
734
  const position = pin.position;
731
735
  const pinY = pinStartY.add((position + 1) * tmpPinSpacing);
732
736
  drawing.addPinMM(pin.pinId, rightPinStart.add(this.pinLength), pinY, rightPinStart, pinY, defaultLineColor);
@@ -742,8 +746,8 @@ export class SymbolCustom extends SymbolGraphic {
742
746
  vanchor: VerticalAlign.Bottom,
743
747
  textColor: defaultLineColor
744
748
  });
745
- });
746
- topPins.forEach(pin => {
749
+ }
750
+ for (const pin of topPins) {
747
751
  const position = pin.position;
748
752
  const pinX = pinStartX.add((position + 1) * tmpPinSpacing);
749
753
  drawing.addPinMM(pin.pinId, pinX, topPinStart.sub(this.pinLength), pinX, topPinStart, defaultLineColor);
@@ -761,8 +765,8 @@ export class SymbolCustom extends SymbolGraphic {
761
765
  textColor: defaultLineColor,
762
766
  angle: numeric(-90),
763
767
  });
764
- });
765
- bottomPins.forEach(pin => {
768
+ }
769
+ for (const pin of bottomPins) {
766
770
  const position = pin.position;
767
771
  const pinX = pinStartX.add((position + 1) * tmpPinSpacing);
768
772
  drawing.addPinMM(pin.pinId, pinX, bottomPinStart.add(this.pinLength), pinX, bottomPinStart, defaultLineColor);
@@ -780,7 +784,7 @@ export class SymbolCustom extends SymbolGraphic {
780
784
  textColor: defaultLineColor,
781
785
  angle: numeric(-90)
782
786
  });
783
- });
787
+ }
784
788
  const instanceName = drawing.variables.get('refdes');
785
789
  instanceName && drawing.addLabel(bodyWidthMM.neg().half(), bodyHeightMM.neg().half().sub(milsToMM(20)), instanceName, {
786
790
  fontSize: numeric(CustomSymbolRefDesSize),
@@ -1,4 +1,5 @@
1
1
  import { registerWindow, SVG } from "@svgdotjs/svg.js";
2
+ import { writeFileSync } from "fs";
2
3
  import fs from 'fs';
3
4
  import path from "path";
4
5
  import CryptoJs from "crypto-js";
@@ -112,8 +113,12 @@ export class NodeScriptEnvironment {
112
113
  return this.prepareSVGEnvironmentInternal(this.getFontsPath());
113
114
  }
114
115
  async readFile(path, options) {
116
+ options = options ?? { encoding: 'utf8' };
115
117
  return fs.promises.readFile(path, options);
116
118
  }
119
+ writeFileSync(path, data) {
120
+ return writeFileSync(path, data);
121
+ }
117
122
  getAbsolutePath(filePath) {
118
123
  return path.resolve(filePath);
119
124
  }
@@ -132,7 +137,7 @@ export class NodeScriptEnvironment {
132
137
  }
133
138
  async exists(path) {
134
139
  try {
135
- fs.promises.access(path, fs.constants.F_OK);
140
+ await fs.promises.access(path, fs.constants.F_OK);
136
141
  return true;
137
142
  }
138
143
  catch (err) {
@@ -142,4 +147,19 @@ export class NodeScriptEnvironment {
142
147
  hashStringSHA256(value) {
143
148
  return CryptoJs.SHA256(value).toString();
144
149
  }
150
+ dirname(filePath) {
151
+ return path.dirname(filePath);
152
+ }
153
+ extname(filePath) {
154
+ return path.extname(filePath);
155
+ }
156
+ basename(filePath, ext) {
157
+ return path.basename(filePath, ext);
158
+ }
159
+ join(...paths) {
160
+ return path.join(...paths);
161
+ }
162
+ relative(from, to) {
163
+ return path.relative(from, to);
164
+ }
145
165
  }
@@ -1,5 +1,5 @@
1
1
  import { BlockTypes, ComponentTypes, Delimiter1, GlobalNames, NoNetText, ParamKeys, ReferenceTypes, SymbolPinSide } from './globals.js';
2
- import { ClassComponent, ModuleComponent } from './objects/ClassComponent.js';
2
+ import { ClassComponent, ComponentUnit, 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
5
  import { numeric, NumericValue } from './objects/ParamDefinition.js';
@@ -65,7 +65,7 @@ export class ExecutionContext {
65
65
  setupRoot() {
66
66
  const componentRoot = ClassComponent.simple(GlobalNames.__root, 1);
67
67
  componentRoot.typeProp = ComponentTypes.net;
68
- componentRoot.displayProp = this.getPointSymbol();
68
+ componentRoot.addDefaultUnit(this.getPointSymbol());
69
69
  this.scope.instances.set(GlobalNames.__root, componentRoot);
70
70
  this.scope.setCurrent(componentRoot);
71
71
  this.scope.componentRoot = componentRoot;
@@ -131,49 +131,13 @@ export class ExecutionContext {
131
131
  }
132
132
  createComponent(instanceName, pins, params, props, isModule = false) {
133
133
  const className = isModule ? ModuleComponent : ClassComponent;
134
+ pins = this.extractPinsFromUnits(props.units);
134
135
  const component = new className(instanceName, pins.length);
135
136
  pins.forEach((pin) => {
136
137
  component.pins.set(pin.id, pin);
137
138
  });
138
- component.displayProp = props.display ?? null;
139
- component.widthProp = props.width ?? null;
140
- component.heightProp = props.height ?? null;
141
139
  component.typeProp = props.type ?? null;
142
140
  component.copyProp = props.copy ?? false;
143
- let useAngle = null;
144
- if (props.angle) {
145
- useAngle = props.angle.toNumber() % 360;
146
- if (useAngle < 0) {
147
- useAngle += 360;
148
- }
149
- }
150
- if (props.display === null && props.arrange === null) {
151
- const tmpArrangeLeft = [];
152
- const tmpArrangeRight = [];
153
- pins.forEach((pin, index) => {
154
- const useArray = (index % 2 === 0) ? tmpArrangeLeft : tmpArrangeRight;
155
- useArray.push(pin.id);
156
- });
157
- const arrangeProp = new Map([
158
- [SymbolPinSide.Left, tmpArrangeLeft],
159
- [SymbolPinSide.Right, tmpArrangeRight]
160
- ]);
161
- props.arrange = arrangeProp;
162
- }
163
- if (props.arrange !== null) {
164
- component.arrangeProps = this.removeArrangePropDuplicates(props.arrange);
165
- const arrangePropPins = this.getArrangePropPins(component.arrangeProps);
166
- pins.forEach(pin => {
167
- if (arrangePropPins.find(id => id.equals(pin.id)) === undefined) {
168
- this.logWarning(`Pin ${pin.id} is not specified in arrange property`);
169
- }
170
- });
171
- }
172
- else {
173
- component.arrangeProps = null;
174
- }
175
- component.angleProp = useAngle ?? 0;
176
- component.followWireOrientationProp = props.followWireOrientation;
177
141
  const paramsMap = new Map();
178
142
  params.forEach((param) => {
179
143
  component.parameters.set(param.paramName, param.paramValue);
@@ -200,27 +164,91 @@ export class ExecutionContext {
200
164
  this.scope.setNet(component, defaultPin, tmpNet);
201
165
  this.log('set net', netName, 'component', component, defaultPin);
202
166
  }
203
- const { pins: pinSides, maxPositions } = getPortSide(component.pins, component.arrangeProps);
204
- component.pinsMaxPositions = maxPositions;
205
- const pinIdKeys = Array.from(component.pins.keys());
206
- pinSides.forEach(({ pinId, side, position }) => {
207
- const matchedPinId = pinIdKeys.find(id => id.equals(pinId));
208
- if (matchedPinId) {
209
- const tmpPin = component.pins.get(matchedPinId);
210
- tmpPin.side = side;
211
- tmpPin.position = position;
212
- }
213
- else {
214
- throw 'Not found!';
215
- }
216
- });
217
167
  this.scope.instances.set(instanceName, component);
218
168
  const pinsOutput = pins.map((pin) => {
219
169
  return pin.id + ':' + pin.name;
220
170
  });
221
171
  this.log('add symbol', instanceName, '[' + pinsOutput.join(', ') + ']');
172
+ component.units = this.generateComponentUnits(props.units, component);
173
+ component.refreshPinUnitMap();
222
174
  return component;
223
175
  }
176
+ extractPinsFromUnits(units) {
177
+ const pins = [];
178
+ units.forEach(([, definition]) => {
179
+ pins.push(...definition.pins);
180
+ });
181
+ return pins;
182
+ }
183
+ generateComponentUnits(units, parent) {
184
+ return units.map(([key, unitDef]) => {
185
+ unitDef = { ...unitDef };
186
+ let useAngle = null;
187
+ const { pins } = unitDef;
188
+ const pinsMap = new Map();
189
+ pins.forEach(pin => {
190
+ pinsMap.set(pin.id, pin);
191
+ });
192
+ if (unitDef.angle) {
193
+ useAngle = unitDef.angle.toNumber() % 360;
194
+ if (useAngle < 0) {
195
+ useAngle += 360;
196
+ }
197
+ }
198
+ if (unitDef.display === null && unitDef.arrange === null) {
199
+ const tmpArrangeLeft = [];
200
+ const tmpArrangeRight = [];
201
+ pins.forEach((pin, index) => {
202
+ const useArray = (index % 2 === 0) ? tmpArrangeLeft : tmpArrangeRight;
203
+ useArray.push(pin.id);
204
+ });
205
+ const arrangeProp = new Map([
206
+ [SymbolPinSide.Left, tmpArrangeLeft],
207
+ [SymbolPinSide.Right, tmpArrangeRight]
208
+ ]);
209
+ unitDef.arrange = arrangeProp;
210
+ }
211
+ if (unitDef.arrange !== null) {
212
+ unitDef.arrange = this.removeArrangePropDuplicates(unitDef.arrange);
213
+ const arrangePropPins = this.getArrangePropPins(unitDef.arrange);
214
+ pins.forEach(pin => {
215
+ if (arrangePropPins.find(id => id.equals(pin.id)) === undefined) {
216
+ this.logWarning(`Pin ${pin.id} is not specified in arrange property`);
217
+ }
218
+ });
219
+ }
220
+ else {
221
+ unitDef.arrange = null;
222
+ }
223
+ unitDef.angle = useAngle ?? 0;
224
+ const { pins: pinSides, maxPositions } = getPortSide(pinsMap, unitDef.arrange);
225
+ const pinIdKeys = Array.from(pinsMap.keys());
226
+ pinSides.forEach(({ pinId, side, position }) => {
227
+ const matchedPinId = pinIdKeys.find(id => id.equals(pinId));
228
+ if (matchedPinId) {
229
+ const tmpPin = pinsMap.get(matchedPinId);
230
+ tmpPin.side = side;
231
+ tmpPin.position = position;
232
+ }
233
+ else {
234
+ throw 'Not found!';
235
+ }
236
+ });
237
+ const componentUnit = new ComponentUnit(key, parent);
238
+ componentUnit.widthProp = unitDef.width;
239
+ componentUnit.heightProp = unitDef.height;
240
+ componentUnit.angleProp = unitDef.angle;
241
+ componentUnit.followWireOrientationProp = unitDef.followWireOrientation;
242
+ componentUnit.pins = pinsMap;
243
+ componentUnit.pinsFlat = pins;
244
+ componentUnit.numPins = unitDef.pins.length;
245
+ componentUnit.pinsMaxPositions = maxPositions;
246
+ componentUnit.displayProp = unitDef.display;
247
+ componentUnit.arrangeProps = unitDef.arrange;
248
+ componentUnit.suffix = unitDef.suffix ?? null;
249
+ return componentUnit;
250
+ });
251
+ }
224
252
  removeArrangePropDuplicates(arrangeProp) {
225
253
  const sides = [
226
254
  SymbolPinSide.Left,
@@ -886,9 +914,10 @@ export class ExecutionContext {
886
914
  this.scope.setActive(ActiveObject.Wire, wireId);
887
915
  this.scope.sequence.push([SequenceAction.Wire, wireId, tmp, newWire]);
888
916
  this.scope.currentComponent.pinWires.set(this.scope.currentPin, tmp);
889
- if (!this.scope.currentComponent.didSetWireOrientationAngle) {
917
+ const currentUnit = this.scope.currentComponent.getUnitForPin(this.scope.currentPin);
918
+ if (!currentUnit.didSetWireOrientationAngle) {
890
919
  this.applyComponentAngleFromWire(this.scope.currentComponent, this.scope.currentPin, true);
891
- this.scope.currentComponent.didSetWireOrientationAngle = true;
920
+ currentUnit.didSetWireOrientationAngle = true;
892
921
  }
893
922
  return newWire;
894
923
  }
@@ -898,7 +927,6 @@ export class ExecutionContext {
898
927
  }
899
928
  const useName = userDefined ? 'point.' + pointId : pointId;
900
929
  const componentPoint = ClassComponent.simple(useName, 1);
901
- componentPoint.displayProp = this.getPointSymbol(useName);
902
930
  componentPoint.typeProp = ComponentTypes.net;
903
931
  let usePointLinkComponent = null;
904
932
  if (this.scope.currentComponent._pointLinkComponent) {
@@ -908,6 +936,7 @@ export class ExecutionContext {
908
936
  usePointLinkComponent = this.scope.currentComponent;
909
937
  }
910
938
  componentPoint._pointLinkComponent = usePointLinkComponent;
939
+ componentPoint.addDefaultUnit(this.getPointSymbol(useName));
911
940
  this.scope.instances.set(pointId, componentPoint);
912
941
  this.toComponent(componentPoint, 1, { addSequence: true });
913
942
  return this.getCurrentPoint();
@@ -981,6 +1010,15 @@ export class ExecutionContext {
981
1010
  if (this.scope.instances.has(idName)) {
982
1011
  const component = this.scope.instances.get(idName);
983
1012
  component.setParam(paramName, value);
1013
+ const unitModifiers = [
1014
+ ParamKeys.angle,
1015
+ ParamKeys.flip,
1016
+ ParamKeys.flipX,
1017
+ ParamKeys.flipY,
1018
+ ];
1019
+ if (unitModifiers.indexOf(paramName) !== -1) {
1020
+ component.getUnit().setParam(paramName, value);
1021
+ }
984
1022
  }
985
1023
  else if (this.scope.variables.has(idName)) {
986
1024
  throw "Not implemented yet!";
@@ -991,17 +1029,18 @@ export class ExecutionContext {
991
1029
  }
992
1030
  }
993
1031
  applyComponentAngleFromWire(component, pin, opposite = false) {
1032
+ const targetUnit = component.getUnitForPin(pin);
994
1033
  if (this.componentAngleFollowsWire
995
- && component.followWireOrientationProp
996
- && component.useWireOrientationAngle
997
- && !component.didSetWireOrientationAngle
1034
+ && targetUnit.followWireOrientationProp
1035
+ && targetUnit.useWireOrientationAngle
1036
+ && !targetUnit.didSetWireOrientationAngle
998
1037
  && this.scope.currentWireId !== -1) {
999
1038
  const currentWire = this.scope.wires[this.scope.currentWireId];
1000
1039
  let useSegment = currentWire.path[currentWire.path.length - 1];
1001
1040
  if (opposite) {
1002
1041
  useSegment = currentWire.path[0];
1003
1042
  }
1004
- const pinPositions = CalculatePinPositions(component);
1043
+ const pinPositions = CalculatePinPositions(targetUnit);
1005
1044
  if (pinPositions.has(pin)) {
1006
1045
  const connectedPinPos = pinPositions.get(pin);
1007
1046
  let targetAngle = null;
@@ -1039,27 +1078,27 @@ export class ExecutionContext {
1039
1078
  if (targetAngle === null) {
1040
1079
  return;
1041
1080
  }
1042
- this.log('set component angle from wire, target angle:', targetAngle, ', component angle:', component.angleProp, 'pin angle:', connectedPinPos.angle);
1081
+ this.log('set component unit angle from wire, target angle:', targetAngle, ', component unit angle:', targetUnit.angleProp, 'pin angle:', connectedPinPos.angle);
1043
1082
  let useAngle = (targetAngle - connectedPinPos.angle.toNumber()) % 360;
1044
1083
  if (useAngle < 0) {
1045
1084
  useAngle += 360;
1046
1085
  }
1047
1086
  if (useAngle === 90) {
1048
- component.setParam(ParamKeys.angle, numeric(90));
1087
+ targetUnit.setParam(ParamKeys.angle, numeric(90));
1049
1088
  }
1050
1089
  else if (useAngle === 180) {
1051
- if (component.angleProp === 0 || component.angleProp === 180) {
1052
- component.setParam(ParamKeys.flipX, 1);
1090
+ if (targetUnit.angleProp === 0 || targetUnit.angleProp === 180) {
1091
+ targetUnit.setParam(ParamKeys.flipX, numeric(1));
1053
1092
  }
1054
- else if (component.angleProp === 90 || component.angleProp === 270) {
1055
- component.setParam(ParamKeys.flipY, 1);
1093
+ else if (targetUnit.angleProp === 90 || targetUnit.angleProp === 270) {
1094
+ targetUnit.setParam(ParamKeys.flipY, numeric(1));
1056
1095
  }
1057
1096
  }
1058
1097
  else if (useAngle === 270) {
1059
- component.setParam(ParamKeys.angle, numeric(270));
1098
+ targetUnit.setParam(ParamKeys.angle, numeric(270));
1060
1099
  }
1061
- component.wireOrientationAngle = useAngle;
1062
- component.didSetWireOrientationAngle = true;
1100
+ targetUnit.wireOrientationAngle = useAngle;
1101
+ targetUnit.didSetWireOrientationAngle = true;
1063
1102
  }
1064
1103
  }
1065
1104
  }
@@ -3,6 +3,7 @@ export const TOOL_VERSION = '0.1.5';
3
3
  export const Delimiter1 = '-';
4
4
  export const DoubleDelimiter1 = `${Delimiter1}${Delimiter1}`;
5
5
  export const BaseNamespace = `${DoubleDelimiter1}.`;
6
+ export const RefdesFileSuffix = '.refdes.json';
6
7
  export var GlobalNames;
7
8
  (function (GlobalNames) {
8
9
  GlobalNames["__root"] = "--root";
@@ -128,3 +129,4 @@ export const RenderFlags = {
128
129
  };
129
130
  export const SymbolValidatorContext = '_sym';
130
131
  export const TrailerArrayIndex = 'index';
132
+ export const DefaultComponentUnit = '__default';
package/dist/esm/graph.js CHANGED
@@ -35,32 +35,33 @@ export class NetGraph {
35
35
  case SequenceAction.At: {
36
36
  this.print(...sequenceStep);
37
37
  const [, component, pin] = sequenceStep;
38
- const tmpInstanceName = component.instanceName;
38
+ const componentUnit = component.getUnitForPin(pin);
39
+ const tmpInstanceName = componentUnit.instanceName;
39
40
  if (action === SequenceAction.At) {
40
41
  previousNode = null;
41
42
  previousPin = null;
42
43
  }
43
44
  if (!graph.hasNode(tmpInstanceName)) {
44
45
  this.print('create instance', tmpInstanceName);
45
- const { displayProp = null } = component;
46
+ const { displayProp = null } = componentUnit;
46
47
  let tmpSymbol;
47
48
  if (displayProp instanceof SymbolDrawing) {
48
49
  tmpSymbol = new SymbolPlaceholder(displayProp);
49
50
  tmpSymbol.drawing.logger = this.logger;
50
51
  }
51
52
  else {
52
- const symbolPinDefinitions = generateLayoutPinDefinition(component);
53
+ const symbolPinDefinitions = generateLayoutPinDefinition(componentUnit);
53
54
  if (component.typeProp === ComponentTypes.module) {
54
- tmpSymbol = new SymbolCustomModule(symbolPinDefinitions, component.pinsMaxPositions);
55
+ tmpSymbol = new SymbolCustomModule(symbolPinDefinitions, componentUnit.pinsMaxPositions);
55
56
  }
56
57
  else {
57
- tmpSymbol = new SymbolCustom(symbolPinDefinitions, component.pinsMaxPositions);
58
+ tmpSymbol = new SymbolCustom(symbolPinDefinitions, componentUnit.pinsMaxPositions);
58
59
  }
59
60
  }
60
- applyComponentParamsToSymbol(component, tmpSymbol);
61
+ applyComponentParamsToSymbol(componentUnit, tmpSymbol);
61
62
  tmpSymbol.refreshDrawing();
62
63
  const { width: useWidth, height: useHeight } = tmpSymbol.size();
63
- tmpComponent = new RenderComponent(component, useWidth, useHeight);
64
+ tmpComponent = new RenderComponent(component, componentUnit.unitId, useWidth, useHeight);
64
65
  tmpComponent.symbol = tmpSymbol;
65
66
  graph.setNode(tmpInstanceName, [RenderItemType.Component, tmpComponent, index]);
66
67
  let useFrame = frameStack[frameStack.length - 1];
@@ -88,7 +89,8 @@ export class NetGraph {
88
89
  const [prevNodeType, prevNodeItem] = graph.node(previousNode);
89
90
  if (prevNodeType === RenderItemType.Component) {
90
91
  const matchingItem = nets.find(([comp, pin]) => {
91
- return comp.instanceName === previousNode
92
+ const unit = comp.getUnitForPin(pin);
93
+ return unit.instanceName === previousNode
92
94
  && pin.equals(previousPin);
93
95
  });
94
96
  if (matchingItem !== undefined) {
@@ -321,11 +323,11 @@ function makeEdgeValue(instanceName1, instancePin1, instanceName2, instancePin2,
321
323
  export function getWireName(wireId) {
322
324
  return 'wire:' + wireId;
323
325
  }
324
- export function generateLayoutPinDefinition(component) {
325
- const pins = component.pins;
326
+ export function generateLayoutPinDefinition(componentUnit) {
327
+ const pins = componentUnit.pins;
326
328
  const symbolPinDefinitions = [];
327
329
  const existingPinIds = Array.from(pins.keys());
328
- const arrangeProps = component.arrangeProps ?? [];
330
+ const arrangeProps = componentUnit.arrangeProps ?? [];
329
331
  const addedPins = [];
330
332
  for (const [key, items] of arrangeProps) {
331
333
  let useItems;
@@ -354,7 +356,7 @@ export function generateLayoutPinDefinition(component) {
354
356
  return addedPins.find(id => id.equals(pinId)) === undefined;
355
357
  });
356
358
  if (unplacedPins.length > 0) {
357
- component._unplacedPins = unplacedPins;
359
+ componentUnit._unplacedPins = unplacedPins;
358
360
  console.warn("Warning: There are unplaced pins: " + unplacedPins);
359
361
  }
360
362
  return symbolPinDefinitions;