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

View File

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

View File

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