refactor: Use aslist-ref instead of assoc/cadr The joys of learning the base library over time :)
refactor: Update for-loop extraction and desugaring to use composition This updates the for loop parser to go from a bunch of if-trees to a bunch of functions, each taking the previous values as input, which results in a very flat tree (dare I say more testable too?).
refactor: Add `assert-type!` to avoid many `(if (top-type?))` trees This is a nice readability enhancement. It's safe since assert-type! calls parse-err! which in turn call/cc's its way to safety (aborting the current parse.
refactor: Allow top-type? to take in symbol or list Might as well use dynamic typing to its fullest!
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!
ch9.4: Implement 'while' loops Another fun one to see come together! ~/src/fisl $ cat examples/while.lox var x = 10; while (x > 0) { print x; x = x - 1; } ~/src/fisl $ ./fisl.scm examples/while.lox 10 9 8 7 6 5 4 3 2 1
assignment: Fix assignment vs definition bug I had intermingled assignment and definition such that var x = 5; and x = 5; did the same thing, when really the first should create a new binding in the current environment and the second should update the value in *whichever environment has x defined (the closest one)*. This was found while implementing 'while' since the following was an infinite loop: var x = 10; while (x > 0) { print x; x = x - 1; } With the splitting of var -> env-def! and = -> env-set! in this patch, it works as expected!
ch9.3: Implement 'and' and 'or' operators It feels a little weird that these return the _value_ and not #t or #f. Let's see what scheme does :thinking: > (and "hi" "hello") "hello" > (or "hi" "hello") "hi" Well, you learn something new every day.
ch9.2: Implement if statements Pretty cool to see this shake out :) > var x = 3; 3 > if (x == 3) { print "woo"; } else { print "else"; } woo
Add full block environments! (ch8.5) This implements the parser for blocks as well as the necessary interpreter bits! Check it out! $ cat examples/scope.lox var a = "global a"; var b = "global b"; var c = "global c"; { var a = "outer a"; var b = "outer b"; { var a = "inner a"; print a; print b; print c; } print a; print b; print c; } print a; print b; print c; $ ./fisl.scm examples/scope.lox inner a outer b global c outer a outer b global c global a global b global c
interpreter: Add custom 'env' object for nested envs This sets the stage for block scope, but keeps the existing "everything is global" behavior. I'm 85% sure the (make-env) returning a proc that returns procs is something I've seen in SICP (as a means of creating objects with methods).
parser: Fix synchronization at end of input In Scheme, only #f is falsey: > (if 0 (print "truthy")) truthy > (if '() (print "truthy")) truthy So checking (and toks ...) wasn't doing the empty list check I was intending!
parser: Add synchronization at declaration level Before the parser stopped entirely at the first parse error: $ cat examples/sync.lox print 1 + for; print 2 + 2; print 1 + this; $ ./fisl.scm examples/sync.lox examples/sync.lox:1:Error at for. Unknown token Now it synchronizes by going to the next statement and finds all parse errors (but does NOT execute them): $ ./fisl.scm examples/sync.lox examples/sync.lox:1:Error at for. Unknown token examples/sync.lox:3:Error at this. Unknown token
docs: Fix some TODO's and comment indentation Emacs likes to put single-; comments way to the right :( Mostly back in Vim now, if anyone is curious.
repl: Print expr-stmts and drop need for ';' In the repl, we can drop the requirements on using ';' for most statements. By allowing execute to evaluate and print expr-statemtents we go from this: > var x = 1; > print x = 2; 2 to > var x = 1; > x = 2 2 > x 2 Nice!
cleanup: Remove repl logging at startup
interpreter: Fix assignment not evaluating RHS This was a funny find :) Before $ ./fisl.scm > var x = 1; > print x = 1 + 1; (+ 1 1) After: > var x; > print x = 1 + 1; 2 > print x; 2
refactor: let-values, fname global, less nested functions This is a large overhaul of the parser.scm code to: * Use let-values / values instead of (let*) and (cons). * Renaming all parsing functions to (parse-*) to indicate they.. parse * Making fname a global for util so that I don't have to keep passing it * Removing the nesting of all the parsing functions (to better support repl development!) * Rewriting all the generic binary / statement code to follow a general form with functions as parameters to "descend"
repl: Add threads and nrepl for live image updates This was a deep rabbit hole, mostly because (read-line) is blocking I/O and _all_ threads block when blocking I/O is hit (except tcp). This was counterintuitive (isn't the whole point of threads to swap when on I/O?) but nevertheless, I got it to work! Here's my setup: 1. Start the CHICKEN interpreter via the executable (drops into Lox interpreter): $ ./fisl.scm > print 1 + 1; 2 > 2. In another tmux split, create a fifo and connect to the 1234 nrepl port (credit: http://www.foldling.org/hacking.html#2012-08-05): $ mkfifo repl $ cat > repl & nc localhost 1234 < repl 3. Lastly, in Vim, run the following to send the current paragraph to the repl on C-c C-c: :nnoremap <C-c><C-c> vap:w >> repl<CR> --- Demo: * Go to (prompt), update s/display "> "/display ">> "/ * C-c C-c * Hit enter in fisl -- notice prompt is changed!
Add support for assignment ch8.4 > var x = 2; > print x = 1; 1