*** empty log message ***
[m17n/m17n-lib-cs.git] / XmlExpr.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.IO;
5 using System.Xml;
6
7 namespace System.Xml.Expression
8 {
9   public class Xexpression
10   {
11     public static int debug_level = 0;
12
13     public struct Symbol : IEquatable<Symbol>
14     {
15       private static NameTable nt = new NameTable ();
16
17       internal string name;
18
19       public Symbol (string str)
20         {
21           name = nt.Add (str);
22         }
23
24       public static implicit operator Symbol (string str)
25       {
26         return new Symbol (str);
27       }
28
29       public static implicit operator string (Symbol name)
30       {
31         return name.name;
32       }
33
34       public static bool operator== (Symbol n1, Symbol n2)
35         {
36           return (object) n1.name == (object) n2.name;
37         }
38
39       public static bool operator!= (Symbol n1, Symbol n2)
40         {
41           return (object) n1.name != (object) n2.name;
42         }
43
44       public static bool operator== (Symbol n1, string n2)
45         {
46           return (object) n1.name == (object) n2;
47         }
48
49       public static bool operator!= (Symbol n1, string n2)
50         {
51           return (object) n1.name != (object) n2;
52         }
53
54       public static bool operator== (string n1, Symbol n2)
55         {
56           return (object) n1 == (object) n2.name;
57         }
58
59       public static bool operator!= (string n1, Symbol n2)
60         {
61           return (object) n1 != (object) n2.name;
62         }
63
64       public bool Equals (Symbol name)
65       {
66         return Object.ReferenceEquals (this.name, name.name);
67       }
68
69       public override bool Equals (object obj)
70       {
71         return Object.ReferenceEquals (this.name, obj);
72       }
73
74       public override int GetHashCode ()
75       {
76         return name.GetHashCode ();
77       }
78
79       public static NameTable Table { get { return nt; } }
80
81       public override string ToString () { return name; }
82     }
83
84     private static Symbol Nexpr = "expr";
85
86     private static Symbol Nnull = "";
87     private static Symbol Nfuncall = "funcall";
88     private static Symbol Nvarref = "varref";
89     private static Symbol Ninteger = "integer";
90     private static Symbol Nstring = "string";
91     private static Symbol Nsymbol = "symbol";
92     private static Symbol Nlist = "list";
93
94     private static Symbol Ndefun = "defun";
95     private static Symbol Nfname = "fname";
96     private static Symbol Nargs = "args";
97     private static Symbol Nargs_unevalled = "args-unevalled";
98     private static Symbol Nfixed = "fixed";
99     private static Symbol Noptional = "optional";
100     private static Symbol Nrest = "rest";
101
102     private static Symbol Ndefvar = "defvar";
103     private static Symbol Nvname = "vname";
104     private static Symbol Ndescription = "description";
105     private static Symbol Nrange = "range";
106
107     public abstract class Function
108     {
109       public Symbol name;
110       public int min_arg, max_arg;
111
112       public Function () { }
113
114       public Function (Symbol name, int min_arg, int max_arg)
115       {
116         this.name = name;
117         this.min_arg = min_arg;
118         this.max_arg = max_arg;
119       }
120
121       public abstract Term Call (Domain domain, Variable vari, Term[] args);
122
123       public override string ToString ()
124       {
125         return name;
126       }
127
128       internal class Subroutine : Function
129       {
130         public Builtin builtin;
131         public bool setvar;
132
133         public Subroutine (Builtin builtin, Symbol name, bool setvar,
134                            int min_arg, int max_arg)
135           : base (name, min_arg, max_arg)
136           {
137             this.builtin = builtin;
138           }
139
140         public override Term Call (Domain domain, Variable vari, Term[] args)
141         {
142           args = (Term[]) args.Clone ();
143           for (int i = 0; i < args.Length; i++)
144             {
145               args[i] = args[i].Eval (domain);
146               if (domain.Thrown)
147                 return args[i];
148             }
149           return builtin (domain, vari, args);
150         }
151       }
152
153       internal class SpecialForm : Function
154       {
155         public Builtin builtin;
156
157         public SpecialForm (Builtin builtin, Symbol name,
158                             int min_arg, int max_arg)
159           : base (name, min_arg, max_arg)
160           {
161             this.builtin = builtin;
162           }
163
164         public override Term Call (Domain domain, Variable vari, Term[] args)
165         {
166           return builtin (domain, vari, args);
167         }
168       }
169
170       internal class Lambda : Function
171       {
172         internal bool args_evalled;
173         internal Variable[] args;
174         internal Term[] body;
175
176         public Lambda (Domain domain, XmlNode node)
177           {
178             int nfixed = 0;
179             int noptional = 0;
180             int nrest = 0;
181             name = node.Attributes[Nfname].Value;
182             
183             node = node.FirstChild;
184             if (node != null
185                 && (node.Name == Nargs || node.Name == Nargs_unevalled))
186               {
187                 XmlNode n;
188                 args_evalled = node.Name == Nargs;
189                 for (n = node.FirstChild; n != null; n = n.NextSibling)
190                   {
191                     if (n.Name == Nfixed)
192                       nfixed++;
193                     else if (n.Name == Noptional)
194                       noptional++;
195                     else if (n.Name == Nrest)
196                       nrest++;
197                     else
198                       throw new Exception ("Invalid argument type: " + n);
199                   }
200                 min_arg = nfixed;
201                 max_arg = nfixed + noptional + nrest;
202                 args = new Variable[max_arg];
203                 n = node.FirstChild;
204                 for (int i = 0; i < max_arg; n = n.NextSibling)
205                   args[i++] = domain.Defvar ((Symbol) n.Attributes[0].Value);
206                 if (nrest == 1)
207                   max_arg = - max_arg;
208               }
209             else
210               {
211                 min_arg = max_arg = 0;
212               }
213           }
214
215         public Lambda (Domain domain, Symbol name, bool args_evalled, Symbol[] args)
216           {
217             int nfixed = 0;
218             int noptional = 0;
219             int nrest = 0;
220
221             this.name = name;
222             this.args_evalled = args_evalled;
223             if (args != null)
224               {
225                 int i = 0;
226                 for (i = 0; i < args.Length; i++, nfixed++)
227                   if (args[i] == Noptional || args[i] == Nrest)
228                     break;
229                 if (i < args.Length)
230                   {
231                     if (args[i] == Noptional)
232                       {
233                         for (i++; i < args.Length; i++, noptional++)
234                           if (args[i] == Nrest)
235                             break;
236                         if (i < args.Length)
237                           nrest = 1;
238                       }
239                   }
240                 min_arg = nfixed;
241                 max_arg = nfixed + noptional + nrest;
242                 this.args = new Variable[max_arg];
243                 int j;
244                 for (i = j = 0; j < this.args.Length; i++)
245                   if (args[i] != Noptional || args[i] != Nrest)
246                     this.args[j++] = domain.Defvar (args[i]);
247               }
248             else
249               {
250                 min_arg = max_arg = 0;
251               }
252           }
253
254         public void SetBody (Domain domain, XmlNode node)
255         {
256           for (node = node.FirstChild; node != null; node = node.NextSibling)
257             if (node.Name != Ndescription
258                 && node.Name != Nargs
259                 && node.Name != Nargs_unevalled)
260               break;
261           int nterms = 0;
262           for (XmlNode n = node; n != null; n = n.NextSibling)
263             nterms++;
264           if (nterms > 0)
265             {
266               body = new Term[nterms];
267               for (nterms = 0; node != null; node = node.NextSibling, nterms++)
268                 body[nterms] = new Term (domain, node);
269             }
270         }
271
272         public void SetBody (Term[] body)
273         {
274           this.body = body;
275         }
276
277         public override Term Call (Domain domain, Variable vari, Term[] args)
278         {
279           Bindings current = domain.bindings;
280           Term result = Zero;
281
282           try {
283             int i;
284             if (args_evalled)
285               {
286                 Term[] newargs = new Term[args.Length];
287                 for (i = 0; i < min_arg; i++)
288                   newargs[i] = args[i].Eval (domain);
289                 args = newargs;
290               }
291             for (i = 0; i < min_arg; i++)
292               domain.Bind (this.args[i], args[i]);
293             if (body != null)
294               {
295                 try {
296                   if (args_evalled)
297                     domain.Catch (CatchTag.Return);
298                   foreach (Term term in body)
299                     {
300                       result = term.Eval (domain);
301                       if (domain.Thrown)
302                         return result;
303                     }
304                 } finally {
305                   if (args_evalled)
306                     domain.Uncatch ();
307                 }
308               }
309           } finally {
310             domain.UnboundTo (current);
311           }
312           return result;
313         }
314       }
315     }
316
317     public class Variable : TermValue
318     {
319       public readonly Symbol name;
320       public string desc;
321       internal Term default_val;
322       internal Term val;
323       object range;
324
325       public Variable (Symbol name, Term value)
326       {
327         this.name = name;
328         val = value;
329         default_val = Zero;
330       }
331
332       public virtual bool ValueP (Term val) { return true; }
333
334       public override TermValue Clone ()
335       {
336         Variable v = new Variable (name, val);
337         v.desc = desc;
338         v.default_val = default_val;
339         v.range = range;
340         return v;
341       }
342
343       public Term Value
344       {
345         get { return val; }
346         set {
347           if (! ValueP (value))
348             throw new Exception ("Invalid value: " + value);
349           val = value;
350         }
351       }
352
353       public Term DefaultValue
354       {
355         get { return default_val; }
356         set {
357           if (! ValueP (value))
358             throw new Exception ("Invalid value: " + value);
359           default_val = value;
360         }
361       }
362
363       public virtual object Range
364       {
365         get { return range; }
366         set { range = value; }
367       }
368
369       public override Term Eval (Domain domain) { return val; }
370
371       public override string ToString () { return name + "(" + val + ")"; }
372
373       public class Int : Variable
374       {
375         public int[] range;
376
377         private static bool SubsetP (int[] r1, int[] r2)
378           {
379             if (r2 == null)
380               return true;
381             for (int i = 0; i < r1.Length; i += 2)
382               {
383                 int j;
384                 for (j = 0; j < r2.Length; j += 2)
385                   if (r2[j] <= r1[i] && r2[j + 1] >= r1[i + 1])
386                     break;
387                 if (j >= r2.Length)
388                   return false;
389               }
390             return true;
391           }
392
393         private static bool SubsetP (int val, int[] r)
394           {
395             if (r == null)
396               return true;
397             for (int i = 0; i < r.Length; i += 2)
398               if (r[i] <= val && r[i + 1] >= val)
399                 return true;
400             return false;
401           }
402
403         public Int (Symbol name, string description, int value, int[] range)
404           : base (name, new Term (value))
405           {
406             if (! SubsetP (value, range))
407               throw new Exception ("Invalid value: " + value);
408             desc = description;
409             default_val = val;
410             this.range = range;
411           }
412
413         public override bool ValueP (Term term)
414         {
415           if (! term.IsInt)
416             return false;
417           return SubsetP (term.Intval, range);
418         }
419
420         public override object Range {
421           get { return range; }
422           set {
423             int[] r = (int[]) value;
424             if (! SubsetP (r, range)
425                 || ! SubsetP (val.Intval, r)
426                 || ! SubsetP (default_val.Intval, r))
427               throw new Exception ("Invalid range");
428             range = r;
429           }
430         }
431       }
432
433       public class Str : Variable
434       {
435         public string[] range;
436
437         private static bool SubsetP (string[] r1, string[] r2)
438           {
439             if (r2 == null)
440               return true;
441             foreach (string s in r1)
442               if (! SubsetP (s, r2))
443                 return false;
444             return true;
445           }
446
447         private static bool SubsetP (string str, string[] r)
448           {
449             if (r == null)
450               return true;
451             foreach (string s in r)
452               if (str == s)
453                 return true;
454             return false;
455         }
456
457         public Str (Symbol name, string description, string value, string[] range)
458           : base (name, new Term (value))
459           {
460             if (! SubsetP (value, range))
461               throw new Exception ("Invalid value: " + value);
462             desc = description;
463             default_val = val;
464             this.range = range;
465           }
466
467         public override bool ValueP (Term term)
468         {
469           if (! (term.objval is string))
470             return false;
471           return SubsetP (term.Strval, range);
472         }
473
474         public override object Range {
475           get { return range; }
476           set {
477             string[] r = (string[]) value;
478             if (! SubsetP (r, range)
479                 || ! SubsetP (val.Strval, r)
480                 || ! SubsetP (default_val.Strval, r))
481               throw new Exception ("Invalid range");
482             range = r;
483           }
484         }
485       }
486
487       public class Sym : Variable
488       {
489         public Symbol[] range;
490
491         private static bool SubsetP (Symbol[] r1, Symbol[] r2)
492           {
493             if (r2 == null)
494               return true;
495             foreach (Symbol n in r1)
496               if (! SubsetP (n, r2))
497                 return false;
498             return true;
499           }
500
501         private static bool SubsetP (Symbol name, Symbol[] r)
502           {
503             if (r == null)
504               return true;
505             foreach (Symbol n in r)
506               if (name == n)
507                 return true;
508             return false;
509         }
510
511         public Sym (Symbol name, string description, Symbol value, Symbol[] range)
512           : base (name, new Term (value))
513           {
514             if (! SubsetP (value, range))
515               throw new Exception ("Invalid value: " + value);
516             desc = description;
517             default_val = val;
518             this.range = range;
519           }
520
521         public override bool ValueP (Term term)
522         {
523           if (! (term.objval is Symbol))
524             return false;
525           return SubsetP (term.Symval, range);
526         }
527
528         public override object Range {
529           get { return range; }
530           set {
531             Symbol[] r = (Symbol[]) value;
532             if (! SubsetP (r, range)
533                 || ! SubsetP (val.Symval, r)
534                 || ! SubsetP (default_val.Symval, r))
535               throw new Exception ("Invalid range");
536             range = r;
537           }
538         }
539       }
540     }
541
542     internal class Bindings
543     {
544       private Variable vari;
545       private Term old_value;
546       private Bindings next;
547         
548       private Bindings (Variable vari)
549       {
550         this.vari = vari;
551         old_value = vari.val;
552       }
553         
554       public static Bindings Bind (Bindings bindings, Variable vari, Term val)
555       {
556         Bindings b = new Bindings (vari);
557
558         b.vari.Value = val;
559         b.next = bindings;
560         return b;
561       }
562
563       internal Bindings UnboundTo (Bindings boundary)
564       {
565         for (Bindings b = this; b != boundary; b = b.next)
566           b.vari.val = b.old_value;
567         return boundary;
568       }
569
570       public override string ToString ()
571       {
572         string str = "(bindings";
573         for (Bindings b = this; b != null; b = b.next)
574           str += " " + vari.name + "=" + b.old_value;
575         return str + ")";
576       }
577     }
578
579 #if false
580     internal class ThrowException : Exception
581     {
582       Symbol tag;
583       public object value;
584
585       public ThrowException (Symbol tag, object value) : base ()
586         {
587           this.tag = tag;
588           this.value = value;
589         }
590     }
591 #endif
592
593     internal class CatchTag : IEquatable<CatchTag>
594     {
595       private object val;
596
597       public CatchTag (Symbol name) { val = name.name; }
598       private CatchTag (int i) { val = i; }
599
600       public static CatchTag Return = new CatchTag (0);
601       public static CatchTag Break = new CatchTag (1);
602
603       public static bool operator== (CatchTag t1, CatchTag t2)
604         { return t1.val == t2.val; }
605
606       public static bool operator!= (CatchTag t1, CatchTag t2)
607         { return t1.val != t2.val; }
608
609       public bool Equals (CatchTag tag) { return this.val == tag.val; }
610       public override bool Equals (object val) { return this.val == val; }
611
612       public override int GetHashCode () { return val.GetHashCode (); }
613     }
614
615     public class Domain
616     {
617       public object context;
618       public int depth = 0;
619
620       internal Dictionary<Symbol, TermType> termtypes
621         = new Dictionary<Symbol, TermType> ();
622       internal Dictionary<Symbol, Function> functions
623         = new Dictionary<Symbol, Function> ();
624       internal Dictionary<Symbol, Variable> variables
625         = new Dictionary<Symbol, Variable> ();
626       internal Bindings bindings;
627       private Stack<CatchTag> catch_stack = new Stack<CatchTag> ();
628       private int catch_count = 0;
629
630       internal Domain () { }
631
632       public Domain (object context) : this (basic, context) { }
633
634       public Domain (Domain parent, object context)
635       {
636         functions = new Dictionary<Symbol, Function> (parent.functions);
637         variables = new Dictionary<Symbol, Variable> (parent.variables);
638         this.context = context;
639       }
640
641       internal void Bind (Variable vari, Term value)
642       {
643         bindings = Bindings.Bind (bindings, vari, value);
644       }
645
646       internal void UnboundTo (Bindings boundary)
647       {
648         if (bindings != null)
649           bindings = bindings.UnboundTo (boundary);
650       }
651
652       internal void Catch (CatchTag tag)
653       {
654         catch_stack.Push (tag);
655         catch_count++;
656       }
657
658       internal void Uncatch ()
659       {
660         catch_stack.Pop ();
661         if (catch_count > catch_stack.Count)
662           catch_count--;
663       }
664
665       public bool Thrown {
666         get { return catch_count < catch_stack.Count; }
667       }
668
669       internal void ThrowReturn ()
670       {
671         foreach (CatchTag tag in catch_stack)
672           {
673             catch_count--;
674             if (tag == CatchTag.Return)
675               break;
676           }
677       }
678
679       internal void ThrowBreak ()
680       {
681         if (catch_stack.Peek () != CatchTag.Break)
682           throw new Exception ("No outer loop to break");
683         catch_count--;
684       }
685
686       internal void ThrowTag (CatchTag tag)
687       {
688         foreach (CatchTag elt in catch_stack)
689           {
690             catch_count--;
691             if (elt == tag)
692               break;
693           }
694       }
695
696       public void DefType (Symbol name, NewObject new_object)
697       {
698         termtypes[name] = new TermType (name, new_object);
699       }
700
701       public void DefSubr (Builtin builtin, string str, bool setvar,
702                            int min_arg, int max_arg, params string[] aliases)
703       {
704         Symbol name = str;
705         Function func = new Function.Subroutine (builtin, name, setvar,
706                                                  min_arg, max_arg);
707         functions[name] = func;
708         foreach (string a in aliases)
709           functions[(Symbol) a] = func;
710       }
711
712       public void DefSpecial (Builtin builtin, string str,
713                               int min_arg, int max_arg,
714                               params string[] aliases)
715       {
716         Symbol name = str;
717         Function func = new Function.SpecialForm (builtin, name,
718                                                   min_arg, max_arg);
719         functions[name] = func;
720         foreach (string a in aliases)
721           functions[(Symbol) a] = func;
722       }
723
724       public void DefAlias (string alias, string str)
725       {
726         functions[(Symbol) alias] = functions[(Symbol) str];
727       }
728
729       public void Defun (Symbol name, bool args_evalled,
730                          Symbol[] args, Term[] body, bool prototype)
731       {
732         Function func;
733
734         if (prototype || ! functions.TryGetValue (name, out func))
735           {
736             func = new Function.Lambda (this, name, args_evalled, args);
737             functions[name] = func;
738           }
739         if (! prototype)
740           ((Function.Lambda) func).SetBody (body);
741       }
742
743       public void Defun (XmlNode node, bool prototype)
744       {
745         Symbol name = node.Attributes[Nfname].Value;
746         Function func;
747
748         if (prototype || ! functions.TryGetValue (name, out func))
749           {
750             func = new Function.Lambda (this, node);
751             functions[name] = func;
752           }
753         if (! prototype)
754           ((Function.Lambda) func).SetBody (this, node);
755       }
756
757       public void Defun (Function func)
758       {
759         functions[func.name] = func;
760       }
761
762       public Variable Defvar (XmlNode node)
763       {
764         Symbol name = node.Attributes[0].Value;
765         String desc;
766         Variable vari;
767
768         node = node.FirstChild;
769         if (node != null && node.Name == Ndescription)
770           {
771             desc = node.InnerText;
772             node = node.NextSibling;
773           }
774         else
775           desc = null;
776         if (node != null)
777           {
778             Symbol type = node.Name;
779             XmlNodeList range_list = null;
780             int nranges = 0;
781             string val = node.InnerText;
782
783             node = node.NextSibling;
784             if (node != null)
785               {
786                 range_list = node.ChildNodes;
787                 nranges = range_list.Count;
788               }
789
790             if (type == Ninteger)
791               {
792                 int intval = parse_integer (val);
793                 int[] range = null;
794                 if (range_list != null)
795                   {
796                     range = new int[nranges * 2];
797                     for (int i = 0; i < nranges; i++)
798                       {
799                         XmlNode n = range_list[i];
800                         if (n.Name == Nrange)
801                           {
802                             range[i * 2]
803                               = parse_integer (n.FirstChild.InnerText);
804                             range[i * 2 + 1]
805                               = parse_integer (n.LastChild.InnerText);
806                           }
807                         else
808                           {
809                             range[i * 2]
810                               = range[i * 2 + 1]
811                               = parse_integer (n.FirstChild.InnerText);
812                           }
813                       }
814                   }
815
816                 if (variables.TryGetValue (name, out vari))
817                   {
818                     if (! (vari is Variable.Int))
819                       throw new Exception ("Inalid value");
820                     vari = (Variable) vari.Clone ();
821                     Term v = new Term (intval);
822                     vari.Value = v;
823                     vari.DefaultValue = v;
824                     if (range != null)
825                       vari.Range = range;
826                   }
827                 else
828                   vari = new Variable.Int (name, desc, intval, range);
829               }
830             else if (type == Nstring)
831               {
832                 string[] range = null;
833                 if (range_list != null)
834                   {
835                     range = new string[nranges];
836                     for (int i = 0; i < nranges; i++)
837                       range[i] = range_list[i].FirstChild.InnerText;
838                   }
839
840                 if (variables.TryGetValue (name, out vari))
841                   {
842                     if (! (vari is Variable.Str))
843                       throw new Exception ("Invalid value");
844                     vari = (Variable) vari.Clone ();
845                     Term v = new Term (val);
846                     vari.Value = v;
847                     vari.DefaultValue = v;
848                     if (range != null)
849                       vari.Range = range;
850                   }
851                 else
852                   vari = new Variable.Str (name, desc, val, range);
853               }
854             else if (type == Nsymbol)
855               {
856                 Symbol[] range = null;
857                 if (range_list != null)
858                   {
859                     range = new Symbol[nranges];
860                     for (int i = 0; i < nranges; i++)
861                       range[i] = range_list[i].FirstChild.InnerText;
862                   }
863
864                 if (variables.TryGetValue (name, out vari))
865                   {
866                     if (! (vari is Variable.Sym))
867                       throw new Exception ("Invalid value");
868                     vari = (Variable) vari.Clone ();
869                     Term v = new Term (val);
870                     vari.Value = v;
871                     vari.DefaultValue = v;
872                     if (range != null)
873                       vari.Range = range;
874                   }
875                 else
876                   vari = new Variable.Sym (name, desc, val, range);
877               }
878             else
879               throw new Exception ("Unknown type: " + type);
880           }
881         else
882           {
883             if (variables.TryGetValue (name, out vari))
884               vari = (Variable) vari.Clone ();
885             else
886               vari = new Variable (name, Zero);
887           }
888         variables[name] = vari;
889         return vari;
890       }
891
892       public Variable Defvar (Variable vari)
893       {
894         variables[vari.name] = vari;
895         return vari;
896       }
897
898       internal Variable Defvar (Symbol name)
899       {
900         Variable vari = new Variable (name, Zero);
901         variables[name] = vari;
902         return vari;
903       }
904
905       internal Function GetFunc (Symbol name)
906       {
907         Function func;
908
909         if (! functions.TryGetValue (name, out func))
910           throw new Exception ("Unknown function: " + name);
911         return func;
912       }
913
914       public bool CopyFunc (Domain domain, Symbol name)
915       {
916         Function func = GetFunc (name);
917
918         domain.functions[name] = func;
919         return true;
920       }
921
922       public void CopyFunc (Domain domain)
923       {
924         foreach (KeyValuePair<Symbol, Function> kv in functions)
925           domain.functions[kv.Key] = kv.Value;
926       }
927
928       public Variable GetVar (Symbol name, bool create)
929       {
930         Variable vari;
931
932         if (! variables.TryGetValue (name, out vari))
933           {
934             if (! create)
935               return null;
936             variables[name] = vari = new Variable (name, Zero);
937           }
938         return vari;
939       }
940
941       public override string ToString ()
942       {
943         string str = "<(functions";
944         foreach (KeyValuePair<Symbol, Function> kv in functions)
945           str += " " + kv.Key;
946         str += ") (variabls";
947         foreach (KeyValuePair<Symbol, Variable> kv in variables)
948           str += " " + kv.Key;
949         str += ")";
950         if (bindings != null)
951           str += " " + bindings;
952         if (context != null)
953           str += " (" + context + ")";
954         str += ">";
955         return str;
956       }
957
958       internal void DebugWrite (bool head, string fmt, params string[] arg)
959       {
960         if (debug_level > depth)
961           {
962             if (head)
963               {
964                 Console.WriteLine ();
965                 for (int i = 0; i < depth; i++)
966                   Console.Write (" ");
967               }
968             Console.Write (fmt, arg);
969           }
970       }
971
972       public object SaveValues ()
973       {
974         Dictionary<Variable,Term> values = new Dictionary<Variable,Term> ();
975
976         foreach (KeyValuePair<Symbol,Variable> kv in variables)
977           values[kv.Value] = kv.Value.val.Clone ();
978         return values;
979       }
980
981       public void RestoreValues (object values)
982       {
983         foreach (KeyValuePair<Variable,Term> kv
984                  in (Dictionary<Variable,Term>) values)
985           kv.Key.val = kv.Value;
986       }
987     }
988
989     public delegate Term Builtin (Domain domain, Variable vari, Term[] args);
990
991     private static Domain basic = new Domain ();
992
993     static Xexpression ()
994     {
995       basic.DefType ("funcall", Funcall.New);
996
997       basic.DefSubr (Fset, "set", true, 1, 1, "=");
998       basic.DefSubr (Fnot, "not", false, 1, 1, "!");
999       basic.DefSubr (Fadd, "add", true, 1, -1, "+");
1000       basic.DefSubr (Fmul, "mul", true, 1, -1, "*");
1001       basic.DefSubr (Fsub, "sub", true, 1, -1, "-");
1002       basic.DefSubr (Fdiv, "div", true, 1, -1, "/");
1003       basic.DefSubr (Fmod, "mod", true, 1, 2, "%");
1004       basic.DefSubr (Flogior, "logior", true, 1, -1, "|");
1005       basic.DefSubr (Flogand, "logand", true, 1, -1, "&");
1006       basic.DefSubr (Flsh, "lsh", true, 1, 2, "<<");
1007       basic.DefSubr (Frsh, "rsh", true, 1, 2, ">>");
1008       basic.DefSubr (Feq, "eq", false, 2, -1, "==");
1009       basic.DefSubr (Fnoteq, "noteq", false, 2, 2, "!=");
1010       basic.DefSubr (Flt, "lt", false, 2, -1, "<");
1011       basic.DefSubr (Fle, "le", false, 2, -1, "<=");
1012       basic.DefSubr (Fgt, "gt", false, 2, -1, ">");
1013       basic.DefSubr (Fge, "ge", false, 2, -1, ">=");
1014       basic.DefSubr (Fappend, "append", true, 0, -1);
1015       basic.DefSubr (Fconcat, "concat", true, 0, -1);
1016       basic.DefSubr (Fnth, "nth", false, 2, 2);
1017       basic.DefSubr (Fcopy, "copy", false, 1, 1);
1018       basic.DefSubr (Fins, "ins", true, 2, 2);
1019       basic.DefSubr (Fdel, "del", true, 2, 2);
1020       basic.DefSubr (Feval, "eval", false, 1, 1);
1021       basic.DefSubr (Fbreak, "break", false, 0, 1);
1022       basic.DefSubr (Freturn, "return", false, 0, 1);
1023
1024       basic.DefSpecial (Fand, "and", 1, -1, "&&");
1025       basic.DefSpecial (For, "or", 1, -1, "||");
1026       basic.DefSpecial (Fprogn, "progn", 0, -1, "expr");
1027       basic.DefSpecial (Fif, "if", 2, 3);
1028       basic.DefSpecial (Fwhen, "when", 1, -1);
1029       basic.DefSpecial (Floop, "loop", 1, -1);
1030       basic.DefSpecial (Fwhile, "while", 1, -1);
1031       basic.DefSpecial (Fcond, "cond", 1, -1);
1032       basic.DefSpecial (Fforeach, "foreach", 2, -1);
1033       basic.DefSpecial (Fquote, "quote", 1, 1);
1034       basic.DefSpecial (Ftype, "type", 1, 1);
1035       basic.DefSpecial (Fcatch, "catch", 2, 2);
1036       basic.DefSpecial (Fthrow, "throw", 1, 2);
1037     }
1038
1039     private static Term Fset (Domain domain, Variable vari, Term[] args)
1040     {
1041       vari.Value = args[0];
1042       return vari.val;
1043     }
1044
1045     private static Term Fnot (Domain domain, Variable vari, Term[] args)
1046     {
1047       return args[0].IsTrue ? Zero : One;
1048     }
1049
1050     private static Term Fadd (Domain domain, Variable vari, Term[] args)
1051     {
1052       int n = vari == null ? 0 : vari.val.Intval;
1053
1054       foreach (Term arg in args)
1055         n += arg.Intval;
1056       if (vari == null)
1057         return new Term (n);
1058       vari.val.intval = n;
1059       return vari.val;
1060     }
1061
1062     private static Term Fmul (Domain domain, Variable vari, Term[] args)
1063     {
1064       int n = vari == null ? 1 : vari.val.Intval;
1065       foreach (Term arg in args)
1066         n *= arg.Intval;
1067       if (vari == null)
1068         return new Term (n);
1069       vari.val.intval = n;
1070       return vari.val;
1071     }
1072
1073     private static Term Fsub (Domain domain, Variable vari, Term[] args)
1074     {
1075       int n, i;
1076
1077       if (vari == null)
1078         {
1079           n = args[0].Intval;
1080           i = 1;
1081         }
1082       else
1083         {
1084           n = vari.val.Intval;
1085           i = 0;
1086         }
1087       while (i < args.Length)
1088         n -= args[i++].Intval;
1089       if (vari == null)
1090         return new Term (n);
1091       vari.val.intval = n;
1092       return vari.val;
1093     }
1094
1095     private static Term Fdiv (Domain domain, Variable vari, Term[] args)
1096     {
1097       int n, i;
1098
1099       if (vari == null)
1100         {
1101           n = args[0].Intval;
1102           i = 1;
1103         }
1104       else
1105         {
1106           n = vari.val.Intval;
1107           i = 0;
1108         }
1109       while (i < args.Length)
1110         n /= args[i++].Intval;
1111       if (vari == null)
1112         return new Term (n);
1113       vari.val.intval = n;
1114       return vari.val;
1115     }
1116
1117     private static Term Fmod (Domain domain, Variable vari, Term[] args)
1118     {
1119       if (vari == null)
1120         return new Term (args[0].Intval % args[1].Intval);
1121       vari.val.intval = vari.val.Intval % args[0].Intval;
1122       return vari.val;
1123     }
1124
1125     private static Term Flogior (Domain domain, Variable vari, Term[] args)
1126     {
1127       int n = vari == null ? 0 : vari.val.Intval;
1128       foreach (Term arg in args)
1129         n |= arg.Intval;
1130       if (vari == null)
1131         return new Term (n);
1132       vari.val.intval = n;
1133       return vari.val;
1134     }
1135
1136     private static Term Flogand (Domain domain, Variable vari, Term[] args)
1137     {
1138       int n, i;
1139
1140       if (vari == null)
1141         {
1142           n = args[0].Intval;
1143           i = 1;
1144         }
1145       else
1146         {
1147           n = vari.val.Intval;
1148           i = 0;
1149         }
1150       while (i < args.Length)
1151         n &= args[i++].Intval;
1152       if (vari == null)
1153         return new Term (n);
1154       vari.val.intval = n;
1155       return vari.val;
1156     }
1157
1158     private static Term Flsh (Domain domain, Variable vari, Term[] args)
1159     {
1160       if (vari == null)
1161         return new Term (args[0].Intval << args[1].Intval);
1162       vari.val.intval = vari.val.Intval << args[0].Intval;
1163       return vari.val;
1164     }
1165
1166     private static Term Frsh (Domain domain, Variable vari, Term[] args)
1167     {
1168       if (vari == null)
1169         return new Term (args[0].Intval >> args[1].Intval);
1170       vari.val.intval = vari.val.Intval >> args[0].Intval;
1171       return vari.val;
1172     }
1173
1174     private static Term Feq (Domain domain, Variable vari, Term[] args)
1175     {
1176       Term o = args[0];
1177
1178       if (o.objval == null)
1179         {
1180           for (int i = 1; i < args.Length; i++)
1181             if (args[i].objval != null || args[i].intval != o.intval)
1182               return Zero;
1183         }
1184       else
1185         {
1186           for (int i = 1; i < args.Length; i++)
1187             if (o.objval.Equals (args[i].objval))
1188               return Zero;
1189         }
1190       return One;
1191     }
1192
1193     private static Term Fnoteq (Domain domain, Variable vari, Term[] args)
1194     {
1195       return Feq (domain, vari, args);
1196     }
1197
1198     private static Term Flt (Domain domain, Variable vari, Term[] args)
1199     {
1200       int n = args[0].Intval;
1201
1202       for (int i = 1; i < args.Length; i++)
1203         {
1204           int n1 = args[i].Intval;
1205           if (n >= n1)
1206             return Zero;
1207           n = n1;
1208         }
1209       return One;
1210     }
1211
1212     private static Term Fle (Domain domain, Variable vari, Term[] args)
1213     {
1214       int n = args[0].Intval;
1215       for (int i = 1; i < args.Length; i++)
1216         {
1217           int n1 = args[i].Intval;
1218           if (n > n1)
1219             return Zero;
1220           n = n1;
1221         }
1222       return One;
1223     }
1224
1225     private static Term Fgt (Domain domain, Variable vari, Term[] args)
1226     {
1227       int n = args[0].Intval;
1228       for (int i = 1; i < args.Length; i++)
1229         {
1230           int n1 = args[i].Intval;
1231           if (n <= n1)
1232             return Zero;
1233           n = n1;
1234         }
1235       return One;
1236     }
1237
1238     private static Term Fge (Domain domain, Variable vari, Term[] args)
1239     {
1240       int n = args[0].Intval;
1241       for (int i = 1; i < args.Length; i++)
1242         {
1243           int n1 = args[i].Intval;
1244           if (n < n1)
1245             return Zero;
1246           n = n1;
1247         }
1248       return One;
1249     }
1250
1251     private static Term Fappend (Domain domain, Variable vari, Term[] args)
1252     {
1253       List<Term> list;
1254
1255       if (vari == null)
1256         list = new List<Term> ();
1257       else
1258         list = vari.val.Listval;
1259
1260       foreach (Term arg in args)
1261         {
1262           if (arg.IsList)
1263             list.AddRange ((List<Term>) arg.objval);
1264           else
1265             list.Add (arg);
1266         }
1267       if (vari == null)
1268         {
1269           Term result;
1270           result.intval = 0;
1271           result.objval = list;
1272           return result;
1273         }
1274       return vari.val;
1275     }
1276
1277     private static Term Fconcat (Domain domain, Variable vari, Term[] args)
1278     {
1279       string str;
1280
1281       if (vari == null)
1282         str = "";
1283       else
1284         str = vari.val.Strval;
1285
1286       foreach (Term arg in args)
1287         {
1288           if (arg.IsStr)
1289             str += (string) arg.objval;
1290           else if (arg.IsList)
1291             foreach (Term term in (List<Term>) arg.objval)
1292               str += (char) term.Intval;
1293           else
1294             str += (char) arg.Intval;
1295         }
1296       if (vari == null)
1297         {
1298           Term result;
1299           result.intval = 0;
1300           result.objval = str;
1301           return result;
1302         }
1303       vari.val.objval = str;
1304       return vari.val;
1305     }
1306
1307     private static Term Fnth (Domain domain, Variable vari, Term[] args)
1308     {
1309       Term result;
1310
1311       if (args[1].IsStr)
1312         {
1313           result.intval = ((string) args[1].objval)[args[0].Intval];
1314           result.objval = null;
1315         }
1316       else if (args[1].IsList)
1317         {
1318           result = ((List<Term>) args[1].objval)[args[0].Intval];
1319         }
1320       else
1321         throw new Exception ("Term is not enumelable: " + args[1]);
1322       return result;
1323     }
1324
1325     private static Term Fcopy (Domain domain, Variable vari, Term[] args)
1326     {
1327       Term result;
1328
1329       result.intval = 0;
1330       result.objval = new List<Term> (args[0].Listval);
1331       return result;
1332     }
1333
1334     private static Term Fins (Domain domain, Variable vari, Term[] args)
1335     {
1336       if (vari.val.IsStr)
1337         vari.val.objval
1338           = vari.val.Strval.Insert (args[0].Intval, args[1].Strval);
1339       else if (vari.val.IsList)
1340         vari.val.Listval.InsertRange (args[0].Intval, args[1].Listval);
1341       else
1342         throw new Exception ("term is not collection: " + vari.val);
1343       return vari.val;
1344     }
1345
1346     private static Term Fdel (Domain domain, Variable vari, Term[] args)
1347     {
1348       if (vari.val.IsStr)
1349         vari.val.objval
1350           = vari.val.Strval.Remove (args[0].Intval,
1351                                     args[1].Intval - args[0].Intval);
1352
1353       else if (vari.val.IsList)
1354         vari.val.Listval.RemoveRange (args[0].Intval,
1355                                       args[1].Intval - args[0].Intval);
1356       else
1357         throw new Exception ("term is not collection: " + vari.val);
1358       return vari.val;
1359     }
1360
1361     private static Term Fand (Domain domain, Variable vari, Term[] args)
1362     {
1363       foreach (Term arg in args)
1364         if (! arg.Eval (domain).IsTrue)
1365           return Zero;
1366       return One;
1367     }
1368
1369     private static Term For (Domain domain, Variable vari, Term[] args)
1370     {
1371       foreach (Term arg in args)
1372         if (arg.Eval (domain).IsTrue)
1373           return One;
1374       return Zero;
1375     }
1376
1377     private static Term Feval (Domain domain, Variable vari, Term[] args)
1378     {
1379       return (args[0].Eval (domain));
1380     }
1381
1382     private static Term Fprogn (Domain domain, Variable vari, Term[] args)
1383     {
1384       Term result = One;
1385
1386       foreach (Term arg in args)
1387         result = arg.Eval (domain);
1388       return result;
1389     }
1390
1391     private static Term Fif (Domain domain, Variable vari, Term[] args)
1392     {
1393       if (args[0].Eval (domain).IsTrue)
1394         return args[1].Eval (domain);
1395       if (args.Length == 2)
1396         return Zero;
1397       return args[2].Eval (domain);
1398     }
1399
1400     private static Term Fwhen (Domain domain, Variable vari, Term[] args)
1401     {
1402       if (! args[0].Eval (domain).IsTrue)
1403         return Zero;
1404       Term result = One;
1405       for (int i = 1; i < args.Length; i++)
1406         result = args[i].Eval (domain);
1407       return result;
1408     }
1409
1410     private static Term Freturn (Domain domain, Variable vari, Term[] args)
1411     {
1412       domain.ThrowReturn ();
1413       return args.Length == 0 ? Zero : args[0];
1414     }     
1415
1416     private static Term Fbreak (Domain domain, Variable vari, Term[] args)
1417     {
1418       domain.ThrowBreak ();
1419       return args.Length == 0 ? Zero : args[0];
1420     }     
1421
1422     private static Term Floop (Domain domain, Variable vari, Term[] args)
1423     {
1424       Term result = Zero;
1425       try {
1426         domain.Catch (CatchTag.Break);
1427         while (! domain.Thrown)
1428           foreach (Term arg in args)
1429             {
1430               result = arg.Eval (domain);
1431               if (domain.Thrown)
1432                 return result;
1433             }
1434       } finally {
1435         domain.Uncatch ();
1436       }
1437       return result;
1438     }
1439
1440     private static Term Fwhile (Domain domain, Variable vari, Term[] args)
1441     {
1442       Term result = Zero;
1443       try {
1444         domain.Catch (CatchTag.Break);
1445         while (! domain.Thrown && args[0].Eval (domain).IsTrue)
1446           for (int i = 1; i < args.Length; i++)
1447             {
1448               result = args[i].Eval (domain);
1449               if (domain.Thrown)
1450                 return result;
1451             }
1452       } finally {
1453         domain.Uncatch ();
1454       }
1455       return result;
1456     }
1457
1458     private static Term Fcond (Domain domain, Variable vari, Term[] args)
1459     {
1460       foreach (Term arg in args)
1461         {
1462           List<Term> list = arg.Listval;
1463           Term result = list[0].Eval (domain);
1464
1465           if (result.IsTrue)
1466             {
1467               for (int i = 1; i < list.Count; i++)
1468                 result = list[i].Eval (domain);
1469               return result;
1470             }
1471         }
1472       return Zero;
1473     }
1474
1475     private static Term Fforeach (Domain domain, Variable vari,
1476                                         Term[] args)
1477     {
1478       Term result = args[0].Eval (domain);
1479       if (domain.Thrown)
1480         return result;
1481       List<Term> list = result.Listval;
1482       Bindings current = domain.bindings;
1483
1484       try {
1485         domain.Catch (CatchTag.Break);
1486         foreach (Term term in list)
1487           {
1488             domain.Bind (vari, term);
1489             try {
1490               for (int i = 1; i < args.Length; i++)
1491                 {
1492                   result = args[i].Eval (domain);
1493                   if (domain.Thrown)
1494                     return result;
1495                 }
1496             } finally {
1497               domain.UnboundTo (current);
1498             }
1499           }
1500       } finally {
1501         domain.Uncatch ();
1502       }
1503       return result;
1504     }
1505
1506     private static Term Fquote (Domain domain, Variable vari, Term[] args)
1507     {
1508       return new Term (args[0]);
1509     }
1510
1511     private static Term Ftype (Domain domain, Variable vari, Term[] args)
1512     {
1513       if (args[0].IsInt)
1514         return TermInt;
1515       if (args[0].IsStr)
1516         return TermStr;
1517       if (args[0].IsSymbol)
1518         return TermSymbol;
1519       if (args[0].IsList)
1520         return TermList;
1521       return TermTerm;
1522     }
1523
1524     public static Term Fcatch (Domain domain, Variable vari, Term[] args)
1525     {
1526       Term result = Zero;
1527       try {
1528         domain.Catch (new CatchTag (args[0].Symval));
1529         result = args[1].Eval (domain);
1530       } finally {
1531         domain.Uncatch ();
1532       }
1533       return result;
1534     }
1535
1536     public static Term Fthrow (Domain domain, Variable vari, Term[] args)
1537     {
1538       domain.ThrowTag (new CatchTag (args[0].Symval));
1539       return (args.Length == 1 ? Zero : args[1]);
1540     }
1541
1542     public delegate TermValue NewObject (Domain domain, XmlNode node);
1543
1544     public class TermType
1545     {
1546       public readonly Symbol type;
1547       internal readonly NewObject New;
1548
1549       public TermType (Symbol type, NewObject new_object)
1550       {
1551         this.type = type;
1552         New = new_object;
1553       }
1554     }
1555
1556     public abstract class TermValue
1557     {
1558       public virtual Term Eval (Domain domain) { return new Term (this); }
1559       public abstract TermValue Clone ();
1560     }
1561
1562     private class Funcall : TermValue
1563     {
1564       internal Function func;
1565       internal Variable vari;
1566       internal Term[] args;
1567
1568       private Funcall (Function func, Variable vari, Term[] args)
1569         {
1570           this.func = func;
1571           this.vari = vari;
1572           this.args = args;
1573         }
1574
1575       public Funcall (Domain domain, Symbol fname, Term[] args)
1576         {
1577           func = domain.GetFunc (fname);
1578           this.args = args;
1579         }
1580
1581       public Funcall (Domain domain, Symbol fname, Symbol vname, Term[] args)
1582         {
1583           func = domain.GetFunc (fname);
1584           int nargs = args.Length;
1585           if (nargs < func.min_arg
1586               || (func.max_arg >= 0 && nargs > func.max_arg))
1587             throw new Exception ("Invalid number of arguments to: "
1588                                  + fname + " " + nargs);
1589           this.args = args;
1590           if (vname != Nnull)
1591             vari = domain.GetVar (vname, true);
1592         }
1593
1594       internal static TermValue New (Domain domain, XmlNode node)
1595         {
1596           Symbol fname = node.Name;
1597           Symbol vname = Nnull;
1598           XmlAttribute attr;
1599
1600           if (fname == Nfuncall)
1601             fname = node.Attributes[Nfname].Value;
1602           attr = node.Attributes[Nvname];
1603           if (attr != null)
1604             vname = attr.Value;
1605
1606           XmlNodeList nlist = node.ChildNodes;
1607           int nargs = nlist.Count;
1608           Term[] args = new Term[nargs];
1609           for (int i = 0; i < nargs; i++)
1610             args[i] = new Term (domain, nlist[i]);
1611           return new Funcall (domain, fname, vname, args);
1612         }
1613
1614       public override Term Eval (Domain domain)
1615       {
1616         domain.DebugWrite (true, "(({0}", func.name);
1617         for (int i = 0; i < args.Length; i++)
1618           domain.DebugWrite (false, " {0}", args[i].ToString ());
1619         domain.DebugWrite (false, ")");
1620         domain.depth++;
1621         Term result = func.Call (domain, vari, args);
1622         domain.depth--;
1623         domain.DebugWrite (true, " ==> {0})", result.ToString ());
1624         return result;
1625       }
1626
1627       public override TermValue Clone ()
1628       {
1629         return new Funcall (func, vari, args);
1630       }
1631
1632       public override string ToString ()
1633       {
1634         string str = "<funcall fname=\"" + func.name;
1635         if (args == null)
1636           return str + "\"/>";
1637         str += "\">";
1638         foreach (Term e in args)
1639           str += e;
1640         return (str + "</funcall>");
1641       }
1642     }
1643
1644     public struct Term
1645     {
1646       public int intval;
1647       public object objval;
1648
1649       public Term (int i) { intval = i; objval = null; }
1650       public Term (Symbol name) { intval = 0; objval = name; }
1651       public Term (string str) { intval = 0; objval = str; }
1652       public Term (List<Term> list) { intval = 0; objval = list; }
1653       public Term (Term term) { intval = term.intval; objval = term.objval; }
1654       public Term (TermValue obj) { intval = 0; objval = obj; }
1655
1656       public Term (Domain domain, XmlNode node)
1657         {
1658           Symbol name = node.Name;
1659
1660           if (name == Ninteger)
1661             {
1662               intval = parse_integer (node.InnerText);
1663               objval = null;
1664             }
1665           else
1666             {
1667               intval = 0;
1668               if (name == Nsymbol)
1669                 objval = (Symbol) node.InnerText;
1670               else if (name == Nstring)
1671                 objval = node.InnerText.Clone ();
1672               else if (name == Nvarref)
1673                 objval = domain.GetVar ((Symbol) node.Attributes[0].Value, true);
1674               else if (name == Nlist)
1675                 {
1676                   List<Term> list = new List<Term> ();
1677                   for (node = node.FirstChild; node != null;
1678                        node = node.NextSibling)
1679                     list.Add (new Term (domain, node));
1680                   objval = list;
1681                 }
1682               else
1683                 {
1684                   TermType term_type;
1685
1686                   if (domain.termtypes.TryGetValue (name, out term_type))
1687                     objval = term_type.New (domain, node);
1688                   else
1689                     objval = Funcall.New (domain, node);
1690                 }
1691             }
1692         }
1693
1694       public Term (Domain domain, Symbol fname, Term[] args)
1695         {
1696           intval = 0;
1697           objval = new Funcall (domain, fname, args);
1698         }
1699
1700       public Term (Domain domain, Symbol fname, Symbol vname, Term[] args)
1701         {
1702           intval = 0;
1703           objval = new Funcall (domain, fname, vname, args);
1704         }
1705
1706       public object Objval {
1707         get {
1708           if (objval == null)
1709             throw new Exception ("term is an integer: " + this);
1710           return objval;
1711         }
1712       }
1713
1714       public int Intval {
1715         get {
1716           if (objval != null)
1717             throw new Exception ("term is not integer: " + this);
1718           return intval;
1719         }
1720       }
1721
1722       public string Strval {
1723         get {
1724           if (! IsStr)
1725             throw new Exception ("term is not string: " + this);
1726           return (string) objval;
1727         }
1728       }
1729
1730       public string Symval {
1731         get {
1732           if (! IsSymbol)
1733             throw new Exception ("term is not symbol: " + this);
1734           return (Symbol) objval;
1735         }
1736       }
1737
1738       public List<Term> Listval {
1739         get {
1740           if (! IsList)
1741             throw new Exception ("term is not list: " + this);
1742           return (List<Term>) objval;
1743         }
1744       }
1745
1746       public bool IsTrue {
1747         get {
1748           return (objval == null
1749                   ? (intval != 0)
1750                   : objval is List<Term>
1751                   ? (((List<Term>) objval).Count != 0)
1752                   : true);
1753         }
1754       }
1755       public bool IsInt { get { return (objval == null); } }
1756       public bool IsStr { get { return (objval is string); } }
1757       public bool IsSymbol { get { return (objval is Symbol); } }
1758       public bool IsList { get { return (objval is List<Term>); } }
1759
1760       public bool IsType (Type type)
1761       {
1762         return (objval == null ? type == typeof (int)
1763                 : type == objval.GetType ());
1764       }
1765
1766       public Term Eval (Domain domain)
1767       {
1768         if (objval == null || objval is Symbol || objval is string)
1769           return this;
1770         if (objval is List<Term>)
1771           return new Term ((List<Term>) objval);
1772         return ((TermValue) objval).Eval (domain);
1773       }
1774
1775       public Term Clone ()
1776       {
1777         if (objval == null || objval is Symbol || objval is string)
1778           return this;
1779         if (objval is List<Term>)
1780           {
1781             List<Term> list = new List<Term> ();
1782             list.InsertRange (0, ((List<Term>) objval));
1783             return new Term (list);
1784           }
1785         return new Term (((TermValue) objval).Clone ());
1786       }
1787
1788       public override string ToString ()
1789       {
1790         string str;
1791
1792         if (objval == null)
1793           str = "<integer>" + intval + "</integer>";
1794         else if (objval is Symbol)
1795           str = "<symbol>" + objval + "</symbol>";
1796         else if (objval is string)
1797           str = "<string>" + objval + "</string>";
1798         else if (objval is List<Term>)
1799           {
1800             str = "<list>";
1801             foreach (Term e in (List<Term>) objval)
1802               str += e;
1803             str += "</list>";
1804           }
1805         else if (objval is Funcall)
1806           str = "<funcall fname=\"" + ((Funcall) objval).func.name + "\"/>";
1807         else if (objval is Variable)
1808           str = "<variable vname=\"" + ((Variable) objval).name + "\"/>";
1809         else if (objval is Term)
1810           str = "<quote>" + objval + "</quote>";
1811         else
1812           throw new Exception ("invalid Term object: " + objval);
1813         return str;
1814       }
1815     }
1816
1817     static private Term Zero = new Term (0);
1818     static private Term One = new Term (1);
1819     static private Term TermInt = new Term (Ninteger);
1820     static private Term TermStr = new Term (Nstring);
1821     static private Term TermSymbol = new Term (Nsymbol);
1822     static private Term TermList = new Term (Nlist);
1823     static private Term TermTerm = new Term ((Symbol) "term");
1824
1825     internal static int parse_integer (string str)
1826     {
1827       int len = str.Length;
1828       bool negative = false;
1829
1830       if (len <= 1)
1831         return (len == 0 ? 0 : str[0] - '0');
1832
1833       int c = str[0];
1834       int i;
1835
1836       if (c == '?')
1837         return str[1];
1838       if ((c == '0' || c == '#') && str[1] == 'x')
1839         {
1840           i = 0;
1841           for (int idx = 2; idx < len; idx++)
1842             {
1843               c = str[idx];
1844               if (c < '0')
1845                 break;
1846               else if (c <= '9')
1847                 i = i * 16 + (c - '0');
1848               else if (c < 'A')
1849                 break;
1850               else if (c <= 'F')
1851                 i = i * 16 + (c - 'A');
1852               else if (c < 'a')
1853                 break;
1854               else if (c <= 'f')
1855                 i = i * 16 + (c - 'a');
1856               else
1857                 break;
1858             }
1859           return i;
1860         }
1861       if (c == '-')
1862         negative = true;
1863       i = c - '0';
1864       for (int idx = 1; idx < len; idx++)
1865         {
1866           c = str[idx];
1867           if (c < '0' || c > '9')
1868             break;
1869           i = i * 10 + (c - '0');
1870         }
1871       return negative ? - i : i;
1872     }
1873
1874     private Term[] terms;
1875
1876     private void parse_terms (Domain domain, XmlNode node)
1877     {
1878       int nterms = 0;
1879       for (XmlNode n = node; n != null; n = n.NextSibling)
1880         if (n.NodeType == XmlNodeType.Element)
1881           {
1882             if (n.Name == Ndefun)
1883               domain.Defun (n, true);
1884             else if (n.Name == Ndefvar)
1885               domain.Defvar (n);
1886             else
1887               nterms++;
1888           }
1889
1890       terms = new Term[nterms];
1891       int i = 0;
1892       for (XmlNode n = node; n != null; n = n.NextSibling)
1893         if (n.NodeType == XmlNodeType.Element)
1894           {
1895             if (n.Name == Ndefun)
1896               domain.Defun (n, false);
1897             else if (n.Name != Ndefvar)
1898               terms[i++]= new Term (domain, n);
1899           }
1900     }
1901
1902     public Xexpression (Domain domain, XmlNode node)
1903     {
1904       parse_terms (domain, node);
1905     }
1906
1907     public Xexpression (Domain domain, string url)
1908     {
1909       XmlDocument doc = new XmlDocument (Symbol.Table);
1910       XmlNode node;
1911
1912       using (XmlTextReader reader = new XmlTextReader (url, Symbol.Table))
1913         {
1914           do {
1915             reader.Read ();
1916           } while (reader.NodeType != XmlNodeType.None
1917                    && (reader.NodeType != XmlNodeType.Element
1918                        || reader.Name != Nexpr));
1919           if (reader.NodeType == XmlNodeType.None)
1920             throw new Exception ("Node <expr> not found");
1921           node = doc.ReadNode (reader);
1922         }
1923       parse_terms (domain, node.FirstChild);
1924     }
1925
1926     public Term Eval (Domain domain)
1927     {
1928       Term result = Zero;
1929
1930       domain.depth = 0;
1931       try {
1932         domain.Catch (CatchTag.Return);
1933         foreach (Term term in terms)
1934           {
1935             result = term.Eval (domain);
1936             if (domain.Thrown)
1937               return result;
1938           }
1939       } finally {
1940         domain.Uncatch ();
1941       }
1942       return result;
1943     }
1944
1945     public override string ToString ()
1946     {
1947       string str = "";
1948       for (int i = 0; i < terms.Length; i++)
1949         str += terms[i];
1950       return str;
1951     }
1952   }
1953 }