Racket: add steps0-A. Self-hosting.
[jackhill/mal.git] / racket / step2_eval.rkt
1 #!/usr/bin/env racket
2 #lang racket
3
4 (require "types.rkt" "readline.rkt" "reader.rkt" "printer.rkt")
5
6 ;; read
7 (define (READ str)
8 (read_str str))
9
10 ;; eval
11 (define (eval-ast ast env)
12 (cond
13 [(symbol? ast)
14 (or (hash-ref env ast
15 (lambda () (raise (string-append "'"
16 (symbol->string ast)
17 "' not found")))))]
18 [(_sequential? ast) (_map (lambda (x) (EVAL x env)) ast)]
19 [(hash? ast) (make-hash
20 (dict-map ast (lambda (k v) (cons k (EVAL v env)))))]
21 [else ast]))
22
23 (define (EVAL ast env)
24 (if (not (list? ast))
25 (eval-ast ast env)
26
27 (let* ([el (eval-ast ast env)]
28 [f (first el)]
29 [args (rest el)])
30 (apply f args))))
31
32 ;; print
33 (define (PRINT exp)
34 (pr_str exp true))
35
36 ;; repl
37 (define repl-env (hash '+ + '- - '* * '/ /))
38 (define (rep str)
39 (PRINT (EVAL (READ str) repl-env)))
40
41 (define (repl-loop)
42 (let ([line (readline "user> ")])
43 (when (not (eq? nil line))
44 (with-handlers
45 ([string? (lambda (exc) (printf "Error: ~a~n" exc))]
46 [blank-exn? (lambda (exc) null)])
47 (printf "~a~n" (rep line)))
48 (repl-loop))))
49 (repl-loop)