Way better handling of calling functions from CSHarp
This commit is contained in:
parent
62ad100aee
commit
47e2dadb8d
|
@ -25,6 +25,8 @@ namespace Upsilon.BaseTypes.Number
|
||||||
|
|
||||||
public static implicit operator long(NumberLong n)
|
public static implicit operator long(NumberLong n)
|
||||||
{
|
{
|
||||||
|
if (n == null)
|
||||||
|
return 0;
|
||||||
return n.Value;
|
return n.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Upsilon.Binder
|
||||||
unboundFunctionStatement.Key.IsBound = true;
|
unboundFunctionStatement.Key.IsBound = true;
|
||||||
}
|
}
|
||||||
_unboundFunctions = new Dictionary<FunctionVariableSymbol, UnboundFunctionStatement>();
|
_unboundFunctions = new Dictionary<FunctionVariableSymbol, UnboundFunctionStatement>();
|
||||||
return new BoundScript(bound);
|
return new BoundScript((BoundBlockStatement) bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindStatement(StatementSyntax s)
|
private BoundStatement BindStatement(StatementSyntax s)
|
||||||
|
@ -173,8 +173,9 @@ namespace Upsilon.Binder
|
||||||
_scope.SetVariable(functionVariable);
|
_scope.SetVariable(functionVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
_unboundFunctions[function].Block =
|
var unboundFunctionStatement = _unboundFunctions[function];
|
||||||
(BoundBlockStatement) BindBlockStatement(_unboundFunctions[function].UnboundBlock);
|
unboundFunctionStatement.Block =
|
||||||
|
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock);
|
||||||
_scope = _scope.ParentScope;
|
_scope = _scope.ParentScope;
|
||||||
function.IsBound = true;
|
function.IsBound = true;
|
||||||
_unboundFunctions.Remove(function);
|
_unboundFunctions.Remove(function);
|
||||||
|
@ -330,7 +331,8 @@ namespace Upsilon.Binder
|
||||||
var block = BindBlockStatement(e.Block);
|
var block = BindBlockStatement(e.Block);
|
||||||
_scope = _scope.ParentScope;
|
_scope = _scope.ParentScope;
|
||||||
((FunctionVariableSymbol) variable).IsBound = true;
|
((FunctionVariableSymbol) variable).IsBound = true;
|
||||||
return new BoundFunctionStatement(variable, parameters.ToImmutable(), (BoundBlockStatement) block);
|
var func = new BoundFunctionStatement(variable, parameters.ToImmutable(), (BoundBlockStatement) block);
|
||||||
|
return func;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public VariableSymbol Identifier { get; }
|
public VariableSymbol Identifier { get; }
|
||||||
public ImmutableArray<VariableSymbol> Parameters { get; }
|
public ImmutableArray<VariableSymbol> Parameters { get; }
|
||||||
public BoundBlockStatement Block { get; }
|
public BoundBlockStatement Block { get; set; }
|
||||||
|
|
||||||
public BoundFunctionStatement(VariableSymbol identifier, ImmutableArray<VariableSymbol> parameters,
|
public BoundFunctionStatement(VariableSymbol identifier, ImmutableArray<VariableSymbol> parameters,
|
||||||
BoundBlockStatement block)
|
BoundBlockStatement block)
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundScript : BoundStatement
|
public class BoundScript : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundScript(BoundStatement statement)
|
public BoundScript(BoundBlockStatement statement)
|
||||||
{
|
{
|
||||||
Statement = statement;
|
Statement = statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundScript;
|
public override BoundKind Kind => BoundKind.BoundScript;
|
||||||
|
|
||||||
public BoundStatement Statement { get; }
|
public BoundBlockStatement Statement { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,21 +3,16 @@ using Upsilon.Parser;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class UnboundFunctionStatement : BoundStatement
|
public class UnboundFunctionStatement : BoundFunctionStatement
|
||||||
{
|
{
|
||||||
public UnboundFunctionStatement(VariableSymbol identifier, ImmutableArray<VariableSymbol> parameters,
|
public UnboundFunctionStatement(VariableSymbol identifier, ImmutableArray<VariableSymbol> parameters,
|
||||||
BlockStatementSyntax unboundBlock)
|
BlockStatementSyntax unboundBlock) : base(identifier, parameters, null)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
|
||||||
Parameters = parameters;
|
|
||||||
UnboundBlock = unboundBlock;
|
UnboundBlock = unboundBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundPromise;
|
public override BoundKind Kind => BoundKind.BoundPromise;
|
||||||
|
|
||||||
public VariableSymbol Identifier { get; }
|
|
||||||
public ImmutableArray<VariableSymbol> Parameters { get; }
|
|
||||||
public BlockStatementSyntax UnboundBlock { get; }
|
public BlockStatementSyntax UnboundBlock { get; }
|
||||||
public BoundBlockStatement Block { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
namespace Upsilon.Evaluator
|
namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
|
@ -34,6 +35,18 @@ namespace Upsilon.Evaluator
|
||||||
return _returnValue;
|
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)
|
private LuaType Evaluate(BoundNode b)
|
||||||
{
|
{
|
||||||
switch (b.Kind)
|
switch (b.Kind)
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Upsilon.Evaluator
|
||||||
private SourceText ScriptString { get; }
|
private SourceText ScriptString { get; }
|
||||||
private Evaluator Evaluator { get; }
|
private Evaluator Evaluator { get; }
|
||||||
private readonly BlockStatementSyntax _parsed;
|
private readonly BlockStatementSyntax _parsed;
|
||||||
|
private BoundScript _bound;
|
||||||
public Diagnostics Diagnostics { get; }
|
public Diagnostics Diagnostics { get; }
|
||||||
private Binder.Binder Binder { get; }
|
private Binder.Binder Binder { get; }
|
||||||
public EvaluationScope Scope { get; }
|
public EvaluationScope Scope { get; }
|
||||||
|
@ -30,7 +31,7 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
public BoundScript Bind()
|
public BoundScript Bind()
|
||||||
{
|
{
|
||||||
return Binder.BindScript(_parsed);
|
return _bound ?? (_bound = Binder.BindScript(_parsed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Evaluate()
|
public object Evaluate()
|
||||||
|
@ -38,11 +39,21 @@ namespace Upsilon.Evaluator
|
||||||
return Evaluator.Evaluate(Bind());
|
return Evaluator.Evaluate(Bind());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object EvaluateFunction(string functionName)
|
||||||
|
{
|
||||||
|
return Evaluator.Evaluate(Bind(), functionName);
|
||||||
|
}
|
||||||
|
|
||||||
public T Evaluate<T>() where T : LuaType
|
public T Evaluate<T>() where T : LuaType
|
||||||
{
|
{
|
||||||
return (T)Evaluator.Evaluate(Bind());
|
return (T)Evaluator.Evaluate(Bind());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T EvaluateFunction<T>(string functionName) where T : LuaType
|
||||||
|
{
|
||||||
|
return (T)Evaluator.Evaluate(Bind(), functionName);
|
||||||
|
}
|
||||||
|
|
||||||
public string PrettyPrintSyntaxTree()
|
public string PrettyPrintSyntaxTree()
|
||||||
{
|
{
|
||||||
return _parsed.Print();
|
return _parsed.Print();
|
||||||
|
|
|
@ -151,5 +151,20 @@ a = 87
|
||||||
Assert.Equal(60, (long)(NumberLong)result);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue