Commit | Line | Data |
---|---|---|
3e60110d JM |
1 | #!/usr/bin/env julia |
2 | ||
82484631 | 3 | push!(LOAD_PATH, pwd(), "/usr/share/julia/base") |
85110962 | 4 | import readline_mod |
3e60110d JM |
5 | import reader |
6 | import printer | |
7 | using env | |
8 | import core | |
9 | ||
10 | # READ | |
11 | function READ(str) | |
12 | reader.read_str(str) | |
13 | end | |
14 | ||
15 | # EVAL | |
16 | function eval_ast(ast, env) | |
17 | if typeof(ast) == Symbol | |
82484631 | 18 | env_get(env,ast) |
3e60110d JM |
19 | elseif isa(ast, Array) || isa(ast, Tuple) |
20 | map((x) -> EVAL(x,env), ast) | |
7e0bb668 JM |
21 | elseif isa(ast, Dict) |
22 | [EVAL(x[1],env) => EVAL(x[2], env) for x=ast] | |
3e60110d JM |
23 | else |
24 | ast | |
25 | end | |
26 | end | |
27 | ||
28 | function EVAL(ast, env) | |
7e0bb668 | 29 | if !isa(ast, Array) return eval_ast(ast, env) end |
3e60110d JM |
30 | |
31 | # apply | |
32 | if :def! == ast[1] | |
82484631 | 33 | env_set(env, ast[2], EVAL(ast[3], env)) |
3e60110d | 34 | elseif symbol("let*") == ast[1] |
7e0bb668 | 35 | let_env = Env(env) |
3e60110d | 36 | for i = 1:2:length(ast[2]) |
82484631 | 37 | env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) |
3e60110d JM |
38 | end |
39 | EVAL(ast[3], let_env) | |
40 | elseif :do == ast[1] | |
41 | eval_ast(ast[2:end], env)[end] | |
42 | elseif :if == ast[1] | |
43 | cond = EVAL(ast[2], env) | |
44 | if cond === nothing || cond === false | |
45 | if length(ast) >= 4 | |
46 | EVAL(ast[4], env) | |
47 | else | |
48 | nothing | |
49 | end | |
50 | else | |
51 | EVAL(ast[3], env) | |
52 | end | |
53 | elseif symbol("fn*") == ast[1] | |
f98e3ea9 | 54 | (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])) |
3e60110d JM |
55 | else |
56 | el = eval_ast(ast, env) | |
57 | f, args = el[1], el[2:end] | |
58 | f(args...) | |
59 | end | |
60 | end | |
61 | ||
62 | ||
63 | function PRINT(exp) | |
64 | printer.pr_str(exp) | |
65 | end | |
66 | ||
67 | # REPL | |
68 | repl_env = nothing | |
69 | function REP(str) | |
70 | return PRINT(EVAL(READ(str), repl_env)) | |
71 | end | |
72 | ||
73 | # core.jl: defined using Julia | |
74 | repl_env = Env(nothing, core.ns) | |
75 | ||
76 | # core.mal: defined using the language itself | |
77 | REP("(def! not (fn* (a) (if a false true)))") | |
78 | ||
79 | while true | |
85110962 JM |
80 | line = readline_mod.do_readline("user> ") |
81 | if line === nothing break end | |
3e60110d JM |
82 | try |
83 | println(REP(line)) | |
84 | catch e | |
85 | if isa(e, ErrorException) | |
86 | println("Error: $(e.msg)") | |
87 | else | |
88 | println("Error: $(string(e))") | |
89 | end | |
82484631 JM |
90 | if !isa(e, StackOverflowError) |
91 | bt = catch_backtrace() | |
92 | Base.show_backtrace(STDERR, bt) | |
93 | end | |
3e60110d JM |
94 | println() |
95 | end | |
96 | end |