switch to tail -f circular pipes
[jackhill/mal.git] / d / step8_macros.d
index e1a7243..01e9432 100644 (file)
@@ -5,7 +5,7 @@ import std.array;
 import std.range;
 import std.stdio;
 import std.string;
-import std.c.process;
+import core.stdc.stdlib;
 import env;
 import mal_core;
 import readline;
@@ -80,26 +80,22 @@ MalType READ(string str)
 
 MalType eval_ast(MalType ast, Env env)
 {
-    if (typeid(ast) == typeid(MalSymbol))
+    if (auto sym = cast(MalSymbol)ast)
     {
-        auto sym = verify_cast!MalSymbol(ast);
         return env.get(sym);
     }
-    else if (typeid(ast) == typeid(MalList))
+    else if (auto lst = cast(MalList)ast)
     {
-        auto lst = verify_cast!MalList(ast);
         auto el = array(lst.elements.map!(e => EVAL(e, env)));
         return new MalList(el);
     }
-    else if (typeid(ast) == typeid(MalVector))
+    else if (auto lst = cast(MalVector)ast)
     {
-        auto lst = verify_cast!MalVector(ast);
         auto el = array(lst.elements.map!(e => EVAL(e, env)));
         return new MalVector(el);
     }
-    else if (typeid(ast) == typeid(MalHashmap))
+    else if (auto hm = cast(MalHashmap)ast)
     {
-        auto hm = verify_cast!MalHashmap(ast);
         typeof(hm.data) new_data;
         foreach (string k, MalType v; hm.data)
         {
@@ -131,6 +127,10 @@ MalType EVAL(MalType ast, Env env)
         }
 
         auto aste = ast_list.elements;
+        if (aste.length == 0)
+        {
+            return ast;
+        }
         auto a0_sym = cast(MalSymbol) aste[0];
         auto sym_name = a0_sym is null ? "" : a0_sym.name;
         switch (sym_name)
@@ -204,17 +204,15 @@ MalType EVAL(MalType ast, Env env)
                 }
                 auto first = el.elements[0];
                 auto rest = el.elements[1..$];
-                if (typeid(first) == typeid(MalFunc))
+                if (auto funcobj = cast(MalFunc)first)
                 {
-                    auto funcobj = verify_cast!MalFunc(first);
                     auto callenv = new Env(funcobj.def_env, funcobj.arg_names, rest);
                     ast = funcobj.func_body;
                     env = callenv;
                     continue; // TCO
                 }
-                else if (typeid(first) == typeid(MalBuiltinFunc))
+                else if (auto builtinfuncobj = cast(MalBuiltinFunc)first)
                 {
-                    auto builtinfuncobj = verify_cast!MalBuiltinFunc(first);
                     return builtinfuncobj.fn(rest);
                 }
                 else
@@ -263,9 +261,8 @@ void main(string[] args)
 
     // core.mal: defined using the language itself
     re("(def! not (fn* (a) (if a false true)))", repl_env);
-    re("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))", repl_env);
+    re("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))", repl_env);
     re("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))", repl_env);
-    re("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))", repl_env);
 
     if (args.length > 1)
     {
@@ -277,7 +274,7 @@ void main(string[] args)
         catch (Exception e)
         {
             writeln("Error: ", e.msg);
-            std.c.process.exit(1);
+            exit(1);
         }
     }