ExprNodePtr SizeNode::evaluate (LContext &lcontext) { obj = obj->evaluate(lcontext); ArrayTypePtr arrayType = obj->type.cast<ArrayType>(); if( !arrayType) { return lcontext.newIntLiteralNode (lineNumber, 1); } else if( arrayType->size() != 0 ) { return lcontext.newIntLiteralNode (lineNumber, arrayType->size()); } return this; }
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() << ")."); } } }