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