+ private Domain parent;
+ internal MPlist 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;
+ }