using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Xml; namespace System.Xml.Expression { public abstract class Xex { public static bool Debug = false; public struct Name : IEquatable { private static NameTable nt = new NameTable (); private string name; public Name (string str) { name = nt.Add (str); } public static implicit operator Name (string str) { return new Name (str); } public static implicit operator string (Name name) { return name.name; } public static bool operator== (Name n1, Name n2) { return (object) n1.name == (object) n2.name; } public static bool operator!= (Name n1, Name n2) { return (object) n1.name != (object) n2.name; } public static bool operator== (Name n1, string n2) { return (object) n1.name == (object) n2; } public static bool operator!= (Name n1, string n2) { return (object) n1.name != (object) n2; } public static bool operator== (string n1, Name n2) { return (object) n1 == (object) n2.name; } public static bool operator!= (string n1, Name n2) { return (object) n1 != (object) n2.name; } public bool Equals (Name name) { return Object.ReferenceEquals (this.name, name.name); } public override bool Equals (object obj) { return Object.ReferenceEquals (this.name, obj); } public override int GetHashCode () { return name.GetHashCode (); } public static NameTable Table { get { return nt; } } public override string ToString () { return name; } } private static Name Nexpr = "expr"; private static Name Nfuncall = "funcall"; private static Name Nvariable = "variable"; private static Name Ninteger = "integer"; private static Name Nstring = "string"; private static Name Nboolean = "boolean"; private static Name Nsymbol = "symbol"; private static Name Nlist = "list"; private static Name Nobject = "object"; private static Name Ndefun = "defun"; private static Name Nfname = "fname"; private static Name Nargs = "args"; private static Name Nargs_unevalled = "args-unevalled"; private static Name Noptional = "optional"; private static Name Nrest = "rest"; private static Name Nbody = "body"; private static Name Ndefvar = "defvar"; private static Name Ndescription = "description"; private static Name Nrange = "range"; private static Name Nprogn = "progn"; internal abstract class Function { public Name name; public int min_arg, max_arg; public Function () { } public Function (Name name, int min_arg, int max_arg) { this.name = name; this.min_arg = min_arg; this.max_arg = max_arg; } public abstract object Call (object[] args, Domain domain); public override string ToString () { return name; } internal class Subroutine : Function { public Builtin builtin; public Subroutine (Builtin builtin, Name name, int min_arg, int max_arg) : base (name, min_arg, max_arg) { this.builtin = builtin; } public override object Call (object[] args, Domain domain) { object result; for (int i = 0; i < args.Length; i++) { object val = args[i]; if (val is Xex) val = ((Xex) val).Eval (domain); if (val == null) throw new Exception (args[i] + ":evaled to null"); args[i] = val; } result = builtin (args, domain); return result; } } internal class SpecialForm : Function { public Builtin builtin; public SpecialForm (Builtin builtin, Name name, int min_arg, int max_arg) : base (name, min_arg, max_arg) { this.builtin = builtin; } public override object Call (object[] args, Domain domain) { return builtin (args, domain); } } internal class Lambda : Function { internal bool args_evalled; internal Name[] args; internal Xex[] body; public Lambda (XmlNode node) { int nargs = 0, noptions = 0, nrest = 0; name = node.Attributes[Nfname].Value; node = node.FirstChild; if (node != null && (node.Name == Nargs || node.Name == Nargs_unevalled)) { XmlNode n; args_evalled = node.Name == Nargs; for (n = node.FirstChild; n != null; n = n.NextSibling) { if (n.Name != Nsymbol) break; nargs++; } if (n != null && n.Name == Noptional) for (n = n.NextSibling; n != null; n = n.NextSibling) { if (n.Name == Nrest) break; noptions++; } if (n != null) nrest++; min_arg = nargs; max_arg = nargs + noptions + nrest; if (nrest == 1) max_arg = - max_arg; args = new Name[max_arg]; n = node.FirstChild; for (int i = 0; i < max_arg; n = n.NextSibling) if (n.Name == Nsymbol) args[i++] = n.InnerText; } else { min_arg = max_arg = 0; } } public void SetBody (XmlNode node, Domain domain) { for (node = node.FirstChild; node != null && node.Name != Nbody; node = node.NextSibling); if (node != null) { XmlNodeList nlist = node.ChildNodes; body = new Xex[nlist.Count]; for (int i = 0; i < nlist.Count; i++) body[i] = New (nlist[i], domain); } } public override object Call (object[] args, Domain domain) { Bindings current = domain.bindings; object result = false; try { int i; if (args_evalled) for (i = 0; i < min_arg; i++) args[i] = ((Xex) args[i]).Eval (domain); for (i = 0; i < min_arg; i++) { Variable var = domain.GetVar (this.args[i]); domain.Bind (var, args[i]); } foreach (Xex e in body) result = e.Eval (domain); } finally { domain.UnboundTo (current); } return result; } public override string ToString () { string str = "(" + name; foreach (Name a in args) str += " " + a; return (str + ")"); } } } internal abstract class Variable { public readonly Name name; public readonly Name type; internal object val; public Variable (Name name, Name type, object value) { if (value != null) Value = value; this.name = name; this.type = type; } public object Value { get { return val; } set { if (! ValueP (value)) throw new Exception ("Invalid value of " + name + ": " + value); val = value; } } public abstract bool ValueP (object value); public override string ToString () { return name + "(" + val + ")"; } } internal class VarInt : Variable { public struct Range { public int from, to; } public Range[] ranges; public VarInt (Name name, object value) : base (name, Ninteger, value) { } public override bool ValueP (object value) { int i; if (! (value is int)) return false; if (ranges == null) return true; i = (int) value; foreach (Range r in ranges) if (i >= r.from && i <= r.to) return true; return false; } } internal class VarStr : Variable { public string[] ranges; public VarStr (Name name, object value) : base (name, Nstring, value) { } public override bool ValueP (object value) { string str; if (! (value is string)) return false; if (ranges == null) return true; str = (string) value; foreach (string s in ranges) if (s == str) return true; return false; } } internal class VarBool : Variable { public VarBool (Name name, object value) : base (name, Nboolean, value) { } public override bool ValueP (object value) { if (! (value is bool)) return false; return true; } } internal class VarMisc : Variable { public VarMisc (Name name, object value) : base (name, Nobject, value) { } public override bool ValueP (object value) { return true; } } internal class Bindings { private Variable vari; private object old_value; private Bindings next; private Bindings (Variable vari) { this.vari = vari; old_value = vari.val; } public static Bindings Bind (Bindings bindings, Variable vari, object value) { Bindings b = new Bindings (vari); b.vari.Value = value; b.next = bindings; return b; } internal Bindings UnboundTo (Bindings boundary) { for (Bindings b = this; b != boundary; b = b.next) b.vari.val = b.old_value; return boundary; } public override string ToString () { string str = "(bindings"; for (Bindings b = this; b != null; b = b.next) str += " " + vari.name + "=" + b.old_value; return str + ")"; } } #if false internal class ThrowException : Exception { Name tag; public object value; public ThrowException (Name tag, object value) : base () { this.tag = tag; this.value = value; } } #endif public class Domain { public object context; public int depth = 0; internal Dictionary functions; internal Dictionary variables; internal Bindings bindings; internal Domain () { functions = new Dictionary (); variables = new Dictionary (); } public Domain (object context) : this (basic, context) { } public Domain (Domain parent, object context) { functions = new Dictionary (parent.functions); variables = new Dictionary (parent.variables); this.context = context; } internal void Bind (Variable vari, object value) { bindings = Bindings.Bind (bindings, vari, value); } internal void UnboundTo (Bindings boundary) { if (bindings != null) bindings = bindings.UnboundTo (boundary); } public void DefSubr (Builtin builtin, string str, int min_arg, int max_arg) { Name name = str; functions[name] = new Function.Subroutine (builtin, name, min_arg, max_arg); } public void DefSpecial (Builtin builtin, string str, int min_arg, int max_arg) { Name name = str; functions[name] = new Function.SpecialForm (builtin, name, min_arg, max_arg); } internal Function.Lambda RegisterFunction (XmlNode node) { Function.Lambda lambda = new Function.Lambda (node); functions[lambda.name] = lambda; return lambda; } internal Function Defun (XmlNode node) { Name name = node.Attributes[Nfname].Value; Function func; if (! functions.TryGetValue (name, out func)) func = RegisterFunction (node); ((Function.Lambda) func).SetBody (node, this); return func; } public void Defvar (Name name, XmlNode node) { Variable vari; if (node.Name == Ndescription) node = node.NextSibling; if (node != null) { Name type = node.Name; XmlNodeList range_list = null; int nranges = 0; string val = node.InnerText; node = node.NextSibling; if (node != null) { range_list = node.ChildNodes; nranges = range_list.Count; } if (type == Ninteger) { VarInt vi = new VarInt (name, parse_integer (val)); if (range_list != null) { vi.ranges = new VarInt.Range[nranges]; for (int i = 0; i < nranges; i++) { XmlNode n = range_list[i]; if (n.Name == Nrange) { vi.ranges[i].from = parse_integer (n.FirstChild.InnerText); vi.ranges[i].to = parse_integer (n.LastChild.InnerText); } else { int num = parse_integer (n.InnerText); vi.ranges[i].from = vi.ranges[i].to = num; } } } vari = vi; } else if (type == Nstring) { VarStr vs = new VarStr (name, val); if (range_list != null) vs.ranges = new string[nranges]; for (int i = 0; i < nranges; i++) vs.ranges[i] = range_list[i].Value; vari = vs; } else if (type == Nboolean) { vari = new VarBool (name, val == "true"); } else throw new Exception ("Unknown type: " + type); } else vari = new VarMisc (name, null); variables[name] = vari; } internal Function GetFunc (Name name) { Function func; if (! functions.TryGetValue (name, out func)) throw new Exception ("Unknown function: " + name); return func; } public bool CopyFunc (Domain domain, Name name) { Function func = GetFunc (name); domain.functions[name] = func; return true; } public void CopyFunc (Domain domain) { foreach (KeyValuePair kv in functions) domain.functions[kv.Key] = kv.Value; } internal Variable GetVar (Name name) { Variable vari; if (! variables.TryGetValue (name, out vari)) variables[name] = vari = new VarMisc (name, null); return vari; } public override string ToString () { string str = "<(functions"; foreach (KeyValuePair kv in functions) str += " " + kv.Key; str += ") (variabls"; foreach (KeyValuePair kv in variables) str += " " + kv.Key; str += ")"; if (bindings != null) str += " " + bindings; if (context != null) str += " (" + context + ")"; str += ">"; return str; } public void DebugWrite (bool head, string fmt, params object[] arg) { if (Debug) { if (head) { Console.WriteLine (); for (int i = 0; i < depth; i++) Console.Write (" "); } Console.Write (fmt, arg); } } } public delegate object Builtin (object[] args, Domain domain); private static Domain basic = new Domain (); internal static Function Fprogn; static Xex () { basic.DefSubr (set_value, "set", 2, 2); basic.DefSubr (set_value, "=", 2, 2); basic.DefSpecial (and, "and", 1, -1); basic.DefSpecial (and, "&&", 1, -1); basic.DefSpecial (or, "or", 1, -1); basic.DefSpecial (or, "||", 1, -1); basic.DefSubr (not, "not", 1, 1); basic.DefSubr (not, "!", 1, 1); basic.DefSubr (add, "add", 2, -1); basic.DefSubr (add, "+", 2, -1); basic.DefSubr (mul, "mul", 2, -1); basic.DefSubr (mul, "*", 2, -1); basic.DefSubr (sub, "sub", 1, -1); basic.DefSubr (sub, "-", 1, -1); basic.DefSubr (div, "div", 2, -1); basic.DefSubr (div, "/", 2, -1); basic.DefSubr (mod, "mod", 2, 2); basic.DefSubr (mod, "%", 2, 2); basic.DefSubr (logior, "logior", 2, -1); basic.DefSubr (logior, "|", 2, -1); basic.DefSubr (logand, "logand", 2, -1); basic.DefSubr (logand, "&", 2, -1); basic.DefSubr (add_set, "add-set", 2, -1); basic.DefSubr (add_set, "+=", 2, -1); basic.DefSubr (mul_set, "mul-set", 2, -1); basic.DefSubr (mul_set, "*=", 2, -1); basic.DefSubr (sub_set, "sub-set", 2, -1); basic.DefSubr (sub_set, "-=", 2, -1); basic.DefSubr (div_set, "div-set", 2, -1); basic.DefSubr (div_set, "/=", 2, -1); basic.DefSubr (mod_set, "mod-set", 2, 2); basic.DefSubr (mod_set, "%=", 2, 2); basic.DefSubr (logior_set, "logior-set", 2, -1); basic.DefSubr (logior_set, "|=", 2, -1); basic.DefSubr (logand_set, "logand-set", 2, -1); basic.DefSubr (logand_set, "&=", 2, -1); basic.DefSubr (lsh, "lsh", 2, 2); basic.DefSubr (lsh, "<<", 2, 2); basic.DefSubr (rsh, "rsh", 2, 2); basic.DefSubr (rsh, ">>", 2, 2); basic.DefSubr (lsh_set, "lsh-set", 2, 2); basic.DefSubr (lsh_set, "<<=", 2, 2); basic.DefSubr (rsh_set, "rsh-set", 2, 2); basic.DefSubr (rsh_set, ">>=", 2, 2); basic.DefSubr (eq, "eq", 2, -1); basic.DefSubr (eq, "==", 2, -1); basic.DefSubr (noteq, "noteq", 2, 2); basic.DefSubr (noteq, "!=", 2, 2); basic.DefSubr (less_than, "lt", 2, -1); basic.DefSubr (less_than, "<", 2, -1); basic.DefSubr (less_eq, "le", 2, -1); basic.DefSubr (less_eq, "<=", 2, -1); basic.DefSubr (greater_than, "gt", 2, -1); basic.DefSubr (greater_than, ">", 2, -1); basic.DefSubr (greater_eq, "ge", 2, -1); basic.DefSubr (greater_eq, ">=", 2, -1); basic.DefSubr (eval_clause, "eval", 1, 1); basic.DefSpecial (progn_clause, "progn", 0, -1); basic.DefSpecial (progn_clause, "expr", 0, -1); basic.DefSpecial (if_clause, "if", 2, -1); basic.DefSpecial (when_clause, "when", 1, -1); basic.DefSpecial (while_clause, "while", 1, -1); Fprogn = basic.GetFunc (Nprogn); } private static bool is_true (object val) { return (val is bool ? (bool) val : val is int ? (int) val == 0 : true); } private static object set_value (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) args[0]); vari.Value = args[1]; return vari.val; } private static object and (object[] args, Domain domain) { foreach (object arg in args) if (! is_true (((Xex) arg).Eval (domain))) return false; return true; } private static object or (object[] args, Domain domain) { foreach (object arg in args) if (is_true (((Xex) arg).Eval (domain))) return true; return false; } private static object not (object[] args, Domain domain) { return ! is_true (args); } private static object add (object[] args, Domain domain) { int n = 0; foreach (object arg in args) n += (int) arg; return n; } private static object mul (object[] args, Domain domain) { int n = 1; foreach (object arg in args) n *= (int) arg; return n; } private static object sub (object[] args, Domain domain) { int n = (int) args[0]; if (args.Length == 1) return - n; for (int i = 1; i < args.Length; i++) n -= (int) args[i]; return n; } private static object div (object[] args, Domain domain) { int n = (int) args[0]; for (int i = 1; i < args.Length; i++) n /= (int) args[i]; return n; } private static object mod (object[] args, Domain domain) { return ((int) args[0] % (int) args[1]); } private static object logior (object[] args, Domain domain) { int n = 0; foreach (object arg in args) n |= (int) arg; return n; } private static object logand (object[] args, Domain domain) { int n = (int) args[0]; for (int i = 1; i < args.Length; i++) n &= (int) args[i]; return n; } private static object add_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n += (int) args[i]; vari.val = n; return n; } private static object mul_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n *= (int) args[i]; vari.val = n; return n; } private static object sub_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n -= (int) args[i]; vari.val = n; return n; } private static object div_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n /= (int) args[i]; vari.val = n; return n; } private static object mod_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n %= (int) args[i]; vari.val = n; return n; } private static object logior_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n |= (int) args[i]; vari.val = n; return n; } private static object logand_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; for (int i = 1; i < args.Length; i++) n &= (int) args[i]; vari.val = n; return n; } private static object lsh (object[] args, Domain domain) { return (int) args[0] << (int) args[1]; } private static object lsh_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; n <<= (int) args[1]; vari.val = n; return n; } private static object rsh (object[] args, Domain domain) { return (int) args[0] >> (int) args[1]; } private static object rsh_set (object[] args, Domain domain) { Variable vari = domain.GetVar ((Name) ((Xex.Const) args[0]).val); int n = (int) vari.val; n >>= (int) args[1]; vari.val = n; return n; } private static object eq (object[] args, Domain domain) { object o = args[0]; for (int i = 1; i < args.Length; i++) if (o != args[i]) return false; return true; } private static object noteq (object[] args, Domain domain) { return (args[0] != args[1]); } private static object less_than (object[] args, Domain domain) { int n = (int) args[0]; for (int i = 1; i < args.Length; i++) { int n1 = (int) args[i]; if (n >= n1) return false; n = n1; } return true; } private static object less_eq (object[] args, Domain domain) { int n = (int) args[0]; for (int i = 1; i < args.Length; i++) { int n1 = (int) args[i]; if (n > n1) return false; n = n1; } return true; } private static object greater_than (object[] args, Domain domain) { int n = (int) args[0]; for (int i = 1; i < args.Length; i++) { int n1 = (int) args[i]; if (n <= n1) return false; n = n1; } return true; } private static object greater_eq (object[] args, Domain domain) { int n = (int) args[0]; for (int i = 1; i < args.Length; i++) { int n1 = (int) args[i]; if (n < n1) return false; n = n1; } return true; } private static object eval_clause (object[] args, Domain domain) { return ((Xex) args[0]).Eval (domain); } private static object progn_clause (object[] args, Domain domain) { object result = true; foreach (object arg in args) result = ((Xex) arg).Eval (domain); return result; } private static object if_clause (object[] args, Domain domain) { object result; if (is_true (((Xex) args[0]).Eval (domain))) result = ((Xex) args[1]).Eval (domain); else { result = false; for (int i = 2; i < args.Length; i++) result = ((Xex) args[i]).Eval (domain); } return result; } private static object when_clause (object[] args, Domain domain) { if (! is_true (((Xex) args[0]).Eval (domain))) return false; object result = true; for (int i = 1; i < args.Length; i++) result = ((Xex) args[i]).Eval (domain); return result; } private static object while_clause (object[] args, Domain domain) { while (is_true (((Xex) args[0]).Eval (domain))) for (int i = 1; i < args.Length; i++) ((Xex) args[i]).Eval (domain); return false; } public abstract object Eval (Domain domain); public abstract Name TypeOf { get; } private class Funcall : Xex { internal Function func; internal Xex[] args; internal object[] real_args; public Funcall (Function func, Xex[] args) { this.func = func; this.args = args; real_args = new object[args.Length]; } public override object Eval (Domain domain) { domain.DebugWrite (true, "(({0}", func); for (int i = 0; i < args.Length; i++) { domain.DebugWrite (false, " {0}", args[i]); real_args[i] = args[i]; } domain.DebugWrite (false, ")"); domain.depth += 2; object result = func.Call (real_args, domain); domain.depth -= 2; domain.DebugWrite (true, " => {0})", result); return result; } public override Name TypeOf { get { return Nfuncall; } } public override string ToString () { string str = "(" + func.name; if (args != null) foreach (Xex e in args) str += " " + e.ToString (); return (str + ")"); } } private class Varref : Xex { internal Variable vari; public Varref (Variable vari) { this.vari = vari; } public override object Eval (Domain domain) { domain.DebugWrite (true, "(get-value {0})", vari); return vari.val; } public override Name TypeOf { get { return Nvariable; } } public override string ToString () { return "$" + vari.name + "/" + vari.val; } } private class Const : Xex { public object val; public Const (object val) { this.val = val; } public override object Eval (Domain domain) { domain.DebugWrite (true, "(const {0})\n", val); return val; } public override Name TypeOf { get { return (val is int ? Ninteger : val is string ? Nstring : val is bool ? Nboolean : val is Name ? Nsymbol : Nlist); } } public override string ToString () { return val.ToString (); } } internal static int parse_integer (string str) { int len = str.Length; bool negative = false; if (len <= 1) return (len == 0 ? 0 : str[0] - '0'); int c = str[0]; int i; if (c == '0' && str[1] == 'x') { i = 0; for (int idx = 2; idx < len; idx++) { c = str[idx]; if (c < '0') break; else if (c <= '9') i = i * 16 + (c - '0'); else if (c < 'A') break; else if (c <= 'F') i = i * 16 + (c - 'A'); else if (c < 'a') break; else if (c <= 'f') i = i * 16 + (c - 'a'); else break; } return i; } if (c == '-') negative = true; i = c - '0'; for (int idx = 1; idx < len; idx++) { c = str[idx]; if (c < '0' || c > '9') break; i = i * 10 + (c - '0'); } return negative ? - i : i; } private static int pre_parse (XmlNodeList nlist, Domain domain) { int len = 0; foreach (XmlNode node in nlist) { if (node.Name == Ndefun) domain.RegisterFunction (node); else if (node.Name == Ndefvar) domain.Defvar ((Name) node.Attributes[0].Value, node.FirstChild); else len++; } return len; } private static void post_parse (XmlNodeList nlist, Xex[] args, Domain domain) { for (int i = 0, j = 0; i < nlist.Count; i++) { XmlNode node = nlist[i]; if (node.Name == Ndefun) domain.Defun (node); else if (node.Name != Ndefvar) args[j++] = New (node, domain); } } public static Xex New (string url, Domain domain) { XmlDocument doc = new XmlDocument (Name.Table); XmlNode node; using (XmlTextReader reader = new XmlTextReader (url, Name.Table)) { do { reader.Read (); } while (reader.NodeType != XmlNodeType.None && (reader.NodeType != XmlNodeType.Element || Nexpr != reader.Name)); if (reader.NodeType == XmlNodeType.None) throw new Exception ("Node not found"); node = doc.ReadNode (reader); } return New (node, domain); } public static Xex New (XmlNode node, Domain domain) { Name name = node.Name; Xex xex; if (name == Nvariable) { Variable vari = domain.GetVar ((Name) node.Attributes[0].Value); xex = new Xex.Varref (vari); } else if (name == Ninteger) xex = new Xex.Const (parse_integer (node.InnerText)); else if (name == Nstring) xex = new Xex.Const (node.InnerText); else if (name == Nsymbol) xex = new Xex.Const ((Name) node.InnerText); else if (name == Nboolean) xex = new Xex.Const (node.InnerText == "true"); else if (name == Nlist) { List list = new List (); for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) list.Add (New (n, domain)); xex = new Xex.Const (list); } else { if (name == Nfuncall) name = node.Attributes[0].Value; Function func = domain.GetFunc (name); XmlNodeList nlist = node.ChildNodes; int nargs = nlist.Count; if (nargs < func.min_arg || (func.max_arg >= 0 && nargs > func.max_arg)) throw new Exception ("Invalid number of arguments to: " + name + " " + nargs); nargs = pre_parse (nlist, domain); Xex[] args = new Xex[nargs]; post_parse (nlist, args, domain); xex = new Xex.Funcall (func, args); } return xex; } } }