circuitscript 0.5.7 → 0.6.1

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 (48) hide show
  1. package/dist/cjs/BaseVisitor.js +1 -0
  2. package/dist/cjs/annotate/ComponentAnnotater.js +6 -12
  3. package/dist/cjs/annotate/RefdesAnnotationVisitor.js +1 -3
  4. package/dist/cjs/antlr/CircuitScriptParser.js +1105 -845
  5. package/dist/cjs/cache/serializer.js +1 -1
  6. package/dist/cjs/errors.js +6 -3
  7. package/dist/cjs/execute.js +16 -10
  8. package/dist/cjs/objects/BlockTypes.js +1 -0
  9. package/dist/cjs/objects/ClassComponent.js +3 -3
  10. package/dist/cjs/objects/Frame.js +4 -0
  11. package/dist/cjs/regenerate-tests.js +4 -1
  12. package/dist/cjs/render/draw_symbols.js +51 -12
  13. package/dist/cjs/render/geometry.js +2 -2
  14. package/dist/cjs/render/layout.js +26 -2
  15. package/dist/cjs/sizing.js +3 -2
  16. package/dist/cjs/visitor.js +126 -32
  17. package/dist/esm/BaseVisitor.js +1 -0
  18. package/dist/esm/annotate/ComponentAnnotater.js +6 -12
  19. package/dist/esm/annotate/RefdesAnnotationVisitor.js +1 -3
  20. package/dist/esm/antlr/CircuitScriptParser.js +1098 -840
  21. package/dist/esm/antlr/CircuitScriptParserVisitor.js +2 -0
  22. package/dist/esm/cache/serializer.js +1 -1
  23. package/dist/esm/errors.js +6 -3
  24. package/dist/esm/execute.js +16 -10
  25. package/dist/esm/objects/BlockTypes.js +1 -0
  26. package/dist/esm/objects/ClassComponent.js +3 -3
  27. package/dist/esm/objects/Frame.js +4 -0
  28. package/dist/esm/regenerate-tests.js +4 -1
  29. package/dist/esm/render/draw_symbols.js +51 -12
  30. package/dist/esm/render/geometry.js +2 -2
  31. package/dist/esm/render/layout.js +26 -2
  32. package/dist/esm/sizing.js +3 -2
  33. package/dist/esm/visitor.js +127 -33
  34. package/dist/libs/std.cst +518 -15
  35. package/dist/types/BaseVisitor.d.ts +2 -2
  36. package/dist/types/antlr/CircuitScriptParser.d.ts +86 -64
  37. package/dist/types/antlr/CircuitScriptParserVisitor.d.ts +4 -0
  38. package/dist/types/execute.d.ts +2 -1
  39. package/dist/types/objects/BlockTypes.d.ts +2 -1
  40. package/dist/types/objects/ClassComponent.d.ts +1 -1
  41. package/dist/types/objects/Frame.d.ts +4 -0
  42. package/dist/types/render/draw_symbols.d.ts +5 -3
  43. package/dist/types/render/geometry.d.ts +1 -0
  44. package/dist/types/render/layout.d.ts +6 -0
  45. package/dist/types/sizing.d.ts +1 -1
  46. package/dist/types/visitor.d.ts +2 -1
  47. package/libs/std.cst +518 -15
  48. package/package.json +1 -1
@@ -65,7 +65,7 @@ function serializeLibraryScope(importedLib, contentHash) {
65
65
  prevStopLine = null;
66
66
  };
