authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-11-13 22:56:20-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-11-13 22:56:20-07:00
log6ffaf4c2e26e90f7e75d2dd5461addcdb8741c85
treee3a72bd4435878583165bc804f0daa91dc7417e3
parent012ce1481e003b25e49934fce17f5e1b4aff218a

parsec supports do loop


2 files changed, 82 insertions(+), 3 deletions(-)

src/parsec.cpp+55-3
...@@ -1987,6 +1987,59 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block,...@@ -1987,6 +1987,59 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block,
1987 return node;1987 return node;
1988}1988}
19891989
1990static 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
1990static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {2043static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {
1991 Stmt::StmtClass sc = stmt->getStmtClass();2044 Stmt::StmtClass sc = stmt->getStmtClass();
1992 switch (sc) {2045 switch (sc) {
...@@ -2026,6 +2079,8 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s...@@ -2026,6 +2079,8 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
2026 return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue);2079 return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue);
2027 case Stmt::UnaryExprOrTypeTraitExprClass:2080 case Stmt::UnaryExprOrTypeTraitExprClass:
2028 return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt);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 case Stmt::CaseStmtClass:2084 case Stmt::CaseStmtClass:
2030 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");2085 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");
2031 return nullptr;2086 return nullptr;
...@@ -2071,9 +2126,6 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s...@@ -2071,9 +2126,6 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
2071 case Stmt::CoroutineBodyStmtClass:2126 case Stmt::CoroutineBodyStmtClass:
2072 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");2127 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");
2073 return nullptr;2128 return nullptr;
2074 case Stmt::DoStmtClass:
2075 emit_warning(c, stmt->getLocStart(), "TODO handle C DoStmtClass");
2076 return nullptr;
2077 case Stmt::BinaryConditionalOperatorClass:2129 case Stmt::BinaryConditionalOperatorClass:
2078 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");2130 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");
2079 return nullptr;2131 return nullptr;
test/parsec.zig+27
...@@ -804,6 +804,33 @@ pub fn addCases(cases: &tests.ParseCContext) {...@@ -804,6 +804,33 @@ pub fn addCases(cases: &tests.ParseCContext) {
804 \\ };804 \\ };
805 \\}805 \\}
806 );806 );
807
808 cases.addC("do loop",
809 \\void foo(void) {
810 \\ int a = 2;
811 \\ do {
812 \\ a--;
813 \\ } while (a != 0);
814 \\
815 \\ int b = 2;
816 \\ do
817 \\ b--;
818 \\ while (b != 0);
819 \\}
820 ,
821 \\export fn foo() {
822 \\ var a: c_int = 2;
823 \\ while (true) {
824 \\ a -= 1;
825 \\ if (!(a != 0)) break;
826 \\ };
827 \\ var b: c_int = 2;
828 \\ while (true) {
829 \\ b -= 1;
830 \\ if (!(b != 0)) break;
831 \\ };
832 \\}
833 );
807}834}
808835
809836