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

View File

@ -1,5 +1,7 @@
using System;
using System.Collections; using System.Collections;
using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.BaseTypes.UserData; using Upsilon.BaseTypes.UserData;
namespace Upsilon.BaseTypes namespace Upsilon.BaseTypes
@ -43,7 +45,7 @@ namespace Upsilon.BaseTypes
return new GenericUserData(o); return new GenericUserData(o);
} }
public static Type GetLuaType(object o) public static Type GetScriptType(object o)
{ {
if (o is ScriptType t) if (o is ScriptType t)
{ {
@ -70,5 +72,38 @@ namespace Upsilon.BaseTypes
return Type.UserData; 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; } public string Name { get; }
private List<UserDataMethodPart> MethodParts { get; } private List<UserDataMethodPart> MethodParts { get; }
public System.Type ReturnType { get; }
public UserDataMethod(MethodInfo method) public UserDataMethod(MethodInfo method)
{ {
@ -41,6 +42,7 @@ namespace Upsilon.BaseTypes.UserData
{ {
part part
}; };
ReturnType = part.Method.ReturnType;
} }
public void LoadMethodPart(MethodInfo method) public void LoadMethodPart(MethodInfo method)

View File

@ -232,27 +232,32 @@ namespace Upsilon.Binder
returnType = function.ResultType; returnType = function.ResultType;
var pars = function.Parameters; var pars = function.Parameters;
if (pars.Length != parameters.Count)
if (!function.IsInternal)
{ {
_diagnostics.LogError( if (pars.Length != parameters.Count)
$"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++)
{ {
var functionParameter = pars[i]; _diagnostics.LogError(
var callingParameter = parameters[i]; $"Invalid number of parameters for function '{function.Name}'. Expected {pars.Length}, got {parameters.Count}",
if (functionParameter.Type != Type.Unknown && e.Span);
callingParameter.Type != Type.Unknown && callingParameter.Type != Type.Nil) }
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( if (callingParameter.Type != functionParameter.Type)
$"Invalid type for function '{function.Name}' at parameter '{functionParameter.Name}'. " + {
$"Expected type '{functionParameter.Type}', got '{callingParameter.Type}'", _diagnostics.LogError(
callingParameter.Span); $"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)) 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() CommentValue = commentData.ToArray()
}; };

View File

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

View File

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

View File

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

View File

@ -5,11 +5,11 @@ using Upsilon.BaseTypes.UserData;
namespace Upsilon.StandardLibraries 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(); var methods = GetType().GetMethods();
foreach (var methodInfo in methods) foreach (var methodInfo in methods)
{ {

View File

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