67
67
  for (const exprCtx of tree.expression()) {
68
- if (exprCtx.function_def_expr() !== null) {
68
+ if (exprCtx.non_newline_expression()?.function_def_expr() !== null) {
69
69
  flushGroup();
70
70
  continue;
71
71
  }
@@ -131,9 +131,12 @@ function collectErrorChain(error) {
131
131
  }
132
132
  exports.collectErrorChain = collectErrorChain;
133
133
  function printErrorChain(error) {
134
- const errors = collectErrorChain(error);
135
- errors.reverse();
136
- for (const err of errors) {
134
+ let useErrors = collectErrorChain(error);
135
+ if (useErrors.length === 0) {
136
+ useErrors = [error];
137
+ }
138
+ useErrors.reverse();
139
+ for (const err of useErrors) {
137
140
  console.log(" " + err.toString());
138
141
  }
139
142
  }
@@ -548,9 +548,7 @@ class ExecutionContext {
548
548
  }
549
549
  else if (blockType === BlockTypes_js_1.BlockTypes.Join || blockType === BlockTypes_js_1.BlockTypes.Parallel) {
550
550
  if (blockIndex === 0) {
551
- const pointIdName = `${globals_js_1.Delimiter1}${(0, utils_js_1.getBlockTypeString)(blockType)}`;
552
- this.addPoint(`${pointIdName}.${this.name}.${this.tmpPointId}`, false);
553
- this.tmpPointId += 1;
551
+ this.addPointForBlockType(blockType);
554
552
  stackRef.end_point = [
555
553
  this.scope.currentComponent,
556
554
  this.scope.currentPin,
@@ -564,6 +562,11 @@ class ExecutionContext {
564
562
  }
565
563
  }
566
564
  }
565
+ addPointForBlockType(blockType) {
566
+ const pointIdName = `${globals_js_1.Delimiter1}${(0, utils_js_1.getBlockTypeString)(blockType)}`;
567
+ this.addPoint(`${pointIdName}.${this.name}.${this.tmpPointId}`, false);
568
+ this.tmpPointId += 1;
569
+ }
567
570
  atPointBlock() {
568
571
  const [component, pin,] = this.getPointBlockLocation();
569
572
  this.atComponent(component, pin, {
@@ -580,10 +583,12 @@ class ExecutionContext {
580
583
  this.log('get block point');
581
584
  for (let i = 0; i < this.scope.scopeLevel; i++) {
582
585
  const stackRef = this.scope.blockStack.get(this.scope.scopeLevel - 1 - i);
583
- const { start_point } = stackRef;
584
- const component = start_point[0];
585
- if (component.instanceName.startsWith(`${globals_js_1.Delimiter1}point.`)) {
586
- return start_point;
586
+ if (stackRef) {
587
+ const { start_point } = stackRef;
588
+ const component = start_point[0];
589
+ if (component.instanceName.startsWith(`${globals_js_1.Delimiter1}point.`)) {
590
+ return start_point;
591
+ }
587
592
  }
588
593
  }
589
594
  this.log('did not find block point');
@@ -1018,7 +1023,8 @@ class ExecutionContext {
1018
1023
  });
1019
1024
  }
1020
1025
  applyComponentAngleFromWire(component, pin, opposite = false) {
1021
- const targetUnit = component.getUnitForPin(pin);
1026
+ const usePin = component.getPin(pin);
1027
+ const targetUnit = component.getUnitForPin(usePin);
1022
1028
  if (this.componentAngleFollowsWire
1023
1029
  && targetUnit.followWireOrientationProp
1024
1030
  && targetUnit.useWireOrientationAngle
@@ -1030,8 +1036,8 @@ class ExecutionContext {
1030
1036
  useSegment = currentWire.path[0];
1031
1037
  }
1032
1038
  const pinPositions = (0, layout_js_1.CalculatePinPositions)(targetUnit);
1033
- if (pinPositions.has(pin)) {
1034
- const connectedPinPos = pinPositions.get(pin);
1039
+ if (pinPositions.has(usePin)) {
1040
+ const connectedPinPos = pinPositions.get(usePin);
1035
1041
  let targetAngle = null;
1036
1042
  let useDirection = useSegment.direction;
1037
1043
  if (opposite) {
@@ -7,4 +7,5 @@ var BlockTypes;
7
7
  BlockTypes[BlockTypes["Join"] = 2] = "Join";
8
8
  BlockTypes[BlockTypes["Parallel"] = 3] = "Parallel";
9
9
  BlockTypes[BlockTypes["Point"] = 4] = "Point";
10
+ BlockTypes[BlockTypes["AtBlock"] = 5] = "AtBlock";
10
11
  })(BlockTypes || (exports.BlockTypes = BlockTypes = {}));
@@ -192,10 +192,10 @@ class ClassComponent {
192
192
  }
193
193
  throw new errors_js_1.RuntimeExecutionError(`Could not find pin '${pinId}' on component '${this.instanceName}'`);
194
194
  }
195
- getNextPinAfter(pinIndex) {
195
+ getNextPinAfter(pinId) {
196
196
  const pins = Array.from(this.pins.keys());
197
- pins.sort();
198
- const index = pins.findIndex(tmp => tmp.equals(pinIndex));
197
+ const foundPin = this.getPin(pinId);
198
+ const index = pins.findIndex(tmp => tmp.equals(foundPin));
199
199
  if (index + 1 < pins.length) {
200
200
  return pins[index + 1];
201
201
  }
@@ -37,6 +37,10 @@ var FrameParamKeys;
37
37
  FrameParamKeys["TitleAlign"] = "title_align";
38
38
  FrameParamKeys["HorizontalAlign"] = "align";
39
39
  FrameParamKeys["VerticalAlign"] = "valign";
40
+ FrameParamKeys["FontSize"] = "font_size";
41
+ FrameParamKeys["Bold"] = "bold";
42
+ FrameParamKeys["Italic"] = "italic";
43
+ FrameParamKeys["Color"] = "color";
40
44
  FrameParamKeys["SheetNumber"] = "sheet_number";
41
45
  FrameParamKeys["SheetTotal"] = "sheet_total";
42
46
  })(FrameParamKeys || (exports.FrameParamKeys = FrameParamKeys = {}));
@@ -27,13 +27,16 @@ async function regenerateTests(extra = "", fileList = []) {
27
27
  const outputPath = mainDir + 'svgs/' + file + extra + '.svg';
28
28
  env.setModuleDirectory(mainDir);
29
29
  env.setDefaultLibsPath(mainDir + '../../../libs/');
30
- await (0, pipeline_js_1.renderScript)(scriptData, outputPath, {
30
+ const { errors } = await (0, pipeline_js_1.renderScript)(scriptData, outputPath, {
31
31
  inputPath,
32
32
  dumpNets: false,
33
33
  dumpData: false,
34
34
  showStats: false,
35
35
  environment: env,
36
36
  });
37
+ if (errors.length > 0) {
38
+ console.log(errors);
39
+ }
37
40
  }
38
41
  return cstFiles;
39
42
  }
@@ -140,7 +140,7 @@ class SymbolGraphic {
140
140
  const labels = this.drawing.getLabels();
141
141
  for (const label of labels) {
142
142
  const tmpLabel = label;
143
- const { fontSize = (0, NumericValue_js_1.numeric)(50), anchor = geometry_js_1.HorizontalAlign.Left, vanchor = geometry_js_1.VerticalAlign.Bottom, fontWeight = 'regular', angle: tmpLabelAngle = (0, NumericValue_js_1.numeric)(0), textColor = "#333", } = tmpLabel.style ?? {};
143
+ const { fontSize = (0, NumericValue_js_1.numeric)(50), anchor = geometry_js_1.HorizontalAlign.Left, vanchor = geometry_js_1.VerticalAlign.Bottom, fontWeight = 'regular', fontStyle = 'normal', angle: tmpLabelAngle = (0, NumericValue_js_1.numeric)(0), textColor = "#333", } = tmpLabel.style ?? {};
144
144
  let anchorStyle = 'start';
145
145
  let dominantBaseline = 'auto';
146
146
  let useAnchor = anchor;
@@ -294,15 +294,19 @@ class SymbolGraphic {
294
294
  if (isRotation180) {
295
295
  useLabelAngle = (labelAngle + 180) % 360;
296
296
  }
297
- textContainer.text(tmpLabel.text)
298
- .fill(textColor)
299
- .font({
297
+ const fontProperties = {
300
298
  family: useFont,
301
299
  size: fontSize.toNumber() * globals_js_1.fontDisplayScale,
302
300
  anchor: anchorStyle,
303
301
  'dominant-baseline': dominantBaseline,
304
302
  weight: fontWeight,
305
- })
303
+ };
304
+ if (fontStyle !== 'normal') {
305
+ fontProperties.style = fontStyle;
306
+ }
307
+ textContainer.text(tmpLabel.text)
308
+ .fill(textColor)
309
+ .font(fontProperties)
306
310
  .attr("xml:space", "preserve")
307
311
  .rotate(useLabelAngle, 0, 0);
308
312
  const { a, b, c, d, e, f } = textContainer.matrix();
@@ -352,6 +356,8 @@ class SymbolText extends SymbolGraphic {
352
356
  super();
353
357
  this.fontSize = (0, NumericValue_js_1.numeric)(40);
354
358
  this.fontWeight = 'regular';
359
+ this.fontStyle = 'normal';
360
+ this.color = undefined;
355
361
  this.text = text;
356
362
  }
357
363
  generateDrawing() {
@@ -361,6 +367,8 @@ class SymbolText extends SymbolGraphic {
361
367
  fontSize: this.fontSize,
362
368
  anchor: geometry_js_1.HorizontalAlign.Center,
363
369
  fontWeight: this.fontWeight,
370
+ fontStyle: this.fontStyle,
371
+ textColor: this.color
364
372
  });
365
373
  this.drawing = drawing;
366
374
  }
@@ -448,6 +456,9 @@ class SymbolPlaceholder extends SymbolGraphic {
448
456
  case PlaceHolderCommands.triangle:
449
457
  drawing.addTriangle(...positionParams);
450
458
  break;
459
+ case PlaceHolderCommands.arrow:
460
+ drawing.addArrow(...positionParams);
461
+ break;
451
462
  case PlaceHolderCommands.pin:
452
463
  case PlaceHolderCommands.hpin:
453
464
  case PlaceHolderCommands.vpin:
@@ -505,18 +516,16 @@ class SymbolPlaceholder extends SymbolGraphic {
505
516
  }
506
517
  parseLabelStyle(keywordParams) {
507
518
  const keywords = ['fontSize', 'anchor', 'vanchor',
508
- 'angle', 'textColor', 'portType', 'bold'];
519
+ 'angle', 'textColor', 'portType', 'bold', 'italic'];
509
520
  const style = {};
510
521
  keywords.forEach(item => {
511
522
  if (keywordParams.has(item)) {
512
523
  style[item] = keywordParams.get(item);
513
524
  if (item === 'bold') {
514
- if (keywordParams.get(item) === true) {
515
- style['fontWeight'] = 'bold';
516
- }
517
- else {
518
- style['fontWeight'] = 'normal';
519
- }
525
+ style.fontWeight = keywordParams.get(item) === true ? 'bold' : 'regular';
526
+ }
527
+ else if (item === 'italic') {
528
+ style.fontStyle = keywordParams.get(item) === true ? 'italic' : 'normal';
520
529
  }
521
530
  }
522
531
  });
@@ -677,6 +686,7 @@ var PlaceHolderCommands;
677
686
  PlaceHolderCommands["rect"] = "rect";
678
687
  PlaceHolderCommands["crect"] = "crect";
679
688
  PlaceHolderCommands["triangle"] = "triangle";
689
+ PlaceHolderCommands["arrow"] = "arrow";
680
690
  PlaceHolderCommands["pin"] = "pin";
681
691
  PlaceHolderCommands["hpin"] = "hpin";
682
692
  PlaceHolderCommands["vpin"] = "vpin";
@@ -1050,6 +1060,35 @@ class SymbolDrawing {
1050
1060
  ]));
1051
1061
  return this;
1052
1062
  }
1063
+ addArrow(startX, startY, endX, endY, arrowLength = (0, NumericValue_js_1.numeric)(25), arrowWidth = (0, NumericValue_js_1.numeric)(25)) {
1064
+ startX = (0, helpers_js_1.milsToMM)(startX);
1065
+ startY = (0, helpers_js_1.milsToMM)(startY);
1066
+ endX = (0, helpers_js_1.milsToMM)(endX);
1067
+ endY = (0, helpers_js_1.milsToMM)(endY);
1068
+ arrowLength = (0, helpers_js_1.milsToMM)(arrowLength);
1069
+ arrowWidth = (0, helpers_js_1.milsToMM)(arrowWidth);
1070
+ const dxNum = endX.sub(startX).toNumber();
1071
+ const dyNum = endY.sub(startY).toNumber();
1072
+ const len = Math.sqrt(dxNum * dxNum + dyNum * dyNum);
1073
+ const unitDx = (0, NumericValue_js_1.numeric)(dxNum / len);
1074
+ const unitDy = (0, NumericValue_js_1.numeric)(dyNum / len);
1075
+ const arrowBaseX = endX.sub(unitDx.mul(arrowLength));
1076
+ const arrowBaseY = endY.sub(unitDy.mul(arrowLength));
1077
+ this.items.push(geometry_js_1.Geometry.segment([startX, startY], [arrowBaseX, arrowBaseY]));
1078
+ const perpX = (0, NumericValue_js_1.numeric)(-unitDy.toNumber());
1079
+ const perpY = (0, NumericValue_js_1.numeric)(unitDx.toNumber());
1080
+ const dx1 = perpX.mul(arrowWidth).half();
1081
+ const dy1 = perpY.mul(arrowWidth).half();
1082
+ const dx2 = perpX.mul(arrowWidth.neg()).half();
1083
+ const dy2 = perpY.mul(arrowWidth.neg()).half();
1084
+ this.items.push(geometry_js_1.Geometry.polygon([
1085
+ [dx1.add(arrowBaseX), dy1.add(arrowBaseY)],
1086
+ [dx2.add(arrowBaseX), dy2.add(arrowBaseY)],
1087
+ [endX, endY],
1088
+ [dx1.add(arrowBaseX), dy1.add(arrowBaseY)],
1089
+ ]));
1090
+ return this;
1091
+ }
1053
1092
  addLabel(x, y, textValue, style) {
1054
1093
  this.items.push(geometry_js_1.Geometry.label(null, x, y, textValue, style));
1055
1094
  return this;
@@ -44,8 +44,8 @@ class Textbox extends core_1.default.Polygon {
44
44
  else {
45
45
  throw 'Invalid string passed into textbox';
46
46
  }
47
- const { fontSize = (0, NumericValue_js_1.numeric)(50), anchor = HorizontalAlign.Left, vanchor = VerticalAlign.Bottom, fontWeight = 'regular', portType = null, } = style ?? {};
48
- const { box } = (0, sizing_js_1.measureTextSize2)(useText, globals_js_1.defaultFont, fontSize.mul(globals_js_1.fontDisplayScale).toNumber(), fontWeight, anchor, vanchor);
47
+ const { fontSize = (0, NumericValue_js_1.numeric)(50), anchor = HorizontalAlign.Left, vanchor = VerticalAlign.Bottom, fontWeight = 'regular', fontStyle = 'normal', portType = null, } = style ?? {};
48
+ const { box } = (0, sizing_js_1.measureTextSize2)(useText, globals_js_1.defaultFont, fontSize.mul(globals_js_1.fontDisplayScale).toNumber(), fontWeight, fontStyle, anchor, vanchor);
49
49
  let polygonCoords = [];
50
50
  let anchorOffsetX = 0;
51
51
  let anchorOffsetY = 0;
@@ -556,12 +556,20 @@ class LayoutEngine {
556
556
  const isSheetFrame = frameObject.frameType === globals_js_1.FrameType.Sheet;
557
557
  if (frameParams.has(Frame_js_1.FrameParamKeys.Title) && !isSheetFrame) {
558
558
  const title = frameParams.get(Frame_js_1.FrameParamKeys.Title);
559
+ const fontSize = frameParams.get(Frame_js_1.FrameParamKeys.FontSize) ?? (0, NumericValue_js_1.numeric)(globals_js_1.defaultFrameTitleTextSize);
560
+ const isBold = frameParams.get(Frame_js_1.FrameParamKeys.Bold) ?? true;
561
+ const isItalic = frameParams.get(Frame_js_1.FrameParamKeys.Italic) ?? false;
562
+ const titleColor = frameParams.get(Frame_js_1.FrameParamKeys.Color) ?? null;
559
563
  const titleFrame = new RenderFrame(new Frame_js_1.Frame(Frame_js_1.FixedFrameIds.FrameIdNotUsed), RenderFrameType.Elements);
560
564
  titleFrame.containsTitle = true;
561
565
  titleFrame.subgraphId = title.replace(/\s/g, "_");
562
566
  const textObject = new RenderText(title);
563
- textObject.fontSize = (0, NumericValue_js_1.numeric)(globals_js_1.defaultFrameTitleTextSize);
564
- textObject.fontWeight = 'bold';
567
+ textObject.fontSize = fontSize;
568
+ textObject.fontWeight = isBold ? 'bold' : 'regular';
569
+ textObject.fontStyle = isItalic ? 'italic' : 'normal';
570
+ if (titleColor !== null) {
571
+ textObject.color = titleColor;
572
+ }
565
573
  textObject.x = (0, NumericValue_js_1.numeric)(0);
566
574
  textObject.y = (0, NumericValue_js_1.numeric)(0);
567
575
  textObject.symbol.refreshDrawing();
@@ -1228,10 +1236,26 @@ class RenderText extends RenderObject {
1228
1236
  this._fontWeight = value;
1229
1237
  this.symbol.fontWeight = value;
1230
1238
  }
1239
+ get fontStyle() {
1240
+ return this._fontStyle;
1241
+ }
1242
+ set fontStyle(value) {
1243
+ this._fontStyle = value;
1244
+ this.symbol.fontStyle = value;
1245
+ }
1246
+ get color() {
1247
+ return this._color;
1248
+ }
1249
+ set color(value) {
1250
+ this._color = value;
1251
+ this.symbol.color = value;
1252
+ }
1231
1253
  constructor(text) {
1232
1254
  super();
1233
1255
  this._fontSize = (0, NumericValue_js_1.numeric)(12);
1234
1256
  this._fontWeight = 'regular';
1257
+ this._fontStyle = 'normal';
1258
+ this._color = undefined;
1235
1259
  this.symbol = new draw_symbols_js_1.SymbolText(text);
1236
1260
  }
1237
1261
  }
@@ -10,10 +10,10 @@ function applyFontsToSVG(canvas) {
10
10
  exports.applyFontsToSVG = applyFontsToSVG;
11
11
  const measureTextSizeCache = {};
12
12
  const measureTextSizeCacheHits = {};
13
- function measureTextSize2(text, fontFamily, fontSize, fontWeight = 'regular', anchor = geometry_js_1.HorizontalAlign.Left, vanchor = geometry_js_1.VerticalAlign.Bottom) {
13
+ function measureTextSize2(text, fontFamily, fontSize, fontWeight = 'regular', fontStyle = 'normal', anchor = geometry_js_1.HorizontalAlign.Left, vanchor = geometry_js_1.VerticalAlign.Bottom) {
14
14
  const environment = environment_js_1.NodeScriptEnvironment.getInstance();
15
15
  const mainCanvas = environment.getCanvasWindow();
16
- const key = `${text}-${fontFamily}-${fontSize}-${fontWeight}-${anchor}-${vanchor}`;
16
+ const key = `${text}-${fontFamily}-${fontSize}-${fontWeight}-${fontStyle}-${anchor}-${vanchor}`;
17
17
  if (measureTextSizeCache[key] === undefined) {
18
18
  let dominantBaseline = geometry_js_1.VerticalAlignProp.Hanging;
19
19
  switch (vanchor) {
@@ -46,6 +46,7 @@ function measureTextSize2(text, fontFamily, fontSize, fontWeight = 'regular', an
46
46
  anchor: useAnchor,
47
47
  'dominant-baseline': dominantBaseline,
48
48
  weight: fontWeight,
49
+ style: fontStyle,
49
50
  })
50
51
  .attr("xml:space", "preserve")
51
52
  .fill('#333');
@@ -75,7 +75,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
75
75
  return this.getExecutor().getCurrentPoint();
76
76
  };
77
77
  this.visitTo_component_expr = (ctx) => {
78
- ctx.component_select_expr().forEach(item => {
78
+ for (const item of ctx.component_select_expr()) {
79
79
  let refComponent;
80
80
  const creationFlag = this.trackNewComponentCreated(() => {
81
81
  const [component, pin] = this.visitResult(item);
@@ -90,7 +90,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
90
90
  }
91
91
  });
92
92
  this.linkComponentToCtx(item, refComponent, creationFlag);
93
- });
93
+ }
94
94
  return this.getExecutor().getCurrentPoint();
95
95
  };
96
96
  this.visitComponent_select_expr = (ctx) => {
@@ -149,7 +149,18 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
149
149
  const blockStackEntry = scope.blockStack.get(scopeLevel);
150
150
  const { current_index } = blockStackEntry;
151
151
  executor.enterBlock(current_index);
152
- this.visit(ctx.expressions_block());
152
+ const ctxNonNewlineExpressions = ctx.non_newline_expression();
153
+ const ctxExpressionsBlock = ctx.expressions_block();
154
+ const ctxAtBlockExpressions = ctx.at_block_expressions();
155
+ if (ctxNonNewlineExpressions.length > 0) {
156
+ this.runExpressions(executor, ctxNonNewlineExpressions);
157
+ }
158
+ else if (ctxExpressionsBlock) {
159
+ this.visit(ctxExpressionsBlock);
160
+ }
161
+ else if (ctxAtBlockExpressions) {
162
+ this.visit(ctxAtBlockExpressions);
163
+ }
153
164
  executor.exitBlock(current_index);
154
165
  blockStackEntry.current_index++;
155
166
  };
@@ -498,14 +509,17 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
498
509
  let shouldIgnoreWireOrientation = false;
499
510
  if (modifierText === globals_js_1.ParamKeys.flip) {
500
511
  const flipValue = result.name;
512
+ let didSetX = false;
513
+ let didSetY = false;
501
514
  if (flipValue.indexOf('x') !== -1) {
502
515
  defaultUnit.setParam(globals_js_1.ParamKeys.flipX, (0, NumericValue_js_2.numeric)(1));
503
- shouldIgnoreWireOrientation = true;
516
+ didSetX = true;
504
517
  }
505
518
  if (flipValue.indexOf('y') !== -1) {
506
519
  defaultUnit.setParam(globals_js_1.ParamKeys.flipY, (0, NumericValue_js_2.numeric)(1));
507
- shouldIgnoreWireOrientation = true;
520
+ didSetY = true;
508
521
  }
522
+ shouldIgnoreWireOrientation = didSetX && didSetY;
509
523
  }
510
524
  else if (modifierText === globals_js_1.ParamKeys.angle) {
511
525
  defaultUnit.setParam(globals_js_1.ParamKeys.angle, result);
@@ -514,6 +528,9 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
514
528
  else if (modifierText === 'anchor') {
515
529
  dataResult.setParam('anchor', result.name);
516
530
  }
531
+ else {
532
+ dataResult.setParam(modifierText, result);
533
+ }
517
534
  if (shouldIgnoreWireOrientation) {
518
535
  defaultUnit.useWireOrientationAngle = false;
519
536
  }
@@ -720,24 +737,63 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
720
737
  };
721
738
  this.visitAt_block_pin_expr = (ctx) => {
722
739
  const executor = this.getExecutor();
723
- const [currentComponent, currentPin] = executor.getCurrentPoint();
740
+ const scope = this.getScope();
741
+ const scopeLevel = scope.scopeLevel;
742
+ const params = this.getResult(ctx);
743
+ const blockIndex = params.index;
744
+ let useComponent;
745
+ for (let i = scopeLevel - 1; i >= 0; i--) {
746
+ const blockStackEntry = scope.blockStack.get(i);
747
+ if (blockStackEntry.type === BlockTypes_js_1.BlockTypes.AtBlock) {
748
+ useComponent = blockStackEntry.start_point[0];
749
+ break;
750
+ }
751
+ }
724
752
  executor.closeOpenPathBlocks();
725
753
  const propKey = this.visitResult(ctx.property_key_expr());
726
754
  const atPin = new PinDefinition_js_1.PinId(propKey);
727
- executor.atComponent(currentComponent, atPin, {
755
+ executor.atComponent(useComponent, atPin, {
728
756
  addSequence: true
729
757
  });
730
- executor.log('at block pin expressions');
731
- const ctxExpression = ctx.expression();
758
+ executor.log(`at block pin expressions, pin id: ${atPin}`);
759
+ const ctxExpression = ctx.non_newline_expression();
732
760
  const ctxExpressionsBlock = ctx.expressions_block();
733
- if (ctxExpression) {
734
- this.visit(ctxExpression);
761
+ if (ctxExpression.length > 0) {
762
+ this.runExpressions(executor, ctxExpression);
735
763
  }
736
764
  else if (ctxExpressionsBlock) {
737
765
  this.visit(ctxExpressionsBlock);
738
766
  }
739
- executor.log('end at block pin expressions');
740
- executor.atComponent(currentComponent, currentPin);
767
+ const parentBlockStackEntry = scope.blockStack.get(scopeLevel - 1);
768
+ if (parentBlockStackEntry.type === BlockTypes_js_1.BlockTypes.Join) {
769
+ if (blockIndex === 0 && parentBlockStackEntry.current_index === 0) {
770
+ executor.addPointForBlockType(BlockTypes_js_1.BlockTypes.Join);
771
+ parentBlockStackEntry.end_point = [
772
+ scope.currentComponent,
773
+ scope.currentPin,
774
+ scope.currentWireId
775
+ ];
776
+ }
777
+ else {
778
+ const { end_point: finalPoint } = parentBlockStackEntry;
779
+ const [component, pin] = finalPoint;
780
+ executor.toComponent(component, pin, { addSequence: true });
781
+ }
782
+ }
783
+ };
784
+ this.visitAt_block_expressions = (ctx) => {
785
+ let atBlockPinIndex = 0;
786
+ for (const tmpCtx of ctx.at_block_expressions_inner()) {
787
+ const ctxAtBlockPin = tmpCtx.at_block_pin_expr();
788
+ if (ctxAtBlockPin) {
789
+ this.setResult(ctxAtBlockPin, { index: atBlockPinIndex });
790
+ atBlockPinIndex++;
791
+ this.visit(ctxAtBlockPin);
792
+ }
793
+ else {
794
+ this.visit(tmpCtx.expression());
795
+ }
796
+ }
741
797
  };
742
798
  this.visitAt_block_header = (ctx) => {
743
799
  const ctxAtComponent = ctx.at_component_expr();
@@ -751,33 +807,65 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
751
807
  };
752
808
  this.visitAt_block = (ctx) => {
753
809
  const executor = this.getExecutor();
754
- executor.log('entering at block');
810
+ const scope = this.getScope();
811
+ const scopeLevel = scope.scopeLevel;
812
+ if (scope.blockStack.has(scopeLevel)) {
813
+ executor.exitBlocks();
814
+ }
755
815
  const ctxAtBlockComponent = ctx.at_block_header();
756
816
  this.visit(ctxAtBlockComponent);
757
817
  const [currentComponent, currentPin] = executor.getCurrentPoint();
758
- executor.scope.scopeLevel += 1;
759
- ctx.at_block_expressions().forEach(expression => {
760
- this.visit(expression);
818
+ scope.blockStack.set(scopeLevel, {
819
+ start_point: [
820
+ scope.currentComponent,
821
+ scope.currentPin,
822
+ scope.currentWireId
823
+ ],
824
+ end_point: null,
825
+ current_index: 0,
826
+ type: BlockTypes_js_1.BlockTypes.AtBlock,
761
827
  });
828
+ executor.log('entering at block');
829
+ executor.scope.scopeLevel += 1;
830
+ this.visit(ctx.at_block_expressions());
762
831
  executor.scope.scopeLevel -= 1;
763
832
  executor.scope.setCurrent(currentComponent, currentPin);
833
+ scope.blockStack.delete(scopeLevel);
764
834
  executor.log('leaving at block');
765
835
  };
766
836
  this.visitWire_expr = (ctx) => {
767
837
  const segments = [];
768
838
  ctx.ID().forEach((ctxId, index) => {
769
- const value = ctxId.getText();
839
+ const valueText = ctxId.getText();
770
840
  const ctxDataExpr = ctx.data_expr(index);
771
- if ((value === globals_js_1.WireAutoDirection.Auto || value === globals_js_1.WireAutoDirection.Auto_) && ctxDataExpr === null) {
772
- segments.push([value]);
841
+ let value = null;
842
+ switch (valueText) {
843
+ case 'right':
844
+ case 'rg':
845
+ case 'r':
846
+ value = types_js_1.Direction.Right;
847
+ break;
848
+ case 'left':
849
+ case 'lf':
850
+ case 'l':
851
+ value = types_js_1.Direction.Left;
852
+ break;
853
+ case 'up':
854
+ case 'u':
855
+ value = types_js_1.Direction.Up;
856
+ break;
857
+ case 'down':
858
+ case 'dw':
859
+ case 'd':
860
+ value = types_js_1.Direction.Down;
861
+ break;
862
+ }
863
+ if ((valueText === globals_js_1.WireAutoDirection.Auto || valueText === globals_js_1.WireAutoDirection.Auto_) && ctxDataExpr === null) {
864
+ segments.push([valueText]);
773
865
  }
774
866
  else if (this.acceptedDirections.indexOf(value) !== -1 && ctxDataExpr) {
775
- let useValue = null;
776
- useValue = this.visitResult(ctxDataExpr);
777
- if (useValue instanceof NumericValue_js_1.NumericValue) {
778
- useValue = useValue.toNumber();
779
- }
780
- segments.push([value, new helpers_js_1.UnitDimension(useValue)]);
867
+ const useValue = this.visitResult(ctxDataExpr);
868
+ segments.push([value, new helpers_js_1.UnitDimension(useValue.toNumber())]);
781
869
  }
782
870
  else {
783
871
  this.throwWithContext(ctx, "Invalid wire expression");
@@ -833,9 +921,12 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
833
921
  if (ctx.Sheet()) {
834
922
  frameType = globals_js_1.FrameType.Sheet;
835
923
  }
836
- const frameId = this.getExecutor().enterFrame(frameType);
837
- this.visit(ctx.expressions_block());
838
- this.getExecutor().exitFrame(frameId);
924
+ const ctxExpressionsBlock = ctx.expressions_block();
925
+ if (ctxExpressionsBlock) {
926
+ const frameId = this.getExecutor().enterFrame(frameType);
927
+ this.visit(ctxExpressionsBlock);
928
+ this.getExecutor().exitFrame(frameId);
929
+ }
839
930
  };
840
931
  this.visitNet_namespace_expr = (ctx) => {
841
932
  let dataValue;
@@ -1108,6 +1199,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1108
1199
  const suffix = properties.get('suffix') ?? null;
1109
1200
  let pins = [];
1110
1201
  if (display !== null && arrange === null && typeProp !== globals_js_1.ComponentTypes.graphic) {
1202
+ display.variables = properties.get('params') ?? new Map();
1111
1203
  const drawCommands = display.getCommands();
1112
1204
  drawCommands.forEach(command => {
1113
1205
  const [commandValue,] = command;
@@ -1115,9 +1207,11 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1115
1207
  || commandValue === draw_symbols_js_1.PlaceHolderCommands.hpin
1116
1208
  || commandValue === draw_symbols_js_1.PlaceHolderCommands.pin) {
1117
1209
  const id = PinDefinition_js_1.PinId.from(command[1][0]);
1118
- const pinType = id.getType();
1119
- const pinName = id.toString();
1120
- pins.push(new PinDefinition_js_1.PinDefinition(id, pinType, pinName, PinTypes_js_1.PinTypes.Any));
1210
+ let pinName = id.toString();
1211
+ if (typeof command[1][1] === 'string') {
1212
+ pinName = command[1][1];
1213
+ }
1214
+ pins.push(new PinDefinition_js_1.PinDefinition(id, id.getType(), pinName, PinTypes_js_1.PinTypes.Any));
1121
1215
  }
1122
1216
  });
1123
1217
  }
@@ -295,6 +295,7 @@ export class BaseVisitor extends CircuitScriptParserVisitor {
295
295
  const rhsValue = unwrapValue(rhsCtxResult);
296
296
  this.assignValueToReference(sequenceParts, leftSideReference, lhsCtx, rhsValue);
297
297
  if (sequenceParts.length > 0) {
298
+ this.log('add sequence action: assign');
298
299
  this.getScope().sequence.push([
299
300
  SequenceAction.Assign, ...sequenceParts
300
301
  ]);
@@ -23,21 +23,15 @@ export class ComponentAnnotater {
23
23
  else {
24
24
  const type = instance.typeProp ?? 'conn';
25
25
  if (this.counter[type] === undefined && type.length <= 2) {
26
- for (const [, value] of Object.entries(ComponentRefDesPrefixes)) {
27
- if (value === type) {
28
- throw "Refdes prefix is already in use!";
29
- }
30
- }
31
- if (ComponentRefDesPrefixes[type] === undefined) {
32
- ComponentRefDesPrefixes[type] = type;
33
- this.counter[type] = 1;
34
- }
26
+ ComponentRefDesPrefixes[type] = type;
27
+ this.counter[type] = 1;
35
28
  }
29
+ let useType = type;
36
30
  if (ComponentRefDesPrefixes[type] === undefined) {
37
- return null;
31
+ useType = 'conn';
38
32
  }
39
- usePrefix = ComponentRefDesPrefixes[type];
40
- useCounterKey = type;
33
+ usePrefix = ComponentRefDesPrefixes[useType];
34
+ useCounterKey = useType;
41
35
  }
42
36
  let prefix = '';
43
37
  let resultRefdes = '';