Add Function Calling
This commit is contained in:
parent
07660b6c46
commit
d5c8a959fb
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
|
@ -57,6 +58,8 @@ namespace Upsilon.Binder
|
||||||
return BindParenthesizedExpression((ParenthesizedExpressionSyntax) e);
|
return BindParenthesizedExpression((ParenthesizedExpressionSyntax) e);
|
||||||
case SyntaxKind.VariableExpression:
|
case SyntaxKind.VariableExpression:
|
||||||
return BindVariableExpression((VariableExpressionSyntax) e);
|
return BindVariableExpression((VariableExpressionSyntax) e);
|
||||||
|
case SyntaxKind.FunctionCallExpression:
|
||||||
|
return BindFunctionCallExpression((FunctionCallExpressionSyntax) e);
|
||||||
case SyntaxKind.BadExpression:
|
case SyntaxKind.BadExpression:
|
||||||
break;
|
break;
|
||||||
case SyntaxKind.ScriptUnit:
|
case SyntaxKind.ScriptUnit:
|
||||||
|
@ -123,6 +126,37 @@ namespace Upsilon.Binder
|
||||||
return BindExpression(e.Expression);
|
return BindExpression(e.Expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BoundExpression BindFunctionCallExpression(FunctionCallExpressionSyntax e)
|
||||||
|
{
|
||||||
|
var name = e.Identifier.Name;
|
||||||
|
if (!_scope.TryGetVariable(name, true, out var functionObj))
|
||||||
|
{
|
||||||
|
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
|
||||||
|
return new BoundLiteralExpression(new LuaNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
var function = (FunctionVariableSymbol) functionObj;
|
||||||
|
|
||||||
|
var parameters = ImmutableArray.CreateBuilder<BoundExpression>();
|
||||||
|
foreach (var expressionSyntax in e.Parameters)
|
||||||
|
{
|
||||||
|
var bound = BindExpression(expressionSyntax);
|
||||||
|
parameters.Add(bound);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < function.Parameters.Length; index++)
|
||||||
|
{
|
||||||
|
var parameter = function.Parameters[index];
|
||||||
|
if (parameter.Type == Type.Unknown)
|
||||||
|
{
|
||||||
|
parameter.Type = parameters[index].Type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: validate parameters
|
||||||
|
return new BoundFunctionCallExpression((FunctionVariableSymbol) function, parameters.ToImmutable());
|
||||||
|
}
|
||||||
|
|
||||||
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
|
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
|
||||||
{
|
{
|
||||||
var name = e.Identifier.Name;
|
var name = e.Identifier.Name;
|
||||||
|
@ -164,6 +198,14 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
variable.Type = boundExpression.Type;
|
variable.Type = boundExpression.Type;
|
||||||
}
|
}
|
||||||
|
else if (variable.Type == Type.Unknown)
|
||||||
|
{
|
||||||
|
variable.Type = boundExpression.Type;
|
||||||
|
}
|
||||||
|
else if (boundExpression.Type == Type.Unknown && boundExpression is BoundVariableExpression v)
|
||||||
|
{
|
||||||
|
v.Variable.Type = variable.Type;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_diagnostics.LogCannotConvert(boundExpression.Type, variable.Type, e.Span);
|
_diagnostics.LogCannotConvert(boundExpression.Type, variable.Type, e.Span);
|
||||||
|
|
|
@ -12,12 +12,12 @@ namespace Upsilon.Binder
|
||||||
Addition, Subtraction, Multiplication, Division, Equality, Inequality
|
Addition, Subtraction, Multiplication, Division, Equality, Inequality
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type LeftType { get; }
|
private Type LeftType { get; }
|
||||||
public Type RightType { get; }
|
private Type RightType { get; }
|
||||||
public Type OutType { get; }
|
public Type OutType { get; }
|
||||||
public OperatorKind Kind { get; }
|
public OperatorKind Kind { get; }
|
||||||
|
|
||||||
public BoundBinaryOperator(OperatorKind kind, Type outType)
|
private BoundBinaryOperator(OperatorKind kind, Type outType)
|
||||||
{
|
{
|
||||||
Kind = kind;
|
Kind = kind;
|
||||||
LeftType = outType;
|
LeftType = outType;
|
||||||
|
@ -25,7 +25,7 @@ namespace Upsilon.Binder
|
||||||
OutType = outType;
|
OutType = outType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundBinaryOperator(OperatorKind kind, Type leftType, Type rightType, Type outType)
|
private BoundBinaryOperator(OperatorKind kind, Type leftType, Type rightType, Type outType)
|
||||||
{
|
{
|
||||||
Kind = kind;
|
Kind = kind;
|
||||||
LeftType = leftType;
|
LeftType = leftType;
|
||||||
|
@ -33,7 +33,7 @@ namespace Upsilon.Binder
|
||||||
OutType = outType;
|
OutType = outType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BoundBinaryOperator[] Operators = new BoundBinaryOperator[]
|
private static readonly BoundBinaryOperator[] Operators = new[]
|
||||||
{
|
{
|
||||||
// Math operators
|
// Math operators
|
||||||
new BoundBinaryOperator(OperatorKind.Addition, Type.Number),
|
new BoundBinaryOperator(OperatorKind.Addition, Type.Number),
|
||||||
|
@ -77,6 +77,13 @@ namespace Upsilon.Binder
|
||||||
throw new Exception("Unknown binary operator token: " + operatorToken);
|
throw new Exception("Unknown binary operator token: " + operatorToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (left == Type.Unknown && right == Type.Unknown)
|
||||||
|
return Operators.FirstOrDefault(op => op.Kind == kind);
|
||||||
|
if (left == Type.Unknown)
|
||||||
|
return Operators.FirstOrDefault(op => op.Kind == kind && op.RightType == right);
|
||||||
|
if (right == Type.Unknown)
|
||||||
|
return Operators.FirstOrDefault(op => op.Kind == kind && op.LeftType == left);
|
||||||
|
|
||||||
return Operators.FirstOrDefault(op => op.Kind == kind && op.LeftType == left && op.RightType == right);
|
return Operators.FirstOrDefault(op => op.Kind == kind && op.LeftType == left && op.RightType == right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.BaseTypes;
|
||||||
|
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class BoundFunctionCallExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public FunctionVariableSymbol Identifier { get; }
|
||||||
|
public ImmutableArray<BoundExpression> Parameters { get; }
|
||||||
|
|
||||||
|
public BoundFunctionCallExpression(FunctionVariableSymbol identifier, ImmutableArray<BoundExpression> parameters)
|
||||||
|
{
|
||||||
|
Identifier = identifier;
|
||||||
|
Parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
||||||
|
public override Type Type => Type.Nil;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ namespace Upsilon.Binder
|
||||||
BoundBinaryExpression,
|
BoundBinaryExpression,
|
||||||
BoundUnaryExpression,
|
BoundUnaryExpression,
|
||||||
VariableExpression,
|
VariableExpression,
|
||||||
|
BoundFunctionCallExpression,
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
BoundAssignmentStatement,
|
BoundAssignmentStatement,
|
||||||
|
@ -15,6 +16,6 @@ namespace Upsilon.Binder
|
||||||
BoundBlockStatement,
|
BoundBlockStatement,
|
||||||
BoundIfStatement,
|
BoundIfStatement,
|
||||||
BoundElseStatement,
|
BoundElseStatement,
|
||||||
BoundFunctionStatement
|
BoundFunctionStatement,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class UnboundFunction
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,17 +7,17 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
public class EvaluationScope
|
public class EvaluationScope
|
||||||
{
|
{
|
||||||
private readonly EvaluationScope _parentScope;
|
public readonly EvaluationScope ParentScope;
|
||||||
private readonly Dictionary<VariableSymbol, LuaType> _variables;
|
private readonly Dictionary<VariableSymbol, LuaType> _variables;
|
||||||
|
|
||||||
internal EvaluationScope(EvaluationScope parentScope)
|
internal EvaluationScope(EvaluationScope parentScope)
|
||||||
{
|
{
|
||||||
_parentScope = parentScope;
|
ParentScope = parentScope;
|
||||||
_variables = new Dictionary<VariableSymbol, LuaType>();
|
_variables = new Dictionary<VariableSymbol, LuaType>();
|
||||||
}
|
}
|
||||||
internal EvaluationScope(Dictionary<VariableSymbol, LuaType> vars)
|
internal EvaluationScope(Dictionary<VariableSymbol, LuaType> vars)
|
||||||
{
|
{
|
||||||
_variables = vars;
|
_variables = new Dictionary<VariableSymbol, LuaType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(VariableSymbol symbol, LuaType obj)
|
public void Set(VariableSymbol symbol, LuaType obj)
|
||||||
|
@ -34,8 +34,8 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
public void SetGlobal(VariableSymbol symbol, LuaType obj)
|
public void SetGlobal(VariableSymbol symbol, LuaType obj)
|
||||||
{
|
{
|
||||||
if (_parentScope != null)
|
if (ParentScope != null)
|
||||||
_parentScope.SetGlobal(symbol, obj);
|
ParentScope.SetGlobal(symbol, obj);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Set(symbol, obj);
|
Set(symbol, obj);
|
||||||
|
@ -46,8 +46,8 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
if (_variables.TryGetValue(symbol, out obj))
|
if (_variables.TryGetValue(symbol, out obj))
|
||||||
return true;
|
return true;
|
||||||
if (_parentScope != null)
|
if (ParentScope != null)
|
||||||
if (_parentScope.TryGet(symbol, out obj))
|
if (ParentScope.TryGet(symbol, out obj))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,8 @@ namespace Upsilon.Evaluator
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (_parentScope != null)
|
if (ParentScope != null)
|
||||||
if (_parentScope.TryGet(variable, out obj))
|
if (ParentScope.TryGet(variable, out obj))
|
||||||
return true;
|
return true;
|
||||||
obj = null;
|
obj = null;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
|
@ -9,12 +10,12 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
private readonly Diagnostics _diagnostics;
|
private readonly Diagnostics _diagnostics;
|
||||||
private LuaType _value;
|
private LuaType _value;
|
||||||
private readonly EvaluationScope _scope;
|
public EvaluationScope Scope { get; private set; }
|
||||||
|
|
||||||
internal Evaluator(Diagnostics diagnostics, EvaluationScope parentScope)
|
internal Evaluator(Diagnostics diagnostics, Dictionary<VariableSymbol, LuaType> variables)
|
||||||
{
|
{
|
||||||
_diagnostics = diagnostics;
|
_diagnostics = diagnostics;
|
||||||
_scope = new EvaluationScope(parentScope);
|
Scope = new EvaluationScope(variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaType Evaluate(BoundScript e)
|
public LuaType Evaluate(BoundScript e)
|
||||||
|
@ -63,6 +64,8 @@ namespace Upsilon.Evaluator
|
||||||
return EvaluateUnaryExpression((BoundUnaryExpression) e);
|
return EvaluateUnaryExpression((BoundUnaryExpression) e);
|
||||||
case BoundKind.VariableExpression:
|
case BoundKind.VariableExpression:
|
||||||
return EvaluateVariableExpression((BoundVariableExpression) e);
|
return EvaluateVariableExpression((BoundVariableExpression) e);
|
||||||
|
case BoundKind.BoundFunctionCallExpression:
|
||||||
|
return EvaluateBoundFunctionCallExpression((BoundFunctionCallExpression) e);
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -112,18 +115,18 @@ namespace Upsilon.Evaluator
|
||||||
var val = EvaluateExpression(e.BoundExpression);
|
var val = EvaluateExpression(e.BoundExpression);
|
||||||
if (e.Variable.Local)
|
if (e.Variable.Local)
|
||||||
{
|
{
|
||||||
_scope.Set(e.Variable, val);
|
Scope.Set(e.Variable, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_scope.SetGlobal(e.Variable, val);
|
Scope.SetGlobal(e.Variable, val);
|
||||||
}
|
}
|
||||||
_value = val;
|
_value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaType EvaluateVariableExpression(BoundVariableExpression e)
|
private LuaType EvaluateVariableExpression(BoundVariableExpression e)
|
||||||
{
|
{
|
||||||
if (_scope.TryGet(e.Variable, out var val))
|
if (Scope.TryGet(e.Variable, out var val))
|
||||||
{
|
{
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -132,18 +135,15 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
|
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
|
||||||
{
|
{
|
||||||
var innerEvaluator = new Evaluator(_diagnostics, _scope);
|
|
||||||
foreach (var boundStatement in boundBlockStatement.Statements)
|
foreach (var boundStatement in boundBlockStatement.Statements)
|
||||||
{
|
{
|
||||||
innerEvaluator.EvaluateStatement(boundStatement);
|
EvaluateStatement(boundStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (innerEvaluator._value != null)
|
|
||||||
_value = innerEvaluator._value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement)
|
private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement)
|
||||||
{
|
{
|
||||||
|
Scope = new EvaluationScope(Scope);
|
||||||
var condition = EvaluateExpression(boundBlockStatement.Condition.Expression);
|
var condition = EvaluateExpression(boundBlockStatement.Condition.Expression);
|
||||||
if ((LuaBoolean) condition)
|
if ((LuaBoolean) condition)
|
||||||
{
|
{
|
||||||
|
@ -157,15 +157,39 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
EvaluateBoundBlockStatement(boundBlockStatement.ElseStatement.Block);
|
EvaluateBoundBlockStatement(boundBlockStatement.ElseStatement.Block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope = Scope.ParentScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EvaluateBoundFunctionStatement(BoundFunctionStatement boundFunctionStatement)
|
private void EvaluateBoundFunctionStatement(BoundFunctionStatement boundFunctionStatement)
|
||||||
{
|
{
|
||||||
var func = new LuaFunction(boundFunctionStatement.Parameters, boundFunctionStatement.Block);
|
var func = new LuaFunction(boundFunctionStatement.Parameters, boundFunctionStatement.Block);
|
||||||
if (boundFunctionStatement.Identifier.Local)
|
if (boundFunctionStatement.Identifier.Local)
|
||||||
_scope.Set(boundFunctionStatement.Identifier, func);
|
Scope.Set(boundFunctionStatement.Identifier, func);
|
||||||
else
|
else
|
||||||
_scope.SetGlobal(boundFunctionStatement.Identifier, func);
|
Scope.SetGlobal(boundFunctionStatement.Identifier, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LuaType EvaluateBoundFunctionCallExpression(BoundFunctionCallExpression boundFunctionCallExpression)
|
||||||
|
{
|
||||||
|
var name = boundFunctionCallExpression.Identifier;
|
||||||
|
if (!Scope.TryGet(name, out var functionObj))
|
||||||
|
{
|
||||||
|
throw new Exception("Cannot find function: " + name.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var function = (LuaFunction) functionObj;
|
||||||
|
|
||||||
|
Scope = new EvaluationScope(Scope);
|
||||||
|
for (var i = 0; i < function.Parameters.Length; i++)
|
||||||
|
{
|
||||||
|
var parameterVariable = function.Parameters[i];
|
||||||
|
var parameterValue = EvaluateExpression(boundFunctionCallExpression.Parameters[i]);
|
||||||
|
Scope.Set(parameterVariable, parameterValue);
|
||||||
|
}
|
||||||
|
EvaluateBoundBlockStatement(function.Block);
|
||||||
|
Scope = Scope.ParentScope;
|
||||||
|
return _value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,8 +24,8 @@ namespace Upsilon.Evaluator
|
||||||
if (variables == null)
|
if (variables == null)
|
||||||
variables = new Dictionary<VariableSymbol, LuaType>();
|
variables = new Dictionary<VariableSymbol, LuaType>();
|
||||||
Binder = new Binder.Binder(Diagnostics);
|
Binder = new Binder.Binder(Diagnostics);
|
||||||
Scope = new EvaluationScope(variables);
|
Evaluator = new Evaluator( Diagnostics, variables);
|
||||||
Evaluator = new Evaluator( Diagnostics, Scope);
|
Scope = Evaluator.Scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundScript Bind()
|
public BoundScript Bind()
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Upsilon.Parser
|
||||||
|
{
|
||||||
|
public class FunctionCallExpressionSyntax : ExpressionSyntax
|
||||||
|
{
|
||||||
|
public IdentifierToken Identifier { get; }
|
||||||
|
public SyntaxToken OpenParenthesis { get; }
|
||||||
|
public ImmutableArray<ExpressionSyntax> Parameters { get; }
|
||||||
|
public SyntaxToken CloseParenthesis { get; }
|
||||||
|
|
||||||
|
public FunctionCallExpressionSyntax(IdentifierToken identifier, SyntaxToken openParenthesis,
|
||||||
|
ImmutableArray<ExpressionSyntax> parameters, SyntaxToken closeParenthesis)
|
||||||
|
{
|
||||||
|
Identifier = identifier;
|
||||||
|
OpenParenthesis = openParenthesis;
|
||||||
|
Parameters = parameters;
|
||||||
|
CloseParenthesis = closeParenthesis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;
|
||||||
|
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||||
|
{
|
||||||
|
yield return Identifier;
|
||||||
|
yield return OpenParenthesis;
|
||||||
|
foreach (var expressionSyntax in Parameters)
|
||||||
|
{
|
||||||
|
yield return expressionSyntax;
|
||||||
|
}
|
||||||
|
yield return CloseParenthesis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -213,6 +213,8 @@ namespace Upsilon.Parser
|
||||||
case SyntaxKind.FalseKeyword:
|
case SyntaxKind.FalseKeyword:
|
||||||
return ParseBoolean();
|
return ParseBoolean();
|
||||||
case SyntaxKind.Identifier:
|
case SyntaxKind.Identifier:
|
||||||
|
if (Next.Kind == SyntaxKind.OpenParenthesis)
|
||||||
|
return ParseFunctionCallExpression();
|
||||||
var token = MatchToken(SyntaxKind.Identifier);
|
var token = MatchToken(SyntaxKind.Identifier);
|
||||||
return new VariableExpressionSyntax((IdentifierToken) token);
|
return new VariableExpressionSyntax((IdentifierToken) token);
|
||||||
case SyntaxKind.NilKeyword:
|
case SyntaxKind.NilKeyword:
|
||||||
|
@ -225,6 +227,24 @@ namespace Upsilon.Parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExpressionSyntax ParseFunctionCallExpression()
|
||||||
|
{
|
||||||
|
var identifier = MatchToken(SyntaxKind.Identifier);
|
||||||
|
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
|
||||||
|
var parameters = ImmutableArray.CreateBuilder<ExpressionSyntax>();
|
||||||
|
while (Current.Kind != SyntaxKind.CloseParenthesis)
|
||||||
|
{
|
||||||
|
var exp = ParseExpression();
|
||||||
|
parameters.Add(exp);
|
||||||
|
if (Current.Kind == SyntaxKind.Comma)
|
||||||
|
NextToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
var closeParenthesis = MatchToken(SyntaxKind.CloseParenthesis);
|
||||||
|
return new FunctionCallExpressionSyntax((IdentifierToken) identifier, openParenthesis,
|
||||||
|
parameters.ToImmutable(), closeParenthesis);
|
||||||
|
}
|
||||||
|
|
||||||
private ExpressionSyntax ParseParenthesizedExpression()
|
private ExpressionSyntax ParseParenthesizedExpression()
|
||||||
{
|
{
|
||||||
var l = MatchToken(SyntaxKind.OpenParenthesis);
|
var l = MatchToken(SyntaxKind.OpenParenthesis);
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace Upsilon.Parser
|
||||||
ParenthesizedExpression,
|
ParenthesizedExpression,
|
||||||
AssignmentStatement,
|
AssignmentStatement,
|
||||||
VariableExpression,
|
VariableExpression,
|
||||||
|
FunctionCallExpression,
|
||||||
BadExpression,
|
BadExpression,
|
||||||
|
|
||||||
// script unit
|
// script unit
|
||||||
|
|
|
@ -26,5 +26,43 @@ testFunc()
|
||||||
Assert.True(script.Scope.TryGet("a", out var a));
|
Assert.True(script.Scope.TryGet("a", out var a));
|
||||||
Assert.Equal(100, (long)(NumberLong)a);
|
Assert.Equal(100, (long)(NumberLong)a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ParameterTest()
|
||||||
|
{
|
||||||
|
const string input = @"
|
||||||
|
function testFunc (var1)
|
||||||
|
a = var1
|
||||||
|
end
|
||||||
|
a = 50
|
||||||
|
testFunc(100)
|
||||||
|
";
|
||||||
|
var script = new Script(input);
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
script.Evaluate();
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
Assert.True(script.Scope.TryGet("testFunc", out var func));
|
||||||
|
Assert.IsType<LuaFunction>(func);
|
||||||
|
Assert.True(script.Scope.TryGet("a", out var a));
|
||||||
|
Assert.Equal(100, (long)(NumberLong)a);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ParameterBindTest()
|
||||||
|
{
|
||||||
|
const string input = @"
|
||||||
|
function testFunc (var1)
|
||||||
|
b = var1 == true
|
||||||
|
end
|
||||||
|
testFunc(100)
|
||||||
|
";
|
||||||
|
var script = new Script(input);
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
script.Evaluate();
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
Assert.True(script.Scope.TryGet("testFunc", out var func));
|
||||||
|
Assert.IsType<LuaFunction>(func);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue