1 source mal_readline.tcl
12 proc eval_ast
{ast env
} {
13 switch [obj_type
$ast] {
15 set varname
[obj_val
$ast]
16 return [$env get
$varname]
20 foreach element
[obj_val
$ast] {
21 lappend res
[EVAL
$element $env]
23 return [list_new
$res]
27 foreach element
[obj_val
$ast] {
28 lappend res
[EVAL
$element $env]
30 return [vector_new
$res]
34 dict
for {k v
} [obj_val
$ast] {
35 dict
set res
$k [EVAL
$v $env]
37 return [hashmap_new
$res]
39 default { return $ast }
45 return [eval_ast
$ast $env]
47 lassign
[obj_val
$ast] a0 a1 a2 a3
51 switch [obj_val
$a0] {
53 set varname
[obj_val
$a1]
54 set value
[EVAL
$a2 $env]
55 return [$env set $varname $value]
58 set letenv
[Env new
$env]
59 set bindings_list
[obj_val
$a1]
60 foreach {varnameobj varvalobj
} $bindings_list {
61 $letenv set [obj_val
$varnameobj] [EVAL
$varvalobj $letenv]
63 return [EVAL
$a2 $letenv]
66 set el
[list_new
[lrange [obj_val
$ast] 1 end-1
]]
68 return [EVAL
[lindex [obj_val
$ast] end
] $env]
71 set condval
[EVAL
$a1 $env]
72 if {[false_q
$condval] ||
[nil_q
$condval]} {
76 return [EVAL
$a3 $env]
78 return [EVAL
$a2 $env]
82 foreach v
[obj_val
$a1] {
83 lappend binds
[obj_val
$v]
85 return [function_new
$a2 $env $binds]
88 set lst_obj
[eval_ast
$ast $env]
89 set lst
[obj_val
$lst_obj]
91 set call_args
[lrange $lst 1 end
]
92 switch [obj_type
$f] {
94 set funcdict
[obj_val
$f]
95 set body
[dict get
$funcdict body
]
96 set env
[dict get
$funcdict env
]
97 set binds
[dict get
$funcdict binds
]
98 set funcenv
[Env new
$env $binds $call_args]
99 return [EVAL
$body $funcenv]
102 set body
[concat [list [obj_val
$f]] {$a}]
103 set lambda
[list {a
} $body]
104 return [apply
$lambda $call_args]
107 error "Not a function"
119 PRINT
[EVAL
[READ
$str] $env]
123 EVAL
[READ
$str] $env
126 set repl_env
[Env new
]
127 dict
for {k v
} $core_ns {
131 # core.mal: defined using the language itself
132 RE
"(def! not (fn* (a) (if a false true)))" $repl_env
134 fconfigure stdout
-translation binary
137 if { [array names env DEBUG
] != "" && $env(DEBUG
) != "0" } {
143 set res
[_readline
"user> "]
144 if {[lindex $res 0] == "EOF"} {
147 set line
[lindex $res 1]
151 if { [catch { puts [REP
$line $repl_env] } exception
] } {
152 puts "Error: $exception"