diff --git a/Upsilon/BaseTypes/ScriptFunction/ScriptMethodInfoFunction.cs b/Upsilon/BaseTypes/ScriptFunction/ScriptMethodInfoFunction.cs index 3e43b15..a010d8d 100644 --- a/Upsilon/BaseTypes/ScriptFunction/ScriptMethodInfoFunction.cs +++ b/Upsilon/BaseTypes/ScriptFunction/ScriptMethodInfoFunction.cs @@ -24,9 +24,9 @@ namespace Upsilon.BaseTypes.ScriptFunction private readonly bool _passScriptReference; public System.Type ReturnType { get; } - public IEnumerable GetParameterTypes() + public IEnumerable 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) diff --git a/Upsilon/BaseTypes/Type.cs b/Upsilon/BaseTypes/Type.cs index 26e4b98..9d5b4f6 100644 --- a/Upsilon/BaseTypes/Type.cs +++ b/Upsilon/BaseTypes/Type.cs @@ -5,8 +5,8 @@ namespace Upsilon.BaseTypes [Flags] public enum Type : byte { - Unknown = 0, - Nil = 1, + Nil = 0, + Unknown = 1, Boolean = 2, Number = 4, String = 8, diff --git a/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs b/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs index 8e8e540..3d76eff 100644 --- a/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs +++ b/Upsilon/Binder/VariableSymbols/InternalFunctionVariableSymbol.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Immutable; +using System.Linq; using Type = Upsilon.BaseTypes.Type; namespace Upsilon.Binder.VariableSymbols @@ -8,44 +9,50 @@ namespace Upsilon.Binder.VariableSymbols { 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) : base(name, local, resultType) { FunctionParameters = functionParameters; + MinimalParametersRequired = functionParameters.Count(x => !x.IsOptional); } public override (bool IsValid, string Error, BoundExpression WrongParameter) ValidateParameters(ImmutableArray callingParameters) { - if (FunctionParameters.Length != callingParameters.Length) + if (FunctionParameters.Length < MinimalParametersRequired + || callingParameters.Length > FunctionParameters.Length) { return (false, $"Invalid number of parameters for function '{Name}'. Expected {FunctionParameters.Length}, got {callingParameters.Length}", null); } - for (var i = 0; i < FunctionParameters.Length; i++) + for (var i = 0; i < callingParameters.Length; i++) { var functionParameter = FunctionParameters[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}'.", - callingParameter); - } + return (false, + $"Unexpected variable passed to internal function '{functionParameter}'." + + $"Expected one of the following: {functionParameter.ValidTypes.ToString()}, got: '{callingParameter.Type}'", + callingParameter); } } diff --git a/Upsilon/StandardLibraries/StaticScope.cs b/Upsilon/StandardLibraries/StaticScope.cs index 7b6527f..137487d 100644 --- a/Upsilon/StandardLibraries/StaticScope.cs +++ b/Upsilon/StandardLibraries/StaticScope.cs @@ -54,8 +54,12 @@ namespace Upsilon.StandardLibraries funcs.Add(func.Key, func.Value.MethodInfoFunction); var functionSymbol = new InternalFunctionVariableSymbol(func.Key, true, func.Value.MethodInfoFunction.ReturnType.GetScriptType(), - func.Value.MethodInfoFunction.GetParameterTypes().Select(x => - new InternalFunctionVariableSymbol.InternalFunctionParameter(DeriveValidTypes(x))).ToArray()) + func.Value.MethodInfoFunction.GetParameterInfo().Select(typeInfo => + { + var derivedType = DeriveValidTypes(typeInfo.Type); + return new InternalFunctionVariableSymbol.InternalFunctionParameter(derivedType, + typeInfo.IsOptional); + }).ToArray()) { CommentValue = func.Value.CommentValue?.Split('\n') };