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