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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue