*** 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.Reflection;
6 using System.Text;
7 using System.Text.RegularExpressions;
8 using System.Xml;
9
10 namespace System.Xml
11 {
12   public static class Xexpression
13   {
14     private static int trace_depth = 0;
15
16     public static int TraceDepth {
17       get { return trace_depth; }
18       set { trace_depth = value; }
19     }
20
21     public class Error : Exception
22     {
23       private readonly Symbol name;
24       private Term[] stack;
25       private XmlNode node;
26
27       public Error (Symbol name, XmlNode node,
28                     string fmt, params object[] args)
29         : base (String.Format (fmt, args))
30         {
31           this.name = name;
32           this.node = node;
33         }
34
35       public Error (Symbol name, XmlNode node, Exception e,
36                     string fmt, params object[] args)
37         : base (String.Format (fmt, args), e)
38         {
39           this.name = name;
40           this.node = node;
41         }
42
43       public Error (Symbol name, string fmt, params object[] args)
44         : base (String.Format (fmt, args))
45         {
46           this.name = name;
47         }
48
49       public Symbol Name { get { return name; } }
50       public XmlNode Node {
51         get { return node; }
52         internal set { node = value; }
53       }
54       public Term[] Stack {
55         get { return stack; }
56         internal set { stack = value; }
57       }
58
59       public override string ToString ()
60       {
61         string str = (InnerException != null ? InnerException.ToString ()
62                       : base.ToString ()) + "\n" + "Xexpression:" + name + "\n";
63         if (node != null)
64           str += "  at " + node.Parent.OuterXml + "\n";
65         if (stack != null)
66           {
67             str += "Call stack: ";
68             foreach (Term term in stack)
69               str += term.ToString (false);
70           }
71         return str;
72       }
73
74       // All time errors.
75       // System.OutOfMemoryException or System.InsufficientMemoryException
76       public static Symbol MemoryError = "memory-error";
77       // System.Exception
78       public static Symbol UnknownError = "unknown-error";
79       public static Symbol WrongArgument = "wrong-argument";
80
81       // Load time errors.
82       public static Symbol InvalidInteger = "invalid-integer";
83       public static Symbol TermTypeInvalid = "term-type-invalid";
84       public static Symbol FunctionConflict = "function-conflict";
85       public static Symbol VariableTypeConflict = "variable-type-conflict";
86       public static Symbol VariableRangeConflict = "variable-range-conflict";
87       public static Symbol VariableWrongRange = "variable-wrong-range";
88       public static Symbol VariableWrongValue = "variable-wrong-value";
89       public static Symbol UnknownFunction = "unknown-function";
90       public static Symbol MacroExpansionError = "macro-expansion-error";
91       public static Symbol NoVariableName = "no-variable-anme";
92
93       // Run time errors.
94       public static Symbol ArithmeticError = "arithmetic-error";
95       public static Symbol WrongType = "wrong-type";
96       public static Symbol IndexOutOfRange = "index-out-of-range";
97       public static Symbol ValueOutOfRange = "value-out-of-range";
98       public static Symbol NoLoopToBreak = "no-loop-to-break";
99       public static Symbol UncaughtThrow = "uncaught-throw";
100     }
101
102     public struct Symbol : IEquatable<Symbol>
103     {
104       private static NameTable nt = new NameTable ();
105
106       private string name;
107
108       public Symbol (string str) { name = nt.Add (str); }
109
110       public static implicit operator Symbol (string str)
111       {
112         return new Symbol (str);
113       }
114
115       public static implicit operator string (Symbol sym) { return sym.name; }
116
117       public static bool operator== (Symbol n1, Symbol n2)
118         {
119           return (object) n1.name == (object) n2.name;
120         }
121
122       public static bool operator!= (Symbol n1, Symbol n2)
123         {
124           return (object) n1.name != (object) n2.name;
125         }
126
127       public static bool operator== (Symbol n1, string n2)
128         {
129           return (object) n1.name == (object) n2;
130         }
131
132       public static bool operator!= (Symbol n1, string n2)
133         {
134           return (object) n1.name != (object) n2;
135         }
136
137       public static bool operator== (string n1, Symbol n2)
138         {
139           return (object) n1 == (object) n2.name;
140         }
141
142       public static bool operator!= (string n1, Symbol n2)
143         {
144           return (object) n1 != (object) n2.name;
145         }
146
147       public bool Equals (Symbol name)
148       {
149         return Object.ReferenceEquals (this.name, name.name);
150       }
151
152       public override bool Equals (object obj)
153       {
154         return (obj is Symbol ? this == (Symbol) obj
155                 : obj is string ? this.name == (string) obj
156                 : false);
157       }
158
159       public override int GetHashCode ()
160       {
161         return name.GetHashCode ();
162       }
163
164       public static NameTable NameTable { get { return nt; } }
165
166       public override string ToString () { return name; }
167     }
168
169     private static Symbol Qexpr = "expr";
170
171     private static Symbol Qnull = "";
172     private static Symbol Qfuncall = "funcall";
173     private static Symbol Qinteger = "integer";
174     private static Symbol Qstring = "string";
175     private static Symbol Qsymbol = "symbol";
176     private static Symbol Qlist = "list";
177
178     public static Symbol Qdefun = "defun";
179     public static Symbol Qdefmacro = "defmacro";
180     private static Symbol Qfname = "fname";
181     private static Symbol Qargs = "args";
182     private static Symbol Qfixed = "fixed";
183     private static Symbol Qoptional = "optional";
184     private static Symbol Qrest = "rest";
185
186     public static Symbol Qdefvar = "defvar";
187     private static Symbol Qvname = "vname";
188     private static Symbol Qdescription = "description";
189     private static Symbol Qrange = "range";
190
191     private static Symbol Qename = "ename";
192
193     public class Variable
194     {
195       public Domain domain;
196       public readonly Symbol name;
197       protected Term val;
198
199       public Variable (Domain domain, Symbol name, Term val)
200       {
201         this.domain = domain;
202         this.name = name;
203         this.val = val;
204       }
205
206       public Term Value { get { return val; } }
207
208       public virtual Term SetValue (Term val) { this.val = val; return val; }
209
210       public virtual Variable Clone (Domain domain)
211       {
212         return new Variable (domain, name, val);
213       }
214
215       public virtual void Reset () { val = Zero; }
216
217       public override string ToString () { return name + "(" + val + ")"; }
218
219       public abstract class Typed : Variable
220       {
221         protected string desc;
222         private Term default_val;
223
224         protected Typed (Domain domain, Symbol name, Term val, string desc)
225           : base (domain, name, val)
226           {
227             this.desc = desc;
228             default_val = val;
229           }
230
231         public override void Reset () { val = default_val; }
232
233         public string Description {
234           get { return desc; }
235           set { desc = value; }
236         }
237
238         public override Term SetValue (Term val)
239         {
240           if (! CheckValue (val))
241             throw new Error (Error.VariableWrongValue,
242                              "Wrong value for variable {0}: {1}",
243                              name, val);
244           this.val = val;
245           return val;
246         }
247
248         public abstract bool CheckValue (Term val);
249       }
250
251       public class IntType : Typed
252       {
253         private int[] range;
254
255         public bool IsSubrange (int[] r)
256           {
257             if (range == null)
258               return true;
259             for (int i = 0; i < r.Length; i += 2)
260               {
261                 int j;
262                 for (j = 0; j < range.Length; j += 2)
263                   if (range[j] <= r[i] && range[j + 1] >= r[i + 1])
264                     break;
265                 if (j >= range.Length)
266                   return false;
267               }
268             return true;
269           }
270
271         public IntType (Domain domain, Symbol name, int n, string desc,
272                         int[] range)
273           : base (domain, name, new Term (n), desc)
274           {
275             if (range != null && range.Length % 2 == 1)
276               throw new Error (Error.VariableWrongRange,
277                                "Range length for {0} not even", name);
278             this.range = range;
279             CheckValue (val);
280           }
281
282         public override bool CheckValue (Term term)
283         {
284           if (term.IsInt)
285             {
286               if (range == null)
287                 return true;
288               int n = term.Intval;
289               for (int i = 0; i < range.Length; i += 2)
290                 if (range[i] <= n && range[i + 1] >= n)
291                   return true;
292             }
293           return false;
294         }
295
296         public override Variable Clone (Domain domain)
297         {
298           return new IntType (domain, name, val.Intval, desc, range);
299         }
300
301         public int[] Range { get { return range; } set { range = value; } }
302       }
303
304       public class StrType : Typed
305       {
306         private string[] range;
307
308         public bool IsSubrange (string[] r)
309           {
310             if (range == null)
311               return true;
312             for (int i = 0; i < r.Length; i++)
313               {
314                 int j;
315                 for (j = 0; j < range.Length; j++)
316                   if (range[j] == r[i])
317                     break;
318                 if (j >= range.Length)
319                   return false;
320               }
321             return true;
322           }
323
324         public StrType (Domain domain, Symbol name, Str str, string desc,
325                         string[] range)
326           : base (domain, name, new Term (str), desc)
327           {
328             this.range = range;
329             CheckValue (val);
330           }
331
332         public override bool CheckValue (Term val)
333         {
334           if (val.IsStr)
335             {
336               if (range == null)
337                 return true;
338               Str str = val.Strval;
339               foreach (string s in range)
340                 if (str.Equals (s))
341                   return true;
342             }
343           return false;
344         }
345
346         public override Variable Clone (Domain domain)
347         {
348           return new StrType (domain, name, val.Strval, desc, range);
349         }
350
351         public string[] Range { get { return range; } set { range = value; } }
352       }
353
354       public class SymType : Typed
355       {
356         public Symbol[] range;
357
358         public bool IsSubrange (Symbol[] r)
359           {
360             if (range == null)
361               return true;
362             for (int i = 0; i < r.Length; i++)
363               {
364                 int j;
365                 for (j = 0; j < range.Length; j++)
366                   if (range[j] == r[i])
367                     break;
368                 if (j >= range.Length)
369                   return false;
370               }
371             return true;
372           }
373
374         public SymType (Domain domain, Symbol name, Symbol sym, string desc,
375                         Symbol[] range)
376           : base (domain, name, new Term (sym), desc)
377           {
378             this.range = range;
379             CheckValue (val);
380           }
381
382         public override bool CheckValue (Term val)
383         {
384           if (val.IsSymbol)
385             {
386               if (range == null)
387                 return true;
388               Symbol sym = val.Symval;
389               foreach (Symbol n in range)
390                 if (sym == n)
391                   return true;
392             }
393           return false;
394         }
395
396         public override Variable Clone (Domain domain)
397         {
398           return new SymType (domain, name, val.Symval, desc, range);
399         }
400
401         public Symbol[] Range { get { return range; } set { range = value; } }
402       }
403     }
404
405     public abstract class Function
406     {
407       public Symbol name;
408       // True iff the function can be called with vname="VNAME" attribute.
409       internal readonly  bool with_var;
410       // Minimum number of positional arguments.
411       internal readonly int min_args;
412       // If non-nengative, maximum number of arguments.  If negative,
413       // maxinum number of positional arguments is (-1 - max_args),
414       // and the remaining unlimit number of arguments are given as a
415       // single list.
416       internal readonly int max_args;
417
418       public delegate Term Builtin (Domain domain, Variable vari, Term[] terms);
419
420       public Function () { }
421
422       public Function (Symbol name, bool with_var, int min_args, int max_args)
423       {
424         this.name = name;
425         this.with_var = with_var;
426         this.min_args = min_args;
427         this.max_args = max_args;
428       }
429
430       public abstract Term Call (Domain domain, Variable vari, Term[] args);
431
432       public override string ToString ()
433       {
434         return name;
435       }
436
437       internal class Subroutine : Function
438       {
439         public Builtin builtin;
440
441         public Subroutine (Builtin builtin, Symbol name, bool with_var,
442                            int min_args, int max_args)
443           : base (name, with_var, min_args, max_args)
444           {
445             this.builtin = builtin;
446           }
447
448         public override Term Call (Domain domain, Variable vari, Term[] args)
449         {
450           if (args.Length > 0)
451             {
452               args = (Term[]) args.Clone ();
453               for (int i = 0; i < args.Length; i++)
454                 {
455                   args[i] = args[i].Eval (domain);
456                   if (domain.Thrown ())
457                     return args[i];
458                 }
459             }
460           return builtin (domain, vari, args);
461         }
462       }
463
464       internal class SpecialForm : Function
465       {
466         public Builtin builtin;
467
468         public SpecialForm (Builtin builtin, Symbol name, bool with_var,
469                             int min_args, int max_args)
470           : base (name, with_var, min_args, max_args)
471           {
472             this.builtin = builtin;
473           }
474
475         public override Term Call (Domain domain, Variable vari, Term[] args)
476         {
477           return builtin (domain, vari, args);
478         }
479       }
480
481       internal class Lambda : Function
482       {
483         private Variable[] args;
484         private Term[] body;
485
486         public Lambda (Symbol name, int min_args, int max_args, Variable[] args,
487                        Term[] body)
488           : base (name, false, min_args, max_args)
489           {
490             this.args = args;
491             this.body = body;
492           }
493
494         public void SetBody (Term[] body)
495         {
496           this.body = body;
497         }
498
499         public override Term Call (Domain domain, Variable vari, Term[] args)
500         {
501           Bindings current = domain.bindings;
502           Term result = Zero;
503           int limit = max_args >= 0 ? args.Length : args.Length - 1;
504
505           try {
506             for (int i = 0; i < limit; i++)
507               {
508                 result = args[i].Eval (domain);
509                 if (domain.Thrown ())
510                   return result;
511                 domain.Bind (this.args[i], result);
512               }
513             if (max_args < 0)
514               {
515                 List<Term> list = new List<Term> ();
516                 list.InsertRange (0, args[limit].Listval);
517
518                 for (int i = 0; i < list.Count; i++)
519                   {
520                     result = list[i].Eval (domain);
521                     if (domain.Thrown ())
522                       return result;
523                     list[i] = result;
524                   }
525                 domain.Bind (this.args[limit], new Term (list));
526               }
527             try {
528               domain.Catch (CatchTag.Return);
529               foreach (Term term in body)
530                 {
531                   result = term.Eval (domain);
532                   if (domain.Thrown ())
533                     return result;
534                 }
535             } finally {
536               domain.Uncatch ();
537             }
538           } finally {
539             domain.UnboundTo (current);
540           }
541           return result;
542         }
543       }
544
545       internal class Macro : Function
546       {
547         private Variable[] args;
548         private Term[] body;
549
550         public Macro (Symbol name, int min_args, int max_args, Variable[] args,
551                       Term[] body)
552           : base (name, false, min_args, max_args)
553           {
554             this.args = args;
555             this.body = body;
556           }
557
558         public void SetBody (Term[] body)
559         {
560           this.body = body;
561         }
562
563         public override Term Call (Domain domain, Variable vari, Term[] args)
564         {
565           Bindings current = domain.bindings;
566           Term result = Zero;
567
568           try {
569             for (int i = 0; i < args.Length; i++)
570               domain.Bind (this.args[i], args[i]);
571             try {
572               domain.Catch (CatchTag.Return);
573               foreach (Term term in body)
574                 {
575                   result = term.Eval (domain);
576                   if (domain.Thrown ())
577                     break;
578                 }
579             } finally {
580               domain.Uncatch ();
581             }
582           } finally {
583             domain.UnboundTo (current);
584           }
585           return result;
586         }
587       }
588     }
589
590     internal class Bindings
591     {
592       private Variable vari;
593       private Term old_value;
594       private Bindings next;
595         
596       private Bindings (Variable vari)
597       {
598         this.vari = vari;
599         old_value = vari.Value;
600       }
601         
602       public static Bindings Bind (Bindings bindings, Variable vari, Term val)
603       {
604         Bindings b = new Bindings (vari);
605
606         b.vari.SetValue (val);
607         b.next = bindings;
608         return b;
609       }
610
611       internal Bindings UnboundTo (Bindings boundary)
612       {
613         for (Bindings b = this; b != boundary; b = b.next)
614           b.vari.SetValue (b.old_value);
615         return boundary;
616       }
617
618       public override string ToString ()
619       {
620         string str = "(bindings";
621         for (Bindings b = this; b != null; b = b.next)
622           str += " " + vari.name + "=" + b.old_value;
623         return str + ")";
624       }
625     }
626
627     internal struct CatchTag
628     {
629       private Term tag;
630       public Term Tag { get { return tag; } }
631
632       // Normal symbolic catch-tag.
633       public CatchTag (Symbol sym) { tag = new Term (sym); }
634       // Special catch-tag for return and break.
635       private CatchTag (int i) { tag = new Term (i); }
636
637       public static CatchTag Return = new CatchTag (0);
638       public static CatchTag Break = new CatchTag (1);
639     }
640
641     public class Domain
642     {
643       public Symbol name;
644       public object context;
645       public int depth = 0;
646       private Stack<Term> call_stack = new Stack<Term> ();
647
648       internal Dictionary<Symbol, MethodInfo> termtypes
649         = new Dictionary<Symbol, MethodInfo> ();
650       internal Dictionary<Symbol, Function> functions
651         = new Dictionary<Symbol, Function> ();
652       internal Dictionary<Symbol, Variable> variables
653         = new Dictionary<Symbol, Variable> ();
654       internal Bindings bindings;
655       private Stack<CatchTag> catch_stack = new Stack<CatchTag> ();
656       private int catch_count = 0;
657
658       internal Domain (Symbol name) { this.name = name; }
659
660       public Domain (Symbol name, object context)
661         : this (name, basic, context) { }
662
663       public Domain (Symbol name, Domain parent, object context) : this (name)
664       {
665         termtypes = new Dictionary<Symbol, MethodInfo> (parent.termtypes);
666         functions = new Dictionary<Symbol, Function> (parent.functions);
667         variables = new Dictionary<Symbol, Variable> (parent.variables);
668         this.context = context;
669       }
670
671       public int CallStackCount { get { return call_stack.Count; } }
672
673       public void CallStackPush (Term term) { call_stack.Push (term); }
674
675       public void CallStackPop () { call_stack.Pop (); }
676
677       public void CallStackPop (int count)
678       {
679         while (count < call_stack.Count)
680           call_stack.Pop ();
681       }
682
683       public Term[] CallStack { get { return call_stack.ToArray (); } }
684
685       internal void Bind (Variable vari, Term value)
686       {
687         bindings = Bindings.Bind (bindings, vari, value);
688       }
689
690       internal void UnboundTo (Bindings boundary)
691       {
692         if (bindings != null)
693           bindings = bindings.UnboundTo (boundary);
694       }
695
696       internal void Catch (CatchTag tag)
697       {
698         catch_stack.Push (tag);
699         catch_count++;
700       }
701
702       internal void Uncatch ()
703       {
704         catch_stack.Pop ();
705         if (catch_count > catch_stack.Count)
706           catch_count--;
707       }
708
709       public bool Thrown () { return catch_count < catch_stack.Count; }
710
711       public bool Thrown (out bool caught)
712       {
713         if (catch_count < catch_stack.Count)
714           {
715             caught = catch_count == catch_stack.Count - 1;
716             return true;
717           }
718         caught = false;
719         return false;
720       }
721
722       internal void ThrowReturn ()
723       {
724         foreach (CatchTag elt in catch_stack)
725           {
726             catch_count--;
727             if (elt.Tag == CatchTag.Return.Tag)
728               break;
729           }
730       }
731
732       internal void ThrowBreak ()
733       {
734         if (catch_stack.Peek ().Tag != CatchTag.Break.Tag)
735           throw new Error (Error.NoLoopToBreak,
736                            "No surrounding loop to break");
737         catch_count--;
738       }
739
740       internal void ThrowSymbol (Term tag)
741       {
742         foreach (CatchTag elt in catch_stack)
743           {
744             catch_count--;
745             if (elt.Tag.Matches (tag))
746               return;
747           }
748         throw new Error (Error.UncaughtThrow,
749                          "No corresponding catch: {0}", tag);
750       }
751
752       public void DefType (Type type)
753       {
754         if (! type.IsSubclassOf (typeof (TermValue)))
755           throw new Error (Error.TermTypeInvalid,
756                            "Not a subclass of TermValue: {0}", type);
757         BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
758         FieldInfo finfo = type.GetField ("name", flags);
759         if (finfo == null || finfo.FieldType != typeof (Symbol))
760           throw new Error (Error.TermTypeInvalid,
761                            "No \"name\" field of string type: {0}", type);
762         Symbol name = (Symbol) finfo.GetValue (null);
763         if (termtypes.ContainsKey (name))
764           throw new Error (Error.TermTypeInvalid,
765                            "Already defined: {0}", name);
766         if (functions.ContainsKey (name))
767           throw new Error (Error.TermTypeInvalid,
768                            "Already defined as a function or a macro: {0}",
769                            name);
770         Type[] types = new Type[] { typeof (Domain), typeof (XmlNode) };
771         MethodInfo parser = type.GetMethod ("Parser", types);
772         if (parser == null || parser.ReturnType != typeof (TermValue))
773           throw new Error (Error.TermTypeInvalid,
774                            "No \"Parser\" method of correct type: {0}", type);
775         termtypes[name] = parser;
776       }
777
778       private void check_func_head (Symbol name, bool with_var,
779                                     int min_args, int max_args, bool as_macro)
780       {
781         if (termtypes.ContainsKey (name))
782           throw new Error (Error.FunctionConflict,
783                            "Already defined as a term type: {0}", name);
784         Function func;
785         if (functions.TryGetValue (name, out func))
786           {
787             if ((func is Function.Macro) != as_macro)
788               throw new Error (Error.FunctionConflict,
789                                "Already defined as a {0}: {1}",
790                                as_macro ? "function" : "macro", name);
791             if (func.with_var != with_var
792                 || func.min_args != min_args
793                 || func.max_args != max_args)
794               throw new Error (Error.FunctionConflict,
795                                "Conflicting arguments: {0}", name);
796           }
797       }
798
799       public void DefSubr (Function.Builtin builtin, Symbol name,
800                            bool with_var, int min_args, int max_args)
801       {
802         check_func_head (name, with_var, min_args, max_args, false);
803         functions[name] = new Function.Subroutine (builtin, name, with_var,
804                                                    min_args, max_args);
805       }
806
807       public void DefSpecial (Function.Builtin builtin, Symbol name,
808                               bool with_var, int min_args, int max_args)
809       {
810         check_func_head (name, with_var, min_args, max_args, false);
811         functions[name] = new Function.SpecialForm (builtin, name, with_var,
812                                                     min_args, max_args);
813       }
814
815       public void Defun (Symbol name, int min_args, int max_args,
816                          Variable[] args, Term[] body)
817       {
818         check_func_head (name, false, min_args, max_args, false);
819         functions[name] = new Function.Lambda (name, min_args, max_args,
820                                                args, body);
821       }
822
823       public void Defun (Function func)
824       {
825         functions[func.name] = func;
826       }
827
828       public void Defmacro (Symbol name, int min_args, int max_args,
829                             Variable[] args, Term[] body)
830       {
831         check_func_head (name, false, min_args, max_args, true);
832         functions[name] = new Function.Macro (name, min_args, max_args,
833                                               args, body);
834       }
835
836       public void DefAlias (Symbol alias, Symbol fname)
837       {
838         Function func;
839         if (termtypes.ContainsKey (alias))
840           throw new Error (Error.FunctionConflict,
841                            "Alread defined as a term type: {0}", alias);
842         if (functions.ContainsKey (alias))
843           throw new Error (Error.FunctionConflict,
844                            "Alread defined as a function: {0}", alias);
845         if (! functions.TryGetValue (fname, out func))
846           throw new Error (Error.UnknownFunction, fname);
847         functions[alias] = func;
848       }
849
850       public Variable Defvar (Variable vari)
851       {
852         vari = vari.Clone (this);
853         variables[vari.name] = vari;
854         return vari;
855       }
856
857       internal Variable Defvar (Symbol name)
858       {
859         Variable vari = new Variable (this, name, Zero);
860         variables[name] = vari;
861         return vari;
862       }
863
864       public Variable DefvarInt (Symbol name, int n, string desc, int[] range)
865       {
866         Variable vari;
867
868         if (variables.TryGetValue (name, out vari))
869           {
870             Variable.IntType intvari = vari as Variable.IntType;
871             if (intvari == null)
872               throw new Error (Error.VariableTypeConflict,
873                                "Not an integer variable: {0}", name);
874             if (range != null)
875               {
876                 if (! intvari.IsSubrange (range))
877                   throw new Error (Error.VariableRangeConflict,
878                                    "Conflicting variable range: {0}", name);
879                 intvari.Range = range;;
880               }
881             if (desc != null)
882               intvari.Description = desc;
883           }
884         else
885           {
886             vari = new Variable.IntType (this, name, n, desc, range);
887             variables[name] = vari;
888           }
889         return vari;
890       }
891
892       public Variable DefvarStr (Symbol name, string str, string desc,
893                                  string[] range)
894       {
895         Variable vari;
896
897         if (variables.TryGetValue (name, out vari))
898           {
899             Variable.StrType strvari = vari as Variable.StrType;
900             if (strvari == null)
901               throw new Error (Error.VariableTypeConflict,
902                                "Not a string variable: {0}", name);
903             if (range != null)
904               {
905                 if (! strvari.IsSubrange (range))
906                   throw new Error (Error.VariableRangeConflict,
907                                    "Conflicting variable range: {0}", name);
908                 strvari.Range = range;
909               }
910             if (desc != null)
911               strvari.Description = desc;
912           }
913         else
914           {
915             vari = new Variable.StrType (this, name, new Str (str), desc,
916                                          range);
917             variables[name] = vari;
918           }
919         return vari;
920       }
921
922       public Variable DefvarSym (Symbol name, Symbol sym, string desc,
923                                  Symbol[] range)
924       {
925         Variable vari;
926
927         if (variables.TryGetValue (name, out vari))
928           {
929             Variable.SymType symvari = vari as Variable.SymType;
930             if (symvari == null)
931               throw new Error (Error.VariableTypeConflict,
932                                "Not a symbol variable: {0}", name);
933             if (range != null)
934               {
935                 if (! symvari.IsSubrange (range))
936                   throw new Error (Error.VariableRangeConflict,
937                                    "Conflicting variable range: {0}", name);
938                 symvari.Range = range;
939               }
940             if (desc != null)
941               symvari.Description = desc;
942           }
943         else
944           {
945             vari = new Variable.SymType (this, name, sym, desc, range);
946             variables[name] = vari;
947           }
948         return vari;
949       }
950
951       internal Function GetFunc (Symbol name)
952       {
953         Function func;
954         if (! functions.TryGetValue (name, out func))
955           throw new Error (Error.UnknownFunction,
956                            "Unknown function: {0}", name);
957         return func;
958       }
959
960       public bool CopyFunc (Domain domain, Symbol name)
961       {
962         Function func = GetFunc (name);
963
964         domain.functions[name] = func;
965         return true;
966       }
967
968       public void CopyFunc (Domain domain)
969       {
970         foreach (KeyValuePair<Symbol, Function> kv in functions)
971           domain.functions[kv.Key] = kv.Value;
972       }
973
974       public Variable GetVar (Symbol name)
975       {
976         Variable vari;
977
978         if (! variables.TryGetValue (name, out vari))
979           variables[name] = vari = new Variable (this, name, Zero);
980         return vari;
981       }
982
983       public override string ToString ()
984       {
985         string str = "<(functions";
986         foreach (KeyValuePair<Symbol, Function> kv in functions)
987           str += " " + kv.Key;
988         str += ") (variabls";
989         foreach (KeyValuePair<Symbol, Variable> kv in variables)
990           str += " " + kv.Value;
991         str += ")";
992         if (bindings != null)
993           str += " " + bindings;
994         if (context != null)
995           str += " (" + context + ")";
996         str += ">";
997         return str;
998       }
999
1000       internal void TraceWrite (string fmt, params string[] arg)
1001       {
1002         if (trace_depth > depth)
1003           {
1004             for (int i = 0; i < depth; i++)
1005               Console.Write ("  ");
1006             Console.WriteLine (fmt, arg);
1007           }
1008       }
1009
1010       public object SaveValues ()
1011       {
1012         Dictionary<Variable,Term> values = new Dictionary<Variable,Term> ();
1013
1014         foreach (KeyValuePair<Symbol,Variable> kv in variables)
1015           values[kv.Value] = kv.Value.Value.Clone ();
1016         return values;
1017       }
1018
1019       public void RestoreValues (object values)
1020       {
1021         foreach (KeyValuePair<Variable,Term> kv
1022                  in (Dictionary<Variable,Term>) values)
1023           kv.Key.SetValue (kv.Value);
1024       }
1025     }
1026
1027     private static Domain basic = new Domain ("basic");
1028
1029     static Xexpression ()
1030     {
1031       basic.DefType (typeof (Varref));
1032       basic.DefType (typeof (Funcall));
1033       basic.DefType (typeof (ErrorTerm));
1034
1035       basic.DefSubr (Fset, "set", true, 1, 1);
1036       basic.DefAlias ("=", "set");
1037       basic.DefSubr (Fnot, "not", false, 1, 1);
1038       basic.DefAlias ("!", "not");
1039       basic.DefSubr (Fadd, "add", true, 1, -1);
1040       basic.DefAlias ("+", "add");
1041       basic.DefSubr (Fmul, "mul", true, 1, -1);
1042       basic.DefAlias ("*", "mul");
1043       basic.DefSubr (Fsub, "sub", true, 1, -1);
1044       basic.DefAlias ("-", "sub");
1045       basic.DefSubr (Fdiv, "div", true, 1, -1);
1046       basic.DefAlias ("/", "div");
1047       basic.DefSubr (Fmod, "mod", true, 1, 2);
1048       basic.DefAlias ("%", "mod");
1049       basic.DefSubr (Flogior, "logior", true, 1, -1);
1050       basic.DefAlias ("|", "logior");
1051       basic.DefSubr (Flogand, "logand", true, 1, -1);
1052       basic.DefAlias ("&", "logand");
1053       basic.DefSubr (Flsh, "lsh", true, 1, 2);
1054       basic.DefAlias ("<<", "lsh");
1055       basic.DefSubr (Frsh, "rsh", true, 1, 2);
1056       basic.DefAlias (">>", "rsh");
1057       basic.DefSubr (Feq, "eq", false, 2, -1);
1058       basic.DefAlias ("==", "eq");
1059       basic.DefSubr (Fnoteq, "noteq", false, 2, 2);
1060       basic.DefAlias ("!=", "noteq");
1061       basic.DefSubr (Flt, "lt", false, 2, -1);
1062       basic.DefAlias ("<", "lt");
1063       basic.DefSubr (Fle, "le", false, 2, -1);
1064       basic.DefAlias ("<=", "le");
1065       basic.DefSubr (Fgt, "gt", false, 2, -1);
1066       basic.DefAlias (">", "gt");
1067       basic.DefSubr (Fge, "ge", false, 2, -1);
1068       basic.DefAlias (">=", "ge");
1069
1070       basic.DefSubr (Fappend, "append", true, 0, -1);
1071       basic.DefSubr (Fconcat, "concat", true, 0, -1);
1072       basic.DefSubr (Fnth, "nth", false, 2, 2);
1073       basic.DefSubr (Fcopy, "copy", false, 1, 1);
1074       basic.DefSubr (Fins, "ins", true, 2, 2);
1075       basic.DefSubr (Fdel, "del", true, 2, 2);
1076       basic.DefSubr (Feval, "eval", false, 1, 1);
1077       basic.DefSubr (Fbreak, "break", false, 0, 1);
1078       basic.DefSubr (Freturn, "return", false, 0, 1);
1079       basic.DefSubr (Fthrow, "throw", false, 1, 2);
1080
1081       basic.DefSpecial (Fand, "and", false, 1, -1);
1082       basic.DefAlias ("&&", "and");
1083       basic.DefSpecial (For, "or", false, 1, -1);
1084       basic.DefAlias ("||", "or");
1085       basic.DefSpecial (Fprogn, "progn", false, 0, -1);
1086       basic.DefAlias ("expr", "progn");
1087       basic.DefSpecial (Fif, "if", false, 2, 3);
1088       basic.DefSpecial (Fwhen, "when", false, 1, -1);
1089       basic.DefSpecial (Floop, "loop", false, 1, -1);
1090       basic.DefSpecial (Fwhile, "while", false, 1, -1);
1091       basic.DefSpecial (Fcond, "cond", false, 1, -1);
1092       basic.DefSpecial (Fforeach, "foreach", true, 2, -1);
1093       basic.DefSpecial (Fquote, "quote", false, 1, 1);
1094       basic.DefSpecial (Ftype, "type", false, 1, 1);
1095       basic.DefSpecial (Fcatch, "catch", true, 2, -1);
1096     }
1097
1098     private static Term Fset (Domain domain, Variable vari, Term[] args)
1099     {
1100       if (vari == null)
1101         throw new Error (Error.NoVariableName, "No variable name to set");
1102       vari.SetValue (args[0]);
1103       return args[0];
1104     }
1105
1106     private static Term Fnot (Domain domain, Variable vari, Term[] args)
1107     {
1108       return args[0].IsTrue ? Zero : One;
1109     }
1110
1111     static Term maybe_set_intvar (Variable vari, int n)
1112     {
1113       Term term = new Term (n);
1114       if (vari != null)
1115         vari.SetValue (term);
1116       return term;
1117     }
1118
1119
1120     private static Term Fadd (Domain domain, Variable vari, Term[] args)
1121     {
1122       int n = vari == null ? 0 : vari.Value.Intval;
1123
1124       foreach (Term arg in args)
1125         n += arg.Intval;
1126       return maybe_set_intvar (vari, n);
1127     }
1128
1129     private static Term Fmul (Domain domain, Variable vari, Term[] args)
1130     {
1131       int n = vari == null ? 1 : vari.Value.Intval;
1132       foreach (Term arg in args)
1133         n *= arg.Intval;
1134       return maybe_set_intvar (vari, n);
1135     }
1136
1137     private static Term Fsub (Domain domain, Variable vari, Term[] args)
1138     {
1139       int n, i;
1140
1141       if (vari == null)
1142         {
1143           n = args[0].Intval;
1144           i = 1;
1145         }
1146       else
1147         {
1148           n = vari.Value.Intval;
1149           i = 0;
1150         }
1151       while (i < args.Length)
1152         n -= args[i++].Intval;
1153       return maybe_set_intvar (vari, n);
1154     }
1155
1156     private static Term Fdiv (Domain domain, Variable vari, Term[] args)
1157     {
1158       int n, i;
1159
1160       if (vari == null)
1161         {
1162           n = args[0].Intval;
1163           i = 1;
1164         }
1165       else
1166         {
1167           n = vari.Value.Intval;
1168           i = 0;
1169         }
1170       while (i < args.Length)
1171         n /= args[i++].Intval;
1172       return maybe_set_intvar (vari, n);
1173     }
1174
1175     private static Term Fmod (Domain domain, Variable vari, Term[] args)
1176     {
1177       return maybe_set_intvar (vari, args[0].Intval % args[1].Intval);
1178     }
1179
1180     private static Term Flogior (Domain domain, Variable vari, Term[] args)
1181     {
1182       int n = vari == null ? 0 : vari.Value.Intval;
1183       foreach (Term arg in args)
1184         n |= arg.Intval;
1185       return maybe_set_intvar (vari, n);
1186     }
1187
1188     private static Term Flogand (Domain domain, Variable vari, Term[] args)
1189     {
1190       int n, i;
1191
1192       if (vari == null)
1193         {
1194           n = args[0].Intval;
1195           i = 1;
1196         }
1197       else
1198         {
1199           n = vari.Value.Intval;
1200           i = 0;
1201         }
1202       while (i < args.Length)
1203         n &= args[i++].Intval;
1204       return maybe_set_intvar (vari, n);
1205     }
1206
1207     private static Term Flsh (Domain domain, Variable vari, Term[] args)
1208     {
1209       return maybe_set_intvar (vari, args[0].Intval << args[1].Intval);
1210     }
1211
1212     private static Term Frsh (Domain domain, Variable vari, Term[] args)
1213     {
1214       return maybe_set_intvar (vari, args[0].Intval >> args[1].Intval);
1215     }
1216
1217     private static Term Feq (Domain domain, Variable vari, Term[] args)
1218     {
1219       Term o = args[0];
1220
1221       if (o.objval == null)
1222         {
1223           for (int i = 1; i < args.Length; i++)
1224             if (args[i].objval != null || args[i].intval != o.intval)
1225               return Zero;
1226         }
1227       else
1228         {
1229           for (int i = 1; i < args.Length; i++)
1230             if (o.objval.Equals (args[i].objval))
1231               return Zero;
1232         }
1233       return One;
1234     }
1235
1236     private static Term Fnoteq (Domain domain, Variable vari, Term[] args)
1237     {
1238       return Feq (domain, vari, args);
1239     }
1240
1241     private static Term Flt (Domain domain, Variable vari, Term[] args)
1242     {
1243       int n = args[0].Intval;
1244
1245       for (int i = 1; i < args.Length; i++)
1246         {
1247           int n1 = args[i].Intval;
1248           if (n >= n1)
1249             return Zero;
1250           n = n1;
1251         }
1252       return One;
1253     }
1254
1255     private static Term Fle (Domain domain, Variable vari, Term[] args)
1256     {
1257       int n = args[0].Intval;
1258       for (int i = 1; i < args.Length; i++)
1259         {
1260           int n1 = args[i].Intval;
1261           if (n > n1)
1262             return Zero;
1263           n = n1;
1264         }
1265       return One;
1266     }
1267
1268     private static Term Fgt (Domain domain, Variable vari, Term[] args)
1269     {
1270       int n = args[0].Intval;
1271       for (int i = 1; i < args.Length; i++)
1272         {
1273           int n1 = args[i].Intval;
1274           if (n <= n1)
1275             return Zero;
1276           n = n1;
1277         }
1278       return One;
1279     }
1280
1281     private static Term Fge (Domain domain, Variable vari, Term[] args)
1282     {
1283       int n = args[0].Intval;
1284       for (int i = 1; i < args.Length; i++)
1285         {
1286           int n1 = args[i].Intval;
1287           if (n < n1)
1288             return Zero;
1289           n = n1;
1290         }
1291       return One;
1292     }
1293
1294     private static Term Fappend (Domain domain, Variable vari, Term[] args)
1295     {
1296       List<Term> list;
1297
1298       if (vari == null)
1299         list = new List<Term> ();
1300       else
1301         list = vari.Value.Listval;
1302
1303       foreach (Term arg in args)
1304         {
1305           if (arg.IsList)
1306             list.AddRange ((List<Term>) arg.objval);
1307           else
1308             list.Add (arg);
1309         }
1310       if (vari == null)
1311         {
1312           Term result;
1313           result.intval = 0;
1314           result.objval = list;
1315           return result;
1316         }
1317       return vari.Value;
1318     }
1319
1320     private static Term Fconcat (Domain domain, Variable vari, Term[] args)
1321     {
1322       Str str = vari == null ? new Str ("") : vari.Value.Strval;
1323
1324       foreach (Term arg in args)
1325         {
1326           if (arg.IsStr)
1327             str.Insert (-1, arg.Strval);
1328           else if (arg.IsList)
1329             foreach (Term term in arg.Listval)
1330               str.Insert (-1, (char) term.Intval);
1331           else
1332             str.Insert (-1, (char) arg.Intval);
1333         }
1334       return vari == null ? new Term (str) : vari.Value;
1335     }
1336
1337     private static Term Fnth (Domain domain, Variable vari, Term[] args)
1338     {
1339       if (args[1].IsStr)
1340         return new Term (args[1].Strval.Nth (args[0].Intval));
1341       if (args[1].IsList)
1342         return args[1].Listval[args[0].Intval];
1343       throw new Error (Error.WrongType,
1344                        "Not a string nor a list: {0}", args[1]);
1345     }
1346
1347     private static Term Fcopy (Domain domain, Variable vari, Term[] args)
1348     {
1349       return args[0].Clone ();
1350     }
1351
1352     private static Term Fins (Domain domain, Variable vari, Term[] args)
1353     {
1354       if (vari == null)
1355         throw new Error (Error.NoVariableName, "No variable name to set");
1356       if (vari.Value.IsStr)
1357         vari.Value.Strval.Insert (args[0].Intval, args[1].Strval);
1358       else if (vari.Value.IsList)
1359         vari.Value.Listval.InsertRange (args[0].Intval, args[1].Listval);
1360       else
1361         throw new Error (Error.WrongType, "Not a string nor a list: {0}",
1362                          vari.Value);
1363       return vari.Value;
1364     }
1365
1366     private static Term Fdel (Domain domain, Variable vari, Term[] args)
1367     {
1368       if (vari == null)
1369         throw new Error (Error.NoVariableName, "No variable name to set");
1370       if (vari.Value.IsStr)
1371         vari.Value.Strval.Delete (args[0].Intval, args[1].Intval);
1372       else if (vari.Value.IsList)
1373         vari.Value.Listval.RemoveRange (args[0].Intval,
1374                                         args[1].Intval - args[0].Intval);
1375       else
1376         throw new Error (Error.WrongType, "Not a string nor a list: {0}",
1377                          vari.Value);
1378       return vari.Value;
1379     }
1380
1381     private static Term Fand (Domain domain, Variable vari, Term[] args)
1382     {
1383       foreach (Term arg in args)
1384         if (! arg.Eval (domain).IsTrue)
1385           return Zero;
1386       return One;
1387     }
1388
1389     private static Term For (Domain domain, Variable vari, Term[] args)
1390     {
1391       foreach (Term arg in args)
1392         if (arg.Eval (domain).IsTrue)
1393           return One;
1394       return Zero;
1395     }
1396
1397     private static Term Feval (Domain domain, Variable vari, Term[] args)
1398     {
1399       return (args[0].Eval (domain));
1400     }
1401
1402     private static Term Fprogn (Domain domain, Variable vari, Term[] args)
1403     {
1404       Term result = One;
1405
1406       foreach (Term arg in args)
1407         result = arg.Eval (domain);
1408       return result;
1409     }
1410
1411     private static Term Fif (Domain domain, Variable vari, Term[] args)
1412     {
1413       if (args[0].Eval (domain).IsTrue)
1414         return args[1].Eval (domain);
1415       if (args.Length == 2)
1416         return Zero;
1417       return args[2].Eval (domain);
1418     }
1419
1420     private static Term Fwhen (Domain domain, Variable vari, Term[] args)
1421     {
1422       if (! args[0].Eval (domain).IsTrue)
1423         return Zero;
1424       Term result = One;
1425       for (int i = 1; i < args.Length; i++)
1426         result = args[i].Eval (domain);
1427       return result;
1428     }
1429
1430     private static Term Freturn (Domain domain, Variable vari, Term[] args)
1431     {
1432       domain.ThrowReturn ();
1433       return args.Length == 0 ? Zero : args[0];
1434     }     
1435
1436     private static Term Fbreak (Domain domain, Variable vari, Term[] args)
1437     {
1438       domain.ThrowBreak ();
1439       return args.Length == 0 ? Zero : args[0];
1440     }     
1441
1442     private static Term Floop (Domain domain, Variable vari, Term[] args)
1443     {
1444       Term result = Zero;
1445       try {
1446         domain.Catch (CatchTag.Break);
1447         while (! domain.Thrown ())
1448           foreach (Term arg in args)
1449             {
1450               result = arg.Eval (domain);
1451               if (domain.Thrown ())
1452                 return result;
1453             }
1454       } finally {
1455         domain.Uncatch ();
1456       }
1457       return result;
1458     }
1459
1460     private static Term Fwhile (Domain domain, Variable vari, Term[] args)
1461     {
1462       Term result = Zero;
1463       try {
1464         domain.Catch (CatchTag.Break);
1465         while (! domain.Thrown () && args[0].Eval (domain).IsTrue)
1466           for (int i = 1; i < args.Length; i++)
1467             {
1468               result = args[i].Eval (domain);
1469               if (domain.Thrown ())
1470                 return result;
1471             }
1472       } finally {
1473         domain.Uncatch ();
1474       }
1475       return result;
1476     }
1477
1478     private static Term Fcond (Domain domain, Variable vari, Term[] args)
1479     {
1480       foreach (Term arg in args)
1481         {
1482           List<Term> list = arg.Listval;
1483           Term result = list[0].Eval (domain);
1484
1485           if (result.IsTrue)
1486             {
1487               for (int i = 1; i < list.Count; i++)
1488                 {
1489                   domain.depth++;
1490                   result = list[i].Eval (domain);
1491                   domain.depth--;
1492                   if (domain.Thrown ())
1493                     return result;
1494                 }                 
1495               return result;
1496             }
1497         }
1498       return Zero;
1499     }
1500
1501     private static Term Fforeach (Domain domain, Variable vari, Term[] args)
1502     {
1503       Term result = args[0].Eval (domain);
1504       if (domain.Thrown ())
1505         return result;
1506       List<Term> list = result.Listval;
1507       Bindings current = domain.bindings;
1508
1509       try {
1510         domain.Catch (CatchTag.Break);
1511         foreach (Term term in list)
1512           {
1513             domain.Bind (vari, term);
1514             try {
1515               for (int i = 1; i < args.Length; i++)
1516                 {
1517                   result = args[i].Eval (domain);
1518                   if (domain.Thrown ())
1519                     return result;
1520                 }
1521             } finally {
1522               domain.UnboundTo (current);
1523             }
1524           }
1525       } finally {
1526         domain.Uncatch ();
1527       }
1528       return result;
1529     }
1530
1531     private static Term Fquote (Domain domain, Variable vari, Term[] args)
1532     {
1533       return args[0];
1534     }
1535
1536     private static Term Ftype (Domain domain, Variable vari, Term[] args)
1537     {
1538       if (args[0].IsInt)
1539         return TermInt;
1540       if (args[0].IsStr)
1541         return TermStr;
1542       if (args[0].IsSymbol)
1543         return TermSymbol;
1544       if (args[0].IsList)
1545         return TermList;
1546       return TermTerm;
1547     }
1548
1549     private static Term eval_terms (Domain domain, Term[] terms, int idx,
1550                                     out bool caught)
1551     {
1552       Term result= Zero;
1553
1554       caught = false;
1555       for (int i = idx; i < terms.Length; i++)
1556         {
1557           result = terms[i].Eval (domain);
1558           if (domain.Thrown (out caught))
1559             break;
1560         }
1561       return result;
1562     }
1563
1564     public static Term Fcatch (Domain domain, Variable vari, Term[] args)
1565     {
1566       Term result;
1567       bool caught = false;
1568
1569       if (args.Length < 2)
1570         throw new Error (Error.WrongArgument,
1571                          "Too few arguments: {0}", args.Length);
1572       ErrorTerm err = args[0].objval as ErrorTerm;
1573       if (err != null)
1574         {
1575           try {
1576             result = eval_terms (domain, args, 1, out caught);
1577           } catch (System.Exception exception) {
1578             Term term;
1579
1580             Error e = exception as Error;
1581             if (e != null)
1582               term = new Term (new ErrorTerm (e.Name, e.Message, e.Stack));
1583             else
1584               term = new Term (new ErrorTerm (exception));
1585             if (! args[0].Matches (term))
1586               throw exception;
1587             if (vari != null)
1588               vari.SetValue (term);
1589             return One;
1590           }
1591         }
1592       else if (args[0].IsSymbol)
1593         {
1594           try {
1595             domain.Catch (new CatchTag (args[0].Symval));
1596             result = eval_terms (domain, args, 1, out caught);
1597             if (caught)
1598               {
1599                 if (vari != null)
1600                   vari.SetValue (result);
1601                 return One;
1602               }
1603             return Zero;
1604           } finally {
1605             domain.Uncatch ();
1606           }
1607         }
1608       throw new Error (Error.WrongArgument,
1609                        "Not a symbol nor an error: {0}", args[0]);
1610     }
1611
1612     public static Term Fthrow (Domain domain, Variable vari, Term[] args)
1613     {
1614       if (args[0].IsSymbol)
1615         {
1616           domain.ThrowSymbol (args[0]);
1617           return (args[args.Length - 1]);
1618         }
1619       if (args[0].IsError)
1620         {
1621           ErrorTerm err = (ErrorTerm) args[0].objval;
1622           throw new Error (err.ErrorName, err.ErrorMessage);
1623         }
1624       throw new Error (Error.WrongArgument,
1625                        "Not a symbol nor an error: {0}", args[0]);
1626     }
1627
1628     public abstract class TermValue
1629     {
1630       public virtual Term Eval (Domain domain) { return new Term (this); }
1631       public virtual TermValue Clone () { return this; }
1632       public virtual bool IsTrue { get { return true; } }
1633       public virtual bool Matches (TermValue other) { return Equals (other); }
1634       public override abstract bool Equals (object obj);
1635       public override abstract int GetHashCode ();
1636       public abstract string ToString (bool detail);
1637     }
1638
1639     private class Varref : TermValue
1640     {
1641       private static Symbol name = "varref";
1642       public static Symbol Name { get { return name; } }
1643
1644       private Symbol vname;
1645       private Variable vari;
1646
1647       public Varref (Symbol vname) { this.vname = vname; }
1648
1649       public override Term Eval (Domain domain)
1650       {
1651         if (vari == null || vari.domain != domain)
1652           vari = domain.GetVar (vname);
1653         return vari.Value;
1654       }
1655
1656       public static TermValue Parser (Domain domain, XmlNode node)
1657       {
1658         return new Varref ((Symbol) node.Attributes[Qvname].Value);
1659       }
1660
1661       public override bool Equals (object obj)
1662       {
1663         Varref varref = obj as Varref;
1664         return (varref != null && varref.vari.name == vari.name);
1665       }
1666
1667       public override int GetHashCode ()
1668       {
1669         return vari.name.GetHashCode ();
1670       } 
1671
1672       public override string ToString () { return ToString (true); }
1673
1674       public override string ToString (bool detail)
1675       {
1676         return "<varref vname=\"" + vname + "\"/>";
1677       }
1678     }
1679
1680     private class Funcall : TermValue
1681     {
1682       private static Symbol name = "funcall";
1683       public static Symbol Name { get { return name; } }
1684
1685       internal Function func;
1686       internal Variable vari;
1687       internal Term[] args;
1688
1689       public Funcall (Function func, Variable vari, Term[] args)
1690         {
1691           int nargs = args.Length;
1692
1693           if (nargs < func.min_args
1694               || (func.max_args >= 0 && nargs > func.max_args))
1695             throw new Error (Error.WrongArgument,
1696                              "Wrong number of arguments to {0}: {1}",
1697                              func.name, nargs);
1698           if (! func.with_var && vari != null)
1699             throw new Error (Error.WrongArgument,
1700                              "Wrong vname attribute to {0}: {1}",
1701                              func.name, vari.name);
1702           this.func = func;
1703           this.vari = vari;
1704           this.args = args;
1705         }
1706
1707       public static TermValue Parser (Domain domain, XmlNode node)
1708       {
1709         Symbol fname = node.Name;
1710         XmlAttribute attr;
1711
1712         if (fname == Qfuncall)
1713           fname = node.Attributes[Qfname].Value;
1714         Function func = domain.GetFunc (fname);
1715         Variable vari;
1716         attr = node.Attributes[Qvname];
1717         vari = attr == null ? null : domain.GetVar (attr.Value);
1718         XmlNodeList nlist = node.ChildNodes;
1719         int nargs = nlist.Count;
1720         Term[] args = new Term[nargs];
1721         for (int i = 0; i < nargs; i++)
1722           args[i] = Parse (domain, nlist[i]);
1723         return new Funcall (func, vari, args);
1724       }
1725
1726       public override Term Eval (Domain domain)
1727       {
1728         Term result;
1729         domain.TraceWrite (ToString ());
1730         try {
1731           domain.depth++;
1732           result = func.Call (domain, vari, args);
1733         } finally {
1734           domain.depth--;
1735         }
1736         domain.TraceWrite ("=> {0}", result.ToString ());
1737         return result;
1738       }
1739
1740       public override TermValue Clone ()
1741       {
1742         return new Funcall (func, vari, args);
1743       }
1744
1745       public override bool Equals (object obj)
1746       {
1747         Funcall funcall = obj as Funcall;
1748         return (obj != null
1749                 && funcall.func == func
1750                 && funcall.vari == vari
1751                 && funcall.args.Length == args.Length);
1752       }
1753
1754       public override int GetHashCode ()
1755       {
1756         return func.GetHashCode () ^ args.Length;
1757       }
1758
1759       public override string ToString () { return ToString (true); }
1760
1761       public override string ToString (bool detail)
1762       {
1763         string str = "<" + func.name;
1764         if (vari != null)
1765           {
1766             str += " vname=\"" + vari.name + "\"";
1767             if (detail)
1768               str += " val=" + vari.Value.ToString ();
1769           }
1770         if (args.Length == 0 || ! detail)
1771           return str + "/>";
1772         str += ">";
1773         if (func is Function.SpecialForm)
1774           {
1775             for (int i = 0; i < args.Length; i++)
1776               str += ".";
1777           }
1778         else
1779           foreach (Term e in args)
1780             str += e;
1781         return (str + "</" + func.name + ">");
1782       }
1783     }
1784
1785     internal class ErrorTerm : TermValue
1786     {
1787       private static Symbol name = "error";
1788       public static Symbol Name { get { return name; } }
1789       
1790       private readonly Symbol ename;
1791       public Symbol ErrorName { get { return ename; } }
1792       private string message;
1793       public string ErrorMessage { get { return message; } }
1794       private Term[] stack;
1795
1796       public ErrorTerm (Symbol ename, string message)
1797         : this (ename, message, null) { }
1798
1799       internal ErrorTerm (Symbol ename, string message, Term[] stack)
1800         {
1801           this.ename = ename;
1802           this.message = message;
1803           this.stack = stack;
1804         }
1805
1806       internal ErrorTerm (Exception e)
1807         {
1808           if (e is ArithmeticException)
1809             ename = Error.ArithmeticError;
1810           else if (e is IndexOutOfRangeException)
1811             ename = Error.IndexOutOfRange;
1812           else if (e is InsufficientMemoryException
1813                    || e is OutOfMemoryException)
1814             ename = Error.MemoryError;
1815           else
1816             ename = Error.UnknownError;
1817           message = e.Message;
1818         }
1819
1820       public static TermValue Parser (Domain domain, XmlNode node)
1821       {
1822         XmlAttribute attr = node.Attributes[Qename];
1823         Symbol ename = attr == null ? Qnull : (Symbol) attr.Value;
1824         string message = node.InnerText;
1825         return new ErrorTerm (ename, message);
1826       }
1827
1828       public Term[] CallStack {
1829         get { return stack; }
1830         internal set { stack = value; }
1831       }
1832
1833       public override TermValue Clone ()
1834       {
1835         return new ErrorTerm (ename, message);
1836       }
1837
1838       public override bool Equals (object obj)
1839       {
1840         ErrorTerm e = obj as ErrorTerm;
1841         return (e != null && e.ename == ename && e.message == message
1842                 && (e.stack == null ? stack == null
1843                     : (stack != null && e.stack.Length == stack.Length)));
1844       }
1845
1846       public override int GetHashCode ()
1847       {
1848         return ename.GetHashCode ();
1849       }
1850
1851       public override bool Matches (TermValue term)
1852       {
1853         ErrorTerm e = term as ErrorTerm;
1854         return (e != null && (ename == Qnull || e.ename == ename));
1855       }
1856
1857       public override string ToString () { return ToString (true); }
1858
1859       public override string ToString (bool detail)
1860         {
1861           string str = "<error type=\"" + ename + "\">";
1862           if (message != null)
1863             str += message;
1864           if (stack != null)
1865             for (int i = 0; i < stack.Length; i++)
1866               str += stack[i].ToString (false);
1867           return str + "</error>";
1868         }
1869     }
1870
1871     public class Str
1872     {
1873       private string str;
1874       private Regex regex;
1875
1876       public Str (string str) { this.str = str; }
1877
1878       public Str Clone (Str str) { return new Str (str.str); }
1879
1880       public bool Equals (string str) { return this.str == str; }
1881
1882       public bool Equals (Str str) { return this.str == str.str; }
1883
1884       public bool Matches (Str str)
1885       {
1886         if (regex != null)
1887           regex = new Regex (this.str);
1888         return regex.IsMatch (str.str);
1889       }
1890
1891       public int Nth (int index) { return (int) str[index]; }
1892
1893       public void Insert (int index, Str str)
1894       {
1895         if (index < 0)
1896           this.str = this.str + str.str;
1897         else
1898           this.str = this.str.Insert (index, str.str);
1899         regex = null;
1900       }
1901
1902       public void Insert (int index, char c)
1903       {
1904         if (index < 0)
1905           this.str = this.str + c;
1906         else
1907           this.str = this.str.Insert (index, new string (c, 1));
1908         regex = null;
1909       }
1910
1911       public void Delete (int from, int to)
1912       {
1913         this.str = this.str.Remove (from, to - from);
1914         regex = null;
1915       }
1916
1917       public override string ToString () { return str; }
1918     }
1919
1920     public struct Term
1921     {
1922       public int intval;
1923       public object objval;
1924
1925       // <integer>...</integer>
1926       public Term (int i) { intval = i; objval = null; }
1927       // <symbol>...</symbol>
1928       public Term (Symbol name) { intval = 0; objval = name; }
1929       // <string>...</string>
1930       public Term (string str) { intval = 0; objval = new Str (str); }
1931       // <list>...</list>
1932       public Term (List<Term> list) { intval = 0; objval = list; }
1933       // <error ename="ERROR-NAME">ERROR-MESSASGE</error>
1934       public Term (Symbol name, string message)
1935         {
1936           intval = 0;
1937           objval = new ErrorTerm (name, message);
1938         }
1939
1940       public Term (Str str) { intval = 0; objval = str; }
1941       public Term (TermValue obj) { intval = 0; objval = obj; }
1942
1943       // <varref vname="VNAME"/>
1944       public Term (Domain domain, Symbol vname)
1945         {
1946           intval = 0;
1947           objval = new Varref (vname);
1948         }
1949
1950       // <funcall fname="FNAME">...</funcall>
1951       public Term (Domain domain, Symbol fname, Term[] args)
1952         : this (domain, fname, Qnull, args) { }
1953
1954       // <funcall fname="FNAME" vname="VNAME">...</funcall>
1955       public Term (Domain domain, Symbol fname, Symbol vname, Term[] args)
1956         {
1957           intval = 0;
1958
1959           Function func = domain.GetFunc (fname);
1960           Variable vari = vname == Qnull ? null : domain.GetVar (vname);
1961           Funcall funcall = new Funcall (func, vari, args);
1962           if (func is Function.Macro)
1963             {
1964               Term result = funcall.Eval (domain);
1965               intval = result.intval;
1966               objval = result.objval;
1967             }
1968           else
1969             objval = funcall;
1970         }
1971
1972       public object Objval {
1973         get {
1974           if (objval == null)
1975             throw new Error (Error.WrongType,
1976                              "term is an integer: {0}", this);
1977           return objval;
1978         }
1979       }
1980
1981       public int Intval {
1982         get {
1983           if (objval != null)
1984             throw new Error (Error.WrongType, "{0} is not an integer", this);
1985           return intval;
1986         }
1987       }
1988
1989       public Str Strval {
1990         get {
1991           if (! IsStr)
1992             throw new Error (Error.WrongType, "{0} is not a string", this);
1993           return (Str) objval;
1994         }
1995       }
1996
1997       public string Symval {
1998         get {
1999           if (! IsSymbol)
2000             throw new Error (Error.WrongType, "{0} is not a symbol", this);
2001           return (Symbol) objval;
2002         }
2003       }
2004
2005       public List<Term> Listval {
2006         get {
2007           if (! IsList)
2008             throw new Error (Error.WrongType, "{0} is not a list");
2009           return (List<Term>) objval;
2010         }
2011       }
2012
2013       public bool IsTrue {
2014         get {
2015           return (objval == null
2016                   ? (intval != 0)
2017                   : objval is List<Term>
2018                   ? (((List<Term>) objval).Count != 0)
2019                   : objval is TermValue
2020                   ? ((TermValue) objval).IsTrue
2021                   : true);
2022         }
2023       }
2024
2025       public bool IsInt { get { return (objval == null); } }
2026       public bool IsStr { get { return (objval is Str); } }
2027       public bool IsSymbol { get { return (objval is Symbol); } }
2028       public bool IsList { get { return (objval is List<Term>); } }
2029       public bool IsError { get { return (objval is ErrorTerm); } }
2030
2031       internal Term Eval (Domain domain)
2032       {
2033         if (objval == null || objval is Symbol || objval is Str
2034             || objval is List<Term>)
2035           return this;
2036         try {
2037           domain.CallStackPush (this);
2038           return ((TermValue) objval).Eval (domain);
2039         } catch (Error e) {
2040           if (e.Stack == null)
2041             e.Stack = domain.CallStack;
2042           throw e;
2043         } finally {
2044           domain.CallStackPop ();
2045         }
2046       }
2047
2048       public Term Clone ()
2049       {
2050         if (objval == null || objval is Symbol)
2051           return this;
2052         if (objval is Str)
2053           return new Term (((Str) objval).ToString ());
2054         if (objval is List<Term>)
2055           {
2056             List<Term> list = new List<Term> ();
2057             list.InsertRange (0, ((List<Term>) objval));
2058             return new Term (list);
2059           }
2060         return new Term (((TermValue) objval).Clone ());
2061       }
2062
2063       public static bool operator== (Term t1, Term t2)
2064         {
2065           return t1.Equals (t2);
2066         }
2067
2068       public static bool operator!= (Term t1, Term t2) { return ! (t1 == t2); }
2069
2070       public override bool Equals (object obj)
2071       {
2072         if (! (obj is Term))
2073           return false;
2074         Term term = (Term) obj;
2075         if (IsInt)
2076           return term.IsInt && term.Intval == Intval;
2077         if (IsSymbol)
2078           return term.IsSymbol && term.Symval == Symval;
2079         if (IsStr)
2080           return (term.IsStr && term.Strval.Equals (Strval));
2081         if (IsList)
2082           {
2083             if (! term.IsList)
2084               return false;
2085             List<Term> l1 = objval as List<Term>;
2086             List<Term> l2 = term.objval as List<Term>;
2087
2088             if (l1.Count != l2.Count)
2089               return false;
2090             for (int i = 0; i < l1.Count; i++)
2091               if (! l1[i].Equals (l2[i]))
2092                 return false;
2093             return true;
2094           }
2095         return ((TermValue) objval).Equals (obj);
2096       }
2097
2098       public override int GetHashCode () { return intval; }
2099
2100       public bool Matches (Term term)
2101       {
2102         if (IsInt)
2103           return term.IsInt && Intval == term.Intval;
2104         if (IsSymbol)
2105           return term.IsSymbol && Symval == term.Symval;
2106         if (IsStr)
2107           return term.IsStr && Strval.Matches (term.Strval);
2108         if (IsList)
2109           {
2110             if (! term.IsList)
2111               return false;
2112             List<Term> l1 = objval as List<Term>;
2113             List<Term> l2 = term.objval as List<Term>;
2114
2115             if (l1.Count > l2.Count)
2116               return false;
2117             for (int i = 0; i < l1.Count; i++)
2118               if (! l1[i].Equals (l2[i]))
2119                 return false;
2120             return true;
2121           }
2122         return ((TermValue) objval).Matches ((TermValue) term.objval);
2123       }
2124
2125       public override string ToString () { return ToString (true); }
2126
2127       public string ToString (bool detail)
2128       {
2129         string str;
2130
2131         if (objval == null)
2132           str = "<integer>" + intval + "</integer>";
2133         else if (objval is Symbol)
2134           str = "<symbol>" + objval + "</symbol>";
2135         else if (objval is Str)
2136           str = "<string>" + objval + "</string>";
2137         else if (objval is List<Term>)
2138           {
2139             if (detail)
2140               {
2141                 str = "<list>";
2142                 foreach (Term e in (List<Term>) objval)
2143                   str += e;
2144                 str += "</list>";
2145               }
2146             else
2147               str = "<list/>";
2148           }
2149         else if (objval is Term)
2150           str = "<quote>" + objval + "</quote>";
2151         else
2152           str = ((TermValue) objval).ToString (detail);
2153         return str;
2154       }
2155     }
2156
2157     private static Term Zero = new Term (0);
2158     private static Term One = new Term (1);
2159     private static Term TermInt = new Term (Qinteger);
2160     private static Term TermStr = new Term (Qstring);
2161     private static Term TermSymbol = new Term (Qsymbol);
2162     private static Term TermList = new Term (Qlist);
2163     private static Term TermTerm = new Term ((Symbol) "term");
2164
2165     private static int parse_integer (XmlNode node)
2166     {
2167       string str = node.InnerText;
2168       int len = str.Length;
2169       int i, c;
2170
2171       if (len == 2 && str[0] == '?')
2172         return str[1];
2173       if (len > 2
2174           && str[1] == 'x' && ((c = str[0]) == '0' || c == '#'))
2175         {
2176           if (! int.TryParse (str.Substring (2),
2177                               Globalization.NumberStyles.HexNumber, null,
2178                               out i))
2179             throw new Error (Error.InvalidInteger, node,
2180                              "Not a integer string: {0}", str);
2181           return i;
2182         }
2183       if (! int.TryParse (str, out i))
2184         throw new Error (Error.InvalidInteger, node,
2185                          "Not a integer string: {0}", str);
2186       return i;
2187     }
2188
2189     private static Symbol parse_defvar (Domain domain, XmlNode node)
2190     {
2191       XmlAttribute name = node.Attributes[Qvname];
2192       if (name == null)
2193         throw new Error (Error.NoVariableName, node,
2194                          "No variable name to define");
2195       Symbol vname = name.Value;
2196       String desc;
2197       Variable vari;
2198
2199       node = node.FirstChild;
2200       if (node != null && node.Name == Qdescription)
2201         {
2202           desc = node.InnerText;
2203           node = node.NextSibling;
2204         }
2205       else
2206         desc = null;
2207       if (node != null)
2208         {
2209           Symbol type = node.Name;
2210           XmlNodeList range_list = null;
2211           int nranges = 0;
2212           XmlNode n = node.NextSibling;
2213
2214           if (n != null)
2215             {
2216               range_list = n.ChildNodes;
2217               nranges = range_list.Count;
2218             }
2219
2220           if (type == Qinteger)
2221             {
2222               int val = parse_integer (node);
2223               int[] range = null;
2224               if (range_list != null)
2225                 {
2226                   range = new int[nranges * 2];
2227                   for (int i = 0; i < nranges; i++)
2228                     {
2229                       XmlNode nd = range_list[i];
2230                       if (nd.Name == Qrange)
2231                         {
2232                           range[i * 2] = parse_integer (nd.FirstChild);
2233                           range[i * 2 + 1] = parse_integer (nd.LastChild);
2234                         }
2235                       else
2236                         {
2237                           range[i * 2] = range[i * 2 + 1]
2238                             = parse_integer (nd.FirstChild);
2239                         }
2240                     }
2241                 }
2242               vari = domain.DefvarInt (vname, val, desc, range);
2243             }
2244           else if (type == Qstring)
2245             {
2246               string[] range = null;
2247               if (range_list != null)
2248                 {
2249                   range = new string[nranges];
2250                   for (int i = 0; i < nranges; i++)
2251                     range[i] = range_list[i].FirstChild.InnerText;
2252                 }
2253               vari = domain.DefvarStr (vname, node.InnerText, desc, range);
2254             }
2255           else if (type == Qsymbol)
2256             {
2257               Symbol[] range = null;
2258               if (range_list != null)
2259                 {
2260                   range = new Symbol[nranges];
2261                   for (int i = 0; i < nranges; i++)
2262                     range[i] = range_list[i].FirstChild.InnerText;
2263                 }
2264               vari = domain.DefvarSym (vname, (Symbol) node.InnerText, desc,
2265                                        range);
2266             }
2267           else
2268             throw new Error (Error.TermTypeInvalid, "Unknown type: {0}", type);
2269         }
2270       else
2271         {
2272           if (domain.variables.TryGetValue (vname, out vari))
2273             vari = vari.Clone (domain);
2274           else
2275             vari = new Variable (domain, vname, Zero);
2276           domain.variables[vname] = vari;
2277         }
2278       return vname;
2279     }
2280
2281     private static Variable[] parse_args (Domain domain, XmlNode node,
2282                                           out int min_args, out int max_args)
2283     {
2284       int nfixed = 0;
2285       int noptional = 0;
2286       int nrest = 0;
2287       Variable[] args;
2288
2289       node = node.FirstChild;
2290       if (node != null && node.Name == Qargs)
2291         {
2292           XmlNode n;
2293           for (n = node.FirstChild; n != null; n = n.NextSibling)
2294             {
2295               if (n.Name == Qfixed)
2296                 nfixed++;
2297               else if (n.Name == Qoptional)
2298                 noptional++;
2299               else if (n.Name == Qrest)
2300                 {
2301                   if (nrest > 0)
2302                     throw new Error (Error.WrongType, n, "Too many <rest>");
2303                   nrest++;
2304                 }
2305               else
2306                 throw new Error (Error.WrongType, n,
2307                                  "Not fixed, optional, nor rest: {0}", n.Name);
2308             }
2309           min_args = nfixed;
2310           max_args = nfixed + noptional + nrest;
2311           args = new Variable[max_args];
2312           n = node.FirstChild;
2313           for (int i = 0; i < max_args; n = n.NextSibling)
2314             args[i++] = domain.Defvar ((Symbol) n.Attributes[0].Value);
2315           if (nrest == 1)
2316             max_args = - max_args;
2317         }
2318       else
2319         {
2320           min_args = max_args = 0;
2321           args = new Variable[0];
2322         }
2323       return args;
2324     }
2325
2326     public static Symbol parse_defun_head (Domain domain, XmlNode node)
2327     {
2328       Symbol name = node.Attributes[Qfname].Value;
2329       int min_args, max_args;
2330       Variable[] args;
2331
2332       args = parse_args (domain, node, out min_args, out max_args);
2333       if (node.Name == Qdefun)
2334         domain.Defun (name, min_args, max_args, args, null);
2335       else
2336         domain.Defmacro (name, min_args, max_args, args, null);
2337       return name;
2338     }
2339
2340     public static void parse_defun_body (Domain domain, XmlNode node)
2341     {
2342       bool is_defun = node.Name == Qdefun;
2343       Symbol name = node.Attributes[Qfname].Value;
2344       Function func = domain.GetFunc (name);
2345
2346       for (node = node.FirstChild; node != null; node = node.NextSibling)
2347         if (node.Name != Qdescription
2348             && node.Name != Qargs)
2349           break;
2350       Term[] body = Parse (domain, node, null);
2351       if (is_defun)
2352         ((Function.Lambda) func).SetBody (body);
2353       else
2354         ((Function.Macro) func).SetBody (body);
2355     }
2356
2357     public static Term Parse (Domain domain, XmlNode node)
2358     {
2359       Symbol name = node.Name;
2360
2361       try {
2362         if (name == Qinteger)
2363           return new Term (parse_integer (node));
2364         if (name == Qsymbol)
2365           return new Term ((Symbol) node.InnerText);
2366         if (name == Qstring)
2367           return new Term (node.InnerText);
2368         if (name == Qlist)
2369           {
2370             List<Term> list = new List<Term> ();
2371             for (node = node.FirstChild; node != null;
2372                  node = node.NextSibling)
2373               list.Add (Parse (domain, node));
2374             return new Term (list);
2375           }
2376         if (name == Qdefun || name == Qdefmacro)
2377           {
2378             name = parse_defun_head (domain, node);
2379             parse_defun_body (domain, node);
2380             return new Term (name);
2381           }
2382         if (name == Qdefvar)
2383           {
2384             name = parse_defvar (domain, node);
2385             return new Term (name);
2386           }
2387         MethodInfo parser;
2388         if (domain.termtypes.TryGetValue (name, out parser))
2389           {
2390             object[] arg = new object[] { domain, node };
2391             return new Term ((TermValue) parser.Invoke (null, arg));
2392           }
2393
2394         Funcall funcall = (Funcall) Funcall.Parser (domain, node);
2395         if (funcall.func is Function.Macro)
2396           return funcall.Eval (domain);
2397         return new Term (funcall);
2398       } catch (Error e) {
2399         if (e.Node == null)
2400           e.Node = node;
2401         throw e;
2402       } catch (Exception e) {
2403         throw new Error (Error.UnknownError, node, e, "Parsing error");
2404       }
2405     }
2406
2407     private static bool default_stop (XmlNode n) { return n == null; }
2408
2409     public delegate bool ParseStop (XmlNode node);
2410
2411     public static Term[] Parse (Domain domain, XmlNode node, ParseStop stop)
2412     {
2413       if (stop == null)
2414         stop = default_stop;
2415
2416       XmlNode n;
2417       for (n = node; ! stop (n); n = n.NextSibling)
2418         if (n.NodeType == XmlNodeType.Element
2419             && (n.Name == Qdefun || n.Name == Qdefmacro))
2420           {
2421             try {
2422               parse_defun_head (domain, n);
2423             } catch (Error e) {
2424               if (e.Node == null)
2425                 e.Node = node;
2426               throw e;
2427             } catch (Exception e) {
2428               throw new Error (Error.UnknownError, node, e, "Parsing error");
2429             }
2430           }
2431
2432       List<Term> terms = new List<Term> ();
2433       for (; node != n; node = node.NextSibling)
2434         if (node.NodeType == XmlNodeType.Element)
2435           {
2436             try {
2437               if (node.Name == Qdefun || node.Name == Qdefmacro)
2438                 parse_defun_body (domain, node);
2439               else if (node.Name == Qdefvar)
2440                 parse_defvar (domain, node);
2441               else
2442                 terms.Add (Parse (domain, node));
2443             } catch (Error e) {
2444               if (e.Node == null)
2445                 e.Node = node;
2446               throw e;
2447             } catch (Exception e) {
2448               throw new Error (Error.UnknownError, node, e, "Parsing error");
2449             }
2450           }
2451       return terms.ToArray ();
2452     }
2453
2454     public static Term[] Parse (Domain domain, string url)
2455     {
2456       XmlDocument doc = new XmlDocument (Symbol.NameTable);
2457       XmlNode node;
2458
2459       using (XmlTextReader reader = new XmlTextReader (url, doc.NameTable))
2460         {
2461           do {
2462             reader.Read ();
2463           } while (reader.NodeType != XmlNodeType.None
2464                    && (reader.NodeType != XmlNodeType.Element
2465                        || reader.Name != Qexpr));
2466           if (reader.NodeType == XmlNodeType.None)
2467             throw new Exception ("Node <expr> not found");
2468           node = doc.ReadNode (reader);
2469         }
2470       return Parse (domain, node.FirstChild, null);
2471     }
2472
2473     public static Term Eval (Domain domain, Term[] terms)
2474     {
2475       Term result = Zero;
2476
2477       try {
2478         foreach (Term term in terms)
2479           {
2480             result = term.Eval (domain);
2481             if (domain.Thrown ())
2482               return result;
2483           }
2484         return result;
2485       } catch (Error e) {
2486         throw e;
2487       } catch (Exception e) {
2488         throw new Error (Error.UnknownError, null, e, "Runtime error");
2489       }
2490     }
2491   }
2492 }