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());
        }
示例#2
0
        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);
        }