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