Exemple #1
0
        private ExternalFunctionCreator AddExternalFunctions(FunctionDefinition[] functionDefinitions, AST ast)
        {
            List <FunctionDefinition> allFunctionDefinitions = new List <FunctionDefinition>();

            allFunctionDefinitions.AddRange(builtInFunctions);
            allFunctionDefinitions.AddRange(functionDefinitions);

            // HasFunction requires a reference to the SprakRunner
            FunctionDocumentation functionDoc_HasFunction =
                new FunctionDocumentation("Check if a function exists on the object", new string[] { "The name of the function" });

            allFunctionDefinitions.Add(new FunctionDefinition("bool", "HasFunction", new string[] { "string" }, new string[] { "functionName" }, new ExternalFunctionCreator.OnFunctionCall(API_hasFunction), functionDoc_HasFunction));
            FunctionDocumentation functionDoc_ListFunctions =
                new FunctionDocumentation("List all functions on the object", new string[] { });

            allFunctionDefinitions.Add(new FunctionDefinition("array", "ListFunctions", new string[] {  }, new string[] { }, new ExternalFunctionCreator.OnFunctionCall(API_listFunction), functionDoc_ListFunctions));

            ExternalFunctionCreator externalFunctionCreator = new ExternalFunctionCreator(allFunctionDefinitions.ToArray());
            AST functionList = ast.getChild(1);

            foreach (AST externalFunction in externalFunctionCreator.FunctionASTs)
            {
                functionList.addChild(externalFunction);
            }

            return(externalFunctionCreator);
        }
        static Dictionary <string, FunctionDocumentation> CreateDocumentation(MethodInfo[] methodInfos)
        {
            Dictionary <string, FunctionDocumentation> functionDocumentations = new Dictionary <string, FunctionDocumentation>();

            foreach (MethodInfo methodInfo in methodInfos)
            {
                //Log("Found method " + methodInfo.Name);
                if (methodInfo.Name.StartsWith("API_"))
                {
                    SprakAPI[] helpAttributes = (SprakAPI[])methodInfo.GetCustomAttributes(typeof(SprakAPI), true);
                    if (helpAttributes.Length > 0)
                    {
                        //Console.WriteLine("found " + String.Join( ",", help[0].Values));
                        List <string> parameterHelp = new List <string> ();
                        for (int i = 1; i < helpAttributes [0].Values.Length; i++)
                        {
                            parameterHelp.Add(helpAttributes [0].Values [i]);
                        }
                        string shortname         = methodInfo.Name.Substring(4);
                        FunctionDocumentation fd = new FunctionDocumentation(helpAttributes [0].Values [0], parameterHelp.ToArray());
                        functionDocumentations.Add(shortname, fd);
                    }
                }
            }

            return(functionDocumentations);
        }
Exemple #3
0
 public FunctionDefinition(string pReturnType, string pFunctionName, string[] pParameterTypes, string[] pParameterNames, ExternalFunctionCreator.OnFunctionCall pCallback, FunctionDocumentation pFunctionDocumentation)
 {
     returnType            = pReturnType;
     functionName          = pFunctionName;
     parameterTypes        = pParameterTypes;
     parameterNames        = pParameterNames;
     callback              = pCallback;
     functionDocumentation = pFunctionDocumentation;
 }
Exemple #4
0
 public FunctionDefinition(string pReturnType, string pFunctionName, string[] pParameterTypes, string[] pParameterNames, ExternalFunctionCreator.OnFunctionCall pCallback, FunctionDocumentation pFunctionDocumentation)
 {
     returnType = pReturnType;
     functionName = pFunctionName;
     parameterTypes = pParameterTypes;
     parameterNames = pParameterNames;
     callback = pCallback;
     functionDocumentation = pFunctionDocumentation;
 }
