RelationalExpression
using CLanguage.Compiler;
using CLanguage.Interpreter;
using CLanguage.Types;
using System;
using System.Runtime.CompilerServices;
namespace CLanguage.Syntax
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class RelationalExpression : Expression
{
public Expression Left { get; set; }
public RelationalOp Op { get; set; }
public Expression Right { get; set; }
public RelationalExpression(Expression left, RelationalOp op, Expression right)
{
Left = left;
Op = op;
Right = right;
}
protected override void DoEmit(EmitContext ec)
{
Expression left = Left;
Expression right = Right;
RelationalOp op = Op;
CType arithmeticType = Expression.GetArithmeticType(left, right, op.ToString(), ec);
Left.Emit(ec);
ec.EmitCast(Left.GetEvaluatedCType(ec), arithmeticType);
Right.Emit(ec);
ec.EmitCast(Right.GetEvaluatedCType(ec), arithmeticType);
int instructionOffset = ec.GetInstructionOffset(arithmeticType);
op = Op;
switch (op) {
case RelationalOp.Equals:
ec.Emit((OpCode)(88 + instructionOffset));
break;
case RelationalOp.NotEquals:
ec.Emit((OpCode)(88 + instructionOffset));
ec.Emit((OpCode)(148 + instructionOffset));
break;
case RelationalOp.LessThan:
ec.Emit((OpCode)(98 + instructionOffset));
break;
case RelationalOp.LessThanOrEqual:
ec.Emit((OpCode)(108 + instructionOffset));
ec.Emit((OpCode)(148 + instructionOffset));
break;
case RelationalOp.GreaterThan:
ec.Emit((OpCode)(108 + instructionOffset));
break;
case RelationalOp.GreaterThanOrEqual:
ec.Emit((OpCode)(98 + instructionOffset));
ec.Emit((OpCode)(148 + instructionOffset));
break;
default:
throw new NotSupportedException("Unsupported relational operator '" + Op.ToString() + "'");
}
}
public override Value EvalConstant(EmitContext ec)
{
CType evaluatedCType = Left.GetEvaluatedCType(ec);
CType evaluatedCType2 = Right.GetEvaluatedCType(ec);
if (evaluatedCType.IsIntegral && evaluatedCType2.IsIntegral) {
int num = (int)Left.EvalConstant(ec);
int num2 = (int)Right.EvalConstant(ec);
switch (Op) {
case RelationalOp.Equals:
return num == num2;
case RelationalOp.NotEquals:
return num != num2;
case RelationalOp.LessThan:
return num < num2;
case RelationalOp.LessThanOrEqual:
return num <= num2;
case RelationalOp.GreaterThan:
return num > num2;
case RelationalOp.GreaterThanOrEqual:
return num >= num2;
default:
throw new NotSupportedException("Unsupported relational operator '" + Op.ToString() + "'");
}
}
return base.EvalConstant(ec);
}
public override CType GetEvaluatedCType(EmitContext ec)
{
return CBasicType.Bool;
}
public override string ToString()
{
return string.Format("({0} {1} {2})", new object[3] {
Left,
Op,
Right
});
}
}
}