152 lines
5.6 KiB
C#
152 lines
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Upsilon.BaseTypes;
|
|
using Upsilon.BaseTypes.Number;
|
|
using Upsilon.Binder;
|
|
|
|
namespace Upsilon.Evaluator
|
|
{
|
|
public class Evaluator
|
|
{
|
|
private readonly Diagnostics _diagnostics;
|
|
private LuaType _value;
|
|
private Script Script { get; }
|
|
private readonly Dictionary<VariableSymbol, LuaType> _variables = new Dictionary<VariableSymbol, LuaType>();
|
|
|
|
public Evaluator(Script script, Diagnostics diagnostics)
|
|
{
|
|
_diagnostics = diagnostics;
|
|
Script = script;
|
|
}
|
|
public Evaluator(Script script, Diagnostics diagnostics, Dictionary<VariableSymbol, LuaType> vars)
|
|
{
|
|
_diagnostics = diagnostics;
|
|
Script = script;
|
|
_variables = vars;
|
|
}
|
|
|
|
public LuaType Evaluate(BoundScript e)
|
|
{
|
|
EvaluateStatement(e.Statement);
|
|
return _value;
|
|
}
|
|
|
|
private void EvaluateStatement(BoundStatement e)
|
|
{
|
|
switch (e.Kind)
|
|
{
|
|
case BoundKind.BoundAssignmentStatement:
|
|
EvaluateAssignmentStatement((BoundVariableAssignment) e);
|
|
break;
|
|
case BoundKind.BoundBlockStatement:
|
|
EvaluateBoundBlockStatement((BoundBlockStatement) e);
|
|
break;
|
|
case BoundKind.BoundIfStatement:
|
|
EvaluateBoundIfStatement((BoundIfStatement) e);
|
|
break;
|
|
default:
|
|
EvaluateExpressionStatement((BoundExpressionStatement) e);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
private void EvaluateExpressionStatement(BoundExpressionStatement e)
|
|
{
|
|
_value = EvaluateExpression(e.Expression);
|
|
}
|
|
|
|
private LuaType EvaluateExpression(BoundExpression e)
|
|
{
|
|
switch (e.Kind)
|
|
{
|
|
case BoundKind.BoundLiteralExpression:
|
|
return ((BoundLiteralExpression) e).Value;
|
|
case BoundKind.BoundBinaryExpression:
|
|
return EvaluateBinaryExpression((BoundBinaryExpression) e);
|
|
case BoundKind.BoundUnaryExpression:
|
|
return EvaluateUnaryExpression((BoundUnaryExpression) e);
|
|
case BoundKind.VariableExpression:
|
|
return EvaluateVariableExpression((BoundVariableExpression) e);
|
|
default:
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
private LuaType EvaluateUnaryExpression(BoundUnaryExpression e)
|
|
{
|
|
var operand = EvaluateExpression(e.InExpression);
|
|
switch (e.Operator.Kind)
|
|
{
|
|
case BoundUnaryOperator.OperatorKind.Identity:
|
|
return operand;
|
|
case BoundUnaryOperator.OperatorKind.Negation:
|
|
return -((Number)operand);
|
|
case BoundUnaryOperator.OperatorKind.LogicalNegation:
|
|
return !(LuaBoolean) operand;
|
|
default:
|
|
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
|
|
}
|
|
}
|
|
|
|
private LuaType EvaluateBinaryExpression(BoundBinaryExpression e)
|
|
{
|
|
var left = EvaluateExpression(e.LeftExpression);
|
|
var right = EvaluateExpression(e.RightExpression);
|
|
switch (e.Operator.Kind)
|
|
{
|
|
case BoundBinaryOperator.OperatorKind.Addition:
|
|
return ((Number)left) + ((Number)right);
|
|
case BoundBinaryOperator.OperatorKind.Subtraction:
|
|
return ((Number)left) - ((Number)right);
|
|
case BoundBinaryOperator.OperatorKind.Multiplication:
|
|
return ((Number)left) * ((Number)right);
|
|
case BoundBinaryOperator.OperatorKind.Division:
|
|
return ((Number)left) / ((Number)right);
|
|
case BoundBinaryOperator.OperatorKind.Equality:
|
|
return new LuaBoolean(Equals(left, right));
|
|
case BoundBinaryOperator.OperatorKind.Inequality:
|
|
return new LuaBoolean(!Equals(left, right));
|
|
default:
|
|
throw new Exception("Invalid Binary Operator: " + e.Operator);
|
|
}
|
|
}
|
|
|
|
private void EvaluateAssignmentStatement(BoundVariableAssignment e)
|
|
{
|
|
var val = EvaluateExpression(e.BoundExpression);
|
|
_variables[e.Variable] = val;
|
|
_value = val;
|
|
}
|
|
|
|
private LuaType EvaluateVariableExpression(BoundVariableExpression e)
|
|
{
|
|
return _variables[e.Variable];
|
|
}
|
|
|
|
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
|
|
{
|
|
foreach (var boundStatement in boundBlockStatement.Statements)
|
|
{
|
|
EvaluateStatement(boundStatement);
|
|
}
|
|
}
|
|
|
|
private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement)
|
|
{
|
|
var condition = EvaluateExpression(boundBlockStatement.Condition.Expression);
|
|
if ((LuaBoolean) condition)
|
|
{
|
|
EvaluateBoundBlockStatement(boundBlockStatement.Block);
|
|
}
|
|
else if (boundBlockStatement.NextElseIf != null)
|
|
{
|
|
EvaluateBoundIfStatement(boundBlockStatement.NextElseIf);
|
|
}
|
|
else if (boundBlockStatement.ElseStatement != null)
|
|
{
|
|
EvaluateBoundBlockStatement(boundBlockStatement.ElseStatement.Block);
|
|
}
|
|
}
|
|
}
|
|
} |