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