2 using System.Collections;
3 using System.Collections.Generic;
10 public class MExpression
12 public delegate object Evaluator (object[] args, MPlist bindings,
15 internal delegate void PrettyPrinter (Function func,
16 string indent, object[] args);
25 internal class Function
27 internal readonly MSymbol name;
28 internal readonly Evaluator eval;
29 internal readonly int min_arg;
30 internal readonly ArgType arg_type;
31 internal object[] data;
33 public PrettyPrinter pp;
35 private static PrettyPrinter default_pretty_printer;
36 private static PrettyPrinter set_pretty_printer;
37 internal static Function literal, varref, block, defun;
39 public Function (MSymbol name, Evaluator eval,
40 int min_arg, enum ArgType arg_type)
44 this.min_arg = min_arg;
45 this.arg_type = arg_type;
46 if (min_arg == 2 && arg_type = ArgType.FIXED)
47 pp = set_pretty_printer;
49 pp = default_pretty_printer;
54 default_pretty_printer = new PrettyPrinter (default_pp);
55 set_pretty_printer = new PrettyPrinter (set_pp);
56 literal = Defun ("nil", null, 1, 1);
57 varref = Defun ("symbol", new Evaluator (get_value), 1, 1);
58 block = Defun ("plist", new Evaluator (progn), 1, -1);
60 Defun ("set", new Evaluator (set_value), 2, 2,
61 typeof (MSymbol), typeof (MExpression));
62 Defun ("=", new Evaluator (set_value), 2, 2,
63 typeof (MSymbol), typeof (MExpression));
64 Defun ("+", new Evaluator (plus), 1, -1);
65 Defun ("*", new Evaluator (multi), 2, -1);
66 Defun ("-", new Evaluator (minus), 1, -1);
67 Defun ("/", new Evaluator (divide), 2, -1);
68 Defun ("%", new Evaluator (percent), 2, -1);
69 Defun ("|", new Evaluator (logior), 2, -1);
70 Defun ("&", new Evaluator (logand), 2, -1);
71 Defun ("+=", new Evaluator (pluseq), 2, -1,
72 typeof (MSymbol), typeof (MExpression));
73 Defun ("*=", new Evaluator (multieq), 2, -1,
74 typeof (MSymbol), typeof (MExpression));
75 Defun ("-=", new Evaluator (minuseq), 2, -1,
76 typeof (MSymbol), typeof (MExpression));
77 Defun ("/=", new Evaluator (divideeq), 2, -1,
78 typeof (MSymbol), typeof (MExpression));
79 Defun ("%=", new Evaluator (percenteq), 2, -1,
80 typeof (MSymbol), typeof (MExpression));
81 Defun ("|=", new Evaluator (logioreq), 2, -1,
82 typeof (MSymbol), typeof (MExpression));
83 Defun ("&=", new Evaluator (logandeq), 2, -1,
84 typeof (MSymbol), typeof (MExpression));
85 Defun ("<<", new Evaluator (lshift), 2, 2);
86 Defun (">>", new Evaluator (rshift), 2, 2);
87 Defun ("<<=", new Evaluator (lshifteq), 2, 2,
88 typeof (MSymbol), typeof (MExpression));
89 Defun (">>=", new Evaluator (rshifteq), 2, 2,
90 typeof (MSymbol), typeof (MExpression));
91 Defun ("==", new Evaluator (eq), 2, -1);
92 Defun ("!=", new Evaluator (noteq), 2, 2);
93 Defun ("<", new Evaluator (less), 2, -1);
94 Defun ("<=", new Evaluator (lesseq), 2, -1);
95 Defun (">", new Evaluator (more), 2, -1);
96 Defun (">=", new Evaluator (moreeq), 2, -1);
97 block = Defun ("progn", new Evaluator (progn), 1, -1);
98 block.pp = new PrettyPrinter (block_pp);
99 Defun ("cond", new Evaluator (cond), 1, -1,
100 typeof (MExpression[])).pp = new PrettyPrinter (cond_pp);
101 Defun ("if", new Evaluator (ifclause), 2, -1,
102 typeof (MExpression)).pp = new PrettyPrinter (if_pp);
103 Defun ("while", new Evaluator (whileclause), 1, -1,
104 typeof (MExpression)).pp = new PrettyPrinter (while_pp);
105 defun = Defun ("defun", new Evaluator (define_function), 4, -1,
106 typeof (FunctionTable),
109 typeof (MExpression));
110 defun.pp = new PrettyPrinter (defun_pp);
113 private static MPlist find_binding (object[] args, MPlist bindings)
115 MSymbol var = (MSymbol) args[0];
116 MPlist slot = bindings.Find (var);
119 throw new Exception ("Unbound variable: " + var);
123 public object Call (object[] args, MPlist bindings, object context)
125 if (name == MSymbol.nil)
128 return eval (args, bindings, context);
130 MPlist arg_symbols = (MPlist) data[0];
131 for (int i = 0; i < args.Length; i++, arg_symbols = arg_symbols.next)
132 bindings = bindings.Cons (arg_symbols.Symbol,
133 ((MExpression) args[i]).Eval (bindings,
136 for (int i = 1; i < data.Length; i++)
137 result = ((MExpression) data[i]).Eval (bindings, context);
141 // Commonly used pretty-printers.
143 public static void default_pp (Function func,
144 string indent, object[] args)
146 Console.Write ("(" + func.name);
148 foreach (object o in args)
151 if (o is MExpression)
152 ((MExpression) o).pp (indent);
159 private static void set_pp (Function func, string indent, object[] args)
161 Console.Write ("(" + func.name + " " + (MSymbol) args[0] + " ");
162 ((MExpression) args[1]).pp (indent);
166 private static object get_value (object[] args, MPlist bindings,
169 return find_binding (args, bindings).val;
172 private static object set_value (object[] args, MPlist bindings,
175 MSymbol var = (MSymbol) args[0];
176 MPlist slot = bindings.Find (var);
179 slot = bindings.Push (var, null);
180 slot.val = ((MExpression) args[1]).Eval (bindings, context);
181 if (slot.val is MText)
182 slot.val = ((MText) slot.val).Dup ();
186 private static object plus (object[] args, MPlist bindings,
189 object val = ((MExpression) args[0]).Eval (bindings, context);
194 foreach (MExpression e in args)
195 n += (int) e.Eval (bindings, context);
198 else if (val is MText)
200 MText mt = new MText ();
201 foreach (MExpression e in args)
202 mt += (MText) e.Eval (bindings, context);
208 private static object multi (object[] args, MPlist bindings,
212 foreach (MExpression e in args)
213 n *= (int) e.Eval (bindings, context);
217 private static object minus (object[] args, MPlist bindings,
220 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
221 if (args.Length == 1)
223 for (int i = 1; i < args.Length; i++)
224 n -= (int) ((MExpression) args[i]).Eval (bindings, context);
228 private static object divide (object[] args, MPlist bindings,
231 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
232 for (int i = 1; i < args.Length; i++)
233 n /= (int) ((MExpression) args[i]).Eval (bindings, context);
237 private static object percent (object[] args, MPlist bindings,
240 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
241 for (int i = 1; i < args.Length; i++)
242 n %= (int) ((MExpression) args[i]).Eval (bindings, context);
246 private static object logior (object[] args, MPlist bindings,
249 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
250 for (int i = 1; i < args.Length; i++)
251 n |= (int) ((MExpression) args[i]).Eval (bindings, context);
255 private static object logand (object[] args, MPlist bindings,
258 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
259 for (int i = 1; i < args.Length; i++)
260 n &= (int) ((MExpression) args[i]).Eval (bindings, context);
264 private static object pluseq (object[] args, MPlist bindings,
267 MPlist slot = find_binding (args, bindings);
268 object val = slot.val;
273 for (int i = 1; i < args.Length; i++)
274 n += (int) ((MExpression) args[i]).Eval (bindings, context);
277 else if (val is MText)
279 MText mt = (MText) val;
280 for (int i = 1; i < args.Length; i++)
281 mt.Cat ((MText) ((MExpression) args[i]).Eval (bindings, context));
286 private static object multieq (object[] args, MPlist bindings,
289 MPlist slot = find_binding (args, bindings);
290 int n = (int) slot.val;
291 for (int i = 1; i < args.Length; i++)
292 n *= (int) ((MExpression) args[i]).Eval (bindings, context);
293 return (slot.val = n);
296 private static object minuseq (object[] args, MPlist bindings,
299 MPlist slot = find_binding (args, bindings);
300 int n = (int) slot.val;
301 for (int i = 1; i < args.Length; i++)
302 n -= (int) ((MExpression) args[i]).Eval (bindings, context);
303 return (slot.val = n);
306 private static object divideeq (object[] args, MPlist bindings,
309 MPlist slot = find_binding (args, bindings);
310 int n = (int) slot.val;
311 for (int i = 1; i < args.Length; i++)
312 n /= (int) ((MExpression) args[i]).Eval (bindings, context);
313 return (slot.val = n);
316 private static object percenteq (object[] args, MPlist bindings,
319 MPlist slot = find_binding (args, bindings);
320 int n = (int) slot.val;
321 for (int i = 1; i < args.Length; i++)
322 n %= (int) ((MExpression) args[i]).Eval (bindings, context);
323 return (slot.val = n);
326 private static object logioreq (object[] args, MPlist bindings,
329 MPlist slot = find_binding (args, bindings);
330 int n = (int) slot.val;
331 for (int i = 1; i < args.Length; i++)
332 n |= (int) ((MExpression) args[i]).Eval (bindings, context);
333 return (slot.val = n);
336 private static object logandeq (object[] args, MPlist bindings,
339 MPlist slot = find_binding (args, bindings);
340 int n = (int) slot.val;
341 for (int i = 1; i < args.Length; i++)
342 n &= (int) ((MExpression) args[i]).Eval (bindings, context);
343 return (slot.val = n);
346 private static object lshift (object[] args, MPlist bindings,
349 int n1 = (int) ((MExpression) args[0]).Eval (bindings, context);
350 int n2 = (int) ((MExpression) args[1]).Eval (bindings, context);
354 private static object lshifteq (object[] args, MPlist bindings,
357 MPlist slot = find_binding (args, bindings);
358 int n1 = (int) slot.val;
359 int n2 = (int) ((MExpression) args[1]).Eval (bindings, context);
360 return (slot.val = (n1 << n2));
363 private static object rshift (object[] args, MPlist bindings,
366 int n1 = (int) ((MExpression) args[0]).Eval (bindings, context);
367 int n2 = (int) ((MExpression) args[1]).Eval (bindings, context);
371 private static object rshifteq (object[] args, MPlist bindings,
374 MPlist slot = find_binding (args, bindings);
375 int n1 = (int) slot.val;
376 int n2 = (int) ((MExpression) args[1]).Eval (bindings, context);
377 return (slot.val = (n1 >> n2));
380 private static object eq (object[] args, MPlist bindings,
383 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
384 for (int i = 1; i < args.Length; i++)
385 if (n != (int) ((MExpression) args[i]).Eval (bindings, context))
390 private static object noteq (object[] args, MPlist bindings,
393 int n1 = (int) ((MExpression) args[0]).Eval (bindings, context);
394 int n2 = (int) ((MExpression) args[1]).Eval (bindings, context);
398 private static object less (object[] args, MPlist bindings,
401 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
402 for (int i = 1; i < args.Length; i++)
404 int n1 = (int) ((MExpression) args[i]).Eval (bindings, context);
412 private static object lesseq (object[] args, MPlist bindings,
415 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
416 for (int i = 1; i < args.Length; i++)
418 int n1 = (int) ((MExpression) args[i]).Eval (bindings, context);
426 private static object more (object[] args, MPlist bindings,
429 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
430 for (int i = 1; i < args.Length; i++)
432 int n1 = (int) ((MExpression) args[i]).Eval (bindings, context);
440 private static object moreeq (object[] args, MPlist bindings,
443 int n = (int) ((MExpression) args[0]).Eval (bindings, context);
444 for (int i = 1; i < args.Length; i++)
446 int n1 = (int) ((MExpression) args[i]).Eval (bindings, context);
454 private static object progn (object[] args, MPlist bindings,
457 object result = null;
459 foreach (MExpression e in args)
460 result = e.Eval (bindings, context);
464 private static void block_pp (Function func,
465 string indent, object[] args)
471 foreach (MExpression e in args)
476 Console.Write ("\n" + indent);
482 private static bool check_condition (MExpression e, MPlist bindings,
485 object result = e.Eval (bindings, context);
486 return (! (result is int) || (int) result != 0);
489 private static object cond (object[] args, MPlist bindings,
492 foreach (MExpression[] elist in args)
493 if (check_condition (elist[0], bindings, context))
496 for (int i = 1; i < elist.Length; i++)
497 result = elist[i].Eval (bindings, context);
503 private static void cond_pp (Function func,
504 string indent, object[] args)
506 Console.Write ("(cond");
508 foreach (MExpression[] expr_list in args)
510 Console.Write ("\n" + indent + "(");
512 foreach (MExpression e in expr_list)
525 private static object ifclause (object[] args, MPlist bindings,
530 if (check_condition ((MExpression) args[0], bindings, context))
531 result = ((MExpression) args[1]).Eval (bindings, context);
533 for (int i = 2; i < args.Length; i++)
534 result = ((MExpression) args[i]).Eval (bindings, context);
538 private static void if_pp (Function func,
539 string indent, object[] args)
541 Console.Write ("(if ");
542 ((MExpression) args[0]).pp (indent + " ");
543 Console.Write ("\n" + indent + " ");
544 ((MExpression) args[1]).pp (indent + " ");
546 for (int i = 2; i < args.Length; i++)
548 Console.Write ("\n" + indent);
549 ((MExpression) args[i]).pp (indent);
554 private static object whileclause (object[] args, MPlist bindings,
559 while (check_condition ((MExpression) args[0], bindings, context))
560 for (int i = 1; i < args.Length; i++)
561 result = ((MExpression) args[i]).Eval (bindings, context);
565 private static void while_pp (Function func,
566 string indent, object[] args)
568 Console.Write ("(while ");
569 ((MExpression) args[0]).pp (indent + " ");
572 for (int i = 1; i < args.Length; i++)
576 Console.Write ("\n" + indent);
581 ((MExpression) args[i]).pp (indent);
586 public static object define_function (object[] args, MPlist bindings,
589 FunctionTable table = (FunctionTable) args[0];
590 MSymbol sym = (MSymbol) args[1];
591 MPlist arg_symbols = (MPlist) args[2];
592 int nargs = arg_symbols.Count;
593 object[] data = new object[args.Length - 2];
596 for (int i = 3; i < args.Length; i++)
597 data[i - 2] = args[i];
599 Function func = new Function (sym, null, nargs, nargs,
600 typeof (MExpression));
601 table.table[sym] = func;
606 private static void defun_pp (Function func,
607 string indent, object[] args)
609 Console.Write ("(defun " + args[1] + " " + args[2]);
612 for (int i = 3; i < args.Length; i++)
616 Console.Write ("\n" + indent);
621 ((MExpression) args[i]).pp (indent);
627 public class FunctionTable
629 internal Dictionary<MSymbol, Function> table;
631 public FunctionTable ()
633 table = new Dictionary<MSymbol, Function> ();
636 public FunctionTable (FunctionTable table)
638 this.table = new Dictionary<MSymbol, Function> (table.table);
641 public void Copy (FunctionTable table)
643 foreach (KeyValuePair<MSymbol, Function> kv in this.table)
644 table.table[kv.Key] = kv.Value;
647 public void Copy (MSymbol name, FunctionTable table)
650 if (this.table.TryGetValue (name, out func))
651 table.table[name] = func;
655 private static FunctionTable basic_table = new FunctionTable ();
657 public static void Defun (FunctionTable table, string name,
658 Evaluator evaluator, int min_arg,
659 enum ArgType arg_type)
661 Function func = Defun (name, evaluator, min_arg, arg_type);
662 table.table[func.name] = func;
665 public static void Defmacro (FunctionTable table, MSymbol name,
668 object[] args = new object[4];
671 args[2] = new MPlist ();
673 Function.define_function (args, null, null);
676 private static Function Defun (string name, Evaluator evaluator,
677 int min_arg, enum ArgType arg_type)
679 MSymbol sym = MSymbol.Of (name);
680 Function func = new Function (sym, evaluator, min_arg, arg_type);
681 basic_table.table[sym] = func;
685 private static Function Defun (string name, Evaluator evaluator,
686 int min_arg, enum ArgType arg_type)
688 return Defun (name, evaluator, min_arg, arg_type, typeof (MExpression));
691 private static Function Find (MSymbol name, FunctionTable table)
693 if (name == MSymbol.integer
694 || name == MSymbol.mtext)
695 return Function.literal;
699 || ! table.table.TryGetValue (name, out func))
700 && ! basic_table.table.TryGetValue (name, out func))
705 private static void invalid_expression (object o)
707 throw new Exception ("Invalid expresssion: " + o);
710 private void invalid_argument (object o)
712 throw new Exception (String.Format ("Invalid argument to {0}: {1}",
716 private Function function;
717 private object[] args;
719 public MExpression (MSymbol function_name, object[] args,
720 FunctionTable function_table)
722 function = Find (function_name, function_table);
723 int nargs = args.Length;
724 if (nargs < function.min_arg
725 || (function.max_arg >= 0 && nargs > function.max_arg))
726 throw new Exception (String.Format ("Invalid number of arguments to {0}: {1}", function.name, nargs));
727 this.args = (object[]) args.Clone ();
730 private static MExpression[] expression_list (MPlist plist,
733 int len = plist.Count;
734 MExpression[] expr_list = new MExpression[len];
736 for (int i = 0; i < len; i++, plist = plist.next)
739 expr_list[i] = new MExpression (plist.Symbol);
740 else if (plist.IsMText || plist.IsInteger)
741 expr_list[i] = new MExpression (plist.val);
742 else if (plist.IsPlist)
744 MPlist p = plist.Plist;
746 expr_list[i] = new MExpression (p.Symbol, p.next, table);
748 expr_list[i] = new MExpression (p, table);
751 invalid_expression (plist.val);
756 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
757 // FUNCALL = '(' SYMBOL EXPR* ')'
758 // EXPRLIST = '(' EXPR* ')'
760 // EXPRLIST: PLIST = EXPR ...
761 public MExpression (MPlist plist, FunctionTable table)
763 function = Function.block;
764 args = expression_list (plist, table);
767 // FUNCALL: NAME = FUNCTION-NAME, ARG-LIST = EXPR ...
768 private MExpression (MSymbol name, MPlist arg_list, FunctionTable table)
770 function = Find (name, table);
771 if (function == null)
772 throw new Exception ("Unknown function: " + name);
774 int nargs = arg_list.Count;
775 if (nargs < function.min_arg
776 || (function.max_arg >= 0 && nargs > function.max_arg))
777 throw new Exception (String.Format
778 ("Invalid number of arguments to {0}: {1}",
779 function.name, nargs));
782 Type arg_type = typeof (MExpression);
783 if (function.arg_types.Length > 0)
785 arg_type = function.arg_types[0];
786 if (arg_type == typeof (FunctionTable))
789 args = new object[nargs];
793 args = new object[nargs];
796 args = new object[nargs];
798 foreach (MPlist p in arg_list)
800 if (i < function.arg_types.Length)
801 arg_type = function.arg_types[i];
802 if (arg_type == typeof (MExpression))
805 args[i++] = new MExpression (p.Symbol);
806 else if (p.IsMText || p.IsInteger)
807 args[i++] = new MExpression (p.val);
812 args[i++] = new MExpression (p0.Symbol, p0.next, table);
814 args[i++] = new MExpression (p0, table);
817 invalid_expression (p.val);
819 else if (arg_type == typeof (MExpression[]))
822 invalid_argument (p.val);
823 args[i++] = expression_list (p.Plist, table);
825 else if (arg_type == typeof (MSymbol))
828 invalid_argument (p.val);
829 args[i++] = p.Symbol;
834 if (function == Function.defun)
835 function.Call (args, null, null);
838 public MExpression (MSymbol sym)
840 function = Function.varref;
841 args = new object[1];
845 public MExpression (object obj)
847 function = Function.literal;
848 args = new object[1];
852 public object Eval (MPlist bindings, object context)
854 return function.Call (args, bindings, context);
857 private void pp (string indent)
859 if (function == Function.varref
860 || function == Function.literal)
862 if (args[0] is MText)
863 Console.Write ("\"{0}\"", args[0]);
865 Console.Write (args[0]);
868 function.pp (function, indent, args);
871 public void PrettyPrint () { pp (""); }