Fixes script --> C# function calls not working

This commit is contained in:
Deukhoofd 2018-11-28 21:23:08 +01:00
parent babbf2875f
commit af0ff235e1
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 106 additions and 53 deletions

View File

@ -25,13 +25,13 @@ namespace Upsilon.BaseTypes
public abstract ScriptType Run(Diagnostics diagnostics, ScriptType[] variables);
}
internal class ScriptInternalFunction : ScriptFunction, IScopeOwner
internal class ScriptRuntimeFunction : ScriptFunction, IScopeOwner
{
public BoundBlockStatement Block { get; }
public ImmutableArray<BoundVariableSymbol> Parameters { get; }
public EvaluationScope EvaluationScope { get; }
public ScriptInternalFunction(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block,
public ScriptRuntimeFunction(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block,
EvaluationScope evaluationScope)
{
Parameters = parameters;
@ -59,11 +59,13 @@ namespace Upsilon.BaseTypes
_method = method;
_object = o;
_directTypeManipulation = directTypeManipulation;
ReturnType = _method.ReturnType;
}
private readonly UserDataMethod _method;
private readonly object _object;
private readonly bool _directTypeManipulation;
public System.Type ReturnType { get; }
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables)
{

View File

@ -1,5 +1,7 @@
using System;
using System.Collections;
using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.BaseTypes.UserData;
namespace Upsilon.BaseTypes
@ -43,7 +45,7 @@ namespace Upsilon.BaseTypes
return new GenericUserData(o);
}
public static Type GetLuaType(object o)
public static Type GetScriptType(object o)
{
if (o is ScriptType t)
{
@ -70,5 +72,38 @@ namespace Upsilon.BaseTypes
return Type.UserData;
}
}
public static Type GetScriptType(this System.Type t)
{
if (t == typeof(bool))
return Type.Boolean;
if (t == typeof(string))
return Type.String;
if (t == typeof(int))
return Type.Number;
if (t == typeof(long))
return Type.Number;
if (t == typeof(float))
return Type.Number;
if (t == typeof(double))
return Type.Number;
if (t == typeof(void))
return Type.Nil;
if (t == typeof(ScriptString))
return Type.String;
if (typeof(ScriptNumber).IsAssignableFrom(t))
return Type.Number;
if (typeof(ScriptFunction).IsAssignableFrom(t))
return Type.Function;
if (typeof(ScriptTable).IsAssignableFrom(t))
return Type.Table;
if (t == typeof(IIterable))
return Type.Nil;
throw new ArgumentException(t.ToString());
}
}
}

View File

@ -32,6 +32,7 @@ namespace Upsilon.BaseTypes.UserData
public string Name { get; }
private List<UserDataMethodPart> MethodParts { get; }
public System.Type ReturnType { get; }
public UserDataMethod(MethodInfo method)
{
@ -41,6 +42,7 @@ namespace Upsilon.BaseTypes.UserData
{
part
};
ReturnType = part.Method.ReturnType;
}
public void LoadMethodPart(MethodInfo method)

View File

