*** 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 M17N;
6 using M17N.Core;
7
8 namespace M17N.Core
9 {
10   public class MExpression
11   {
12     public delegate object Evaluator (object[] args, MPlist bindings);
13
14     internal delegate void PrettyPrinter (Function func,
15                                           string indent, object[] args);
16
17     internal class Function
18     {
19       internal readonly MSymbol name;
20       internal readonly Evaluator eval;
21       internal readonly int min_arg;
22       internal readonly int max_arg;
23       internal readonly Type[] arg_types;
24       internal object[] data;
25
26       public PrettyPrinter pp;
27
28       private static PrettyPrinter default_pretty_printer;
29       private static PrettyPrinter set_pretty_printer;
30       internal static Function literal, varref, block, defun;
31
32       public Function (MSymbol name, Evaluator eval,
33                        int min_arg, int max_arg, params Type[] arg_types)
34       {
35         this.name = name;
36         this.eval = eval;
37         this.min_arg = min_arg;
38         this.max_arg = max_arg;
39         this.arg_types = (Type []) arg_types.Clone ();
40         if (arg_types.Length == 2 && arg_types[0] == typeof (MSymbol))
41           pp = set_pretty_printer;
42         else
43           pp = default_pretty_printer;
44       }
45
46       static Function ()
47       {
48         default_pretty_printer = new PrettyPrinter (default_pp);
49         set_pretty_printer = new PrettyPrinter (set_pp);
50         literal = Defun ("nil", null, 1, 1);
51         varref = Defun ("symbol", new Evaluator (get_value), 1, 1);
52         block = Defun ("plist", new Evaluator (progn), 1, -1);
53
54         Defun ("set", new Evaluator (set_value), 2, 2,
55                typeof (MSymbol), typeof (MExpression));
56         Defun ("=", new Evaluator (set_value), 2, 2,
57                typeof (MSymbol), typeof (MExpression));
58         Defun ("+", new Evaluator (plus), 1, -1);
59         Defun ("*", new Evaluator (multi), 2, -1);
60         Defun ("-", new Evaluator (minus), 1, -1);
61         Defun ("/", new Evaluator (divide), 2, -1);
62         Defun ("%", new Evaluator (percent), 2, -1);
63         Defun ("|", new Evaluator (logior), 2, -1);
64         Defun ("&", new Evaluator (logand), 2, -1);
65         Defun ("+=", new Evaluator (pluseq), 2, -1,
66                typeof (MSymbol), typeof (MExpression));
67         Defun ("*=", new Evaluator (multieq), 2, -1,
68                typeof (MSymbol), typeof (MExpression));
69         Defun ("-=", new Evaluator (minuseq), 2, -1,
70                typeof (MSymbol), typeof (MExpression));
71         Defun ("/=", new Evaluator (divideeq), 2, -1,
72                typeof (MSymbol), typeof (MExpression));
73         Defun ("%=", new Evaluator (percenteq), 2, -1,
74                typeof (MSymbol), typeof (MExpression));
75         Defun ("|=", new Evaluator (logioreq), 2, -1,
76                typeof (MSymbol), typeof (MExpression));
77         Defun ("&=", new Evaluator (logandeq), 2, -1,
78                typeof (MSymbol), typeof (MExpression));
79         Defun ("<<", new Evaluator (lshift), 2, 2);
80         Defun (">>", new Evaluator (rshift), 2, 2);
81         Defun ("<<=", new Evaluator (lshifteq), 2, 2,
82                typeof (MSymbol), typeof (MExpression));
83         Defun (">>=", new Evaluator (rshifteq), 2, 2,
84                typeof (MSymbol), typeof (MExpression));
85         Defun ("==", new Evaluator (eq), 2, -1);
86         Defun ("!=", new Evaluator (noteq), 2, 2);
87         Defun ("<", new Evaluator (less), 2, -1);
88         Defun ("<=", new Evaluator (lesseq), 2, -1);
89         Defun (">", new Evaluator (more), 2, -1);
90         Defun (">=", new Evaluator (moreeq), 2, -1);
91         block = Defun ("progn", new Evaluator (progn), 1, -1);
92         block.pp = new PrettyPrinter (block_pp);
93         Defun ("cond", new Evaluator (cond), 1, -1,
94                typeof (MExpression[])).pp = new PrettyPrinter (cond_pp);
95         Defun ("if", new Evaluator (ifclause), 2, -1,
96                typeof (MExpression)).pp = new PrettyPrinter (if_pp);
97         Defun ("while", new Evaluator (whileclause), 1, -1,
98                typeof (MExpression)).pp = new PrettyPrinter (while_pp);
99         defun = Defun ("defun", new Evaluator (define_function), 4, -1,
100                        typeof (FunctionTable),
101                        typeof (MSymbol),
102                        typeof (MPlist),
103                        typeof (MExpression));
104         defun.pp = new PrettyPrinter (defun_pp);
105       }
106
107       private static MPlist find_binding (object[] args, MPlist bindings)
108       {
109         MSymbol var = (MSymbol) args[0];
110         MPlist slot = bindings.Find (var);
111
112         if (slot == null)
113           throw new Exception ("Unbound variable: " + var);
114         return slot;
115       }
116
117       public object Call (object[] args, MPlist bindings)
118       {
119         if (name == MSymbol.nil)
120           return args[0];
121         if (eval != null)
122           return eval (args, bindings);
123
124         MPlist arg_symbols = (MPlist) data[0];
125         for (int i = 0; i < args.Length; i++, arg_symbols = arg_symbols.next)
126           bindings = bindings.Cons (arg_symbols.Symbol,
127                                     ((MExpression) args[i]).Eval (bindings));
128         object result = 0;
129         for (int i = 1; i < data.Length; i++)
130           result = ((MExpression) data[i]).Eval (bindings);
131         return result;
132       }
133
134       // Commonly used pretty-printers.
135
136       public static void default_pp (Function func,
137                                      string indent, object[] args)
138       {
139         Console.Write ("(" + func.name);
140         indent += "  ";
141         foreach (MExpression o in args)
142           {
143             Console.Write (" ");
144             o.pp (indent);
145           }
146         Console.Write (")");
147       }
148
149       private static void set_pp (Function func, string indent, object[] args)
150       {
151         Console.Write ("(" + func.name + " " + (MSymbol) args[0] + " ");
152         ((MExpression) args[1]).pp (indent);
153         Console.Write (")");
154       }
155
156       private static object get_value (object[] args, MPlist bindings)
157       {
158         return find_binding (args, bindings).val;
159       }
160
161       private static object set_value (object[] args, MPlist bindings)
162       {
163         MSymbol var = (MSymbol) args[0];
164         MPlist slot = bindings.Find (var);
165
166         if (slot == null)
167           slot = bindings.Push (var, null);
168         slot.val = ((MExpression) args[1]).Eval (bindings);
169         if (slot.val is MText)
170           slot.val = ((MText) slot.val).Dup ();
171         return slot.val;
172       }
173
174       private static object plus (object[] args, MPlist bindings)
175       {
176         object val = ((MExpression) args[0]).Eval (bindings);
177
178         if (val is int)
179           {
180             int n = 0;
181             foreach (MExpression e in args)
182               n += (int) e.Eval (bindings);
183             val = n;
184           }
185         else if (val is MText)
186           {
187             MText mt = new MText ();
188             foreach (MExpression e in args)
189               mt += (MText) e.Eval (bindings);
190             val = mt;
191           }
192         return val;
193       }
194
195       private static object multi (object[] args, MPlist bindings)
196       {
197         int n = 1;
198         foreach (MExpression e in args)
199           n *= (int) e.Eval (bindings);
200         return n;
201       }
202
203       private static object minus (object[] args, MPlist bindings)
204       {
205         int n = (int) ((MExpression) args[0]).Eval (bindings);
206         if (args.Length == 1)
207           return - n;
208         for (int i = 1; i < args.Length; i++)
209           n -= (int) ((MExpression) args[i]).Eval (bindings);
210         return n;
211       }
212
213       private static object divide (object[] args, MPlist bindings)
214       {
215         int n = (int) ((MExpression) args[0]).Eval (bindings);
216         for (int i = 1; i < args.Length; i++)
217           n /= (int) ((MExpression) args[i]).Eval (bindings);
218         return n;
219       }
220
221       private static object percent (object[] args, MPlist bindings)
222       {
223         int n = (int) ((MExpression) args[0]).Eval (bindings);
224         for (int i = 1; i < args.Length; i++)
225           n %= (int) ((MExpression) args[i]).Eval (bindings);
226         return n;
227       }
228
229       private static object logior (object[] args, MPlist bindings)
230       {
231         int n = (int) ((MExpression) args[0]).Eval (bindings);
232         for (int i = 1; i < args.Length; i++)
233           n |= (int) ((MExpression) args[i]).Eval (bindings);
234         return n;
235       }
236
237       private static object logand (object[] args, MPlist bindings)
238       {
239         int n = (int) ((MExpression) args[0]).Eval (bindings);
240         for (int i = 1; i < args.Length; i++)
241           n &= (int) ((MExpression) args[i]).Eval (bindings);
242         return n;
243       }
244
245       private static object pluseq (object[] args, MPlist bindings)
246       {
247         MPlist slot = find_binding (args, bindings);
248         object val = slot.val;
249
250         if (val is int)
251           {
252             int n = (int) val;
253             for (int i = 1; i < args.Length; i++)
254               n += (int) ((MExpression) args[i]).Eval (bindings);
255             slot.val = n;
256           }
257         else if (val is MText)
258           {
259             MText mt = (MText) val;
260             for (int i = 1; i < args.Length; i++)
261               mt.Cat ((MText) ((MExpression) args[i]).Eval (bindings));
262           }
263         return slot.val;
264       }
265
266       private static object multieq (object[] args, MPlist bindings)
267       {
268         MPlist slot = find_binding (args, bindings);
269         int n = (int) slot.val;
270         for (int i = 1; i < args.Length; i++)
271           n *= (int) ((MExpression) args[i]).Eval (bindings);
272         return (slot.val = n);
273       }
274
275       private static object minuseq (object[] args, MPlist bindings)
276       {
277         MPlist slot = find_binding (args, bindings);
278         int n = (int) slot.val;
279         for (int i = 1; i < args.Length; i++)
280           n -= (int) ((MExpression) args[i]).Eval (bindings);
281         return (slot.val = n);
282       }
283
284       private static object divideeq (object[] args, MPlist bindings)
285       {
286         MPlist slot = find_binding (args, bindings);
287         int n = (int) slot.val;
288         for (int i = 1; i < args.Length; i++)
289           n /= (int) ((MExpression) args[i]).Eval (bindings);
290         return (slot.val = n);
291       }
292
293       private static object percenteq (object[] args, MPlist bindings)
294       {
295         MPlist slot = find_binding (args, bindings);
296         int n = (int) slot.val;
297         for (int i = 1; i < args.Length; i++)
298           n %= (int) ((MExpression) args[i]).Eval (bindings);
299         return (slot.val = n);
300       }
301
302       private static object logioreq (object[] args, MPlist bindings)
303       {
304         MPlist slot = find_binding (args, bindings);
305         int n = (int) slot.val;
306         for (int i = 1; i < args.Length; i++)
307           n |= (int) ((MExpression) args[i]).Eval (bindings);
308         return (slot.val = n);
309       }
310
311       private static object logandeq (object[] args, MPlist bindings)
312       {
313         MPlist slot = find_binding (args, bindings);
314         int n = (int) slot.val;
315         for (int i = 1; i < args.Length; i++)
316           n &= (int) ((MExpression) args[i]).Eval (bindings);
317         return (slot.val = n);
318       }
319
320       private static object lshift (object[] args, MPlist bindings)
321       {
322         int n1 = (int) ((MExpression) args[0]).Eval (bindings);
323         int n2 = (int) ((MExpression) args[1]).Eval (bindings);
324         return n1 << n2;
325       }
326
327       private static object lshifteq (object[] args, MPlist bindings)
328       {
329         MPlist slot = find_binding (args, bindings);
330         int n1 = (int) slot.val;
331         int n2 = (int) ((MExpression) args[1]).Eval (bindings);
332         return (slot.val = (n1 << n2));
333       }
334
335       private static object rshift (object[] args, MPlist bindings)
336       {
337         int n1 = (int) ((MExpression) args[0]).Eval (bindings);
338         int n2 = (int) ((MExpression) args[1]).Eval (bindings);
339         return n1 >> n2;
340       }
341
342       private static object rshifteq (object[] args, MPlist bindings)
343       {
344         MPlist slot = find_binding (args, bindings);
345         int n1 = (int) slot.val;
346         int n2 = (int) ((MExpression) args[1]).Eval (bindings);
347         return (slot.val = (n1 >> n2));
348       }
349
350       private static object eq (object[] args, MPlist bindings)
351       {
352         int n = (int) ((MExpression) args[0]).Eval (bindings);
353         for (int i = 1; i < args.Length; i++)
354           if (n != (int) ((MExpression) args[i]).Eval (bindings))
355             return 0;
356         return 1;
357       }
358
359       private static object noteq (object[] args, MPlist bindings)
360       {
361         int n1 = (int) ((MExpression) args[0]).Eval (bindings);
362         int n2 = (int) ((MExpression) args[1]).Eval (bindings);
363         return (n1 != n2);
364       }
365
366       private static object less (object[] args, MPlist bindings)
367       {
368         int n = (int) ((MExpression) args[0]).Eval (bindings);
369         for (int i = 1; i < args.Length; i++)
370           {
371             int n1 = (int) ((MExpression) args[i]).Eval (bindings);
372             if (n >= n1)
373               return 0;
374             n = n1;
375           }
376         return 1;
377       }
378
379       private static object lesseq (object[] args, MPlist bindings)
380       {
381         int n = (int) ((MExpression) args[0]).Eval (bindings);
382         for (int i = 1; i < args.Length; i++)
383           {
384             int n1 = (int) ((MExpression) args[i]).Eval (bindings);
385             if (n > n1)
386               return 0;
387             n = n1;
388           }
389         return 1;
390       }
391
392       private static object more (object[] args, MPlist bindings)
393       {
394         int n = (int) ((MExpression) args[0]).Eval (bindings);
395         for (int i = 1; i < args.Length; i++)
396           {
397             int n1 = (int) ((MExpression) args[i]).Eval (bindings);
398             if (n <= n1)
399               return 0;
400             n = n1;
401           }
402         return 1;
403       }
404
405       private static object moreeq (object[] args, MPlist bindings)
406       {
407         int n = (int) ((MExpression) args[0]).Eval (bindings);
408         for (int i = 1; i < args.Length; i++)
409           {
410             int n1 = (int) ((MExpression) args[i]).Eval (bindings);
411             if (n < n1)
412               return 0;
413             n = n1;
414           }
415         return 1;
416       }
417
418       private static object progn (object[] args, MPlist bindings)
419       {
420         object result = null;
421
422         foreach (MExpression e in args)
423           result = e.Eval (bindings);
424         return result;
425       }
426
427       private static void block_pp (Function func,
428                                     string indent, object[] args)
429       {
430         bool first = true;
431
432         Console.Write ("(");
433         indent += " ";
434         foreach (MExpression e in args)
435           {
436             if (first)
437               first = false;
438             else
439               Console.Write ("\n" + indent);
440             e.pp (indent);
441           }
442         Console.Write (")");
443       }
444
445       private static bool check_condition (MExpression e, MPlist bindings)
446       {
447         object result = e.Eval (bindings);
448         return (! (result is int) || (int) result != 0);
449       }
450
451       private static object cond (object[] args, MPlist bindings)
452       {
453         foreach (MExpression[] elist in args)
454           if (check_condition (elist[0], bindings))
455             {
456               object result = 0;
457               for (int i = 1; i < elist.Length; i++)
458                 result = elist[i].Eval (bindings);
459               return result;
460             }
461         return 0;
462       }
463
464       private static void cond_pp (Function func,
465                                    string indent, object[] args)
466       {
467         Console.Write ("(cond");
468         indent += "  ";
469         foreach (MExpression[] expr_list in args)
470           {
471             Console.Write ("\n" + indent + "(");
472             bool first = true;
473             foreach (MExpression e in expr_list)
474               {
475                 if (first)
476                   first = false;
477                 else
478                   Console.Write (" ");
479                 e.pp (indent);
480               }
481             Console.Write (")");
482           }
483         Console.Write (")");
484       }
485
486       private static object ifclause (object[] args, MPlist bindings)
487       {
488         object result = 0;
489
490         if (check_condition ((MExpression) args[0], bindings))
491           result = ((MExpression) args[1]).Eval (bindings);
492         else
493           for (int i = 2; i < args.Length; i++)
494             result = ((MExpression) args[i]).Eval (bindings);
495         return result;
496       }
497
498       private static void if_pp (Function func,
499                                  string indent, object[] args)
500       {
501         Console.Write ("(if ");
502         ((MExpression) args[0]).pp (indent + "    ");
503         Console.Write ("\n" + indent + "    ");
504         ((MExpression) args[1]).pp (indent + "    ");
505         indent += "  ";
506         for (int i = 2; i < args.Length; i++)
507           {
508             Console.Write ("\n" + indent);
509             ((MExpression) args[i]).pp (indent);
510           }
511         Console.Write (")");
512       }
513
514       private static object whileclause (object[] args, MPlist bindings)
515       {
516         object result = 0;
517
518         while (check_condition ((MExpression) args[0], bindings))
519           for (int i = 1; i < args.Length; i++)
520             result = ((MExpression) args[i]).Eval (bindings);
521         return result;
522       }
523
524       private static void while_pp (Function func,
525                                     string indent, object[] args)
526       {
527         Console.Write ("(while ");
528         ((MExpression) args[0]).pp (indent + "       ");
529         bool first = true;
530         indent += "  ";
531         for (int i = 1; i < args.Length; i++)
532           {
533             if (first)
534               {
535                 Console.Write ("\n" + indent);
536                 first = false;
537               }
538             else
539               Console.Write (" ");
540             ((MExpression) args[i]).pp (indent);
541           }
542         Console.Write (")");
543       }
544
545       private static object define_function (object[] args, MPlist bindings)
546       {
547         FunctionTable table = (FunctionTable) args[0];
548         MSymbol sym = (MSymbol) args[1];
549         MPlist arg_symbols = (MPlist) args[2];
550         int nargs = arg_symbols.Count;
551         object[] data = new object[args.Length - 2];
552
553         data[0] = args[2];
554         for (int i = 3; i < args.Length; i++)
555           data[i - 2] = args[i];
556
557         Function func = new Function (sym, null, nargs, nargs,
558                                       typeof (MExpression));
559         table.table[sym] = func;
560         func.data = data;
561         return null;
562       }
563
564       private static void defun_pp (Function func,
565                                     string indent, object[] args)
566       {
567         Console.Write ("(defun " + args[1] + " " + args[2]);
568         bool first = true;
569         indent += "  ";
570         for (int i = 3; i < args.Length; i++)
571           {
572             if (first)
573               {
574                 Console.Write ("\n" + indent);
575                 first = false;
576               }
577             else
578               Console.Write (" ");
579             ((MExpression) args[i]).pp (indent);
580           }
581         Console.Write (")");
582       }
583     }
584
585     public class FunctionTable
586     {
587       internal Dictionary<MSymbol, Function> table
588         = new Dictionary<MSymbol, Function> ();
589     }
590
591     private static FunctionTable basic_table = new FunctionTable ();
592
593     public static void Defun (FunctionTable table, string name,
594                               Evaluator evaluator, int min_arg, int max_arg,
595                               params Type[] arg_types)
596     {
597       Function func = Defun (name, evaluator, min_arg, max_arg, arg_types);
598       table.table[func.name] = func;
599     }
600
601     private static Function Defun (string name, Evaluator evaluator,
602                                    int min_arg, int max_arg,
603                                    params Type[] arg_types)
604     {
605       MSymbol sym = MSymbol.Of (name);
606       Function func = new Function (sym, evaluator, min_arg, max_arg,
607                                       arg_types);
608       basic_table.table[sym] = func;
609       return func;
610     }
611
612     private static Function Defun (string name, Evaluator evaluator,
613                                     int min_arg, int max_arg)
614     {
615       return Defun (name, evaluator, min_arg, max_arg, typeof (MExpression));
616     }
617
618     private static Function Find (MSymbol name, FunctionTable table)
619     {
620       if (name == MSymbol.integer
621           || name == MSymbol.mtext)
622         return Function.literal;
623
624       Function func;
625       if ((table == null
626            || ! table.table.TryGetValue (name, out func))
627           && ! basic_table.table.TryGetValue (name, out func))
628         return null;
629       return func;
630     }
631
632     private void invalid_expression (object o)
633     {
634       throw new Exception ("Invalid expresssion: " + o);
635     }
636
637     private void invalid_argument (object o)
638     {
639       throw new Exception (String.Format ("Invalid argument to {0}: {1}",
640                                           function.name, o));
641     }
642
643     private Function function;
644     private object[] args;
645
646     public MExpression (MSymbol function_name, object[] args,
647                         FunctionTable function_table)
648     {
649       function = Find (function_name, function_table);
650       int nargs = args.Length;
651       if (nargs < function.min_arg
652           || (function.max_arg >= 0 && nargs > function.max_arg))
653         throw new Exception (String.Format ("Invalid number of arguments to {0}: {1}", function.name, nargs));
654       this.args = (object[]) args.Clone ();
655     }
656
657     private MExpression[] expression_list (MPlist plist, FunctionTable table)
658     {
659       int len = plist.Count;
660       MExpression[] expr_list = new MExpression[len];
661
662       for (int i = 0; i < len; i++, plist = plist.next)
663         {
664           if (plist.IsSymbol)
665             expr_list[i] = new MExpression (plist.Symbol);
666           else if (plist.IsMText || plist.IsInteger)
667             expr_list[i] = new MExpression (plist.val);
668           else if (plist.IsPlist)
669             {
670               MPlist p = plist.Plist;
671               if (p.IsSymbol)
672                 expr_list[i] = new MExpression (p.Symbol, p.next, table);
673               else
674                 expr_list[i] = new MExpression (p, table);
675             }
676           else
677             invalid_expression (plist.val);
678         }
679       return expr_list;
680     }
681
682     // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | EXPRLIST
683     // FUNCALL = '(' SYMBOL EXPR* ')'
684     // EXPRLIST = '(' EXPR* ')'
685
686     // EXPRLIST: PLIST = EXPR ...
687     public MExpression (MPlist plist, FunctionTable table)
688     {
689       function = Function.block;
690       args = expression_list (plist, table);
691     }
692
693     // FUNCALL: NAME = FUNCTION-NAME, ARG-LIST = EXPR ...
694     private MExpression (MSymbol name, MPlist arg_list, FunctionTable table)
695     {
696       function = Find (name, table);
697       if (function == null)
698         throw new Exception ("Unknown function: " + name);
699
700       int nargs = arg_list.Count;
701       if (nargs < function.min_arg
702           || (function.max_arg >= 0 && nargs > function.max_arg))
703         throw new Exception (String.Format
704                              ("Invalid number of arguments to {0}: {1}",
705                               function.name, nargs));
706
707       int i = 0;
708       Type arg_type = typeof (MExpression);
709       if (function.arg_types.Length > 0)
710         {
711           arg_type = function.arg_types[0];
712           if (arg_type == typeof (FunctionTable))
713             {
714               nargs++;
715               args = new object[nargs];
716               args[i++] = table;
717             }
718           else
719             args = new object[nargs];
720         }
721       else
722         args = new object[nargs];
723
724       foreach (MPlist p in arg_list)
725         {
726           if (i < function.arg_types.Length)
727             arg_type = function.arg_types[i];
728           if (arg_type == typeof (MExpression))
729             {
730               if (p.IsSymbol)
731                 args[i++] = new MExpression (p.Symbol);
732               else if (p.IsMText || p.IsInteger)
733                 args[i++] = new MExpression (p.val);
734               else if (p.IsPlist)
735                 {
736                   MPlist p0 = p.Plist;
737                   if (p0.IsSymbol)
738                     args[i++] = new MExpression (p0.Symbol, p0.next, table);
739                   else
740                     args[i++] = new MExpression (p0, table);
741                 }
742               else
743                 invalid_expression (p.val);
744             }
745           else if (arg_type == typeof (MExpression[]))
746             {
747               if (! p.IsPlist)
748                 invalid_argument (p.val);
749               args[i++] = expression_list (p.Plist, table);
750             }
751           else if (arg_type == typeof (MSymbol))
752             {
753               if (! p.IsSymbol)
754                 invalid_argument (p.val);
755               args[i++] = p.Symbol;
756             }
757           else
758             args[i++] = p.val;
759         }
760       if (function == Function.defun)
761         function.Call (args, null);
762     }
763
764     public MExpression (MSymbol sym)
765     {
766       function = Function.varref;
767       args = new object[1];
768       args[0] = sym;
769     }
770
771     public MExpression (object obj)
772     {
773       function = Function.literal;
774       args = new object[1];
775       args[0] = obj;
776     }
777
778     public object Eval (MPlist bindings)
779     {
780       return function.Call (args, bindings);
781     }
782
783     private void pp (string indent)
784     {
785       if (function == Function.varref
786           || function == Function.literal)
787         {
788           if (args[0] is MText)
789             Console.Write ("\"{0}\"", args[0]);
790           else
791             Console.Write (args[0]);
792         }
793       else
794         function.pp (function, indent, args);
795     }
796
797     public void PrettyPrint () { pp (""); }
798   }
799 }