private FunctionIdentifier(string methodName, FunctionMethod method, AbstractInstruction instruction) { Code = FunctionCode.__NULL__; ArgBuilder = instruction.ArgBuilder; flag = instruction.Flag; Method = method; Name = methodName; Instruction = instruction; }
public static void Register(FunctionKey functionKey, FunctionMethod functionMethod) { if (Hooks.ContainsKey(functionKey)) { Hooks[functionKey] = functionMethod; } else { Hooks.Add(functionKey, functionMethod); } }
// REF: https://github.com/OData/WebApi/blob/master/src/Microsoft.AspNet.OData.Shared/Routing/Conventions/ActionRoutingConvention.cs // REF: https://github.com/OData/WebApi/blob/master/src/Microsoft.AspNet.OData.Shared/Routing/Conventions/FunctionRoutingConvention.cs // REF: https://github.com/OData/WebApi/blob/master/src/Microsoft.AspNet.OData.Shared/Routing/Conventions/EntitySetRoutingConvention.cs // REF: https://github.com/OData/WebApi/blob/master/src/Microsoft.AspNet.OData.Shared/Routing/Conventions/EntityRoutingConvention.cs // REF: https://github.com/OData/WebApi/blob/master/src/Microsoft.AspNet.OData.Shared/Routing/Conventions/SingletonRoutingConvention.cs static bool IsActionOrFunction(IEdmEntitySet?entitySet, IEdmSingleton?singleton, string actionName, IEnumerable <string> methods) { using var iterator = methods.GetEnumerator(); if (!iterator.MoveNext()) { return(false); } var method = iterator.Current; if (iterator.MoveNext()) { return(false); } if (entitySet == null && singleton == null) { return(true); } const string ActionMethod = "Post"; const string AddNavigationLink = ActionMethod + "To"; const string FunctionMethod = "Get"; if (ActionMethod.Equals(method, OrdinalIgnoreCase) && actionName != ActionMethod) { if (actionName.StartsWith("CreateRef", Ordinal) || (entitySet != null && actionName == (ActionMethod + entitySet.Name))) { return(false); } return(!IsNavigationPropertyLink(entitySet, singleton, actionName, ActionMethod, AddNavigationLink)); } else if (FunctionMethod.Equals(method, OrdinalIgnoreCase) && actionName != FunctionMethod) { if (actionName.StartsWith("GetRef", Ordinal) || (entitySet != null && actionName == (FunctionMethod + entitySet.Name))) { return(false); } return(!IsNavigationPropertyLink(entitySet, singleton, actionName, FunctionMethod)); } return(false); }
public UserdataMethod MakeGenericMethod(Type[] parameters) { List <MethodInfo> methods = new List <MethodInfo>(); for (int i = 0; i < m_Count; ++i) { FunctionMethod method = m_Methods[i] as FunctionMethod; if (method != null) { if (method.Method.IsGenericMethod) { Type[] types = method.Method.GetGenericArguments(); if (types.Length == parameters.Length) { bool accord = true; int length = types.Length; for (int j = 0; j < length; ++j) { #if UWP if (!types[j].GetTypeInfo().BaseType.IsAssignableFrom(parameters[j])) { accord = false; break; } #else if (!types[j].BaseType.IsAssignableFrom(parameters[j])) { accord = false; break; } #endif } if (accord) { methods.Add(method.Method.MakeGenericMethod(parameters)); break; } } } } } if (methods.Count > 0) { return(new UserdataMethod(m_Script, m_Type, MethodName, methods)); } throw new ExecutionException(m_Script, "没有找到合适的泛型函数 " + MethodName); }
public UserdataMethod MakeGenericMethod(Type[] parameters) { if ((this.m_GenericCount > 0) && (this.m_GenericMethods != null)) { List <MethodInfo> methods = new List <MethodInfo>(); for (int i = 0; i < this.m_GenericCount; i++) { FunctionMethod method = this.m_GenericMethods[i] as FunctionMethod; if (method != null) { Type[] genericArguments = method.Method.GetGenericArguments(); if (genericArguments.Length == parameters.Length) { bool flag = true; int length = genericArguments.Length; for (int j = 0; j < length; j++) { if (!genericArguments[j].GetTypeInfo().BaseType.GetTypeInfo().IsAssignableFrom(parameters[j])) { flag = false; break; } } if (flag) { methods.Add(method.Method.MakeGenericMethod(parameters)); break; } } } } if (methods.Count > 0) { return(new UserdataMethod(this.m_Script, this.m_Type, this.MethodName, methods)); } } throw new ExecutionException(this.m_Script, "没有找到合适的泛型函数 " + this.MethodName); }
private void Initialize_impl(Type type, string methodName, List <MethodBase> methods) { m_Type = type; m_IsClass = type.IsClass; m_MethodName = methodName; List <FunctionBase> functionMethod = new List <FunctionBase>(); List <FunctionBase> genericMethods = new List <FunctionBase>(); bool Params = false; //是否是不定参函数 Type ParamType = null; //不定参类型 ParameterInfo[] Parameters; //所有参数 List <Type> parameterTypes = new List <Type>(); //参数类型 List <object> defaultParameter = new List <object>(); //默认参数 int length = methods.Count; //总数量 MethodBase method = null; FunctionBase functionBase; for (int i = 0; i < length; ++i) { method = methods[i]; Params = false; ParamType = null; parameterTypes.Clear(); defaultParameter.Clear(); Parameters = method.GetParameters(); if (Util.IsExtensionMethod(method)) { for (int j = 1; j < Parameters.Length; ++j) { var par = Parameters[j]; parameterTypes.Add(par.ParameterType); if (par.DefaultValue != DBNull.Value) { defaultParameter.Add(par.DefaultValue); } Params = Util.IsParamArray(par); if (Params) { ParamType = par.ParameterType.GetElementType(); } } functionBase = new ExtensionMethod(method as MethodInfo, parameterTypes.ToArray(), defaultParameter.ToArray(), ParamType, Params, ""); } else { foreach (ParameterInfo par in Parameters) { parameterTypes.Add(par.ParameterType); if (par.DefaultValue != DBNull.Value) { defaultParameter.Add(par.DefaultValue); } Params = Util.IsParamArray(par); if (Params) { ParamType = par.ParameterType.GetElementType(); } } if (method is MethodInfo) { functionBase = new FunctionMethod(method as MethodInfo, parameterTypes.ToArray(), defaultParameter.ToArray(), ParamType, Params, ""); } else { functionBase = new FunctionConstructor(method as ConstructorInfo, parameterTypes.ToArray(), defaultParameter.ToArray(), ParamType, Params, ""); } } if (functionBase.IsGeneric) { genericMethods.Add(functionBase); } else { functionMethod.Add(functionBase); } } m_Methods = functionMethod.ToArray(); m_Count = m_Methods.Length; m_GenericMethods = genericMethods.ToArray(); m_GenericCount = m_GenericMethods.Length; }
public IOperandTerm GetFunctionMethod(LabelDictionary labelDic, string codeStr, IOperandTerm[] arguments, bool userDefinedOnly) { if (Config.ICFunction) { codeStr = codeStr.ToUpper(); } if (arguments == null) //引数なし、名前のみの探索 { if (refmethodDic.ContainsKey(codeStr)) { return(new UserDefinedRefMethodNoArgTerm(refmethodDic[codeStr])); } return(null); } if ((labelDic != null) && (labelDic.Initialized)) { if (refmethodDic.ContainsKey(codeStr)) { return(new UserDefinedRefMethodTerm(refmethodDic[codeStr], arguments)); } FunctionLabelLine func = labelDic.GetNonEventLabel(codeStr); if (func != null) { if (userDefinedOnly && !func.IsMethod) { throw new CodeEE("#FUNCTIONが指定されていない関数\"@" + func.LabelName + "\"をCALLF系命令で呼び出そうとしました"); } if (func.IsMethod) { string errMes; IOperandTerm ret = UserDefinedMethodTerm.Create(func, arguments, out errMes); if (ret == null) { throw new CodeEE(errMes); } return(ret); } //1.721 #FUNCTIONが定義されていない関数は組み込み関数を上書きしない方向に。 PANCTION.ERBのRANDとか。 if (!methodDic.ContainsKey(codeStr)) { throw new CodeEE("#FUNCTIONが定義されていない関数(" + func.Position.Filename + ":" + func.Position.LineNo + "行目)を式中で呼び出そうとしました"); } } } if (userDefinedOnly) { return(null); } FunctionMethod method = null; if (!methodDic.TryGetValue(codeStr, out method)) { return(null); } string errmes = method.CheckArgumentType(codeStr, arguments); if (errmes != null) { throw new CodeEE(errmes); } return(new FunctionMethodTerm(method, arguments)); }
/// <summary> /// 1803beta005 予め引数の数を合わせて規定値を代入しておく /// 1806+v6.99 式中関数の引数に無効な#DIM変数を与えている場合に例外になるのを修正 /// 1808beta009 REF型に対応 /// </summary> public UserDefinedFunctionArgument ConvertArg(IOperandTerm[] srcArgs, out string errMes) { errMes = null; if (TopLabel.IsError) { errMes = TopLabel.ErrMes; return(null); } var func = TopLabel; var convertedArg = new IOperandTerm[func.Arg.Length]; if (convertedArg.Length < srcArgs.Length) { errMes = "引数の数が関数\"@" + func.LabelName + "\"に設定された数を超えています"; return(null); } IOperandTerm term = null; VariableTerm destArg = null; var isString = false; for (var i = 0; i < func.Arg.Length; i++) { term = i < srcArgs.Length ? srcArgs[i] : null; destArg = func.Arg[i]; isString = destArg.IsString; if (destArg.Identifier.IsReference) //参照渡しの場合 { if (term == null) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1) + "番目の引数は参照渡しのため省略できません"; return(null); } var vTerm = term as VariableTerm; if (vTerm == null || vTerm.Identifier.Dimension == 0) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1) + "番目の引数は参照渡しのための配列変数でなければなりません"; return(null); } //TODO 1810alpha007 キャラ型を認めるかどうかはっきりしたい 今のところ認めない方向 //型チェック if (!((ReferenceToken)destArg.Identifier).MatchType(vTerm.Identifier, false, out errMes)) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1) + "番目の引数:" + errMes; return(null); } } else if (term == null) //引数が省略されたとき { term = func.Def[i]; //デフォルト値を代入 //1808beta001 デフォルト値がない場合はエラーにする //一応逃がす if (term == null && !Config.CompatiFuncArgOptional) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1) + "番目の引数は省略できません(この警告は互換性オプション「" + Config.GetConfigName(ConfigCode.CompatiFuncArgOptional) + "」により無視できます)"; return(null); } } else if (term.GetOperandType() != destArg.GetOperandType()) { if (term.GetOperandType() == typeof(string)) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1) + "番目の引数を文字列型から整数型に変換できません"; return(null); } if (!Config.CompatiFuncArgAutoConvert) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1) + "番目の引数を整数型から文字列型に変換できません(この警告は互換性オプション「" + Config.GetConfigName(ConfigCode.CompatiFuncArgAutoConvert) + "」により無視できます)"; return(null); } if (tostrMethod == null) { tostrMethod = FunctionMethodCreator.GetMethodList()["TOSTR"]; } term = new FunctionMethodTerm(tostrMethod, new[] { term }); } convertedArg[i] = term; } return(new UserDefinedFunctionArgument(convertedArg, func.Arg)); }
private void Initialize_impl(Type type, string methodName, List<MethodBase> methods) { m_Type = type; m_MethodName = methodName; List<FunctionBase> functionMethod = new List<FunctionBase>(); List<FunctionBase> genericMethods = new List<FunctionBase>(); bool Params = false; //是否是不定参函数 Type ParamType = null; //不定参类型 ParameterInfo[] Parameters; //所有参数 List<Type> parameterTypes = new List<Type>(); //参数类型 List<object> defaultParameter = new List<object>(); //默认参数 int length = methods.Count; //总数量 MethodBase method = null; FunctionBase functionBase; for (int i = 0; i < length; ++i) { method = methods[i]; Params = false; ParamType = null; parameterTypes.Clear(); defaultParameter.Clear(); Parameters = method.GetParameters(); if (Util.IsExtensionMethod(method)) { for (int j = 1; j < Parameters.Length; ++j) { var par = Parameters[j]; parameterTypes.Add(par.ParameterType); if (par.DefaultValue != DBNull.Value) { defaultParameter.Add(par.DefaultValue); } Params = Util.IsParamArray(par); if (Params) ParamType = par.ParameterType.GetElementType(); } functionBase = new ExtensionMethod(method as MethodInfo, parameterTypes.ToArray(), defaultParameter.ToArray(), ParamType, Params, ""); } else { foreach (ParameterInfo par in Parameters) { parameterTypes.Add(par.ParameterType); if (par.DefaultValue != DBNull.Value) { defaultParameter.Add(par.DefaultValue); } Params = Util.IsParamArray(par); if (Params) ParamType = par.ParameterType.GetElementType(); } if (method is MethodInfo) functionBase = new FunctionMethod(method as MethodInfo, parameterTypes.ToArray(), defaultParameter.ToArray(), ParamType, Params, ""); else functionBase = new FunctionConstructor(method as ConstructorInfo, parameterTypes.ToArray(), defaultParameter.ToArray(), ParamType, Params, ""); } if (functionBase.IsGeneric) genericMethods.Add(functionBase); else functionMethod.Add(functionBase); } m_Methods = functionMethod.ToArray(); m_Count = m_Methods.Length; m_GenericMethods = genericMethods.ToArray(); m_GenericCount = m_GenericMethods.Length; }
public object Call(ScriptObject[] parameters) { if (m_Count == 0) { throw new ScriptException("找不到函数 [" + MethodName + "]"); } FunctionMethod methodInfo = null; if (m_Count == 1) { if (parameters.Length == m_Methods[0].ParameterType.Length) { methodInfo = m_Methods[0]; } } else { foreach (FunctionMethod method in m_Methods) { if (Util.CanChangeType(parameters, method.ParameterType)) { methodInfo = method; break; } } } if (methodInfo != null) { int length = methodInfo.ParameterType.Length; object[] objs = new object[length]; for (int i = 0; i < length; i++) { objs[i] = Util.ChangeType(parameters[i], methodInfo.ParameterType[i]); } return(methodInfo.Invoke(m_Object, objs)); } else { foreach (FunctionMethod method in m_Methods) { int length = method.ParameterType.Length; if (method.Params && parameters.Length >= length - 1) { bool fit = true; for (int i = 0; i < parameters.Length; ++i) { if (!Util.CanChangeType(parameters[i], i >= length - 1 ? method.ParamType : method.ParameterType[i])) { fit = false; break; } } if (fit) { object[] objs = new object[length]; for (int i = 0; i < length - 1; ++i) { objs[i] = Util.ChangeType(parameters[i], method.ParameterType[i]); } List <object> param = new List <object>(); for (int i = length - 1; i < parameters.Length; ++i) { param.Add(Util.ChangeType(parameters[i], method.ParamType)); } objs[length - 1] = param.ToArray(); return(method.Invoke(m_Object, objs)); } } } throw new ScriptException("找不到合适的函数 [" + MethodName + "]"); } }
public object Call(object obj, ScriptObject[] parameters) { if (m_Count == 0) { throw new ExecutionException(m_Script, "找不到函数 [" + MethodName + "]"); } FunctionMethod methodInfo = null; if (m_Count == 1) { methodInfo = m_Methods[0]; if (!methodInfo.IsValid) { throw new ExecutionException(m_Script, "Type[" + m_Type.ToString() + "] 找不到合适的函数 [" + MethodName + "]"); } } else { foreach (FunctionMethod method in m_Methods) { if (method.IsValid && Util.CanChangeType(parameters, method.ParameterType)) { methodInfo = method; break; } } } try { if (methodInfo != null && !methodInfo.Params) { int length = methodInfo.ParameterType.Length; object[] objs = methodInfo.Args; for (int i = 0; i < length; i++) { objs[i] = Util.ChangeType(m_Script, parameters[i], methodInfo.ParameterType[i]); } return(methodInfo.Invoke(obj, m_Type)); } else { foreach (FunctionMethod method in m_Methods) { int length = method.ParameterType.Length; if (method.Params && parameters.Length >= length - 1) { bool fit = true; for (int i = 0; i < parameters.Length; ++i) { if (!Util.CanChangeType(parameters[i], i >= length - 1 ? method.ParamType : method.ParameterType[i])) { fit = false; break; } } if (fit) { object[] objs = method.Args; for (int i = 0; i < length - 1; ++i) { objs[i] = Util.ChangeType(m_Script, parameters[i], method.ParameterType[i]); } Array array = Array.CreateInstance(method.ParamType, parameters.Length - length + 1); for (int i = length - 1; i < parameters.Length; ++i) { array.SetValue(Util.ChangeType(m_Script, parameters[i], method.ParamType), i - length + 1); } objs[length - 1] = array; return(method.Invoke(obj, m_Type)); } } } } } catch (System.Exception e) { throw new ExecutionException(m_Script, "Type[" + m_Type.ToString() + "] 调用函数出错 [" + MethodName + "] : " + e.ToString()); } throw new ExecutionException(m_Script, "Type[" + m_Type.ToString() + "] 找不到合适的函数 [" + MethodName + "]"); }
internal FunctionEmitter(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup) { Contract.Requires(function != null); Contract.Requires(methodFactory != null); Contract.Requires(functionLookup != null); this.declaration = function; this.functionLookup = functionLookup; var signature = new FunctionSignature(function.Inputs.Select(i => i.StaticRepr), function.Outputs.Select(o => o.StaticRepr)); // Determine the method signature var parameterDescriptors = new List <ParameterDescriptor>(); foreach (var input in function.Inputs) { locals.Add(input, VariableLocation.Parameter(parameterDescriptors.Count)); parameterDescriptors.Add(new ParameterDescriptor(input.StaticCliType, ParameterAttributes.None, input.Name)); } Type returnType = typeof(void); if (function.Outputs.Length == 1) { returnType = function.Outputs[0].StaticCliType; // 1 output, use return value } else if (function.Outputs.Length >= 2) { // 2 or more outputs, use 'out' parameters foreach (var output in function.Outputs) { string name = output.Name; if (locals.ContainsKey(output)) { // inout parameter, rename not to clash with input name += "$out"; } else { locals.Add(output, VariableLocation.Parameter(parameterDescriptors.Count)); } var parameterType = output.StaticCliType.MakeByRefType(); parameterDescriptors.Add(new ParameterDescriptor(parameterType, ParameterAttributes.Out, name)); } } // Create the method and get its IL generator ILGenerator ilGenerator; var methodInfo = methodFactory(function.Name, parameterDescriptors, returnType, out ilGenerator); this.method = new FunctionMethod(methodInfo, signature); cil = new ILGeneratorMethodBodyWriter(ilGenerator); cil = new MethodBodyVerifier(new MethodBodyVerificationContext { Method = methodInfo, ParameterTypes = parameterDescriptors.Select(p => p.Type).ToArray(), ReturnType = returnType, HasInitLocals = true, MaxStackSize = ushort.MaxValue }, cil); temporaryPool = new TemporaryLocalPool(cil, "$temp"); if (function.Outputs.Length == 1) { // Declare a local variable for the return value var output = function.Outputs[0]; var localIndex = cil.DeclareLocal(output.StaticCliType, output.Name); if (!function.Inputs.Contains(output)) { locals.Add(output, VariableLocation.Local(localIndex)); } } }
public void DefineAndExecuteSimpleFunctionMethod() { FunctionMethod method = new FunctionMethod((context, receiver, arguments) => "Foo"); Assert.AreEqual("Foo", method.Execute(null, null, null)); }
private void EmitCall(ImmutableArray <Variable> targets, FunctionMethod function, ImmutableArray <Variable> arguments) { var signature = function.Signature; Contract.Assert(arguments.Length == signature.Inputs.Count); Contract.Assert(targets.Length <= signature.Outputs.Count); // Prepare the eventual return value store if (signature.HasReturnValue && targets.Length == 1) { BeginEmitStore(targets[0]); } // Push the input arguments for (int i = 0; i < arguments.Length; ++i) { var argument = arguments[i]; EmitLoad(argument); EmitConvert(argument.StaticRepr, signature.Inputs[i]); } if (signature.OutParameterCount > 0) { // Push the pointers to the output arguments for (int i = 0; i < signature.Outputs.Count; ++i) { if (i < targets.Length) { var target = targets[i]; var location = GetLocation(target); if (declaration.Outputs.Contains(target) && declaration.Outputs.Length >= 2) { cil.Load(location); // Target is a ByRef parameter, so already a (managed) pointer } else { cil.LoadAddress(location); } } else { throw new NotImplementedException("Ignored outputs of a multi-output function."); } } } // Call the function var method = function.Method; if (method is System.Reflection.Emit.MethodBuilder) { // We have to supply the parameter types ourselves since MethodBodyWriter // can't call MethodBuilder.GetParameters() without receiving an exception. cil.Call(Opcode.GetDefaultCall(method), method, function.Signature.GetParameterCliTypes(), function.Signature.ReturnCliType); } else { // We're calling a builtin var builtinCilOpcodeAttribute = method.GetCustomAttribute <BuiltinCilOpcodeAttribute>(); if (builtinCilOpcodeAttribute == null) { cil.Invoke(method); } else { // Calling the builtin is equivalent to emitting a sequence of CIL opcodes, so do that instead foreach (var opcodeValue in builtinCilOpcodeAttribute.Opcodes) { var opcode = Opcode.FromValue((OpcodeValue)opcodeValue); Contract.Assert(opcode != null); cil.Instruction(opcode); } } } // Handle the return value, if any if (signature.HasReturnValue) { if (targets.Length == 1) { EmitConvert(signature.Outputs[0], targets[0].StaticRepr); EndEmitStore(targets[0]); } else { // Return value ignored. Contract.Assert(targets.Length == 0); cil.Pop(); } } }
private void Initialize_impl(Type type, string methodName, List <MethodBase> methods) { this.m_Type = type; this.m_MethodName = methodName; List <FunctionBase> list = new List <FunctionBase>(); List <FunctionBase> list2 = new List <FunctionBase>(); bool @params = false; Type paramType = null; List <Type> list3 = new List <Type>(); List <object> list4 = new List <object>(); int count = methods.Count; MethodBase method = null; for (int i = 0; i < count; i++) { FunctionBase base3; method = methods[i]; @params = false; paramType = null; list3.Clear(); list4.Clear(); ParameterInfo[] parameters = method.GetParameters(); if (Util.IsExtensionMethod(method)) { for (int j = 1; j < parameters.Length; j++) { ParameterInfo info = parameters[j]; list3.Add(info.ParameterType); if (info.DefaultValue != DBNull.Value) { list4.Add(info.DefaultValue); } @params = Util.IsParamArray(info); if (@params) { paramType = info.ParameterType.GetElementType(); } } base3 = new ExtensionMethod(method as MethodInfo, list3.ToArray(), list4.ToArray(), paramType, @params, ""); } else { foreach (ParameterInfo info2 in parameters) { list3.Add(info2.ParameterType); if (info2.DefaultValue != DBNull.Value) { list4.Add(info2.DefaultValue); } @params = Util.IsParamArray(info2); if (@params) { paramType = info2.ParameterType.GetElementType(); } } if (method is MethodInfo) { base3 = new FunctionMethod(method as MethodInfo, list3.ToArray(), list4.ToArray(), paramType, @params, ""); } else { base3 = new FunctionConstructor(method as ConstructorInfo, list3.ToArray(), list4.ToArray(), paramType, @params, ""); } } if (base3.IsGeneric) { list2.Add(base3); } else { list.Add(base3); } } this.m_Methods = list.ToArray(); this.m_Count = this.m_Methods.Length; this.m_GenericMethods = list2.ToArray(); this.m_GenericCount = this.m_GenericMethods.Length; }