2 using System.Collections;
3 using System.Collections.Generic;
10 public class MExpression
12 public delegate object Evaluator (object[] args, MPlist bindings);
14 internal delegate void PrettyPrinter (MFunction func,
15 string indent, object[] args);
17 internal class MFunction
19 internal MSymbol name;
20 internal readonly Evaluator eval;
23 internal Type[] arg_types;
24 internal object[] data;
26 public PrettyPrinter pp;
28 private static PrettyPrinter default_pretty_printer;
29 private static PrettyPrinter set_pretty_printer;
30 internal static MFunction literal, varref, block, defun;
32 public MFunction (MSymbol name, Evaluator eval,
33 int min_arg, int max_arg, params Type[] arg_types)
37 this.min_arg = min_arg;
38 this.max_arg = max_arg;
39 this.arg_types = (Type []) arg_types.Clone ();
40 if (arg_types.Length == 2 && arg_types[0] == typeof (MSymbol))
41 pp = set_pretty_printer;
43 pp = default_pretty_printer;
48 default_pretty_printer = new PrettyPrinter (default_pp);
49 set_pretty_printer = new PrettyPrinter (set_pp);
50 literal = Defun ("nil", null, 1, 1);
51 varref = Defun ("symbol", new Evaluator (get_value), 1, 1);
52 block = Defun ("plist", new Evaluator (progn), 1, -1);
54 Defun ("set", new Evaluator (set_value), 2, 2,
55 typeof (MSymbol), typeof (MExpression));
56 Defun ("=", new Evaluator (set_value), 2, 2,
57 typeof (MSymbol), typeof (MExpression));
58 Defun ("+", new Evaluator (plus), 1, -1);
59 Defun ("*", new Evaluator (multi), 2, -1);
60 Defun ("-", new Evaluator (minus), 1, -1);
61 Defun ("/", new Evaluator (divide), 2, -1);
62 Defun ("%", new Evaluator (percent), 2, -1);
63 Defun ("|", new Evaluator (logior), 2, -1);
64 Defun ("&", new Evaluator (logand), 2, -1);
65 Defun ("+=", new Evaluator (pluseq), 2, -1,
66 typeof (MSymbol), typeof (MExpression));
67 Defun ("*=", new Evaluator (multieq), 2, -1,
68 typeof (MSymbol), typeof (MExpression));
69 Defun ("-=", new Evaluator (minuseq), 2, -1,
70 typeof (MSymbol), typeof (MExpression));
71 Defun ("/=", new Evaluator (divideeq), 2, -1,
72 typeof (MSymbol), typeof (MExpression));
73 Defun ("%=", new Evaluator (percenteq), 2, -1,
74 typeof (MSymbol), typeof (MExpression));
75 Defun ("|=", new Evaluator (logioreq), 2, -1,
76 typeof (MSymbol), typeof (MExpression));
77 Defun ("&=", new Evaluator (logandeq), 2, -1,
78 typeof (MSymbol), typeof (MExpression));
79 Defun ("<<", new Evaluator (lshift), 2, 2);
80 Defun (">>", new Evaluator (rshift), 2, 2);
81 Defun ("<<=", new Evaluator (lshifteq), 2, 2,
82 typeof (MSymbol), typeof (MExpression));
83 Defun (">>=", new Evaluator (rshifteq), 2, 2,
84 typeof (MSymbol), typeof (MExpression));
85 Defun ("==", new Evaluator (eq), 2, -1);
86 Defun ("!=", new Evaluator (noteq), 2, 2);
87 Defun ("<", new Evaluator (less), 2, -1);
88 Defun ("<=", new Evaluator (lesseq), 2, -1);
89 Defun (">", new Evaluator (more), 2, -1);
90 Defun (">=", new Evaluator (moreeq), 2, -1);
91 block = Defun ("progn", new Evaluator (progn), 1, -1);
92 block.pp = new PrettyPrinter (block_pp);
93 Defun ("cond", new Evaluator (cond), 1, -1,
94 typeof (MExpression[])).pp = new PrettyPrinter (cond_pp);
95 Defun ("if", new Evaluator (ifclause), 2, -1,
96 typeof (MExpression)).pp = new PrettyPrinter (if_pp);
97 Defun ("while", new Evaluator (whileclause), 1, -1,
98 typeof (MExpression)).pp = new PrettyPrinter (while_pp);
99 defun = Defun ("defun", new Evaluator (define_function), 4, -1,
100 typeof (FunctionTable),
103 typeof (MExpression));
104 defun.pp = new PrettyPrinter (defun_pp);
107 private static MPlist find_binding (object[] args, MPlist bindings)
109 MSymbol var = (MSymbol) args[0];
110 MPlist slot = bindings.Find (var);
113 throw new Exception ("Unbound variable: " + var);
117 public object Call (object[] args, MPlist bindings)
119 if (name == MSymbol.nil)
122 return eval (args, bindings);
124 MPlist arg_symbols = (MPlist) data[0];
125 for (int i = 0; i < args.Length; i++, arg_symbols = arg_symbols.next)
126 bindings = bindings.Cons (arg_symbols.Symbol,
127 ((MExpression) args[i]).Eval (bindings));
129 for (int i = 1; i < data.Length; i++)
130 result = ((MExpression) data[i]).Eval (bindings);
134 // Commonly used pretty-printers.
136 public static void default_pp (MFunction func,
137 string indent, object[] args)
139 Console.Write ("(" + func.name);
141 foreach (MExpression o in args)
149 private static void set_pp (MFunction func, string indent, object[] args)
151 Console.Write ("(" + func.name + " " + (MSymbol) args[0] + " ");
152 ((MExpression) args[1]).pp (indent);
156 private static object get_value (object[] args, MPlist bindings)
158 return find_binding (args, bindings).val;
161 private static object set_value (object[] args, MPlist bindings)
163 MSymbol var = (MSymbol) args[0];
164 MPlist slot = bindings.Find (var);
167 slot = bindings.Push (var, null);
168 slot.val = ((MExpression) args[1]).Eval (bindings);
169 if (slot.val is MText)
170 slot.val = ((MText) slot.val).Dup ();
174 private static object plus (object[] args, MPlist bindings)
176 object val = ((MExpression) args[0]).Eval (bindings);
181 foreach (MExpression e in args)
182 n += (int) e.Eval (bindings);
185 else if (val is MText)
187 MText mt = new MText ();
188 foreach (MExpression e in args)
189 mt += (MText) e.Eval (bindings);
195 private static object multi (object[] args, MPlist bindings)
198 foreach (MExpression e in args)
199 n *= (int) e.Eval (bindings);
203 private static object minus (object[] args, MPlist bindings)
205 int n = (int) ((MExpression) args[0]).Eval (bindings);
206 if (args.Length == 1)
208 for (int i = 1; i < args.Length; i++)
209 n -= (int) ((MExpression) args[i]).Eval (bindings);
213 private static object divide (object[] args, MPlist bindings)
215 int n = (int) ((MExpression) args[0]).Eval (bindings);
216 for (int i = 1; i < args.Length; i++)
217 n /= (int) ((MExpression) args[i]).Eval (bindings);
221 private static object percent (object[] args, MPlist bindings)
223 int n = (int) ((MExpression) args[0]).Eval (bindings);
224 for (int i = 1; i < args.Length; i++)
225 n %= (int) ((MExpression) args[i]).Eval (bindings);
229 private static object logior (object[] args, MPlist bindings)
231 int n = (int) ((MExpression) args[0]).Eval (bindings);
232 for (int i = 1; i < args.Length; i++)
233 n |= (int) ((MExpression) args[i]).Eval (bindings);
237 private static object logand (object[] args, MPlist bindings)
239 int n = (int) ((MExpression) args[0]).Eval (bindings);
240 for (int i = 1; i < args.Length; i++)
241 n &= (int) ((MExpression) args[i]).Eval (bindings);
245 private static object pluseq (object[] args, MPlist bindings)
247 MPlist slot = find_binding (args, bindings);
248 object val = slot.val;
253 for (int i = 1; i < args.Length; i++)
254 n += (int) ((MExpression) args[i]).Eval (bindings);
257 else if (val is MText)
259 MText mt = (MText) val;
260 for (int i = 1; i < args.Length; i++)
261 mt.Cat ((MText) ((MExpression) args[i]).Eval (bindings));
266 private static object multieq (object[] args, MPlist bindings)
268 MPlist slot = find_binding (args, bindings);
269 int n = (int) slot.val;
270 for (int i = 1; i < args.Length; i++)
271 n *= (int) ((MExpression) args[i]).Eval (bindings);
272 return (slot.val = n);
275 private static object minuseq (object[] args, MPlist bindings)
277 MPlist slot = find_binding (args, bindings);
278 int n = (int) slot.val;
279 for (int i = 1; i < args.Length; i++)
280 n -= (int) ((MExpression) args[i]).Eval (bindings);
281 return (slot.val = n);
284 private static object divideeq (object[] args, MPlist bindings)
286 MPlist slot = find_binding (args, bindings);
287 int n = (int) slot.val;
288 for (int i = 1; i < args.Length; i++)
289 n /= (int) ((MExpression) args[i]).Eval (bindings);
290 return (slot.val = n);
293 private static object percenteq (object[] args, MPlist bindings)
295 MPlist slot = find_binding (args, bindings);
296 int n = (int) slot.val;
297 for (int i = 1; i < args.Length; i++)
298 n %= (int) ((MExpression) args[i]).Eval (bindings);
299 return (slot.val = n);
302 private static object logioreq (object[] args, MPlist bindings)
304 MPlist slot = find_binding (args, bindings);
305 int n = (int) slot.val;
306 for (int i = 1; i < args.Length; i++)
307 n |= (int) ((MExpression) args[i]).Eval (bindings);
308 return (slot.val = n);
311 private static object logandeq (object[] args, MPlist bindings)
313 MPlist slot = find_binding (args, bindings);
314 int n = (int) slot.val;
315 for (int i = 1; i < args.Length; i++)
316 n &= (int) ((MExpression) args[i]).Eval (bindings);
317 return (slot.val = n);
320 private static object lshift (object[] args, MPlist bindings)
322 int n1 = (int) ((MExpression) args[0]).Eval (bindings);
323 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
327 private static object lshifteq (object[] args, MPlist bindings)
329 MPlist slot = find_binding (args, bindings);
330 int n1 = (int) slot.val;
331 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
332 return (slot.val = (n1 << n2));
335 private static object rshift (object[] args, MPlist bindings)
337 int n1 = (int) ((MExpression) args[0]).Eval (bindings);
338 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
342 private static object rshifteq (object[] args, MPlist bindings)
344 MPlist slot = find_binding (args, bindings);
345 int n1 = (int) slot.val;
346 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
347 return (slot.val = (n1 >> n2));
350 private static object eq (object[] args, MPlist bindings)
352 int n = (int) ((MExpression) args[0]).Eval (bindings);
353 for (int i = 1; i < args.Length; i++)
354 if (n != (int) ((MExpression) args[i]).Eval (bindings))
359 private static object noteq (object[] args, MPlist bindings)
361 int n1 = (int) ((MExpression) args[0]).Eval (bindings);
362 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
366 private static object less (object[] args, MPlist bindings)
368 int n = (int) ((MExpression) args[0]).Eval (bindings);
369 for (int i = 1; i < args.Length; i++)
371 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
379 private static object lesseq (object[] args, MPlist bindings)
381 int n = (int) ((MExpression) args[0]).Eval (bindings);
382 for (int i = 1; i < args.Length; i++)
384 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
392 private static object more (object[] args, MPlist bindings)
394 int n = (int) ((MExpression) args[0]).Eval (bindings);
395 for (int i = 1; i < args.Length; i++)
397 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
405 private static object moreeq (object[] args, MPlist bindings)
407 int n = (int) ((MExpression) args[0]).Eval (bindings);
408 for (int i = 1; i < args.Length; i++)
410 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
418 private static object progn (object[] args, MPlist bindings)
420 object result = null;
422 foreach (MExpression e in args)
423 result = e.Eval (bindings);
427 private static void block_pp (MFunction func,
428 string indent, object[] args)
434 foreach (MExpression e in args)
439 Console.Write ("\n" + indent);
445 private static object cond (object[] args, MPlist bindings)
447 foreach (MExpression[] elist in args)
449 int i = (int) elist[0].Eval (bindings);
451 return progn ((object[]) elist, bindings);
456 private static void cond_pp (MFunction func,
457 string indent, object[] args)
459 Console.Write ("(cond");
461 foreach (MExpression[] expr_list in args)
463 Console.Write ("\n" + indent + "(");
465 foreach (MExpression e in expr_list)
478 private static object ifclause (object[] args, MPlist bindings)
482 if ((int) ((MExpression) args[0]).Eval (bindings) != 0)
483 result = ((MExpression) args[1]).Eval (bindings);
485 for (int i = 2; i < args.Length; i++)
486 result = ((MExpression) args[i]).Eval (bindings);
490 private static void if_pp (MFunction func,
491 string indent, object[] args)
493 Console.Write ("(if ");
494 ((MExpression) args[0]).pp (indent + " ");
495 Console.Write ("\n" + indent + " ");
496 ((MExpression) args[1]).pp (indent + " ");
499 for (int i = 2; i < args.Length; i++)
503 Console.Write ("\n" + indent);
508 ((MExpression) args[i]).pp (indent);
512 private static object whileclause (object[] args, MPlist bindings)
516 while ((int) ((MExpression) args[0]).Eval (bindings) != 0)
517 for (int i = 1; i < args.Length; i++)
518 result = ((MExpression) args[i]).Eval (bindings);
522 private static void while_pp (MFunction func,
523 string indent, object[] args)
525 Console.Write ("(while ");
526 ((MExpression) args[0]).pp (indent + " ");
529 for (int i = 1; i < args.Length; i++)
533 Console.Write ("\n" + indent);
538 ((MExpression) args[i]).pp (indent);
542 private static object define_function (object[] args, MPlist bindings)
544 FunctionTable table = (FunctionTable) args[0];
545 MSymbol sym = (MSymbol) args[1];
546 MPlist arg_symbols = (MPlist) args[2];
547 int nargs = arg_symbols.Count;
548 object[] data = new object[args.Length - 2];
551 for (int i = 3; i < args.Length; i++)
552 data[i - 2] = args[i];
554 MFunction func = new MFunction (sym, null, nargs, nargs,
555 typeof (MExpression));
556 table.table[sym] = func;
561 private static void defun_pp (MFunction func,
562 string indent, object[] args)
564 Console.Write ("(defun " + args[1] + " " + args[2]);
567 for (int i = 3; i < args.Length; i++)
571 Console.Write ("\n" + indent);
576 ((MExpression) args[i]).pp (indent);
581 public class FunctionTable
583 internal Dictionary<MSymbol, MFunction> table
584 = new Dictionary<MSymbol, MFunction> ();
587 private static FunctionTable basic_table = new FunctionTable ();
589 public static void Defun (FunctionTable table, string name,
590 Evaluator evaluator, int min_arg, int max_arg,
591 params Type[] arg_types)
593 MFunction func = Defun (name, evaluator, min_arg, max_arg, arg_types);
594 table.table[func.name] = func;
597 private static MFunction Defun (string name, Evaluator evaluator,
598 int min_arg, int max_arg,
599 params Type[] arg_types)
601 MSymbol sym = MSymbol.Of (name);
602 MFunction func = new MFunction (sym, evaluator, min_arg, max_arg,
604 basic_table.table[sym] = func;
608 private static MFunction Defun (string name, Evaluator evaluator,
609 int min_arg, int max_arg)
611 return Defun (name, evaluator, min_arg, max_arg, typeof (MExpression));
614 private static MFunction Find (MSymbol name, FunctionTable table)
616 if (name == MSymbol.integer
617 || name == MSymbol.mtext)
618 return MFunction.literal;
622 || ! table.table.TryGetValue (name, out func))
623 && ! basic_table.table.TryGetValue (name, out func))
628 private void invalid_expression (object o)
630 throw new Exception ("Invalid expresssion: " + o);
633 private void invalid_argument (object o)
635 throw new Exception ("Invalid argument: " + o);
638 private MFunction function;
639 private object[] args;
641 public MExpression (MSymbol function_name, object[] args,
642 FunctionTable function_table)
644 function = Find (function_name, function_table);
645 int nargs = args.Length;
646 if (nargs < function.min_arg
647 || (function.max_arg >= 0 && nargs > function.max_arg))
648 throw new Exception ("Invalid number of arguments: " + args);
649 this.args = (object[]) args.Clone ();
652 private MExpression[] expression_list (MPlist plist, FunctionTable table)
654 int len = plist.Count;
655 MExpression[] expr_list = new MExpression[len];
657 for (int i = 0; i < len; i++, plist = plist.next)
660 expr_list[i] = new MExpression (plist.Symbol);
661 else if (plist.IsMText || plist.IsInteger)
662 expr_list[i] = new MExpression (plist.val);
663 else if (plist.IsPlist)
665 MPlist p = plist.Plist;
667 expr_list[i] = new MExpression (p.Symbol, p.next, table);
669 expr_list[i] = new MExpression (p, table);
672 invalid_expression (plist.val);
677 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
678 // FUNCALL = '(' SYMBOL EXPR* ')'
679 // EXPRLIST = '(' EXPR* ')'
681 // EXPRLIST: PLIST = EXPR ...
682 public MExpression (MPlist plist, FunctionTable table)
684 function = MFunction.block;
685 args = expression_list (plist, table);
688 // FUNCALL: NAME = FUNCTION-NAME, ARG-LIST = EXPR ...
689 private MExpression (MSymbol name, MPlist arg_list, FunctionTable table)
691 function = Find (name, table);
692 if (function == null)
693 throw new Exception ("Unknown function: " + name);
695 int nargs = arg_list.Count;
696 if (nargs < function.min_arg
697 || (function.max_arg >= 0 && nargs > function.max_arg))
698 throw new Exception ("Invalid number of arguments: " + nargs);
701 Type arg_type = typeof (MExpression);
702 if (function.arg_types.Length > 0)
704 arg_type = function.arg_types[0];
705 if (arg_type == typeof (FunctionTable))
708 args = new object[nargs];
712 args = new object[nargs];
715 args = new object[nargs];
717 foreach (MPlist p in arg_list)
719 if (i < function.arg_types.Length)
720 arg_type = function.arg_types[i];
721 if (arg_type == typeof (MExpression))
724 args[i++] = new MExpression (p.Symbol);
725 else if (p.IsMText || p.IsInteger)
726 args[i++] = new MExpression (p.val);
731 args[i++] = new MExpression (p0.Symbol, p0.next, table);
733 args[i++] = new MExpression (p0, table);
736 invalid_expression (p.val);
738 else if (arg_type == typeof (MExpression[]))
741 invalid_argument (p.val);
742 args[i++] = expression_list (p.Plist, table);
744 else if (arg_type == typeof (MSymbol))
747 invalid_argument (p.val);
748 args[i++] = p.Symbol;
753 if (function == MFunction.defun)
754 function.Call (args, null);
757 public MExpression (MSymbol sym)
759 function = MFunction.varref;
760 args = new object[1];
764 public MExpression (object obj)
766 function = MFunction.literal;
767 args = new object[1];
771 public object Eval (MPlist bindings)
773 return function.Call (args, bindings);
776 private void pp (string indent)
778 if (function == MFunction.varref
779 || function == MFunction.literal)
781 if (args[0] is MText)
782 Console.Write ("\"{0}\"", args[0]);
784 Console.Write (args[0]);
787 function.pp (function, indent, args);
790 public void PrettyPrint () { pp (""); }