From dcfed43433328a91972709f16ddcb94754f57bef Mon Sep 17 00:00:00 2001 From: MichalMarsalek <MichalMarsalek@users.noreply.github.com> Date: Sun, 12 Nov 2023 16:51:56 +0100 Subject: [PATCH 1/2] flatten block after replacement causes nesting --- src/common/Spine.ts | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/common/Spine.ts b/src/common/Spine.ts index 19b50d3c..7fefd105 100644 --- a/src/common/Spine.ts +++ b/src/common/Spine.ts @@ -1,4 +1,4 @@ -import { type IR, isOp, op } from "../IR"; +import { type IR, isOp, op, isOfKind, block } from "../IR"; import { type CompilationContext } from "./compile"; import { getChild, getChildFragments, type PathFragment } from "./fragments"; import { replaceAtIndex } from "./arrays"; @@ -70,26 +70,29 @@ export class Spine<N extends IR.Node = IR.Node> { if (this.parent === null || this.pathFragment === null) { return new Spine(newNode, null, null); } - if (newNode.kind === "Block" && this.parent.node.kind === "Block") { - throw new Error( - `Programming error: attempt to insert a Block into a Block`, - ); - } const parentNode = this.parent.node; const parent = canonizeAndReturnRoot && - isOp()(parentNode) && + isOfKind("Op", "Block")(parentNode) && typeof this.pathFragment === "object" ? this.parent.replacedWith( { - ...op( - parentNode.op, - ...replaceAtIndex( - parentNode.args, - this.pathFragment.index, - newNode, - ), - ), + ...(isOp()(parentNode) + ? op( + parentNode.op, + ...replaceAtIndex( + parentNode.args, + this.pathFragment.index, + newNode, + ), + ) + : block( + replaceAtIndex( + parentNode.children, + this.pathFragment.index, + newNode, + ), + )), targetType: parentNode.targetType, }, true, @@ -144,8 +147,8 @@ export class Spine<N extends IR.Node = IR.Node> { // eslint-disable-next-line @typescript-eslint/no-this-alias let curr = this as Spine; // recurse on children - if (isOp()(this.node)) { - // Create canonical Op instead of just replacing the chidren + if (isOfKind("Op", "Block")(this.node)) { + // Create canonical Op / block instead of just replacing the chidren const newChildren: IR.Node[] = []; let someChildrenIsNew = false; for (const child of this.getChildSpines()) { @@ -155,7 +158,9 @@ export class Spine<N extends IR.Node = IR.Node> { } if (someChildrenIsNew) curr = curr.replacedWith({ - ...op(this.node.op, ...newChildren), + ...(isOp()(this.node) + ? op(this.node.op, ...newChildren) + : block(newChildren)), targetType: this.node.targetType, }); } else { From e79a89ad08b1e38ab3673f9be82835618a37d49b Mon Sep 17 00:00:00 2001 From: Jared Hughes <jahughes241@gmail.com> Date: Sun, 12 Nov 2023 14:06:23 -0800 Subject: [PATCH 2/2] Add test "For range to while, inside a block" --- src/plugins/loops.test.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/plugins/loops.test.md b/src/plugins/loops.test.md index 219349e1..50790c2f 100644 --- a/src/plugins/loops.test.md +++ b/src/plugins/loops.test.md @@ -28,6 +28,30 @@ for_c_like ($i <- 0) ($i < 10) ($i <- (1 + $i)) ( ); ``` +## For range to while, inside a block + +```polygolf +for $i 0 10 { + print_int $x; +}; +for $j 1 11 { + print_int $y; +}; +``` + +```polygolf loops.forRangeToWhile +$i <- 0; +while ($i < 10) { + print_int $x; + $i <- (1 + $i); +}; +$j <- 1; +while ($j < 11) { + print_int $y; + $j <- (1 + $j); +}; +``` + ## For each ```polygolf