*** empty log message ***
authorhanda <handa>
Thu, 23 Jul 2009 12:42:35 +0000 (12:42 +0000)
committerhanda <handa>
Thu, 23 Jul 2009 12:42:35 +0000 (12:42 +0000)
MExpression.cs
MText.cs
eval.txt
expr.cs

index 1affae0..7da715e 100644 (file)
@@ -7,176 +7,715 @@ using M17N.Core;
 
 namespace M17N.Core
 {
-  public delegate object MEvaluator (object arg, MPlist bindings);
-
-  public class MFunction
+  public class MExpression
   {
-    MSymbol name;
-    internal readonly MEvaluator evaluator;
+    public delegate object Evaluator (object[] args, MPlist bindings);
 
-    public static Dictionary<MSymbol, MFunction> CommonTable
-      = new Dictionary<MSymbol, MFunction> ();
-    public static readonly MFunction Identity
-    = new MFunction (MSymbol.nil, null);
+    internal delegate void PretyPrinter (MFunction func,
+                                        string indent, object[] args);
 
-    static MFunction ()
+    internal class MFunction
     {
-      new MFunction (MSymbol.Of ("+"), new MEvaluator (plus));
-      new MFunction (MSymbol.Of ("*"), new MEvaluator (multi));
-      new MFunction (MSymbol.Of ("-"), new MEvaluator (minus));
-    }
+      internal MSymbol name;
+      internal readonly Evaluator eval;
+      internal int min_arg;
+      internal int max_arg;
+      internal Type[] arg_types;
 
-    internal MFunction (MSymbol name, MEvaluator evaluator)
-    {
-      this.name = name;
-      this.evaluator = evaluator;
-      CommonTable[name] = this;
-    }
+      public PretyPrinter pp;
 
-    public MFunction (MSymbol name, MEvaluator evaluator,
-                     Dictionary<MSymbol, MFunction> dict)
-    {
-      this.evaluator = evaluator;
-      dict[name] = this;
-    }
+      private static PretyPrinter default_prety_printer;
+      private static PretyPrinter set_prety_printer;
+      internal static MFunction literal, varref, block;
 
-    internal static MFunction Find (MSymbol name,
-                                 Dictionary<MSymbol, MFunction> Table)
-    {
-      if (name == MSymbol.integer
-         || name == MSymbol.plist
-         || name == MSymbol.mtext
-         || name == MSymbol.symbol)
-       return Identity;
+      public MFunction (MSymbol name, Evaluator eval,
+                       int min_arg, int max_arg, Type[] arg_types)
+      {
+       this.name = name;
+       this.eval = eval;
+       this.min_arg = min_arg;
+       this.max_arg = max_arg;
+       this.arg_types = (Type []) arg_types.Clone ();
+       if (arg_types.Length == 2 && arg_types[0] == typeof (MSymbol))
+         pp = set_prety_printer;
+       else
+         pp = default_prety_printer;
+      }
 
-      MFunction func;
-      if ((Table == null
-          || ! Table.TryGetValue (name, out func))
-         && ! MFunction.CommonTable.TryGetValue (name, out func))
-       throw new Exception ("Unknown function: " + name);
-      return func;
-    }
+      static MFunction ()
+      {
+       default_prety_printer = new PretyPrinter (default_pp);
+       set_prety_printer = new PretyPrinter (set_pp);
+       literal = Defun ("nil", null, 1, 1);
+       varref = Defun ("symbol", new Evaluator (get_value), 1, 1);
+       block = Defun ("plist", new Evaluator (progn), 1, -1);
 
-    public object Call (object arg, MPlist bindings)
-    {
-      if (name == MSymbol.nil)
-       return arg;
-      return evaluator (arg, bindings);
-    }
+       Defun ("set", new Evaluator (set_value), 2, 2,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("=", new Evaluator (set_value), 2, 2,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("+", new Evaluator (plus), 1, -1);
+       Defun ("*", new Evaluator (multi), 2, -1);
+       Defun ("-", new Evaluator (minus), 1, -1);
+       Defun ("/", new Evaluator (divide), 2, -1);
+       Defun ("%", new Evaluator (percent), 2, -1);
+       Defun ("|", new Evaluator (logior), 2, -1);
+       Defun ("&", new Evaluator (logand), 2, -1);
+       Defun ("+=", new Evaluator (pluseq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("*=", new Evaluator (multieq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("-=", new Evaluator (minuseq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("/=", new Evaluator (divideeq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("%=", new Evaluator (percenteq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("|=", new Evaluator (logioreq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("&=", new Evaluator (logandeq), 2, -1,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("<<", new Evaluator (lshift), 2, 2);
+       Defun (">>", new Evaluator (rshift), 2, 2);
+       Defun ("<<=", new Evaluator (lshifteq), 2, 2,
+              typeof (MSymbol), typeof (MExpression));
+       Defun (">>=", new Evaluator (rshifteq), 2, 2,
+              typeof (MSymbol), typeof (MExpression));
+       Defun ("==", new Evaluator (eq), 2, -1);
+       Defun ("!=", new Evaluator (noteq), 2, 2);
+       Defun ("<", new Evaluator (less), 2, -1);
+       Defun ("<=", new Evaluator (lesseq), 2, -1);
+       Defun (">", new Evaluator (more), 2, -1);
+       Defun (">=", new Evaluator (moreeq), 2, -1);
+       block = Defun ("progn", new Evaluator (progn), 1, -1);
+       block.pp = new PretyPrinter (block_pp);
+       Defun ("cond", new Evaluator (cond), 1, -1,
+              typeof (MExpression[])).pp = new PretyPrinter (cond_pp);
+       Defun ("if", new Evaluator (ifclause), 2, -1,
+              typeof (MExpression)).pp = new PretyPrinter (if_pp);
+       Defun ("while", new Evaluator (whileclause), 1, -1,
+              typeof (MExpression)).pp = new PretyPrinter (while_pp);
+      }
 
-    private static object plus (object arg, MPlist bindings)
-    {
-      MExpression expr = (MExpression) arg;
+      public object Call (object[] args, MPlist bindings)
+      {
+       if (name == MSymbol.nil)
+         return args[0];
+       return eval (args, bindings);
+      }
 
-      int n = 0;
-      foreach (MExpression e in expr)
-       n += (int) e.Eval (bindings);
-      return n;
-    }
+      private static MPlist find_binding (object[] args, MPlist bindings)
+      {
+       MSymbol var = (MSymbol) args[0];
+       MPlist slot = bindings.Find (var);
 
-    private static object multi (object arg, MPlist bindings)
-    {
-      MExpression expr = (MExpression) arg;
+       if (slot == null)
+         throw new Exception ("Unbound variable: " + var);
+       return slot;
+      }
 
-      int n = 1;
-      foreach (MExpression e in expr)
-       n *= (int) e.Eval (bindings);
-      return n;
-    }
+      public static void default_pp (MFunction func,
+                                    string indent, object[] args)
+      {
+       Console.Write ("(" + func.name);
+       indent += "  ";
+       foreach (MExpression o in args)
+         {
+           Console.Write (" ");
+           o.pp (indent);
+         }
+       Console.Write (")");
+      }
+
+      private static object get_value (object[] args, MPlist bindings)
+      {
+       return find_binding (args, bindings).val;
+      }
+
+      private static object set_value (object[] args, MPlist bindings)
+      {
+       MSymbol var = (MSymbol) args[0];
+       MPlist slot = bindings.Find (var);
 
-    private static object minus (object arg, MPlist bindings)
+       if (slot == null)
+         slot = bindings.Push (var, null);
+       slot.val = ((MExpression) args[1]).Eval (bindings);
+       if (slot.val is MText)
+         slot.val = ((MText) slot.val).Dup ();
+       return slot.val;
+      }
+
+      private static void set_pp (MFunction func, string indent, object[] args)
+      {
+       Console.Write ("(set " + (MSymbol) args[0] + " ");
+       ((MExpression) args[1]).pp (indent);
+       Console.Write (")");
+      }
+
+      private static object plus (object[] args, MPlist bindings)
       {
-       MExpression expr = (MExpression) arg;
+       object val = ((MExpression) args[0]).Eval (bindings);
 
-       int n = (int) expr.Eval (bindings);
-       foreach (MExpression e in expr.next)
-         n -= (int) e.Eval (bindings);
+       if (val is int)
+         {
+           int n = 0;
+           foreach (MExpression e in args)
+             n += (int) e.Eval (bindings);
+           val = n;
+         }
+       else if (val is MText)
+         {
+           MText mt = new MText ();
+           foreach (MExpression e in args)
+             mt += (MText) e.Eval (bindings);
+           val = mt;
+         }
+       return val;
+      }
+
+      private static object multi (object[] args, MPlist bindings)
+      {
+       int n = 1;
+       foreach (MExpression e in args)
+         n *= (int) e.Eval (bindings);
        return n;
       }
 
-#if false
+      private static object minus (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       if (args.Length == 1)
+         return - n;
+       for (int i = 1; i < args.Length; i++)
+         n -= (int) ((MExpression) args[i]).Eval (bindings);
+       return n;
+      }
 
-    if (key == Mslash)
+      private static object divide (object[] args, MPlist bindings)
       {
-       int n = Plist.Eval (env);
-       foreach (MPlist plist in Plist.next)
-         n /= plist.Eval (env);
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         n /= (int) ((MExpression) args[i]).Eval (bindings);
        return n;
       }
-    if (key == Mpercent)
+
+      private static object percent (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         n %= (int) ((MExpression) args[i]).Eval (bindings);
+       return n;
+      }
+
+      private static object logior (object[] args, MPlist bindings)
       {
-       return Plist.Eval (env) % Plist.next.Eval (env);
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         n |= (int) ((MExpression) args[i]).Eval (bindings);
+       return n;
       }
-    if (key == Mlogior)
+
+      private static object logand (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         n &= (int) ((MExpression) args[i]).Eval (bindings);
+       return n;
+      }
+
+      private static object pluseq (object[] args, MPlist bindings)
       {
-       return Plist.Eval (env) | Plist.next.Eval (env);
+       MPlist slot = find_binding (args, bindings);
+       object val = slot.val;
+
+       if (val is int)
+         {
+           int n = (int) val;
+           for (int i = 1; i < args.Length; i++)
+             n += (int) ((MExpression) args[i]).Eval (bindings);
+           slot.val = n;
+         }
+       else if (val is MText)
+         {
+           MText mt = (MText) val;
+           for (int i = 1; i < args.Length; i++)
+             mt.Cat ((MText) ((MExpression) args[i]).Eval (bindings));
+         }
+       return slot.val;
       }
-    if (key == Mlogand)
+
+      private static object multieq (object[] args, MPlist bindings)
       {
-       return Plist.Eval (env) & Plist.next.Eval (env);
+       MPlist slot = find_binding (args, bindings);
+       int n = (int) slot.val;
+       for (int i = 1; i < args.Length; i++)
+         n *= (int) ((MExpression) args[i]).Eval (bindings);
+       return (slot.val = n);
       }
-    if (key == Mlshift)
+
+      private static object minuseq (object[] args, MPlist bindings)
       {
-       return Plist.Eval (env) << Plist.next.Eval (env);
+       MPlist slot = find_binding (args, bindings);
+       int n = (int) slot.val;
+       for (int i = 1; i < args.Length; i++)
+         n -= (int) ((MExpression) args[i]).Eval (bindings);
+       return (slot.val = n);
       }
-    if (key == Mrshift)
+
+      private static object divideeq (object[] args, MPlist bindings)
       {
-       return Plist.Eval (env) >> Plist.next.Eval (env);
+       MPlist slot = find_binding (args, bindings);
+       int n = (int) slot.val;
+       for (int i = 1; i < args.Length; i++)
+         n /= (int) ((MExpression) args[i]).Eval (bindings);
+       return (slot.val = n);
       }
-    if (key == Mset)
+
+      private static object percenteq (object[] args, MPlist bindings)
       {
-       MSymbol var = (MSymbol) Plist.val;
+       MPlist slot = find_binding (args, bindings);
+       int n = (int) slot.val;
+       for (int i = 1; i < args.Length; i++)
+         n %= (int) ((MExpression) args[i]).Eval (bindings);
+       return (slot.val = n);
+      }
 
+      private static object logioreq (object[] args, MPlist bindings)
+      {
+       MPlist slot = find_binding (args, bindings);
+       int n = (int) slot.val;
+       for (int i = 1; i < args.Length; i++)
+         n |= (int) ((MExpression) args[i]).Eval (bindings);
+       return (slot.val = n);
       }
-#endif
-  }
 
-  public class MExpression : MPlist
-  {
-    internal Dictionary<MSymbol, MFunction> FunctionTable;
+      private static object logandeq (object[] args, MPlist bindings)
+      {
+       MPlist slot = find_binding (args, bindings);
+       int n = (int) slot.val;
+       for (int i = 1; i < args.Length; i++)
+         n &= (int) ((MExpression) args[i]).Eval (bindings);
+       return (slot.val = n);
+      }
+
+      private static object lshift (object[] args, MPlist bindings)
+      {
+       int n1 = (int) ((MExpression) args[0]).Eval (bindings);
+       int n2 = (int) ((MExpression) args[1]).Eval (bindings);
+       return n1 << n2;
+      }
+
+      private static object lshifteq (object[] args, MPlist bindings)
+      {
+       MPlist slot = find_binding (args, bindings);
+       int n1 = (int) slot.val;
+       int n2 = (int) ((MExpression) args[1]).Eval (bindings);
+       return (slot.val = (n1 << n2));
+      }
+
+      private static object rshift (object[] args, MPlist bindings)
+      {
+       int n1 = (int) ((MExpression) args[0]).Eval (bindings);
+       int n2 = (int) ((MExpression) args[1]).Eval (bindings);
+       return n1 >> n2;
+      }
+
+      private static object rshifteq (object[] args, MPlist bindings)
+      {
+       MPlist slot = find_binding (args, bindings);
+       int n1 = (int) slot.val;
+       int n2 = (int) ((MExpression) args[1]).Eval (bindings);
+       return (slot.val = (n1 >> n2));
+      }
+
+      private static object eq (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         if (n != (int) ((MExpression) args[i]).Eval (bindings))
+           return 0;
+       return 1;
+      }
+
+      private static object noteq (object[] args, MPlist bindings)
+      {
+       int n1 = (int) ((MExpression) args[0]).Eval (bindings);
+       int n2 = (int) ((MExpression) args[1]).Eval (bindings);
+       return (n1 != n2);
+      }
+
+      private static object less (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         {
+           int n1 = (int) ((MExpression) args[i]).Eval (bindings);
+           if (n >= n1)
+             return 0;
+           n = n1;
+         }
+       return 1;
+      }
+
+      private static object lesseq (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         {
+           int n1 = (int) ((MExpression) args[i]).Eval (bindings);
+           if (n > n1)
+             return 0;
+           n = n1;
+         }
+       return 1;
+      }
+
+      private static object more (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         {
+           int n1 = (int) ((MExpression) args[i]).Eval (bindings);
+           if (n <= n1)
+             return 0;
+           n = n1;
+         }
+       return 1;
+      }
+
+      private static object moreeq (object[] args, MPlist bindings)
+      {
+       int n = (int) ((MExpression) args[0]).Eval (bindings);
+       for (int i = 1; i < args.Length; i++)
+         {
+           int n1 = (int) ((MExpression) args[i]).Eval (bindings);
+           if (n < n1)
+             return 0;
+           n = n1;
+         }
+       return 1;
+      }
+
+      private static object progn (object[] args, MPlist bindings)
+      {
+       object result = null;
+
+       foreach (MExpression e in args)
+         result = e.Eval (bindings);
+       return result;
+      }
+
+      private static void block_pp (MFunction func,
+                                   string indent, object[] args)
+      {
+       bool first = true;
+
+       Console.Write ("(");
+       indent += " ";
+       foreach (MExpression e in args)
+         {
+           if (first)
+             first = false;
+           else
+             Console.Write ("\n" + indent);
+           e.pp (indent);
+         }
+       Console.Write (")");
+      }
+
+      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);
+         }
+       return 0;
+      }
+
+      private static void cond_pp (MFunction func,
+                                   string indent, object[] args)
+      {
+       Console.Write ("(cond");
+       indent += "  ";
+       foreach (MExpression[] expr_list in args)
+         {
+           Console.Write ("\n" + indent + "(");
+           bool first = true;
+           foreach (MExpression e in expr_list)
+             {
+               if (first)
+                 first = false;
+               else
+                 Console.Write (" ");
+               e.pp (indent);
+             }
+           Console.Write (")");
+         }
+       Console.Write (")");
+      }
+
+      private static object ifclause (object[] args, MPlist bindings)
+      {
+       object result = 0;
+
+       if ((int) ((MExpression) args[0]).Eval (bindings) != 0)
+         result = ((MExpression) args[1]).Eval (bindings);
+       else
+         for (int i = 2; i < args.Length; i++)
+           result = ((MExpression) args[i]).Eval (bindings);
+       return result;
+      }
+
+      private static void if_pp (MFunction 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 (" ");
+           ((MExpression) args[i]).pp (indent);
+         }
+      }
+
+      private static object whileclause (object[] args, MPlist bindings)
+      {
+       object result = 0;
+
+       while ((int) ((MExpression) args[0]).Eval (bindings) != 0)
+         for (int i = 1; i < args.Length; i++)
+           result = ((MExpression) args[i]).Eval (bindings);
+       return result;
+      }
+
+      private static void while_pp (MFunction func,
+                                   string indent, object[] args)
+      {
+       Console.Write ("(while ");
+       ((MExpression) args[0]).pp (indent + "       ");
+       bool first = true;
+       indent += "  ";
+       for (int i = 1; i < args.Length; i++)
+         {
+           if (first)
+             {
+               Console.Write ("\n" + indent);
+               first = false;
+             }
+           else
+             Console.Write (" ");
+           ((MExpression) args[i]).pp (indent);
+         }
+      }
+    }
+
+    public class FunctionTable
+    {
+      internal Dictionary<MSymbol, MFunction> table
+       = new Dictionary<MSymbol, MFunction> ();
+    }
+
+    private static FunctionTable basic_table = new FunctionTable ();
+
+    public static void Defun (FunctionTable table, 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,
+                                     arg_types);
+      table.table[sym] = func;
+    }
+
+    private static MFunction 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,
+                                     arg_types);
+      basic_table.table[sym] = func;
+      return func;
+    }
+
+    private static MFunction 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)
+    {
+      if (name == MSymbol.integer
+         || name == MSymbol.mtext)
+       return MFunction.literal;
+
+      MFunction func;
+      if ((table == null
+          || ! table.table.TryGetValue (name, out func))
+         && ! basic_table.table.TryGetValue (name, out func))
+       return null;
+      return func;
+    }
+
+    private void invalid_expression (object o)
+    {
+      throw new Exception ("Invalid expresssion: " + o);
+    }
+
+    private void invalid_argument (object o)
+    {
+      throw new Exception ("Invalid argument: " + o);
+    }
 
     private MFunction function;
+    private object[] args;
 
-    public MExpression () : base () { }
+    public MExpression (MSymbol function_name, object[] args,
+                       FunctionTable function_table)
+    {
+      function = Find (function_name, function_table);
+      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);
+      this.args = (object[]) args.Clone ();
+    }
+
+    private MExpression[] expression_list (MPlist plist, FunctionTable table)
+    {
+      int len = plist.Count;
+      MExpression[] expr_list = new MExpression[len];
 
-    public MExpression (Dictionary<MSymbol, MFunction> function_table)
-      : base () { FunctionTable = function_table; }
+      for (int i = 0; i < len; i++, plist = plist.next)
+       {
+         if (plist.IsSymbol)
+           expr_list[i] = new MExpression (plist.Symbol);
+         else if (plist.IsMText || plist.IsInteger)
+           expr_list[i] = new MExpression (plist.val);
+         else if (plist.IsPlist)
+           {
+             MPlist p = plist.Plist;
+             if (p.IsSymbol)
+               expr_list[i] = new MExpression (p.Symbol, p.next, table);
+             else
+               expr_list[i] = new MExpression (p, table);
+           }
+         else
+           invalid_expression (plist.val);
+       }
+      return expr_list;
+    }
 
-    public new MExpression Add (MPlist plist)
+    // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
+    // FUNCALL = '(' SYMBOL EXPR* ')'
+    // EXPRLIST = '(' EXPR* ')'
+
+    // EXPRLIST: PLIST = EXPR ...
+    public MExpression (MPlist plist, FunctionTable table)
     {
-      if (plist.IsPlist)
+      function = MFunction.block;
+      args = expression_list (plist, table);
+    }
+
+    // FUNCALL: NAME = FUNCTION-NAME, ARG-LIST = EXPR ...
+    private MExpression (MSymbol name, MPlist arg_list, FunctionTable table)
+    {
+      function = Find (name, table);
+      if (function == null)
+       throw new Exception ("Unknown function: " + name);
+
+      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);
+      args = new object[nargs];
+
+      int i = 0;
+      Type arg_type = typeof (MExpression);
+      foreach (MPlist p in arg_list)
        {
-         MPlist pl = plist.Plist;
-         
-         if (! pl.IsSymbol)
-           throw new Exception ("Invalid expression: " + plist);
-         MExpression e = new MExpression (FunctionTable);
-         pl.key = pl.Symbol;
-         foreach (MPlist p in pl.next)
-           e.Add (p);
-         pl.val = e;
-         return Add (pl);
+         if (i < function.arg_types.Length)
+           arg_type = function.arg_types[i];
+         if (arg_type == typeof (MExpression))
+           {
+             if (p.IsSymbol)
+               args[i++] = new MExpression (p.Symbol);
+             else if (p.IsMText || p.IsInteger)
+               args[i++] = new MExpression (p.val);
+             else if (p.IsPlist)
+               {
+                 MPlist p0 = p.Plist;
+                 if (p0.IsSymbol)
+                   args[i++] = new MExpression (p0.Symbol, p0.next, table);
+                 else
+                   args[i++] = new MExpression (p0, table);
+               }
+             else
+               invalid_expression (p.val);
+           }
+         else if (arg_type == typeof (MExpression[]))
+           {
+             if (! p.IsPlist)
+               invalid_argument (p.val);
+             args[i++] = expression_list (p.Plist, table);
+           }
+         else if (arg_type == typeof (MSymbol))
+           {
+             if (! p.IsSymbol)
+               invalid_argument (p.val);
+             args[i++] = p.Symbol;
+           }
+         else
+           args[i++] = p.val;
        }
-      return Add (plist.key, plist.val);
     }
 
-    public new MExpression Add (MSymbol function_name, object arg)
+    public MExpression (MSymbol sym)
     {
-      MExpression expr = this, e = new MExpression ();
+      function = MFunction.varref;
+      args = new object[1];
+      args[0] = sym;
+    }
 
-      while (! expr.IsEmpty)
-       expr = (MExpression) expr.next;
-      expr.key = function_name;
-      expr.val = arg;
-      expr.next = e;
-      expr.FunctionTable = FunctionTable;
-      expr.function = MFunction.Find (function_name, FunctionTable);
-      return expr;
+    public MExpression (object obj)
+    {
+      function = MFunction.literal;
+      args = new object[1];
+      args[0] = obj;
     }
 
     public object Eval (MPlist bindings)
     {
-      return function.Call (val, bindings);
+      return function.Call (args, bindings);
+    }
+
+    private void pp (string indent)
+    {
+      if (function == MFunction.varref
+         || function == MFunction.literal)
+       {
+         if (args[0] is MText)
+           Console.Write ("\"{0}\"", args[0]);
+         else
+           Console.Write (args[0]);
+       }
+      else
+       function.pp (function, indent, args);
     }
+
+    public void PretyPrint () { pp (""); }
   }
-}
\ No newline at end of file
+}
index 05e6fcf..5c916f1 100644 (file)
--- a/MText.cs
+++ b/MText.cs
@@ -440,6 +440,12 @@ namespace M17N.Core
       return this;
     }
 
+    public MText Cat (MText mt)
+    {
+      insert (nchars, mt, 0, mt.Length);
+      return this;
+    }
+
     public MText Del (int from, int to)
     {
       if (check_range (from, to, true))
index beec40f..174896d 100644 (file)
--- a/eval.txt
+++ b/eval.txt
@@ -1,16 +1,14 @@
 ;; -*- lisp -*-
 
-(progn
-  (cond
-   (0 (+ X 2 (* 3 4) (- 3 4)))
-   (1 (+= X 10)))
-  (if (> 20 X 10)
-      (progn
-       (<<= X 2)
-       (set Y "abc")
-       (+= Y "def"))
-    (while (> X 7)
-      (/= X 2))
-    (set Y "ABC")
-    (set Z (+ Y "def")))
-  (insert "kkk"))
+(cond
+ (0 (+ X 2 (* 3 4) (- 3 4)) (set X 4))
+ (1 (+= X 10)))
+(if (> 20 X 10)
+    ((<<= X 2)
+     (set Y "abc")
+     (+= Y "def"))
+  (while (> X 7)
+    (/= X 2))
+  (set Y "ABC")
+  (set Z (+ Y "def")))
+(insert "kkk")
diff --git a/expr.cs b/expr.cs
index e527b92..a2294a2 100644 (file)
--- a/expr.cs
+++ b/expr.cs
@@ -1,21 +1,43 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
 using M17N;
 using M17N.Core;
 
 public class Test
 {
+  static MSymbol Mpreedit = MSymbol.Of ("preedit");
+
+  public static object insert (object[] args, MPlist bindings)
+  {
+    object arg = ((MExpression) args[0]).Eval (bindings);
+    MPlist slot = bindings.Find (Mpreedit);
+    MText preedit = (MText) slot.val;
+
+    if (arg is int)
+      preedit.Cat ((int) arg);
+    else
+      preedit.Cat ((MText) arg);
+    return arg;
+  }
+
   public static void Main()
   {
-    MExpression expr = new MExpression ();
+    MExpression expr;
+    MPlist bindings = new MPlist ();
+    MExpression.FunctionTable func_table = new MExpression.FunctionTable ();
+
+    MExpression.Defun (func_table, "insert", new MExpression.Evaluator (insert),
+                      1, 1, typeof (MExpression));
+    bindings.Add (MSymbol.Of ("X"), 10);
+    bindings.Add (Mpreedit, new MText ("PREEDIT TEXT"));
 
     using (FileStream stream = new FileStream ("eval.txt", FileMode.Open))
       {
-       MPlist plist = new MPlist (stream);
-
-       foreach (MPlist p in plist)
-         expr.Add (p);
+       expr = new MExpression (new MPlist (stream), func_table);
       }
-    Console.WriteLine (expr+"="+expr.Eval (null));
+    expr.PretyPrint ();
+    Console.WriteLine ("\n  => " + expr.Eval (bindings));
+    Console.WriteLine (bindings);
   }
 }