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