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