2 using System.Collections;
3 using System.Collections.Generic;
7 namespace System.Xml.Expression
9 public class XmlName : IEquatable<XmlName>
11 private static NameTable nt = new NameTable ();
15 private XmlName (string str)
20 public static implicit operator XmlName (string str)
22 return new XmlName (str);
25 public static bool operator== (object obj, XmlName nam)
27 return obj == nam.name;
30 public static bool operator!= (object obj, XmlName nam)
32 return obj != nam.name;
35 public bool Equals (XmlName other) { return name == other.name; }
36 public override bool Equals (object obj) { return obj == name; }
37 public override int GetHashCode ()
39 return ((string) name).GetHashCode ();
42 public static NameTable Table { get { return nt; } }
47 private static NameTable nt = new NameTable ();
49 public static object Name (string str)
54 public static NameTable Table { get { return nt; } }
56 private static object Nvar = Name ("var");
57 private static object Ndefun = Name ("defun");
58 private static object Ncond = Name ("cond");
59 private static object Nprogn = Name ("progn");
60 private static object Nwhen = Name ("when");
64 private Domain parent;
65 internal Dictionary<object,functions = new MPlist ();
66 internal MPlist bindings = new MPlist ();
67 private Stack<MPlist> boundaries = new Stack<MPlist> ();
68 internal Translator translator;
69 public object context;
73 boundaries.Push (bindings);
76 public Domain (object context) : this (basic, context) { }
78 public Domain (Domain parent, object context)
81 this.context = context;
82 boundaries.Push (bindings);
85 public void AddTranslator (Translator translator)
87 if (this.translator == null)
88 this.translator = translator;
90 this.translator += translator;
93 public void Bind (MSymbol sym, object value)
95 bindings = bindings.Cons (sym, value);
98 public MPlist SetBoundary ()
100 boundaries.Push (bindings);
104 public void UnboundTo (MPlist boundary)
106 while (boundary != boundaries.Pop ());
107 while (bindings != boundary)
108 bindings = bindings.next;
111 public void Defun (string name, Builtin builtin, int min_arg, int max_arg)
113 Defun (name, builtin, min_arg, max_arg, false);
116 public void Defun (string name, Builtin builtin, int min_arg, int max_arg,
120 Function func = (Function) functions.Get (sym);
124 if (func.min_arg < min_arg || func.max_arg > max_arg)
125 throw new Exception ("Incompatible argument numbers to override: "
127 func.builtin = builtin;
129 func.min_arg = min_arg;
130 func.max_arg = max_arg;
131 func.specialp = specialp;
135 func = new Function (sym, builtin, min_arg, max_arg, specialp);
136 functions = functions.Cons (sym, func);
140 public void Defun (MSymbol sym, MPlist args, MPlist body)
142 Function func = (Function) functions.Get (sym);
146 int nargs = args == null ? 0 : args.Count;
148 if (func.min_arg < nargs || func.max_arg > nargs)
149 throw new Exception ("Incompatible argument numbers to override: "
151 func.lambda.SetArgs (args);
152 func.lambda.SetBody (body, this);
157 func = new Function (sym, args, body, this);
158 functions = functions.Cons (sym, func);
162 public void Defun (XmlNode node)
164 MSymbol sym = node.Attributes["id"].Value;
165 Function func = (Function) functions.Get (sym);
169 XmlNode args = node.FirstChild;
170 int nargs = args.Name == "args" ? args.ChildNodes.Count : 0;
172 if (func.min_arg < nargs || func.max_arg > nargs)
173 throw new Exception ("Incompatible argument numbers to override: "
175 func.lambda.Set (node, this);
180 func = new Function (sym, node, this);
181 functions = functions.Cons (sym, func);
185 internal Function GetFunc (MSymbol name)
187 Function func = (Function) functions.Get (name);
192 return parent.GetFunc (name);
193 throw new Exception ("Unknown function: " + name);
198 public bool CopyFunc (Domain domain, MSymbol name)
200 Function func = (Function) functions.Get (name);
203 domain.functions = domain.functions.Cons (name, func);
207 public void CopyFunc (Domain domain)
209 foreach (MPlist p in functions)
210 domain.functions = domain.functions.Cons (p.key, p.val);
213 public object GetValue (MSymbol name)
215 MPlist slot = bindings.Find (name);
220 return parent.GetValue (name);
221 throw new Exception ("Unbound variable: " + name);
226 public object SetValue (MSymbol name, object val)
228 MPlist boundary = boundaries.Peek ();
230 for (MPlist plist = bindings; plist != boundary; plist = plist.next)
231 if (plist.key == name)
236 bindings = bindings.Cons (name, val);
240 public bool IsBound (MSymbol name)
242 return (bindings.Find (name) != null);
245 public void Translate (MPlist plist)
248 parent.Translate (plist);
249 if (translator != null)
250 for (MPlist p = plist; ! p.IsEmpty; p = p.next)
251 translator (p, this);
254 public override string ToString ()
256 string str = "<(functions";
257 foreach (MPlist p in functions)
259 str += ") (bindings " + bindings + ")";
261 str += " (" + context + ")";
267 public delegate object Builtin (MExpression[] args, Domain domain);
268 public delegate void Translator (MPlist plist, Domain domain);
270 internal class Function
272 internal class Lambda
274 internal MSymbol[] args;
275 internal MExpression[] body;
277 public Lambda (MPlist args, MPlist body, Domain domain)
280 SetBody (body, domain);
283 public Lambda (XmlNode node, Domain domain)
288 public void SetArgs (MPlist args)
290 int len = args == null ? 0 : args.Count;
292 if (this.args == null)
293 this.args = new MSymbol[len];
294 for (int i = 0; i < len; i++, args = args.next)
295 this.args[i] = args.Symbol;
298 public void SetBody (MPlist body, Domain domain)
300 int len = body == null ? 0 : body.Count;
301 if (this.body == null)
302 this.body = new MExpression[len];
303 for (int i = 0; i < len; i++, body = body.next)
305 domain.Translate (body);
306 this.body[i] = new MExpression (body.key, body.val, domain);
310 public void Set (XmlNode node, Domain domain)
312 XmlNodeList body = node.ChildNodes;
315 if (body[0].Name == "args")
317 XmlNodeList args = body[0].ChildNodes;
318 if (this.args == null)
319 this.args = new MSymbol[args.Count];
320 for (int i = 0; i < args.Count; i++)
321 this.args[i] = args[i].InnerText;
324 else if (this.args == null)
325 this.args = new MSymbol[0];
326 if (this.body == null)
327 this.body = new MExpression[body.Count - idx];
328 for (int i = 0; idx < body.Count; i++, idx++)
329 this.body[i] = new MExpression (body[idx], domain);
333 public readonly MSymbol Name;
334 public Builtin builtin;
335 public int min_arg, max_arg;
336 internal Lambda lambda;
337 public bool specialp = false;
339 internal static Function ignore, varref, block;
341 public Function (MSymbol name, Builtin builtin,
342 int min_arg, int max_arg, bool specialp)
345 this.builtin = builtin;
346 this.min_arg = min_arg;
347 this.max_arg = max_arg;
348 this.specialp = specialp;
351 internal Function (MSymbol name, MPlist args, MPlist body,
355 lambda = new Lambda (args, body, domain);
356 this.min_arg = this.max_arg = lambda.args.Length;
359 internal Function (MSymbol name, XmlNode node, Domain domain)
362 lambda = new Lambda (node, domain);
363 this.min_arg = this.max_arg = lambda.args.Length;
373 ignore = new Function ();
374 varref = new Function (Mvarref, get_value, 1, 1, true);
375 block = new Function (Mprogn, progn, 0, -1, true);
378 private static object get_value (MExpression[] args, Domain domain)
380 return domain.GetValue ((MSymbol) args[0].val);
383 public object Call (MExpression[] args, Domain domain)
388 foreach (MExpression e in args)
390 return builtin (args, domain);
394 MPlist orig_bindings = domain.bindings;
395 object result = false;
398 foreach (MSymbol arg in lambda.args)
399 domain.Bind (arg, args[i++].Eval (domain));
400 foreach (MExpression e in lambda.body)
401 result = e.Eval (domain);
403 domain.bindings = orig_bindings;
409 private static Domain basic;
411 static MExpression ()
413 basic = new Domain ();
415 basic.Defun ("set", set_value, 2, 2, true);
416 basic.Defun ("=", set_value, 2, 2, true);
417 basic.Defun ("!", not, 1, 1, false);
418 basic.Defun ("+", plus, 2, -1, false);
419 basic.Defun ("*", multi, 2, -1, false);
420 basic.Defun ("-", minus, 1, -1, false);
421 basic.Defun ("/", divide, 2, -1, false);
422 basic.Defun ("%", percent, 2, -1, false);
423 basic.Defun ("|", logior, 2, -1, false);
424 basic.Defun ("&", logand, 2, -1, false);
425 basic.Defun ("+=", pluseq, 2, -1, true);
426 basic.Defun ("*=", multieq, 2, -1, true);
427 basic.Defun ("-=", minuseq, 2, -1, true);
428 basic.Defun ("/=", divideeq, 2, -1, true);
429 basic.Defun ("%=", percenteq, 2, -1, true);
430 basic.Defun ("|=", logioreq, 2, -1, true);
431 basic.Defun ("&=", logandeq, 2, -1, true);
432 basic.Defun ("<<", lshift, 2, 2, false);
433 basic.Defun (">>", rshift, 2, 2, false);
434 basic.Defun ("<<=", lshifteq, 2, 2, true);
435 basic.Defun (">>=", rshifteq, 2, 2, true);
436 basic.Defun ("==", eq, 2, -1, false);
437 basic.Defun ("!=", noteq, 2, 2, false);
438 basic.Defun ("<", less, 2, -1, false);
439 basic.Defun ("<=", lesseq, 2, -1, false);
440 basic.Defun (">", more, 2, -1, false);
441 basic.Defun (">=", moreeq, 2, -1, false);
442 basic.Defun ("progn", progn, 0, -1, true);
443 basic.Defun ("if", ifclause, 2, -1, true);
444 basic.Defun ("when", whenclause, 1, -1, true);
445 basic.Defun ("while", whileclause, 1, -1, true);
447 basic.AddTranslator (new Translator (translate_cond));
450 private static object set_value (MExpression[] args, Domain domain)
452 return domain.SetValue ((MSymbol) args[0].args[0].val,
453 args[1].Eval (domain));
456 private static object not (MExpression[] args, Domain domain)
458 if (args[0].val is int)
459 return (int) args[0].val == 0;
460 if (args[0].val is bool)
461 return ! ((bool) args[0].val);
465 private static object plus (MExpression[] args, Domain domain)
467 if (args[0].val is int)
470 foreach (MExpression e in args)
474 else if (args[0].val is MText)
476 MText mt = new MText ();
477 foreach (MExpression e in args)
481 throw new Exception ("Not an integer nor MText: " + args[0].val);
484 private static object multi (MExpression[] args, Domain domain)
487 foreach (MExpression e in args)
492 private static object minus (MExpression[] args, Domain domain)
494 int n = (int) args[0].val;
495 if (args.Length == 1)
497 for (int i = 1; i < args.Length; i++)
498 n -= (int) args[i].val;
502 private static object divide (MExpression[] args, Domain domain)
504 int n = (int) args[0].val;
505 for (int i = 1; i < args.Length; i++)
506 n /= (int) args[i].val;
510 private static object percent (MExpression[] args, Domain domain)
512 int n = (int) args[0].val;
513 for (int i = 1; i < args.Length; i++)
514 n %= (int) args[i].val;
518 private static object logior (MExpression[] args, Domain domain)
521 foreach (MExpression e in args)
526 private static object logand (MExpression[] args, Domain domain)
529 foreach (MExpression e in args)
534 private static object pluseq (MExpression[] args, Domain domain)
536 MSymbol sym = (MSymbol) args[0].args[0].val;
537 object val = domain.GetValue (sym);
542 for (int i = 1; i < args.Length; i++)
543 n += (int) args[i].Eval (domain);
546 else if (val is MText)
548 MText mt = (MText) val;
549 for (int i = 1; i < args.Length; i++)
550 mt.Cat ((MText) args[i].Eval (domain));
553 domain.SetValue (sym, val);
557 private static object multieq (MExpression[] args, Domain domain)
559 MSymbol sym = (MSymbol) args[0].args[0].val;
560 int n = (int) domain.GetValue (sym);
562 for (int i = 1; i < args.Length; i++)
563 n *= (int) args[i].Eval (domain);
564 return domain.SetValue (sym, (object) n);
567 private static object minuseq (MExpression[] args, Domain domain)
569 MSymbol sym = (MSymbol) args[0].args[0].val;
570 int n = (int) domain.GetValue (sym);
572 for (int i = 1; i < args.Length; i++)
573 n -= (int) args[i].Eval (domain);
574 return domain.SetValue (sym, (object) n);
577 private static object divideeq (MExpression[] args, Domain domain)
579 MSymbol sym = (MSymbol) args[0].args[0].val;
580 int n = (int) domain.GetValue (sym);
582 for (int i = 1; i < args.Length; i++)
583 n /= (int) args[i].Eval (domain);
584 return domain.SetValue (sym, (object) n);
587 private static object percenteq (MExpression[] args, Domain domain)
589 MSymbol sym = (MSymbol) args[0].args[0].val;
590 int n = (int) domain.GetValue (sym);
592 for (int i = 1; i < args.Length; i++)
593 n %= (int) args[i].Eval (domain);
594 return domain.SetValue (sym, (object) n);
597 private static object logioreq (MExpression[] args, Domain domain)
599 MSymbol sym = (MSymbol) args[0].args[0].val;
600 int n = (int) domain.GetValue (sym);
602 for (int i = 1; i < args.Length; i++)
603 n |= (int) args[i].Eval (domain);
604 return domain.SetValue (sym, (object) n);
607 private static object logandeq (MExpression[] args, Domain domain)
609 MSymbol sym = (MSymbol) args[0].args[0].val;
610 int n = (int) domain.GetValue (sym);
612 for (int i = 1; i < args.Length; i++)
613 n &= (int) args[i].Eval (domain);
614 return domain.SetValue (sym, (object) n);
617 private static object lshift (MExpression[] args, Domain domain)
619 return (int) args[0].val << (int) args[1].val;
622 private static object lshifteq (MExpression[] args, Domain domain)
624 MSymbol sym = (MSymbol) args[0].args[0].val;
625 int n = (int) domain.GetValue (sym);
627 n <<= (int) args[1].Eval (domain);
628 return domain.SetValue (sym, (object) n);
631 private static object rshift (MExpression[] args, Domain domain)
633 return (int) args[0].val >> (int) args[1].val;
636 private static object rshifteq (MExpression[] args, Domain domain)
638 MSymbol sym = (MSymbol) args[0].args[0].val;
639 int n = (int) domain.GetValue (sym);
641 n >>= (int) args[1].Eval (domain);
642 return domain.SetValue (sym, (object) n);
645 private static object eq (MExpression[] args, Domain domain)
647 int n = (int) args[0].val;
649 for (int i = 1; i < args.Length; i++)
650 if (n != (int) args[i].val)
655 private static object noteq (MExpression[] args, Domain domain)
657 return ((int) args[0].val != (int) args[1].val);
660 private static object less (MExpression[] args, Domain domain)
662 int n = (int) args[0].val;
664 for (int i = 1; i < args.Length; i++)
666 int n1 = (int) args[i].val;
674 private static object lesseq (MExpression[] args, Domain domain)
676 int n = (int) args[0].val;
677 for (int i = 1; i < args.Length; i++)
679 int n1 = (int) args[i].val;
687 private static object more (MExpression[] args, Domain domain)
689 int n = (int) args[0].val;
690 for (int i = 1; i < args.Length; i++)
692 int n1 = (int) args[i].val;
700 private static object moreeq (MExpression[] args, Domain domain)
702 int n = (int) args[0].val;
703 for (int i = 1; i < args.Length; i++)
705 int n1 = (int) args[i].val;
713 private static object progn (MExpression[] args, Domain domain)
715 object result = false;
717 foreach (MExpression e in args)
718 result = e.Eval (domain);
722 private static bool check_condition (MExpression condition, Domain domain)
724 object result = condition.Eval (domain);
725 return (result is bool ? (bool) result
726 : result is int ? ((int) result) != 0
730 private static object ifclause (MExpression[] args, Domain domain)
732 object result = false;
734 if (check_condition (args[0], domain))
735 result = args[1].Eval (domain);
737 for (int i = 2; i < args.Length; i++)
738 result = args[i].Eval (domain);
742 private static object whenclause (MExpression[] args, Domain domain)
744 object result = false;
746 if (check_condition (args[0], domain))
747 for (int i = 1; i < args.Length; i++)
748 result = args[i].Eval (domain);
752 private static object whileclause (MExpression[] args, Domain domain)
754 while (check_condition (args[0], domain))
755 for (int i = 1; i < args.Length; i++)
756 args[i].Eval (domain);
760 // (cond (COND1 ...) (COND2 ...) ...)
761 // => (cond (when COND1 ...) (when COND2 ...) ...)
762 private static void translate_cond (MPlist plist, Domain domain)
767 if (plist.IsSymbol && plist.Symbol == Mcond)
770 for (plist = plist.next; ! plist.IsEmpty; plist = plist.next)
773 throw new Exception ("Invalid cond form: " + plist);
774 plist.Plist.Push (MSymbol.symbol, Mwhen);
780 private Function function;
781 private MExpression[] args;
784 public MExpression[] Args { get { return args; } }
785 public object Val { get { return val; } }
787 private MExpression (object val)
792 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | PROGN
793 // FUNCALL = '(' SYMBOL EXPR* ')'
794 // PROGN = '(' EXPR * ')'
795 private MExpression (MSymbol key, object val, Domain domain)
797 if (key == MSymbol.symbol)
799 function = Function.varref;
800 args = new MExpression[1];
801 args[0] = new MExpression (val);
803 else if (key == MSymbol.integer
804 || key == MSymbol.mtext)
808 else if (key == MSymbol.plist)
810 MPlist p = (MPlist) val;
814 MSymbol sym = p.Symbol;
820 throw new Exception ("Invalid function argument: "
825 throw new Exception ("Invalid function argument: "
827 domain.Defun (sym, p.Plist, p.next);
828 // This Mexpression is just a dummy.
832 function = domain.GetFunc (sym);
835 if (nargs < function.min_arg
836 || (function.max_arg >= 0 && nargs > function.max_arg))
837 throw new Exception ("Invalid number of arguments to: "
838 + sym + " " + nargs);
839 args = new MExpression[nargs];
840 for (int i = 0; i < nargs; i++, p = p.next)
842 domain.Translate (p);
843 args[i] = new MExpression (p.key, p.val, domain);
849 args = new MExpression[1];
850 args[0] = new MExpression (p, domain);
854 throw new Exception ("Invalid expression: " + key + ":" + val);
857 public MExpression (MPlist plist, Domain domain)
859 function = Function.block;
860 args = new MExpression[plist.Count];
861 for (int i = 0; ! plist.IsEmpty; i++, plist = plist.next)
863 domain.Translate (plist);
864 args[i] = new MExpression (plist.key, plist.val, domain);
868 public MExpression (XmlNode node, Domain domain)
870 MSymbol sym = node.Name;
872 function = domain.GetFunc (sym);
874 XmlAttributeCollection attrs = node.Attributes;
876 int nargs = attrs.Count + node.ChildNodes.Count;
877 if (nargs < function.min_arg
878 || (function.max_arg >= 0 && nargs > function.max_arg))
879 throw new Exception ("Invalid number of arguments: " + node.InnerXml);
880 args = new MExpression[nargs];
882 for (i = 0; i < attrs.Count; i++)
884 string str = sttrs[i].Value;
889 public object Eval (Domain domain)
891 if (function == null)
894 val = domain.GetValue ((MSymbol) val);
897 val = function.Call (args, domain);
901 public override string ToString ()
905 if (function != null)
907 str = "(" + function.Name.Name;
909 foreach (MExpression e in args)
910 str += " " + e.ToString ();
913 else if (val != null)
916 str = "\"" + (string) ((MText) val) + "\"";
918 str = val.ToString ();