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