Exemple #5
0
        private static List <FunctionDefinition> __CreateBuiltInFunctionDefinitions()
        {
            List <FunctionDefinition> result            = new List <FunctionDefinition>();
            FunctionDocumentation     functionDoc_count =
                new FunctionDocumentation("Count the number of elements in an array", new string[] { "The array" });

            result.Add(new FunctionDefinition("number", "count", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_count), functionDoc_count));

            FunctionDocumentation functionDoc_allocate =
                new FunctionDocumentation("Create a new array with X number of elements", new string[] { "How many elements the array should hold" });

            result.Add(new FunctionDefinition("number", "allocate", new string[] { "number" }, new string[] { "X" }, new ExternalFunctionCreator.OnFunctionCall(API_allocate), functionDoc_allocate));

            FunctionDocumentation functionDoc_range =
                new FunctionDocumentation("Create a new array that contains a range of numbers", new string[] { "The start value of the range", "The end value of the range" });

            result.Add(new FunctionDefinition("number", "range", new string[] { "number", "number" }, new string[] { "min", "max" }, new ExternalFunctionCreator.OnFunctionCall(API_range), functionDoc_range));

            FunctionDocumentation functionDoc_toArray =
                new FunctionDocumentation("Convert something to an array", new string[] { "The value to convert" });

            result.Add(new FunctionDefinition("array", "toArray", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toArray), functionDoc_toArray));

            FunctionDocumentation functionDoc_toNumber =
                new FunctionDocumentation("Convert something to a number", new string[] { "The value to convert" });

            result.Add(new FunctionDefinition("number", "toNumber", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toNumber), functionDoc_toNumber));

            FunctionDocumentation functionDoc_toString =
                new FunctionDocumentation("Convert something to a string", new string[] { "The value to convert" });

            result.Add(new FunctionDefinition("string", "toString", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toString), functionDoc_toString));

            FunctionDocumentation functionDoc_toBool =
                new FunctionDocumentation("Convert something to a bool", new string[] { "The value to convert" });

            result.Add(new FunctionDefinition("bool", "toBool", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toBool), functionDoc_toBool));

            FunctionDocumentation functionDoc_getIndexes =
                new FunctionDocumentation("Create a new array that contains the indexes of another array", new string[] { "The array with indexes" });

            result.Add(new FunctionDefinition("array", "getIndexes", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_createArrayOfArrayIndexes), functionDoc_getIndexes));

            FunctionDocumentation functionDoc_removeElement =
                new FunctionDocumentation("Remove an element from an array", new string[] { "The array to remove an element from", "The position in the array to remove (starts at 0)" });

            result.Add(new FunctionDefinition("void", "removeElement", new string[] { "array", "number" }, new string[] { "array", "position" }, new ExternalFunctionCreator.OnFunctionCall(API_removeElement), functionDoc_removeElement));

            FunctionDocumentation functionDoc_type =
                new FunctionDocumentation("Get the type of something (returns a string)", new string[] { "The value to get the type of" });

            result.Add(new FunctionDefinition("string", "type", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_type), functionDoc_type));
            return(result);
        }
Exemple #6
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);
        }
Exemple #7
0
        private static List<FunctionDefinition> __CreateBuiltInFunctionDefinitions()
        {
            List<FunctionDefinition> result = new List<FunctionDefinition>();
            FunctionDocumentation functionDoc_count =
            new FunctionDocumentation("Count the number of elements in an array", new string[] { "The array" });
            result.Add(new FunctionDefinition("number", "count", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_count), functionDoc_count));

            FunctionDocumentation functionDoc_allocate =
                new FunctionDocumentation("Create a new array with X number of elements", new string[] { "How many elements the array should hold" });
            result.Add(new FunctionDefinition("number", "allocate", new string[] { "number" }, new string[] { "X" }, new ExternalFunctionCreator.OnFunctionCall(API_allocate), functionDoc_allocate));

            FunctionDocumentation functionDoc_range =
                new FunctionDocumentation("Create a new array that contains a range of numbers", new string[] { "The start value of the range", "The end value of the range" });
            result.Add(new FunctionDefinition("number", "range", new string[] { "number", "number" }, new string[] { "min", "max" }, new ExternalFunctionCreator.OnFunctionCall(API_range), functionDoc_range));

            FunctionDocumentation functionDoc_toArray =
                new FunctionDocumentation("Convert something to an array", new string[] { "The value to convert" });
            result.Add(new FunctionDefinition("array", "toArray", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toArray), functionDoc_toArray));

            FunctionDocumentation functionDoc_toNumber =
                new FunctionDocumentation("Convert something to a number", new string[] { "The value to convert" });
            result.Add(new FunctionDefinition("number", "toNumber", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toNumber), functionDoc_toNumber));

            FunctionDocumentation functionDoc_toString =
                new FunctionDocumentation("Convert something to a string", new string[] { "The value to convert" });
            result.Add(new FunctionDefinition("string", "toString", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toString), functionDoc_toString));

            FunctionDocumentation functionDoc_toBool =
                new FunctionDocumentation("Convert something to a bool", new string[] { "The value to convert" });
            result.Add(new FunctionDefinition("bool", "toBool", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toBool), functionDoc_toBool));

            FunctionDocumentation functionDoc_getIndexes =
                new FunctionDocumentation("Create a new array that contains the indexes of another array", new string[] { "The array with indexes" });
            result.Add(new FunctionDefinition("array", "getIndexes", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_createArrayOfArrayIndexes), functionDoc_getIndexes));

            FunctionDocumentation functionDoc_removeElement =
                new FunctionDocumentation("Remove an element from an array", new string[] { "The array to remove an element from", "The position in the array to remove (starts at 0)" });
            result.Add(new FunctionDefinition("void", "removeElement", new string[] { "array", "number" }, new string[] { "array", "position" }, new ExternalFunctionCreator.OnFunctionCall(API_removeElement), functionDoc_removeElement));

            FunctionDocumentation functionDoc_type =
                new FunctionDocumentation("Get the type of something (returns a string)", new string[] { "The value to get the type of" });
            result.Add(new FunctionDefinition("string", "type", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_type), functionDoc_type));
            return result;
        }
