Handling for type checking parameters of internal functions

This commit is contained in:
Deukhoofd 2018-11-30 16:19:25 +01:00
parent f08d1c2541
commit 00178cfa82
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
4 changed files with 30 additions and 19 deletions

View File

@ -24,9 +24,9 @@ namespace Upsilon.BaseTypes.ScriptFunction
private readonly bool _passScriptReference; private readonly bool _passScriptReference;
public System.Type ReturnType { get; } public System.Type ReturnType { get; }
public IEnumerable<System.Type> GetParameterTypes() public IEnumerable<UserDataMethod.UserDataMethodParameter> GetParameterInfo()
{ {
return _method.GetMethods().First().Parameters.Select(x => x.Type); return _method.GetMethods().First().Parameters;
} }
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script) public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script)

View File

@ -5,8 +5,8 @@ namespace Upsilon.BaseTypes
[Flags] [Flags]
public enum Type : byte public enum Type : byte
{ {
Unknown = 0, Nil = 0,
Nil = 1, Unknown = 1,
Boolean = 2, Boolean = 2,
Number = 4, Number = 4,
String = 8, String = 8,

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq;
using Type = Upsilon.BaseTypes.Type; using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Binder.VariableSymbols namespace Upsilon.Binder.VariableSymbols
@ -8,44 +9,50 @@ namespace Upsilon.Binder.VariableSymbols
{ {
public class InternalFunctionParameter public class InternalFunctionParameter
{ {
public InternalFunctionParameter(Type t) public InternalFunctionParameter(Type type, bool isOptional)
{ {
ValidTypes = t; ValidTypes = type;
IsOptional = isOptional;
} }
public Type ValidTypes { get; set; } public Type ValidTypes { get; }
public bool IsOptional { get; }
} }
public InternalFunctionParameter[] FunctionParameters { get; } private InternalFunctionParameter[] FunctionParameters { get; }
private int MinimalParametersRequired { get; }
public InternalFunctionVariableSymbol(string name, bool local, Type resultType, InternalFunctionParameter[] functionParameters) public InternalFunctionVariableSymbol(string name, bool local, Type resultType, InternalFunctionParameter[] functionParameters)
: base(name, local, resultType) : base(name, local, resultType)
{ {
FunctionParameters = functionParameters; FunctionParameters = functionParameters;
MinimalParametersRequired = functionParameters.Count(x => !x.IsOptional);
} }
public override (bool IsValid, string Error, public override (bool IsValid, string Error,
BoundExpression WrongParameter) ValidateParameters(ImmutableArray<BoundExpression> callingParameters) BoundExpression WrongParameter) ValidateParameters(ImmutableArray<BoundExpression> callingParameters)
{ {
if (FunctionParameters.Length != callingParameters.Length) if (FunctionParameters.Length < MinimalParametersRequired
|| callingParameters.Length > FunctionParameters.Length)
{ {
return (false, return (false,
$"Invalid number of parameters for function '{Name}'. Expected {FunctionParameters.Length}, got {callingParameters.Length}", $"Invalid number of parameters for function '{Name}'. Expected {FunctionParameters.Length}, got {callingParameters.Length}",
null); null);
} }
for (var i = 0; i < FunctionParameters.Length; i++) for (var i = 0; i < callingParameters.Length; i++)
{ {
var functionParameter = FunctionParameters[i]; var functionParameter = FunctionParameters[i];
var callingParameter = callingParameters[i]; var callingParameter = callingParameters[i];
if (callingParameter.Type != Type.Unknown && callingParameter.Type != Type.Nil) if (callingParameter.Type == Type.Unknown || callingParameter.Type == Type.Nil)
continue;
if (!functionParameter.ValidTypes.HasFlag(callingParameter.Type))
{ {
if ((functionParameter.ValidTypes ^ callingParameter.Type) != 0) return (false,
{ $"Unexpected variable passed to internal function '{functionParameter}'." +
return (false, $"Expected one of the following: {functionParameter.ValidTypes.ToString()}, got: '{callingParameter.Type}'",
$"Unexpected variable passed to internal function '{functionParameter}'.", callingParameter);
callingParameter);
}
} }
} }

View File

@ -54,8 +54,12 @@ namespace Upsilon.StandardLibraries
funcs.Add(func.Key, func.Value.MethodInfoFunction); funcs.Add(func.Key, func.Value.MethodInfoFunction);
var functionSymbol = new InternalFunctionVariableSymbol(func.Key, true, var functionSymbol = new InternalFunctionVariableSymbol(func.Key, true,
func.Value.MethodInfoFunction.ReturnType.GetScriptType(), func.Value.MethodInfoFunction.ReturnType.GetScriptType(),
func.Value.MethodInfoFunction.GetParameterTypes().Select(x => func.Value.MethodInfoFunction.GetParameterInfo().Select(typeInfo =>
new InternalFunctionVariableSymbol.InternalFunctionParameter(DeriveValidTypes(x))).ToArray()) {
var derivedType = DeriveValidTypes(typeInfo.Type);
return new InternalFunctionVariableSymbol.InternalFunctionParameter(derivedType,
typeInfo.IsOptional);
}).ToArray())
{ {
CommentValue = func.Value.CommentValue?.Split('\n') CommentValue = func.Value.CommentValue?.Split('\n')
}; };