public static FunctionDefinition[] CreateDefinitions(object o, Type t) { List <FunctionDefinition> methods = new List <FunctionDefinition>(); Dictionary <string, FunctionDocumentation> HelpInfo = new Dictionary <string, FunctionDocumentation>(); MethodInfo[] methodInfos = t.GetMethods(); foreach (MethodInfo methodI in methodInfos) { if (methodI.Name.StartsWith("API_")) { SprakAPI[] help = (SprakAPI[])methodI.GetCustomAttributes(typeof(SprakAPI), true); if (help.Length > 0) { //Console.WriteLine("found " + String.Join( ",", help[0].Values)); List <string> parameterHelp = new List <string>(); for (int i = 1; i < help[0].Values.Length; i++) { parameterHelp.Add(help[0].Values[i]); } string shortname = methodI.Name.Substring(4); FunctionDocumentation fd = new FunctionDocumentation(help[0].Values[0], parameterHelp.ToArray()); HelpInfo.Add(shortname, fd); } } } foreach (MethodInfo mi in methodInfos) { if (mi.Name.StartsWith("API_")) { //Console.WriteLine("parsing " + mi.Name + " return Type " + mi.ReturnType.Name); string shortname = mi.Name.Substring(4); if (mi.ReturnType.IsArray) { throw new Exception("FunctionDefinitionCreator can't handle array return value!"); } List <ReturnValueType> parameterTypes = new List <ReturnValueType>(); List <string> parameterNames = new List <string>(); List <string> parameterTypeNames = new List <string>(); foreach (ParameterInfo pi in mi.GetParameters()) { if (pi.ParameterType.IsArray) { throw new Exception("FunctionDefinitionCreator can't handle array parameters!"); } parameterNames.Add(pi.Name); parameterTypes.Add(ReturnValue.SystemTypeToReturnValueType(pi.ParameterType)); parameterTypeNames.Add(ReturnValue.SystemTypeToReturnValueType(pi.ParameterType).ToString().ToLower()); } MethodInfo lamdaMethodInfo = mi; ExternalFunctionCreator.OnFunctionCall function = (retvals) => { int i = 0; ParameterInfo[] realParamInfo = lamdaMethodInfo.GetParameters(); List <object> parameters = new List <object>(); foreach (ReturnValue r in retvals) { if (realParamInfo[i++].ParameterType == typeof(int)) { parameters.Add(Convert.ToInt32(r.Unpack())); } else { parameters.Add(r.Unpack()); } } //Console.WriteLine("supplied parameter count" + parameters.Count + " neededParamter count " + lamdaMethodInfo.GetParameters().Length); object result = lamdaMethodInfo.Invoke(o, parameters.ToArray()); if (lamdaMethodInfo.ReturnType == typeof(void)) { return(new ReturnValue(ReturnValueType.VOID)); } else { return(new ReturnValue(ReturnValue.SystemTypeToReturnValueType(lamdaMethodInfo.ReturnType), result)); } }; ReturnValueType returnValueType = ReturnValue.SystemTypeToReturnValueType(mi.ReturnType); FunctionDocumentation doc; if (HelpInfo.TryGetValue(shortname, out doc)) { methods.Add(new FunctionDefinition(returnValueType.ToString(), shortname, parameterTypeNames.ToArray(), parameterNames.ToArray(), function, doc)); } else { methods.Add(new FunctionDefinition(returnValueType.ToString(), shortname, parameterTypeNames.ToArray(), parameterNames.ToArray(), function, FunctionDocumentation.Default())); } } } return(methods.ToArray()); }
public DefaultSprakRunner(TextReader stream) { FunctionDefinition[] functionDefinitions = new FunctionDefinition[] { new FunctionDefinition("void", "print", new string[] { "string" }, new string[] { "text" }, new ExternalFunctionCreator.OnFunctionCall(print), FunctionDocumentation.Default()), new FunctionDefinition("number", "sqrt", new string[] { "number" }, new string[] { "f" }, new ExternalFunctionCreator.OnFunctionCall(sqrt), FunctionDocumentation.Default()) }; m_sprakRunner = new SprakRunner(stream, functionDefinitions); }
static List <FunctionDefinition> CreateFunctionDefinitions(object pProgramTarget, Dictionary <string, FunctionDocumentation> functionDocumentations, MethodInfo[] methodInfos) { List <FunctionDefinition> functionDefinitions = new List <FunctionDefinition>(); foreach (MethodInfo methodInfo in methodInfos) { if (!methodInfo.Name.StartsWith("API_")) { continue; } MethodInfo lambdaMethodInfo = methodInfo; // "hard copy" because of c# lambda rules string shortname = lambdaMethodInfo.Name.Substring(4); List <ReturnValueType> parameterTypes = new List <ReturnValueType> (); List <string> parameterNames = new List <string> (); List <string> parameterTypeNames = new List <string> (); foreach (ParameterInfo parameterInfo in lambdaMethodInfo.GetParameters()) { var t = ReturnValueConversions.SystemTypeToReturnValueType(parameterInfo.ParameterType); //Console.WriteLine("Registering parameter '" + parameterInfo.Name + "' (" + parameterInfo.ParameterType + ") with ReturnValueType " + t + " for function " + shortname); parameterNames.Add(parameterInfo.Name); parameterTypes.Add(t); parameterTypeNames.Add(t.ToString().ToLower()); } ExternalFunctionCreator.OnFunctionCall function = (sprakArguments => { ParameterInfo[] realParamInfo = lambdaMethodInfo.GetParameters(); if (sprakArguments.Count() != realParamInfo.Length) { throw new Error("Should call '" + shortname + "' with " + realParamInfo.Length + " argument" + (realParamInfo.Length == 1 ? "" : "s")); } int i = 0; foreach (object sprakArg in sprakArguments) { //Console.WriteLine(string.Format("Parameter {0} in function {1} is of type {2}", i, shortname, realParamInfo[i].ParameterType)); var realParamType = realParamInfo [i].ParameterType; if (sprakArg.GetType() == typeof(SortedDictionary <KeyWrapper, object>)) { sprakArguments[i] = (sprakArg as SortedDictionary <KeyWrapper, object>).Values.ToArray(); } if (sprakArg.GetType() == typeof(int)) { // YES, this is kind of a HACK (allowing definitions with int arguments, making them work like the were floats. Remove later! sprakArguments[i] = (float)sprakArg; realParamType = typeof(int); } if (acceptableTypes.Contains(realParamType)) { // OK } else { throw new Error("Can't deal with parameter " + i.ToString() + " of type " + realParamType + " in function " + shortname); } i++; } //Console.WriteLine("supplied parameter count" + parameters.Count + " neededParamter count " + lamdaMethodInfo.GetParameters().Length); object result = null; try { /* * Console.WriteLine("Will call " + shortname + " with sprak arguments:"); * int j = 0; * foreach(var a in sprakArguments) { * Console.WriteLine(" Argument " + (j++) + ": " + ReturnValueConversions.PrettyStringRepresenation(a) + " (" + a.GetType() + ")"); * } */ result = lambdaMethodInfo.Invoke(pProgramTarget, sprakArguments.ToArray()); } catch (System.Reflection.TargetInvocationException e) { //Console.WriteLine("Got an exception when calling the lambda: " + e.ToString()); //Console.WriteLine("The base exception: " + e.GetBaseException().ToString()); throw e.GetBaseException(); } // HACK if (lambdaMethodInfo.ReturnType == typeof(int)) { return((float)(int)result); } if (lambdaMethodInfo.ReturnType.IsSubclassOf(typeof(Array))) { var dictArray = new SortedDictionary <KeyWrapper, object>(); int j = 0; foreach (var o in (Array)result) { //Console.WriteLine(" - " + o.ToString()); dictArray.Add(new KeyWrapper((float)j++), o); } //Console.WriteLine("Converted object[] to SortedDictionary when returning from " + shortname + ": " + ReturnValueConversions.PrettyStringRepresenation(dictArray)); return(dictArray); } if (!acceptableTypes.Contains(lambdaMethodInfo.ReturnType)) { throw new Error("Function '" + shortname + "' can't return value of type " + lambdaMethodInfo.ReturnType.ToString()); } if (lambdaMethodInfo.ReturnType == typeof(void)) { //Console.WriteLine("Returning void from " + shortname); return(VoidType.voidType); } else { //Console.WriteLine("Returning from " + shortname + ": " + ReturnValueConversions.PrettyStringRepresenation(result)); return(result); } }); ReturnValueType returnValueType = ReturnValueConversions.SystemTypeToReturnValueType(lambdaMethodInfo.ReturnType); FunctionDocumentation doc; if (functionDocumentations.ContainsKey(shortname)) { doc = functionDocumentations [shortname]; } else { doc = FunctionDocumentation.Default(); } functionDefinitions.Add(new FunctionDefinition( returnValueType.ToString(), shortname, parameterTypeNames.ToArray(), parameterNames.ToArray(), function, // The lambda doc)); } return(functionDefinitions); }