Bind User Data methods
This commit is contained in:
parent
e741e9c355
commit
898a18a60a
|
@ -292,6 +292,14 @@ namespace Upsilon.Binder
|
|||
if (udSymbol.Parent.Properties.TryGetValue(resolved.Name, out var ubProperty) && ubProperty is UserDataBoundMethod ubMethod)
|
||||
{
|
||||
returnType = ubMethod.ResultType;
|
||||
var (isValid, error, wrongParameter) = ubMethod.ValidateParameters(parameters.ToImmutable());
|
||||
if (!isValid)
|
||||
{
|
||||
var span = e.Span;
|
||||
if (wrongParameter != null)
|
||||
span = wrongParameter.Span;
|
||||
_diagnostics.LogError(error, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Upsilon.BaseTypes;
|
||||
using Upsilon.Binder;
|
||||
using Upsilon.StandardLibraries;
|
||||
using Type = Upsilon.BaseTypes.Type;
|
||||
|
||||
|
@ -67,11 +69,20 @@ namespace Upsilon.BoundTypes
|
|||
{
|
||||
methodName = sfa.Name;
|
||||
}
|
||||
|
||||
var parameters = backingMethod.GetParameters().Select(parameter => new UserDataBoundFunctionParameter()
|
||||
{
|
||||
Name = parameter.Name,
|
||||
ActualType = parameter.ParameterType.Name,
|
||||
Type = StaticScope.DeriveValidTypes(parameter.ParameterType),
|
||||
IsOptional = parameter.IsOptional
|
||||
}).ToArray();
|
||||
methods.Add(new UserDataBoundMethod()
|
||||
{
|
||||
Name = methodName,
|
||||
Type = Type.Function,
|
||||
ResultType = backingMethod.ReturnType.GetScriptType()
|
||||
ResultType = backingMethod.ReturnType.GetScriptType(),
|
||||
Parameters = parameters
|
||||
});
|
||||
}
|
||||
foreach (var f in methods)
|
||||
|
@ -123,10 +134,47 @@ namespace Upsilon.BoundTypes
|
|||
public string Comment { get; set; }
|
||||
}
|
||||
|
||||
public class UserDataBoundFunctionParameter : UserDataBoundProperty
|
||||
{
|
||||
public bool IsOptional { get; set; }
|
||||
}
|
||||
|
||||
public class UserDataBoundMethod: UserDataBoundProperty
|
||||
{
|
||||
public override string ActualType => "Function";
|
||||
public Type ResultType { get; set; }
|
||||
public UserDataBoundFunctionParameter[] Parameters { get; set; }
|
||||
|
||||
public (bool IsValid, string Error,
|
||||
BoundExpression WrongParameter) ValidateParameters(ImmutableArray<BoundExpression> callingParameters)
|
||||
{
|
||||
if (callingParameters.Length < Parameters.Count(x => !x.IsOptional)
|
||||
|| callingParameters.Length > Parameters.Length)
|
||||
{
|
||||
return (false,
|
||||
$"Invalid number of parameters for function '{Name}'. Expected {Parameters.Length}, got {callingParameters.Length}",
|
||||
null);
|
||||
}
|
||||
|
||||
for (var i = 0; i < callingParameters.Length; i++)
|
||||
{
|
||||
var functionParameter = Parameters[i];
|
||||
var callingParameter = callingParameters[i];
|
||||
if (callingParameter.Type == Type.Unknown || callingParameter.Type == Type.Nil)
|
||||
continue;
|
||||
|
||||
if (!functionParameter.Type.HasFlag(callingParameter.Type))
|
||||
{
|
||||
return (false,
|
||||
$"Unexpected variable passed to internal function at variable {i + 1}. " +
|
||||
$"Expected one of the following: {functionParameter.Type.ToString()}, got: '{callingParameter.Type}'",
|
||||
callingParameter);
|
||||
}
|
||||
}
|
||||
|
||||
return (true, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -138,7 +138,7 @@ namespace Upsilon.StandardLibraries
|
|||
new InternalFunctionVariableSymbol.InternalFunctionParameter(t, false)).ToArray());
|
||||
}
|
||||
|
||||
private static Type DeriveValidTypes(System.Type type)
|
||||
public static Type DeriveValidTypes(System.Type type)
|
||||
{
|
||||
var typeCode = System.Type.GetTypeCode(type);
|
||||
switch (typeCode)
|
||||
|
|
Loading…
Reference in New Issue