From ea31bac351e90cd4c8d502bdb55d12df86d16c15 Mon Sep 17 00:00:00 2001 From: John Lorentzson Date: Wed, 9 Jul 2025 13:30:20 +0200 Subject: [PATCH] Fix compilation of loops with variable as stop value It was previously decided that, since the language is not to be Turing-complete, a loop that takes a variable for its upper bound should use the variable's value at the time of the loop's start, not look it up. I forgot this while writing the syntax->IR compiler, so loops with non-constant stop counts failed to compile. --- .../middle/compile-node-to-ir.lisp | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/wip-duuqnd/user-side-compiler/middle/compile-node-to-ir.lisp b/wip-duuqnd/user-side-compiler/middle/compile-node-to-ir.lisp index e29b1d9..ebbbb41 100644 --- a/wip-duuqnd/user-side-compiler/middle/compile-node-to-ir.lisp +++ b/wip-duuqnd/user-side-compiler/middle/compile-node-to-ir.lisp @@ -91,14 +91,27 @@ (build-begin builder continuation))) (defmethod compile-node ((node node-dotimes) builder) - (unless (zerop (ref-value (stop-ref node))) - (let ((const-zero (make-instance 'ir-constant)) - (const-stop (make-instance 'ir-constant)) - (loop-body (make-instance 'iblock :name "loop")) - (continuation (make-instance 'iblock :name "after_loop")) - (counter-variable (find-variable (counter-ref node) builder)) - - (test-result (make-instance 'ir-result))) + (unless (and (typep (stop-ref node) 'reference-constant) + (zerop (ref-value (stop-ref node)))) + (let* ((stop-ref-const-p (typep (stop-ref node) 'reference-constant)) + (const-zero (make-instance 'ir-constant)) + (const-stop (if stop-ref-const-p + (make-instance 'ir-constant) + (make-instance 'ir-result))) + (loop-body (make-instance 'iblock :name "loop")) + (continuation (make-instance 'iblock :name "after_loop")) + (counter-variable (find-variable (counter-ref node) builder)) + (test-result (make-instance 'ir-result))) + (unless stop-ref-const-p + (let ((zero (make-instance 'ir-constant))) + (build-insert (make-instance 'ir-getconst :input 0 :output zero) + builder) + (build-insert (make-instance + 'ir-plus + :inputs (list (compile-node (stop-ref node) builder) + zero) + :output const-stop) + builder))) (build-insert (make-instance 'ir-getconst :input 0 :output const-zero) builder) @@ -138,10 +151,11 @@ :input counter-variable :output counter-value) builder) - (build-insert (make-instance 'ir-getconst - :input (ref-value (stop-ref node)) - :output const-stop) - builder) + (when stop-ref-const-p + (build-insert (make-instance 'ir-getconst + :input (ref-value (stop-ref node)) + :output const-stop) + builder)) (build-insert (make-instance 'ir-test-equal :inputs (list counter-value const-stop) :output test-result)