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 PretyPrinter (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;
25 public PretyPrinter pp;
27 private static PretyPrinter default_prety_printer;
28 private static PretyPrinter set_prety_printer;
29 internal static MFunction literal, varref, block;
31 public MFunction (MSymbol name, Evaluator eval,
32 int min_arg, int max_arg, Type[] arg_types)
36 this.min_arg = min_arg;
37 this.max_arg = max_arg;
38 this.arg_types = (Type []) arg_types.Clone ();
39 if (arg_types.Length == 2 && arg_types[0] == typeof (MSymbol))
40 pp = set_prety_printer;
42 pp = default_prety_printer;
47 default_prety_printer = new PretyPrinter (default_pp);
48 set_prety_printer = new PretyPrinter (set_pp);
49 literal = Defun ("nil", null, 1, 1);
50 varref = Defun ("symbol", new Evaluator (get_value), 1, 1);
51 block = Defun ("plist", new Evaluator (progn), 1, -1);
53 Defun ("set", new Evaluator (set_value), 2, 2,
54 typeof (MSymbol), typeof (MExpression));
55 Defun ("=", new Evaluator (set_value), 2, 2,
56 typeof (MSymbol), typeof (MExpression));
57 Defun ("+", new Evaluator (plus), 1, -1);
58 Defun ("*", new Evaluator (multi), 2, -1);
59 Defun ("-", new Evaluator (minus), 1, -1);
60 Defun ("/", new Evaluator (divide), 2, -1);
61 Defun ("%", new Evaluator (percent), 2, -1);
62 Defun ("|", new Evaluator (logior), 2, -1);
63 Defun ("&", new Evaluator (logand), 2, -1);
64 Defun ("+=", new Evaluator (pluseq), 2, -1,
65 typeof (MSymbol), typeof (MExpression));
66 Defun ("*=", new Evaluator (multieq), 2, -1,
67 typeof (MSymbol), typeof (MExpression));
68 Defun ("-=", new Evaluator (minuseq), 2, -1,
69 typeof (MSymbol), typeof (MExpression));
70 Defun ("/=", new Evaluator (divideeq), 2, -1,
71 typeof (MSymbol), typeof (MExpression));
72 Defun ("%=", new Evaluator (percenteq), 2, -1,
73 typeof (MSymbol), typeof (MExpression));
74 Defun ("|=", new Evaluator (logioreq), 2, -1,
75 typeof (MSymbol), typeof (MExpression));
76 Defun ("&=", new Evaluator (logandeq), 2, -1,
77 typeof (MSymbol), typeof (MExpression));
78 Defun ("<<", new Evaluator (lshift), 2, 2);
79 Defun (">>", new Evaluator (rshift), 2, 2);
80 Defun ("<<=", new Evaluator (lshifteq), 2, 2,
81 typeof (MSymbol), typeof (MExpression));
82 Defun (">>=", new Evaluator (rshifteq), 2, 2,
83 typeof (MSymbol), typeof (MExpression));
84 Defun ("==", new Evaluator (eq), 2, -1);
85 Defun ("!=", new Evaluator (noteq), 2, 2);
86 Defun ("<", new Evaluator (less), 2, -1);
87 Defun ("<=", new Evaluator (lesseq), 2, -1);
88 Defun (">", new Evaluator (more), 2, -1);
89 Defun (">=", new Evaluator (moreeq), 2, -1);
90 block = Defun ("progn", new Evaluator (progn), 1, -1);
91 block.pp = new PretyPrinter (block_pp);
92 Defun ("cond", new Evaluator (cond), 1, -1,
93 typeof (MExpression[])).pp = new PretyPrinter (cond_pp);
94 Defun ("if", new Evaluator (ifclause), 2, -1,
95 typeof (MExpression)).pp = new PretyPrinter (if_pp);
96 Defun ("while", new Evaluator (whileclause), 1, -1,
97 typeof (MExpression)).pp = new PretyPrinter (while_pp);
100 public object Call (object[] args, MPlist bindings)
102 if (name == MSymbol.nil)
104 return eval (args, bindings);
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 static void default_pp (MFunction func,
118 string indent, object[] args)
120 Console.Write ("(" + func.name);
122 foreach (MExpression o in args)
130 private static object get_value (object[] args, MPlist bindings)
132 return find_binding (args, bindings).val;
135 private static object set_value (object[] args, MPlist bindings)
137 MSymbol var = (MSymbol) args[0];
138 MPlist slot = bindings.Find (var);
141 slot = bindings.Push (var, null);
142 slot.val = ((MExpression) args[1]).Eval (bindings);
143 if (slot.val is MText)
144 slot.val = ((MText) slot.val).Dup ();
148 private static void set_pp (MFunction func, string indent, object[] args)
150 Console.Write ("(set " + (MSymbol) args[0] + " ");
151 ((MExpression) args[1]).pp (indent);
155 private static object plus (object[] args, MPlist bindings)
157 object val = ((MExpression) args[0]).Eval (bindings);
162 foreach (MExpression e in args)
163 n += (int) e.Eval (bindings);
166 else if (val is MText)
168 MText mt = new MText ();
169 foreach (MExpression e in args)
170 mt += (MText) e.Eval (bindings);
176 private static object multi (object[] args, MPlist bindings)
179 foreach (MExpression e in args)
180 n *= (int) e.Eval (bindings);
184 private static object minus (object[] args, MPlist bindings)
186 int n = (int) ((MExpression) args[0]).Eval (bindings);
187 if (args.Length == 1)
189 for (int i = 1; i < args.Length; i++)
190 n -= (int) ((MExpression) args[i]).Eval (bindings);
194 private static object divide (object[] args, MPlist bindings)
196 int n = (int) ((MExpression) args[0]).Eval (bindings);
197 for (int i = 1; i < args.Length; i++)
198 n /= (int) ((MExpression) args[i]).Eval (bindings);
202 private static object percent (object[] args, MPlist bindings)
204 int n = (int) ((MExpression) args[0]).Eval (bindings);
205 for (int i = 1; i < args.Length; i++)
206 n %= (int) ((MExpression) args[i]).Eval (bindings);
210 private static object logior (object[] args, MPlist bindings)
212 int n = (int) ((MExpression) args[0]).Eval (bindings);
213 for (int i = 1; i < args.Length; i++)
214 n |= (int) ((MExpression) args[i]).Eval (bindings);
218 private static object logand (object[] args, MPlist bindings)
220 int n = (int) ((MExpression) args[0]).Eval (bindings);
221 for (int i = 1; i < args.Length; i++)
222 n &= (int) ((MExpression) args[i]).Eval (bindings);
226 private static object pluseq (object[] args, MPlist bindings)
228 MPlist slot = find_binding (args, bindings);
229 object val = slot.val;
234 for (int i = 1; i < args.Length; i++)
235 n += (int) ((MExpression) args[i]).Eval (bindings);
238 else if (val is MText)
240 MText mt = (MText) val;
241 for (int i = 1; i < args.Length; i++)
242 mt.Cat ((MText) ((MExpression) args[i]).Eval (bindings));
247 private static object multieq (object[] args, MPlist bindings)
249 MPlist slot = find_binding (args, bindings);
250 int n = (int) slot.val;
251 for (int i = 1; i < args.Length; i++)
252 n *= (int) ((MExpression) args[i]).Eval (bindings);
253 return (slot.val = n);
256 private static object minuseq (object[] args, MPlist bindings)
258 MPlist slot = find_binding (args, bindings);
259 int n = (int) slot.val;
260 for (int i = 1; i < args.Length; i++)
261 n -= (int) ((MExpression) args[i]).Eval (bindings);
262 return (slot.val = n);
265 private static object divideeq (object[] args, MPlist bindings)
267 MPlist slot = find_binding (args, bindings);
268 int n = (int) slot.val;
269 for (int i = 1; i < args.Length; i++)
270 n /= (int) ((MExpression) args[i]).Eval (bindings);
271 return (slot.val = n);
274 private static object percenteq (object[] args, MPlist bindings)
276 MPlist slot = find_binding (args, bindings);
277 int n = (int) slot.val;
278 for (int i = 1; i < args.Length; i++)
279 n %= (int) ((MExpression) args[i]).Eval (bindings);
280 return (slot.val = n);
283 private static object logioreq (object[] args, MPlist bindings)
285 MPlist slot = find_binding (args, bindings);
286 int n = (int) slot.val;
287 for (int i = 1; i < args.Length; i++)
288 n |= (int) ((MExpression) args[i]).Eval (bindings);
289 return (slot.val = n);
292 private static object logandeq (object[] args, MPlist bindings)
294 MPlist slot = find_binding (args, bindings);
295 int n = (int) slot.val;
296 for (int i = 1; i < args.Length; i++)
297 n &= (int) ((MExpression) args[i]).Eval (bindings);
298 return (slot.val = n);
301 private static object lshift (object[] args, MPlist bindings)
303 int n1 = (int) ((MExpression) args[0]).Eval (bindings);
304 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
308 private static object lshifteq (object[] args, MPlist bindings)
310 MPlist slot = find_binding (args, bindings);
311 int n1 = (int) slot.val;
312 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
313 return (slot.val = (n1 << n2));
316 private static object rshift (object[] args, MPlist bindings)
318 int n1 = (int) ((MExpression) args[0]).Eval (bindings);
319 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
323 private static object rshifteq (object[] args, MPlist bindings)
325 MPlist slot = find_binding (args, bindings);
326 int n1 = (int) slot.val;
327 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
328 return (slot.val = (n1 >> n2));
331 private static object eq (object[] args, MPlist bindings)
333 int n = (int) ((MExpression) args[0]).Eval (bindings);
334 for (int i = 1; i < args.Length; i++)
335 if (n != (int) ((MExpression) args[i]).Eval (bindings))
340 private static object noteq (object[] args, MPlist bindings)
342 int n1 = (int) ((MExpression) args[0]).Eval (bindings);
343 int n2 = (int) ((MExpression) args[1]).Eval (bindings);
347 private static object less (object[] args, MPlist bindings)
349 int n = (int) ((MExpression) args[0]).Eval (bindings);
350 for (int i = 1; i < args.Length; i++)
352 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
360 private static object lesseq (object[] args, MPlist bindings)
362 int n = (int) ((MExpression) args[0]).Eval (bindings);
363 for (int i = 1; i < args.Length; i++)
365 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
373 private static object more (object[] args, MPlist bindings)
375 int n = (int) ((MExpression) args[0]).Eval (bindings);
376 for (int i = 1; i < args.Length; i++)
378 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
386 private static object moreeq (object[] args, MPlist bindings)
388 int n = (int) ((MExpression) args[0]).Eval (bindings);
389 for (int i = 1; i < args.Length; i++)
391 int n1 = (int) ((MExpression) args[i]).Eval (bindings);
399 private static object progn (object[] args, MPlist bindings)
401 object result = null;
403 foreach (MExpression e in args)
404 result = e.Eval (bindings);
408 private static void block_pp (MFunction func,
409 string indent, object[] args)
415 foreach (MExpression e in args)
420 Console.Write ("\n" + indent);
426 private static object cond (object[] args, MPlist bindings)
428 foreach (MExpression[] elist in args)
430 int i = (int) elist[0].Eval (bindings);
432 return progn ((object[]) elist, bindings);
437 private static void cond_pp (MFunction func,
438 string indent, object[] args)
440 Console.Write ("(cond");
442 foreach (MExpression[] expr_list in args)
444 Console.Write ("\n" + indent + "(");
446 foreach (MExpression e in expr_list)
459 private static object ifclause (object[] args, MPlist bindings)
463 if ((int) ((MExpression) args[0]).Eval (bindings) != 0)
464 result = ((MExpression) args[1]).Eval (bindings);
466 for (int i = 2; i < args.Length; i++)
467 result = ((MExpression) args[i]).Eval (bindings);
471 private static void if_pp (MFunction func,
472 string indent, object[] args)
474 Console.Write ("(if ");
475 ((MExpression) args[0]).pp (indent + " ");
476 Console.Write ("\n" + indent + " ");
477 ((MExpression) args[1]).pp (indent + " ");
480 for (int i = 2; i < args.Length; i++)
484 Console.Write ("\n" + indent);
489 ((MExpression) args[i]).pp (indent);
493 private static object whileclause (object[] args, MPlist bindings)
497 while ((int) ((MExpression) args[0]).Eval (bindings) != 0)
498 for (int i = 1; i < args.Length; i++)
499 result = ((MExpression) args[i]).Eval (bindings);
503 private static void while_pp (MFunction func,
504 string indent, object[] args)
506 Console.Write ("(while ");
507 ((MExpression) args[0]).pp (indent + " ");
510 for (int i = 1; i < args.Length; i++)
514 Console.Write ("\n" + indent);
519 ((MExpression) args[i]).pp (indent);
524 public class FunctionTable
526 internal Dictionary<MSymbol, MFunction> table
527 = new Dictionary<MSymbol, MFunction> ();
530 private static FunctionTable basic_table = new FunctionTable ();
532 public static void Defun (FunctionTable table, string name,
533 Evaluator evaluator, int min_arg, int max_arg,
534 params Type[] arg_types)
536 MSymbol sym = MSymbol.Of (name);
537 MFunction func = new MFunction (sym, evaluator, min_arg, max_arg,
539 table.table[sym] = func;
542 private static MFunction Defun (string name, Evaluator evaluator,
543 int min_arg, int max_arg,
544 params Type[] arg_types)
546 MSymbol sym = MSymbol.Of (name);
547 MFunction func = new MFunction (sym, evaluator, min_arg, max_arg,
549 basic_table.table[sym] = func;
553 private static MFunction Defun (string name, Evaluator evaluator,
554 int min_arg, int max_arg)
556 return Defun (name, evaluator, min_arg, max_arg, typeof (MExpression));
559 private static MFunction Find (MSymbol name, FunctionTable table)
561 if (name == MSymbol.integer
562 || name == MSymbol.mtext)
563 return MFunction.literal;
567 || ! table.table.TryGetValue (name, out func))
568 && ! basic_table.table.TryGetValue (name, out func))
573 private void invalid_expression (object o)
575 throw new Exception ("Invalid expresssion: " + o);
578 private void invalid_argument (object o)
580 throw new Exception ("Invalid argument: " + o);
583 private MFunction function;
584 private object[] args;
586 public MExpression (MSymbol function_name, object[] args,
587 FunctionTable function_table)
589 function = Find (function_name, function_table);
590 int nargs = args.Length;
591 if (nargs < function.min_arg
592 || (function.max_arg >= 0 && nargs > function.max_arg))
593 throw new Exception ("Invalid number of arguments: " + args);
594 this.args = (object[]) args.Clone ();
597 private MExpression[] expression_list (MPlist plist, FunctionTable table)
599 int len = plist.Count;
600 MExpression[] expr_list = new MExpression[len];
602 for (int i = 0; i < len; i++, plist = plist.next)
605 expr_list[i] = new MExpression (plist.Symbol);
606 else if (plist.IsMText || plist.IsInteger)
607 expr_list[i] = new MExpression (plist.val);
608 else if (plist.IsPlist)
610 MPlist p = plist.Plist;
612 expr_list[i] = new MExpression (p.Symbol, p.next, table);
614 expr_list[i] = new MExpression (p, table);
617 invalid_expression (plist.val);
622 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
623 // FUNCALL = '(' SYMBOL EXPR* ')'
624 // EXPRLIST = '(' EXPR* ')'
626 // EXPRLIST: PLIST = EXPR ...
627 public MExpression (MPlist plist, FunctionTable table)
629 function = MFunction.block;
630 args = expression_list (plist, table);
633 // FUNCALL: NAME = FUNCTION-NAME, ARG-LIST = EXPR ...
634 private MExpression (MSymbol name, MPlist arg_list, FunctionTable table)
636 function = Find (name, table);
637 if (function == null)
638 throw new Exception ("Unknown function: " + name);
640 int nargs = arg_list.Count;
641 if (nargs < function.min_arg
642 || (function.max_arg >= 0 && nargs > function.max_arg))
643 throw new Exception ("Invalid number of arguments: " + nargs);
644 args = new object[nargs];
647 Type arg_type = typeof (MExpression);
648 foreach (MPlist p in arg_list)
650 if (i < function.arg_types.Length)
651 arg_type = function.arg_types[i];
652 if (arg_type == typeof (MExpression))
655 args[i++] = new MExpression (p.Symbol);
656 else if (p.IsMText || p.IsInteger)
657 args[i++] = new MExpression (p.val);
662 args[i++] = new MExpression (p0.Symbol, p0.next, table);
664 args[i++] = new MExpression (p0, table);
667 invalid_expression (p.val);
669 else if (arg_type == typeof (MExpression[]))
672 invalid_argument (p.val);
673 args[i++] = expression_list (p.Plist, table);
675 else if (arg_type == typeof (MSymbol))
678 invalid_argument (p.val);
679 args[i++] = p.Symbol;
686 public MExpression (MSymbol sym)
688 function = MFunction.varref;
689 args = new object[1];
693 public MExpression (object obj)
695 function = MFunction.literal;
696 args = new object[1];
700 public object Eval (MPlist bindings)
702 return function.Call (args, bindings);
705 private void pp (string indent)
707 if (function == MFunction.varref
708 || function == MFunction.literal)
710 if (args[0] is MText)
711 Console.Write ("\"{0}\"", args[0]);
713 Console.Write (args[0]);
716 function.pp (function, indent, args);
719 public void PretyPrint () { pp (""); }