Fixes to the Type Binder and static method handling

This commit is contained in:
Deukhoofd 2018-12-09 22:12:03 +01:00
parent 3d9b7a53e9
commit 5646ff1da1
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
3 changed files with 130 additions and 104 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Linq;
using System.Reflection; using System.Reflection;
using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptFunction; using Upsilon.BaseTypes.ScriptFunction;
@ -71,6 +72,11 @@ namespace Upsilon.BaseTypes
} }
} }
if (o is IEnumerable enumerable)
{
return new ListUserData(enumerable.Cast<object>().ToList());
}
return new GenericUserData(o); return new GenericUserData(o);
} }

View File

@ -25,78 +25,7 @@ namespace Upsilon.BaseTypes.UserData
foreach (var match in matches) foreach (var match in matches)
{ {
var validMatch = true; if (IsValidMatch(match, ref args))
var parameters = match.GetParameters();
for (var i = 0; i < parameters.Length; i++)
{
var matchParameter = parameters[i];
if (args.Length <= i)
{
if (matchParameter.IsOptional)
return match;
validMatch = false;
break;
}
var argument = args[i];
var argumentType = argument.GetType();
var typeCode = System.Type.GetTypeCode(matchParameter.ParameterType);
switch (typeCode)
{
case TypeCode.Boolean:
if (argument is ScriptBoolean b)
{
continue;
}
break;
case TypeCode.Char:
case TypeCode.String:
if (argument is ScriptString s)
{
continue;
}
break;
case TypeCode.Byte:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
if (argument is ScriptNumber numeric)
{
continue;
}
break;
case TypeCode.Object:
continue;
}
if (!typeof(ScriptType).IsAssignableFrom(matchParameter.ParameterType) &&
argument is IUserData ud)
{
var csharpType = ud.GetCSharpType();
if (matchParameter.ParameterType.IsAssignableFrom(csharpType))
continue;
}
if (argumentType == typeof(ScriptNull))
{
continue;
}
if (!matchParameter.ParameterType.IsAssignableFrom(argumentType))
{
validMatch = false;
break;
}
}
if (validMatch)
return match; return match;
} }
@ -104,6 +33,83 @@ namespace Upsilon.BaseTypes.UserData
return null; return null;
} }
public bool IsValidMatch(MethodBase match, ref object[] args)
{
var validMatch = true;
var parameters = match.GetParameters();
for (var i = 0; i < parameters.Length; i++)
{
var matchParameter = parameters[i];
if (args.Length <= i)
{
if (matchParameter.IsOptional)
return true;
return false;
}
var argument = args[i];
var argumentType = argument.GetType();
var typeCode = System.Type.GetTypeCode(matchParameter.ParameterType);
switch (typeCode)
{
case TypeCode.Boolean:
if (argument is ScriptBoolean b)
{
continue;
}
break;
case TypeCode.Char:
case TypeCode.String:
if (argument is ScriptString s)
{
continue;
}
break;
case TypeCode.Byte:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
if (argument is ScriptNumber numeric)
{
continue;
}
break;
case TypeCode.Object:
continue;
}
if (!typeof(ScriptType).IsAssignableFrom(matchParameter.ParameterType) &&
argument is IUserData ud)
{
var csharpType = ud.GetCSharpType();
if (matchParameter.ParameterType.IsAssignableFrom(csharpType))
continue;
}
if (argumentType == typeof(ScriptNull))
{
continue;
}
if (!matchParameter.ParameterType.IsAssignableFrom(argumentType))
{
return false;
}
}
return validMatch;
}
public override object ChangeType(object value, System.Type type, CultureInfo culture) public override object ChangeType(object value, System.Type type, CultureInfo culture)
{ {
if (type.IsInstanceOfType(value)) if (type.IsInstanceOfType(value))
@ -185,7 +191,40 @@ namespace Upsilon.BaseTypes.UserData
if (value is ListUserData d) if (value is ListUserData d)
return d.List; return d.List;
if (value is ScriptTable.ScriptTable table) if (value is ScriptTable.ScriptTable table)
return table.EvaluationScope.Variables.Select(x => x.Value.ToCSharpObject()); {
var generics = type.GetGenericArguments();
if (generics.Length > 0)
{
var l1 = typeof(List<>);
var requiredListType = l1.MakeGenericType(generics[0]);
var list = (IList)Activator.CreateInstance(requiredListType);
foreach (var variable in table.EvaluationScope.Variables)
{
list.Add(variable.Value.ToCSharpObject());
}
return list;
}
return table.EvaluationScope.Variables.Select(x => x.Value.ToCSharpObject()).ToArray();
}
}
if (typeof(IEnumerable).IsAssignableFrom(type))
{
if (value is ListUserData d)
return d.List;
if (value is ScriptTable.ScriptTable table)
{
var generics = type.GetGenericArguments();
var l1 = typeof(List<>);
var requiredListType = l1.MakeGenericType(generics[0]);
var list = (IList)Activator.CreateInstance(requiredListType);
foreach (var variable in table.EvaluationScope.Variables)
{
list.Add(variable.Value.ToCSharpObject());
}
return list;
}
} }
var isScriptTypeRequired = typeof(ScriptType).IsAssignableFrom(type); var isScriptTypeRequired = typeof(ScriptType).IsAssignableFrom(type);

View File

@ -1,5 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Globalization;
using System.Reflection; using System.Reflection;
using Upsilon.Evaluator; using Upsilon.Evaluator;
using Upsilon.StandardLibraries; using Upsilon.StandardLibraries;
@ -73,43 +73,24 @@ namespace Upsilon.BaseTypes.UserData
return MethodParts; return MethodParts;
} }
public MethodInfo GetMethod(ref object[] parameters) public MethodInfo GetMethod(ref object[] arguments)
{ {
foreach (var userDataMethodPart in MethodParts) foreach (var userDataMethodPart in MethodParts)
{ {
if (userDataMethodPart.Parameters.Length < parameters.Length) var methodBase = userDataMethodPart.Method;
continue; if (UpsilonBinder.Default.IsValidMatch(methodBase, ref arguments))
bool valid = true;
for (var index = 0; index < userDataMethodPart.Parameters.Length; index++)
{ {
var userDataMethodParameter = userDataMethodPart.Parameters[index]; var parameters = methodBase.GetParameters();
if (index >= parameters.Length) for (var i = 0; i < parameters.Length; i++)
{ {
if (userDataMethodParameter.IsOptional) var argument = arguments[i];
return userDataMethodPart.Method; var requiredType = parameters[i].ParameterType;
valid = false; arguments[i] =
break; UpsilonBinder.Default.ChangeType(argument, requiredType, CultureInfo.InvariantCulture);
} }
var parameter = parameters[index];
var parameterType = parameter.GetType();
if (parameterType.IsGenericType) parameter = parameterType.GetGenericTypeDefinition();
if (userDataMethodParameter.Type != parameterType &&
!userDataMethodParameter.Type.IsAssignableFrom(parameterType))
{
if (parameter is ScriptType t)
{
if (userDataMethodParameter.Type.IsAssignableFrom(t.GetCSharpType()))
{
parameters[index] = ((ScriptType) parameter).ToCSharpObject();
continue;
}
}
valid = false;
break;
}
}
if (valid) return userDataMethodPart.Method; return methodBase;
}
} }
return null; return null;