2 using System.Collections;
3 using System.Collections.Generic;
7 namespace System.Xml.Expression
11 public struct Name : IEquatable<Name>
13 private static NameTable nt = new NameTable ();
17 public Name (string str)
22 public static implicit operator Name (string str)
24 return new Name (str);
27 public static implicit operator string (Name name)
32 public static bool operator== (Name n1, Name n2)
34 return (object) n1.name == (object) n2.name;
37 public static bool operator!= (Name n1, Name n2)
39 return (object) n1.name != (object) n2.name;
42 public static bool operator== (Name n1, string n2)
44 return (object) n1.name == (object) n2;
47 public static bool operator!= (Name n1, string n2)
49 return (object) n1.name != (object) n2;
52 public bool Equals (Name name)
54 Console.WriteLine ("Equals ({0}, {1})", this, name);
55 bool result = Object.ReferenceEquals (this.name, name.name);
56 Console.WriteLine (result);
60 public override bool Equals (object obj)
62 Console.WriteLine ("Equals ({0}, {1})", this, obj);
63 bool result = Object.ReferenceEquals (this.name, obj);
64 Console.WriteLine (result);
68 public override int GetHashCode ()
70 return name.GetHashCode ();
73 public static NameTable Table { get { return nt; } }
75 public override string ToString () { return name; }
78 private static Name Nexpr = "expr";
79 private static Name Nargs = "args";
81 private static Name Ninteger = "integer";
82 private static Name Nstring = "string";
83 private static Name Nboolean = "boolean";
84 private static Name Nsymbol = "symbol";
85 private static Name Nlist = "list";
86 private static Name Nobject = "object";
88 private static Name Nconst = "const";
89 private static Name Nvariable = "varialbe";
91 private static Name Nfuncall = "funcall";
92 private static Name Nmname = "mname";
93 private static Name Nprogn = "progn";
95 internal class Function
102 public Lambda (XmlNode node, Domain domain)
107 public void Set (XmlNode node, Domain domain)
109 XmlNodeList body = node.ChildNodes;
112 if (Nargs == body[0].Name)
114 XmlNodeList args = body[0].ChildNodes;
115 if (this.args == null)
116 this.args = new Name[args.Count];
117 for (int i = 0; i < args.Count; i++)
118 this.args[i] = args[i].InnerText;
121 else if (this.args == null)
122 this.args = new Name[0];
123 if (this.body == null)
124 this.body = new Xex[body.Count - idx];
125 for (int i = 0; idx < body.Count; i++, idx++)
126 this.body[i] = new Xex (body[idx], domain);
130 public readonly Name name;
131 public Builtin builtin;
132 public int min_arg, max_arg;
133 internal Lambda lambda;
134 public bool specialp = false;
136 public Function (Name name, Builtin builtin,
137 int min_arg, int max_arg, bool specialp)
140 this.builtin = builtin;
141 this.min_arg = min_arg;
142 this.max_arg = max_arg;
143 this.specialp = specialp;
146 internal Function (Name name, XmlNode node, Domain domain)
149 lambda = new Lambda (node, domain);
150 this.min_arg = this.max_arg = lambda.args.Length;
158 public object Call (Xex[] args, Domain domain)
160 Bindings current = domain.bindings;
161 object result = false;
165 foreach (Xex e in args)
168 return builtin (args, domain);
172 foreach (Xex e in lambda.body)
173 result = e.Eval (domain);
175 domain.UnboundTo (current);
181 internal abstract class Variable
183 public readonly Name name;
184 public readonly Name type;
187 public Variable (Name name, Name type, object value)
199 if (! ValueP (value))
200 throw new Exception ("Invalid value type: " + value);
205 public abstract bool ValueP (object value);
207 public override string ToString () { return name + "(" + type + ")"; }
210 internal class VarInt : Variable
217 public Range[] ranges;
219 public VarInt (Name name, int value) : base (name, Ninteger, value) { }
221 public override bool ValueP (object value)
225 if (! (value is int))
230 foreach (Range r in ranges)
231 if (i >= r.from && i <= r.to)
237 internal class VarStr : Variable
239 public string[] ranges;
241 public VarStr (Name name, string value) : base (name, Nstring, value) { }
243 public override bool ValueP (object value)
247 if (! (value is string))
251 str = (string) value;
252 foreach (string s in ranges)
259 internal class VarBool : Variable
261 public VarBool (Name name, bool value) : base (name, Nboolean, value) { }
263 public override bool ValueP (object value)
265 return value is bool;
269 internal class VarMisc : Variable
271 public VarMisc (Name name, object value) : base (name, Nobject, value) { }
273 public override bool ValueP (object value)
279 internal class Bindings
281 private Variable vari;
282 private object old_value;
283 private Bindings next;
285 private Bindings (Variable vari, object value)
291 public static Bindings Bind (Bindings bindings,
292 Variable vari, object value)
294 Bindings b = new Bindings (vari, vari.val);
296 b.vari.Value = value;
301 internal Bindings UnboundTo (Bindings boundary)
303 for (Bindings b = this; b != boundary; b = b.next)
304 vari.val = b.old_value;
308 public override string ToString ()
310 string str = "(bindings";
311 for (Bindings b = this; b != null; b = b.next)
318 internal class ThrowException : Exception
323 public ThrowException (Name tag, object value) : base ()
333 private Domain parent;
334 public object context;
336 internal Dictionary<Name, Function> functions
337 = new Dictionary<Name, Function> ();
338 internal Dictionary<Name, Variable> variables
339 = new Dictionary<Name, Variable> ();
340 internal Bindings bindings;
342 internal Domain () { }
344 public Domain (object context) : this (basic, context)
346 Console.WriteLine (basic);
349 public Domain (Domain parent, object context)
351 this.parent = parent;
352 this.context = context;
355 internal void Bind (Variable vari, object value)
357 bindings = Bindings.Bind (bindings, vari, value);
360 internal void UnboundTo (Bindings boundary)
362 bindings = bindings.UnboundTo (boundary);
365 public void Defun (Name name, Builtin builtin, int min_arg, int max_arg)
367 Defun (name, builtin, min_arg, max_arg, false);
370 public void Defun (Name name, Builtin builtin, int min_arg, int max_arg,
375 if (functions.TryGetValue (name, out func))
377 if (func.min_arg < min_arg || func.max_arg > max_arg)
378 throw new Exception ("Incompatible argument numbers to override: "
380 func.builtin = builtin;
382 func.min_arg = min_arg;
383 func.max_arg = max_arg;
384 func.specialp = specialp;
389 = new Function (name, builtin, min_arg, max_arg, specialp);
393 public void Defun (XmlNode node)
395 Name name = node.Attributes["id"].Value;
398 if (functions.TryGetValue (name, out func))
400 XmlNode args = node.FirstChild;
401 int nargs = args.Name == "args" ? args.ChildNodes.Count : 0;
403 if (func.min_arg < nargs || func.max_arg > nargs)
404 throw new Exception ("Incompatible argument numbers to override: "
406 func.lambda.Set (node, this);
411 func = new Function (name, node, this);
412 functions[name] = func;
416 internal Function GetFunc (Name name)
420 if (! functions.TryGetValue (name, out func))
423 return parent.GetFunc (name);
424 throw new Exception ("Unknown function: " + name);
429 public bool CopyFunc (Domain domain, Name name)
431 Function func = GetFunc (name);
433 domain.functions[name] = func;
437 public void CopyFunc (Domain domain)
439 foreach (KeyValuePair<Name, Function> kv in functions)
440 domain.functions[kv.Key] = kv.Value;
443 internal Variable GetVar (Name name)
447 if (! variables.TryGetValue (name, out vari))
448 variables[name] = vari = new VarMisc (name, null);
452 internal Variable GetVar (Xex e)
454 if (! (e.val is Name))
455 throw new Exception ("Not a symbol" + e.val);
456 return GetVar ((Name) e.val);
459 public override string ToString ()
461 string str = "<(functions";
462 foreach (KeyValuePair<Name, Function> kv in functions)
464 str += ") (variabls";
465 foreach (KeyValuePair<Name, Variable> kv in variables)
468 if (bindings != null)
469 str += " " + bindings;
471 str += " (" + context + ")";
477 public delegate object Builtin (Xex[] args, Domain domain);
479 private static Domain basic = new Domain ();
481 internal static Function Fprogn;
485 basic.Defun ("set", set_value, 2, 2, false);
486 basic.Defun ("=", set_value, 2, 2, false);
487 basic.Defun ("and", and, 1, -1, false);
488 basic.Defun ("&&", and, 1, -1, false);
489 basic.Defun ("or", or, 1, -1, false);
490 basic.Defun ("||", or, 1, -1, false);
491 basic.Defun ("not", not, 1, 1, false);
492 basic.Defun ("!", not, 1, 1, false);
493 basic.Defun ("add", add, 2, -1, false);
494 basic.Defun ("+", add, 2, -1, false);
495 basic.Defun ("mul", mul, 2, -1, false);
496 basic.Defun ("*", mul, 2, -1, false);
497 basic.Defun ("sub", sub, 1, -1, false);
498 basic.Defun ("-", sub, 1, -1, false);
499 basic.Defun ("div", div, 2, -1, false);
500 basic.Defun ("/", div, 2, -1, false);
501 basic.Defun ("mod", mod, 2, 2, false);
502 basic.Defun ("%", mod, 2, 2, false);
503 basic.Defun ("logior", logior, 2, -1, false);
504 basic.Defun ("|", logior, 2, -1, false);
505 basic.Defun ("logand", logand, 2, -1, false);
506 basic.Defun ("&", logand, 2, -1, false);
507 basic.Defun ("add-set", add_set, 2, -1, true);
508 basic.Defun ("+=", add_set, 2, -1, true);
509 basic.Defun ("mul-set", mul_set, 2, -1, true);
510 basic.Defun ("*=", mul_set, 2, -1, true);
511 basic.Defun ("sub-set", sub_set, 2, -1, true);
512 basic.Defun ("-=", sub_set, 2, -1, true);
513 basic.Defun ("div-set", div_set, 2, -1, true);
514 basic.Defun ("/=", div_set, 2, -1, true);
515 basic.Defun ("mod-set", mod_set, 2, 2, true);
516 basic.Defun ("%=", mod_set, 2, 2, true);
517 basic.Defun ("logior-set", logior_set, 2, -1, true);
518 basic.Defun ("|=", logior_set, 2, -1, true);
519 basic.Defun ("logand-set", logand_set, 2, -1, true);
520 basic.Defun ("&=", logand_set, 2, -1, true);
521 basic.Defun ("lsh", lsh, 2, 2, false);
522 basic.Defun ("<<", lsh, 2, 2, false);
523 basic.Defun ("rsh", rsh, 2, 2, false);
524 basic.Defun (">>", rsh, 2, 2, false);
525 basic.Defun ("lsh-set", lsh_set, 2, 2, true);
526 basic.Defun ("<<=", lsh_set, 2, 2, true);
527 basic.Defun ("rsh-set", rsh_set, 2, 2, true);
528 basic.Defun (">>=", rsh_set, 2, 2, true);
529 basic.Defun ("eq", eq, 2, -1, false);
530 basic.Defun ("==", eq, 2, -1, false);
531 basic.Defun ("noteq", noteq, 2, 2, false);
532 basic.Defun ("!=", noteq, 2, 2, false);
533 basic.Defun ("lt", less_than, 2, -1, false);
534 basic.Defun ("<", less_than, 2, -1, false);
535 basic.Defun ("le", less_eq, 2, -1, false);
536 basic.Defun ("<=", less_eq, 2, -1, false);
537 basic.Defun ("gt", greater_than, 2, -1, false);
538 basic.Defun (">", greater_than, 2, -1, false);
539 basic.Defun ("ge", greater_eq, 2, -1, false);
540 basic.Defun (">=", greater_eq, 2, -1, false);
541 basic.Defun ("progn", progn_clause, 0, -1, true);
542 basic.Defun ("expr", progn_clause, 0, -1, true);
543 basic.Defun ("if", if_clause, 2, -1, true);
544 basic.Defun ("when", when_clause, 1, -1, true);
545 basic.Defun ("while", while_clause, 1, -1, true);
547 Fprogn = basic.GetFunc (Nprogn);
550 private static bool is_true (object val)
552 return (val is bool ? (bool) val
553 : val is int ? (int) val == 0
557 private static object set_value (Xex[] args, Domain domain)
559 Variable vari = domain.GetVar (args[0]);
561 vari.Value = args[1].val;
565 private static object and (Xex[] args, Domain domain)
567 foreach (Xex arg in args)
568 if (! is_true (arg.val))
573 private static object or (Xex[] args, Domain domain)
575 foreach (Xex arg in args)
576 if (is_true (arg.val))
581 private static object not (Xex[] args, Domain domain)
583 return ! is_true (args[0].val);
586 private static object add (Xex[] args, Domain domain)
589 foreach (Xex e in args)
594 private static object mul (Xex[] args, Domain domain)
597 foreach (Xex e in args)
602 private static object sub (Xex[] args, Domain domain)
604 int n = (int) args[0].val;
605 if (args.Length == 1)
607 for (int i = 1; i < args.Length; i++)
608 n -= (int) args[i].val;
612 private static object div (Xex[] args, Domain domain)
614 int n = (int) args[0].val;
615 for (int i = 1; i < args.Length; i++)
616 n /= (int) args[i].val;
620 private static object mod (Xex[] args, Domain domain)
622 return ((int) args[0].val % (int) args[1].val);
625 private static object logior (Xex[] args, Domain domain)
628 foreach (Xex e in args)
633 private static object logand (Xex[] args, Domain domain)
635 int n = (int) args[0].val;
636 for (int i = 1; i < args.Length; i++)
637 n &= (int) args[i].val;
641 private static object add_set (Xex[] args, Domain domain)
643 Variable vari = domain.GetVar (args[0]);
644 int n = (int) vari.val;
646 for (int i = 1; i < args.Length; i++)
647 n += (int) args[i].val;
652 private static object mul_set (Xex[] args, Domain domain)
654 Variable vari = domain.GetVar (args[0]);
655 int n = (int) vari.val;
657 for (int i = 1; i < args.Length; i++)
658 n *= (int) args[i].val;
663 private static object sub_set (Xex[] args, Domain domain)
665 Variable vari = domain.GetVar (args[0]);
666 int n = (int) vari.val;
668 for (int i = 1; i < args.Length; i++)
669 n -= (int) args[i].val;
674 private static object div_set (Xex[] args, Domain domain)
676 Variable vari = domain.GetVar (args[0]);
677 int n = (int) vari.val;
679 for (int i = 1; i < args.Length; i++)
680 n /= (int) args[i].val;
685 private static object mod_set (Xex[] args, Domain domain)
687 Variable vari = domain.GetVar (args[0]);
688 int n = (int) vari.val;
690 for (int i = 1; i < args.Length; i++)
691 n %= (int) args[i].val;
696 private static object logior_set (Xex[] args, Domain domain)
698 Variable vari = domain.GetVar (args[0]);
699 int n = (int) vari.val;
701 for (int i = 1; i < args.Length; i++)
702 n |= (int) args[i].val;
707 private static object logand_set (Xex[] args, Domain domain)
709 Variable vari = domain.GetVar (args[0]);
710 int n = (int) vari.val;
712 for (int i = 1; i < args.Length; i++)
713 n &= (int) args[i].val;
718 private static object lsh (Xex[] args, Domain domain)
720 return (int) args[0].val << (int) args[1].val;
723 private static object lsh_set (Xex[] args, Domain domain)
725 Variable vari = domain.GetVar (args[0]);
726 int n = (int) vari.val;
728 n <<= (int) args[1].val;
733 private static object rsh (Xex[] args, Domain domain)
735 return (int) args[0].val >> (int) args[1].val;
738 private static object rsh_set (Xex[] args, Domain domain)
740 Variable vari = domain.GetVar (args[0]);
741 int n = (int) vari.val;
743 n >>= (int) args[1].val;
748 private static object eq (Xex[] args, Domain domain)
750 int n = (int) args[0].val;
752 for (int i = 1; i < args.Length; i++)
753 if (n != (int) args[i].val)
758 private static object noteq (Xex[] args, Domain domain)
760 return ((int) args[0].val != (int) args[1].val);
763 private static object less_than (Xex[] args, Domain domain)
765 int n = (int) args[0].val;
767 for (int i = 1; i < args.Length; i++)
769 int n1 = (int) args[i].val;
777 private static object less_eq (Xex[] args, Domain domain)
779 int n = (int) args[0].val;
780 for (int i = 1; i < args.Length; i++)
782 int n1 = (int) args[i].val;
790 private static object greater_than (Xex[] args, Domain domain)
792 int n = (int) args[0].val;
793 for (int i = 1; i < args.Length; i++)
795 int n1 = (int) args[i].val;
803 private static object greater_eq (Xex[] args, Domain domain)
805 int n = (int) args[0].val;
806 for (int i = 1; i < args.Length; i++)
808 int n1 = (int) args[i].val;
816 private static object progn_clause (Xex[] args, Domain domain)
818 object result = true;
820 foreach (Xex e in args)
821 result = e.Eval (domain);
825 private static object if_clause (Xex[] args, Domain domain)
829 if (is_true (args[0].Eval (domain)))
830 result = args[1].Eval (domain);
834 for (int i = 2; i < args.Length; i++)
835 result = args[i].Eval (domain);
840 private static object when_clause (Xex[] args, Domain domain)
842 if (! is_true (args[0].Eval (domain)))
845 object result = true;
846 for (int i = 1; i < args.Length; i++)
847 result = args[i].Eval (domain);
851 private static object while_clause (Xex[] args, Domain domain)
853 while (is_true (args[0].Eval (domain)))
854 for (int i = 1; i < args.Length; i++)
855 args[i].Eval (domain);
859 // FUNCALL: function != null
860 // VARREF: function == null, args[0] = DIRECT-SYMBOL
861 // DIRECT: function == null, args == null
863 private Function function;
867 public Xex[] Args { get { return args; } }
868 public object Val { get { return val; } }
872 private Xex (object val)
877 private static Xex macro_expand (Xex[] bindings, Name[] args, Xex e)
881 if (e.function != null)
884 xex.function = e.function;
885 xex.args = new Xex[e.args.Length];
886 for (int i = e.args.Length - 1; i >= 0; i--)
887 xex.args[i] = macro_expand (bindings, args, e.args[i]);
889 else if (e.args != null)
892 Name name = (Name) e.args[0].val;
893 for (int i = args.Length - 1; i >= 0; i--)
897 xex.args = new Xex[1];
898 xex.args[0] = e.args[0];
907 private void Setup (XmlNode node, Domain domain)
909 Name name = node.Name;
913 Name type = node.Attributes["type"].Value;
915 if (type == Ninteger)
916 val = parse_integer (node.InnerText);
917 else if (type == Nstring)
918 val = node.InnerText;
919 else if (type == Nsymbol)
920 val = (Name) node.InnerText;
921 else if (type == Nboolean)
922 val = node.InnerText == "true";
923 else if (type == Nlist)
925 List<Xex> list = new List<Xex> ();
926 for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
927 list.Add (new Xex (n, domain));
931 throw new Exception ("Unknown type: " + type);
933 else if (name == Nvariable)
936 args[0] = new Xex (node.Attributes[0]);
940 bool is_macro = false;
942 if (name == Nfuncall)
944 name = node.Attributes[0].Value;
945 if (Nmname == node.Attributes[0].Name)
948 function = domain.GetFunc (name);
950 XmlNodeList nlist = node.ChildNodes;
951 int nargs = nlist.Count;
953 if (nargs < function.min_arg
954 || (function.max_arg >= 0 && nargs > function.max_arg))
955 throw new Exception ("Invalid number of arguments to: "
956 + name + " " + nargs);
957 args = new Xex[nargs];
958 for (int i = 0; i < nargs; i++)
959 args[i] = new Xex (nlist[i]);
963 Function.Lambda lambda = function.lambda;
964 Xex[] body = lambda.body;
965 int len = body.Length;
966 Xex[] newargs = new Xex[len];
968 for (int i = 0; i < len; i++)
969 newargs[i] = macro_expand (args, lambda.args, body[i]);
976 public Xex (string url, Domain domain)
978 XmlDocument doc = new XmlDocument (Name.Table);
981 using (XmlTextReader reader = new XmlTextReader (url, Name.Table))
985 } while (reader.NodeType != XmlNodeType.None
986 && (reader.NodeType != XmlNodeType.Element
987 || (object) Nexpr != (object) reader.Name));
988 if (reader.NodeType != XmlNodeType.None)
989 throw new Exception ("Node <expr> not found");
990 Console.WriteLine (doc.ReadNode (reader).OuterXml);
991 node = doc.ReadNode (reader);
992 Console.WriteLine ("node read:" + node.OuterXml);
995 Setup (node, domain);
999 // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | PROGN
1000 // FUNCALL = '(' SYMBOL EXPR* ')'
1001 // PROGN = '(' EXPR * ')'
1002 public Xex (XmlNode node, Domain domain)
1004 Setup (node, domain);
1007 private int parse_integer (string str)
1009 int len = str.Length;
1010 bool negative = false;
1013 return (len == 0 ? 0 : str[0]);
1018 if (c == '0' && str[1] == 'x')
1021 for (int idx = 2; idx < len; idx++)
1031 i = i * 16 + (c - 'A');
1035 i = i * 16 + (c - 'a');
1044 for (int idx = 1; idx < len; idx++)
1047 if (c < '0' || c > '9')
1049 i = i * 10 + (c - '0');
1051 return negative ? - i : i;
1054 public object Eval (Domain domain)
1056 if (function == null)
1060 Variable vari = domain.GetVar ((Name) args[0].val);
1066 val = function.Call (args, domain);
1070 public override string ToString ()
1074 if (function != null)
1076 str = "(" + function.name;
1078 foreach (Xex e in args)
1079 str += " " + e.ToString ();
1082 else if (args != null)
1084 str = (string) args[0].val;
1086 else if (val != null)
1089 str = "\"" + ((string) val) + "\"";
1091 str = val.ToString ();