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)
|
if (udSymbol.Parent.Properties.TryGetValue(resolved.Name, out var ubProperty) && ubProperty is UserDataBoundMethod ubMethod)
|
||||||
{
|
{
|
||||||
returnType = ubMethod.ResultType;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Binder;
|
||||||
using Upsilon.StandardLibraries;
|
using Upsilon.StandardLibraries;
|
||||||
using Type = Upsilon.BaseTypes.Type;
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
|
@ -67,11 +69,20 @@ namespace Upsilon.BoundTypes
|
||||||
{
|
{
|
||||||
methodName = sfa.Name;
|
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()
|
methods.Add(new UserDataBoundMethod()
|
||||||
{
|
{
|
||||||
Name = methodName,
|
Name = methodName,
|
||||||
Type = Type.Function,
|
Type = Type.Function,
|
||||||
ResultType = backingMethod.ReturnType.GetScriptType()
|
ResultType = backingMethod.ReturnType.GetScriptType(),
|
||||||
|
Parameters = parameters
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
foreach (var f in methods)
|
foreach (var f in methods)
|
||||||
|
@ -123,10 +134,47 @@ namespace Upsilon.BoundTypes
|
||||||
public string Comment { get; set; }
|
public string Comment { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class UserDataBoundFunctionParameter : UserDataBoundProperty
|
||||||
|
{
|
||||||
|
public bool IsOptional { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class UserDataBoundMethod: UserDataBoundProperty
|
public class UserDataBoundMethod: UserDataBoundProperty
|
||||||
{
|
{
|
||||||
public override string ActualType => "Function";
|
public override string ActualType => "Function";
|
||||||
public Type ResultType { get; set; }
|
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());
|
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);
|
var typeCode = System.Type.GetTypeCode(type);
|
||||||
switch (typeCode)
|
switch (typeCode)
|
||||||
|
|
Loading…
Reference in New Issue