void JoinOperator::updateExpression(Expression *exp, unordered_map<string, Expression*> lm, unordered_map<string, Expression*> rm , string ltable, string rtable) { ExprType t = exp->getType(); if(t != ExprType::COLEXPRESSION && t != ExprType::DOUBLEVALUEEXPRESSION && t != ExprType::STRINGVALUEEXPRESSION && t != ExprType::LONGVALUEEXPRESSION && t != ExprType::DATEVALUEEXPRESSION){ BinaryExpression* bexp = (BinaryExpression*)exp; updateExpression(bexp->getLeftExpression(), lm, rm, ltable, rtable); updateExpression(bexp->getRightExpression(), lm, rm, ltable, rtable); } else if(t == COLEXPRESSION){ ColExpression* col = (ColExpression*)exp; if(lm.find(col->getQualifiedName()) != lm.end()){ ColExpression* e = (ColExpression*)lm[col->getQualifiedName()]; col->setType(e->getDataType()); col->setColPos(e->getColPos()); left.push_back(col); } else if(rm.find(col->getQualifiedName()) != rm.end()){ ColExpression* e = (ColExpression*)rm[col->getQualifiedName()]; col->setType(e->getDataType()); col->setColPos(e->getColPos() + (int)lm.size()); ColExpression *rcol = new ColExpression(col->getQualifiedName(), col->getColPos()-(int)lm.size(), col->getDataType()); right.push_back(rcol); } else { std::cout << "column : " << col->getQualifiedName() << " not found in any schema " << std::endl; } } }
void ProjectionOperator::updateExpression(Expression *newExp, unordered_map<std::string, Expression *> m, string tableName) { ExprType t = newExp->getType(); if(t != ExprType::COLEXPRESSION && t != ExprType::DOUBLEVALUEEXPRESSION && t != ExprType::STRINGVALUEEXPRESSION && t != ExprType::LONGVALUEEXPRESSION && t != ExprType::DATEVALUEEXPRESSION){ BinaryExpression* b = (BinaryExpression*)newExp; updateExpression(b->getLeftExpression(), m, tableName); updateExpression(b->getRightExpression(), m, tableName); } else if(t == ExprType::COLEXPRESSION){ if(((ColExpression*)newExp)->getTableName() == "") ((ColExpression*)newExp)->setTableName(tableName); ColExpression* col = (ColExpression*)m[((ColExpression*)newExp)->getQualifiedName()]; ((ColExpression*)newExp)->setColPos(col->getColPos()); ((ColExpression*)newExp)->setType(col->getDataType()); } }
static String handle_static_binary_expression(CPrintStyleModule *state, const SuifObject *obj) { BinaryExpression *expr = to<BinaryExpression>(obj); LString opc = expr->get_opcode(); String src_string1 = state->print_to_string(expr->get_source1()); String src_string2 = state->print_to_string(expr->get_source2()); // Should we special case: add, mod, etc? for (size_t i = 0; i < NUM_BINARY_OPER; i++ ) { if (*(binary_oper_table[i]._oper) == opc) { const char *op_char = binary_oper_table[i]._op_char; return(String("(") + src_string1 + op_char + src_string2 + ")"); } } return(String(opc) + "(" + src_string1 + "," + src_string2 + ")"); }
VariableSymbol* ReferenceCleanupPass::FindVariable(Expression* e) { LoadVariableExpression* lve = dynamic_cast<LoadVariableExpression*>(e) ; BinaryExpression* be = dynamic_cast<BinaryExpression*>(e) ; if (lve != NULL) { return lve->get_source() ; } if (be != NULL) { return FindVariable(be->get_source1()) ; } FormattedText tmpText ; e->print(tmpText) ; std::cout << tmpText.get_value() << std::endl ; return NULL ; }
ExpressionPtr OrExpression::getDNFImpl() const { UnaryExpression * leftLeaf = dynamic_cast<UnaryExpression*>(left()); UnaryExpression * rightLeaf = dynamic_cast<UnaryExpression*>(right()); // A or B if (leftLeaf && rightLeaf) { return clone(); } // A or (B and C) => (A and B) or (A and C) BinaryExpression * rightAnd = dynamic_cast<AndExpression*>(right()); if (leftLeaf && rightAnd) { return Or(And(leftLeaf, rightAnd->left()), And(leftLeaf, rightAnd->right())); } // (A and B) or C => (A and C) or (B and C) BinaryExpression * leftAnd = dynamic_cast<AndExpression*>(left()); if (leftAnd && rightLeaf) { return Or(And(leftAnd->left(), rightLeaf), And(leftAnd->right(), rightLeaf)); } return Or(left()->getDNF(), right()->getDNF()); }
DataType Expression::getDataType() { ExprType t = this->getType(); if(t == STRINGVALUEEXPRESSION) return STRING; if(t == DOUBLEVALUEEXPRESSION) return DOUBLE; if(t == LONGVALUEEXPRESSION) return LONG; if(t == DATEVALUEEXPRESSION) return DATE; if(t == ADDITIONEXPRESSION || t == SUBTRACTIONEXPRESSION || t == MULTIPLICATIONEXPRESSION || t == DIVISIONEXPRESSION){ BinaryExpression* bexp = (BinaryExpression*)this; DataType t1 = bexp->getLeftExpression()->getDataType(); DataType t2 = bexp->getRightExpression()->getDataType(); if(t1 == DOUBLE || t2 == DOUBLE) return DOUBLE; return LONG; } if(t == COLEXPRESSION) return getDataType(); //Boolean return LONG; }
bool CombineSummationPass::IsSummation(Expression* e, VariableSymbol* v) { assert(e != NULL) ; assert(v != NULL) ; BinaryExpression* binExp = dynamic_cast<BinaryExpression*>(e) ; if (binExp == NULL) { return false ; } if (binExp->get_opcode() != LString("add")) { return false ; } Expression* leftSide = binExp->get_source1() ; Expression* rightSide = binExp->get_source2() ; LoadVariableExpression* leftLoadVar = dynamic_cast<LoadVariableExpression*>(leftSide) ; LoadVariableExpression* rightLoadVar = dynamic_cast<LoadVariableExpression*>(rightSide) ; if (leftLoadVar != NULL && leftLoadVar->get_source() == v) { return true ; } if (rightLoadVar != NULL && rightLoadVar->get_source() == v) { return true ; } return IsSummation(leftSide, v) || IsSummation(rightSide, v) ; }
Expression* ExpressionParser::parseExpression(std::vector<std::string> tokens){ if(tokens.size() == 1) return leafExpression(tokens[0]); if(tokens.size() > 3 && tokens[tokens.size()-2] == "AS") return parseExpression(std::vector<std::string>(tokens.begin(), tokens.end()-2)); for(int i = 0; i < tokens.size(); i++){ if(logicalOperators.find(tokens[i]) != logicalOperators.end()){ Expression *left = parseExpression(std::vector<std::string>(tokens.begin(), tokens.begin()+i)); Expression *right = parseExpression(std::vector<std::string>(tokens.begin()+i+1, tokens.end())); BinaryExpression *op = NULL; op = binaryExpression(tokens[i]); op->setLeftExpression(left); op->setRightExpression(right); return op; } } for(int i = 0; i < tokens.size(); i++){ if(relationalOperators.find(tokens[i]) != relationalOperators.end()){ Expression *left = parseExpression(std::vector<std::string>(tokens.begin(), tokens.begin()+i)); Expression *right = parseExpression(std::vector<std::string>(tokens.begin()+i+1, tokens.end())); BinaryExpression *op = NULL; op = binaryExpression(tokens[i]); op->setLeftExpression(left); op->setRightExpression(right); return op; } } for(int i = 0; i < tokens.size(); i++){ if(arithmeticOperators.find(tokens[i]) != arithmeticOperators.end()){ Expression *left = parseExpression(std::vector<std::string>(tokens.begin(), tokens.begin()+i)); Expression *right = parseExpression(std::vector<std::string>(tokens.begin()+i+1, tokens.end())); BinaryExpression *op = NULL; op = binaryExpression(tokens[i]); op->setLeftExpression(left); op->setRightExpression(right); return op; } } raise_exception(); return NULL; }
Expression* CombineSummationPass::RemoveValue(Expression* original, VariableSymbol* v) { assert(original != NULL) ; assert(v != NULL) ; BinaryExpression* binExp = dynamic_cast<BinaryExpression*>(original) ; if (binExp == NULL) { return NULL ; } Expression* leftSide = binExp->get_source1() ; Expression* rightSide = binExp->get_source2() ; // Check to see if we are the correct format LoadVariableExpression* leftVar = dynamic_cast<LoadVariableExpression*>(leftSide) ; LoadVariableExpression* rightVar = dynamic_cast<LoadVariableExpression*>(rightSide) ; if (leftVar != NULL && leftVar->get_source() == v) { binExp->set_source2(NULL) ; return rightSide ; } if (rightVar != NULL && rightVar->get_source() == v) { binExp->set_source1(NULL) ; return leftSide ; } // Recursively go through and find the value Expression* leftSideReplacement = RemoveValue(leftSide, v) ; if (leftSideReplacement != NULL) { binExp->set_source2(leftSideReplacement) ; return binExp ; } Expression* rightSideReplacement = RemoveValue(rightSide, v) ; if (rightSideReplacement != NULL) { binExp->set_source2(rightSideReplacement) ; return binExp ; } return NULL ; }
void SemanticsVisitor::visit(BinaryExpression& bexpr) { visitChildren(bexpr); bexpr.setType(bexpr.binaryResultType()); }
/* Another helper function for print_var_def(). This function * expects that it will need to add a return before printing * anything, and it expects that you will add a return after * it is done. * It returns the number of bits of initialization data that it * generates. */ int PrinterX86::process_value_block(ValueBlock *vblk) { int bits_filled = 0; if (is_a<ExpressionValueBlock>(vblk)) { // An ExpressionValueBlock either holds a constant value or a // simple expression representing either an address relative to // a symbol or a pointer generated by conversion from an integer // constant (presumably zero). ExpressionValueBlock *evb = (ExpressionValueBlock*)vblk; Expression *exp = evb->get_expression(); if (is_a<IntConstant>(exp)) { IntConstant *ic = (IntConstant*)exp; bits_filled = print_size_directive(ic->get_result_type()); fprint(out, ic->get_value()); cur_opnd_cnt++; } else if (is_a<FloatConstant>(exp)) { FloatConstant *fc = (FloatConstant*)exp; bits_filled = print_size_directive(fc->get_result_type()); fputs(fc->get_value().c_str(), out); cur_opnd_cnt++; } else { // We use non-constant ExpressionValueBlocks to hold a symbolic // address, optionally with an offset, or a pointer initializer // consisting of a `convert' expression. // A SymbolAddressExpression represents a plain symbolic // address. // An address obtained by conversion from another type is a // unary expression with opcode "convert". // A symbol+delta is represented by an add whose first operand // is the load-address and whose second is an IntConstant // expression. // No other kind of "expression" is recognized. if (is_a<UnaryExpression>(exp)) { UnaryExpression *ux = (UnaryExpression*)exp; claim(ux->get_opcode() == k_convert, "unexpected unary expression in expression block"); DataType *tt = ux->get_result_type(); // target type claim(is_kind_of<PointerType>(tt), "unexpected target type when converting initializer"); exp = ux->get_source(); if (is_a<IntConstant>(exp)) { IntConstant *ic = (IntConstant*)exp; bits_filled = print_size_directive(tt); fprint(out, ic->get_value()); cur_opnd_cnt++; return bits_filled; } // Fall through to handle symbol-relative address, on the // assumption that the front end validated the conversion. } SymbolAddressExpression *sax; long delta; if (is_a<BinaryExpression>(exp)) { BinaryExpression *bx = (BinaryExpression*)exp; claim(bx->get_opcode() == k_add, "unexpected binary expression in expression block"); Expression *s1 = bx->get_source1(); Expression *s2 = bx->get_source2(); sax = to<SymbolAddressExpression>(s1); delta = to<IntConstant>(s2)->get_value().c_long(); } else if (is_a<SymbolAddressExpression>(exp)) { sax = (SymbolAddressExpression*)exp; delta = 0; } else { claim(false, "unexpected kind of expression block"); } Sym *sym = sax->get_addressed_symbol(); // symbol initialization bits_filled = print_size_directive(type_ptr); print_sym(sym); if (delta != 0) { fprintf(out, "%+ld", delta); } // always force the start of a new data directive cur_opcode = opcode_null; cur_opnd_cnt = 0; } } else if (is_a<MultiValueBlock>(vblk)) { MultiValueBlock *mvb = (MultiValueBlock*)vblk; for (int i = 0; i < mvb->get_sub_block_count(); i++ ) { int offset = mvb->get_sub_block(i).first.c_int(); claim(offset >= bits_filled); if (bits_filled < offset) // pad to offset bits_filled += print_bit_filler(offset - bits_filled); bits_filled += process_value_block(mvb->get_sub_block(i).second); } int all_bits = get_bit_size(mvb->get_type()); if (all_bits > bits_filled) bits_filled += print_bit_filler(all_bits - bits_filled); } else if (is_a<RepeatValueBlock>(vblk)) { // Simplifying assumption: We now expect the front-end // to remove initialization code of large arrays of zeros. RepeatValueBlock *rvb = (RepeatValueBlock*)vblk; int repeat_cnt = rvb->get_num_repetitions(); if (repeat_cnt > 1) { // insert .repeat pseudo-op fprintf(out, "\n\t%s\t%d", x86_opcode_names[REPEAT], repeat_cnt); cur_opcode = opcode_null; // force new data directive } // actual data directive bits_filled = repeat_cnt * process_value_block(rvb->get_sub_block()); if (repeat_cnt > 1) { // insert .endr pseudo-op fprintf(out, "\n\t%s", x86_opcode_names[ENDR]); cur_opcode = opcode_null; // force new data directive } } else if (is_a<UndefinedValueBlock>(vblk)) { bits_filled += print_bit_filler(get_bit_size(vblk->get_type())); } else { claim(false, "unexpected kind of ValueBlock"); } return bits_filled; }
void CombineSummationPass::do_procedure_definition(ProcedureDefinition* p) { procDef = p ; assert(procDef != NULL) ; OutputInformation("Combine summation pass begins") ; StatementList* innermost = InnermostList(procDef) ; assert(innermost != NULL) ; bool change = false ; do { // Find the first summation StoreVariableStatement* firstStatement = NULL ; StoreVariableStatement* secondStatement = NULL ; change = false ; int i ; int firstStatementPosition = -1 ; i = 0 ; while (i < innermost->get_statement_count()) { StoreVariableStatement* currentStoreVariable = dynamic_cast<StoreVariableStatement*>(innermost->get_statement(i)) ; if (currentStoreVariable != NULL && IsSummation(currentStoreVariable)) { firstStatement = currentStoreVariable ; firstStatementPosition = i ; break ; } ++i ; } if (firstStatement != NULL) { VariableSymbol* firstDest = firstStatement->get_destination() ; for (int j = i+1 ; j < innermost->get_statement_count() ; ++j) { StoreVariableStatement* nextStoreVar = dynamic_cast<StoreVariableStatement*>(innermost->get_statement(j)); if (nextStoreVar != NULL && IsSummation(nextStoreVar, firstDest)) { secondStatement = nextStoreVar ; break ; } if (IsDefinition(innermost->get_statement(j), firstDest) || HasUses(innermost->get_statement(j), firstDest)) { break ; } } } if (secondStatement != NULL) { // Go through each of the variables used in the first statement and // make sure there are no definitions to any of them. // I only have to worry about variables and not array accesses because // we don't allow them to read and write to array values. int originalPosition = DeterminePosition(innermost, firstStatement) ; assert(originalPosition >= 0) ; list<VariableSymbol*> usedVars = AllUsedVariablesBut(firstStatement, firstStatement->get_destination()); bool goodPath = true ; for (int j = originalPosition ; j < innermost->get_statement_count() && innermost->get_statement(j) != secondStatement ; ++j) { list<VariableSymbol*>::iterator usedIter = usedVars.begin() ; while (usedIter != usedVars.end()) { if (IsOutputVariable((*usedIter), innermost->get_statement(j))) { goodPath = false ; break ; } ++usedIter ; } if (!goodPath) { break ; } } if (!goodPath) { continue ; } // Actually do the combining here change = true ; Expression* remains = RemoveValue(firstStatement) ; Expression* secondRemains = RemoveValue(secondStatement) ; // Create two binary expressions BinaryExpression* remainsSum = create_binary_expression(theEnv, remains->get_result_type(), LString("add"), remains, secondRemains) ; LoadVariableExpression* loadDest = create_load_variable_expression(theEnv, secondStatement->get_destination()->get_type()->get_base_type(), secondStatement->get_destination()) ; BinaryExpression* finalSum = create_binary_expression(theEnv, remainsSum->get_result_type(), LString("add"), remainsSum, loadDest) ; secondStatement->set_value(finalSum) ; // Delete? innermost->remove_statement(firstStatementPosition) ; } } while (change == true) ; OutputInformation("Combine summation pass ends") ; }
/** * $ANTLR start boolean_term * /home/cross/workspace/djondb/db/grammars/filter_expression.g:88:1: boolean_term returns [BaseExpression* val] : b1= boolean_value ( AND b2= boolean_value )* ; */ static BaseExpression* boolean_term(pfilter_expressionParser ctx) { BaseExpression* val; BaseExpression* b1; #undef RETURN_TYPE_b1 #define RETURN_TYPE_b1 BaseExpression* BaseExpression* b2; #undef RETURN_TYPE_b2 #define RETURN_TYPE_b2 BaseExpression* /* Initialize rule variables */ { // /home/cross/workspace/djondb/db/grammars/filter_expression.g:89:2: (b1= boolean_value ( AND b2= boolean_value )* ) // /home/cross/workspace/djondb/db/grammars/filter_expression.g:89:4: b1= boolean_value ( AND b2= boolean_value )* { FOLLOWPUSH(FOLLOW_boolean_value_in_boolean_term138); b1=boolean_value(ctx); FOLLOWPOP(); if (HASEXCEPTION()) { goto ruleboolean_termEx; } { val= b1 ; } // /home/cross/workspace/djondb/db/grammars/filter_expression.g:93:3: ( AND b2= boolean_value )* for (;;) { int alt2=2; switch ( LA(1) ) { case AND: { alt2=1; } break; } switch (alt2) { case 1: // /home/cross/workspace/djondb/db/grammars/filter_expression.g:93:4: AND b2= boolean_value { MATCHT(AND, &FOLLOW_AND_in_boolean_term146); if (HASEXCEPTION()) { goto ruleboolean_termEx; } FOLLOWPUSH(FOLLOW_boolean_value_in_boolean_term150); b2=boolean_value(ctx); FOLLOWPOP(); if (HASEXCEPTION()) { goto ruleboolean_termEx; } { BinaryExpression* be = new BinaryExpression(FO_AND); be->push(val ); be->push(b2 ); val= be; } } break; default: goto loop2; /* break out of the loop */ break; } } loop2: ; /* Jump out to here if this rule does not match */ } } // This is where rules clean up and exit // goto ruleboolean_termEx; /* Prevent compiler warnings */ ruleboolean_termEx: ; return val; }
/** * $ANTLR start boolean_expr * /home/cross/workspace/djondb/db/grammars/filter_expression.g:76:1: boolean_expr returns [BaseExpression* val] : b1= boolean_term ( OR b2= boolean_term )* ; */ static BaseExpression* boolean_expr(pfilter_expressionParser ctx) { BaseExpression* val; BaseExpression* b1; #undef RETURN_TYPE_b1 #define RETURN_TYPE_b1 BaseExpression* BaseExpression* b2; #undef RETURN_TYPE_b2 #define RETURN_TYPE_b2 BaseExpression* /* Initialize rule variables */ { // /home/cross/workspace/djondb/db/grammars/filter_expression.g:77:2: (b1= boolean_term ( OR b2= boolean_term )* ) // /home/cross/workspace/djondb/db/grammars/filter_expression.g:77:4: b1= boolean_term ( OR b2= boolean_term )* { FOLLOWPUSH(FOLLOW_boolean_term_in_boolean_expr107); b1=boolean_term(ctx); FOLLOWPOP(); if (HASEXCEPTION()) { goto ruleboolean_exprEx; } { val= b1 ; } // /home/cross/workspace/djondb/db/grammars/filter_expression.g:81:2: ( OR b2= boolean_term )* for (;;) { int alt1=2; switch ( LA(1) ) { case OR: { alt1=1; } break; } switch (alt1) { case 1: // /home/cross/workspace/djondb/db/grammars/filter_expression.g:81:3: OR b2= boolean_term { MATCHT(OR, &FOLLOW_OR_in_boolean_expr115); if (HASEXCEPTION()) { goto ruleboolean_exprEx; } FOLLOWPUSH(FOLLOW_boolean_term_in_boolean_expr119); b2=boolean_term(ctx); FOLLOWPOP(); if (HASEXCEPTION()) { goto ruleboolean_exprEx; } { BinaryExpression* be = new BinaryExpression(FO_OR); be->push(val ); be->push(b2 ); val= be; } } break; default: goto loop1; /* break out of the loop */ break; } } loop1: ; /* Jump out to here if this rule does not match */ } } // This is where rules clean up and exit // goto ruleboolean_exprEx; /* Prevent compiler warnings */ ruleboolean_exprEx: ; return val; }
/** * $ANTLR start nonparentherized_boolean * /home/cross/workspace/djondb/db/grammars/filter_expression.g:114:1: nonparentherized_boolean returns [BaseExpression* val] : u1= unary_expr ( OPER u2= unary_expr )* ; */ static BaseExpression* nonparentherized_boolean(pfilter_expressionParser ctx) { BaseExpression* val; pANTLR3_COMMON_TOKEN OPER6; BaseExpression* u1; #undef RETURN_TYPE_u1 #define RETURN_TYPE_u1 BaseExpression* BaseExpression* u2; #undef RETURN_TYPE_u2 #define RETURN_TYPE_u2 BaseExpression* /* Initialize rule variables */ OPER6 = NULL; { // /home/cross/workspace/djondb/db/grammars/filter_expression.g:115:2: (u1= unary_expr ( OPER u2= unary_expr )* ) // /home/cross/workspace/djondb/db/grammars/filter_expression.g:115:4: u1= unary_expr ( OPER u2= unary_expr )* { FOLLOWPUSH(FOLLOW_unary_expr_in_nonparentherized_boolean215); u1=unary_expr(ctx); FOLLOWPOP(); if (HASEXCEPTION()) { goto rulenonparentherized_booleanEx; } { val= u1 ; } // /home/cross/workspace/djondb/db/grammars/filter_expression.g:117:4: ( OPER u2= unary_expr )* for (;;) { int alt4=2; switch ( LA(1) ) { case OPER: { alt4=1; } break; } switch (alt4) { case 1: // /home/cross/workspace/djondb/db/grammars/filter_expression.g:117:6: OPER u2= unary_expr { OPER6 = (pANTLR3_COMMON_TOKEN) MATCHT(OPER, &FOLLOW_OPER_in_nonparentherized_boolean221); if (HASEXCEPTION()) { goto rulenonparentherized_booleanEx; } FOLLOWPUSH(FOLLOW_unary_expr_in_nonparentherized_boolean225); u2=unary_expr(ctx); FOLLOWPOP(); if (HASEXCEPTION()) { goto rulenonparentherized_booleanEx; } { FILTER_OPERATORS oper = parseFilterOperator((char*)(OPER6->getText(OPER6))->chars); BinaryExpression* be = new BinaryExpression(oper); be->push( val ); be->push(u2 ); val= be; } } break; default: goto loop4; /* break out of the loop */ break; } } loop4: ; /* Jump out to here if this rule does not match */ } } // This is where rules clean up and exit // goto rulenonparentherized_booleanEx; /* Prevent compiler warnings */ rulenonparentherized_booleanEx: ; return val; }
// visitForTest helps optimize statements with expressions like: // if (x && y || z) // // Where, with a naive conversion we would reduce (x && y) to a boolean, and // then reduce (that || z) to another boolean, and another test - we can simply // test each individual component and combine the jump paths with the paths // the if-test needs to take. // // Unfortunately, this logic comes at a complexity price: it is illegal to // emit non-statements from SemA, since the following situation could occur: // (1) SemA builds HIR chain #1 for statement X. // (2) SemA builds HIR chain #2 for statement X. // (3) SemA forces HIR chain #2 to be emitted to the code stream. // (4) SemA emits statement X, with HIR chain #1. // // In this situation, the HIR chains have been emitted out-of-order. So, // visitForTest takes in a HIRList which it populates with instructions, which // may include internal statements (like jumps and binds). // // The trueBranch and falseBranch parameters are self-explanatory. The // fallthrough case describes which branch comes immediately after the // test. This is used to optimize cases like: // if (x) { // ... // } // do { // ... // } while (y); // // After testing |x|, if it evaluated to true, there is no need to jump to the // true branch, because we'll fallthrough (as long as the expression does not // have logical ands/ors which could short-circuit). Similarly for |y|, the // false condition does not need an actual jump target. // void SemanticAnalysis::visitForTest(HIRList *output, Expression *expr, Label *trueBranch, Label *falseBranch, Label *fallthrough) { Type *boolType = cc_.types()->getPrimitive(PrimitiveType::Bool); // Handle logical and/or. BinaryExpression *bin = expr->asBinaryExpression(); if (bin && (bin->token() == TOK_AND || bin->token() == TOK_OR)) { HLabel *next = new (pool_) HLabel(); if (bin->token() == TOK_AND) visitForTest(output, bin->left(), next, falseBranch, next); else visitForTest(output, bin->left(), trueBranch, next, next); output->append(new (pool_) HBind(expr, next)); visitForTest(output, bin->right(), trueBranch, falseBranch, fallthrough); return; } // Handle equality and relational operators. if (bin && (bin->token() >= TOK_EQUALS && bin->token() <= TOK_GE)) { HIR *left = rvalue(bin->left()); HIR *right = rvalue(bin->right()); if (!left || !right) return; Type *coercion = coercionType(bin->token(), left, right); if (!coercion || ((left = coerce(left, coercion, Coerce_Arg)) == nullptr) || ((right = coerce(right, coercion, Coerce_Arg)) == nullptr)) { return; } Label *target = (fallthrough == trueBranch) ? falseBranch : trueBranch; TokenKind token = (fallthrough == trueBranch) ? InvertTest(bin->token()) : bin->token(); output->append(new (pool_) HCompareAndJump(bin, token, left, right, target)); return; } // Handle unary not (!) UnaryExpression *unary = expr->asUnaryExpression(); if (unary && unary->token() == TOK_NOT) { // Re-invoke visitForTest but invert the branches. Note that we don't touch // |fallthrough|, since it's used to determine whether to jump on success // or failure, so inverting it as well would do nothing. visitForTest(output, unary->expression(), falseBranch, trueBranch, fallthrough); return; } // We couldn't match anything easy, so just coerce the input to a boolean. HIR *hir = rvalue(expr); if (!hir || ((hir = coerce(hir, boolType, Coerce_Assign)) == nullptr)) return; if (fallthrough == falseBranch) output->append(new (pool_) HJump(expr, hir, true, trueBranch)); else output->append(new (pool_) HJump(expr, hir, false, falseBranch)); }