Handling for type checking parameters of internal functions
This commit is contained in:
parent
f08d1c2541
commit
00178cfa82
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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')
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue