2 using System.Collections;
3 using System.Collections.Generic;
7 namespace System.Xml.Expression
13 private static NameTable nt = new NameTable ();
17 public Name (string str)
22 public Name (XmlAttribute attr)
24 name = nt.Add (attr.Value);
27 public Name (XmlNode node)
32 public static implicit operator Name (string str)
34 return new Name (str);
37 public static implicit operator Name (XmlAttribute attr)
39 return new Name (attr);
42 public static implicit operator Name (XmlNode node)
44 return new Name (node);
47 public static implicit operator string (Name name)
52 public static bool operator== (Name n1, Name n2)
54 return (object) n1.name == (object) n2.name;
57 public static bool operator== (Name n1, string n2)
59 return (object) n1.name == (object) n2;
62 public static bool operator== (string n1, Name n2)
64 return (object) n1 == (object) n2.name;
67 public static bool operator!= (Name n1, Name n2)
69 return (object) n1.name != (object) n2.name;
72 public static bool operator!= (Name n1, string n2)
74 return (object) n1.name != (object) n2;
77 public static bool operator!= (string n1, Name n2)
79 return (object) n1 != (object) n2.name;
82 public override bool Equals (object other)
84 Console.WriteLine ("Equals (object)");
85 return Object.ReferenceEquals (this, other);
88 public override int GetHashCode ()
90 return name.GetHashCode ();
93 public static NameTable Table { get { return nt; } }
96 private static Name Ninteger = "integer";
97 private static Name Nstring = "string";
98 private static Name Nboolean = "boolean";
99 private static Name Nsymbol = "symbol";
100 private static Name Nlist = "list";
101 private static Name Nobject = "object";
103 private static Name Nconst = "const";
104 private static Name Nvariable = "varialbe";
106 private static Name Nfuncall = "funcall";
107 private static Name Nmname = "mname";
108 private static Name Nprogn = "progn";
110 internal class Function
112 internal class Lambda
114 internal Name[] args;
117 public Lambda (XmlNode node, Domain domain)
122 public void Set (XmlNode node, Domain domain)
124 XmlNodeList body = node.ChildNodes;
127 if (body[0].Name == "args")
129 XmlNodeList args = body[0].ChildNodes;
130 if (this.args == null)
131 this.args = new Name[args.Count];
132 for (int i = 0; i < args.Count; i++)
133 this.args[i] = args[i].InnerText;
136 else if (this.args == null)
137 this.args = new Name[0];
138 if (this.body == null)
139 this.body = new Xex[body.Count - idx];
140 for (int i = 0; idx < body.Count; i++, idx++)
141 this.body[i] = new Xex (body[idx], domain);
145 public readonly Name name;
146 public Builtin builtin;
147 public int min_arg, max_arg;
148 internal Lambda lambda;
149 public bool specialp = false;
151 public Function (Name name, Builtin builtin,
152 int min_arg, int max_arg, bool specialp)
155 this.builtin = builtin;
156 this.min_arg = min_arg;
157 this.max_arg = max_arg;
158 this.specialp = specialp;
161 internal Function (Name name, XmlNode node, Domain domain)
164 lambda = new Lambda (node, domain);
165 this.min_arg = this.max_arg = lambda.args.Length;
173 public object Call (Xex[] args, Domain domain)
175 Bindings current = domain.bindings;
176 object result = false;
180 foreach (Xex e in args)
183 return builtin (args, domain);
187 foreach (Xex e in lambda.body)
188 result = e.Eval (domain);
190 domain.UnboundTo (current);
196 internal abstract class Variable
198 public readonly Name name;
199 public readonly Name type;
202 public Variable (Name name, Name type, object value)
214 if (! ValueP (value))
215 throw new Exception ("Invalid value type: " + value);
220 public abstract bool ValueP (object value);
222 public override string ToString () { return name + "(" + type + ")"; }
225 internal class VarInt : Variable
232 public Range[] ranges;
234 public VarInt (Name name, int value) : base (name, Ninteger, value) { }
236 public override bool ValueP (object value)
240 if (! (value is int))
245 foreach (Range r in ranges)
246 if (i >= r.from && i <= r.to)
252 internal class VarStr : Variable
254 public string[] ranges;
256 public VarStr (Name name, string value) : base (name, Nstring, value) { }
258 public override bool ValueP (object value)
262 if (! (value is string))
266 str = (string) value;
267 foreach (string s in ranges)
274 internal class VarBool : Variable
276 public VarBool (Name name, bool value) : base (name, Nboolean, value) { }
278 public override bool ValueP (object value)
280 return value is bool;
284 internal class VarMisc : Variable
286 public VarMisc (Name name, object value) : base (name, Nobject, value) { }
288 public override bool ValueP (object value)
294 internal class Bindings
296 private Variable vari;
297 private object old_value;
298 private Bindings next;
300 private Bindings (Variable vari, object value)
306 public static Bindings Bind (Bindings bindings,
307 Variable vari, object value)
309 Bindings b = new Bindings (vari, vari.val);
311 b.vari.Value = value;
316 internal Bindings UnboundTo (Bindings boundary)
318 for (Bindings b = this; b != boundary; b = b.next)
319 vari.val = b.old_value;
323 public override string ToString ()
325 string str = "(bindings";
326 for (Bindings b = this; b != null; b = b.next)
332 internal class ThrowException : Exception
337 public ThrowException (Name tag, object value) : base ()
346 private Domain parent;
347 public object context;
349 internal Dictionary<Name, Function> functions
350 = new Dictionary<Name, Function> ();
351 internal Dictionary<Name, Variable> variables
352 = new Dictionary<Name, Variable> ();
353 internal Bindings bindings;
355 internal Domain () { }
357 public Domain (object context) : this (basic, context) { }
359 public Domain (Domain parent, object context)
361 this.parent = parent;
362 this.context = context;
365 internal void Bind (Variable vari, object value)
367 bindings = Bindings.Bind (bindings, vari, value);
370 internal void UnboundTo (Bindings boundary)
372 bindings = bindings.UnboundTo (boundary);
375 public void Defun (Name name, Builtin builtin, int min_arg, int max_arg)
377 Defun (name, builtin, min_arg, max_arg, false);
380 public void Defun (Name name, Builtin builtin, int min_arg, int max_arg,
385 if (functions.TryGetValue (name, out func))
387 if (func.min_arg < min_arg || func.max_arg > max_arg)
388 throw new Exception ("Incompatible argument numbers to override: "
390 func.builtin = builtin;
392 func.min_arg = min_arg;
393 func.max_arg = max_arg;
394 func.specialp = specialp;
399 = new Function (name, builtin, min_arg, max_arg, specialp);
403 public void Defun (XmlNode node)
405 Name name = node.Attributes["id"];
408 if (functions.TryGetValue (name, out func))
410 XmlNode args = node.FirstChild;
411 int nargs = args.Name == "args" ? args.ChildNodes.Count : 0;
413 if (func.min_arg < nargs || func.max_arg > nargs)
414 throw new Exception ("Incompatible argument numbers to override: "
416 func.lambda.Set (node, this);
421 func = new Function (name, node, this);
422 functions[name] = func;
426 internal Function GetFunc (Name name)
430 if (! functions.TryGetValue (name, out func))
433 return parent.GetFunc (name);
434 throw new Exception ("Unknown function: " + name);
439 public bool CopyFunc (Domain domain, Name name)
441 Function func = GetFunc (name);
443 domain.functions[name] = func;
447 public void CopyFunc (Domain domain)
449 foreach (KeyValuePair<Name, Function> kv in functions)
450 domain.functions[kv.Key] = kv.Value;
453 internal Variable GetVar (Name name)
457 if (! variables.TryGetValue (name, out vari))
458 variables[name] = vari = new VarMisc (name, null);
462 internal Variable GetVar (Xex e)
464 if (! (e.val is Name))
465 throw new Exception ("Not a symbol" + e.val);
466 return GetVar ((Name) e.val);
469 public override string ToString ()
471 string str = "<(functions";
472 foreach (KeyValuePair<Name, Function> kv in functions)
474 str += ") (variabls";
475 foreach (KeyValuePair<Name, Variable> kv in variables)
477 str += " " + bindings;
479 str += " (" + context + ")";
485 public delegate object Builtin (Xex[] args, Domain domain);
487 private static Domain basic = new Domain ();
489 internal static Function Fprogn;
493 basic.Defun ("set", set_value, 2, 2, false);
494 basic.Defun ("=", set_value, 2, 2, false);
495 basic.Defun ("and", and, 1, -1, false);
496 basic.Defun ("&&", and, 1, -1, false);
497 basic.Defun ("or", or, 1, -1, false);
498 basic.Defun ("||", or, 1, -1, false);
499 basic.Defun ("not", not, 1, 1, false);
500 basic.Defun ("!", not, 1, 1, false);
501 basic.Defun ("+", add, 2, -1, false);
502 basic.Defun ("*", mul, 2, -1, false);
503 basic.Defun ("-", sub, 1, -1, false);
504 basic.Defun ("/", div, 2, -1, false);
505 basic.Defun ("%", mod, 2, 2, false);
506 basic.Defun ("|", logior, 2, -1, false);
507 basic.Defun ("&", logand, 2, -1, false);
508 basic.Defun ("+=", add_set, 2, -1, true);
509 basic.Defun ("*=", mul_set, 2, -1, true);
510 basic.Defun ("-=", sub_set, 2, -1, true);
511 basic.Defun ("/=", div_set, 2, -1, true);
512 basic.Defun ("%=", mod_set, 2, 2, true);
513 basic.Defun ("|=", logior_set, 2, -1, true);
514 basic.Defun ("&=", logand_set, 2, -1, true);
515 basic.Defun ("<<", lsh, 2, 2, false);
516 basic.Defun (">>", rsh, 2, 2, false);
517 basic.Defun ("<<=", lsh_set, 2, 2, true);
518 basic.Defun (">>=", rsh_set, 2, 2, true);
519 basic.Defun ("==", eq, 2, -1, false);
520 basic.Defun ("!=", noteq, 2, 2, false);
521 basic.Defun ("<", less_than, 2, -1, false);
522 basic.Defun ("<=", less_eq, 2, -1, false);
523 basic.Defun (">", greater_than, 2, -1, false);
524 basic.Defun (">=", greater_eq, 2, -1, false);
525 basic.Defun ("progn", progn_clause, 0, -1, true);
526 basic.Defun ("if", if_clause, 2, -1, true);
527 basic.Defun ("when", when_clause, 1, -1, true);
528 basic.Defun ("while", while_clause, 1, -1, true);
530 Fprogn = basic.GetFunc (Nprogn);
533 private static bool is_true (object val)
535 return (val is bool ? (bool) val
536 : val is int ? (int) val == 0
540 private static object set_value (Xex[] args, Domain domain)
542 Variable vari = domain.GetVar (args[0]);
544 vari.Value = args[1].val;
548 private static object and (Xex[] args, Domain domain)
550 foreach (Xex arg in args)
551 if (! is_true (arg.val))
556 private static object or (Xex[] args, Domain domain)
558 foreach (Xex arg in args)
559 if (is_true (arg.val))
564 private static object not (Xex[] args, Domain domain)
566 return ! is_true (args[0].val);
569 private static object add (Xex[] args, Domain domain)
572 foreach (Xex e in args)
577 private static object mul (Xex[] args, Domain domain)
580 foreach (Xex e in args)
585 private static object sub (Xex[] args, Domain domain)
587 int n = (int) args[0].val;
588 if (args.Length == 1)
590 for (int i = 1; i < args.Length; i++)
591 n -= (int) args[i].val;
595 private static object div (Xex[] args, Domain domain)
597 int n = (int) args[0].val;
598 for (int i = 1; i < args.Length; i++)
599 n /= (int) args[i].val;
603 private static object mod (Xex[] args, Domain domain)
605 return ((int) args[0].val % (int) args[1].val);
608 private static object logior (Xex[] args, Domain domain)
611 foreach (Xex e in args)
616 private static object logand (Xex[] args, Domain domain)
618 int n = (int) args[0].val;
619 for (int i = 1; i < args.Length; i++)
620 n &= (int) args[i].val;
624 private static object add_set (Xex[] args, Domain domain)
626 Variable vari = domain.GetVar (args[0]);
627 int n = (int) vari.val;
629 for (int i = 1; i < args.Length; i++)
630 n += (int) args[i].val;
635 private static object mul_set (Xex[] args, Domain domain)
637 Variable vari = domain.GetVar (args[0]);
638 int n = (int) vari.val;
640 for (int i = 1; i < args.Length; i++)
641 n *= (int) args[i].val;
646 private static object sub_set (Xex[] args, Domain domain)
648 Variable vari = domain.GetVar (args[0]);
649 int n = (int) vari.val;
651 for (int i = 1; i < args.Length; i++)
652 n -= (int) args[i].val;
657 private static object div_set (Xex[] args, Domain domain)
659 Variable vari = domain.GetVar (args[0]);
660 int n = (int) vari.val;
662 for (int i = 1; i < args.Length; i++)
663 n /= (int) args[i].val;
668 private static object mod_set (Xex[] args, Domain domain)
670 Variable vari = domain.GetVar (args[0]);
671 int n = (int) vari.val;
673 for (int i = 1; i < args.Length; i++)
674 n %= (int) args[i].val;
679 private static object logior_set (Xex[] args, Domain domain)
681 Variable vari = domain.GetVar (args[0]);
682 int n = (int) vari.val;
684 for (int i = 1; i < args.Length; i++)
685 n |= (int) args[i].val;
690 private static object logand_set (Xex[] args, Domain domain)
692 Variable vari = domain.GetVar (args[0]);
693 int n = (int) vari.val;
695 for (int i = 1; i < args.Length; i++)
696 n &= (int) args[i].val;
701 private static object lsh (Xex[] args, Domain domain)
703 return (int) args[0].val << (int) args[1].val;
706 private static object lsh_set (Xex[] args, Domain domain)
708 Variable vari = domain.GetVar (args[0]);
709 int n = (int) vari.val;
711 n <<= (int) args[1].val;
716 private static object rsh (Xex[] args, Domain domain)
718 return (int) args[0].val >> (int) args[1].val;
721 private static object rsh_set (Xex[] args, Domain domain)
723 Variable vari = domain.GetVar (args[0]);
724 int n = (int) vari.val;
726 n >>= (int) args[1].val;
731 private static object eq (Xex[] args, Domain domain)
733 int n = (int) args[0].val;
735 for (int i = 1; i < args.Length; i++)
736 if (n != (int) args[i].val)
741 private static object noteq (Xex[] args, Domain domain)
743 return ((int) args[0].val != (int) args[1].val);
746 private static object less_than (Xex[] args, Domain domain)
748 int n = (int) args[0].val;
750 for (int i = 1; i < args.Length; i++)
752 int n1 = (int) args[i].val;
760 private static object less_eq (Xex[] args, Domain domain)
762 int n = (int) args[0].val;
763 for (int i = 1; i < args.Length; i++)
765 int n1 = (int) args[i].val;
773 private static object greater_than (Xex[] args, Domain domain)
775 int n = (int) args[0].val;
776 for (int i = 1; i < args.Length; i++)
778 int n1 = (int) args[i].val;
786 private static object greater_eq (Xex[] args, Domain domain)
788 int n = (int) args[0].val;
789 for (int i = 1; i < args.Length; i++)
791 int n1 = (int) args[i].val;
799 private static object progn_clause (Xex[] args, Domain domain)
801 object result = true;
803 foreach (Xex e in args)
804 result = e.Eval (domain);
808 private static object if_clause (Xex[] args, Domain domain)
812 if (is_true (args[0].Eval (domain)))
813 result = args[1].Eval (domain);
817 for (int i = 2; i < args.Length; i++)
818 result = args[i].Eval (domain);
823 private static object when_clause (Xex[] args, Domain domain)
825 if (! is_true (args[0].Eval (domain)))
828 object result = true;
829 for (int i = 1; i < args.Length; i++)
830 result = args[i].Eval (domain);
834 private static object while_clause (Xex[] args, Domain domain)
836 while (is_true (args[0].Eval (domain)))
837 for (int i = 1; i < args.Length; i++)
838 args[i].Eval (domain);
842 // FUNCALL: function != null
843 // VARREF: function == null, args[0] = DIRECT-SYMBOL
844 // DIRECT: function == null, args == null
846 private Function function;
850 public Xex[] Args { get { return args; } }
851 public object Val { get { return val; } }
855 private Xex (object val)
860 private static Xex macro_expand (Xex[] bindings, Name[] args, Xex e)
864 if (e.function != null)
867 xex.function = e.function;
868 xex.args = new Xex[e.args.Length];
869 for (int i = e.args.Length - 1; i >= 0; i--)
870 xex.args[i] = macro_expand (bindings, args, e.args[i]);
872 else if (e.args != null)
875 Name name = (Name) e.args[0].val;
876 for (int i = args.Length - 1; i >= 0; i--)
880 xex.args = new Xex[1];
881 xex.args[0] = e.args[0];
890 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | PROGN
891 // FUNCALL = '(' SYMBOL EXPR* ')'
892 // PROGN = '(' EXPR * ')'
893 public Xex (XmlNode node, Domain domain)
895 Name name = node.Name;
899 Name type = node.Attributes["type"].Value;
901 if (type == Ninteger)
902 val = parse_integer (node.InnerText);
903 else if (type == Nstring)
904 val = node.InnerText;
905 else if (type == Nsymbol)
906 val = (Name) node.InnerText;
907 else if (type == Nboolean)
908 val = node.InnerText == "true";
909 else if (type == Nlist)
911 List<Xex> list = new List<Xex> ();
912 for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
913 list.Add (new Xex (n, domain));
917 throw new Exception ("Unknown type: " + type);
919 else if (name == Nvariable)
922 args[0] = new Xex (node.Attributes[0]);
926 bool is_macro = false;
928 if (name == Nfuncall)
930 name = node.Attributes[0].Value;
931 if (Nmname == node.Attributes[0].Name)
934 function = domain.GetFunc (name);
936 XmlNodeList nlist = node.ChildNodes;
937 int nargs = nlist.Count;
939 if (nargs < function.min_arg
940 || (function.max_arg >= 0 && nargs > function.max_arg))
941 throw new Exception ("Invalid number of arguments to: "
942 + name + " " + nargs);
943 args = new Xex[nargs];
944 for (int i = 0; i < nargs; i++)
945 args[i] = new Xex (nlist[i]);
949 Function.Lambda lambda = function.lambda;
950 Xex[] body = lambda.body;
951 int len = body.Length;
952 Xex[] newargs = new Xex[len];
954 for (int i = 0; i < len; i++)
955 newargs[i] = macro_expand (args, lambda.args, body[i]);
962 private int parse_integer (string str)
964 int len = str.Length;
965 bool negative = false;
968 return (len == 0 ? 0 : str[0]);
973 if (c == '0' && str[1] == 'x')
976 for (int idx = 2; idx < len; idx++)
986 i = i * 16 + (c - 'A');
990 i = i * 16 + (c - 'a');
999 for (int idx = 1; idx < len; idx++)
1002 if (c < '0' || c > '9')
1004 i = i * 10 + (c - '0');
1006 return negative ? - i : i;
1009 public object Eval (Domain domain)
1011 if (function == null)
1015 Variable vari = domain.GetVar ((Name) args[0].val);
1021 val = function.Call (args, domain);
1025 public override string ToString ()
1029 if (function != null)
1031 str = "(" + function.name;
1033 foreach (Xex e in args)
1034 str += " " + e.ToString ();
1037 else if (args != null)
1039 str = (string) args[0].val;
1041 else if (val != null)
1044 str = "\"" + ((string) val) + "\"";
1046 str = val.ToString ();