Merge pull request #358 from bjh21/bjh21-extra-tests
[jackhill/mal.git] / scala / step2_eval.scala
1 import types.{MalList, _list_Q, MalVector, MalHashMap, MalFunction}
2
3 object step2_eval {
4 // read
5 def READ(str: String): Any = {
6 reader.read_str(str)
7 }
8
9 // eval
10 def eval_ast(ast: Any, env: Map[Symbol,Any]): Any = {
11 ast match {
12 case s : Symbol => env(s)
13 case v: MalVector => v.map(EVAL(_, env))
14 case l: MalList => l.map(EVAL(_, env))
15 case m: MalHashMap => {
16 m.map{case (k,v) => (k, EVAL(v, env))}
17 }
18 case _ => ast
19 }
20 }
21
22 def EVAL(ast: Any, env: Map[Symbol,Any]): Any = {
23 //println("EVAL: " + printer._pr_str(ast,true))
24 if (!_list_Q(ast))
25 return eval_ast(ast, env)
26
27 // apply list
28 if (ast.asInstanceOf[MalList].value.length == 0)
29 return ast
30 eval_ast(ast, env).asInstanceOf[MalList].value match {
31 case f :: el => {
32 var fn: List[Any] => Any = null
33 try {
34 fn = f.asInstanceOf[List[Any] => Any]
35 } catch {
36 case _: Throwable =>
37 throw new Exception("attempt to call non-function")
38 }
39 return fn(el)
40 }
41 case _ => throw new Exception("invalid apply")
42 }
43 }
44
45 // print
46 def PRINT(exp: Any): String = {
47 printer._pr_str(exp, true)
48 }
49
50 // repl
51 def main(args: Array[String]) = {
52 val repl_env: Map[Symbol,Any] = Map(
53 '+ -> ((a: List[Any]) => a(0).asInstanceOf[Long] + a(1).asInstanceOf[Long]),
54 '- -> ((a: List[Any]) => a(0).asInstanceOf[Long] - a(1).asInstanceOf[Long]),
55 '* -> ((a: List[Any]) => a(0).asInstanceOf[Long] * a(1).asInstanceOf[Long]),
56 '/ -> ((a: List[Any]) => a(0).asInstanceOf[Long] / a(1).asInstanceOf[Long]))
57 val REP = (str: String) => {
58 PRINT(EVAL(READ(str), repl_env))
59 }
60
61 var line:String = null
62 while ({line = readLine("user> "); line != null}) {
63 try {
64 println(REP(line))
65 } catch {
66 case e : Exception => {
67 println("Error: " + e.getMessage)
68 println(" " + e.getStackTrace.mkString("\n "))
69 }
70 }
71 }
72 }
73 }
74
75 // vim: ts=2:sw=2