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.
This commit is contained in:
John Lorentzson 2025-07-09 13:30:20 +02:00
parent 857fa43df0
commit ea31bac351

View file

@ -91,14 +91,27 @@
(build-begin builder continuation))) (build-begin builder continuation)))
(defmethod compile-node ((node node-dotimes) builder) (defmethod compile-node ((node node-dotimes) builder)
(unless (zerop (ref-value (stop-ref node))) (unless (and (typep (stop-ref node) 'reference-constant)
(let ((const-zero (make-instance 'ir-constant)) (zerop (ref-value (stop-ref node))))
(const-stop (make-instance 'ir-constant)) (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")) (loop-body (make-instance 'iblock :name "loop"))
(continuation (make-instance 'iblock :name "after_loop")) (continuation (make-instance 'iblock :name "after_loop"))
(counter-variable (find-variable (counter-ref node) builder)) (counter-variable (find-variable (counter-ref node) builder))
(test-result (make-instance 'ir-result))) (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 (build-insert (make-instance 'ir-getconst
:input 0 :output const-zero) :input 0 :output const-zero)
builder) builder)
@ -138,10 +151,11 @@
:input counter-variable :input counter-variable
:output counter-value) :output counter-value)
builder) builder)
(when stop-ref-const-p
(build-insert (make-instance 'ir-getconst (build-insert (make-instance 'ir-getconst
:input (ref-value (stop-ref node)) :input (ref-value (stop-ref node))
:output const-stop) :output const-stop)
builder) builder))
(build-insert (make-instance 'ir-test-equal (build-insert (make-instance 'ir-test-equal
:inputs (list counter-value const-stop) :inputs (list counter-value const-stop)
:output test-result) :output test-result)