8 Reading code
So far, all test programs have been fed pre-parsed code in a list. To read code (or data, it’s all the same) from a file, we can use port-read-value (see More builtins). However, the interpreter doesn’t know how to do that, so we need a way of using it when the program expects to read more code.
So here it is. This read-eval loop checks quote-read-syntax? to read code from source-input-port, and basically reimplements the core interpreter loop. If you wanted, you could redefine source-input-port to read from a different file or syntax-read to change the character-level syntax.
«read-eval-loop» ::=
; Add definitions to support a read-eval-loop from the given input port. (: read-eval-loop-definitions (-> (Immutable-HashTable Symbol Function) Input-Port (Immutable-HashTable Symbol Function))) (define (read-eval-loop-definitions builtins source-input-port) (hash-set* builtins 'source-input-port `(,source-input-port) 'syntax-read '(; read a value from the current source file source-input-port port-read-value swap drop) 'quote-read-syntax? '(; This could be consolidated builtin-quote current-context-root? uplevel) ; Override quote to read from the source input file ; at the toplevel 'builtin-quote (hash-ref (*builtins*) 'quote) 'quote '(builtin-quote builtin-quote builtin-quote syntax-read builtin-quote quote-read-syntax? uplevel builtin-quote swap when drop uplevel) 'read-eval-loop '(; Read next value quote quote uplevel ; Leave <eof> here (this is a little wonky) eof-object? quote current-context-clear when ; Eval symbols; leave everything else on stack symbol? ; Stack dance to get everything in place quote call swap quote drop swap quote uplevel swap ; 'eval 'drop 'uplevel #t 'swap when drop ; => 'eval 'uplevel ; 'eval 'drop 'uplevel #f 'swap when drop ; => 'eval 'drop quote swap when drop call ; Loop (reusing the current stack frame) quote read-eval-loop definition-resolve swap drop current-context-set-code)))