From 520cd1ffccfd6733834c7795557a2919ac1a4d75 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Wed, 5 Dec 2018 17:20:28 +0100 Subject: [PATCH] Initial support for generic funcs --- .../ScriptFunction/ScriptFunction.cs | 2 +- .../ScriptFunction/ScriptGenericFunction.cs | 31 ++++++++++++++++ Upsilon/BaseTypes/TypeConversion.cs | 17 ++++++++- .../BaseTypes/UserData/UserDataTypeHandler.cs | 1 + .../InternalFunctionVariableSymbol.cs | 2 +- Upsilon/StandardLibraries/StaticScope.cs | 36 ++++++++++++++++++- Upsilon/Upsilon.csproj | 3 ++ 7 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 Upsilon/BaseTypes/ScriptFunction/ScriptGenericFunction.cs diff --git a/Upsilon/BaseTypes/ScriptFunction/ScriptFunction.cs b/Upsilon/BaseTypes/ScriptFunction/ScriptFunction.cs index d73063f..3229361 100644 --- a/Upsilon/BaseTypes/ScriptFunction/ScriptFunction.cs +++ b/Upsilon/BaseTypes/ScriptFunction/ScriptFunction.cs @@ -2,7 +2,7 @@ using Upsilon.Evaluator; namespace Upsilon.BaseTypes.ScriptFunction { - internal abstract class ScriptFunction : ScriptType + public abstract class ScriptFunction : ScriptType { public override Type Type => Type.Function; public override object ToCSharpObject() diff --git a/Upsilon/BaseTypes/ScriptFunction/ScriptGenericFunction.cs b/Upsilon/BaseTypes/ScriptFunction/ScriptGenericFunction.cs new file mode 100644 index 0000000..8266473 --- /dev/null +++ b/Upsilon/BaseTypes/ScriptFunction/ScriptGenericFunction.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Upsilon.Evaluator; + +namespace Upsilon.BaseTypes.ScriptFunction +{ + public class ScriptGenericFunction : ScriptFunction + { + public ScriptGenericFunction(Func> function) + { + Function = function; + } + + public ScriptGenericFunction(object o) + { + var type = o.GetType(); + var generics = type.GetGenericArguments(); + Function.GetMethodInfo(); + } + + public Func> Function { get; } + + public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script, + EvaluationScope scope) + { + return Function.Invoke(variables.Select(x => x.ToCSharpObject())).ToScriptType(); + } + } +} \ No newline at end of file diff --git a/Upsilon/BaseTypes/TypeConversion.cs b/Upsilon/BaseTypes/TypeConversion.cs index 4bb6b10..76af299 100644 --- a/Upsilon/BaseTypes/TypeConversion.cs +++ b/Upsilon/BaseTypes/TypeConversion.cs @@ -1,6 +1,8 @@ using System; using System.Collections; +using System.Reflection; using Upsilon.BaseTypes.Number; +using Upsilon.BaseTypes.ScriptFunction; using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.BaseTypes.UserData; @@ -42,6 +44,18 @@ namespace Upsilon.BaseTypes { return new DictionaryUserData(dic); } + if (o.GetType().IsGenericType) + { + var generic = o.GetType().GetGenericTypeDefinition(); + if (generic.FullName != null && generic.FullName.Contains("System.Func")) + { + var function = (Delegate)o; + var method = new UserDataMethod(function.GetMethodInfo()); + return new ScriptMethodInfoFunction(method, null, false, + false, false); + } + } + return new GenericUserData(o); } @@ -102,7 +116,8 @@ namespace Upsilon.BaseTypes return Type.Nil; if (t == typeof(ScriptType)) return Type.Unknown; - + if (typeof(IEnumerable).IsAssignableFrom(t)) + return Type.Table | Type.Function; return Type.UserData; } diff --git a/Upsilon/BaseTypes/UserData/UserDataTypeHandler.cs b/Upsilon/BaseTypes/UserData/UserDataTypeHandler.cs index 128ef98..d86a98d 100644 --- a/Upsilon/BaseTypes/UserData/UserDataTypeHandler.cs +++ b/Upsilon/BaseTypes/UserData/UserDataTypeHandler.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Upsilon.BoundTypes; diff --git a/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs b/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs index 3d76eff..fac4d04 100644 --- a/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs +++ b/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs @@ -50,7 +50,7 @@ namespace Upsilon.Binder.VariableSymbols if (!functionParameter.ValidTypes.HasFlag(callingParameter.Type)) { return (false, - $"Unexpected variable passed to internal function '{functionParameter}'." + + $"Unexpected variable passed to internal function at position {i + 1}. " + $"Expected one of the following: {functionParameter.ValidTypes.ToString()}, got: '{callingParameter.Type}'", callingParameter); } diff --git a/Upsilon/StandardLibraries/StaticScope.cs b/Upsilon/StandardLibraries/StaticScope.cs index 289cae2..50c66dc 100644 --- a/Upsilon/StandardLibraries/StaticScope.cs +++ b/Upsilon/StandardLibraries/StaticScope.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Upsilon.BaseTypes; using Upsilon.BaseTypes.Number; @@ -75,11 +76,44 @@ namespace Upsilon.StandardLibraries { var luaVariable = value.ToScriptType(); var ubDef = BoundTypeHandler.GetTypeDefinition(value.GetType()); - var varSymbol = new FunctionParameterSymbol(name, ubDef); + VariableSymbol varSymbol = null; + if (ubDef != null) + { + varSymbol = new FunctionParameterSymbol(name, ubDef); + } + else + { + var type = value.GetType(); + if (type.IsGenericType) + { + var generic = type.GetGenericTypeDefinition(); + if (generic.FullName != null && generic.FullName.Contains("System.Func")) + { + varSymbol = BuildFunctionVariableSymbol(name, type); + } + } + if (varSymbol == null) + throw new Exception("Unknown type: " + type); + + } BoundScope.AssignToNearest(varSymbol); Scope.AssignToNearest(varSymbol, luaVariable); } + private static VariableSymbol BuildFunctionVariableSymbol(string name, System.Type type) + { + var genericParameters = type.GetGenericArguments(); + var parameters = new List(); + for (var i = 0; i < genericParameters.Length - 1; i++) + { + var t = genericParameters[i].GetScriptType(); + parameters.Add(new InternalFunctionVariableSymbol.InternalFunctionParameter(t, false)); + } + + var result = genericParameters[parameters.Count - 1].GetScriptType(); + return new InternalFunctionVariableSymbol(name, true, result, parameters.ToArray()); + } + private static Type DeriveValidTypes(System.Type type) { if (type == typeof(ScriptString)) diff --git a/Upsilon/Upsilon.csproj b/Upsilon/Upsilon.csproj index 4f3fa9d..0adac55 100644 --- a/Upsilon/Upsilon.csproj +++ b/Upsilon/Upsilon.csproj @@ -5,6 +5,9 @@ + + ..\..\..\..\..\..\usr\share\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.CSharp.dll + ..\..\..\..\..\usr\share\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll