1 import types
.{MalList
, _list
, _list_Q
, MalVector
, MalHashMap
,
7 def READ(str
: String
): Any
= {
12 def eval_ast(ast
: Any
, env
: Env
): Any
= {
14 case s
: Symbol
=> env
.get(s
)
15 case v
: MalVector
=> v
.map(EVAL(_
, env
))
16 case l
: MalList
=> l
.map(EVAL(_
, env
))
17 case m
: MalHashMap
=> {
18 m
.map
{case (k
,v
) => (k
, EVAL(v
, env
))}
24 def EVAL(orig_ast
: Any
, orig_env
: Env
): Any
= {
25 var ast
= orig_ast
; var env
= orig_env
;
28 //println("EVAL: " + printer._pr_str(ast,true))
30 return eval_ast(ast
, env
)
33 ast
.asInstanceOf
[MalList
].value
match {
37 case Symbol("def!") :: a1
:: a2
:: Nil
=> {
38 return env
.set(a1
.asInstanceOf
[Symbol
], EVAL(a2
, env
))
40 case Symbol("let*") :: a1
:: a2
:: Nil
=> {
41 val let_env
= new Env(env
)
42 for (g
<- a1
.asInstanceOf
[MalList
].value
.grouped(2)) {
43 let_env
.set(g(0).asInstanceOf
[Symbol
],EVAL(g(1),let_env
))
46 ast
= a2
// continue loop (TCO)
48 case Symbol("do") :: rest
=> {
49 eval_ast(_list(rest
.slice(0,rest
.length
-1):_
*), env
)
50 ast
= ast
.asInstanceOf
[MalList
].value
.last
// continue loop (TCO)
52 case Symbol("if") :: a1
:: a2
:: rest
=> {
53 val cond
= EVAL(a1
, env
)
54 if (cond
== null || cond
== false) {
55 if (rest
.length
== 0) return null
56 ast
= rest(0) // continue loop (TCO)
58 ast
= a2
// continue loop (TCO)
61 case Symbol("fn*") :: a1
:: a2
:: Nil
=> {
62 return new MalFunction(a2
, env
, a1
.asInstanceOf
[MalList
],
63 (args
: List
[Any
]) => {
64 EVAL(a2
, new Env(env
, types
._toIter(a1
), args
.iterator
))
70 eval_ast(ast
, env
).asInstanceOf
[MalList
].value
match {
73 case fn
: MalFunction
=> {
75 ast
= fn
.ast
// continue loop (TCO)
81 throw new Exception("attempt to call non-function: " + f
)
85 case _
=> throw new Exception("invalid apply")
93 def PRINT(exp
: Any
): String
= {
94 printer
._pr_str(exp
, true)
98 def main(args
: Array
[String
]) = {
99 val repl_env
: Env
= new Env()
100 val REP
= (str
: String
) => PRINT(EVAL(READ(str
), repl_env
))
102 // core.scala: defined using scala
103 core
.ns
.map
{case (k
: String
,v
: Any
) => {
104 repl_env
.set(Symbol(k
), new Func(v
))
106 repl_env
.set(Symbol("eval"), new Func((a
: List
[Any
]) => EVAL(a(0), repl_env
)))
107 repl_env
.set(Symbol("*ARGV*"), _list(args
.slice(1,args
.length
):_
*))
109 // core.mal: defined using the language itself
110 REP("(def! not (fn* (a) (if a false true)))")
111 REP("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))")
113 if (args
.length
> 0) {
114 REP("(load-file \"" + args(0) + "\")")
119 var line
:String
= null
120 while ({line
= readLine("user> "); line
!= null}) {
124 case e
: Throwable
=> {
125 println("Error: " + e
.getMessage
)
126 println(" " + e
.getStackTrace
.mkString("\n "))