circuitscript 0.5.6 → 0.6.0

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 (41) hide show
  1. package/dist/cjs/BaseVisitor.js +1 -0
  2. package/dist/cjs/annotate/RefdesAnnotationVisitor.js +1 -3
  3. package/dist/cjs/antlr/CircuitScriptParser.js +1070 -840
  4. package/dist/cjs/cache/serializer.js +1 -1
  5. package/dist/cjs/execute.js +18 -7
  6. package/dist/cjs/objects/BlockTypes.js +1 -0
  7. package/dist/cjs/objects/Frame.js +4 -0
  8. package/dist/cjs/regenerate-tests.js +12 -3
  9. package/dist/cjs/render/draw_symbols.js +18 -12
  10. package/dist/cjs/render/geometry.js +2 -2
  11. package/dist/cjs/render/layout.js +26 -2
  12. package/dist/cjs/sizing.js +3 -2
  13. package/dist/cjs/visitor.js +85 -18
  14. package/dist/esm/BaseVisitor.js +1 -0
  15. package/dist/esm/annotate/RefdesAnnotationVisitor.js +1 -3
  16. package/dist/esm/antlr/CircuitScriptParser.js +1063 -835
  17. package/dist/esm/antlr/CircuitScriptParserVisitor.js +2 -0
  18. package/dist/esm/cache/serializer.js +1 -1
  19. package/dist/esm/execute.js +18 -7
  20. package/dist/esm/objects/BlockTypes.js +1 -0
  21. package/dist/esm/objects/Frame.js +4 -0
  22. package/dist/esm/regenerate-tests.js +12 -3
  23. package/dist/esm/render/draw_symbols.js +18 -12
  24. package/dist/esm/render/geometry.js +2 -2
  25. package/dist/esm/render/layout.js +26 -2
  26. package/dist/esm/sizing.js +3 -2
  27. package/dist/esm/visitor.js +85 -18
  28. package/dist/libs/std.cst +3 -1
  29. package/dist/types/BaseVisitor.d.ts +2 -2
  30. package/dist/types/antlr/CircuitScriptParser.d.ts +83 -63
  31. package/dist/types/antlr/CircuitScriptParserVisitor.d.ts +4 -0
  32. package/dist/types/execute.d.ts +1 -0
  33. package/dist/types/objects/BlockTypes.d.ts +2 -1
  34. package/dist/types/objects/Frame.d.ts +4 -0
  35. package/dist/types/render/draw_symbols.d.ts +3 -3
  36. package/dist/types/render/geometry.d.ts +1 -0
  37. package/dist/types/render/layout.d.ts +6 -0
  38. package/dist/types/sizing.d.ts +1 -1
  39. package/dist/types/visitor.d.ts +2 -1
  40. package/libs/std.cst +3 -1
  41. package/package.json +5 -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
  }
