static void Main(string[] args) { // Add custom function to Functal. FunctalResources.CreateFunctionGroup("IsLessThanFive"); FunctalResources.AddFunctionToGroup("IsLessThanFive", new FnFunction_IsLessThanFive()); FunctalResources.AddFunctionToGroup("IsLessThanFive", new FnFunction_IsLessThanFiveChars()); FunctalCompiler compiler = new FunctalCompiler(); Console.WriteLine( compiler.Compile <string>( "\"First Result: \" + ToString(IsLessThanFive(3))", null ).Execute() ); Console.WriteLine( compiler.Compile <string>( "\"Second Result: \" + ToString(IsLessThanFive(7))", null ).Execute() ); Console.WriteLine( compiler.Compile <string>( "\"Third Result: \" + ToString(IsLessThanFive(\"Definitely More Than Five Characters\"))", null ).Execute() ); Console.ReadKey(); }
/// <summary> /// Creates an FnObject which contains the function pointer that match the specified arguments /// </summary> /// <param name="arguments">The function arguments to use</param> /// <param name="ghostArguments">Any ghost arguments you want to add to the FnObject</param> /// <returns></returns> public FnObject CreateObjectWithPointer(List <FnObject> arguments, Dictionary <String, FnObject> parameters, FnVariable <Boolean> isPreExecute) { //try to find an exact match for (int i = 0; i < FunctionPointers.Count; i++) { Type[] currentFunctionsTypeArray = FunctionPointers[i].GetFunctionTypeArray(); //if we find a potential overload match if (currentFunctionsTypeArray.Length == arguments.Count) { for (int j = 0; j < currentFunctionsTypeArray.Length; j++) { //if we find a mismatch if (currentFunctionsTypeArray[j] != arguments[j].GetWrappedObjectType()) { break; } //else if we get to the end of the list with no mistakes else if (j == currentFunctionsTypeArray.Length - 1) { return(FunctionPointers[i].CreateObjectWithPointer(arguments, parameters, isPreExecute)); } } } } //we didn't get an exact match, now iterate through each overload and find the least ambiguous one (this will only happen for numeric data types) List <Int32> Ambiguity = new List <Int32>(FunctionPointers.Count); for (int i = 0; i < FunctionPointers.Count; i++) { Type[] currentFunctionsTypeArray = FunctionPointers[i].GetFunctionTypeArray(); if (currentFunctionsTypeArray.Length == arguments.Count) { //add new count to the ambiguity list and increment it with each type and argument analysed Ambiguity.Add(0); for (int j = 0; j < currentFunctionsTypeArray.Length; j++) { //if we have two conflicting data types if (currentFunctionsTypeArray[j] != arguments[j].GetWrappedObjectType()) { Int32 TypeAmbiguity = FunctalResources.GetAmbiguityScore(currentFunctionsTypeArray[j], arguments[j].GetWrappedObjectType()); if (TypeAmbiguity <= 0) //if this is 0, then our two types are on the same level of ambiguity and so are unable to up cast. If it is less than zero, than the one to cast to is of a lower data type, so up casting isn't possible { Ambiguity[i] = -1; break; } else { Ambiguity[i] += TypeAmbiguity; } } } } else { Ambiguity.Add(-1); } } //we now have a list of the ambiguities for all the function overloads, we now need to find the lowest //non negative ambiguity score, and make sure there are no others which have it. Int32 LowestScoreIndex = -1; Int32 LowestScoreCount = 1; for (int i = 0; i < Ambiguity.Count; i++) { if (Ambiguity[i] >= 0) { if (LowestScoreIndex == -1) { LowestScoreIndex = i; } else { if (Ambiguity[i] < Ambiguity[LowestScoreIndex]) { LowestScoreIndex = i; LowestScoreCount = 1; } else if (Ambiguity[i] == Ambiguity[LowestScoreIndex]) { LowestScoreCount += 1; } } } } if (LowestScoreIndex >= 0 && LowestScoreCount == 1) { // Now we iterate through the list of arguments, and everywhere we have a type mismatch, we replace the argument // with an implicit cast of the argument to the correct data type for (int i = 0; i < arguments.Count; i++) { if (FunctionPointers[LowestScoreIndex].GetFunctionTypeArray()[i] != arguments[i].GetWrappedObjectType()) { arguments[i] = FunctalResources.ImplicitConversionSwitches[FunctionPointers[LowestScoreIndex].GetFunctionTypeArray()[i]].CreateObjectWithPointer(new List <FnObject> { arguments[i] }, parameters, isPreExecute); //ExecutionList.Add(FnScriptResources.ImplicitConversionSwitches[typeof(T)].CreateObjectWithPointer(new List<FnObject> { ExecutionList.Last() }, GhostArguments)); } } return(FunctionPointers[LowestScoreIndex].CreateObjectWithPointer(arguments, parameters, isPreExecute)); } else if (LowestScoreIndex >= 0 && LowestScoreCount > 1) { throw new ArgumentException( "The function call is too ambiguous to resolve, use more specific argument types", arguments.ToString() ); } else { throw new ArgumentException( "The function has no overloads which match the specified arguments", arguments.ToString() ); } }
public FnObject CreateObjectWithPointer( List <FnObject> arguments, Dictionary <string, FnObject> parameters, FnVariable <bool> isPreExecute) { for (int index1 = 0; index1 < this.FunctionPointers.Count; ++index1) { Type[] functionTypeArray = this.FunctionPointers[index1].GetFunctionTypeArray(); if (functionTypeArray.Length == arguments.Count) { for (int index2 = 0; index2 < functionTypeArray.Length && !(functionTypeArray[index2] != arguments[index2].GetWrappedObjectType()); ++index2) { if (index2 == functionTypeArray.Length - 1) { return(this.FunctionPointers[index1].CreateObjectWithPointer(arguments, parameters, isPreExecute)); } } } } List <int> intList = new List <int>(this.FunctionPointers.Count); for (int index1 = 0; index1 < this.FunctionPointers.Count; ++index1) { Type[] functionTypeArray = this.FunctionPointers[index1].GetFunctionTypeArray(); if (functionTypeArray.Length == arguments.Count) { intList.Add(0); for (int index2 = 0; index2 < functionTypeArray.Length; ++index2) { if (functionTypeArray[index2] != arguments[index2].GetWrappedObjectType()) { int ambiguityScore = FunctalResources.GetAmbiguityScore(functionTypeArray[index2], arguments[index2].GetWrappedObjectType()); if (ambiguityScore <= 0) { intList[index1] = -1; break; } intList[index1] += ambiguityScore; } } } else { intList.Add(-1); } } int index3 = -1; int num = 1; for (int index1 = 0; index1 < intList.Count; ++index1) { if (intList[index1] >= 0) { if (index3 == -1) { index3 = index1; } else if (intList[index1] < intList[index3]) { index3 = index1; num = 1; } else if (intList[index1] == intList[index3]) { ++num; } } } if (index3 >= 0 && num == 1) { for (int index1 = 0; index1 < arguments.Count; ++index1) { if (this.FunctionPointers[index3].GetFunctionTypeArray()[index1] != arguments[index1].GetWrappedObjectType()) { List <FnObject> fnObjectList = arguments; int index2 = index1; FnFunctionGroup conversionSwitch = FunctalResources.ImplicitConversionSwitches[this.FunctionPointers[index3].GetFunctionTypeArray()[index1]]; List <FnObject> arguments1 = new List <FnObject>(); arguments1.Add(arguments[index1]); Dictionary <string, FnObject> parameters1 = parameters; FnVariable <bool> isPreExecute1 = isPreExecute; FnObject objectWithPointer = conversionSwitch.CreateObjectWithPointer(arguments1, parameters1, isPreExecute1); fnObjectList[index2] = objectWithPointer; } } return(this.FunctionPointers[index3].CreateObjectWithPointer(arguments, parameters, isPreExecute)); } if (index3 >= 0 && num > 1) { throw new ArgumentException("The function call is too ambiguous to resolve, use more specific argument types", arguments.ToString()); } throw new ArgumentException("The function has no overloads which match the specified arguments", arguments.ToString()); }