{
public delegate object Evaluator (object[] args, MPlist bindings);
- internal delegate void PretyPrinter (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 PretyPrinter pp;
+ public PrettyPrinter pp;
- private static PretyPrinter default_prety_printer;
- private static PretyPrinter set_prety_printer;
- internal static MFunction literal, varref, block;
+ private static PrettyPrinter default_pretty_printer;
+ private static PrettyPrinter set_pretty_printer;
+ internal static Function literal, varref, block, defun;
- public MFunction (MSymbol name, Evaluator eval,
- int min_arg, int max_arg, 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;
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;
+ pp = set_pretty_printer;
else
- pp = default_prety_printer;
+ pp = default_pretty_printer;
}
- static MFunction ()
+ static Function ()
{
- default_prety_printer = new PretyPrinter (default_pp);
- set_prety_printer = new PretyPrinter (set_pp);
+ 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 (">", 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);
+ block.pp = new PrettyPrinter (block_pp);
Defun ("cond", new Evaluator (cond), 1, -1,
- typeof (MExpression[])).pp = new PretyPrinter (cond_pp);
+ typeof (MExpression[])).pp = new PrettyPrinter (cond_pp);
Defun ("if", new Evaluator (ifclause), 2, -1,
- typeof (MExpression)).pp = new PretyPrinter (if_pp);
+ typeof (MExpression)).pp = new PrettyPrinter (if_pp);
Defun ("while", new Evaluator (whileclause), 1, -1,
- typeof (MExpression)).pp = new PretyPrinter (while_pp);
- }
-
- public object Call (object[] args, MPlist bindings)
- {
- if (name == MSymbol.nil)
- return args[0];
- return eval (args, bindings);
+ 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)
return slot;
}
- public static void default_pp (MFunction func,
+ 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 (MExpression o in args)
+ foreach (object o in args)
{
Console.Write (" ");
- o.pp (indent);
+ 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;
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)
{
object val = ((MExpression) args[0]).Eval (bindings);
return result;
}
- private static void block_pp (MFunction func,
+ private static void block_pp (Function func,
string indent, object[] args)
{
bool first = true;
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 += " ";
{
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++)
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 ");
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, MFunction> table
- = new Dictionary<MSymbol, MFunction> ();
+ 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 ();
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;
+ Function func = Defun (name, evaluator, min_arg, max_arg, arg_types);
+ table.table[func.name] = func;
+ }
+
+ public static void Defmacro (FunctionTable table, MSymbol name,
+ MExpression expr)
+ {
+ object[] args = new object[4];
+ args[0] = table;
+ args[1] = name;
+ args[2] = new MPlist ();
+ args[3] = expr;
+ Function.define_function (args, null);
}
- 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,
- arg_types);
+ 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,
- int min_arg, int max_arg)
+ 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))
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,
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 ();
}
// EXPRLIST: PLIST = EXPR ...
public MExpression (MPlist plist, FunctionTable table)
{
- function = MFunction.block;
+ function = Function.block;
args = expression_list (plist, table);
}
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];
+ 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)
+ {
+ arg_type = function.arg_types[0];
+ if (arg_type == typeof (FunctionTable))
+ {
+ nargs++;
+ args = new object[nargs];
+ args[i++] = table;
+ }
+ else
+ args = new object[nargs];
+ }
+ else
+ args = new object[nargs];
+
foreach (MPlist p in arg_list)
{
if (i < function.arg_types.Length)
else
args[i++] = p.val;
}
+ 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;
}
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]);
function.pp (function, indent, args);
}
- public void PretyPrint () { pp (""); }
+ public void PrettyPrint () { pp (""); }
}
}