Handling for type checking parameters of internal functions
This commit is contained in:
		| @@ -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,46 +9,52 @@ 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 ^ callingParameter.Type) != 0) |  | ||||||
|  |                 if (!functionParameter.ValidTypes.HasFlag(callingParameter.Type)) | ||||||
|                 { |                 { | ||||||
|                     return (false, |                     return (false, | ||||||
|                             $"Unexpected variable passed to internal function '{functionParameter}'.", |                         $"Unexpected variable passed to internal function '{functionParameter}'." + | ||||||
|  |                         $"Expected one of the following: {functionParameter.ValidTypes.ToString()}, got: '{callingParameter.Type}'", | ||||||
|                         callingParameter); |                         callingParameter); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return (true, null, null); |             return (true, null, null); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -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') | ||||||
|                 }; |                 }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user