| ... | ... | @@ -1987,6 +1987,59 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, |
| 1987 | 1987 | return node; |
| 1988 | 1988 | } |
| 1989 | 1989 | |
| 1990 | static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 1991 | stmt->getBody(); |
| 1992 | stmt->getCond(); |
| 1993 | |
| 1994 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 1995 | |
| 1996 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); |
| 1997 | true_node->data.bool_literal.value = true; |
| 1998 | while_node->data.while_expr.condition = true_node; |
| 1999 | |
| 2000 | AstNode *body_node; |
| 2001 | if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) { |
| 2002 | // there's already a block in C, so we'll append our condition to it. |
| 2003 | // c: do { |
| 2004 | // c: a; |
| 2005 | // c: b; |
| 2006 | // c: } while(c); |
| 2007 | // zig: while (true) { |
| 2008 | // zig: a; |
| 2009 | // zig: b; |
| 2010 | // zig: if (!cond) break; |
| 2011 | // zig: } |
| 2012 | body_node = trans_stmt(c, false, block, stmt->getBody(), TransRValue); |
| 2013 | if (body_node == nullptr) return nullptr; |
| 2014 | assert(body_node->type == NodeTypeBlock); |
| 2015 | } else { |
| 2016 | // the C statement is without a block, so we need to create a block to contain it. |
| 2017 | // c: do |
| 2018 | // c: a; |
| 2019 | // c: while(c); |
| 2020 | // zig: while (true) { |
| 2021 | // zig: a; |
| 2022 | // zig: if (!cond) break; |
| 2023 | // zig: } |
| 2024 | body_node = trans_create_node(c, NodeTypeBlock); |
| 2025 | AstNode *child_statement = trans_stmt(c, false, body_node, stmt->getBody(), TransRValue); |
| 2026 | if (child_statement == nullptr) return nullptr; |
| 2027 | body_node->data.block.statements.append(child_statement); |
| 2028 | } |
| 2029 | |
| 2030 | // if (!cond) break; |
| 2031 | AstNode *condition_node = trans_expr(c, true, body_node, stmt->getCond(), TransRValue); |
| 2032 | if (condition_node == nullptr) return nullptr; |
| 2033 | AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2034 | terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node); |
| 2035 | terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak); |
| 2036 | body_node->data.block.statements.append(terminator_node); |
| 2037 | |
| 2038 | while_node->data.while_expr.body = body_node; |
| 2039 | |
| 2040 | return while_node; |
| 2041 | } |
| 2042 | |
| 1990 | 2043 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) { |
| 1991 | 2044 | Stmt::StmtClass sc = stmt->getStmtClass(); |
| 1992 | 2045 | switch (sc) { |
| ... | ... | @@ -2026,6 +2079,8 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s |
| 2026 | 2079 | return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue); |
| 2027 | 2080 | case Stmt::UnaryExprOrTypeTraitExprClass: |
| 2028 | 2081 | return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt); |
| 2082 | case Stmt::DoStmtClass: |
| 2083 | return trans_do_loop(c, block, (DoStmt *)stmt); |
| 2029 | 2084 | case Stmt::CaseStmtClass: |
| 2030 | 2085 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); |
| 2031 | 2086 | return nullptr; |
| ... | ... | @@ -2071,9 +2126,6 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s |
| 2071 | 2126 | case Stmt::CoroutineBodyStmtClass: |
| 2072 | 2127 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass"); |
| 2073 | 2128 | return nullptr; |
| 2074 | | case Stmt::DoStmtClass: |
| 2075 | | emit_warning(c, stmt->getLocStart(), "TODO handle C DoStmtClass"); |
| 2076 | | return nullptr; |
| 2077 | 2129 | case Stmt::BinaryConditionalOperatorClass: |
| 2078 | 2130 | emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass"); |
| 2079 | 2131 | return nullptr; |