*** empty log message ***
[m17n/m17n-lib-cs.git] / MExpression.cs
index ccc4878..959ea1d 100644 (file)
@@ -11,26 +11,26 @@ namespace M17N.Core
   {
     public delegate object Evaluator (object[] args, MPlist bindings);
 
-    internal delegate void PrettyPrinter (MFunction func,
-                                        string indent, object[] args);
+    internal delegate void PrettyPrinter (Function func,
+                                         string indent, object[] args);
 
-    internal class MFunction
+    internal class Function
     {
-      internal MSymbol name;
+      internal readonly MSymbol name;
       internal readonly Evaluator eval;
-      internal int min_arg;
-      internal int max_arg;
-      internal Type[] arg_types;
+      internal readonly int min_arg;
+      internal readonly int max_arg;
+      internal readonly Type[] arg_types;
       internal object[] data;
 
       public PrettyPrinter pp;
 
       private static PrettyPrinter default_pretty_printer;
       private static PrettyPrinter set_pretty_printer;
-      internal static MFunction literal, varref, block, defun;
+      internal static Function literal, varref, block, defun;
 
-      public MFunction (MSymbol name, Evaluator eval,
-                       int min_arg, int max_arg, params Type[] arg_types)
+      public Function (MSymbol name, Evaluator eval,
+                      int min_arg, int max_arg, params Type[] arg_types)
       {
        this.name = name;
        this.eval = eval;
@@ -43,7 +43,7 @@ namespace M17N.Core
          pp = default_pretty_printer;
       }
 
-      static MFunction ()
+      static Function ()
       {
        default_pretty_printer = new PrettyPrinter (default_pp);
        set_pretty_printer = new PrettyPrinter (set_pp);
@@ -133,7 +133,7 @@ namespace M17N.Core
 
       // Commonly used pretty-printers.
 
-      public static void default_pp (MFunction func,
+      public static void default_pp (Function func,
                                     string indent, object[] args)
       {
        Console.Write ("(" + func.name);
@@ -146,7 +146,7 @@ namespace M17N.Core
        Console.Write (")");
       }
 
-      private static void set_pp (MFunction func, string indent, object[] args)
+      private static void set_pp (Function func, string indent, object[] args)
       {
        Console.Write ("(" + func.name + " " + (MSymbol) args[0] + " ");
        ((MExpression) args[1]).pp (indent);
@@ -424,7 +424,7 @@ namespace M17N.Core
        return result;
       }
 
-      private static void block_pp (MFunction func,
+      private static void block_pp (Function func,
                                    string indent, object[] args)
       {
        bool first = true;
@@ -442,19 +442,27 @@ namespace M17N.Core
        Console.Write (")");
       }
 
+      private static bool check_condition (MExpression e, MPlist bindings)
+      {
+       object result = e.Eval (bindings);
+       return (! (result is int) || (int) result != 0);
+      }
+
       private static object cond (object[] args, MPlist bindings)
       {
        foreach (MExpression[] elist in args)
-         {
-           int i = (int) elist[0].Eval (bindings);
-           if (i != 0)
-             return progn ((object[]) elist, bindings);
-         }
+         if (check_condition (elist[0], bindings))
+           {
+             object result = 0;
+             for (int i = 1; i < elist.Length; i++)
+               result = elist[i].Eval (bindings);
+             return result;
+           }
        return 0;
       }
 
-      private static void cond_pp (MFunction func,
-                                   string indent, object[] args)
+      private static void cond_pp (Function func,
+                                  string indent, object[] args)
       {
        Console.Write ("(cond");
        indent += "  ";
@@ -479,7 +487,7 @@ namespace M17N.Core
       {
        object result = 0;
 
-       if ((int) ((MExpression) args[0]).Eval (bindings) != 0)
+       if (check_condition ((MExpression) args[0], bindings))
          result = ((MExpression) args[1]).Eval (bindings);
        else
          for (int i = 2; i < args.Length; i++)
@@ -487,39 +495,33 @@ namespace M17N.Core
        return result;
       }
 
-      private static void if_pp (MFunction func,
+      private static void if_pp (Function func,
                                 string indent, object[] args)
       {
        Console.Write ("(if ");
        ((MExpression) args[0]).pp (indent + "    ");
        Console.Write ("\n" + indent + "    ");
        ((MExpression) args[1]).pp (indent + "    ");
-       bool first = true;
        indent += "  ";
        for (int i = 2; i < args.Length; i++)
          {
-           if (first)
-             {
-               Console.Write ("\n" + indent);
-               first = false;
-             }
-           else
-             Console.Write (" ");
+           Console.Write ("\n" + indent);
            ((MExpression) args[i]).pp (indent);
          }
+       Console.Write (")");
       }
 
       private static object whileclause (object[] args, MPlist bindings)
       {
        object result = 0;
 
-       while ((int) ((MExpression) args[0]).Eval (bindings) != 0)
+       while (check_condition ((MExpression) args[0], bindings))
          for (int i = 1; i < args.Length; i++)
            result = ((MExpression) args[i]).Eval (bindings);
        return result;
       }
 
-      private static void while_pp (MFunction func,
+      private static void while_pp (Function func,
                                    string indent, object[] args)
       {
        Console.Write ("(while ");
@@ -537,6 +539,7 @@ namespace M17N.Core
              Console.Write (" ");
            ((MExpression) args[i]).pp (indent);
          }
+       Console.Write (")");
       }
 
       private static object define_function (object[] args, MPlist bindings)
@@ -551,14 +554,14 @@ namespace M17N.Core
        for (int i = 3; i < args.Length; i++)
          data[i - 2] = args[i];
 
-       MFunction func = new MFunction (sym, null, nargs, nargs,
-                                       typeof (MExpression));
+       Function func = new Function (sym, null, nargs, nargs,
+                                     typeof (MExpression));
        table.table[sym] = func;
        func.data = data;
        return null;
       }
 
-      private static void defun_pp (MFunction func,
+      private static void defun_pp (Function func,
                                    string indent, object[] args)
       {
        Console.Write ("(defun " + args[1] + " " + args[2]);
@@ -575,13 +578,14 @@ namespace M17N.Core
              Console.Write (" ");
            ((MExpression) args[i]).pp (indent);
          }
+       Console.Write (")");
       }
     }
 
     public class FunctionTable
     {
-      internal Dictionary<MSymbol, MFunction> table
-       = new Dictionary<MSymbol, MFunction> ();
+      internal Dictionary<MSymbol, Function> table
+       = new Dictionary<MSymbol, Function> ();
     }
 
     private static FunctionTable basic_table = new FunctionTable ();
@@ -590,34 +594,34 @@ namespace M17N.Core
                              Evaluator evaluator, int min_arg, int max_arg,
                              params Type[] arg_types)
     {
-      MFunction func = Defun (name, evaluator, min_arg, max_arg, arg_types);
+      Function func = Defun (name, evaluator, min_arg, max_arg, arg_types);
       table.table[func.name] = func;
     }
 
-    private static MFunction Defun (string name, Evaluator evaluator,
-                                   int min_arg, int max_arg,
-                                   params Type[] arg_types)
+    private static Function Defun (string name, Evaluator evaluator,
+                                  int min_arg, int max_arg,
+                                  params Type[] arg_types)
     {
       MSymbol sym = MSymbol.Of (name);
-      MFunction func = new MFunction (sym, evaluator, min_arg, max_arg,
+      Function func = new Function (sym, evaluator, min_arg, max_arg,
                                      arg_types);
       basic_table.table[sym] = func;
       return func;
     }
 
-    private static MFunction Defun (string name, Evaluator evaluator,
+    private static Function Defun (string name, Evaluator evaluator,
                                    int min_arg, int max_arg)
     {
       return Defun (name, evaluator, min_arg, max_arg, typeof (MExpression));
     }
 
-    private static MFunction Find (MSymbol name, FunctionTable table)
+    private static Function Find (MSymbol name, FunctionTable table)
     {
       if (name == MSymbol.integer
          || name == MSymbol.mtext)
-       return MFunction.literal;
+       return Function.literal;
 
-      MFunction func;
+      Function func;
       if ((table == null
           || ! table.table.TryGetValue (name, out func))
          && ! basic_table.table.TryGetValue (name, out func))
@@ -632,10 +636,11 @@ namespace M17N.Core
 
     private void invalid_argument (object o)
     {
-      throw new Exception ("Invalid argument: " + o);
+      throw new Exception (String.Format ("Invalid argument to {0}: {1}",
+                                         function.name, o));
     }
 
-    private MFunction function;
+    private Function function;
     private object[] args;
 
     public MExpression (MSymbol function_name, object[] args,
@@ -645,7 +650,7 @@ namespace M17N.Core
       int nargs = args.Length;
       if (nargs < function.min_arg
          || (function.max_arg >= 0 && nargs > function.max_arg))
-       throw new Exception ("Invalid number of arguments: " + args);
+       throw new Exception (String.Format ("Invalid number of arguments to {0}: {1}", function.name, nargs));
       this.args = (object[]) args.Clone ();
     }
 
@@ -681,7 +686,7 @@ namespace M17N.Core
     // EXPRLIST: PLIST = EXPR ...
     public MExpression (MPlist plist, FunctionTable table)
     {
-      function = MFunction.block;
+      function = Function.block;
       args = expression_list (plist, table);
     }
 
@@ -695,7 +700,9 @@ namespace M17N.Core
       int nargs = arg_list.Count;
       if (nargs < function.min_arg
          || (function.max_arg >= 0 && nargs > function.max_arg))
-       throw new Exception ("Invalid number of arguments: " + nargs);
+       throw new Exception (String.Format
+                            ("Invalid number of arguments to {0}: {1}",
+                             function.name, nargs));
 
       int i = 0;
       Type arg_type = typeof (MExpression);
@@ -750,20 +757,20 @@ namespace M17N.Core
          else
            args[i++] = p.val;
        }
-      if (function == MFunction.defun)
+      if (function == Function.defun)
        function.Call (args, null);
     }
 
     public MExpression (MSymbol sym)
     {
-      function = MFunction.varref;
+      function = Function.varref;
       args = new object[1];
       args[0] = sym;
     }
 
     public MExpression (object obj)
     {
-      function = MFunction.literal;
+      function = Function.literal;
       args = new object[1];
       args[0] = obj;
     }
@@ -775,8 +782,8 @@ namespace M17N.Core
 
     private void pp (string indent)
     {
-      if (function == MFunction.varref
-         || function == MFunction.literal)
+      if (function == Function.varref
+         || function == Function.literal)
        {
          if (args[0] is MText)
            Console.Write ("\"{0}\"", args[0]);