DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / logo / step4_if_fn_do.lg
1 load "../logo/readline.lg
2 load "../logo/reader.lg
3 load "../logo/printer.lg
4 load "../logo/types.lg
5 load "../logo/env.lg
6 load "../logo/core.lg
7
8 to _read :str
9 output read_str :str
10 end
11
12 to eval_ast :ast :env
13 output case (obj_type :ast) [
14 [[symbol] env_get :env :ast]
15 [[list] obj_new "list map [_eval ? :env] obj_val :ast]
16 [[vector] obj_new "vector map [_eval ? :env] obj_val :ast]
17 [[hashmap] obj_new "hashmap map [_eval ? :env] obj_val :ast]
18 [else :ast]
19 ]
20 end
21
22 to _eval :ast :env
23 if (obj_type :ast) <> "list [output eval_ast :ast :env]
24 if emptyp obj_val :ast [output :ast]
25 localmake "a0 nth :ast 0
26 case list obj_type :a0 obj_val :a0 [
27 [[[symbol def!]]
28 localmake "a1 nth :ast 1
29 localmake "a2 nth :ast 2
30 output env_set :env :a1 _eval :a2 :env ]
31
32 [[[symbol let*]]
33 localmake "a1 nth :ast 1
34 localmake "letenv env_new :env [] []
35 localmake "i 0
36 while [:i < _count :a1] [
37 ignore env_set :letenv nth :a1 :i _eval nth :a1 (:i + 1) :letenv
38 make "i (:i + 2)
39 ]
40 output _eval nth :ast 2 :letenv ]
41
42 [[[symbol do]]
43 output last obj_val eval_ast rest :ast :env ]
44
45 [[[symbol if]]
46 localmake "a1 nth :ast 1
47 localmake "cond _eval :a1 :env
48 output case obj_type :cond [
49 [[nil false] ifelse (_count :ast) > 3 [
50 _eval nth :ast 3 :env
51 ] [
52 nil_new
53 ]]
54 [else _eval nth :ast 2 :env]
55 ]]
56
57 [[[symbol fn*]]
58 output fn_new nth :ast 1 :env nth :ast 2 ]
59
60 [else
61 localmake "el eval_ast :ast :env
62 localmake "f nth :el 0
63 case obj_type :f [
64 [[nativefn]
65 output apply obj_val :f butfirst obj_val :el ]
66 [[fn]
67 localmake "funcenv env_new fn_env :f fn_args :f rest :el
68 output _eval fn_body :f :funcenv ]
69 [else
70 (throw "error [Wrong type for apply])]
71 ] ]
72 ]
73 end
74
75 to _print :exp
76 output pr_str :exp "true
77 end
78
79 to re :str
80 output _eval _read :str :repl_env
81 end
82
83 to rep :str
84 output _print re :str
85 end
86
87 to repl
88 localmake "running "true
89 while [:running] [
90 localmake "line readline word "user> :space_char
91 ifelse :line=[] [
92 print "
93 make "running "false
94 ] [
95 if not emptyp :line [
96 catch "error [print rep :line]
97 localmake "exception error
98 if not emptyp :exception [
99 (print "Error: first butfirst :exception)
100 ]
101 ]
102 ]
103 ]
104 end
105
106 make "repl_env env_new [] [] []
107 foreach :core_ns [
108 ignore env_set :repl_env first ? first butfirst ?
109 ]
110 ; core.mal: defined using the language itself
111 ignore re "|(def! not (fn* (a) (if a false true)))|
112 repl
113 bye