Allow non-standard libraries to have a script pass variable as well

This commit is contained in:
Deukhoofd 2019-02-16 16:13:28 +01:00
parent 80afeacda6
commit 59909b0d53
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
1 changed files with 26 additions and 9 deletions

View File

@ -63,7 +63,8 @@ namespace Upsilon.BoundTypes
Properties = new Dictionary<string, UserDataBoundProperty>(), Properties = new Dictionary<string, UserDataBoundProperty>(),
Name = name Name = name
}; };
var fields = backingType.GetFields(BindingFlags.Public | BindingFlags.Instance).Select(x => new UserDataBoundProperty() const BindingFlags generalBindAttributes = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
var fields = backingType.GetFields(generalBindAttributes).Select(x => new UserDataBoundProperty()
{ {
Name = x.Name, Name = x.Name,
ActualType = x.FieldType.Name, ActualType = x.FieldType.Name,
@ -79,11 +80,11 @@ namespace Upsilon.BoundTypes
{ {
realProperties = new[]{backingType} realProperties = new[]{backingType}
.Concat(backingType.GetInterfaces()) .Concat(backingType.GetInterfaces())
.SelectMany(x => x.GetProperties(BindingFlags.Public | BindingFlags.Instance)).ToArray(); .SelectMany(x => x.GetProperties(generalBindAttributes)).ToArray();
} }
else else
{ {
realProperties = backingType.GetProperties(BindingFlags.Public | BindingFlags.Instance); realProperties = backingType.GetProperties(generalBindAttributes);
} }
var properties = realProperties.Select(x => new UserDataBoundProperty() var properties = realProperties.Select(x => new UserDataBoundProperty()
{ {
@ -96,16 +97,18 @@ namespace Upsilon.BoundTypes
obj.Properties.Add(f.Name.ToLowerInvariant(), f); obj.Properties.Add(f.Name.ToLowerInvariant(), f);
} }
var methods = new Dictionary<string, UserDataBoundMethod>(); var methods = new Dictionary<string, UserDataBoundMethod>();
var backingMethods = backingType.GetMethods(BindingFlags.Public | BindingFlags.Instance); var backingMethods = backingType.GetMethods(generalBindAttributes);
foreach (var backingMethod in backingMethods) foreach (var backingMethod in backingMethods)
{ {
if (backingMethod.IsSpecialName) if (backingMethod.IsSpecialName)
continue; continue;
var methodName = backingMethod.Name; var methodName = backingMethod.Name;
var passScriptReference = false;
var attribute = backingMethod.GetCustomAttribute(typeof(ScriptFunctionAttribute)); var attribute = backingMethod.GetCustomAttribute(typeof(ScriptFunctionAttribute));
if (attribute is ScriptFunctionAttribute sfa ) if (attribute is ScriptFunctionAttribute sfa )
{ {
methodName = sfa.Name; methodName = sfa.Name;
passScriptReference = sfa.PassScriptReference;
} }
var parameters = backingMethod.GetParameters().Select(parameter => new UserDataBoundFunctionParameter() var parameters = backingMethod.GetParameters().Select(parameter => new UserDataBoundFunctionParameter()
@ -115,7 +118,7 @@ namespace Upsilon.BoundTypes
Type = StaticScope.DeriveValidTypes(parameter.ParameterType), Type = StaticScope.DeriveValidTypes(parameter.ParameterType),
IsOptional = parameter.IsOptional IsOptional = parameter.IsOptional
}).ToArray(); }).ToArray();
var option = new UserDataBoundMethodOption(backingMethod.ReturnType.GetScriptType(), parameters); var option = new UserDataBoundMethodOption(backingMethod.ReturnType.GetScriptType(), parameters, passScriptReference);
if (methods.TryGetValue(methodName, out var func)) if (methods.TryGetValue(methodName, out var func))
{ {
func.Options.Add(option); func.Options.Add(option);
@ -219,29 +222,43 @@ namespace Upsilon.BoundTypes
public class UserDataBoundMethodOption public class UserDataBoundMethodOption
{ {
public UserDataBoundMethodOption(TypeContainer resultType, UserDataBoundFunctionParameter[] parameters) public UserDataBoundMethodOption(TypeContainer resultType, UserDataBoundFunctionParameter[] parameters,
bool passScriptReference)
{ {
ResultType = resultType; ResultType = resultType;
Parameters = parameters; Parameters = parameters;
PassScriptReference = passScriptReference;
NonOptionalParameterCount = Parameters.Count(x => !x.IsOptional); NonOptionalParameterCount = Parameters.Count(x => !x.IsOptional);
} }
public TypeContainer ResultType { get; } public TypeContainer ResultType { get; }
public UserDataBoundFunctionParameter[] Parameters { get; } public UserDataBoundFunctionParameter[] Parameters { get; }
public bool PassScriptReference { get; }
private int NonOptionalParameterCount { get; } private int NonOptionalParameterCount { get; }
public bool ValidateParameters(ImmutableArray<BoundExpression> callingParameters) public bool ValidateParameters(ImmutableArray<BoundExpression> callingParameters)
{ {
if (callingParameters.Length < NonOptionalParameterCount var effectiveLength = callingParameters.Length;
|| callingParameters.Length > Parameters.Length) if (PassScriptReference)
effectiveLength++;
if (effectiveLength < NonOptionalParameterCount
|| effectiveLength > Parameters.Length)
{ {
return false; return false;
} }
var callingIndexOffset = 0;
for (var i = 0; i < callingParameters.Length; i++) for (var i = 0; i < callingParameters.Length; i++)
{ {
var functionParameter = Parameters[i]; var functionParameter = Parameters[i];
var callingParameter = callingParameters[i]; if (i == 0 && PassScriptReference)
{
callingIndexOffset++;
continue;
}
var callingParameter = callingParameters[i + callingIndexOffset];
if (callingParameter.ValueType == Type.Unknown || callingParameter.ValueType == Type.Nil || if (callingParameter.ValueType == Type.Unknown || callingParameter.ValueType == Type.Nil ||
functionParameter.Type == Type.Unknown) functionParameter.Type == Type.Unknown)
continue; continue;