Merge pull request #174 from dubek/issue_166_schemes
[jackhill/mal.git] / racket / step4_if_fn_do.rkt
CommitLineData
f5223195
JM
1#!/usr/bin/env racket
2#lang racket
3
4(require "readline.rkt" "types.rkt" "reader.rkt" "printer.rkt"
5 "env.rkt" "core.rkt")
6
7;; read
8(define (READ str)
9 (read_str str))
10
11;; eval
12(define (eval-ast ast env)
13 (cond
14 [(symbol? ast) (send env get ast)]
15 [(_sequential? ast) (_map (lambda (x) (EVAL x env)) ast)]
16 [(hash? ast) (make-hash
17 (dict-map ast (lambda (k v) (cons k (EVAL v env)))))]
18 [else ast]))
19
20(define (EVAL ast env)
21 (if (not (list? ast))
22 (eval-ast ast env)
23
24 (let ([a0 (_nth ast 0)])
25 (cond
26 [(eq? 'def! a0)
27 (send env set (_nth ast 1) (EVAL (_nth ast 2) env))]
28 [(eq? 'let* a0)
29 (let ([let-env (new Env% [outer env] [binds null] [exprs null])])
30 (_map (lambda (b_e)
31 (send let-env set (_first b_e)
32 (EVAL (_nth b_e 1) let-env)))
33 (_partition 2 (_to_list (_nth ast 1))))
34 (EVAL (_nth ast 2) let-env))]
35 [(eq? 'do a0)
36 (last (eval-ast (rest ast) env))]
37 [(eq? 'if a0)
38 (let ([cnd (EVAL (_nth ast 1) env)])
39 (if (or (eq? cnd nil) (eq? cnd #f))
40 (if (> (length ast) 3)
41 (EVAL (_nth ast 3) env)
42 nil)
43 (EVAL (_nth ast 2) env)))]
44 [(eq? 'fn* a0)
45 (lambda args (EVAL (_nth ast 2)
46 (new Env% [outer env]
47 [binds (_nth ast 1)]
48 [exprs args])))]
49 [else (let* ([el (eval-ast ast env)]
50 [f (first el)]
51 [args (rest el)])
52 (apply f args))]))))
53
54;; print
55(define (PRINT exp)
56 (pr_str exp true))
57
58;; repl
59(define repl-env
60 (new Env% [outer null] [binds null] [exprs null]))
61(define (rep str)
62 (PRINT (EVAL (READ str) repl-env)))
63
64(for () ;; ignore return values
65
66;; core.rkt: defined using Racket
67(hash-for-each core_ns (lambda (k v) (send repl-env set k v)))
68
69;; core.mal: defined using the language itself
70(rep "(def! not (fn* (a) (if a false true)))")
71
72)
73
74(define (repl-loop)
75 (let ([line (readline "user> ")])
76 (when (not (eq? nil line))
77 (with-handlers
78 ([string? (lambda (exc) (printf "Error: ~a~n" exc))]
79 [blank-exn? (lambda (exc) null)])
80 (printf "~a~n" (rep line)))
81 (repl-loop))))
82(repl-loop)