Upsilon/Upsilon/Evaluator/Evaluator.cs

152 lines
5.6 KiB
C#
Raw Normal View History

2018-11-10 12:11:36 +00:00
using System;
2018-11-11 19:31:55 +00:00
using System.Collections.Generic;
using Upsilon.BaseTypes;
2018-11-11 17:12:42 +00:00
using Upsilon.BaseTypes.Number;
using Upsilon.Binder;
2018-11-10 12:11:36 +00:00
namespace Upsilon.Evaluator
{
2018-11-10 16:00:39 +00:00
public class Evaluator
2018-11-10 12:11:36 +00:00
{
2018-11-11 09:26:52 +00:00
private readonly Diagnostics _diagnostics;
private LuaType _value;
private Script Script { get; }
private readonly Dictionary<VariableSymbol, LuaType> _variables = new Dictionary<VariableSymbol, LuaType>();
2018-11-10 16:00:39 +00:00
2018-11-11 17:12:42 +00:00
public Evaluator(Script script, Diagnostics diagnostics)
2018-11-10 16:00:39 +00:00
{
2018-11-11 09:26:52 +00:00
_diagnostics = diagnostics;
2018-11-11 20:03:50 +00:00
Script = script;
}
public Evaluator(Script script, Diagnostics diagnostics, Dictionary<VariableSymbol, LuaType> vars)
2018-11-11 20:03:50 +00:00
{
_diagnostics = diagnostics;
Script = script;
_variables = vars;
2018-11-10 16:00:39 +00:00
}
public LuaType Evaluate(BoundScript e)
2018-11-10 12:11:36 +00:00
{
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;
2018-11-13 11:48:50 +00:00
case BoundKind.BoundIfStatement:
EvaluateBoundIfStatement((BoundIfStatement) e);
break;
default:
EvaluateExpressionStatement((BoundExpressionStatement) e);
break;
}
}
private void EvaluateExpressionStatement(BoundExpressionStatement e)
{
_value = EvaluateExpression(e.Expression);
2018-11-10 12:11:36 +00:00
}
private LuaType EvaluateExpression(BoundExpression e)
2018-11-10 12:11:36 +00:00
{
switch (e.Kind)
{
2018-11-11 17:12:42 +00:00
case BoundKind.BoundLiteralExpression:
return ((BoundLiteralExpression) e).Value;
case BoundKind.BoundBinaryExpression:
return EvaluateBinaryExpression((BoundBinaryExpression) e);
2018-11-11 18:56:53 +00:00
case BoundKind.BoundUnaryExpression:
return EvaluateUnaryExpression((BoundUnaryExpression) e);
2018-11-11 20:03:50 +00:00
case BoundKind.VariableExpression:
return EvaluateVariableExpression((BoundVariableExpression) e);
2018-11-10 12:11:36 +00:00
default:
2018-11-11 18:56:53 +00:00
throw new NotImplementedException();
2018-11-10 12:11:36 +00:00
}
}
private LuaType EvaluateUnaryExpression(BoundUnaryExpression e)
2018-11-10 12:11:36 +00:00
{
2018-11-11 18:56:53 +00:00
var operand = EvaluateExpression(e.InExpression);
2018-11-10 12:11:36 +00:00
switch (e.Operator.Kind)
{
2018-11-11 18:56:53 +00:00
case BoundUnaryOperator.OperatorKind.Identity:
2018-11-10 12:11:36 +00:00
return operand;
2018-11-11 18:56:53 +00:00
case BoundUnaryOperator.OperatorKind.Negation:
return -((Number)operand);
case BoundUnaryOperator.OperatorKind.LogicalNegation:
return !(LuaBoolean) operand;
2018-11-10 12:11:36 +00:00
default:
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
}
2018-11-11 18:56:53 +00:00
}
2018-11-10 12:11:36 +00:00
private LuaType EvaluateBinaryExpression(BoundBinaryExpression e)
2018-11-10 12:11:36 +00:00
{
2018-11-11 17:12:42 +00:00
var left = EvaluateExpression(e.LeftExpression);
var right = EvaluateExpression(e.RightExpression);
switch (e.Operator.Kind)
2018-11-11 09:26:52 +00:00
{
2018-11-11 17:12:42 +00:00
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));
2018-11-11 17:12:42 +00:00
case BoundBinaryOperator.OperatorKind.Inequality:
return new LuaBoolean(!Equals(left, right));
2018-11-11 17:12:42 +00:00
default:
throw new Exception("Invalid Binary Operator: " + e.Operator);
2018-11-10 12:11:36 +00:00
}
}
private void EvaluateAssignmentStatement(BoundVariableAssignment e)
2018-11-10 16:00:39 +00:00
{
var val = EvaluateExpression(e.BoundExpression);
2018-11-11 20:03:50 +00:00
_variables[e.Variable] = val;
_value = val;
2018-11-11 19:31:55 +00:00
}
2018-11-10 16:00:39 +00:00
private LuaType EvaluateVariableExpression(BoundVariableExpression e)
2018-11-10 16:00:39 +00:00
{
2018-11-11 20:03:50 +00:00
return _variables[e.Variable];
2018-11-10 16:00:39 +00:00
}
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
{
foreach (var boundStatement in boundBlockStatement.Statements)
{
EvaluateStatement(boundStatement);
}
}
2018-11-13 11:48:50 +00:00
private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement)
{
var condition = EvaluateExpression(boundBlockStatement.Condition.Expression);
if ((LuaBoolean) condition)
2018-11-13 11:48:50 +00:00
{
EvaluateBoundBlockStatement(boundBlockStatement.Block);
}
2018-11-13 14:15:44 +00:00
else if (boundBlockStatement.NextElseIf != null)
{
EvaluateBoundIfStatement(boundBlockStatement.NextElseIf);
}
2018-11-13 12:54:51 +00:00
else if (boundBlockStatement.ElseStatement != null)
{
EvaluateBoundBlockStatement(boundBlockStatement.ElseStatement.Block);
}
2018-11-13 11:48:50 +00:00
}
2018-11-10 12:11:36 +00:00
}
}