Exemple #8
0
        private static List <FunctionDefinition> __CreateBuiltInFunctionDefinitions()
        {
            List <FunctionDefinition> result            = new List <FunctionDefinition>();
            FunctionDocumentation     functionDoc_Count =
                new FunctionDocumentation("Count the number of elements in an array", new string[] { "The array" });

            result.Add(new FunctionDefinition("number", "Count", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_count), functionDoc_Count));

            // Need an add-function???!
//			FunctionDocumentation functionDoc_add =
//				new FunctionDocumentation("Add an element to the end of the array", new string[] { "The element" });
//			result.Add(new FunctionDefinition("array", "add", new string[] { "var" }, new string[] { "element" }, new ExternalFunctionCreator.OnFunctionCall(API_add), functionDoc_add));

//            FunctionDocumentation functionDoc_allocate =
//                new FunctionDocumentation("Create a new array with X number of elements", new string[] { "How many elements the array should hold" });
//            result.Add(new FunctionDefinition("number", "allocate", new string[] { "number" }, new string[] { "X" }, new ExternalFunctionCreator.OnFunctionCall(API_allocate), functionDoc_allocate));

            FunctionDocumentation functionDoc_Range =
                new FunctionDocumentation("Create a range of numbers from 'min' to (and including) 'max'", new string[] { "The start value of the range", "The end value of the range" });

            result.Add(new FunctionDefinition("number", "Range", new string[] { "number", "number" }, new string[] { "min", "max" }, new ExternalFunctionCreator.OnFunctionCall(API_range), functionDoc_Range));

//            FunctionDocumentation functionDoc_toArray =
//                new FunctionDocumentation("Convert something to an array", new string[] { "The value to convert" });
//            result.Add(new FunctionDefinition("array", "toArray", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toArray), functionDoc_toArray));
//
//            FunctionDocumentation functionDoc_toNumber =
//                new FunctionDocumentation("Convert something to a number", new string[] { "The value to convert" });
//            result.Add(new FunctionDefinition("number", "toNumber", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toNumber), functionDoc_toNumber));
//
//            FunctionDocumentation functionDoc_toString =
//                new FunctionDocumentation("Convert something to a string", new string[] { "The value to convert" });
//            result.Add(new FunctionDefinition("string", "toString", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toString), functionDoc_toString));
//
//            FunctionDocumentation functionDoc_toBool =
//                new FunctionDocumentation("Convert something to a bool", new string[] { "The value to convert" });
//            result.Add(new FunctionDefinition("bool", "toBool", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toBool), functionDoc_toBool));

            FunctionDocumentation functionDoc_GetIndexes =
                new FunctionDocumentation("Create a new array that contains the indexes of another array", new string[] { "The array with indexes" });

            result.Add(new FunctionDefinition("array", "GetIndexes", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_createArrayOrRangeOfIndexes), functionDoc_GetIndexes));

            FunctionDocumentation functionDoc_RemoveElement =
                new FunctionDocumentation("Remove an element from an array", new string[] { "The array to remove an element from", "The index in the array to remove" });

            result.Add(new FunctionDefinition("void", "Remove", new string[] { "array", "number" }, new string[] { "array", "position" }, new ExternalFunctionCreator.OnFunctionCall(API_removeElement), functionDoc_RemoveElement));

            FunctionDocumentation functionDoc_RemoveAllElements =
                new FunctionDocumentation("Remove an element from an array", new string[] { "The array to remove an element from", "The index in the array to remove" });

            result.Add(new FunctionDefinition("void", "RemoveAll", new string[] { "array" }, new string[] { "array" }, new ExternalFunctionCreator.OnFunctionCall(API_removeAllElements), functionDoc_RemoveAllElements));

            FunctionDocumentation functionDoc_HasIndex =
                new FunctionDocumentation("Check if an index is in the array", new string[] { "The array to check in", "The index to check for in the array" });

            result.Add(new FunctionDefinition("bool", "HasIndex", new string[] { "array", "var" }, new string[] { "array", "key" }, new ExternalFunctionCreator.OnFunctionCall(API_hasKey), functionDoc_HasIndex));

            FunctionDocumentation functionDoc_Append =
                new FunctionDocumentation("Add an element to the end of an array", new string[] { "The array to add an element to", "The element to add" });

            result.Add(new FunctionDefinition("void", "Append", new string[] { "array", "var" }, new string[] { "array", "elem" }, new ExternalFunctionCreator.OnFunctionCall(API_append), functionDoc_Append));

