--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+
+namespace System.Xml.Expression
+{
+ public class XmlName : IEquatable<XmlName>
+ {
+ private static NameTable nt = new NameTable ();
+
+ private object name;
+
+ private XmlName (string str)
+ {
+ name = nt.Add (str);
+ }
+
+ public static implicit operator XmlName (string str)
+ {
+ return new XmlName (str);
+ }
+
+ public static bool operator== (object obj, XmlName nam)
+ {
+ return obj == nam.name;
+ }
+
+ public static bool operator!= (object obj, XmlName nam)
+ {
+ return obj != nam.name;
+ }
+
+ public bool Equals (XmlName other) { return name == other.name; }
+ public override bool Equals (object obj) { return obj == name; }
+ public override int GetHashCode ()
+ {
+ return ((string) name).GetHashCode ();
+ }
+
+ public static NameTable Table { get { return nt; } }
+ }
+
+ public class Xex
+ {
+ private static NameTable nt = new NameTable ();
+
+ public static object Name (string str)
+ {
+ return nt.Add (str);
+ }
+
+ public static NameTable Table { get { return nt; } }
+
+ private static object Nvar = Name ("var");
+ private static object Ndefun = Name ("defun");
+ private static object Ncond = Name ("cond");
+ private static object Nprogn = Name ("progn");
+ private static object Nwhen = Name ("when");
+
+ public class Domain
+ {
+ private Domain parent;
+ internal Dictionary<object,functions = new MPlist ();
+ internal MPlist bindings = new MPlist ();
+ private Stack<MPlist> boundaries = new Stack<MPlist> ();
+ internal Translator translator;
+ public object context;
+
+ internal Domain ()
+ {
+ boundaries.Push (bindings);
+ }
+
+ public Domain (object context) : this (basic, context) { }
+
+ public Domain (Domain parent, object context)
+ {
+ this.parent = parent;
+ this.context = context;
+ boundaries.Push (bindings);
+ }
+
+ public void AddTranslator (Translator translator)
+ {
+ if (this.translator == null)
+ this.translator = translator;
+ else
+ this.translator += translator;
+ }
+
+ public void Bind (MSymbol sym, object value)
+ {
+ bindings = bindings.Cons (sym, value);
+ }
+
+ public MPlist SetBoundary ()
+ {
+ boundaries.Push (bindings);
+ return bindings;
+ }
+
+ public void UnboundTo (MPlist boundary)
+ {
+ while (boundary != boundaries.Pop ());
+ while (bindings != boundary)
+ bindings = bindings.next;
+ }
+
+ public void Defun (string name, Builtin builtin, int min_arg, int max_arg)
+ {
+ Defun (name, builtin, min_arg, max_arg, false);
+ }
+
+ public void Defun (string name, Builtin builtin, int min_arg, int max_arg,
+ bool specialp)
+ {
+ MSymbol sym = name;
+ Function func = (Function) functions.Get (sym);
+
+ if (func != null)
+ {
+ if (func.min_arg < min_arg || func.max_arg > max_arg)
+ throw new Exception ("Incompatible argument numbers to override: "
+ + name);
+ func.builtin = builtin;
+ func.lambda = null;
+ func.min_arg = min_arg;
+ func.max_arg = max_arg;
+ func.specialp = specialp;
+ }
+ else
+ {
+ func = new Function (sym, builtin, min_arg, max_arg, specialp);
+ functions = functions.Cons (sym, func);
+ }
+ }
+
+ public void Defun (MSymbol sym, MPlist args, MPlist body)
+ {
+ Function func = (Function) functions.Get (sym);
+
+ if (func != null)
+ {
+ int nargs = args == null ? 0 : args.Count;
+
+ if (func.min_arg < nargs || func.max_arg > nargs)
+ throw new Exception ("Incompatible argument numbers to override: "
+ + sym);
+ func.lambda.SetArgs (args);
+ func.lambda.SetBody (body, this);
+ func.builtin = null;
+ }
+ else
+ {
+ func = new Function (sym, args, body, this);
+ functions = functions.Cons (sym, func);
+ }
+ }
+
+ public void Defun (XmlNode node)
+ {
+ MSymbol sym = node.Attributes["id"].Value;
+ Function func = (Function) functions.Get (sym);
+
+ if (func != null)
+ {
+ XmlNode args = node.FirstChild;
+ int nargs = args.Name == "args" ? args.ChildNodes.Count : 0;
+
+ if (func.min_arg < nargs || func.max_arg > nargs)
+ throw new Exception ("Incompatible argument numbers to override: "
+ + sym);
+ func.lambda.Set (node, this);
+ func.builtin = null;
+ }
+ else
+ {
+ func = new Function (sym, node, this);
+ functions = functions.Cons (sym, func);
+ }
+ }
+
+ internal Function GetFunc (MSymbol name)
+ {
+ Function func = (Function) functions.Get (name);
+
+ if (func == null)
+ {
+ if (parent != null)
+ return parent.GetFunc (name);
+ throw new Exception ("Unknown function: " + name);
+ }
+ return func;
+ }
+
+ public bool CopyFunc (Domain domain, MSymbol name)
+ {
+ Function func = (Function) functions.Get (name);
+ if (func == null)
+ return false;
+ domain.functions = domain.functions.Cons (name, func);
+ return true;
+ }
+
+ public void CopyFunc (Domain domain)
+ {
+ foreach (MPlist p in functions)
+ domain.functions = domain.functions.Cons (p.key, p.val);
+ }
+
+ public object GetValue (MSymbol name)
+ {
+ MPlist slot = bindings.Find (name);
+
+ if (slot == null)
+ {
+ if (parent != null)
+ return parent.GetValue (name);
+ throw new Exception ("Unbound variable: " + name);
+ }
+ return slot.val;
+ }
+
+ public object SetValue (MSymbol name, object val)
+ {
+ MPlist boundary = boundaries.Peek ();
+
+ for (MPlist plist = bindings; plist != boundary; plist = plist.next)
+ if (plist.key == name)
+ {
+ plist.val = val;
+ return val;
+ }
+ bindings = bindings.Cons (name, val);
+ return val;
+ }
+
+ public bool IsBound (MSymbol name)
+ {
+ return (bindings.Find (name) != null);
+ }
+
+ public void Translate (MPlist plist)
+ {
+ if (parent != null)
+ parent.Translate (plist);
+ if (translator != null)
+ for (MPlist p = plist; ! p.IsEmpty; p = p.next)
+ translator (p, this);
+ }
+
+ public override string ToString ()
+ {
+ string str = "<(functions";
+ foreach (MPlist p in functions)
+ str += " " + p.key;
+ str += ") (bindings " + bindings + ")";
+ if (context != null)
+ str += " (" + context + ")";
+ str += ">";
+ return str;
+ }
+ }
+
+ public delegate object Builtin (MExpression[] args, Domain domain);
+ public delegate void Translator (MPlist plist, Domain domain);
+
+ internal class Function
+ {
+ internal class Lambda
+ {
+ internal MSymbol[] args;
+ internal MExpression[] body;
+
+ public Lambda (MPlist args, MPlist body, Domain domain)
+ {
+ SetArgs (args);
+ SetBody (body, domain);
+ }
+
+ public Lambda (XmlNode node, Domain domain)
+ {
+ Set (node, domain);
+ }
+
+ public void SetArgs (MPlist args)
+ {
+ int len = args == null ? 0 : args.Count;
+
+ if (this.args == null)
+ this.args = new MSymbol[len];
+ for (int i = 0; i < len; i++, args = args.next)
+ this.args[i] = args.Symbol;
+ }
+
+ public void SetBody (MPlist body, Domain domain)
+ {
+ int len = body == null ? 0 : body.Count;
+ if (this.body == null)
+ this.body = new MExpression[len];
+ for (int i = 0; i < len; i++, body = body.next)
+ {
+ domain.Translate (body);
+ this.body[i] = new MExpression (body.key, body.val, domain);
+ }
+ }
+
+ public void Set (XmlNode node, Domain domain)
+ {
+ XmlNodeList body = node.ChildNodes;
+ int idx = 0;
+
+ if (body[0].Name == "args")
+ {
+ XmlNodeList args = body[0].ChildNodes;
+ if (this.args == null)
+ this.args = new MSymbol[args.Count];
+ for (int i = 0; i < args.Count; i++)
+ this.args[i] = args[i].InnerText;
+ idx++;
+ }
+ else if (this.args == null)
+ this.args = new MSymbol[0];
+ if (this.body == null)
+ this.body = new MExpression[body.Count - idx];
+ for (int i = 0; idx < body.Count; i++, idx++)
+ this.body[i] = new MExpression (body[idx], domain);
+ }
+ }
+
+ public readonly MSymbol Name;
+ public Builtin builtin;
+ public int min_arg, max_arg;
+ internal Lambda lambda;
+ public bool specialp = false;
+
+ internal static Function ignore, varref, block;
+
+ public Function (MSymbol name, Builtin builtin,
+ int min_arg, int max_arg, bool specialp)
+ {
+ Name = name;
+ this.builtin = builtin;
+ this.min_arg = min_arg;
+ this.max_arg = max_arg;
+ this.specialp = specialp;
+ }
+
+ internal Function (MSymbol name, MPlist args, MPlist body,
+ Domain domain)
+ {
+ Name = name;
+ lambda = new Lambda (args, body, domain);
+ this.min_arg = this.max_arg = lambda.args.Length;
+ }
+
+ internal Function (MSymbol name, XmlNode node, Domain domain)
+ {
+ Name = name;
+ lambda = new Lambda (node, domain);
+ this.min_arg = this.max_arg = lambda.args.Length;
+ }
+
+ private Function ()
+ {
+ Name = MSymbol.nil;
+ }
+
+ static Function ()
+ {
+ ignore = new Function ();
+ varref = new Function (Mvarref, get_value, 1, 1, true);
+ block = new Function (Mprogn, progn, 0, -1, true);
+ }
+
+ private static object get_value (MExpression[] args, Domain domain)
+ {
+ return domain.GetValue ((MSymbol) args[0].val);
+ }
+
+ public object Call (MExpression[] args, Domain domain)
+ {
+ if (builtin != null)
+ {
+ if (! specialp)
+ foreach (MExpression e in args)
+ e.Eval (domain);
+ return builtin (args, domain);
+ }
+ if (lambda == null)
+ return null;
+ MPlist orig_bindings = domain.bindings;
+ object result = false;
+ try {
+ int i = 0;
+ foreach (MSymbol arg in lambda.args)
+ domain.Bind (arg, args[i++].Eval (domain));
+ foreach (MExpression e in lambda.body)
+ result = e.Eval (domain);
+ } finally {
+ domain.bindings = orig_bindings;
+ }
+ return result;
+ }
+ }
+
+ private static Domain basic;
+
+ static MExpression ()
+ {
+ basic = new Domain ();
+
+ basic.Defun ("set", set_value, 2, 2, true);
+ basic.Defun ("=", set_value, 2, 2, true);
+ basic.Defun ("!", not, 1, 1, false);
+ basic.Defun ("+", plus, 2, -1, false);
+ basic.Defun ("*", multi, 2, -1, false);
+ basic.Defun ("-", minus, 1, -1, false);
+ basic.Defun ("/", divide, 2, -1, false);
+ basic.Defun ("%", percent, 2, -1, false);
+ basic.Defun ("|", logior, 2, -1, false);
+ basic.Defun ("&", logand, 2, -1, false);
+ basic.Defun ("+=", pluseq, 2, -1, true);
+ basic.Defun ("*=", multieq, 2, -1, true);
+ basic.Defun ("-=", minuseq, 2, -1, true);
+ basic.Defun ("/=", divideeq, 2, -1, true);
+ basic.Defun ("%=", percenteq, 2, -1, true);
+ basic.Defun ("|=", logioreq, 2, -1, true);
+ basic.Defun ("&=", logandeq, 2, -1, true);
+ basic.Defun ("<<", lshift, 2, 2, false);
+ basic.Defun (">>", rshift, 2, 2, false);
+ basic.Defun ("<<=", lshifteq, 2, 2, true);
+ basic.Defun (">>=", rshifteq, 2, 2, true);
+ basic.Defun ("==", eq, 2, -1, false);
+ basic.Defun ("!=", noteq, 2, 2, false);
+ basic.Defun ("<", less, 2, -1, false);
+ basic.Defun ("<=", lesseq, 2, -1, false);
+ basic.Defun (">", more, 2, -1, false);
+ basic.Defun (">=", moreeq, 2, -1, false);
+ basic.Defun ("progn", progn, 0, -1, true);
+ basic.Defun ("if", ifclause, 2, -1, true);
+ basic.Defun ("when", whenclause, 1, -1, true);
+ basic.Defun ("while", whileclause, 1, -1, true);
+
+ basic.AddTranslator (new Translator (translate_cond));
+ }
+
+ private static object set_value (MExpression[] args, Domain domain)
+ {
+ return domain.SetValue ((MSymbol) args[0].args[0].val,
+ args[1].Eval (domain));
+ }
+
+ private static object not (MExpression[] args, Domain domain)
+ {
+ if (args[0].val is int)
+ return (int) args[0].val == 0;
+ if (args[0].val is bool)
+ return ! ((bool) args[0].val);
+ return true;
+ }
+
+ private static object plus (MExpression[] args, Domain domain)
+ {
+ if (args[0].val is int)
+ {
+ int n = 0;
+ foreach (MExpression e in args)
+ n += (int) e.val;
+ return n;
+ }
+ else if (args[0].val is MText)
+ {
+ MText mt = new MText ();
+ foreach (MExpression e in args)
+ mt += (MText) e.val;
+ return mt;
+ }
+ throw new Exception ("Not an integer nor MText: " + args[0].val);
+ }
+
+ private static object multi (MExpression[] args, Domain domain)
+ {
+ int n = 1;
+ foreach (MExpression e in args)
+ n *= (int) e.val;
+ return n;
+ }
+
+ private static object minus (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+ if (args.Length == 1)
+ return - n;
+ for (int i = 1; i < args.Length; i++)
+ n -= (int) args[i].val;
+ return n;
+ }
+
+ private static object divide (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+ for (int i = 1; i < args.Length; i++)
+ n /= (int) args[i].val;
+ return n;
+ }
+
+ private static object percent (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+ for (int i = 1; i < args.Length; i++)
+ n %= (int) args[i].val;
+ return n;
+ }
+
+ private static object logior (MExpression[] args, Domain domain)
+ {
+ int n = 0;
+ foreach (MExpression e in args)
+ n |= (int) e.val;
+ return n;
+ }
+
+ private static object logand (MExpression[] args, Domain domain)
+ {
+ int n = 0;
+ foreach (MExpression e in args)
+ n &= (int) e.val;
+ return n;
+ }
+
+ private static object pluseq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ object val = domain.GetValue (sym);
+
+ if (val is int)
+ {
+ int n = (int) val;
+ for (int i = 1; i < args.Length; i++)
+ n += (int) args[i].Eval (domain);
+ val = n;
+ }
+ else if (val is MText)
+ {
+ MText mt = (MText) val;
+ for (int i = 1; i < args.Length; i++)
+ mt.Cat ((MText) args[i].Eval (domain));
+ val = mt;
+ }
+ domain.SetValue (sym, val);
+ return val;
+ }
+
+ private static object multieq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ for (int i = 1; i < args.Length; i++)
+ n *= (int) args[i].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object minuseq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ for (int i = 1; i < args.Length; i++)
+ n -= (int) args[i].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object divideeq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ for (int i = 1; i < args.Length; i++)
+ n /= (int) args[i].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object percenteq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ for (int i = 1; i < args.Length; i++)
+ n %= (int) args[i].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object logioreq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ for (int i = 1; i < args.Length; i++)
+ n |= (int) args[i].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object logandeq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ for (int i = 1; i < args.Length; i++)
+ n &= (int) args[i].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object lshift (MExpression[] args, Domain domain)
+ {
+ return (int) args[0].val << (int) args[1].val;
+ }
+
+ private static object lshifteq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ n <<= (int) args[1].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object rshift (MExpression[] args, Domain domain)
+ {
+ return (int) args[0].val >> (int) args[1].val;
+ }
+
+ private static object rshifteq (MExpression[] args, Domain domain)
+ {
+ MSymbol sym = (MSymbol) args[0].args[0].val;
+ int n = (int) domain.GetValue (sym);
+
+ n >>= (int) args[1].Eval (domain);
+ return domain.SetValue (sym, (object) n);
+ }
+
+ private static object eq (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+
+ for (int i = 1; i < args.Length; i++)
+ if (n != (int) args[i].val)
+ return false;
+ return true;
+ }
+
+ private static object noteq (MExpression[] args, Domain domain)
+ {
+ return ((int) args[0].val != (int) args[1].val);
+ }
+
+ private static object less (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+
+ for (int i = 1; i < args.Length; i++)
+ {
+ int n1 = (int) args[i].val;
+ if (n >= n1)
+ return false;
+ n = n1;
+ }
+ return true;
+ }
+
+ private static object lesseq (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+ for (int i = 1; i < args.Length; i++)
+ {
+ int n1 = (int) args[i].val;
+ if (n > n1)
+ return false;
+ n = n1;
+ }
+ return true;
+ }
+
+ private static object more (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+ for (int i = 1; i < args.Length; i++)
+ {
+ int n1 = (int) args[i].val;
+ if (n <= n1)
+ return false;
+ n = n1;
+ }
+ return true;
+ }
+
+ private static object moreeq (MExpression[] args, Domain domain)
+ {
+ int n = (int) args[0].val;
+ for (int i = 1; i < args.Length; i++)
+ {
+ int n1 = (int) args[i].val;
+ if (n < n1)
+ return false;
+ n = n1;
+ }
+ return true;
+ }
+
+ private static object progn (MExpression[] args, Domain domain)
+ {
+ object result = false;
+
+ foreach (MExpression e in args)
+ result = e.Eval (domain);
+ return result;
+ }
+
+ private static bool check_condition (MExpression condition, Domain domain)
+ {
+ object result = condition.Eval (domain);
+ return (result is bool ? (bool) result
+ : result is int ? ((int) result) != 0
+ : true);
+ }
+
+ private static object ifclause (MExpression[] args, Domain domain)
+ {
+ object result = false;
+
+ if (check_condition (args[0], domain))
+ result = args[1].Eval (domain);
+ else
+ for (int i = 2; i < args.Length; i++)
+ result = args[i].Eval (domain);
+ return result;
+ }
+
+ private static object whenclause (MExpression[] args, Domain domain)
+ {
+ object result = false;
+
+ if (check_condition (args[0], domain))
+ for (int i = 1; i < args.Length; i++)
+ result = args[i].Eval (domain);
+ return result;
+ }
+
+ private static object whileclause (MExpression[] args, Domain domain)
+ {
+ while (check_condition (args[0], domain))
+ for (int i = 1; i < args.Length; i++)
+ args[i].Eval (domain);
+ return false;
+ }
+
+ // (cond (COND1 ...) (COND2 ...) ...)
+ // => (cond (when COND1 ...) (when COND2 ...) ...)
+ private static void translate_cond (MPlist plist, Domain domain)
+ {
+ if (plist.IsPlist)
+ {
+ plist = plist.Plist;
+ if (plist.IsSymbol && plist.Symbol == Mcond)
+ {
+ plist.val = Mprogn;
+ for (plist = plist.next; ! plist.IsEmpty; plist = plist.next)
+ {
+ if (! plist.IsPlist)
+ throw new Exception ("Invalid cond form: " + plist);
+ plist.Plist.Push (MSymbol.symbol, Mwhen);
+ }
+ }
+ }
+ }
+
+ private Function function;
+ private MExpression[] args;
+ private object val;
+
+ public MExpression[] Args { get { return args; } }
+ public object Val { get { return val; } }
+
+ private MExpression (object val)
+ {
+ this.val = val;
+ }
+
+ // EXPR = SYMBOL | MTEXT | INTEGER | FUNCALL | PROGN
+ // FUNCALL = '(' SYMBOL EXPR* ')'
+ // PROGN = '(' EXPR * ')'
+ private MExpression (MSymbol key, object val, Domain domain)
+ {
+ if (key == MSymbol.symbol)
+ {
+ function = Function.varref;
+ args = new MExpression[1];
+ args[0] = new MExpression (val);
+ }
+ else if (key == MSymbol.integer
+ || key == MSymbol.mtext)
+ {
+ this.val = val;
+ }
+ else if (key == MSymbol.plist)
+ {
+ MPlist p = (MPlist) val;
+
+ if (p.IsSymbol)
+ {
+ MSymbol sym = p.Symbol;
+
+ if (sym == Mdefun)
+ {
+ p = p.next;
+ if (! p.IsSymbol)
+ throw new Exception ("Invalid function argument: "
+ + p.val);
+ sym = p.Symbol;
+ p = p.next;
+ if (! p.IsPlist)
+ throw new Exception ("Invalid function argument: "
+ + p.val);
+ domain.Defun (sym, p.Plist, p.next);
+ // This Mexpression is just a dummy.
+ }
+ else
+ {
+ function = domain.GetFunc (sym);
+ p = p.next;
+ int nargs = p.Count;
+ if (nargs < function.min_arg
+ || (function.max_arg >= 0 && nargs > function.max_arg))
+ throw new Exception ("Invalid number of arguments to: "
+ + sym + " " + nargs);
+ args = new MExpression[nargs];
+ for (int i = 0; i < nargs; i++, p = p.next)
+ {
+ domain.Translate (p);
+ args[i] = new MExpression (p.key, p.val, domain);
+ }
+ }
+ }
+ else
+ {
+ args = new MExpression[1];
+ args[0] = new MExpression (p, domain);
+ }
+ }
+ else
+ throw new Exception ("Invalid expression: " + key + ":" + val);
+ }
+
+ public MExpression (MPlist plist, Domain domain)
+ {
+ function = Function.block;
+ args = new MExpression[plist.Count];
+ for (int i = 0; ! plist.IsEmpty; i++, plist = plist.next)
+ {
+ domain.Translate (plist);
+ args[i] = new MExpression (plist.key, plist.val, domain);
+ }
+ }
+
+ public MExpression (XmlNode node, Domain domain)
+ {
+ MSymbol sym = node.Name;
+
+ function = domain.GetFunc (sym);
+
+ XmlAttributeCollection attrs = node.Attributes;
+
+ int nargs = attrs.Count + node.ChildNodes.Count;
+ if (nargs < function.min_arg
+ || (function.max_arg >= 0 && nargs > function.max_arg))
+ throw new Exception ("Invalid number of arguments: " + node.InnerXml);
+ args = new MExpression[nargs];
+ int i;
+ for (i = 0; i < attrs.Count; i++)
+ {
+ string str = sttrs[i].Value;
+
+ }
+ }
+
+ public object Eval (Domain domain)
+ {
+ if (function == null)
+ {
+ if (val is MSymbol)
+ val = domain.GetValue ((MSymbol) val);
+ }
+ else
+ val = function.Call (args, domain);
+ return val;
+ }
+
+ public override string ToString ()
+ {
+ string str;
+
+ if (function != null)
+ {
+ str = "(" + function.Name.Name;
+ if (args != null)
+ foreach (MExpression e in args)
+ str += " " + e.ToString ();
+ str += ")";
+ }
+ else if (val != null)
+ {
+ if (val is MText)
+ str = "\"" + (string) ((MText) val) + "\"";
+ else
+ str = val.ToString ();
+ }
+ else
+ str = "()";
+ return str;
+ }
+ }
+}