@@ -374,6 +374,7 @@ class ExecutionContext {
374
374
  this.applyComponentAngleFromWire(component, pinId);
375
375
  this.scope.setCurrent(component, pinId);
376
376
  this.scope.clearActive();
377
+ this.log('clear active wire/frame (to component)');
377
378
  if (addSequence) {
378
379
  if (this.scope.sequence.length > 0) {
379
380
  const [entryType, , segments] = this.scope.sequence[this.scope.sequence.length - 1];
@@ -410,6 +411,7 @@ class ExecutionContext {
410
411
  this.scope.setNet(component, usePinId, tmpNet);
411
412
  }
412
413
  this.scope.clearActive();
414
+ this.log('clear active wire/frame (at component)');
413
415
  if (addSequence) {
414
416
  this.scope.sequence.push([ExecutionScope_js_1.SequenceAction.At,
415
417
  component, usePinId]);
@@ -448,8 +450,12 @@ class ExecutionContext {
448
450
  || blockType === BlockTypes_js_1.BlockTypes.Parallel
449
451
  || blockType === BlockTypes_js_1.BlockTypes.Branch) {
450
452
  const key = (0, utils_js_1.getBlockTypeString)(blockType);
453
+ const wireIdBefore = this.scope.currentWireId;
451
454
  this.addPoint(`${globals_js_1.Delimiter1}${key}.${this.name}.${this.tmpPointId}`, false);
452
455
  this.tmpPointId += 1;
456
+ if (wireIdBefore !== -1) {
457
+ this.scope.currentWireId = wireIdBefore;
458
+ }
453
459
  }
454
460
  this.scope.blockStack.set(this.scope.scopeLevel, {
455
461
  start_point: [
@@ -542,9 +548,7 @@ class ExecutionContext {
542
548
  }
543
549
  else if (blockType === BlockTypes_js_1.BlockTypes.Join || blockType === BlockTypes_js_1.BlockTypes.Parallel) {
544
550
  if (blockIndex === 0) {
545
- const pointIdName = `${globals_js_1.Delimiter1}${(0, utils_js_1.getBlockTypeString)(blockType)}`;
546
- this.addPoint(`${pointIdName}.${this.name}.${this.tmpPointId}`, false);
547
- this.tmpPointId += 1;
551
+ this.addPointForBlockType(blockType);
548
552
  stackRef.end_point = [
549
553
  this.scope.currentComponent,
550
554
  this.scope.currentPin,
@@ -558,6 +562,11 @@ class ExecutionContext {
558
562
  }
559
563
  }
560
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
+ }
561
570
  atPointBlock() {
562
571
  const [component, pin,] = this.getPointBlockLocation();
563
572
  this.atComponent(component, pin, {
@@ -574,10 +583,12 @@ class ExecutionContext {
574
583
  this.log('get block point');
575
584
  for (let i = 0; i < this.scope.scopeLevel; i++) {
576
585
  const stackRef = this.scope.blockStack.get(this.scope.scopeLevel - 1 - i);
577
- const { start_point } = stackRef;
578
- const component = start_point[0];
579
- if (component.instanceName.startsWith(`${globals_js_1.Delimiter1}point.`)) {
580
- 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
+ }
581
592
  }
582
593
  }
583
594
  this.log('did not find block point');
@@ -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 = {}));
@@ -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 = {}));
@@ -9,13 +9,15 @@ const environment_js_1 = require("./environment/environment.js");
9
9
  const mainDir = './__tests__/testData/renderData/';
10
10
  const env = new environment_js_1.NodeScriptEnvironment();
11
11
  environment_js_1.NodeScriptEnvironment.setInstance(env);
12
- async function regenerateTests(extra = "") {
12
+ async function regenerateTests(extra = "", fileList = []) {
13
13
  await env.prepareSVGEnvironment();
14
14
  const cstFiles = [];
15
15
  const files = fs_1.default.readdirSync(mainDir);
16
16
  files.forEach(file => {
17
17
  if (file.endsWith('.cst') && file.startsWith('script')) {
18
- cstFiles.push(file);
18
+ if (fileList.length === 0 || fileList.includes(file)) {
19
+ cstFiles.push(file);
20
+ }
19
21
  }
20
22
  });
21
23
  for (let i = 0; i < cstFiles.length; i++) {
@@ -38,8 +40,15 @@ async function regenerateTests(extra = "") {
38
40
  (async () => {
39
41
  const generateDiff = (process.argv.indexOf('-diff') !== -1);
40
42
  console.log('diff flag: ', generateDiff);
43
+ const listIndex = process.argv.indexOf('--list');
44
+ const fileList = listIndex !== -1 && process.argv[listIndex + 1]
45
+ ? process.argv[listIndex + 1].split(',').map(f => f.trim())
46
+ : [];
47
+ if (fileList.length > 0) {
48
+ console.log('filtering to files: ', fileList);
49
+ }
41
50
  const nextExtra = generateDiff ? '.next' : '';
42
- const cstFiles = await regenerateTests(nextExtra);
51
+ const cstFiles = await regenerateTests(nextExtra, fileList);
43
52
  const allFiles = [];
44
53
  if (generateDiff) {
45
54
  cstFiles.forEach(file => {
@@ -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
  }
@@ -505,18 +513,16 @@ class SymbolPlaceholder extends SymbolGraphic {
505
513
  }
506
514
  parseLabelStyle(keywordParams) {
507
515
  const keywords = ['fontSize', 'anchor', 'vanchor',
508
- 'angle', 'textColor', 'portType', 'bold'];
516
+ 'angle', 'textColor', 'portType', 'bold', 'italic'];
509
517
  const style = {};
510
518
  keywords.forEach(item => {
511
519
  if (keywordParams.has(item)) {
512
520
  style[item] = keywordParams.get(item);
513
521
  if (item === 'bold') {
514
- if (keywordParams.get(item) === true) {
515
- style['fontWeight'] = 'bold';
516
- }
517
- else {
518
- style['fontWeight'] = 'normal';
519
- }
522
+ style.fontWeight = keywordParams.get(item) === true ? 'bold' : 'regular';
523
+ }
524
+ else if (item === 'italic') {
525
+ style.fontStyle = keywordParams.get(item) === true ? 'italic' : 'normal';
520
526
  }
521
527
  }
522
528
  });
@@ -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
  };
@@ -720,24 +731,63 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
720
731
  };
721
732
  this.visitAt_block_pin_expr = (ctx) => {
722
733
  const executor = this.getExecutor();
723
- const [currentComponent, currentPin] = executor.getCurrentPoint();
734
+ const scope = this.getScope();
735
+ const scopeLevel = scope.scopeLevel;
736
+ const params = this.getResult(ctx);
737
+ const blockIndex = params.index;
738
+ let useComponent;
739
+ for (let i = scopeLevel - 1; i >= 0; i--) {
740
+ const blockStackEntry = scope.blockStack.get(i);
741
+ if (blockStackEntry.type === BlockTypes_js_1.BlockTypes.AtBlock) {
742
+ useComponent = blockStackEntry.start_point[0];
743
+ break;
744
+ }
745
+ }
724
746
  executor.closeOpenPathBlocks();
725
747
  const propKey = this.visitResult(ctx.property_key_expr());
726
748
  const atPin = new PinDefinition_js_1.PinId(propKey);
727
- executor.atComponent(currentComponent, atPin, {
749
+ executor.atComponent(useComponent, atPin, {
728
750
  addSequence: true
729
751
  });
730
- executor.log('at block pin expressions');
731
- const ctxExpression = ctx.expression();
752
+ executor.log(`at block pin expressions, pin id: ${atPin}`);
753
+ const ctxExpression = ctx.non_newline_expression();
732
754
  const ctxExpressionsBlock = ctx.expressions_block();
733
- if (ctxExpression) {
734
- this.visit(ctxExpression);
755
+ if (ctxExpression.length > 0) {
756
+ this.runExpressions(executor, ctxExpression);
735
757
  }
736
758
  else if (ctxExpressionsBlock) {
737
759
  this.visit(ctxExpressionsBlock);
738
760
  }
739
- executor.log('end at block pin expressions');
740
- executor.atComponent(currentComponent, currentPin);
761
+ const parentBlockStackEntry = scope.blockStack.get(scopeLevel - 1);
762
+ if (parentBlockStackEntry.type === BlockTypes_js_1.BlockTypes.Join) {
763
+ if (blockIndex === 0 && parentBlockStackEntry.current_index === 0) {
764
+ executor.addPointForBlockType(BlockTypes_js_1.BlockTypes.Join);
765
+ parentBlockStackEntry.end_point = [
766
+ scope.currentComponent,
767
+ scope.currentPin,
768
+ scope.currentWireId
769
+ ];
770
+ }
771
+ else {
772
+ const { end_point: finalPoint } = parentBlockStackEntry;
773
+ const [component, pin] = finalPoint;
774
+ executor.toComponent(component, pin, { addSequence: true });
775
+ }
776
+ }
777
+ };
778
+ this.visitAt_block_expressions = (ctx) => {
779
+ let atBlockPinIndex = 0;
780
+ for (const tmpCtx of ctx.at_block_expressions_inner()) {
781
+ const ctxAtBlockPin = tmpCtx.at_block_pin_expr();
782
+ if (ctxAtBlockPin) {
783
+ this.setResult(ctxAtBlockPin, { index: atBlockPinIndex });
784
+ atBlockPinIndex++;
785
+ this.visit(ctxAtBlockPin);
786
+ }
787
+ else {
788
+ this.visit(tmpCtx.expression());
789
+ }
790
+ }
741
791
  };
742
792
  this.visitAt_block_header = (ctx) => {
743
793
  const ctxAtComponent = ctx.at_component_expr();
@@ -751,16 +801,30 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
751
801
  };
752
802
  this.visitAt_block = (ctx) => {
753
803
  const executor = this.getExecutor();
754
- executor.log('entering at block');
804
+ const scope = this.getScope();
805
+ const scopeLevel = scope.scopeLevel;
806
+ if (scope.blockStack.has(scopeLevel)) {
807
+ executor.exitBlocks();
808
+ }
755
809
  const ctxAtBlockComponent = ctx.at_block_header();
756
810
  this.visit(ctxAtBlockComponent);
757
811
  const [currentComponent, currentPin] = executor.getCurrentPoint();
758
- executor.scope.scopeLevel += 1;
759
- ctx.at_block_expressions().forEach(expression => {
760
- this.visit(expression);
812
+ scope.blockStack.set(scopeLevel, {
813
+ start_point: [
814
+ scope.currentComponent,
815
+ scope.currentPin,
816
+ scope.currentWireId
817
+ ],
818
+ end_point: null,
819
+ current_index: 0,
820
+ type: BlockTypes_js_1.BlockTypes.AtBlock,
761
821
  });
822
+ executor.log('entering at block');
823
+ executor.scope.scopeLevel += 1;
824
+ this.visit(ctx.at_block_expressions());
762
825
  executor.scope.scopeLevel -= 1;
763
826
  executor.scope.setCurrent(currentComponent, currentPin);
827
+ scope.blockStack.delete(scopeLevel);
764
828
  executor.log('leaving at block');
765
829
  };
766
830
  this.visitWire_expr = (ctx) => {
@@ -833,9 +897,12 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
833
897
  if (ctx.Sheet()) {
834
898
  frameType = globals_js_1.FrameType.Sheet;
835
899
  }
836
- const frameId = this.getExecutor().enterFrame(frameType);
837
- this.visit(ctx.expressions_block());
838
- this.getExecutor().exitFrame(frameId);
900
+ const ctxExpressionsBlock = ctx.expressions_block();
901
+ if (ctxExpressionsBlock) {
902
+ const frameId = this.getExecutor().enterFrame(frameType);
903
+ this.visit(ctxExpressionsBlock);
904
+ this.getExecutor().exitFrame(frameId);
905
+ }
839
906
  };
840
907
  this.visitNet_namespace_expr = (ctx) => {
841
908
  let dataValue;
@@ -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
  ]);
@@ -47,9 +47,7 @@ export class RefdesAnnotationVisitor extends BaseVisitor {
47
47
  };
48
48
  visitAt_block = (ctx) => {
49
49
  this.visit(ctx.at_block_header());
50
- ctx.at_block_expressions().forEach(expression => {
51
- this.visit(expression);
52
- });
50
+ this.visit(ctx.at_block_expressions());
53
51
  };
54
52
  visitTo_component_expr = (ctx) => {
55
53
  const allRefdes = [];