fisl

fisl is scheme lox
git clone git://git.alexkarle.com.com/fisl
Log | Files | Refs | README | LICENSE

commit 415557bdff9d34b562c8b8c17dbe6467a54420e5 (patch)
parent cf77b879d8cbf5bd345a8c40d197dd9f8708c9fb
Author: Alex Karle <alex@alexkarle.com>
Date:   Fri, 18 Nov 2022 14:03:52 -0500

ch9.5: Implement an ugly version of for-loops

I realized knee deep into the desugaring that these cascading 'let's
should just be function composition... I'll refactor in a subsequent
commit. For now I need to go for a jog!

Diffstat:
Aexamples/for.lox | 8++++++++
Mparser.scm | 42++++++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/examples/for.lox b/examples/for.lox @@ -0,0 +1,8 @@ +var a = 0; +var temp; + +for (var b = 1; a < 10000; b = temp + b) { + print a; + temp = a; + a = b; +} diff --git a/parser.scm b/parser.scm @@ -102,6 +102,8 @@ (define (parse-statement tokens) (cond ((top-type? tokens '(PRINT)) (parse-print-statement (cdr tokens))) + ((top-type? tokens '(FOR)) + (parse-for-statement (cdr tokens))) ((top-type? tokens '(IF)) (parse-if-statement (cdr tokens))) ((top-type? tokens '(WHILE)) @@ -120,6 +122,7 @@ (values (maker expr) (cdr toks)) (if in-repl (values (maker expr) toks) + ;; TODO: this might break for-loop parsing in the repl? (parse-err! toks "expected ;"))))) (define (parse-print-statement tokens) @@ -137,6 +140,45 @@ (let-values (((body-stmt toks2) (parse-statement (cdr toks)))) (values (make-while-stmt cond-expr body-stmt) toks2)))))) +(define (parse-for-statement tokens) + ;; TODO: how do we simplify this many parse-err! asserts / parse passes? + (if (not (top-type? tokens '(LEFT_PAREN))) + (parse-err! tokens "Expected '(' after 'for'") + (let-values (((init toks) + (cond ((top-type? (cdr tokens) '(SEMICOLON)) + (values '() (cddr tokens))) + ((top-type? (cdr tokens) '(VAR)) + (parse-var-decl (cddr tokens))) + (else (parse-expression-statement (cdr tokens)))))) + (let-values (((conde toks2) + (cond ((top-type? toks '(SEMICOLON)) + (values '() toks)) + (else (parse-expression '() toks))))) + (if (not (top-type? toks2 '(SEMICOLON))) + (parse-err! toks2 "Expected ';' after loop condition") + (let-values (((incr toks3) + (cond ((top-type? (cdr toks2) '(RIGHT_PAREN)) + (values '() (cdr toks2))) + (else (parse-expression '() (cdr toks2)))))) + (if (not (top-type? toks3 '(RIGHT_PAREN))) + (parse-err! toks3 "Expected ')' after for clauses") + (let-values (((body toks4) (parse-statement (cdr toks3)))) + ;; TODO: refactor. I seem to like to "transform" variables + ;; by just repeatedly let-binding new versions instead of + ;; using set! --> maybe use composed functions? + (let ((incr-body + (if (null? incr) + body + (make-block (list body (make-expr-stmt incr)))))) + (let ((cond-body + (if (null? conde) + (make-while-stmt (make-literal #t) incr-body) + (make-while-stmt conde incr-body)))) + (if (null? init) + (values cond-body toks4) + (values (make-block (list init cond-body)) toks4)))))))))))) + + (define (parse-block tokens) (let loop ((stmts '()) (toks tokens)) (if (top-type? toks '(RIGHT_BRACE))