*** 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 XmlName : IEquatable<XmlName>
10   {
11     private static NameTable nt = new NameTable ();
12
13     private object name;
14
15     private XmlName (string str)
16       {
17         name = nt.Add (str);
18       }
19
20     public static implicit operator XmlName (string str)
21     {
22       return new XmlName (str);
23     }
24
25     public static bool operator== (object obj, XmlName nam)
26       {
27         return obj == nam.name;
28       }
29
30     public static bool operator!= (object obj, XmlName nam)
31       {
32         return obj != nam.name;
33       }
34
35     public bool Equals (XmlName other) { return name == other.name; }
36     public override bool Equals (object obj) { return obj == name; }
37     public override int GetHashCode ()
38     {
39       return ((string) name).GetHashCode ();
40     }
41
42     public static NameTable Table { get { return nt; } }
43   }
44
45   public class Xex
46   {
47     private static NameTable nt = new NameTable ();
48
49     public static object Name (string str)
50     {
51       return nt.Add (str);
52     }
53
54     public static NameTable Table { get { return nt; } }
55
56     private static object Nvar = Name ("var");
57     private static object Ndefun = Name ("defun");
58     private static object Ncond = Name ("cond");
59     private static object Nprogn = Name ("progn");
60     private static object Nwhen = Name ("when");
61
62     public class Domain
63     {
64       private Domain parent;
65       internal Dictionary<object,functions = new MPlist ();
66       internal MPlist bindings = new MPlist ();
67       private Stack<MPlist> boundaries = new Stack<MPlist> ();
68       internal Translator translator;
69       public object context;
70
71       internal Domain ()
72       {
73         boundaries.Push (bindings);
74       }
75
76       public Domain (object context) : this (basic, context) { }
77
78       public Domain (Domain parent, object context)
79       {
80         this.parent = parent;
81         this.context = context;
82         boundaries.Push (bindings);
83       }
84
85       public void AddTranslator (Translator translator)
86       {
87         if (this.translator == null)
88           this.translator = translator;
89         else
90           this.translator += translator;
91       }
92
93       public void Bind (MSymbol sym, object value)
94       {
95         bindings = bindings.Cons (sym, value);
96       }
97
98       public MPlist SetBoundary ()
99       {
100         boundaries.Push (bindings);
101         return bindings;
102       }
103
104       public void UnboundTo (MPlist boundary)
105       {
106         while (boundary != boundaries.Pop ());
107         while (bindings != boundary)
108           bindings = bindings.next;
109       }
110
111       public void Defun (string name, Builtin builtin, int min_arg, int max_arg)
112       {
113         Defun (name, builtin, min_arg, max_arg, false);
114       }
115
116       public void Defun (string name, Builtin builtin, int min_arg, int max_arg,
117                          bool specialp)
118       {
119         MSymbol sym = name;
120         Function func = (Function) functions.Get (sym);
121
122         if (func != null)
123           {
124             if (func.min_arg < min_arg || func.max_arg > max_arg)
125               throw new Exception ("Incompatible argument numbers to override: "
126                                    + name);
127             func.builtin = builtin;
128             func.lambda = null;
129             func.min_arg = min_arg;
130             func.max_arg = max_arg;
131             func.specialp = specialp;
132           }
133         else
134           {
135             func = new Function (sym, builtin, min_arg, max_arg, specialp);
136             functions = functions.Cons (sym, func);
137           }
138       }
139
140       public void Defun (MSymbol sym, MPlist args, MPlist body)
141       {
142         Function func = (Function) functions.Get (sym);
143
144         if (func != null)
145           {
146             int nargs = args == null ? 0 : args.Count;
147
148             if (func.min_arg < nargs || func.max_arg > nargs)
149               throw new Exception ("Incompatible argument numbers to override: "
150                                    + sym);
151             func.lambda.SetArgs (args);
152             func.lambda.SetBody (body, this);
153             func.builtin = null;
154           }
155         else
156           {
157             func = new Function (sym, args, body, this);
158             functions = functions.Cons (sym, func);
159           }         
160       }
161
162       public void Defun (XmlNode node)
163       {
164         MSymbol sym = node.Attributes["id"].Value;
165         Function func = (Function) functions.Get (sym);
166
167         if (func != null)
168           {
169             XmlNode args = node.FirstChild;
170             int nargs = args.Name == "args" ? args.ChildNodes.Count : 0;
171
172             if (func.min_arg < nargs || func.max_arg > nargs)
173               throw new Exception ("Incompatible argument numbers to override: "
174                                    + sym);
175             func.lambda.Set (node, this);
176             func.builtin = null;
177           }
178         else
179           {
180             func = new Function (sym, node, this);
181             functions = functions.Cons (sym, func);
182           }         
183       }
184
185       internal Function GetFunc (MSymbol name)
186       {
187         Function func = (Function) functions.Get (name);
188
189         if (func == null)
190           {
191             if (parent != null)
192               return parent.GetFunc (name);
193             throw new Exception ("Unknown function: " + name);
194           }
195         return func;
196       }
197
198       public bool CopyFunc (Domain domain, MSymbol name)
199       {
200         Function func = (Function) functions.Get (name);
201         if (func == null)
202           return false;
203         domain.functions = domain.functions.Cons (name, func);
204         return true;
205       }
206
207       public void CopyFunc (Domain domain)
208       {
209         foreach (MPlist p in functions)
210           domain.functions = domain.functions.Cons (p.key, p.val);
211       }
212
213       public object GetValue (MSymbol name)
214       {
215         MPlist slot = bindings.Find (name);
216
217         if (slot == null)
218           {
219             if (parent != null)
220               return parent.GetValue (name);
221             throw new Exception ("Unbound variable: " + name);
222           }
223         return slot.val;
224       }
225
226       public object SetValue (MSymbol name, object val)
227       {
228         MPlist boundary = boundaries.Peek ();
229
230         for (MPlist plist = bindings; plist != boundary; plist = plist.next)
231           if (plist.key == name)
232             {
233               plist.val = val;
234               return val;
235             }
236         bindings = bindings.Cons (name, val);
237         return val;
238       }
239
240       public bool IsBound (MSymbol name)
241       {
242         return (bindings.Find (name) != null);
243       }
244
245       public void Translate (MPlist plist)
246       {
247         if (parent != null)
248           parent.Translate (plist);
249         if (translator != null)
250           for (MPlist p = plist; ! p.IsEmpty; p = p.next)
251             translator (p, this);
252       }
253
254       public override string ToString ()
255       {
256         string str = "<(functions";
257         foreach (MPlist p in functions)
258           str += " " + p.key;
259         str += ") (bindings " + bindings + ")";
260         if (context != null)
261           str += " (" + context + ")";
262         str += ">";
263         return str;
264       }
265     }
266
267     public delegate object Builtin (MExpression[] args, Domain domain);
268     public delegate void Translator (MPlist plist, Domain domain);
269
270     internal class Function
271     {
272       internal class Lambda
273       {
274         internal MSymbol[] args;
275         internal MExpression[] body;
276
277         public Lambda (MPlist args, MPlist body, Domain domain)
278         {
279           SetArgs (args);
280           SetBody (body, domain);
281         }
282
283         public Lambda (XmlNode node, Domain domain)
284         {
285           Set (node, domain);
286         }
287
288         public void SetArgs (MPlist args)
289         {
290           int len = args == null ? 0 : args.Count;
291
292           if (this.args == null)
293             this.args = new MSymbol[len];
294           for (int i = 0; i < len; i++, args = args.next)
295             this.args[i] = args.Symbol;
296         }
297
298         public void SetBody (MPlist body, Domain domain)
299         {
300           int len = body == null ? 0 : body.Count;
301           if (this.body == null)
302             this.body = new MExpression[len];
303           for (int i = 0; i < len; i++, body = body.next)
304             {
305               domain.Translate (body);
306               this.body[i] = new MExpression (body.key, body.val, domain);
307             }
308         }
309
310         public void Set (XmlNode node, Domain domain)
311         {
312           XmlNodeList body = node.ChildNodes;
313           int idx = 0;
314
315           if (body[0].Name == "args")
316             {
317               XmlNodeList args = body[0].ChildNodes;
318               if (this.args == null)
319                 this.args = new MSymbol[args.Count];
320               for (int i = 0; i < args.Count; i++)
321                 this.args[i] = args[i].InnerText;
322               idx++;
323             }
324           else if (this.args == null)
325             this.args = new MSymbol[0];
326           if (this.body == null)
327             this.body = new MExpression[body.Count - idx];
328           for (int i = 0; idx < body.Count; i++, idx++)
329             this.body[i] = new MExpression (body[idx], domain);
330         }
331       }
332
333       public readonly MSymbol Name;
334       public Builtin builtin;
335       public int min_arg, max_arg;
336       internal Lambda lambda;
337       public bool specialp = false;
338
339       internal static Function ignore, varref, block;
340
341       public Function (MSymbol name, Builtin builtin,
342                        int min_arg, int max_arg, bool specialp)
343       {
344         Name = name;
345         this.builtin = builtin;
346         this.min_arg = min_arg;
347         this.max_arg = max_arg;
348         this.specialp = specialp;
349       }
350
351       internal Function (MSymbol name, MPlist args, MPlist body,
352                          Domain domain)
353       {
354         Name = name;
355         lambda = new Lambda (args, body, domain);
356         this.min_arg = this.max_arg = lambda.args.Length;
357       }
358
359       internal Function (MSymbol name, XmlNode node, Domain domain)
360       {
361         Name = name;
362         lambda = new Lambda (node, domain);
363         this.min_arg = this.max_arg = lambda.args.Length;
364       }
365
366       private Function ()
367       {
368         Name = MSymbol.nil;
369       }
370
371       static Function ()
372       {
373         ignore = new Function ();
374         varref = new Function (Mvarref, get_value, 1, 1, true);
375         block = new Function (Mprogn, progn, 0, -1, true);
376       }
377
378       private static object get_value (MExpression[] args, Domain domain)
379       {
380         return domain.GetValue ((MSymbol) args[0].val);
381       }
382
383       public object Call (MExpression[] args, Domain domain)
384       {
385         if (builtin != null)
386           {
387             if (! specialp)
388               foreach (MExpression e in args)
389                 e.Eval (domain);
390             return builtin (args, domain);
391           }
392         if (lambda == null)
393           return null;
394         MPlist orig_bindings = domain.bindings;
395         object result = false;
396         try {
397           int i = 0;
398           foreach (MSymbol arg in lambda.args)
399             domain.Bind (arg, args[i++].Eval (domain));
400           foreach (MExpression e in lambda.body)
401             result = e.Eval (domain);
402         } finally {
403           domain.bindings = orig_bindings;
404         }
405         return result;
406       }
407     }
408
409     private static Domain basic;
410
411     static MExpression ()
412     {
413       basic = new Domain ();
414
415       basic.Defun ("set", set_value, 2, 2, true);
416       basic.Defun ("=", set_value, 2, 2, true);
417       basic.Defun ("!", not, 1, 1, false);
418       basic.Defun ("+", plus, 2, -1, false);
419       basic.Defun ("*", multi, 2, -1, false);
420       basic.Defun ("-", minus, 1, -1, false);
421       basic.Defun ("/", divide, 2, -1, false);
422       basic.Defun ("%", percent, 2, -1, false);
423       basic.Defun ("|", logior, 2, -1, false);
424       basic.Defun ("&", logand, 2, -1, false);
425       basic.Defun ("+=", pluseq, 2, -1, true);
426       basic.Defun ("*=", multieq, 2, -1, true);
427       basic.Defun ("-=", minuseq, 2, -1, true);
428       basic.Defun ("/=", divideeq, 2, -1, true);
429       basic.Defun ("%=", percenteq, 2, -1, true);
430       basic.Defun ("|=", logioreq, 2, -1, true);
431       basic.Defun ("&=", logandeq, 2, -1, true);
432       basic.Defun ("<<", lshift, 2, 2, false);
433       basic.Defun (">>", rshift, 2, 2, false);
434       basic.Defun ("<<=", lshifteq, 2, 2, true);
435       basic.Defun (">>=", rshifteq, 2, 2, true);
436       basic.Defun ("==", eq, 2, -1, false);
437       basic.Defun ("!=", noteq, 2, 2, false);
438       basic.Defun ("<", less, 2, -1, false);
439       basic.Defun ("<=", lesseq, 2, -1, false);
440       basic.Defun (">", more, 2, -1, false);
441       basic.Defun (">=", moreeq, 2, -1, false);
442       basic.Defun ("progn", progn, 0, -1, true);
443       basic.Defun ("if", ifclause, 2, -1, true);
444       basic.Defun ("when", whenclause, 1, -1, true);
445       basic.Defun ("while", whileclause, 1, -1, true);
446
447       basic.AddTranslator (new Translator (translate_cond));
448     }
449
450     private static object set_value (MExpression[] args, Domain domain)
451     {
452       return domain.SetValue ((MSymbol) args[0].args[0].val,
453                               args[1].Eval (domain));
454     }
455
456     private static object not (MExpression[] args, Domain domain)
457     {
458       if (args[0].val is int)
459         return (int) args[0].val == 0;
460       if (args[0].val is bool)
461         return ! ((bool) args[0].val);
462       return true;
463     }
464
465     private static object plus (MExpression[] args, Domain domain)
466     {
467       if (args[0].val is int)
468         {
469           int n = 0;
470           foreach (MExpression e in args)
471             n += (int) e.val;
472           return n;
473         }
474       else if (args[0].val is MText)
475         {
476           MText mt = new MText ();
477           foreach (MExpression e in args)
478             mt += (MText) e.val;
479           return mt;
480         }
481       throw new Exception ("Not an integer nor MText: " + args[0].val);
482     }
483
484       private static object multi (MExpression[] args, Domain domain)
485       {
486         int n = 1;
487         foreach (MExpression e in args)
488           n *= (int) e.val;
489         return n;
490       }
491
492       private static object minus (MExpression[] args, Domain domain)
493       {
494         int n = (int) args[0].val;
495         if (args.Length == 1)
496           return - n;
497         for (int i = 1; i < args.Length; i++)
498           n -= (int) args[i].val;
499         return n;
500       }
501
502       private static object divide (MExpression[] args, Domain domain)
503       {
504         int n = (int) args[0].val;
505         for (int i = 1; i < args.Length; i++)
506           n /= (int) args[i].val;
507         return n;
508       }
509
510       private static object percent (MExpression[] args, Domain domain)
511       {
512         int n = (int) args[0].val;
513         for (int i = 1; i < args.Length; i++)
514           n %= (int) args[i].val;
515         return n;
516       }
517
518       private static object logior (MExpression[] args, Domain domain)
519       {
520         int n = 0;
521         foreach (MExpression e in args)
522           n |= (int) e.val;
523         return n;
524       }
525
526       private static object logand (MExpression[] args, Domain domain)
527       {
528         int n = 0;
529         foreach (MExpression e in args)
530           n &= (int) e.val;
531         return n;
532       }
533
534       private static object pluseq (MExpression[] args, Domain domain)
535       {
536         MSymbol sym = (MSymbol) args[0].args[0].val;
537         object val = domain.GetValue (sym);
538
539         if (val is int)
540           {
541             int n = (int) val;
542             for (int i = 1; i < args.Length; i++)
543               n += (int) args[i].Eval (domain);
544             val = n;
545           }
546         else if (val is MText)
547           {
548             MText mt = (MText) val;
549             for (int i = 1; i < args.Length; i++)
550               mt.Cat ((MText) args[i].Eval (domain));
551             val = mt;
552           }
553         domain.SetValue (sym, val);
554         return val;
555       }
556
557       private static object multieq (MExpression[] args, Domain domain)
558       {
559         MSymbol sym = (MSymbol) args[0].args[0].val;
560         int n = (int) domain.GetValue (sym);
561
562         for (int i = 1; i < args.Length; i++)
563           n *= (int) args[i].Eval (domain);
564         return domain.SetValue (sym, (object) n);
565       }
566
567       private static object minuseq (MExpression[] args, Domain domain)
568       {
569         MSymbol sym = (MSymbol) args[0].args[0].val;
570         int n = (int) domain.GetValue (sym);
571
572         for (int i = 1; i < args.Length; i++)
573           n -= (int) args[i].Eval (domain);
574         return domain.SetValue (sym, (object) n);
575       }
576
577       private static object divideeq (MExpression[] args, Domain domain)
578       {
579         MSymbol sym = (MSymbol) args[0].args[0].val;
580         int n = (int) domain.GetValue (sym);
581
582         for (int i = 1; i < args.Length; i++)
583           n /= (int) args[i].Eval (domain);
584         return domain.SetValue (sym, (object) n);
585       }
586
587       private static object percenteq (MExpression[] args, Domain domain)
588       {
589         MSymbol sym = (MSymbol) args[0].args[0].val;
590         int n = (int) domain.GetValue (sym);
591
592         for (int i = 1; i < args.Length; i++)
593           n %= (int) args[i].Eval (domain);
594         return domain.SetValue (sym, (object) n);
595       }
596
597       private static object logioreq (MExpression[] args, Domain domain)
598       {
599         MSymbol sym = (MSymbol) args[0].args[0].val;
600         int n = (int) domain.GetValue (sym);
601
602         for (int i = 1; i < args.Length; i++)
603           n |= (int) args[i].Eval (domain);
604         return domain.SetValue (sym, (object) n);
605       }
606
607       private static object logandeq (MExpression[] args, Domain domain)
608       {
609         MSymbol sym = (MSymbol) args[0].args[0].val;
610         int n = (int) domain.GetValue (sym);
611
612         for (int i = 1; i < args.Length; i++)
613           n &= (int) args[i].Eval (domain);
614         return domain.SetValue (sym, (object) n);
615       }
616
617       private static object lshift (MExpression[] args, Domain domain)
618       {
619         return (int) args[0].val << (int) args[1].val;
620       }
621
622       private static object lshifteq (MExpression[] args, Domain domain)
623       {
624         MSymbol sym = (MSymbol) args[0].args[0].val;
625         int n = (int) domain.GetValue (sym);
626
627         n <<= (int) args[1].Eval (domain);
628         return domain.SetValue (sym, (object) n);
629       }
630
631       private static object rshift (MExpression[] args, Domain domain)
632       {
633         return (int) args[0].val >> (int) args[1].val;
634       }
635
636       private static object rshifteq (MExpression[] args, Domain domain)
637       {
638         MSymbol sym = (MSymbol) args[0].args[0].val;
639         int n = (int) domain.GetValue (sym);
640
641         n >>= (int) args[1].Eval (domain);
642         return domain.SetValue (sym, (object) n);
643       }
644
645       private static object eq (MExpression[] args, Domain domain)
646       {
647         int n = (int) args[0].val;
648
649         for (int i = 1; i < args.Length; i++)
650           if (n != (int) args[i].val)
651             return false;
652         return true;
653       }
654
655       private static object noteq (MExpression[] args, Domain domain)
656       {
657         return ((int) args[0].val != (int) args[1].val);
658       }
659
660       private static object less (MExpression[] args, Domain domain)
661       {
662         int n = (int) args[0].val;
663
664         for (int i = 1; i < args.Length; i++)
665           {
666             int n1 = (int) args[i].val;
667             if (n >= n1)
668               return false;
669             n = n1;
670           }
671         return true;
672       }
673
674       private static object lesseq (MExpression[] args, Domain domain)
675       {
676         int n = (int) args[0].val;
677         for (int i = 1; i < args.Length; i++)
678           {
679             int n1 = (int) args[i].val;
680             if (n > n1)
681               return false;
682             n = n1;
683           }
684         return true;
685       }
686
687       private static object more (MExpression[] args, Domain domain)
688       {
689         int n = (int) args[0].val;
690         for (int i = 1; i < args.Length; i++)
691           {
692             int n1 = (int) args[i].val;
693             if (n <= n1)
694               return false;
695             n = n1;
696           }
697         return true;
698       }
699
700       private static object moreeq (MExpression[] args, Domain domain)
701       {
702         int n = (int) args[0].val;
703         for (int i = 1; i < args.Length; i++)
704           {
705             int n1 = (int) args[i].val;
706             if (n < n1)
707               return false;
708             n = n1;
709           }
710         return true;
711       }
712
713       private static object progn (MExpression[] args, Domain domain)
714       {
715         object result = false;
716
717         foreach (MExpression e in args)
718           result = e.Eval (domain);
719         return result;
720       }
721
722       private static bool check_condition (MExpression condition, Domain domain)
723       {
724         object result = condition.Eval (domain);
725         return (result is bool ? (bool) result
726                 : result is int ? ((int) result) != 0
727                 : true);
728       }
729
730       private static object ifclause (MExpression[] args, Domain domain)
731       {
732         object result = false;
733
734         if (check_condition (args[0], domain))
735           result = args[1].Eval (domain);
736         else
737           for (int i = 2; i < args.Length; i++)
738             result = args[i].Eval (domain);
739         return result;
740       }
741
742       private static object whenclause (MExpression[] args, Domain domain)
743       {
744         object result = false;
745
746         if (check_condition (args[0], domain))
747           for (int i = 1; i < args.Length; i++)
748             result = args[i].Eval (domain);
749         return result;
750       }
751
752       private static object whileclause (MExpression[] args, Domain domain)
753       {
754         while (check_condition (args[0], domain))
755           for (int i = 1; i < args.Length; i++)
756             args[i].Eval (domain);
757         return false;
758       }
759
760     // (cond (COND1 ...) (COND2 ...) ...)
761     //   => (cond (when COND1 ...) (when COND2 ...) ...)
762     private static void translate_cond (MPlist plist, Domain domain)
763     {
764       if (plist.IsPlist)
765         {
766           plist = plist.Plist;
767           if (plist.IsSymbol && plist.Symbol == Mcond)
768             {
769               plist.val = Mprogn;
770               for (plist = plist.next; ! plist.IsEmpty; plist = plist.next)
771                 {
772                   if (! plist.IsPlist)
773                     throw new Exception ("Invalid cond form: " + plist);
774                   plist.Plist.Push (MSymbol.symbol, Mwhen);
775                 }               
776             }
777         }
778     }
779
780     private Function function;
781     private MExpression[] args;
782     private object val;
783
784     public MExpression[] Args { get { return args; } }
785     public object Val { get { return val; } }
786
787     private MExpression (object val)
788     {
789       this.val = val;
790     }
791
792     // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | PROGN
793     // FUNCALL = '(' SYMBOL EXPR* ')'
794     // PROGN = '(' EXPR * ')'
795     private MExpression (MSymbol key, object val, Domain domain)
796     {
797       if (key == MSymbol.symbol)
798         {
799           function = Function.varref;
800           args = new MExpression[1];
801           args[0] = new MExpression (val);
802         }
803       else if (key == MSymbol.integer
804                || key == MSymbol.mtext)
805         {
806           this.val = val;
807         }
808       else if (key == MSymbol.plist)
809         {
810           MPlist p = (MPlist) val;
811
812           if (p.IsSymbol)
813             {
814               MSymbol sym = p.Symbol;
815
816               if (sym == Mdefun)
817                 {
818                   p = p.next;
819                   if (! p.IsSymbol)
820                     throw new Exception ("Invalid function argument: "
821                                          + p.val);
822                   sym = p.Symbol;
823                   p = p.next;
824                   if (! p.IsPlist)
825                     throw new Exception ("Invalid function argument: "
826                                          + p.val);
827                   domain.Defun (sym, p.Plist, p.next);
828                   // This Mexpression is just a dummy.
829                 }
830               else
831                 {
832                   function = domain.GetFunc (sym);
833                   p = p.next;
834                   int nargs = p.Count;
835                   if (nargs < function.min_arg
836                       || (function.max_arg >= 0 && nargs > function.max_arg))
837                     throw new Exception ("Invalid number of arguments to: "
838                                          + sym + " " + nargs);
839                   args = new MExpression[nargs];
840                   for (int i = 0; i < nargs; i++, p = p.next)
841                     {
842                       domain.Translate (p);
843                       args[i] = new MExpression (p.key, p.val, domain);
844                     }
845                 }
846             }
847           else
848             {
849               args = new MExpression[1];
850               args[0] = new MExpression (p, domain);
851             }
852         }
853       else
854         throw new Exception ("Invalid expression: " + key + ":" + val);
855     }
856
857     public MExpression (MPlist plist, Domain domain)
858     {
859       function = Function.block;
860       args = new MExpression[plist.Count];
861       for (int i = 0; ! plist.IsEmpty; i++, plist = plist.next)
862         {
863           domain.Translate (plist);
864           args[i] = new MExpression (plist.key, plist.val, domain);
865         }
866     }
867
868     public MExpression (XmlNode node, Domain domain)
869     {
870       MSymbol sym = node.Name;
871
872       function = domain.GetFunc (sym);
873
874       XmlAttributeCollection attrs = node.Attributes;
875
876       int nargs = attrs.Count + node.ChildNodes.Count;
877       if (nargs < function.min_arg
878           || (function.max_arg >= 0 && nargs > function.max_arg))
879         throw new Exception ("Invalid number of arguments: " + node.InnerXml);
880       args = new MExpression[nargs];
881       int i;
882       for (i = 0; i < attrs.Count; i++)
883         {
884           string str = sttrs[i].Value;
885
886         }
887     }
888
889     public object Eval (Domain domain)
890     {
891       if (function == null)
892         {
893           if (val is MSymbol)
894             val = domain.GetValue ((MSymbol) val);
895         }
896       else
897         val = function.Call (args, domain);
898       return val;
899     }
900
901     public override string ToString ()
902     {
903       string str;
904
905       if (function != null)
906         {
907           str = "(" + function.Name.Name;
908           if (args != null)
909             foreach (MExpression e in args)
910               str += " " + e.ToString ();
911           str += ")";
912         }
913       else if (val != null)
914         {
915           if (val is MText)
916             str = "\"" + (string) ((MText) val) + "\"";
917           else
918             str = val.ToString ();
919         }
920       else
921         str = "()";
922       return str;
923     }
924   }
925 }