namespace M17N.Core
{
- public delegate object MEvaluator (MExpression args);
-
- public class MFunction
+ public class MExpression
{
- internal readonly MSymbol name;
- internal readonly MEvaluator evaluator;
- public static Dictionary<MSymbol, MFunction> CommonTable
- = new Dictionary<MSymbol, MFunction> ();
+ public delegate object Evaluator (object[] args, MPlist bindings);
+
+ internal delegate void PrettyPrinter (Function func,
+ string indent, object[] args);
+
+ internal class Function
+ {
+ internal readonly MSymbol name;
+ internal readonly Evaluator eval;
+ 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 Function literal, varref, block, defun;
+
+ public Function (MSymbol name, Evaluator eval,
+ int min_arg, int max_arg, params 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_pretty_printer;
+ else
+ pp = default_pretty_printer;
+ }
+
+ static Function ()
+ {
+ default_pretty_printer = new PrettyPrinter (default_pp);
+ set_pretty_printer = new PrettyPrinter (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);
+
+ 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 PrettyPrinter (block_pp);
+ Defun ("cond", new Evaluator (cond), 1, -1,
+ typeof (MExpression[])).pp = new PrettyPrinter (cond_pp);
+ Defun ("if", new Evaluator (ifclause), 2, -1,
+ typeof (MExpression)).pp = new PrettyPrinter (if_pp);
+ Defun ("while", new Evaluator (whileclause), 1, -1,
+ typeof (MExpression)).pp = new PrettyPrinter (while_pp);
+ defun = Defun ("defun", new Evaluator (define_function), 4, -1,
+ typeof (FunctionTable),
+ typeof (MSymbol),
+ typeof (MPlist),
+ typeof (MExpression));
+ defun.pp = new PrettyPrinter (defun_pp);
+ }
+
+ private static MPlist find_binding (object[] args, MPlist bindings)
+ {
+ MSymbol var = (MSymbol) args[0];
+ MPlist slot = bindings.Find (var);
+
+ if (slot == null)
+ throw new Exception ("Unbound variable: " + var);
+ return slot;
+ }
+
+ public object Call (object[] args, MPlist bindings)
+ {
+ if (name == MSymbol.nil)
+ return args[0];
+ if (eval != null)
+ return eval (args, bindings);
+
+ MPlist arg_symbols = (MPlist) data[0];
+ for (int i = 0; i < args.Length; i++, arg_symbols = arg_symbols.next)
+ bindings = bindings.Cons (arg_symbols.Symbol,
+ ((MExpression) args[i]).Eval (bindings));
+ object result = 0;
+ for (int i = 1; i < data.Length; i++)
+ result = ((MExpression) data[i]).Eval (bindings);
+ return result;
+ }
+
+ // Commonly used pretty-printers.
+
+ public static void default_pp (Function func,
+ string indent, object[] args)
+ {
+ Console.Write ("(" + func.name);
+ indent += " ";
+ foreach (object o in args)
+ {
+ Console.Write (" ");
+ if (o is MExpression)
+ ((MExpression) o).pp (indent);
+ else
+ Console.Write (o);
+ }
+ Console.Write (")");
+ }
+
+ private static void set_pp (Function func, string indent, object[] args)
+ {
+ Console.Write ("(" + func.name + " " + (MSymbol) args[0] + " ");
+ ((MExpression) args[1]).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);
+
+ 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 object plus (object[] args, MPlist bindings)
+ {
+ object val = ((MExpression) args[0]).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;
+ }
+
+ 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;
+ }
+
+ private static object divide (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 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)
+ {
+ 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 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)
+ {
+ 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;
+ }
+
+ private static object multieq (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 minuseq (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 divideeq (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 percenteq (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 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);
+ }
+
+ 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;
+ }
- public MFunction (MSymbol name, MEvaluator evaluator)
+ 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 (Function 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 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)
+ 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 (Function 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 (check_condition ((MExpression) args[0], bindings))
+ 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 (Function func,
+ string indent, object[] args)
+ {
+ Console.Write ("(if ");
+ ((MExpression) args[0]).pp (indent + " ");
+ Console.Write ("\n" + indent + " ");
+ ((MExpression) args[1]).pp (indent + " ");
+ indent += " ";
+ for (int i = 2; i < args.Length; i++)
+ {
+ Console.Write ("\n" + indent);
+ ((MExpression) args[i]).pp (indent);
+ }
+ Console.Write (")");
+ }
+
+ private static object whileclause (object[] args, MPlist bindings)
+ {
+ object result = 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 (Function 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);
+ }
+ Console.Write (")");
+ }
+
+ public static object define_function (object[] args, MPlist bindings)
+ {
+ FunctionTable table = (FunctionTable) args[0];
+ MSymbol sym = (MSymbol) args[1];
+ MPlist arg_symbols = (MPlist) args[2];
+ int nargs = arg_symbols.Count;
+ object[] data = new object[args.Length - 2];
+
+ data[0] = args[2];
+ for (int i = 3; i < args.Length; i++)
+ data[i - 2] = args[i];
+
+ Function func = new Function (sym, null, nargs, nargs,
+ typeof (MExpression));
+ table.table[sym] = func;
+ func.data = data;
+ return null;
+ }
+
+ private static void defun_pp (Function func,
+ string indent, object[] args)
+ {
+ Console.Write ("(defun " + args[1] + " " + args[2]);
+ bool first = true;
+ indent += " ";
+ for (int i = 3; i < args.Length; i++)
+ {
+ if (first)
+ {
+ Console.Write ("\n" + indent);
+ first = false;
+ }
+ else
+ Console.Write (" ");
+ ((MExpression) args[i]).pp (indent);
+ }
+ Console.Write (")");
+ }
+ }
+
+ public class FunctionTable
+ {
+ internal Dictionary<MSymbol, Function> table;
+
+ public FunctionTable ()
+ {
+ table = new Dictionary<MSymbol, Function> ();
+ }
+
+ public FunctionTable (FunctionTable table)
+ {
+ this.table = new Dictionary<MSymbol, Function> (table.table);
+ }
+
+ public void Copy (FunctionTable table)
+ {
+ foreach (KeyValuePair<MSymbol, Function> kv in this.table)
+ table.table[kv.Key] = kv.Value;
+ }
+
+ public void Copy (MSymbol name, FunctionTable table)
+ {
+ Function func;
+ if (this.table.TryGetValue (name, out func))
+ table.table[name] = func;
+ }
+ }
+
+ 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)
{
- this.evaluator = evaluator;
- CommonTable[name] = this;
+ Function func = Defun (name, evaluator, min_arg, max_arg, arg_types);
+ table.table[func.name] = func;
}
- public MFunction (MSymbol name, MEvaluator evaluator,
- Dictionary<MSymbol, MFunction> dict)
+ public static void Defmacro (FunctionTable table, MSymbol name,
+ MExpression expr)
{
- this.evaluator = evaluator;
- dict[name] = this;
+ object[] args = new object[4];
+ args[0] = table;
+ args[1] = name;
+ args[2] = new MPlist ();
+ args[3] = expr;
+ Function.define_function (args, null);
}
- public object Call (MExpression args)
+ private static Function Defun (string name, Evaluator evaluator,
+ int min_arg, int max_arg,
+ params Type[] arg_types)
{
- return evaluator (args);
+ MSymbol sym = MSymbol.Of (name);
+ Function func = new Function (sym, evaluator, min_arg, max_arg,
+ arg_types);
+ basic_table.table[sym] = func;
+ return func;
}
- private object plus (MExpression args)
+ private static Function Defun (string name, Evaluator evaluator,
+ int min_arg, int max_arg)
{
- int n = 0;
- foreach (MExpression expr in args)
- n += expr.Eval (bindings);
- return n;
+ return Defun (name, evaluator, min_arg, max_arg, typeof (MExpression));
}
- private object multiply (MExpression args)
+ private static Function Find (MSymbol name, FunctionTable table)
{
- int n = 1;
- foreach (MExpression expr in args)
- n *= expr.Eval (bindings);
- return n;
+ if (name == MSymbol.integer
+ || name == MSymbol.mtext)
+ return Function.literal;
+
+ Function func;
+ if ((table == null
+ || ! table.table.TryGetValue (name, out func))
+ && ! basic_table.table.TryGetValue (name, out func))
+ return null;
+ return func;
}
-#if false
- if (key == Mminus)
- {
- int n = - Plist.Eval (env);
- foreach (MPlist plist in Plist.next)
- n -= plist.Eval (env);
- return n;
- }
- if (key == Mslash)
- {
- int n = Plist.Eval (env);
- foreach (MPlist plist in Plist.next)
- n /= plist.Eval (env);
- return n;
- }
- if (key == Mpercent)
- {
- return Plist.Eval (env) % Plist.next.Eval (env);
- }
- if (key == Mlogior)
- {
- return Plist.Eval (env) | Plist.next.Eval (env);
- }
- if (key == Mlogand)
- {
- return Plist.Eval (env) & Plist.next.Eval (env);
- }
- if (key == Mlshift)
+ private void invalid_expression (object o)
+ {
+ throw new Exception ("Invalid expresssion: " + o);
+ }
+
+ private void invalid_argument (object o)
+ {
+ throw new Exception (String.Format ("Invalid argument to {0}: {1}",
+ function.name, o));
+ }
+
+ private Function function;
+ private object[] args;
+
+ 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 (String.Format ("Invalid number of arguments to {0}: {1}", function.name, nargs));
+ this.args = (object[]) args.Clone ();
+ }
+
+ private MExpression[] expression_list (MPlist plist, FunctionTable table)
+ {
+ int len = plist.Count;
+ MExpression[] expr_list = new MExpression[len];
+
+ for (int i = 0; i < len; i++, plist = plist.next)
{
- return Plist.Eval (env) << Plist.next.Eval (env);
+ 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);
}
- if (key == Mrshift)
+ return expr_list;
+ }
+
+ // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
+ // FUNCALL = '(' SYMBOL EXPR* ')'
+ // EXPRLIST = '(' EXPR* ')'
+
+ // EXPRLIST: PLIST = EXPR ...
+ public MExpression (MPlist plist, FunctionTable table)
+ {
+ function = Function.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 (String.Format
+ ("Invalid number of arguments to {0}: {1}",
+ function.name, nargs));
+
+ int i = 0;
+ Type arg_type = typeof (MExpression);
+ if (function.arg_types.Length > 0)
{
- return Plist.Eval (env) >> Plist.next.Eval (env);
+ arg_type = function.arg_types[0];
+ if (arg_type == typeof (FunctionTable))
+ {
+ nargs++;
+ args = new object[nargs];
+ args[i++] = table;
+ }
+ else
+ args = new object[nargs];
}
- if (key == Mset)
- {
- MSymbol var = (MSymbol) Plist.val;
+ else
+ args = new object[nargs];
+ foreach (MPlist p in arg_list)
+ {
+ 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;
}
-#endif
- }
-
- public class MBindings : MPlist
- {
- public MBindings () : base () { }
+ if (function == Function.defun)
+ function.Call (args, null);
+ }
- public new MBindings Push (MSymbol variable, object value)
+ public MExpression (MSymbol sym)
{
- base.Push (variable, value);
+ function = Function.varref;
+ args = new object[1];
+ args[0] = sym;
}
- public override string ToString ()
- {
- string str = "(";
- foreach (MBindings b in this)
- {
- if (b != this)
- str += ", ";
- str += b.key + " = " + b.val;
- }
- return str + ")";
- }
- }
-
- public class MExpression : MPlist
- {
- public MExpression () : base () { }
-
- public MExpression Append (MFunction func, MExpression args)
+ public MExpression (object obj)
{
- base.Add (op, (MPlist) args);
- return this;
+ function = Function.literal;
+ args = new object[1];
+ args[0] = obj;
}
- public object Eval ()
+ public object Eval (MPlist bindings)
{
-
+ return function.Call (args, bindings);
+ }
+ private void pp (string indent)
+ {
+ if (function == Function.varref
+ || function == Function.literal)
+ {
+ if (args[0] is MText)
+ Console.Write ("\"{0}\"", args[0]);
+ else
+ Console.Write (args[0]);
+ }
+ else
+ function.pp (function, indent, args);
}
+
+ public void PrettyPrint () { pp (""); }
}
-}
\ No newline at end of file
+}