#if TYPE_FUNCTION
            FunctionDocumentation functionDoc_type =
                new FunctionDocumentation("Get the type of something (returns a string)", new string[] { "The value to get the type of" });
            result.Add(new FunctionDefinition("string", "Type", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_type), functionDoc_type));
#endif

            FunctionDocumentation functionDoc_Round =
                new FunctionDocumentation("Round a number to the nearest integer", new string[] { "The number to round" });
            result.Add(new FunctionDefinition("number", "Round", new string[] { "var" }, new string[] { "x" }, new ExternalFunctionCreator.OnFunctionCall(API_round), functionDoc_Round));

            FunctionDocumentation functionDoc_Int =
                new FunctionDocumentation("Remove the decimals of a float", new string[] { "The number to convert to an integer" });
            result.Add(new FunctionDefinition("number", "Int", new string[] { "var" }, new string[] { "x" }, new ExternalFunctionCreator.OnFunctionCall(API_int), functionDoc_Int));

            FunctionDocumentation functionDoc_Mod =
                new FunctionDocumentation("Get the remainder of x / y", new string[] { "x", "y" });
            result.Add(new FunctionDefinition("number", "Mod", new string[] { "var", "var" }, new string[] { "x", "y" }, new ExternalFunctionCreator.OnFunctionCall(API_mod), functionDoc_Mod));

            return(result);
        }
        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());
        }
