Fixes script --> C# function calls not working
This commit is contained in:
parent
babbf2875f
commit
af0ff235e1
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue