aboutsummaryrefslogtreecommitdiff
path: root/racket/step2_eval.rkt
blob: ce4d563368ecea045425cc7141e2e6558d37903e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env racket
#lang racket

(require "types.rkt" "readline.rkt" "reader.rkt" "printer.rkt")

;; read
(define (READ str)
  (read_str str))

;; eval
(define (eval-ast ast env)
  (cond
    [(symbol? ast)
     (or (hash-ref env ast
                   (lambda () (raise (string-append "'"
                                                    (symbol->string ast)
                                                    "' not found")))))]
    [(_sequential? ast) (_map (lambda (x) (EVAL x env)) ast)]
    [(hash? ast) (make-hash
                  (dict-map ast (lambda (k v) (cons k (EVAL v env)))))]
    [else ast]))

(define (EVAL ast env)
  (if (not (list? ast))
        (eval-ast ast env)

        (let* ([el (eval-ast ast env)]
               [f (first el)]
               [args (rest el)])
          (apply f args))))

;; print
(define (PRINT exp)
  (pr_str exp true))

;; repl
(define repl-env (hash '+ + '- - '* * '/ /))
(define (rep str)
  (PRINT (EVAL (READ str) repl-env)))

(define (repl-loop)
  (let ([line (readline "user> ")])
    (when (not (eq? nil line))
      (with-handlers
        ([string? (lambda (exc) (printf "Error: ~a~n" exc))]
         [blank-exn? (lambda (exc) null)])
        (printf "~a~n" (rep line)))
      (repl-loop))))
(repl-loop)