Exemple #10
0
        private static List<FunctionDefinition> __CreateBuiltInFunctionDefinitions()
        {
            List<FunctionDefinition> result = new List<FunctionDefinition>();
            FunctionDocumentation functionDoc_Count =
            new FunctionDocumentation("Count the number of elements in an array", new string[] { "The array" });
            result.Add(new FunctionDefinition("number", "Count", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_count), functionDoc_Count));

            // Need an add-function???!
            //			FunctionDocumentation functionDoc_add =
            //				new FunctionDocumentation("Add an element to the end of the array", new string[] { "The element" });
            //			result.Add(new FunctionDefinition("array", "add", new string[] { "var" }, new string[] { "element" }, new ExternalFunctionCreator.OnFunctionCall(API_add), functionDoc_add));

            //            FunctionDocumentation functionDoc_allocate =
            //                new FunctionDocumentation("Create a new array with X number of elements", new string[] { "How many elements the array should hold" });
            //            result.Add(new FunctionDefinition("number", "allocate", new string[] { "number" }, new string[] { "X" }, new ExternalFunctionCreator.OnFunctionCall(API_allocate), functionDoc_allocate));

            FunctionDocumentation functionDoc_Range =
                new FunctionDocumentation("Create a range of numbers from 'min' to (and including) 'max'", new string[] { "The start value of the range", "The end value of the range" });
            result.Add(new FunctionDefinition("number", "Range", new string[] { "number", "number" }, new string[] { "min", "max" }, new ExternalFunctionCreator.OnFunctionCall(API_range), functionDoc_Range));

            //            FunctionDocumentation functionDoc_toArray =
            //                new FunctionDocumentation("Convert something to an array", new string[] { "The value to convert" });
            //            result.Add(new FunctionDefinition("array", "toArray", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toArray), functionDoc_toArray));
            //
            //            FunctionDocumentation functionDoc_toNumber =
            //                new FunctionDocumentation("Convert something to a number", new string[] { "The value to convert" });
            //            result.Add(new FunctionDefinition("number", "toNumber", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toNumber), functionDoc_toNumber));
            //
            //            FunctionDocumentation functionDoc_toString =
            //                new FunctionDocumentation("Convert something to a string", new string[] { "The value to convert" });
            //            result.Add(new FunctionDefinition("string", "toString", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toString), functionDoc_toString));
            //
            //            FunctionDocumentation functionDoc_toBool =
            //                new FunctionDocumentation("Convert something to a bool", new string[] { "The value to convert" });
            //            result.Add(new FunctionDefinition("bool", "toBool", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_toBool), functionDoc_toBool));

            FunctionDocumentation functionDoc_GetIndexes =
                new FunctionDocumentation("Create a new array that contains the indexes of another array", new string[] { "The array with indexes" });
            result.Add(new FunctionDefinition("array", "GetIndexes", new string[] { "array" }, new string[] { "a" }, new ExternalFunctionCreator.OnFunctionCall(API_createArrayOrRangeOfIndexes), functionDoc_GetIndexes));

            FunctionDocumentation functionDoc_RemoveElement =
                new FunctionDocumentation("Remove an element from an array", new string[] { "The array to remove an element from", "The index in the array to remove" });
            result.Add(new FunctionDefinition("void", "Remove", new string[] { "array", "number" }, new string[] { "array", "position" }, new ExternalFunctionCreator.OnFunctionCall(API_removeElement), functionDoc_RemoveElement));

            FunctionDocumentation functionDoc_RemoveAllElements =
                new FunctionDocumentation("Remove an element from an array", new string[] { "The array to remove an element from", "The index in the array to remove" });
            result.Add(new FunctionDefinition("void", "RemoveAll", new string[] { "array" }, new string[] { "array" }, new ExternalFunctionCreator.OnFunctionCall(API_removeAllElements), functionDoc_RemoveAllElements));

            FunctionDocumentation functionDoc_HasIndex =
                new FunctionDocumentation("Check if an index is in the array", new string[] { "The array to check in", "The index to check for in the array" });
            result.Add(new FunctionDefinition("bool", "HasIndex", new string[] { "array", "var" }, new string[] { "array", "key" }, new ExternalFunctionCreator.OnFunctionCall(API_hasKey), functionDoc_HasIndex));

            FunctionDocumentation functionDoc_Append =
                new FunctionDocumentation("Add an element to the end of an array", new string[] { "The array to add an element to", "The element to add" });
            result.Add(new FunctionDefinition("void", "Append", new string[] { "array", "var" }, new string[] { "array", "elem" }, new ExternalFunctionCreator.OnFunctionCall(API_append), functionDoc_Append));

            #if TYPE_FUNCTION
            FunctionDocumentation functionDoc_type =
                new FunctionDocumentation("Get the type of something (returns a string)", new string[] { "The value to get the type of" });
            result.Add(new FunctionDefinition("string", "type", new string[] { "var" }, new string[] { "value" }, new ExternalFunctionCreator.OnFunctionCall(API_type), functionDoc_type));
            #endif

            FunctionDocumentation functionDoc_Round =
                new FunctionDocumentation("Round a number to the nearest integer", new string[] { "The number to round" });
            result.Add(new FunctionDefinition("number", "Round", new string[] { "var" }, new string[] { "x" }, new ExternalFunctionCreator.OnFunctionCall(API_round), functionDoc_Round));

            FunctionDocumentation functionDoc_Int =
                new FunctionDocumentation("Remove the decimals of a float", new string[] { "The number to convert to an integer" });
            result.Add(new FunctionDefinition("number", "Int", new string[] { "var" }, new string[] { "x" }, new ExternalFunctionCreator.OnFunctionCall(API_int), functionDoc_Int));

            FunctionDocumentation functionDoc_Mod =
                new FunctionDocumentation("Remove the decimals of a float", new string[] { "Get the remainder of x / y" });
            result.Add(new FunctionDefinition("number", "Mod", new string[] { "var", "var" }, new string[] { "x", "y" }, new ExternalFunctionCreator.OnFunctionCall(API_mod), functionDoc_Mod));

            return result;
        }
        private ExternalFunctionCreator AddExternalFunctions(FunctionDefinition[] functionDefinitions, AST ast)
        {
			List<FunctionDefinition> allFunctionDefinitions = new List<FunctionDefinition>();
            allFunctionDefinitions.AddRange(builtInFunctions);
            allFunctionDefinitions.AddRange(functionDefinitions);
            
			// HasFunction requires a reference to the SprakRunner
			FunctionDocumentation functionDoc_HasFunction =
				new FunctionDocumentation("Check if a function exists on the object", new string[] { "The name of the function" });
			allFunctionDefinitions.Add(new FunctionDefinition("bool", "HasFunction", new string[] { "string" }, new string[] { "functionName" }, new ExternalFunctionCreator.OnFunctionCall(API_hasFunction), functionDoc_HasFunction));

			ExternalFunctionCreator externalFunctionCreator = new ExternalFunctionCreator(allFunctionDefinitions.ToArray());
            AST functionList = ast.getChild(1);

            foreach (AST externalFunction in externalFunctionCreator.FunctionASTs)
            {
                functionList.addChild(externalFunction);
            }

            return externalFunctionCreator;
        }
        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();
        }
        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);
        }