Example #1
0
ExprNodePtr
BoolType::castValue (LContext &lcontext, const ExprNodePtr &expr) const
{
    if (IntLiteralNodePtr x = expr.cast<IntLiteralNode>())
	return lcontext.newBoolLiteralNode (x->lineNumber, (bool) x->value);

    if (UIntLiteralNodePtr x = expr.cast<UIntLiteralNode>())
	return lcontext.newBoolLiteralNode (x->lineNumber, (bool) x->value);

    if (HalfLiteralNodePtr x = expr.cast<HalfLiteralNode>())
	return lcontext.newBoolLiteralNode (x->lineNumber, (bool) x->value);

    if (FloatLiteralNodePtr x = expr.cast<FloatLiteralNode>())
	return lcontext.newBoolLiteralNode (x->lineNumber, (bool) x->value);

    return expr;
}
Example #2
0
ExprNodePtr
IntType::evaluate (LContext &lcontext, const ExprNodePtr &expr) const
{
    if (UnaryOpNodePtr unOp = expr.cast<UnaryOpNode>())
    {
	IntLiteralNodePtr x = unOp->operand.cast<IntLiteralNode>();

	if (x)
	{
	    switch (unOp->op)
	    {
	      case TK_BITNOT:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, ~x->value);

	      case TK_MINUS:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, -x->value);

	      case TK_NOT:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, !x->value);

	      default:

		MESSAGE_LE (lcontext, ERR_OP_TYPE, expr->lineNumber,
		    "Cannot apply " << tokenAsString (unOp->op) << " "
		    "operator to value of type " << asString() << ".");
	    }
	}
    }

    if (BinaryOpNodePtr binOp = expr.cast<BinaryOpNode>())
    {
	IntLiteralNodePtr x =
	    evaluate(lcontext, binOp->leftOperand).cast<IntLiteralNode>();

	IntLiteralNodePtr y =
	    evaluate(lcontext, binOp->rightOperand).cast<IntLiteralNode>();

	if (x && y)
	{
	    switch (binOp->op)
	    {
	      case TK_AND:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value && y->value);

	      case TK_BITAND:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value & y->value);

	      case TK_BITOR:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value | y->value);

	      case TK_BITXOR:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value ^ y->value);

	      case TK_DIV:
		if (y->value != 0)
		{
		    return lcontext.newIntLiteralNode
				(expr->lineNumber, x->value / y->value);
		}
		else
		{
		    MESSAGE_LW (lcontext, ERR_DIV_ZERO, expr->lineNumber,
				"Warning: Division by zero "
				"(" << x->value << "/" << y->value << ").");

		    return lcontext.newIntLiteralNode (expr->lineNumber, 0);
		}

	      case TK_EQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value == y->value);

	      case TK_GREATER:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value > y->value);

	      case TK_GREATEREQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value >= y->value);

	      case TK_LEFTSHIFT:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value << y->value);

	      case TK_LESS:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value < y->value);

	      case TK_LESSEQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value <= y->value);

	      case TK_MINUS:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value - y->value);

	      case TK_MOD:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value % y->value);

	      case TK_NOTEQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value != y->value);

	      case TK_OR:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value || y->value);

	      case TK_PLUS:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value + y->value);

	      case TK_RIGHTSHIFT:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value >> y->value);

	      case TK_TIMES:
		return lcontext.newIntLiteralNode
			    (expr->lineNumber, x->value * y->value);

	      default:

		MESSAGE_LE (lcontext, ERR_OP_TYPE, expr->lineNumber,
		    "Invalid operand types "
		    "for " << tokenAsString (binOp->op) << " operator "
		    "(" << binOp->leftOperand->type->asString() << " " <<
		    tokenAsString (binOp->op) << " " <<
		    binOp->rightOperand->type->asString() << ").");
	    }
	}
    }
Example #3
0
ExprNodePtr
BoolType::evaluate (LContext &lcontext, const ExprNodePtr &expr) const
{
    if (UnaryOpNodePtr unOp = expr.cast<UnaryOpNode>())
    {
	BoolLiteralNodePtr x = unOp->operand.cast<BoolLiteralNode>();

	if (x)
	{
	    switch (unOp->op)
	    {
	      case TK_BITNOT:

		//
		// We use the C++ ! operation to evaluate the CTL expression ~x,
		// where x is of type bool.  This ensures that ~true == false
		// and ~false == true.
		//

		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, !x->value);

	      case TK_NOT:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, !x->value);

	      default:

		MESSAGE_LE (lcontext, ERR_OP_TYPE, expr->lineNumber,
		    "Cannot apply " << tokenAsString (unOp->op) << " "
		    "operator to value of type " << asString() << ".");
	    }
	}
    }

    if (BinaryOpNodePtr binOp = expr.cast<BinaryOpNode>())
    {
	BoolLiteralNodePtr x = binOp->leftOperand.cast<BoolLiteralNode>();
	BoolLiteralNodePtr y = binOp->rightOperand.cast<BoolLiteralNode>();

	if (x && y)
	{
	    switch (binOp->op)
	    {
	      case TK_AND:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value && y->value);

	      case TK_BITAND:

		//
		// For the bit-wise &, | and ^ operators, we normalize bool
		// operands before applying the operators.  This avoids
		// surprises, for example, true^true == true.
		// 

		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, !!x->value & !!y->value);

	      case TK_BITOR:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, !!x->value | !!y->value);

	      case TK_BITXOR:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, !!x->value ^ !!y->value);

	      case TK_EQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value == y->value);

	      case TK_GREATER:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value > y->value);

	      case TK_GREATEREQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value >= y->value);

	      case TK_LESS:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value < y->value);

	      case TK_LESSEQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value <= y->value);

	      case TK_NOTEQUAL:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value != y->value);

	      case TK_OR:
		return lcontext.newBoolLiteralNode
			    (expr->lineNumber, x->value || y->value);

	      default:

		MESSAGE_LE (lcontext, ERR_OP_TYPE, expr->lineNumber,
		    "Invalid operand types "
		    "for " << tokenAsString (binOp->op) << " operator "
		    "(" << binOp->leftOperand->type->asString() << " " <<
		    tokenAsString (binOp->op) << " " <<
		    binOp->rightOperand->type->asString() << ").");
	    }
	}
    }

    return expr;
}