@ -232,27 +232,32 @@ namespace Upsilon.Binder
returnType = function.ResultType;
var pars = function.Parameters;
if (pars.Length != parameters.Count)
if (!function.IsInternal)
{
_diagnostics.LogError(
$"Invalid number of parameters for function '{function.Name}'. Expected {pars.Length}, got {parameters.Count}",
e.Span);
}
else
{
for (var i = 0; i < pars.Length; i++)
if (pars.Length != parameters.Count)
{
var functionParameter = pars[i];
var callingParameter = parameters[i];
if (functionParameter.Type != Type.Unknown &&
callingParameter.Type != Type.Unknown && callingParameter.Type != Type.Nil)
_diagnostics.LogError(
$"Invalid number of parameters for function '{function.Name}'. Expected {pars.Length}, got {parameters.Count}",
e.Span);
}
else
{
for (var i = 0; i < pars.Length; i++)
{
if (callingParameter.Type != functionParameter.Type)
var functionParameter = pars[i];
var callingParameter = parameters[i];
if (functionParameter.Type != Type.Unknown &&
callingParameter.Type != Type.Unknown && callingParameter.Type != Type.Nil)
{
_diagnostics.LogError(
$"Invalid type for function '{function.Name}' at parameter '{functionParameter.Name}'. " +
$"Expected type '{functionParameter.Type}', got '{callingParameter.Type}'",
callingParameter.Span);
if (callingParameter.Type != functionParameter.Type)
{
_diagnostics.LogError(
$"Invalid type for function '{function.Name}' at parameter '{functionParameter.Name}'. " +
$"Expected type '{functionParameter.Type}', got '{callingParameter.Type}'",
callingParameter.Span);
}
}
}
}
@ -508,7 +513,7 @@ namespace Upsilon.Binder
if (!Scope.TryGetVariable(name, !isLocal, out var variable))
{
var functionVariable = new FunctionVariableSymbol(name, isLocal, parameters.ToImmutable(), func.ReturnType)
var functionVariable = new FunctionVariableSymbol(name, isLocal, parameters.ToImmutable(), func.ReturnType, false)
{
CommentValue = commentData.ToArray()
};

View File

@ -26,12 +26,14 @@ namespace Upsilon.Binder
public ImmutableArray<VariableSymbol> Parameters { get; }
public Type ResultType { get; internal set; }
public bool IsBound { get; set; }
public bool IsInternal { get; }
public FunctionVariableSymbol(string name, bool local, ImmutableArray<VariableSymbol> parameters, Type resultType)
public FunctionVariableSymbol(string name, bool local, ImmutableArray<VariableSymbol> parameters, Type resultType, bool isInternal)
: base(name, Type.Function, local)
{
Parameters = parameters;
ResultType = resultType;
IsInternal = isInternal;
}
}

View File

@ -61,33 +61,36 @@ namespace Upsilon.Evaluator
{
throw new ArgumentException(($"Function '{functionName}' could not be found"));
}
var function = (ScriptInternalFunction) statement;
var function = (ScriptRuntimeFunction) statement;
var innerEvaluator = new Evaluator(_diagnostics, Scope);
for (var index = 0; index < parameters.Length; index++)
if (parameters != null)
{
var parameter = parameters[index];
var parameterSymbol = (FunctionParameterSymbol)function.Parameters[index].VariableSymbol;
if (parameterSymbol.BoundTypeDefinition != null)
for (var index = 0; index < parameters.Length; index++)
{
bool isCompatible = false;
var parameterType = parameter.GetType();
foreach (var validType in parameterSymbol.BoundTypeDefinition.ValidInternalTypes)
var parameter = parameters[index];
var parameterSymbol = (FunctionParameterSymbol)function.Parameters[index].VariableSymbol;
if (parameterSymbol.BoundTypeDefinition != null)
{
if (validType.IsAssignableFrom(parameterType))
bool isCompatible = false;
var parameterType = parameter.GetType();
foreach (var validType in parameterSymbol.BoundTypeDefinition.ValidInternalTypes)
{
isCompatible = true;
break;
if (validType.IsAssignableFrom(parameterType))
{
isCompatible = true;
break;
}
}
if (!isCompatible)
{
throw new EvaluationException(
$"Parameter '{parameterSymbol.Name}' of function '{functionName}' can't handle the given object with type '{parameterType}'");
}
}
if (!isCompatible)
{
throw new EvaluationException(
$"Parameter '{parameterSymbol.Name}' of function '{functionName}' can't handle the given object with type '{parameterType}'");
}
innerEvaluator.Scope.CreateLocal(parameterSymbol, parameter.ToScriptType());
}
innerEvaluator.Scope.CreateLocal(parameterSymbol, parameter.ToScriptType());
}
var result = innerEvaluator.EvaluateNode(function.Block);
@ -414,13 +417,13 @@ namespace Upsilon.Evaluator
private ScriptType EvaluateBoundFunctionStatement(BoundFunctionExpression boundFunctionExpression)
{
var func = new ScriptInternalFunction(boundFunctionExpression.Parameters, boundFunctionExpression.Block, Scope);
var func = new ScriptRuntimeFunction(boundFunctionExpression.Parameters, boundFunctionExpression.Block, Scope);
return func;
}
private ScriptType EvaluateUnboundFunctionStatement(UnboundFunctionExpression unboundFunctionExpression)
{
var func = new ScriptInternalFunction(unboundFunctionExpression.Parameters, unboundFunctionExpression.Block, Scope);
var func = new ScriptRuntimeFunction(unboundFunctionExpression.Parameters, unboundFunctionExpression.Block, Scope);
return func;
}

View File

@ -8,7 +8,7 @@ using Upsilon.BaseTypes.ScriptTypeInterfaces;
namespace Upsilon.StandardLibraries
{
internal class BasicFunctions : LuaLibrary
internal class BasicFunctions : ScriptLibrary
{
[StandardLibraryScriptFunction("assert")]
public void Assert(ScriptBoolean boolean, ScriptString message = null)

View File

@ -5,11 +5,11 @@ using Upsilon.BaseTypes.UserData;
namespace Upsilon.StandardLibraries
{
internal abstract class LuaLibrary
internal abstract class ScriptLibrary
{
public Dictionary<string, ScriptFunction> LoadMethods()
public Dictionary<string, ScriptMethodInfoFunction> LoadMethods()
{
var dictionary = new Dictionary<string, ScriptFunction>();
var dictionary = new Dictionary<string, ScriptMethodInfoFunction>();
var methods = GetType().GetMethods();
foreach (var methodInfo in methods)
{

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Upsilon.BaseTypes;
@ -42,13 +43,16 @@ namespace Upsilon.StandardLibraries
public static (EvaluationScope, BoundScope) CreateStandardLibrary()
{
var basicFunctions = new BasicFunctions().LoadMethods();
var scope = new EvaluationScope(basicFunctions.ToDictionary(x => x.Key, x => (ScriptType)x.Value));
var boundScope =
new BoundScope(
scope.Variables.ToDictionary(x => x.Key,
x => (VariableSymbol) new FunctionVariableSymbol(x.Key, false,
ImmutableArray<VariableSymbol>.Empty, x.Value.Type) {IsBound = true}),
null);
var funcs = new Dictionary<string, ScriptType>();
var boundFuncs = new Dictionary<string, VariableSymbol>();
foreach (var func in basicFunctions)
{
funcs.Add(func.Key, func.Value);
boundFuncs.Add(func.Key, new FunctionVariableSymbol(func.Key, true, ImmutableArray<VariableSymbol>.Empty,
func.Value.ReturnType.GetScriptType(), true){IsBound = true});
}
var scope = new EvaluationScope(funcs);
var boundScope = new BoundScope(boundFuncs, null);
return (scope, boundScope);
}