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