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 (Function func,
15 string indent, object[] args);
17 internal class Function
19 internal readonly MSymbol name;
20 internal readonly Evaluator eval;
21 internal readonly int min_arg;
22 internal readonly int max_arg;
23 internal readonly 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 Function literal, varref, block, defun;
32 public Function (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 (Function func,
137 string indent, object[] args)
139 Console.Write ("(" + func.name);
141 foreach (MExpression o in args)
149 private static void set_pp (Function 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 (Function func,
428 string indent, object[] args)
434 foreach (MExpression e in args)
439 Console.Write ("\n" + indent);
445 private static bool check_condition (MExpression e, MPlist bindings)
447 object result = e.Eval (bindings);
448 return (! (result is int) || (int) result != 0);
451 private static object cond (object[] args, MPlist bindings)
453 foreach (MExpression[] elist in args)
454 if (check_condition (elist[0], bindings))
457 for (int i = 1; i < elist.Length; i++)
458 result = elist[i].Eval (bindings);
464 private static void cond_pp (Function func,
465 string indent, object[] args)
467 Console.Write ("(cond");
469 foreach (MExpression[] expr_list in args)
471 Console.Write ("\n" + indent + "(");
473 foreach (MExpression e in expr_list)
486 private static object ifclause (object[] args, MPlist bindings)
490 if (check_condition ((MExpression) args[0], bindings))
491 result = ((MExpression) args[1]).Eval (bindings);
493 for (int i = 2; i < args.Length; i++)
494 result = ((MExpression) args[i]).Eval (bindings);
498 private static void if_pp (Function func,
499 string indent, object[] args)
501 Console.Write ("(if ");
502 ((MExpression) args[0]).pp (indent + " ");
503 Console.Write ("\n" + indent + " ");
504 ((MExpression) args[1]).pp (indent + " ");
506 for (int i = 2; i < args.Length; i++)
508 Console.Write ("\n" + indent);
509 ((MExpression) args[i]).pp (indent);
514 private static object whileclause (object[] args, MPlist bindings)
518 while (check_condition ((MExpression) args[0], bindings))
519 for (int i = 1; i < args.Length; i++)
520 result = ((MExpression) args[i]).Eval (bindings);
524 private static void while_pp (Function func,
525 string indent, object[] args)
527 Console.Write ("(while ");
528 ((MExpression) args[0]).pp (indent + " ");
531 for (int i = 1; i < args.Length; i++)
535 Console.Write ("\n" + indent);
540 ((MExpression) args[i]).pp (indent);
545 private static object define_function (object[] args, MPlist bindings)
547 FunctionTable table = (FunctionTable) args[0];
548 MSymbol sym = (MSymbol) args[1];
549 MPlist arg_symbols = (MPlist) args[2];
550 int nargs = arg_symbols.Count;
551 object[] data = new object[args.Length - 2];
554 for (int i = 3; i < args.Length; i++)
555 data[i - 2] = args[i];
557 Function func = new Function (sym, null, nargs, nargs,
558 typeof (MExpression));
559 table.table[sym] = func;
564 private static void defun_pp (Function func,
565 string indent, object[] args)
567 Console.Write ("(defun " + args[1] + " " + args[2]);
570 for (int i = 3; i < args.Length; i++)
574 Console.Write ("\n" + indent);
579 ((MExpression) args[i]).pp (indent);
585 public class FunctionTable
587 internal Dictionary<MSymbol, Function> table
588 = new Dictionary<MSymbol, Function> ();
591 private static FunctionTable basic_table = new FunctionTable ();
593 public static void Defun (FunctionTable table, string name,
594 Evaluator evaluator, int min_arg, int max_arg,
595 params Type[] arg_types)
597 Function func = Defun (name, evaluator, min_arg, max_arg, arg_types);
598 table.table[func.name] = func;
601 private static Function Defun (string name, Evaluator evaluator,
602 int min_arg, int max_arg,
603 params Type[] arg_types)
605 MSymbol sym = MSymbol.Of (name);
606 Function func = new Function (sym, evaluator, min_arg, max_arg,
608 basic_table.table[sym] = func;
612 private static Function Defun (string name, Evaluator evaluator,
613 int min_arg, int max_arg)
615 return Defun (name, evaluator, min_arg, max_arg, typeof (MExpression));
618 private static Function Find (MSymbol name, FunctionTable table)
620 if (name == MSymbol.integer
621 || name == MSymbol.mtext)
622 return Function.literal;
626 || ! table.table.TryGetValue (name, out func))
627 && ! basic_table.table.TryGetValue (name, out func))
632 private void invalid_expression (object o)
634 throw new Exception ("Invalid expresssion: " + o);
637 private void invalid_argument (object o)
639 throw new Exception (String.Format ("Invalid argument to {0}: {1}",
643 private Function function;
644 private object[] args;
646 public MExpression (MSymbol function_name, object[] args,
647 FunctionTable function_table)
649 function = Find (function_name, function_table);
650 int nargs = args.Length;
651 if (nargs < function.min_arg
652 || (function.max_arg >= 0 && nargs > function.max_arg))
653 throw new Exception (String.Format ("Invalid number of arguments to {0}: {1}", function.name, nargs));
654 this.args = (object[]) args.Clone ();
657 private MExpression[] expression_list (MPlist plist, FunctionTable table)
659 int len = plist.Count;
660 MExpression[] expr_list = new MExpression[len];
662 for (int i = 0; i < len; i++, plist = plist.next)
665 expr_list[i] = new MExpression (plist.Symbol);
666 else if (plist.IsMText || plist.IsInteger)
667 expr_list[i] = new MExpression (plist.val);
668 else if (plist.IsPlist)
670 MPlist p = plist.Plist;
672 expr_list[i] = new MExpression (p.Symbol, p.next, table);
674 expr_list[i] = new MExpression (p, table);
677 invalid_expression (plist.val);
682 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
683 // FUNCALL = '(' SYMBOL EXPR* ')'
684 // EXPRLIST = '(' EXPR* ')'
686 // EXPRLIST: PLIST = EXPR ...
687 public MExpression (MPlist plist, FunctionTable table)
689 function = Function.block;
690 args = expression_list (plist, table);
693 // FUNCALL: NAME = FUNCTION-NAME, ARG-LIST = EXPR ...
694 private MExpression (MSymbol name, MPlist arg_list, FunctionTable table)
696 function = Find (name, table);
697 if (function == null)
698 throw new Exception ("Unknown function: " + name);
700 int nargs = arg_list.Count;
701 if (nargs < function.min_arg
702 || (function.max_arg >= 0 && nargs > function.max_arg))
703 throw new Exception (String.Format
704 ("Invalid number of arguments to {0}: {1}",
705 function.name, nargs));
708 Type arg_type = typeof (MExpression);
709 if (function.arg_types.Length > 0)
711 arg_type = function.arg_types[0];
712 if (arg_type == typeof (FunctionTable))
715 args = new object[nargs];
719 args = new object[nargs];
722 args = new object[nargs];
724 foreach (MPlist p in arg_list)
726 if (i < function.arg_types.Length)
727 arg_type = function.arg_types[i];
728 if (arg_type == typeof (MExpression))
731 args[i++] = new MExpression (p.Symbol);
732 else if (p.IsMText || p.IsInteger)
733 args[i++] = new MExpression (p.val);
738 args[i++] = new MExpression (p0.Symbol, p0.next, table);
740 args[i++] = new MExpression (p0, table);
743 invalid_expression (p.val);
745 else if (arg_type == typeof (MExpression[]))
748 invalid_argument (p.val);
749 args[i++] = expression_list (p.Plist, table);
751 else if (arg_type == typeof (MSymbol))
754 invalid_argument (p.val);
755 args[i++] = p.Symbol;
760 if (function == Function.defun)
761 function.Call (args, null);
764 public MExpression (MSymbol sym)
766 function = Function.varref;
767 args = new object[1];
771 public MExpression (object obj)
773 function = Function.literal;
774 args = new object[1];
778 public object Eval (MPlist bindings)
780 return function.Call (args, bindings);
783 private void pp (string indent)
785 if (function == Function.varref
786 || function == Function.literal)
788 if (args[0] is MText)
789 Console.Write ("\"{0}\"", args[0]);
791 Console.Write (args[0]);
794 function.pp (function, indent, args);
797 public void PrettyPrint () { pp (""); }