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