*** 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.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, string 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 (Str 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 Function () { }
419
420       public Function (Symbol name, bool with_var, int min_args, int max_args)
421       {
422         this.name = name;
423         this.with_var = with_var;
424         this.min_args = min_args;
425         this.max_args = max_args;
426       }
427
428       public abstract Term Call (Domain domain, Variable vari, Term[] args);
429
430       public override string ToString ()
431       {
432         return name;
433       }
434
435       internal class Subroutine : Function
436       {
437         public Func<Domain, Variable, Term[], Term> builtin;
438
439         public Subroutine (Func<Domain, Variable, Term[], Term> builtin,
440                            Symbol name, bool with_var,
441                            int min_args, int max_args)
442           : base (name, with_var, min_args, max_args)
443           {
444             this.builtin = builtin;
445           }
446
447         public override Term Call (Domain domain, Variable vari, Term[] args)
448         {
449           if (args.Length > 0)
450             {
451               args = (Term[]) args.Clone ();
452               for (int i = 0; i < args.Length; i++)
453                 {
454                   args[i] = args[i].Eval (domain);
455                   if (domain.Thrown ())
456                     return args[i];
457                 }
458             }
459           return builtin (domain, vari, args);
460         }
461       }
462
463       internal class SpecialForm : Function
464       {
465         public Func<Domain, Variable, Term[], Term> builtin;
466
467         public SpecialForm (Func<Domain, Variable, Term[], Term> builtin,
468                             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 (Func<Domain, Variable, Term[], Term> builtin,
800                            Symbol name, bool with_var,
801                            int min_args, int max_args)
802       {
803         check_func_head (name, with_var, min_args, max_args, false);
804         functions[name] = new Function.Subroutine (builtin, name, with_var,
805                                                    min_args, max_args);
806       }
807
808       public void DefSpecial (Func<Domain, Variable, Term[], Term> builtin,
809                               Symbol name, bool with_var,
810                               int min_args, int max_args)
811       {
812         check_func_head (name, with_var, min_args, max_args, false);
813         functions[name] = new Function.SpecialForm (builtin, name, with_var,
814                                                     min_args, max_args);
815       }
816
817       public void Defun (Symbol name, int min_args, int max_args,
818                          Variable[] args, Term[] body)
819       {
820         check_func_head (name, false, min_args, max_args, false);
821         functions[name] = new Function.Lambda (name, min_args, max_args,
822                                                args, body);
823       }
824
825       public void Defun (Function func)
826       {
827         functions[func.name] = func;
828       }
829
830       public void Defmacro (Symbol name, int min_args, int max_args,
831                             Variable[] args, Term[] body)
832       {
833         check_func_head (name, false, min_args, max_args, true);
834         functions[name] = new Function.Macro (name, min_args, max_args,
835                                               args, body);
836       }
837
838       public void DefAlias (Symbol alias, Symbol fname)
839       {
840         Function func;
841         if (termtypes.ContainsKey (alias))
842           throw new Error (Error.FunctionConflict,
843                            "Alread defined as a term type: {0}", alias);
844         if (functions.ContainsKey (alias))
845           throw new Error (Error.FunctionConflict,
846                            "Alread defined as a function: {0}", alias);
847         if (! functions.TryGetValue (fname, out func))
848           throw new Error (Error.UnknownFunction, fname);
849         functions[alias] = func;
850       }
851
852       public Variable Defvar (Variable vari)
853       {
854         vari = vari.Clone (this);
855         variables[vari.name] = vari;
856         return vari;
857       }
858
859       internal Variable Defvar (Symbol name)
860       {
861         Variable vari = new Variable (this, name, Zero);
862         variables[name] = vari;
863         return vari;
864       }
865
866       public Variable DefvarInt (Symbol name, int n, string desc, int[] range)
867       {
868         Variable vari;
869
870         if (variables.TryGetValue (name, out vari))
871           {
872             Variable.IntType intvari = vari as Variable.IntType;
873             if (intvari == null)
874               throw new Error (Error.VariableTypeConflict,
875                                "Not an integer variable: {0}", name);
876             if (range != null)
877               {
878                 if (! intvari.IsSubrange (range))
879                   throw new Error (Error.VariableRangeConflict,
880                                    "Conflicting variable range: {0}", name);
881                 intvari.Range = range;;
882               }
883             if (desc != null)
884               intvari.Description = desc;
885           }
886         else
887           {
888             vari = new Variable.IntType (this, name, n, desc, range);
889             variables[name] = vari;
890           }
891         return vari;
892       }
893
894       public Variable DefvarStr (Symbol name, string str, string desc,
895                                  string[] range)
896       {
897         Variable vari;
898
899         if (variables.TryGetValue (name, out vari))
900           {
901             Variable.StrType strvari = vari as Variable.StrType;
902             if (strvari == null)
903               throw new Error (Error.VariableTypeConflict,
904                                "Not a string variable: {0}", name);
905             if (range != null)
906               {
907                 if (! strvari.IsSubrange (range))
908                   throw new Error (Error.VariableRangeConflict,
909                                    "Conflicting variable range: {0}", name);
910                 strvari.Range = range;
911               }
912             if (desc != null)
913               strvari.Description = desc;
914           }
915         else
916           {
917             vari = new Variable.StrType (this, name, str, desc, range);
918             variables[name] = vari;
919           }
920         return vari;
921       }
922
923       public Variable DefvarSym (Symbol name, Symbol sym, string desc,
924                                  Symbol[] range)
925       {
926         Variable vari;
927
928         if (variables.TryGetValue (name, out vari))
929           {
930             Variable.SymType symvari = vari as Variable.SymType;
931             if (symvari == null)
932               throw new Error (Error.VariableTypeConflict,
933                                "Not a symbol variable: {0}", name);
934             if (range != null)
935               {
936                 if (! symvari.IsSubrange (range))
937                   throw new Error (Error.VariableRangeConflict,
938                                    "Conflicting variable range: {0}", name);
939                 symvari.Range = range;
940               }
941             if (desc != null)
942               symvari.Description = desc;
943           }
944         else
945           {
946             vari = new Variable.SymType (this, name, sym, desc, range);
947             variables[name] = vari;
948           }
949         return vari;
950       }
951
952       internal Function GetFunc (Symbol name)
953       {
954         Function func;
955         if (! functions.TryGetValue (name, out func))
956           throw new Error (Error.UnknownFunction,
957                            "Unknown function: {0}", name);
958         return func;
959       }
960
961       public bool CopyFunc (Domain domain, Symbol name)
962       {
963         Function func = GetFunc (name);
964
965         domain.functions[name] = func;
966         return true;
967       }
968
969       public void CopyFunc (Domain domain)
970       {
971         foreach (KeyValuePair<Symbol, Function> kv in functions)
972           domain.functions[kv.Key] = kv.Value;
973       }
974
975       public Variable GetVar (Symbol name)
976       {
977         Variable vari;
978
979         if (! variables.TryGetValue (name, out vari))
980           variables[name] = vari = new Variable (this, name, Zero);
981         return vari;
982       }
983
984       public override string ToString ()
985       {
986         string str = "<(functions";
987         foreach (KeyValuePair<Symbol, Function> kv in functions)
988           str += " " + kv.Key;
989         str += ") (variabls";
990         foreach (KeyValuePair<Symbol, Variable> kv in variables)
991           str += " " + kv.Value;
992         str += ")";
993         if (bindings != null)
994           str += " " + bindings;
995         if (context != null)
996           str += " (" + context + ")";
997         str += ">";
998         return str;
999       }
1000
1001       internal void TraceWrite (string fmt, params string[] arg)
1002       {
1003         if (trace_depth > depth)
1004           {
1005             for (int i = 0; i < depth; i++)
1006               Console.Write ("  ");
1007             Console.WriteLine (fmt, arg);
1008           }
1009       }
1010
1011       public object SaveValues ()
1012       {
1013         Dictionary<Variable,Term> values = new Dictionary<Variable,Term> ();
1014
1015         foreach (KeyValuePair<Symbol,Variable> kv in variables)
1016           values[kv.Value] = kv.Value.Value.Clone ();
1017         return values;
1018       }
1019
1020       public void RestoreValues (object values)
1021       {
1022         foreach (KeyValuePair<Variable,Term> kv
1023                  in (Dictionary<Variable,Term>) values)
1024           kv.Key.SetValue (kv.Value);
1025       }
1026     }
1027
1028     private static Domain basic = new Domain ("basic");
1029
1030     static Xexpression ()
1031     {
1032       basic.DefType (typeof (Varref));
1033       basic.DefType (typeof (Funcall));
1034       basic.DefType (typeof (ErrorTerm));
1035
1036       basic.DefSubr (Fset, "set", true, 1, 1);
1037       basic.DefAlias ("=", "set");
1038       basic.DefSubr (Fnot, "not", false, 1, 1);
1039       basic.DefAlias ("!", "not");
1040       basic.DefSubr (Fadd, "add", true, 1, -1);
1041       basic.DefAlias ("+", "add");
1042       basic.DefSubr (Fmul, "mul", true, 1, -1);
1043       basic.DefAlias ("*", "mul");
1044       basic.DefSubr (Fsub, "sub", true, 1, -1);
1045       basic.DefAlias ("-", "sub");
1046       basic.DefSubr (Fdiv, "div", true, 1, -1);
1047       basic.DefAlias ("/", "div");
1048       basic.DefSubr (Fmod, "mod", true, 1, 2);
1049       basic.DefAlias ("%", "mod");
1050       basic.DefSubr (Flogior, "logior", true, 1, -1);
1051       basic.DefAlias ("|", "logior");
1052       basic.DefSubr (Flogand, "logand", true, 1, -1);
1053       basic.DefAlias ("&", "logand");
1054       basic.DefSubr (Flsh, "lsh", true, 1, 2);
1055       basic.DefAlias ("<<", "lsh");
1056       basic.DefSubr (Frsh, "rsh", true, 1, 2);
1057       basic.DefAlias (">>", "rsh");
1058       basic.DefSubr (Feq, "eq", false, 2, -1);
1059       basic.DefAlias ("==", "eq");
1060       basic.DefSubr (Fnoteq, "noteq", false, 2, 2);
1061       basic.DefAlias ("!=", "noteq");
1062       basic.DefSubr (Flt, "lt", false, 2, -1);
1063       basic.DefAlias ("<", "lt");
1064       basic.DefSubr (Fle, "le", false, 2, -1);
1065       basic.DefAlias ("<=", "le");
1066       basic.DefSubr (Fgt, "gt", false, 2, -1);
1067       basic.DefAlias (">", "gt");
1068       basic.DefSubr (Fge, "ge", false, 2, -1);
1069       basic.DefAlias (">=", "ge");
1070
1071       basic.DefSubr (Fappend, "append", true, 0, -1);
1072       basic.DefSubr (Fconcat, "concat", true, 0, -1);
1073       basic.DefSubr (Fnth, "nth", false, 2, 2);
1074       basic.DefSubr (Fcopy, "copy", false, 1, 1);
1075       basic.DefSubr (Fins, "ins", true, 2, 2);
1076       basic.DefSubr (Fdel, "del", true, 2, 2);
1077       basic.DefSubr (Feval, "eval", false, 1, 1);
1078       basic.DefSubr (Fbreak, "break", false, 0, 1);
1079       basic.DefSubr (Freturn, "return", false, 0, 1);
1080       basic.DefSubr (Fthrow, "throw", false, 1, 2);
1081
1082       basic.DefSpecial (Fand, "and", false, 1, -1);
1083       basic.DefAlias ("&&", "and");
1084       basic.DefSpecial (For, "or", false, 1, -1);
1085       basic.DefAlias ("||", "or");
1086       basic.DefSpecial (Fprogn, "progn", false, 0, -1);
1087       basic.DefAlias ("expr", "progn");
1088       basic.DefSpecial (Fif, "if", false, 2, 3);
1089       basic.DefSpecial (Fwhen, "when", false, 1, -1);
1090       basic.DefSpecial (Floop, "loop", false, 1, -1);
1091       basic.DefSpecial (Fwhile, "while", false, 1, -1);
1092       basic.DefSpecial (Fcond, "cond", false, 1, -1);
1093       basic.DefSpecial (Fforeach, "foreach", true, 2, -1);
1094       basic.DefSpecial (Fquote, "quote", false, 1, 1);
1095       basic.DefSpecial (Ftype, "type", false, 1, 1);
1096       basic.DefSpecial (Fcatch, "catch", true, 2, -1);
1097     }
1098
1099     private static Term Fset (Domain domain, Variable vari, Term[] args)
1100     {
1101       if (vari == null)
1102         throw new Error (Error.NoVariableName, "No variable name to set");
1103       vari.SetValue (args[0]);
1104       return args[0];
1105     }
1106
1107     private static Term Fnot (Domain domain, Variable vari, Term[] args)
1108     {
1109       return args[0].IsTrue ? Zero : One;
1110     }
1111
1112     static Term maybe_set_intvar (Variable vari, int n)
1113     {
1114       Term term = new Term (n);
1115       if (vari != null)
1116         vari.SetValue (term);
1117       return term;
1118     }
1119
1120
1121     private static Term Fadd (Domain domain, Variable vari, Term[] args)
1122     {
1123       int n = vari == null ? 0 : vari.Value.Intval;
1124
1125       foreach (Term arg in args)
1126         n += arg.Intval;
1127       return maybe_set_intvar (vari, n);
1128     }
1129
1130     private static Term Fmul (Domain domain, Variable vari, Term[] args)
1131     {
1132       int n = vari == null ? 1 : vari.Value.Intval;
1133       foreach (Term arg in args)
1134         n *= arg.Intval;
1135       return maybe_set_intvar (vari, n);
1136     }
1137
1138     private static Term Fsub (Domain domain, Variable vari, Term[] args)
1139     {
1140       int n, i;
1141
1142       if (vari == null)
1143         {
1144           n = args[0].Intval;
1145           i = 1;
1146         }
1147       else
1148         {
1149           n = vari.Value.Intval;
1150           i = 0;
1151         }
1152       while (i < args.Length)
1153         n -= args[i++].Intval;
1154       return maybe_set_intvar (vari, n);
1155     }
1156
1157     private static Term Fdiv (Domain domain, Variable vari, Term[] args)
1158     {
1159       int n, i;
1160
1161       if (vari == null)
1162         {
1163           n = args[0].Intval;
1164           i = 1;
1165         }
1166       else
1167         {
1168           n = vari.Value.Intval;
1169           i = 0;
1170         }
1171       while (i < args.Length)
1172         n /= args[i++].Intval;
1173       return maybe_set_intvar (vari, n);
1174     }
1175
1176     private static Term Fmod (Domain domain, Variable vari, Term[] args)
1177     {
1178       return maybe_set_intvar (vari, args[0].Intval % args[1].Intval);
1179     }
1180
1181     private static Term Flogior (Domain domain, Variable vari, Term[] args)
1182     {
1183       int n = vari == null ? 0 : vari.Value.Intval;
1184       foreach (Term arg in args)
1185         n |= arg.Intval;
1186       return maybe_set_intvar (vari, n);
1187     }
1188
1189     private static Term Flogand (Domain domain, Variable vari, Term[] args)
1190     {
1191       int n, i;
1192
1193       if (vari == null)
1194         {
1195           n = args[0].Intval;
1196           i = 1;
1197         }
1198       else
1199         {
1200           n = vari.Value.Intval;
1201           i = 0;
1202         }
1203       while (i < args.Length)
1204         n &= args[i++].Intval;
1205       return maybe_set_intvar (vari, n);
1206     }
1207
1208     private static Term Flsh (Domain domain, Variable vari, Term[] args)
1209     {
1210       return maybe_set_intvar (vari, args[0].Intval << args[1].Intval);
1211     }
1212
1213     private static Term Frsh (Domain domain, Variable vari, Term[] args)
1214     {
1215       return maybe_set_intvar (vari, args[0].Intval >> args[1].Intval);
1216     }
1217
1218     private static Term Feq (Domain domain, Variable vari, Term[] args)
1219     {
1220       Term o = args[0];
1221
1222       if (o.objval == null)
1223         {
1224           for (int i = 1; i < args.Length; i++)
1225             if (args[i].objval != null || args[i].intval != o.intval)
1226               return Zero;
1227         }
1228       else
1229         {
1230           for (int i = 1; i < args.Length; i++)
1231             if (o.objval.Equals (args[i].objval))
1232               return Zero;
1233         }
1234       return One;
1235     }
1236
1237     private static Term Fnoteq (Domain domain, Variable vari, Term[] args)
1238     {
1239       return Feq (domain, vari, args);
1240     }
1241
1242     private static Term Flt (Domain domain, Variable vari, Term[] args)
1243     {
1244       int n = args[0].Intval;
1245
1246       for (int i = 1; i < args.Length; i++)
1247         {
1248           int n1 = args[i].Intval;
1249           if (n >= n1)
1250             return Zero;
1251           n = n1;
1252         }
1253       return One;
1254     }
1255
1256     private static Term Fle (Domain domain, Variable vari, Term[] args)
1257     {
1258       int n = args[0].Intval;
1259       for (int i = 1; i < args.Length; i++)
1260         {
1261           int n1 = args[i].Intval;
1262           if (n > n1)
1263             return Zero;
1264           n = n1;
1265         }
1266       return One;
1267     }
1268
1269     private static Term Fgt (Domain domain, Variable vari, Term[] args)
1270     {
1271       int n = args[0].Intval;
1272       for (int i = 1; i < args.Length; i++)
1273         {
1274           int n1 = args[i].Intval;
1275           if (n <= n1)
1276             return Zero;
1277           n = n1;
1278         }
1279       return One;
1280     }
1281
1282     private static Term Fge (Domain domain, Variable vari, Term[] args)
1283     {
1284       int n = args[0].Intval;
1285       for (int i = 1; i < args.Length; i++)
1286         {
1287           int n1 = args[i].Intval;
1288           if (n < n1)
1289             return Zero;
1290           n = n1;
1291         }
1292       return One;
1293     }
1294
1295     private static Term Fappend (Domain domain, Variable vari, Term[] args)
1296     {
1297       List<Term> list;
1298
1299       if (vari == null)
1300         list = new List<Term> ();
1301       else
1302         list = vari.Value.Listval;
1303
1304       foreach (Term arg in args)
1305         {
1306           if (arg.IsList)
1307             list.AddRange ((List<Term>) arg.objval);
1308           else
1309             list.Add (arg);
1310         }
1311       if (vari == null)
1312         {
1313           Term result;
1314           result.intval = 0;
1315           result.objval = list;
1316           return result;
1317         }
1318       return vari.Value;
1319     }
1320
1321     private static Term Fconcat (Domain domain, Variable vari, Term[] args)
1322     {
1323       Str str = vari == null ? new Str ("") : vari.Value.Strval;
1324
1325       foreach (Term arg in args)
1326         {
1327           if (arg.IsStr)
1328             str.Insert (-1, arg.Strval);
1329           else if (arg.IsList)
1330             foreach (Term term in arg.Listval)
1331               str.Insert (-1, (char) term.Intval);
1332           else
1333             str.Insert (-1, (char) arg.Intval);
1334         }
1335       return vari == null ? new Term (str) : vari.Value;
1336     }
1337
1338     private static Term Fnth (Domain domain, Variable vari, Term[] args)
1339     {
1340       Term result;
1341
1342       if (args[1].IsStr)
1343         return new Term (args[1].Strval.Nth (args[0].Intval));
1344       if (args[1].IsList)
1345         return args[1].Listval[args[0].Intval];
1346       throw new Error (Error.WrongType,
1347                        "Not a string nor a list: {0}", args[1]);
1348     }
1349
1350     private static Term Fcopy (Domain domain, Variable vari, Term[] args)
1351     {
1352       return args[0].Clone ();
1353     }
1354
1355     private static Term Fins (Domain domain, Variable vari, Term[] args)
1356     {
1357       if (vari == null)
1358         throw new Error (Error.NoVariableName, "No variable name to set");
1359       if (vari.Value.IsStr)
1360         vari.Value.Strval.Insert (args[0].Intval, args[1].Strval);
1361       else if (vari.Value.IsList)
1362         vari.Value.Listval.InsertRange (args[0].Intval, args[1].Listval);
1363       else
1364         throw new Error (Error.WrongType, "Not a string nor a list: {0}",
1365                          vari.Value);
1366       return vari.Value;
1367     }
1368
1369     private static Term Fdel (Domain domain, Variable vari, Term[] args)
1370     {
1371       if (vari == null)
1372         throw new Error (Error.NoVariableName, "No variable name to set");
1373       if (vari.Value.IsStr)
1374         vari.Value.Strval.Delete (args[0].Intval, args[1].Intval);
1375       else if (vari.Value.IsList)
1376         vari.Value.Listval.RemoveRange (args[0].Intval,
1377                                         args[1].Intval - args[0].Intval);
1378       else
1379         throw new Error (Error.WrongType, "Not a string nor a list: {0}",
1380                          vari.Value);
1381       return vari.Value;
1382     }
1383
1384     private static Term Fand (Domain domain, Variable vari, Term[] args)
1385     {
1386       foreach (Term arg in args)
1387         if (! arg.Eval (domain).IsTrue)
1388           return Zero;
1389       return One;
1390     }
1391
1392     private static Term For (Domain domain, Variable vari, Term[] args)
1393     {
1394       foreach (Term arg in args)
1395         if (arg.Eval (domain).IsTrue)
1396           return One;
1397       return Zero;
1398     }
1399
1400     private static Term Feval (Domain domain, Variable vari, Term[] args)
1401     {
1402       return (args[0].Eval (domain));
1403     }
1404
1405     private static Term Fprogn (Domain domain, Variable vari, Term[] args)
1406     {
1407       Term result = One;
1408
1409       foreach (Term arg in args)
1410         result = arg.Eval (domain);
1411       return result;
1412     }
1413
1414     private static Term Fif (Domain domain, Variable vari, Term[] args)
1415     {
1416       if (args[0].Eval (domain).IsTrue)
1417         return args[1].Eval (domain);
1418       if (args.Length == 2)
1419         return Zero;
1420       return args[2].Eval (domain);
1421     }
1422
1423     private static Term Fwhen (Domain domain, Variable vari, Term[] args)
1424     {
1425       if (! args[0].Eval (domain).IsTrue)
1426         return Zero;
1427       Term result = One;
1428       for (int i = 1; i < args.Length; i++)
1429         result = args[i].Eval (domain);
1430       return result;
1431     }
1432
1433     private static Term Freturn (Domain domain, Variable vari, Term[] args)
1434     {
1435       domain.ThrowReturn ();
1436       return args.Length == 0 ? Zero : args[0];
1437     }     
1438
1439     private static Term Fbreak (Domain domain, Variable vari, Term[] args)
1440     {
1441       domain.ThrowBreak ();
1442       return args.Length == 0 ? Zero : args[0];
1443     }     
1444
1445     private static Term Floop (Domain domain, Variable vari, Term[] args)
1446     {
1447       Term result = Zero;
1448       try {
1449         domain.Catch (CatchTag.Break);
1450         while (! domain.Thrown ())
1451           foreach (Term arg in args)
1452             {
1453               result = arg.Eval (domain);
1454               if (domain.Thrown ())
1455                 return result;
1456             }
1457       } finally {
1458         domain.Uncatch ();
1459       }
1460       return result;
1461     }
1462
1463     private static Term Fwhile (Domain domain, Variable vari, Term[] args)
1464     {
1465       Term result = Zero;
1466       try {
1467         domain.Catch (CatchTag.Break);
1468         while (! domain.Thrown () && args[0].Eval (domain).IsTrue)
1469           for (int i = 1; i < args.Length; i++)
1470             {
1471               result = args[i].Eval (domain);
1472               if (domain.Thrown ())
1473                 return result;
1474             }
1475       } finally {
1476         domain.Uncatch ();
1477       }
1478       return result;
1479     }
1480
1481     private static Term Fcond (Domain domain, Variable vari, Term[] args)
1482     {
1483       foreach (Term arg in args)
1484         {
1485           List<Term> list = arg.Listval;
1486           Term result = list[0].Eval (domain);
1487
1488           if (result.IsTrue)
1489             {
1490               for (int i = 1; i < list.Count; i++)
1491                 {
1492                   domain.depth++;
1493                   result = list[i].Eval (domain);
1494                   domain.depth--;
1495                   if (domain.Thrown ())
1496                     return result;
1497                 }                 
1498               return result;
1499             }
1500         }
1501       return Zero;
1502     }
1503
1504     private static Term Fforeach (Domain domain, Variable vari, Term[] args)
1505     {
1506       Term result = args[0].Eval (domain);
1507       if (domain.Thrown ())
1508         return result;
1509       List<Term> list = result.Listval;
1510       Bindings current = domain.bindings;
1511
1512       try {
1513         domain.Catch (CatchTag.Break);
1514         foreach (Term term in list)
1515           {
1516             domain.Bind (vari, term);
1517             try {
1518               for (int i = 1; i < args.Length; i++)
1519                 {
1520                   result = args[i].Eval (domain);
1521                   if (domain.Thrown ())
1522                     return result;
1523                 }
1524             } finally {
1525               domain.UnboundTo (current);
1526             }
1527           }
1528       } finally {
1529         domain.Uncatch ();
1530       }
1531       return result;
1532     }
1533
1534     private static Term Fquote (Domain domain, Variable vari, Term[] args)
1535     {
1536       return args[0];
1537     }
1538
1539     private static Term Ftype (Domain domain, Variable vari, Term[] args)
1540     {
1541       if (args[0].IsInt)
1542         return TermInt;
1543       if (args[0].IsStr)
1544         return TermStr;
1545       if (args[0].IsSymbol)
1546         return TermSymbol;
1547       if (args[0].IsList)
1548         return TermList;
1549       return TermTerm;
1550     }
1551
1552     private static Term eval_terms (Domain domain, Term[] terms, int idx,
1553                                     out bool caught)
1554     {
1555       Term result= Zero;
1556
1557       caught = false;
1558       for (int i = idx; i < terms.Length; i++)
1559         {
1560           result = terms[i].Eval (domain);
1561           if (domain.Thrown (out caught))
1562             break;
1563         }
1564       return result;
1565     }
1566
1567     public static Term Fcatch (Domain domain, Variable vari, Term[] args)
1568     {
1569       Term result;
1570       bool caught = false;
1571
1572       if (args.Length < 2)
1573         throw new Error (Error.WrongArgument,
1574                          "Too few arguments: {0}", args.Length);
1575       ErrorTerm err = args[0].objval as ErrorTerm;
1576       if (err != null)
1577         {
1578           try {
1579             result = eval_terms (domain, args, 1, out caught);
1580           } catch (System.Exception exception) {
1581             Term term;
1582
1583             Error e = exception as Error;
1584             if (e != null)
1585               term = new Term (new ErrorTerm (e.Name, e.Message, e.Stack));
1586             else
1587               term = new Term (new ErrorTerm (exception));
1588             if (! args[0].Matches (term))
1589               throw exception;
1590             if (vari != null)
1591               vari.SetValue (term);
1592             return One;
1593           }
1594         }
1595       else if (args[0].IsSymbol)
1596         {
1597           try {
1598             domain.Catch (new CatchTag (args[0].Symval));
1599             result = eval_terms (domain, args, 1, out caught);
1600             if (caught)
1601               {
1602                 if (vari != null)
1603                   vari.SetValue (result);
1604                 return One;
1605               }
1606             return Zero;
1607           } finally {
1608             domain.Uncatch ();
1609           }
1610         }
1611       throw new Error (Error.WrongArgument,
1612                        "Not a symbol nor an error: {0}", args[0]);
1613     }
1614
1615     public static Term Fthrow (Domain domain, Variable vari, Term[] args)
1616     {
1617       if (args[0].IsSymbol)
1618         {
1619           domain.ThrowSymbol (args[0]);
1620           return (args[args.Length - 1]);
1621         }
1622       if (args[0].IsError)
1623         {
1624           ErrorTerm err = (ErrorTerm) args[0].objval;
1625           throw new Error (err.ErrorName, err.ErrorMessage);
1626         }
1627       throw new Error (Error.WrongArgument,
1628                        "Not a symbol nor an error: {0}", args[0]);
1629     }
1630
1631     public abstract class TermValue
1632     {
1633       public virtual Term Eval (Domain domain) { return new Term (this); }
1634       public virtual TermValue Clone () { return this; }
1635       public virtual bool IsTrue { get { return true; } }
1636       public virtual bool Matches (TermValue other) { return Equals (other); }
1637       public override abstract bool Equals (object obj);
1638       public override abstract int GetHashCode ();
1639       public abstract string ToString (bool detail);
1640     }
1641
1642     private class Varref : TermValue
1643     {
1644       private static Symbol name = "varref";
1645       public static Symbol Name { get { return name; } }
1646
1647       private Symbol vname;
1648       private Variable vari;
1649
1650       public Varref (Symbol vname) { this.vname = vname; }
1651
1652       public override Term Eval (Domain domain)
1653       {
1654         if (vari == null || vari.domain != domain)
1655           vari = domain.GetVar (vname);
1656         return vari.Value;
1657       }
1658
1659       public static TermValue Parser (Domain domain, XmlNode node)
1660       {
1661         return new Varref ((Symbol) node.Attributes[Qvname].Value);
1662       }
1663
1664       public override bool Equals (object obj)
1665       {
1666         Varref varref = obj as Varref;
1667         return (varref != null && varref.vari.name == vari.name);
1668       }
1669
1670       public override int GetHashCode ()
1671       {
1672         return vari.name.GetHashCode ();
1673       } 
1674
1675       public override string ToString () { return ToString (true); }
1676
1677       public override string ToString (bool detail)
1678       {
1679         return "<varref vname=\"" + vname + "\"/>";
1680       }
1681     }
1682
1683     private class Funcall : TermValue
1684     {
1685       private static Symbol name = "funcall";
1686       public static Symbol Name { get { return name; } }
1687
1688       internal Function func;
1689       internal Variable vari;
1690       internal Term[] args;
1691
1692       public Funcall (Function func, Variable vari, Term[] args)
1693         {
1694           int nargs = args.Length;
1695
1696           if (nargs < func.min_args
1697               || (func.max_args >= 0 && nargs > func.max_args))
1698             throw new Error (Error.WrongArgument,
1699                              "Wrong number of arguments to {0}: {1}",
1700                              func.name, nargs);
1701           if (! func.with_var && vari != null)
1702             throw new Error (Error.WrongArgument,
1703                              "Wrong vname attribute to {0}: {1}",
1704                              func.name, vari.name);
1705           this.func = func;
1706           this.vari = vari;
1707           this.args = args;
1708         }
1709
1710       public static TermValue Parser (Domain domain, XmlNode node)
1711       {
1712         Symbol fname = node.Name;
1713         XmlAttribute attr;
1714
1715         if (fname == Qfuncall)
1716           fname = node.Attributes[Qfname].Value;
1717         Function func = domain.GetFunc (fname);
1718         Variable vari;
1719         attr = node.Attributes[Qvname];
1720         vari = attr == null ? null : domain.GetVar (attr.Value);
1721         XmlNodeList nlist = node.ChildNodes;
1722         int nargs = nlist.Count;
1723         Term[] args = new Term[nargs];
1724         for (int i = 0; i < nargs; i++)
1725           args[i] = Parse (domain, nlist[i]);
1726         return new Funcall (func, vari, args);
1727       }
1728
1729       public override Term Eval (Domain domain)
1730       {
1731         Term result;
1732         domain.TraceWrite (ToString ());
1733         try {
1734           domain.depth++;
1735           result = func.Call (domain, vari, args);
1736         } finally {
1737           domain.depth--;
1738         }
1739         domain.TraceWrite ("=> {0}", result.ToString ());
1740         return result;
1741       }
1742
1743       public override TermValue Clone ()
1744       {
1745         return new Funcall (func, vari, args);
1746       }
1747
1748       public override bool Equals (object obj)
1749       {
1750         Funcall funcall = obj as Funcall;
1751         return (obj != null
1752                 && funcall.func == func
1753                 && funcall.vari == vari
1754                 && funcall.args.Length == args.Length);
1755       }
1756
1757       public override int GetHashCode ()
1758       {
1759         return func.GetHashCode () ^ args.Length;
1760       }
1761
1762       public override string ToString () { return ToString (true); }
1763
1764       public override string ToString (bool detail)
1765       {
1766         string str = "<" + func.name;
1767         if (vari != null)
1768           {
1769             str += " vname=\"" + vari.name + "\"";
1770             if (detail)
1771               str += " val=" + vari.Value.ToString ();
1772           }
1773         if (args.Length == 0 || ! detail)
1774           return str + "/>";
1775         str += ">";
1776         if (func is Function.SpecialForm)
1777           {
1778             for (int i = 0; i < args.Length; i++)
1779               str += ".";
1780           }
1781         else
1782           foreach (Term e in args)
1783             str += e;
1784         return (str + "</" + func.name + ">");
1785       }
1786     }
1787
1788     internal class ErrorTerm : TermValue
1789     {
1790       private static Symbol name = "error";
1791       public static Symbol Name { get { return name; } }
1792       
1793       private readonly Symbol ename;
1794       public Symbol ErrorName { get { return ename; } }
1795       private string message;
1796       public string ErrorMessage { get { return message; } }
1797       private Term[] stack;
1798
1799       public ErrorTerm (Symbol ename, string message)
1800         : this (ename, message, null) { }
1801
1802       internal ErrorTerm (Symbol ename, string message, Term[] stack)
1803         {
1804           this.ename = ename;
1805           this.message = message;
1806           this.stack = stack;
1807         }
1808
1809       internal ErrorTerm (Exception e)
1810         {
1811           if (e is ArithmeticException)
1812             ename = Error.ArithmeticError;
1813           else if (e is IndexOutOfRangeException)
1814             ename = Error.IndexOutOfRange;
1815           else if (e is InsufficientMemoryException
1816                    || e is OutOfMemoryException)
1817             ename = Error.MemoryError;
1818           else
1819             ename = Error.UnknownError;
1820           message = e.Message;
1821         }
1822
1823       public static TermValue Parser (Domain domain, XmlNode node)
1824       {
1825         XmlAttribute attr = node.Attributes[Qename];
1826         Symbol ename = attr == null ? Qnull : (Symbol) attr.Value;
1827         string message = node.InnerText;
1828         return new ErrorTerm (ename, message);
1829       }
1830
1831       public Term[] CallStack {
1832         get { return stack; }
1833         internal set { stack = value; }
1834       }
1835
1836       public override TermValue Clone ()
1837       {
1838         return new ErrorTerm (ename, message);
1839       }
1840
1841       public override bool Equals (object obj)
1842       {
1843         ErrorTerm e = obj as ErrorTerm;
1844         return (e != null && e.ename == ename && e.message == message
1845                 && (e.stack == null ? stack == null
1846                     : (stack != null && e.stack.Length == stack.Length)));
1847       }
1848
1849       public override int GetHashCode ()
1850       {
1851         return ename.GetHashCode ();
1852       }
1853
1854       public override bool Matches (TermValue term)
1855       {
1856         ErrorTerm e = term as ErrorTerm;
1857         return (e != null && (ename == Qnull || e.ename == ename));
1858       }
1859
1860       public override string ToString () { return ToString (true); }
1861
1862       public override string ToString (bool detail)
1863         {
1864           string str = "<error type=\"" + ename + "\">";
1865           if (message != null)
1866             str += message;
1867           if (stack != null)
1868             for (int i = 0; i < stack.Length; i++)
1869               str += stack[i].ToString (false);
1870           return str + "</error>";
1871         }
1872     }
1873
1874     public class Str
1875     {
1876       private string str;
1877       private Regex regex;
1878
1879       public Str (string str) { this.str = str; }
1880
1881       public Str Clone (Str str) { return new Str (str.str); }
1882
1883       public bool Equals (Str str) { return this.str == str.str; }
1884
1885       public bool Matches (Str str)
1886       {
1887         if (regex = null)
1888           regex = new Regex (this.str);
1889         return regex.IsMatch (str.str);
1890       }
1891
1892       public void Insert (int index, Str str)
1893       {
1894         if (index < 0)
1895           this.str = this.str + str.str;
1896         else
1897           this.str = this.str.Insert (index, str.str);
1898         regex = null;
1899       }
1900
1901       public void Insert (int index, char c)
1902       {
1903         if (index < 0)
1904           this.str = this.str + c;
1905         else
1906           this.str = this.str.Insert (index, new string (c, 1));
1907         regex = null;
1908       }
1909
1910       public void Delete (int from, int to)
1911       {
1912         this.str = this.str.Remove (from, to - from);
1913         regex = null;
1914       }
1915     }
1916
1917     public struct Term
1918     {
1919       public int intval;
1920       public object objval;
1921
1922       // <integer>...</integer>
1923       public Term (int i) { intval = i; objval = null; }
1924       // <symbol>...</symbol>
1925       public Term (Symbol name) { intval = 0; objval = name; }
1926       // <string>...</string>
1927       public Term (string str) { intval = 0; objval = new StringBuilder (str); }
1928       // <list>...</list>
1929       public Term (List<Term> list) { intval = 0; objval = list; }
1930       // <error ename="ERROR-NAME">ERROR-MESSASGE</error>
1931       public Term (Symbol name, string message)
1932         {
1933           intval = 0;
1934           objval = new ErrorTerm (name, message);
1935         }
1936
1937       public Term (TermValue obj) { intval = 0; objval = obj; }
1938
1939       // <varref vname="VNAME"/>
1940       public Term (Domain domain, Symbol vname)
1941         {
1942           intval = 0;
1943           objval = new Varref (vname);
1944         }
1945
1946       // <funcall fname="FNAME">...</funcall>
1947       public Term (Domain domain, Symbol fname, Term[] args)
1948         : this (domain, fname, Qnull, args) { }
1949
1950       // <funcall fname="FNAME" vname="VNAME">...</funcall>
1951       public Term (Domain domain, Symbol fname, Symbol vname, Term[] args)
1952         {
1953           intval = 0;
1954
1955           Function func = domain.GetFunc (fname);
1956           Variable vari = vname == Qnull ? null : domain.GetVar (vname);
1957           Funcall funcall = new Funcall (func, vari, args);
1958           if (func is Function.Macro)
1959             {
1960               Term result = funcall.Eval (domain);
1961               intval = result.intval;
1962               objval = result.objval;
1963             }
1964           else
1965             objval = funcall;
1966         }
1967
1968       public object Objval {
1969         get {
1970           if (objval == null)
1971             throw new Error (Error.WrongType,
1972                              "term is an integer: {0}", this);
1973           return objval;
1974         }
1975       }
1976
1977       public int Intval {
1978         get {
1979           if (objval != null)
1980             throw new Error (Error.WrongType, "{0} is not an integer", this);
1981           return intval;
1982         }
1983       }
1984
1985       public Str Strval {
1986         get {
1987           if (! IsStr)
1988             throw new Error (Error.WrongType, "{0} is not a string", this);
1989           return (Str) objval;
1990         }
1991       }
1992
1993       public string Symval {
1994         get {
1995           if (! IsSymbol)
1996             throw new Error (Error.WrongType, "{0} is not a symbol", this);
1997           return (Symbol) objval;
1998         }
1999       }
2000
2001       public List<Term> Listval {
2002         get {
2003           if (! IsList)
2004             throw new Error (Error.WrongType, "{0} is not a list");
2005           return (List<Term>) objval;
2006         }
2007       }
2008
2009       public bool IsTrue {
2010         get {
2011           return (objval == null
2012                   ? (intval != 0)
2013                   : objval is List<Term>
2014                   ? (((List<Term>) objval).Count != 0)
2015                   : objval is TermValue
2016                   ? ((TermValue) objval).IsTrue
2017                   : true);
2018         }
2019       }
2020
2021       public bool IsInt { get { return (objval == null); } }
2022       public bool IsStr { get { return (objval is StringBuilder); } }
2023       public bool IsSymbol { get { return (objval is Symbol); } }
2024       public bool IsList { get { return (objval is List<Term>); } }
2025       public bool IsError { get { return (objval is ErrorTerm); } }
2026
2027       internal Term Eval (Domain domain)
2028       {
2029         if (objval == null || objval is Symbol || objval is string
2030             || objval is List<Term>)
2031           return this;
2032         try {
2033           domain.CallStackPush (this);
2034           return ((TermValue) objval).Eval (domain);
2035         } catch (Error e) {
2036           if (e.Stack == null)
2037             e.Stack = domain.CallStack;
2038           throw e;
2039         } finally {
2040           domain.CallStackPop ();
2041         }
2042       }
2043
2044       public Term Clone ()
2045       {
2046         if (objval == null || objval is Symbol)
2047           return this;
2048         if (objval is StringBuilder)
2049           return new Term (((StringBuilder) objval).ToString ());
2050         if (objval is List<Term>)
2051           {
2052             List<Term> list = new List<Term> ();
2053             list.InsertRange (0, ((List<Term>) objval));
2054             return new Term (list);
2055           }
2056         return new Term (((TermValue) objval).Clone ());
2057       }
2058
2059       public static bool operator== (Term t1, Term t2)
2060         {
2061           return t1.Equals (t2);
2062         }
2063
2064       public static bool operator!= (Term t1, Term t2) { return ! (t1 == t2); }
2065
2066       public override bool Equals (object obj)
2067       {
2068         if (! (obj is Term))
2069           return false;
2070         Term term = (Term) obj;
2071         if (IsInt)
2072           return term.IsInt && term.Intval == Intval;
2073         if (IsSymbol)
2074           return term.IsSymbol && term.Symval == Symval;
2075         if (IsStr)
2076           return (term.IsStr && term.Strval.Equals (Strval));
2077         if (IsList)
2078           {
2079             if (! term.IsList)
2080               return false;
2081             List<Term> l1 = objval as List<Term>;
2082             List<Term> l2 = term.objval as List<Term>;
2083
2084             if (l1.Count != l2.Count)
2085               return false;
2086             for (int i = 0; i < l1.Count; i++)
2087               if (! l1[i].Equals (l2[i]))
2088                 return false;
2089             return true;
2090           }
2091         return ((TermValue) objval).Equals (obj);
2092       }
2093
2094       public override int GetHashCode () { return intval; }
2095
2096       public bool Matches (Term term)
2097       {
2098         if (IsInt)
2099           return term.IsInt && Intval == term.Intval;
2100         if (IsSymbol)
2101           return term.IsSymbol && Symval == term.Symval;
2102         if (IsStr)
2103           return term.IsStr && Strval.Matches (term.Strval);
2104         if (IsList)
2105           {
2106             if (! term.IsList)
2107               return false;
2108             List<Term> l1 = objval as List<Term>;
2109             List<Term> l2 = term.objval as List<Term>;
2110
2111             if (l1.Count > l2.Count)
2112               return false;
2113             for (int i = 0; i < l1.Count; i++)
2114               if (! l1[i].Equals (l2[i]))
2115                 return false;
2116             return true;
2117           }
2118         return ((TermValue) objval).Matches ((TermValue) term.objval);
2119       }
2120
2121       public override string ToString () { return ToString (true); }
2122
2123       public string ToString (bool detail)
2124       {
2125         string str;
2126
2127         if (objval == null)
2128           str = "<integer>" + intval + "</integer>";
2129         else if (objval is Symbol)
2130           str = "<symbol>" + objval + "</symbol>";
2131         else if (objval is string)
2132           str = "<string>" + objval + "</string>";
2133         else if (objval is List<Term>)
2134           {
2135             if (detail)
2136               {
2137                 str = "<list>";
2138                 foreach (Term e in (List<Term>) objval)
2139                   str += e;
2140                 str += "</list>";
2141               }
2142             else
2143               str = "<list/>";
2144           }
2145         else if (objval is Term)
2146           str = "<quote>" + objval + "</quote>";
2147         else
2148           str = ((TermValue) objval).ToString (detail);
2149         return str;
2150       }
2151     }
2152
2153     private static Term Zero = new Term (0);
2154     private static Term One = new Term (1);
2155     private static Term TermInt = new Term (Qinteger);
2156     private static Term TermStr = new Term (Qstring);
2157     private static Term TermSymbol = new Term (Qsymbol);
2158     private static Term TermList = new Term (Qlist);
2159     private static Term TermTerm = new Term ((Symbol) "term");
2160
2161     private static int parse_integer (XmlNode node)
2162     {
2163       string str = node.InnerText;
2164       int len = str.Length;
2165       int i, c;
2166
2167       if (len == 2 && str[0] == '?')
2168         return str[1];
2169       if (len > 2
2170           && str[1] == 'x' && ((c = str[0]) == '0' || c == '#'))
2171         {
2172           if (! int.TryParse (str.Substring (2),
2173                               Globalization.NumberStyles.HexNumber, null,
2174                               out i))
2175             throw new Error (Error.InvalidInteger, node,
2176                              "Not a integer string: {0}", str);
2177           return i;
2178         }
2179       if (! int.TryParse (str, out i))
2180         throw new Error (Error.InvalidInteger, node,
2181                          "Not a integer string: {0}", str);
2182       return i;
2183     }
2184
2185     private static Symbol parse_defvar (Domain domain, XmlNode node)
2186     {
2187       XmlAttribute name = node.Attributes[Qvname];
2188       if (name == null)
2189         throw new Error (Error.NoVariableName, node,
2190                          "No variable name to define");
2191       Symbol vname = name.Value;
2192       String desc;
2193       Variable vari;
2194
2195       node = node.FirstChild;
2196       if (node != null && node.Name == Qdescription)
2197         {
2198           desc = node.InnerText;
2199           node = node.NextSibling;
2200         }
2201       else
2202         desc = null;
2203       if (node != null)
2204         {
2205           Symbol type = node.Name;
2206           XmlNodeList range_list = null;
2207           int nranges = 0;
2208           XmlNode n = node.NextSibling;
2209
2210           if (n != null)
2211             {
2212               range_list = n.ChildNodes;
2213               nranges = range_list.Count;
2214             }
2215
2216           if (type == Qinteger)
2217             {
2218               int val = parse_integer (node);
2219               int[] range = null;
2220               if (range_list != null)
2221                 {
2222                   range = new int[nranges * 2];
2223                   for (int i = 0; i < nranges; i++)
2224                     {
2225                       XmlNode nd = range_list[i];
2226                       if (nd.Name == Qrange)
2227                         {
2228                           range[i * 2] = parse_integer (nd.FirstChild);
2229                           range[i * 2 + 1] = parse_integer (nd.LastChild);
2230                         }
2231                       else
2232                         {
2233                           range[i * 2] = range[i * 2 + 1]
2234                             = parse_integer (nd.FirstChild);
2235                         }
2236                     }
2237                 }
2238               vari = domain.DefvarInt (vname, val, desc, range);
2239             }
2240           else if (type == Qstring)
2241             {
2242               string[] range = null;
2243               if (range_list != null)
2244                 {
2245                   range = new string[nranges];
2246                   for (int i = 0; i < nranges; i++)
2247                     range[i] = range_list[i].FirstChild.InnerText;
2248                 }
2249               vari = domain.DefvarStr (vname, node.InnerText, desc, range);
2250             }
2251           else if (type == Qsymbol)
2252             {
2253               Symbol[] range = null;
2254               if (range_list != null)
2255                 {
2256                   range = new Symbol[nranges];
2257                   for (int i = 0; i < nranges; i++)
2258                     range[i] = range_list[i].FirstChild.InnerText;
2259                 }
2260               vari = domain.DefvarSym (vname, (Symbol) node.InnerText, desc,
2261                                        range);
2262             }
2263           else
2264             throw new Error (Error.TermTypeInvalid, "Unknown type: {0}", type);
2265         }
2266       else
2267         {
2268           if (domain.variables.TryGetValue (vname, out vari))
2269             vari = vari.Clone (domain);
2270           else
2271             vari = new Variable (domain, vname, Zero);
2272           domain.variables[vname] = vari;
2273         }
2274       return vname;
2275     }
2276
2277     private static Variable[] parse_args (Domain domain, XmlNode node,
2278                                           out int min_args, out int max_args)
2279     {
2280       int nfixed = 0;
2281       int noptional = 0;
2282       int nrest = 0;
2283       Variable[] args;
2284
2285       node = node.FirstChild;
2286       if (node != null && node.Name == Qargs)
2287         {
2288           XmlNode n;
2289           for (n = node.FirstChild; n != null; n = n.NextSibling)
2290             {
2291               if (n.Name == Qfixed)
2292                 nfixed++;
2293               else if (n.Name == Qoptional)
2294                 noptional++;
2295               else if (n.Name == Qrest)
2296                 {
2297                   if (nrest > 0)
2298                     throw new Error (Error.WrongType, n, "Too many <rest>");
2299                   nrest++;
2300                 }
2301               else
2302                 throw new Error (Error.WrongType, n,
2303                                  "Not fixed, optional, nor rest: {0}", n.Name);
2304             }
2305           min_args = nfixed;
2306           max_args = nfixed + noptional + nrest;
2307           args = new Variable[max_args];
2308           n = node.FirstChild;
2309           for (int i = 0; i < max_args; n = n.NextSibling)
2310             args[i++] = domain.Defvar ((Symbol) n.Attributes[0].Value);
2311           if (nrest == 1)
2312             max_args = - max_args;
2313         }
2314       else
2315         {
2316           min_args = max_args = 0;
2317           args = new Variable[0];
2318         }
2319       return args;
2320     }
2321
2322     public static Symbol parse_defun_head (Domain domain, XmlNode node)
2323     {
2324       Symbol name = node.Attributes[Qfname].Value;
2325       int min_args, max_args;
2326       Variable[] args;
2327
2328       args = parse_args (domain, node, out min_args, out max_args);
2329       if (node.Name == Qdefun)
2330         domain.Defun (name, min_args, max_args, args, null);
2331       else
2332         domain.Defmacro (name, min_args, max_args, args, null);
2333       return name;
2334     }
2335
2336     public static void parse_defun_body (Domain domain, XmlNode node)
2337     {
2338       bool is_defun = node.Name == Qdefun;
2339       Symbol name = node.Attributes[Qfname].Value;
2340       Function func = domain.GetFunc (name);
2341
2342       for (node = node.FirstChild; node != null; node = node.NextSibling)
2343         if (node.Name != Qdescription
2344             && node.Name != Qargs)
2345           break;
2346       Term[] body = Parse (domain, node, null);
2347       if (is_defun)
2348         ((Function.Lambda) func).SetBody (body);
2349       else
2350         ((Function.Macro) func).SetBody (body);
2351     }
2352
2353     public static Term Parse (Domain domain, XmlNode node)
2354     {
2355       Symbol name = node.Name;
2356
2357       try {
2358         if (name == Qinteger)
2359           return new Term (parse_integer (node));
2360         if (name == Qsymbol)
2361           return new Term ((Symbol) node.InnerText);
2362         if (name == Qstring)
2363           return new Term (node.InnerText);
2364         if (name == Qlist)
2365           {
2366             List<Term> list = new List<Term> ();
2367             for (node = node.FirstChild; node != null;
2368                  node = node.NextSibling)
2369               list.Add (Parse (domain, node));
2370             return new Term (list);
2371           }
2372         if (name == Qdefun || name == Qdefmacro)
2373           {
2374             name = parse_defun_head (domain, node);
2375             parse_defun_body (domain, node);
2376             return new Term (name);
2377           }
2378         if (name == Qdefvar)
2379           {
2380             name = parse_defvar (domain, node);
2381             return new Term (name);
2382           }
2383         MethodInfo parser;
2384         if (domain.termtypes.TryGetValue (name, out parser))
2385           {
2386             object[] arg = new object[] { domain, node };
2387             return new Term ((TermValue) parser.Invoke (null, arg));
2388           }
2389
2390         Funcall funcall = (Funcall) Funcall.Parser (domain, node);
2391         if (funcall.func is Function.Macro)
2392           return funcall.Eval (domain);
2393         return new Term (funcall);
2394       } catch (Error e) {
2395         if (e.Node == null)
2396           e.Node = node;
2397         throw e;
2398       } catch (Exception e) {
2399         throw new Error (Error.UnknownError, node, e, "Parsing error");
2400       }
2401     }
2402
2403     private static bool default_stop (XmlNode n) { return n == null; }
2404
2405     public static Term[] Parse (Domain domain, XmlNode node,
2406                                 Func<XmlNode, bool> stop)
2407     {
2408       if (stop == null)
2409         stop = default_stop;
2410
2411       XmlNode n;
2412       for (n = node; ! stop (n); n = n.NextSibling)
2413         if (n.NodeType == XmlNodeType.Element
2414             && (n.Name == Qdefun || n.Name == Qdefmacro))
2415           {
2416             try {
2417               parse_defun_head (domain, n);
2418             } catch (Error e) {
2419               if (e.Node == null)
2420                 e.Node = node;
2421               throw e;
2422             } catch (Exception e) {
2423               throw new Error (Error.UnknownError, node, e, "Parsing error");
2424             }
2425           }
2426
2427       List<Term> terms = new List<Term> ();
2428       for (; node != n; node = node.NextSibling)
2429         if (node.NodeType == XmlNodeType.Element)
2430           {
2431             try {
2432               if (node.Name == Qdefun || node.Name == Qdefmacro)
2433                 parse_defun_body (domain, node);
2434               else if (node.Name == Qdefvar)
2435                 parse_defvar (domain, node);
2436               else
2437                 terms.Add (Parse (domain, node));
2438             } catch (Error e) {
2439               if (e.Node == null)
2440                 e.Node = node;
2441               throw e;
2442             } catch (Exception e) {
2443               throw new Error (Error.UnknownError, node, e, "Parsing error");
2444             }
2445           }
2446       return terms.ToArray ();
2447     }
2448
2449     public static Term[] Parse (Domain domain, string url)
2450     {
2451       XmlDocument doc = new XmlDocument (Symbol.NameTable);
2452       XmlNode node;
2453
2454       using (XmlTextReader reader = new XmlTextReader (url, doc.NameTable))
2455         {
2456           do {
2457             reader.Read ();
2458           } while (reader.NodeType != XmlNodeType.None
2459                    && (reader.NodeType != XmlNodeType.Element
2460                        || reader.Name != Qexpr));
2461           if (reader.NodeType == XmlNodeType.None)
2462             throw new Exception ("Node <expr> not found");
2463           node = doc.ReadNode (reader);
2464         }
2465       return Parse (domain, node.FirstChild, null);
2466     }
2467
2468     public static Term Eval (Domain domain, Term[] terms)
2469     {
2470       Term result = Zero;
2471
2472       try {
2473         foreach (Term term in terms)
2474           {
2475             result = term.Eval (domain);
2476             if (domain.Thrown ())
2477               return result;
2478           }
2479         return result;
2480       } catch (Error e) {
2481         throw e;
2482       } catch (Exception e) {
2483         throw new Error (Error.UnknownError, null, e, "Runtime error");
2484       }
2485     }
2486   }
2487 }