public void Register(object id, XQueryContext module, XQuerySequenceType[] parameters, XQuerySequenceType resType) { XQueryFunctionRecord rec = new XQueryFunctionRecord(); rec.id = id; rec.module = module; rec.parameters = parameters; rec.returnType = resType; FunctionSocket sock = new FunctionSocket(rec); FunctionSocket next; if (m_table.TryGetValue(rec.id, out next)) sock.next = next; m_table[rec.id] = sock; }
public FunctionSocket(XQueryFunctionRecord rec) { this.rec = rec; }
public void Register(object id, MethodInfo method) { bool context = false; XQueryFunctionRecord rec = new XQueryFunctionRecord(); rec.id = id; object[] attrs = method.GetCustomAttributes(typeof(XQuerySignatureAttribute), false); XQuerySignatureAttribute sig = null; if (attrs.Length > 0) sig = (XQuerySignatureAttribute)attrs[0]; ParameterInfo[] parameter_info = method.GetParameters(); List<XQuerySequenceType> type_list = new List<XQuerySequenceType>(); int implict = -1; foreach (ParameterInfo pi in parameter_info) { if (pi.ParameterType == typeof(IContextProvider)) { if (context) throw new ArgumentException(pi.Name); context = true; continue; } bool customized = false; bool variableParam = false; object[] pi_attrs = pi.GetCustomAttributes(false); foreach (object pi_atr in pi_attrs) { if (pi_atr is System.ParamArrayAttribute) variableParam = true; else if (pi_atr is ImplictAttribute) { customized = true; if (implict != -1) throw new ArgumentException(pi.Name); implict = pi.Position; } else { XQueryParameterAttribute xattr = pi_atr as XQueryParameterAttribute; if (xattr != null) { type_list.Add(new XQuerySequenceType(xattr.TypeCode, xattr.Cardinality, variableParam ? pi.ParameterType.GetElementType() : pi.ParameterType)); customized = true; break; } } } if (!customized) { if (pi.ParameterType == typeof(XQueryNodeIterator)) type_list.Add(new XQuerySequenceType(XmlTypeCode.Item, XmlTypeCardinality.ZeroOrMore, pi.ParameterType)); else type_list.Add(new XQuerySequenceType(pi.ParameterType, XmlTypeCardinality.One)); } } if (sig != null && sig.Return != XmlTypeCode.None) rec.returnType = new XQuerySequenceType(sig.Return, sig.Cardinality, method.ReturnType); else { if (method.ReturnType == typeof(XQueryNodeIterator)) rec.returnType = new XQuerySequenceType(XmlTypeCode.Item, XmlTypeCardinality.ZeroOrMore, method.ReturnType); else rec.returnType = new XQuerySequenceType(method.ReturnType, XmlTypeCardinality.One); } if (sig != null) { rec.variableParams = sig.VariableParams; rec.validationReader = sig.ValidationReaderDemanded; } rec.parameters = type_list.ToArray(); FunctionSocket sock = new FunctionSocket(rec); FunctionSocket next; if (m_table.TryGetValue(rec.id, out next)) { FunctionSocket curr = next; while (curr != null) { if (curr.rec.parameters.Length == rec.parameters.Length && curr.rec.variableParams == rec.variableParams) throw new InvalidOperationException(method.ToString()); curr = curr.next; } sock.next = next; } m_table[rec.id] = sock; GlobalSymbols.DefineStaticOperator(rec.id, method); if (context) { object[] body; Executive.Parameter[] parameters; if (implict == -1) { parameters = new Executive.Parameter[parameter_info.Length - 1]; body = new object[parameter_info.Length + 2]; } else { parameters = new Executive.Parameter[parameter_info.Length - 2]; body = new object[parameter_info.Length + 1]; } int k = 0; int i = 2; body[0] = Funcs.List; body[1] = Lisp.List(Lisp.QUOTE, rec.id); foreach (ParameterInfo pi in parameter_info) { if (pi.Position != implict) { if (pi.ParameterType != typeof(IContextProvider)) { parameters[k] = new Executive.Parameter(); parameters[k].ID = ATOM.Create(String.Format("p{0}", k + 1)); parameters[k].Type = typeof(System.Object); parameters[k].VariableParam = false; body[i++] = parameters[k].ID; k++; } else body[i++] = Lisp.List(Lisp.QUOTE, ID.Context); } } GlobalSymbols.Defmacro(rec.id, parameters, Lisp.List(body)); } }