Way better handling of calling functions from CSHarp

This commit is contained in:
Deukhoofd 2018-11-16 14:46:12 +01:00
parent 62ad100aee
commit 47e2dadb8d
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
8 changed files with 55 additions and 15 deletions

View File

@ -25,6 +25,8 @@ namespace Upsilon.BaseTypes.Number
public static implicit operator long(NumberLong n)
{
if (n == null)
return 0;
return n.Value;
}
}

View File

@ -38,7 +38,7 @@ namespace Upsilon.Binder
unboundFunctionStatement.Key.IsBound = true;
}
_unboundFunctions = new Dictionary<FunctionVariableSymbol, UnboundFunctionStatement>();
return new BoundScript(bound);
return new BoundScript((BoundBlockStatement) bound);
}
private BoundStatement BindStatement(StatementSyntax s)
@ -173,8 +173,9 @@ namespace Upsilon.Binder
_scope.SetVariable(functionVariable);
}
_unboundFunctions[function].Block =
(BoundBlockStatement) BindBlockStatement(_unboundFunctions[function].UnboundBlock);
var unboundFunctionStatement = _unboundFunctions[function];
unboundFunctionStatement.Block =
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock);
_scope = _scope.ParentScope;
function.IsBound = true;
_unboundFunctions.Remove(function);
@ -330,7 +331,8 @@ namespace Upsilon.Binder
var block = BindBlockStatement(e.Block);
_scope = _scope.ParentScope;
((FunctionVariableSymbol) variable).IsBound = true;
return new BoundFunctionStatement(variable, parameters.ToImmutable(), (BoundBlockStatement) block);
var func = new BoundFunctionStatement(variable, parameters.ToImmutable(), (BoundBlockStatement) block);
return func;
}
else
{

View File

@ -6,7 +6,7 @@ namespace Upsilon.Binder
{
public VariableSymbol Identifier { get; }
public ImmutableArray<VariableSymbol> Parameters { get; }
public BoundBlockStatement Block { get; }
public BoundBlockStatement Block { get; set; }
public BoundFunctionStatement(VariableSymbol identifier, ImmutableArray<VariableSymbol> parameters,
BoundBlockStatement block)

View File

@ -1,14 +1,16 @@
using System.Collections.Generic;
namespace Upsilon.Binder
{
public class BoundScript : BoundStatement
{
public BoundScript(BoundStatement statement)
public BoundScript(BoundBlockStatement statement)
{
Statement = statement;
}
public override BoundKind Kind => BoundKind.BoundScript;
public BoundStatement Statement { get; }
public BoundBlockStatement Statement { get; }
}
}

View File

@ -3,21 +3,16 @@ using Upsilon.Parser;
namespace Upsilon.Binder
{
public class UnboundFunctionStatement : BoundStatement
public class UnboundFunctionStatement : BoundFunctionStatement
{
public UnboundFunctionStatement(VariableSymbol identifier, ImmutableArray<VariableSymbol> parameters,
BlockStatementSyntax unboundBlock)
BlockStatementSyntax unboundBlock) : base(identifier, parameters, null)
{
Identifier = identifier;
Parameters = parameters;
UnboundBlock = unboundBlock;
}
public override BoundKind Kind => BoundKind.BoundPromise;
public VariableSymbol Identifier { get; }
public ImmutableArray<VariableSymbol> Parameters { get; }
public BlockStatementSyntax UnboundBlock { get; }
public BoundBlockStatement Block { get; set; }
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.Binder;
using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Evaluator
{
@ -34,6 +35,18 @@ namespace Upsilon.Evaluator
return _returnValue;
}
public LuaType Evaluate(BoundScript e, string functionName)
{
Evaluate(e.Statement);
if (!Scope.TryGet(functionName, out var statement) || statement.Type != Type.Function)
{
throw new ArgumentException(($"Function '{functionName}' could not be found"));
}
var innerEvaluator = new Evaluator(_diagnostics, Scope);
var result = innerEvaluator.Evaluate(((LuaFunction)statement).Block);
return result;
}
private LuaType Evaluate(BoundNode b)
{
switch (b.Kind)

View File

@ -12,6 +12,7 @@ namespace Upsilon.Evaluator
private SourceText ScriptString { get; }
private Evaluator Evaluator { get; }
private readonly BlockStatementSyntax _parsed;
private BoundScript _bound;
public Diagnostics Diagnostics { get; }
private Binder.Binder Binder { get; }
public EvaluationScope Scope { get; }
@ -30,7 +31,7 @@ namespace Upsilon.Evaluator
public BoundScript Bind()
{
return Binder.BindScript(_parsed);
return _bound ?? (_bound = Binder.BindScript(_parsed));
}
public object Evaluate()
@ -38,11 +39,21 @@ namespace Upsilon.Evaluator
return Evaluator.Evaluate(Bind());
}
public object EvaluateFunction(string functionName)
{
return Evaluator.Evaluate(Bind(), functionName);
}
public T Evaluate<T>() where T : LuaType
{
return (T)Evaluator.Evaluate(Bind());
}
public T EvaluateFunction<T>(string functionName) where T : LuaType
{
return (T)Evaluator.Evaluate(Bind(), functionName);
}
public string PrettyPrintSyntaxTree()
{
return _parsed.Print();

View File

@ -151,5 +151,20 @@ a = 87
Assert.Equal(60, (long)(NumberLong)result);
}
[Fact]
public void ReturnFromCSharpCall()
{
const string input = @"
function testFunc ()
return 100
end
";
var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages);
var result = script.EvaluateFunction<NumberLong>("testFunc");
Assert.Empty(script.Diagnostics.Messages);
Assert.Equal(100, (long)result);
}
}
}