Update Crystal implementation
[jackhill/mal.git] / crystal / step2_eval.cr
index f93b957..eeef93c 100755 (executable)
@@ -1,6 +1,6 @@
 #! /usr/bin/env crystal run
 
-require "./readline"
+require "readline"
 require "./reader"
 require "./printer"
 require "./types"
@@ -16,7 +16,7 @@ module Mal
   end
 
   def num_func(func)
-    -> (args : Array(Mal::Type)) {
+    ->(args : Array(Mal::Type)) {
       x, y = args[0].unwrap, args[1].unwrap
       eval_error "invalid arguments" unless x.is_a?(Int64) && y.is_a?(Int64)
       Mal::Type.new func.call(x, y)
@@ -24,7 +24,7 @@ module Mal
   end
 
   def eval_ast(a, env)
-    return a.map{|n| eval(n, env) as Mal::Type} if a.is_a? Mal::List
+    return a.map { |n| eval(n, env).as(Mal::Type) } if a.is_a? Mal::List
     return a unless a
 
     ast = a.unwrap
@@ -36,11 +36,12 @@ module Mal
         eval_error "'#{ast.str}' not found"
       end
     when Mal::List
-      ast.each_with_object(Mal::List.new){|n, l| l << eval(n, env)}
+      ast.each_with_object(Mal::List.new) { |n, l| l << eval(n, env) }
     when Mal::Vector
-      ast.each_with_object(Mal::Vector.new){|n, l| l << eval(n, env)}
+      ast.each_with_object(Mal::Vector.new) { |n, l| l << eval(n, env) }
     when Mal::HashMap
-      ast.each{|k, v| ast[k] = eval(v, env)}
+      ast.each { |k, v| ast[k] = eval(v, env) }
+      ast
     else
       ast
     end
@@ -74,18 +75,18 @@ module Mal
   end
 
   def rep(str)
-    print(eval(read(str), $repl_env))
+    print(eval(read(str), REPL_ENV))
   end
 end
 
-$repl_env = {
-  "+" => Mal.num_func(->(x : Int64, y : Int64){ x + y }),
-  "-" => Mal.num_func(->(x : Int64, y : Int64){ x - y }),
-  "*" => Mal.num_func(->(x : Int64, y : Int64){ x * y }),
-  "/" => Mal.num_func(->(x : Int64, y : Int64){ x / y }),
+REPL_ENV = {
+  "+" => Mal.num_func(->(x : Int64, y : Int64) { x + y }),
+  "-" => Mal.num_func(->(x : Int64, y : Int64) { x - y }),
+  "*" => Mal.num_func(->(x : Int64, y : Int64) { x * y }),
+  "/" => Mal.num_func(->(x : Int64, y : Int64) { x / y }),
 } of String => Mal::Func
 
-while line = my_readline("user> ")
+while line = Readline.readline("user> ", true)
   begin
     puts Mal.rep(line)
   rescue e