*** 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.Expression
8 {
9   public class Xex
10   {
11     public struct Name : IEquatable<Name>
12     {
13       private static NameTable nt = new NameTable ();
14
15       private string name;
16
17       public Name (string str)
18         {
19           name = nt.Add (str);
20         }
21
22       public static implicit operator Name (string str)
23       {
24         return new Name (str);
25       }
26
27       public static implicit operator string (Name name)
28       {
29         return name.name;
30       }
31
32       public static bool operator== (Name n1, Name n2)
33         {
34           return (object) n1.name == (object) n2.name;
35         }
36
37       public static bool operator!= (Name n1, Name n2)
38         {
39           return (object) n1.name != (object) n2.name;
40         }
41
42       public static bool operator== (Name n1, string n2)
43         {
44           return (object) n1.name == (object) n2;
45         }
46
47       public static bool operator!= (Name n1, string n2)
48         {
49           return (object) n1.name != (object) n2;
50         }
51
52       public static bool operator== (string n1, Name n2)
53         {
54           return (object) n1 == (object) n2.name;
55         }
56
57       public static bool operator!= (string n1, Name n2)
58         {
59           return (object) n1 != (object) n2.name;
60         }
61
62       public bool Equals (Name name)
63       {
64         return Object.ReferenceEquals (this.name, name.name);
65       }
66
67       public override bool Equals (object obj)
68       {
69         return Object.ReferenceEquals (this.name, obj);
70       }
71
72       public override int GetHashCode ()
73       {
74         return name.GetHashCode ();
75       }
76
77       public static NameTable Table { get { return nt; } }
78
79       public override string ToString () { return name; }
80     }
81
82     private static Name Nexpr = "expr";
83     private static Name Ntype = "type";
84
85     private static Name Ninteger = "integer";
86     private static Name Nstring = "string";
87     private static Name Nboolean = "boolean";
88     private static Name Nsymbol = "symbol";
89     private static Name Nlist = "list";
90     private static Name Nobject = "object";
91
92     private static Name Ndefun = "defun";
93     private static Name Nfname = "fname";
94     private static Name Nargs = "args";
95     private static Name Noptional = "optional";
96     private static Name Nrest = "rest";
97     private static Name Nbody = "body";
98
99     private static Name Ndefvar = "defvar";
100     private static Name Nconst = "const";
101     private static Name Nvariable = "variable";
102     private static Name Ndescription = "description";
103     private static Name Npossible_value = "possible-value";
104
105     private static Name Nfuncall = "funcall";
106     private static Name Nprogn = "progn";
107
108     internal class Function
109     {
110       internal class Lambda
111       {
112         internal Xex[] args;
113         internal Xex[] body;
114
115         public void SetArgs (XmlNode node, int nargs, Domain domain)
116         {
117           args = new Xex[nargs];
118           node = node.FirstChild;
119           for (int i = 0; i < nargs; node = node.NextSibling)
120             if (node.Name != Noptional && node.Name != Nrest)
121               args[i++] = new Xex (node, domain);
122         }
123
124         public void SetBody (XmlNode node, Domain domain)
125         {
126           XmlNodeList nlist = node.ChildNodes;
127
128           body = new Xex[nlist.Count];
129           for (int i = 0; i < nlist.Count; i++)
130             body[i] = new Xex (nlist[i], domain);
131         }
132       }
133
134       public readonly Name name;
135       public Builtin builtin;
136       public int min_arg, max_arg;
137       internal Lambda lambda;
138       public bool specialp = false;
139
140       public Function (Name name, Builtin builtin,
141                        int min_arg, int max_arg, bool specialp)
142       {
143         this.name = name;
144         this.builtin = builtin;
145         this.min_arg = min_arg;
146         this.max_arg = max_arg;
147         this.specialp = specialp;
148       }
149
150       public Function (Name name, int min_arg, int max_arg)
151       {
152         this.name = name;
153         this.min_arg = min_arg;
154         this.max_arg = max_arg;
155       }
156
157       public void Setup (XmlNode node, Domain domain)
158       {
159         lambda = new Lambda ();
160         node = node.FirstChild;
161         if (node.Name == Nargs)
162           {
163             lambda.SetArgs (node, max_arg, domain);
164             node = node.NextSibling;
165           }
166         if (node.Name == Nbody)
167           lambda.SetBody (node, domain);
168       }
169
170       public static Name ParseHead (XmlNode node,
171                                     out int min_arg, out int max_arg)
172       {
173         Name name = node.Attributes[Nfname].Value;
174         int nargs = 0, noptions = 0, nrest = 0;
175         XmlNode n;
176             
177         for (n = node.FirstChild; n != null; n = n.NextSibling)
178           {
179             if (n.Name == Noptional || n.Name == Nrest)
180               break;
181             nargs++;
182           }
183         if (n != null && n.Name == Noptional)
184           for (n = n.NextSibling; n != null; n = n.NextSibling)
185             {
186               if (n.Name == Nrest)
187                 break;
188               noptions++;
189             }
190         if (n != null && n.Name == Nrest)
191           for (n = n.NextSibling; n != null; n = n.NextSibling)
192             nrest++;
193         min_arg = nargs;
194         max_arg = nargs + noptions + nrest;
195         if (nrest == 1)
196           max_arg = - max_arg;
197         return name;
198       }
199
200       public object Call (Xex[] args, Domain domain)
201       {
202         Bindings current = domain.bindings;
203         object result = false;
204
205         Console.Write ("calling (" + this);
206         try {
207           foreach (Xex e in args)
208             Console.Write (" " + e);
209           Console.Write (") => ");
210           if (builtin != null)
211             {
212               if (! specialp)
213                 foreach (Xex a in args)
214                   if (a.Eval (domain) == null)
215                     throw new Exception (a + ":evaled to null");
216               result = builtin (args, domain);
217               Console.WriteLine (result);
218               return result;
219             }
220
221           int i;
222           for (i = 0; i < min_arg; i++)
223             {
224               Xex a = lambda.args[i];
225               bool isdirect = a.args == null;
226               Name name = isdirect ? (Name) a.val : (Name) a.args[0].val;
227               Variable var = new VarMisc (name, null);
228
229               domain.variables[name] = var;
230               if (isdirect)
231                 domain.Bind (var, args[i]);
232               else
233                 domain.Bind (var, args[i].Eval (domain));
234             }
235           foreach (Xex e in lambda.body)
236             result = e.Eval (domain);
237           Console.WriteLine (result);
238         } finally {
239           domain.UnboundTo (current);
240         }
241         return result;
242       }
243
244       public override string ToString ()
245       {
246         string str;
247
248         if (builtin != null)
249           str = name;
250         else
251           {
252             str = "(" + name;
253             foreach (Xex a in lambda.args)
254               str += " " + a;
255             str += ")";
256           }
257         return str;
258       }
259     }
260
261     internal abstract class Variable
262     {
263       public readonly Name name;
264       public readonly Name type;
265       internal object val;
266
267       public Variable (Name name, Name type, object value)
268       {
269         if (value != null)
270           Value = value;
271         this.name = name;
272         this.type = type;
273       }
274
275       public object Value
276       {
277         get { return val; }
278         set
279           {
280             if (! ValueP (value))
281               throw new Exception ("Invalid value type: " + value);
282             val = value;
283           }
284       }
285
286       public abstract bool ValueP (object value);
287
288       public override string ToString () { return name + "=" + val; }
289     }
290
291     internal class VarInt : Variable
292     {
293       public struct Range
294       {
295         public int from, to;
296       }
297
298       public Range[] ranges;
299
300       public VarInt (Name name, object value) : base (name, Ninteger, value) { }
301
302       public override bool ValueP (object value)
303       {
304         int i;
305
306         if (! (value is int))
307           return false;
308         if (ranges == null)
309           return true;
310         i = (int) value;
311         foreach (Range r in ranges)
312           if (i >= r.from && i <= r.to)
313             return true;
314         return false;
315       }
316     }
317
318     internal class VarStr : Variable
319     {
320       public string[] ranges;
321
322       public VarStr (Name name, object value) : base (name, Nstring, value) { }
323
324       public override bool ValueP (object value)
325       {
326         string str;
327
328         if (! (value is string))
329           return false;
330         if (ranges == null)
331           return true;
332         str = (string) value;
333         foreach (string s in ranges)
334           if (s == str)
335             return true;
336         return false;
337       }
338     }
339
340     internal class VarBool : Variable
341     {
342       public VarBool (Name name, object value)
343         : base (name, Nboolean, value) { }
344
345       public override bool ValueP (object value)
346       {
347         if (! (value is bool))
348           return false;
349         return true;
350       }
351     }
352
353     internal class VarMisc : Variable
354     {
355       public VarMisc (Name name, object value) : base (name, Nobject, value) { }
356
357       public override bool ValueP (object value)
358       {
359         return true;
360       }
361     }
362
363     internal class Bindings
364     {
365       private Variable vari;
366       private object old_value;
367       private Bindings next;
368         
369       private Bindings (Variable vari, object value)
370       {
371         this.vari = vari;
372         old_value = value;
373       }
374         
375       public static Bindings Bind (Bindings bindings,
376                                    Variable vari, object value)
377       {
378         Bindings b = new Bindings (vari, vari.val);
379
380         b.vari.Value = value;
381         b.next = bindings;
382         return b;
383       }
384
385       internal Bindings UnboundTo (Bindings boundary)
386       {
387         for (Bindings b = this; b != boundary; b = b.next)
388           vari.val = b.old_value;
389         return boundary;
390       }
391
392       public override string ToString ()
393       {
394         string str = "(bindings";
395         for (Bindings b = this; b != null; b = b.next)
396           str += " " + vari;
397         return str + ")";
398       }
399     }
400
401 #if false
402     internal class ThrowException : Exception
403     {
404       Name tag;
405       public object value;
406
407       public ThrowException (Name tag, object value) : base ()
408         {
409           this.tag = tag;
410           this.value = value;
411         }
412     }
413 #endif
414
415     public class Domain
416     {
417       public object context;
418
419       internal Dictionary<Name, Function> functions;
420       internal Dictionary<Name, Variable> variables;
421       internal Bindings bindings;
422
423       internal Domain ()
424       {
425         functions = new Dictionary<Name, Function> ();
426         variables = new Dictionary<Name, Variable> ();
427       }
428
429       public Domain (object context) : this (basic, context)
430       {
431       }
432
433       public Domain (Domain parent, object context)
434       {
435         functions = new Dictionary<Name, Function> (parent.functions);
436         variables = new Dictionary<Name, Variable> (parent.variables);
437         this.context = context;
438       }
439
440       internal void Bind (Variable vari, object value)
441       {
442         bindings = Bindings.Bind (bindings, vari, value);
443       }
444
445       internal void UnboundTo (Bindings boundary)
446       {
447         if (bindings != null)
448           bindings = bindings.UnboundTo (boundary);
449       }
450
451       public void Defun (Name name, Builtin builtin, int min_arg, int max_arg)
452       {
453         Defun (name, builtin, min_arg, max_arg, false);
454       }
455
456       public void Defun (Name name, Builtin builtin,
457                          int min_arg, int max_arg, bool specialp)
458       {
459         Function func;
460
461         if (functions.TryGetValue (name, out func))
462           {
463             if (func.min_arg < min_arg || func.max_arg > max_arg)
464               throw new Exception ("Incompatible argument numbers to override: "
465                                    + name);
466             func.builtin = builtin;
467             func.lambda = null;
468             func.min_arg = min_arg;
469             func.max_arg = max_arg;
470             func.specialp = specialp;
471           }
472         else
473           {
474             functions[name]
475               = new Function (name, builtin, min_arg, max_arg, specialp);
476           }
477       }
478
479       internal Function RegisterFunction (XmlNode node)
480       {
481         int min_arg, max_arg;
482         Name name = Function.ParseHead (node, out min_arg, out max_arg);
483         Function func = new Function (name, min_arg, max_arg);
484
485         functions[name] = func; 
486         return func;
487       }
488
489       internal Function Defun (XmlNode node)
490       {
491         Name name = node.Attributes[Nfname].Value;
492         Function func;
493
494         if (! functions.TryGetValue (name, out func))
495           func = RegisterFunction (node);
496         func.Setup (node, this);
497         return func;
498       }
499
500       public void Defvar (Name name, XmlNode node)
501       {
502         Variable vari;
503
504         if (node.Name == Ndescription)
505           node = node.NextSibling;
506         if (node.Name == Nconst)
507           {
508             Name type = (Name) node.Attributes[Ntype].Value;
509             string val = node.Value;
510             XmlNodeList range_list = null;
511             int nranges = 0;
512
513             node = node.NextSibling;
514             if (node.Name == Npossible_value)
515               {
516                 range_list = node.ChildNodes;
517                 nranges = range_list.Count;
518               }
519
520             if (type == Ninteger)
521               {
522                 VarInt vi = new VarInt (name, parse_integer (val));
523                 if (range_list != null)
524                   {
525                     vi.ranges = new VarInt.Range[nranges];
526
527                     for (int i = 0; i < nranges; i++)
528                       {
529                         XmlNode n = range_list[i];
530
531                         if (n.Name == Nconst)
532                           {
533                             int num = parse_integer (n.Value);
534                             vi.ranges[i].from = vi.ranges[i].to = num;
535                           }
536                         else    // range_list[i].Name == "range"
537                           {
538                             vi.ranges[i].from =
539                               parse_integer (n.FirstChild.Value);
540                             vi.ranges[i].to =
541                               parse_integer (n.LastChild.Value);
542                           }
543                       }
544                   }
545                 vari = vi;
546               }
547             else if (type == Nstring)
548               {
549                 VarStr vs = new VarStr (name, val);
550                 if (range_list != null)
551                   vs.ranges = new string[nranges];
552                 for (int i = 0; i < nranges; i++)
553                   vs.ranges[i] = range_list[i].Value;
554                 vari = vs;
555               }
556             else if (type == Nboolean)
557               {
558                 vari = new VarBool (name, val == "true");
559               }
560             else
561               throw new Exception ("Unknown type: " + type);
562           }
563         else
564           vari = new VarMisc (name, null);
565         variables[name] = vari;
566       }
567
568       internal Function GetFunc (Name name)
569       {
570         Function func;
571
572         if (! functions.TryGetValue (name, out func))
573           throw new Exception ("Unknown function: " + name);
574         return func;
575       }
576
577       public bool CopyFunc (Domain domain, Name name)
578       {
579         Function func = GetFunc (name);
580
581         domain.functions[name] = func;
582         return true;
583       }
584
585       public void CopyFunc (Domain domain)
586       {
587         foreach (KeyValuePair<Name, Function> kv in functions)
588           domain.functions[kv.Key] = kv.Value;
589       }
590
591       internal Variable GetVar (Name name)
592       {
593         Variable vari;
594
595         if (! variables.TryGetValue (name, out vari))
596           variables[name] = vari = new VarMisc (name, null);
597         return vari;
598       }
599
600       internal Variable GetVar (Xex e)
601       {
602         if (! (e.val is Name))
603           throw new Exception ("Not a symbol" + e.val);
604         return GetVar ((Name) e.val);
605       }
606
607       public override string ToString ()
608       {
609         string str = "<(functions";
610         foreach (KeyValuePair<Name, Function> kv in functions)
611           str += " " + kv.Key;
612         str += ") (variabls";
613         foreach (KeyValuePair<Name, Variable> kv in variables)
614           str += " " + kv.Key;
615         str += ")";
616         if (bindings != null)
617           str += " " + bindings;
618         if (context != null)
619           str += " (" + context + ")";
620         str += ">";
621         return str;
622       }
623     }
624
625     public delegate object Builtin (Xex[] args, Domain domain);
626
627     private static Domain basic = new Domain ();
628
629     internal static Function Fprogn;
630
631     static Xex ()
632     {
633       basic.Defun ("set", set_value, 2, 2, false);
634       basic.Defun ("=", set_value, 2, 2, false);
635       basic.Defun ("and", and, 1, -1, false);
636       basic.Defun ("&&", and, 1, -1, false);
637       basic.Defun ("or", or, 1, -1, false);
638       basic.Defun ("||", or, 1, -1, false);
639       basic.Defun ("not", not, 1, 1, false);
640       basic.Defun ("!", not, 1, 1, false);
641       basic.Defun ("add", add, 2, -1, false);
642       basic.Defun ("+", add, 2, -1, false);
643       basic.Defun ("mul", mul, 2, -1, false);
644       basic.Defun ("*", mul, 2, -1, false);
645       basic.Defun ("sub", sub, 1, -1, false);
646       basic.Defun ("-", sub, 1, -1, false);
647       basic.Defun ("div", div, 2, -1, false);
648       basic.Defun ("/", div, 2, -1, false);
649       basic.Defun ("mod", mod, 2, 2, false);
650       basic.Defun ("%", mod, 2, 2, false);
651       basic.Defun ("logior", logior, 2, -1, false);
652       basic.Defun ("|", logior, 2, -1, false);
653       basic.Defun ("logand", logand, 2, -1, false);
654       basic.Defun ("&", logand, 2, -1, false);
655       basic.Defun ("add-set", add_set, 2, -1, true);
656       basic.Defun ("+=", add_set, 2, -1, true);
657       basic.Defun ("mul-set", mul_set, 2, -1, true);
658       basic.Defun ("*=", mul_set, 2, -1, true);
659       basic.Defun ("sub-set", sub_set, 2, -1, true);
660       basic.Defun ("-=", sub_set, 2, -1, true);
661       basic.Defun ("div-set", div_set, 2, -1, true);
662       basic.Defun ("/=", div_set, 2, -1, true);
663       basic.Defun ("mod-set", mod_set, 2, 2, true);
664       basic.Defun ("%=", mod_set, 2, 2, true);
665       basic.Defun ("logior-set", logior_set, 2, -1, true);
666       basic.Defun ("|=", logior_set, 2, -1, true);
667       basic.Defun ("logand-set", logand_set, 2, -1, true);
668       basic.Defun ("&=", logand_set, 2, -1, true);
669       basic.Defun ("lsh", lsh, 2, 2, false);
670       basic.Defun ("<<", lsh, 2, 2, false);
671       basic.Defun ("rsh", rsh, 2, 2, false);
672       basic.Defun (">>", rsh, 2, 2, false);
673       basic.Defun ("lsh-set", lsh_set, 2, 2, true);
674       basic.Defun ("<<=", lsh_set, 2, 2, true);
675       basic.Defun ("rsh-set", rsh_set, 2, 2, true);
676       basic.Defun (">>=", rsh_set, 2, 2, true);
677       basic.Defun ("eq", eq, 2, -1, false);
678       basic.Defun ("==", eq, 2, -1, false);
679       basic.Defun ("noteq", noteq, 2, 2, false);
680       basic.Defun ("!=", noteq, 2, 2, false);
681       basic.Defun ("lt", less_than, 2, -1, false);
682       basic.Defun ("<", less_than, 2, -1, false);
683       basic.Defun ("le", less_eq, 2, -1, false);
684       basic.Defun ("<=", less_eq, 2, -1, false);
685       basic.Defun ("gt", greater_than, 2, -1, false);
686       basic.Defun (">", greater_than, 2, -1, false);
687       basic.Defun ("ge", greater_eq, 2, -1, false);
688       basic.Defun (">=", greater_eq, 2, -1, false);
689       basic.Defun ("eval", eval_clause, 1, 1, true);
690       basic.Defun ("progn", progn_clause, 0, -1, true);
691       basic.Defun ("expr", progn_clause, 0, -1, true);
692       basic.Defun ("if", if_clause, 2, -1, true);
693       basic.Defun ("when", when_clause, 1, -1, true);
694       basic.Defun ("while", while_clause, 1, -1, true);
695
696       Fprogn = basic.GetFunc (Nprogn);
697     }
698
699     private static bool is_true (object val)
700     {
701       return (val is bool ? (bool) val
702               : val is int ? (int) val == 0
703               : true);
704     }
705
706     private static object set_value (Xex[] args, Domain domain)
707     {
708       Variable vari = domain.GetVar (args[0]);
709
710       vari.Value = args[1].val;
711       return vari.val;
712     }
713
714     private static object and (Xex[] args, Domain domain)
715     {
716       foreach (Xex arg in args)
717         if (! is_true (arg.val))
718           return false;
719       return true;
720     }
721
722     private static object or (Xex[] args, Domain domain)
723     {
724       foreach (Xex arg in args)
725         if (is_true (arg.val))
726           return true;
727       return false;
728     }
729
730     private static object not (Xex[] args, Domain domain)
731     {
732       return ! is_true (args[0].val);
733     }
734
735     private static object add (Xex[] args, Domain domain)
736     {
737       int n = 0;
738       foreach (Xex e in args)
739         n += (int) e.val;
740       return n;
741     }
742
743     private static object mul (Xex[] args, Domain domain)
744     {
745       int n = 1;
746       foreach (Xex e in args)
747         n *= (int) e.val;
748       return n;
749     }
750
751     private static object sub (Xex[] args, Domain domain)
752     {
753       int n = (int) args[0].val;
754       if (args.Length == 1)
755         return - n;
756       for (int i = 1; i < args.Length; i++)
757         n -= (int) args[i].val;
758       return n;
759     }
760
761     private static object div (Xex[] args, Domain domain)
762     {
763       int n = (int) args[0].val;
764       for (int i = 1; i < args.Length; i++)
765         n /= (int) args[i].val;
766       return n;
767     }
768
769     private static object mod (Xex[] args, Domain domain)
770     {
771       return ((int) args[0].val % (int) args[1].val);
772     }
773
774     private static object logior (Xex[] args, Domain domain)
775     {
776       int n = 0;
777       foreach (Xex e in args)
778         n |= (int) e.val;
779       return n;
780     }
781
782     private static object logand (Xex[] args, Domain domain)
783     {
784       int n = (int) args[0].val;
785       for (int i = 1; i < args.Length; i++)
786         n &= (int) args[i].val;
787       return n;
788     }
789
790     private static object add_set (Xex[] args, Domain domain)
791     {
792       Variable vari = domain.GetVar (args[0]);
793       int n = (int) vari.val;
794
795       for (int i = 1; i < args.Length; i++)
796         n += (int) args[i].val;
797       vari.val = n;
798       return n;
799     }
800
801     private static object mul_set (Xex[] args, Domain domain)
802     {
803       Variable vari = domain.GetVar (args[0]);
804       int n = (int) vari.val;
805
806       for (int i = 1; i < args.Length; i++)
807         n *= (int) args[i].val;
808       vari.val = n;
809       return n;
810     }
811
812     private static object sub_set (Xex[] args, Domain domain)
813     {
814       Variable vari = domain.GetVar (args[0]);
815       int n = (int) vari.val;
816
817       for (int i = 1; i < args.Length; i++)
818         n -= (int) args[i].val;
819       vari.val = n;
820       return n;
821     }
822
823     private static object div_set (Xex[] args, Domain domain)
824     {
825       Variable vari = domain.GetVar (args[0]);
826       int n = (int) vari.val;
827
828       for (int i = 1; i < args.Length; i++)
829         n /= (int) args[i].val;
830       vari.val = n;
831       return n;
832     }
833
834     private static object mod_set (Xex[] args, Domain domain)
835     {
836       Variable vari = domain.GetVar (args[0]);
837       int n = (int) vari.val;
838
839       for (int i = 1; i < args.Length; i++)
840         n %= (int) args[i].val;
841       vari.val = n;
842       return n;
843     }
844
845     private static object logior_set (Xex[] args, Domain domain)
846     {
847       Variable vari = domain.GetVar (args[0]);
848       int n = (int) vari.val;
849
850       for (int i = 1; i < args.Length; i++)
851         n |= (int) args[i].val;
852       vari.val = n;
853       return n;
854     }
855
856     private static object logand_set (Xex[] args, Domain domain)
857     {
858       Variable vari = domain.GetVar (args[0]);
859       int n = (int) vari.val;
860
861       for (int i = 1; i < args.Length; i++)
862         n &= (int) args[i].val;
863       vari.val = n;
864       return n;
865     }
866
867     private static object lsh (Xex[] args, Domain domain)
868     {
869       return (int) args[0].val << (int) args[1].val;
870     }
871
872     private static object lsh_set (Xex[] args, Domain domain)
873     {
874       Variable vari = domain.GetVar (args[0]);
875       int n = (int) vari.val;
876
877       n <<= (int) args[1].val;
878       vari.val = n;
879       return n;
880     }
881
882     private static object rsh (Xex[] args, Domain domain)
883     {
884       return (int) args[0].val >> (int) args[1].val;
885     }
886
887     private static object rsh_set (Xex[] args, Domain domain)
888     {
889       Variable vari = domain.GetVar (args[0]);
890       int n = (int) vari.val;
891
892       n >>= (int) args[1].val;
893       vari.val = n;
894       return n;
895     }
896
897     private static object eq (Xex[] args, Domain domain)
898     {
899       int n = (int) args[0].val;
900
901       for (int i = 1; i < args.Length; i++)
902         if (n != (int) args[i].val)
903           return false;
904       return true;
905     }
906
907     private static object noteq (Xex[] args, Domain domain)
908     {
909       return ((int) args[0].val != (int) args[1].val);
910     }
911
912     private static object less_than (Xex[] args, Domain domain)
913     {
914       int n = (int) args[0].val;
915
916       for (int i = 1; i < args.Length; i++)
917         {
918           int n1 = (int) args[i].val;
919           if (n >= n1)
920             return false;
921           n = n1;
922         }
923       return true;
924     }
925
926     private static object less_eq (Xex[] args, Domain domain)
927     {
928       int n = (int) args[0].val;
929       for (int i = 1; i < args.Length; i++)
930         {
931           int n1 = (int) args[i].val;
932           if (n > n1)
933             return false;
934           n = n1;
935         }
936       return true;
937     }
938
939     private static object greater_than (Xex[] args, Domain domain)
940     {
941       int n = (int) args[0].val;
942       for (int i = 1; i < args.Length; i++)
943         {
944           int n1 = (int) args[i].val;
945           if (n <= n1)
946             return false;
947           n = n1;
948         }
949       return true;
950     }
951
952     private static object greater_eq (Xex[] args, Domain domain)
953     {
954       int n = (int) args[0].val;
955       for (int i = 1; i < args.Length; i++)
956         {
957           int n1 = (int) args[i].val;
958           if (n < n1)
959             return false;
960           n = n1;
961         }
962       return true;
963     }
964
965     private static object eval_clause (Xex[] args, Domain domain)
966     {
967       return args[0].Eval (domain);
968     }
969
970     private static object progn_clause (Xex[] args, Domain domain)
971     {
972       object result = true;
973
974       foreach (Xex e in args)
975         result = e.Eval (domain);
976       return result;
977     }
978
979     private static object if_clause (Xex[] args, Domain domain)
980     {
981       object result;
982
983       if (is_true (args[0].Eval (domain)))
984         result = args[1].Eval (domain);
985       else
986         {
987           result = false;
988           for (int i = 2; i < args.Length; i++)
989             result = args[i].Eval (domain);
990         }
991       return result;
992     }
993
994     private static object when_clause (Xex[] args, Domain domain)
995     {
996       if (! is_true (args[0].Eval (domain)))
997         return false;
998
999       object result = true;
1000       for (int i = 1; i < args.Length; i++)
1001         result = args[i].Eval (domain);
1002       return result;
1003     }
1004
1005     private static object while_clause (Xex[] args, Domain domain)
1006     {
1007       while (is_true (args[0].Eval (domain)))
1008         for (int i = 1; i < args.Length; i++)
1009           args[i].Eval (domain);
1010       return false;
1011     }
1012
1013     // FUNCALL: function != null
1014     // VARREF:  function == null, args[0] = DIRECT-SYMBOL
1015     // DIRECT:  function == null, args == null
1016
1017     private Function function;
1018     private Xex[] args;
1019     private object val;
1020
1021     public Xex[] Args { get { return args; } }
1022     public object Val { get { return val; } }
1023
1024     private Xex () { }
1025
1026     private Xex (object val)
1027     {
1028       this.val = val;
1029     }
1030
1031     internal static int parse_integer (string str)
1032     {
1033       int len = str.Length;
1034       bool negative = false;
1035
1036       if (len <= 1)
1037         return (len == 0 ? 0 : str[0] - '0');
1038
1039       int c = str[0];
1040       int i;
1041
1042       if (c == '0' && str[1] == 'x')
1043         {
1044           i = 0;
1045           for (int idx = 2; idx < len; idx++)
1046             {
1047               c = str[idx];
1048               if (c < '0')
1049                 break;
1050               else if (c <= '9')
1051                 i = i * 16 + (c - '0');
1052               else if (c < 'A')
1053                 break;
1054               else if (c <= 'F')
1055                 i = i * 16 + (c - 'A');
1056               else if (c < 'a')
1057                 break;
1058               else if (c <= 'f')
1059                 i = i * 16 + (c - 'a');
1060               else
1061                 break;
1062             }
1063           return i;
1064         }
1065       if (c == '-')
1066         negative = true;
1067       i = c - '0';
1068       for (int idx = 1; idx < len; idx++)
1069         {
1070           c = str[idx];
1071           if (c < '0' || c > '9')
1072             break;
1073           i = i * 10 + (c - '0');
1074         }
1075       return negative ? - i : i;
1076     }
1077
1078     private int pre_parse (XmlNodeList nlist, Domain domain)
1079     {
1080       int len = 0;
1081       foreach (XmlNode node in nlist)
1082         {
1083           if (node.Name == Ndefun)
1084             domain.RegisterFunction (node);
1085           else if (node.Name == Ndefvar)
1086             domain.Defvar ((Name) node.Attributes[0].Value, node.FirstChild);
1087           else
1088             len++;
1089         }
1090       return len;
1091     }
1092
1093     private void post_parse (XmlNodeList nlist, Domain domain)
1094     {
1095       for (int i = 0, j = 0; i < nlist.Count; i++)
1096         {
1097           XmlNode node = nlist[i];
1098
1099           if (node.Name == Ndefun)
1100             domain.Defun (node);
1101           else if (node.Name != Ndefvar)
1102             args[j++] = new Xex (node, domain);
1103         }
1104     }
1105
1106     private void Setup (XmlNode node, Domain domain)
1107     {
1108       Name name = node.Name;
1109
1110       if (name == Nconst)
1111         {
1112           Name type = node.Attributes[Ntype].Value;
1113
1114           if (type == Ninteger)
1115             val = parse_integer (node.InnerText);
1116           else if (type == Nstring)
1117             val = node.InnerText;
1118           else if (type == Nsymbol)
1119             val = (Name) node.InnerText;
1120           else if (type == Nboolean)
1121             val = node.InnerText == "true";
1122           else if (type == Nlist)
1123             {
1124               List<Xex> list = new List<Xex> ();
1125               for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
1126                 list.Add (new Xex (n, domain));
1127               val = list;
1128             }
1129           else
1130             throw new Exception ("Unknown type: " + type);
1131         }
1132       else if (name == Nvariable)
1133         {
1134           args = new Xex[1];
1135           args[0] = new Xex ((Name) node.Attributes[0].Value);
1136         }
1137       else
1138         {
1139           if (name == Nfuncall)
1140             name = node.Attributes[0].Value;
1141           function = domain.GetFunc (name);
1142
1143           XmlNodeList nlist = node.ChildNodes;
1144           int nargs = nlist.Count;
1145
1146           if (nargs < function.min_arg
1147               || (function.max_arg >= 0 && nargs > function.max_arg))
1148             throw new Exception ("Invalid number of arguments to: "
1149                                  + name + " " + nargs);
1150           nargs =  pre_parse (nlist, domain);
1151           args = new Xex[nargs];
1152           post_parse (nlist, domain);
1153         }
1154     }
1155
1156     public Xex (string url, Domain domain)
1157     {
1158       XmlDocument doc = new XmlDocument (Name.Table);
1159       XmlNode node;
1160
1161       using (XmlTextReader reader = new XmlTextReader (url, Name.Table))
1162         {
1163           do {
1164             reader.Read ();
1165           } while (reader.NodeType != XmlNodeType.None
1166                    && (reader.NodeType != XmlNodeType.Element
1167                        || Nexpr != reader.Name));
1168           if (reader.NodeType == XmlNodeType.None)
1169             throw new Exception ("Node <expr> not found");
1170           node = doc.ReadNode (reader);
1171         }
1172
1173       Setup (node, domain);
1174     }
1175
1176     // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | PROGN
1177     // FUNCALL = '(' SYMBOL EXPR* ')'
1178     // PROGN = '(' EXPR * ')'
1179     public Xex (XmlNode node, Domain domain)
1180     {
1181       Setup (node, domain);
1182     }
1183
1184     public object Eval (Domain domain)
1185     {
1186       if (function == null)
1187         {
1188           if (args != null)
1189             {
1190               Variable vari = domain.GetVar ((Name) args[0].val);
1191               val = vari.val;
1192             }
1193           return val;
1194         }
1195       else
1196         val = function.Call (args, domain);
1197       return val;
1198     }
1199
1200     public override string ToString ()
1201     {
1202       string str;
1203
1204       if (function != null)
1205         {
1206           str = "(" + function.name;
1207           if (args != null)
1208             foreach (Xex e in args)
1209               str += " " + e.ToString ();
1210           str += ")";
1211         }
1212       else if (args != null)
1213         {
1214           str = (Name) args[0].val;
1215         }
1216       else if (val != null)
1217         {
1218           if (val is string)
1219             str = "\"" + ((string) val) + "\"";
1220           else
1221             str = val.ToString ();
1222         }
1223       else
1224         str = "()";
1225       return str;
1226     }
1227   }
1228 }