1 source mal_readline.tcl
13 expr {[sequential_q
$ast] && [llength [obj_val
$ast]] > 0}
16 proc quasiquote
{ast
} {
17 if {![is_pair
$ast]} {
18 return [list_new
[list [symbol_new
"quote"] $ast]]
20 lassign
[obj_val
$ast] a0 a1
21 if {[symbol_q
$a0] && [obj_val
$a0] == "unquote"} {
24 lassign
[obj_val
$a0] a00 a01
25 set rest
[list_new
[lrange [obj_val
$ast] 1 end
]]
26 if {[is_pair
$a0] && [symbol_q
$a00] && [obj_val
$a00] == "splice-unquote"} {
27 return [list_new
[list [symbol_new
"concat"] $a01 [quasiquote
$rest]]]
29 return [list_new
[list [symbol_new
"cons"] [quasiquote
$a0] [quasiquote
$rest]]]
33 proc eval_ast
{ast env
} {
34 switch [obj_type
$ast] {
36 set varname
[obj_val
$ast]
37 return [$env get
$varname]
41 foreach element
[obj_val
$ast] {
42 lappend res
[EVAL
$element $env]
44 return [list_new
$res]
48 foreach element
[obj_val
$ast] {
49 lappend res
[EVAL
$element $env]
51 return [vector_new
$res]
55 dict
for {k v
} [obj_val
$ast] {
56 dict
set res
$k [EVAL
$v $env]
58 return [hashmap_new
$res]
60 default { return $ast }
67 return [eval_ast
$ast $env]
69 lassign
[obj_val
$ast] a0 a1 a2 a3
70 switch [obj_val
$a0] {
72 set varname
[obj_val
$a1]
73 set value
[EVAL
$a2 $env]
74 return [$env set $varname $value]
77 set letenv
[Env new
$env]
78 set bindings_list
[obj_val
$a1]
79 foreach {varnameobj varvalobj
} $bindings_list {
80 $letenv set [obj_val
$varnameobj] [EVAL
$varvalobj $letenv]
90 set ast
[quasiquote
$a1]
93 set el
[list_new
[lrange [obj_val
$ast] 1 end-1
]]
95 set ast
[lindex [obj_val
$ast] end
]
99 set condval
[EVAL
$a1 $env]
100 if {[false_q
$condval] ||
[nil_q
$condval]} {
112 foreach v
[obj_val
$a1] {
113 lappend binds
[obj_val
$v]
115 return [function_new
$a2 $env $binds]
118 set lst_obj
[eval_ast
$ast $env]
119 set lst
[obj_val
$lst_obj]
120 set f
[lindex $lst 0]
121 set call_args
[lrange $lst 1 end
]
122 switch [obj_type
$f] {
125 set ast
[dict get
$fn body
]
126 set env
[Env new
[dict get
$fn env
] [dict get
$fn binds
] $call_args]
130 set body
[concat [list [obj_val
$f]] {$a}]
131 set lambda
[list {a
} $body]
132 return [apply
$lambda $call_args]
135 error "Not a function"
148 PRINT
[EVAL
[READ
$str] $env]
152 EVAL
[READ
$str] $env
157 EVAL
[lindex $a 0] $repl_env
160 set repl_env
[Env new
]
161 dict
for {k v
} $core_ns {
165 $repl_env set "eval" [nativefunction_new mal_eval
]
168 foreach arg
[lrange $argv 1 end
] {
169 lappend argv_list
[string_new
$arg]
171 $repl_env set "*ARGV*" [list_new
$argv_list]
173 # core.mal: defined using the language itself
174 RE
"(def! not (fn* (a) (if a false true)))" $repl_env
175 RE
"(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))" $repl_env
177 fconfigure stdout
-translation binary
180 if { [array names env DEBUG
] != "" && $env(DEBUG
) != "0" } {
185 REP
"(load-file \"[lindex $argv 0]\")" $repl_env
191 set res
[_readline
"user> "]
192 if {[lindex $res 0] == "EOF"} {
195 set line
[lindex $res 1]
199 if { [catch { puts [REP
$line $repl_env] } exception
] } {
200 puts "Error: $exception"