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)))
(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)