Bind User Data methods

This commit is contained in:
Deukhoofd 2018-12-12 17:28:12 +01:00
parent e741e9c355
commit 898a18a60a
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
3 changed files with 58 additions and 2 deletions

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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)