authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-26 00:58:11-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-26 00:58:11-05:00
log1b0e90f70b4dc26c2ba96b7b5709a3ff269bb48a
tree365012ba5cfbb10d6723733edbe23c28fd446634
parent687e3592919940bc3c77a22adbee065fb5c1bc7e

translate-c supports switch statements


2 files changed, 280 insertions(+), 127 deletions(-)

src/translate_c.cpp+240-87
...@@ -69,6 +69,7 @@ enum TransScopeId {...@@ -69,6 +69,7 @@ enum TransScopeId {
69 TransScopeIdVar,69 TransScopeIdVar,
70 TransScopeIdBlock,70 TransScopeIdBlock,
71 TransScopeIdRoot,71 TransScopeIdRoot,
72 TransScopeIdWhile,
72};73};
7374
74struct TransScope {75struct TransScope {
...@@ -79,6 +80,8 @@ struct TransScope {...@@ -79,6 +80,8 @@ struct TransScope {
79struct TransScopeSwitch {80struct TransScopeSwitch {
80 TransScope base;81 TransScope base;
81 AstNode *switch_node;82 AstNode *switch_node;
83 uint32_t case_index;
84 bool found_default;
82};85};
8386
84struct TransScopeVar {87struct TransScopeVar {
...@@ -96,12 +99,19 @@ struct TransScopeRoot {...@@ -96,12 +99,19 @@ struct TransScopeRoot {
96 TransScope base;99 TransScope base;
97};100};
98101
102struct TransScopeWhile {
103 TransScope base;
104 AstNode *node;
105};
106
99static TransScopeRoot *trans_scope_root_create(Context *c);107static TransScopeRoot *trans_scope_root_create(Context *c);
108static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope);
100static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope);109static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope);
101static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name);110static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name);
102//static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope);111static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope);
103112
104static TransScopeBlock *trans_scope_block_find(TransScope *scope);113static TransScopeBlock *trans_scope_block_find(TransScope *scope);
114static TransScopeSwitch *trans_scope_switch_find(TransScope *scope);
105115
106static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);116static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
107static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);117static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
...@@ -238,6 +248,12 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol...@@ -238,6 +248,12 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol
238 return node;248 return node;
239}249}
240250
251static AstNode *trans_create_node_bool(Context *c, bool value) {
252 AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral);
253 bool_node->data.bool_literal.value = value;
254 return bool_node;
255}
256
241static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {257static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
242 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);258 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
243 node->data.string_literal.buf = buf;259 node->data.string_literal.buf = buf;
...@@ -965,22 +981,30 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s...@@ -965,22 +981,30 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s
965 return trans_type(c, qt.getTypePtr(), source_loc);981 return trans_type(c, qt.getTypePtr(), source_loc);
966}982}
967983
968static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt,984static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt,
969 TransScope **out_node_scope)985 AstNode *block_node, TransScope **out_node_scope)
970{986{
971 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);987 assert(block_node->type == NodeTypeBlock);
972 scope = &child_scope_block->base;
973 for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {988 for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
974 AstNode *child_node;989 AstNode *child_node;
975 scope = trans_stmt(c, scope, *it, &child_node);990 scope = trans_stmt(c, scope, *it, &child_node);
976 if (scope == nullptr)991 if (scope == nullptr)
977 return nullptr;992 return ErrorUnexpected;
978 if (child_node != nullptr)993 if (child_node != nullptr)
979 child_scope_block->node->data.block.statements.append(child_node);994 block_node->data.block.statements.append(child_node);
980 }995 }
981 if (out_node_scope != nullptr) {996 if (out_node_scope != nullptr) {
982 *out_node_scope = &child_scope_block->base;997 *out_node_scope = scope;
983 }998 }
999 return ErrorNone;
1000}
1001
1002static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt,
1003 TransScope **out_node_scope)
1004{
1005 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);
1006 if (trans_compound_stmt_inline(c, &child_scope_block->base, stmt, child_scope_block->node, out_node_scope))
1007 return nullptr;
984 return child_scope_block->node;1008 return child_scope_block->node;
985}1009}
9861010
...@@ -2081,17 +2105,18 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt...@@ -2081,17 +2105,18 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2081}2105}
20822106
2083static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {2107static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
2084 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);2108 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
20852109
2086 while_node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);2110 while_scope->node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2087 if (while_node->data.while_expr.condition == nullptr)2111 if (while_scope->node->data.while_expr.condition == nullptr)
2088 return nullptr;2112 return nullptr;
20892113
2090 TransScope *body_scope = trans_stmt(c, scope, stmt->getBody(), &while_node->data.while_expr.body);2114 TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),
2115 &while_scope->node->data.while_expr.body);
2091 if (body_scope == nullptr) 2116 if (body_scope == nullptr)
2092 return nullptr;2117 return nullptr;
20932118
2094 return while_node;2119 return while_scope->node;
2095}2120}
20962121
2097static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {2122static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
...@@ -2201,11 +2226,9 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop...@@ -2201,11 +2226,9 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
2201}2226}
22022227
2203static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) {2228static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) {
2204 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);2229 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
22052230
2206 AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral);2231 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2207 true_node->data.bool_literal.value = true;
2208 while_node->data.while_expr.condition = true_node;
22092232
2210 AstNode *body_node;2233 AstNode *body_node;
2211 TransScope *child_scope;2234 TransScope *child_scope;
...@@ -2222,7 +2245,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt...@@ -2222,7 +2245,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
2222 // zig: }2245 // zig: }
22232246
2224 // We call the low level function so that we can set child_scope to the scope of the generated block.2247 // We call the low level function so that we can set child_scope to the scope of the generated block.
2225 if (trans_stmt_extra(c, parent_scope, stmt->getBody(), ResultUsedNo, TransRValue, &body_node,2248 if (trans_stmt_extra(c, &while_scope->base, stmt->getBody(), ResultUsedNo, TransRValue, &body_node,
2226 nullptr, &child_scope))2249 nullptr, &child_scope))
2227 {2250 {
2228 return nullptr;2251 return nullptr;
...@@ -2237,7 +2260,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt...@@ -2237,7 +2260,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
2237 // zig: a;2260 // zig: a;
2238 // zig: if (!cond) break;2261 // zig: if (!cond) break;
2239 // zig: }2262 // zig: }
2240 TransScopeBlock *child_block_scope = trans_scope_block_create(c, parent_scope);2263 TransScopeBlock *child_block_scope = trans_scope_block_create(c, &while_scope->base);
2241 body_node = child_block_scope->node;2264 body_node = child_block_scope->node;
2242 AstNode *child_statement;2265 AstNode *child_statement;
2243 child_scope = trans_stmt(c, &child_block_scope->base, stmt->getBody(), &child_statement);2266 child_scope = trans_stmt(c, &child_block_scope->base, stmt->getBody(), &child_statement);
...@@ -2254,89 +2277,206 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt...@@ -2254,89 +2277,206 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
22542277
2255 body_node->data.block.statements.append(terminator_node);2278 body_node->data.block.statements.append(terminator_node);
22562279
2257 while_node->data.while_expr.body = body_node;2280 while_scope->node->data.while_expr.body = body_node;
22582281
2259 return while_node;2282 return while_scope->node;
2260}2283}
22612284
2262//static AstNode *trans_switch_stmt(Context *c, TransScope *scope, const SwitchStmt *stmt) {2285static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) {
2263// AstNode *switch_block_node = trans_create_node(c, NodeTypeBlock);2286 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
2264// AstNode *switch_node = trans_create_node(c, NodeTypeSwitchExpr);2287 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2265// const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();2288
2266// if (var_decl_stmt != nullptr) {2289 TransScopeBlock *block_scope = trans_scope_block_create(c, &while_scope->base);
2267// AstNode *vars_node = trans_stmt(c, switch_block_node, var_decl_stmt);2290 while_scope->node->data.while_expr.body = block_scope->node;
2268// if (vars_node == nullptr)2291
2269// return nullptr;2292 TransScopeSwitch *switch_scope;
2270// if (vars_node != nullptr)2293
2271// switch_block_node->data.block.statements.append(vars_node);2294 const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
2272// }2295 if (var_decl_stmt == nullptr) {
2273// switch_block_node->data.block.statements.append(switch_node);2296 switch_scope = trans_scope_switch_create(c, &block_scope->base);
2274//2297 } else {
2275// const Expr *cond_expr = stmt->getCond();2298 AstNode *vars_node;
2276// assert(cond_expr != nullptr);2299 TransScope *var_scope = trans_stmt(c, &block_scope->base, var_decl_stmt, &vars_node);
2277//2300 if (var_scope == nullptr)
2278// AstNode *expr_node = trans_expr(c, ResultUsedYes, switch_block_node, cond_expr, TransRValue);2301 return nullptr;
2279// if (expr_node == nullptr)2302 if (vars_node != nullptr)
2280// return nullptr;2303 block_scope->node->data.block.statements.append(vars_node);
2281// switch_node->data.switch_expr.expr = expr_node;2304 switch_scope = trans_scope_switch_create(c, var_scope);
2282//2305 }
2283// AstNode *body_node = trans_stmt(c, switch_block_node, stmt->getBody());2306 block_scope->node->data.block.statements.append(switch_scope->switch_node);
2284// if (body_node == nullptr)2307
2285// return nullptr;2308 const Expr *cond_expr = stmt->getCond();
2286// if (body_node != nullptr)2309 assert(cond_expr != nullptr);
2287// switch_block_node->data.block.statements.append(body_node);2310
2288//2311 AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);
2289// return switch_block_node;2312 if (expr_node == nullptr)
2290//}2313 return nullptr;
2314 switch_scope->switch_node->data.switch_expr.expr = expr_node;
2315
2316 AstNode *body_node;
2317 const Stmt *body_stmt = stmt->getBody();
2318 if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {
2319 if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,
2320 block_scope->node, nullptr))
2321 {
2322 return nullptr;
2323 }
2324 } else {
2325 TransScope *body_scope = trans_stmt(c, &switch_scope->base, body_stmt, &body_node);
2326 if (body_scope == nullptr)
2327 return nullptr;
2328 if (body_node != nullptr)
2329 block_scope->node->data.block.statements.append(body_node);
2330 }
2331
2332 if (!switch_scope->found_default && !stmt->isAllEnumCasesCovered()) {
2333 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
2334 prong_node->data.switch_prong.expr = trans_create_node(c, NodeTypeBreak);
2335 switch_scope->switch_node->data.switch_expr.prongs.append(prong_node);
2336 }
2337
2338 // This is necessary if the last switch case "falls through" the end of the switch block
2339 block_scope->node->data.block.statements.append(trans_create_node(c, NodeTypeBreak));
2340
2341 return while_scope->node;
2342}
2343
2344static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node,
2345 TransScope **out_scope)
2346{
2347 *out_node = nullptr;
2348
2349 if (stmt->getRHS() != nullptr) {
2350 emit_warning(c, stmt->getLocStart(), "TODO support GNU switch case a ... b extension");
2351 return ErrorUnexpected;
2352 }
2353
2354 TransScopeSwitch *switch_scope = trans_scope_switch_find(parent_scope);
2355 assert(switch_scope != nullptr);
2356
2357 Buf *label_name = buf_sprintf("case_%" PRIu32, switch_scope->case_index);
2358 switch_scope->case_index += 1;
2359
2360 {
2361 // Add the prong
2362 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
2363 AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, stmt->getLHS(), TransRValue);
2364 if (item_node == nullptr)
2365 return ErrorUnexpected;
2366 prong_node->data.switch_prong.items.append(item_node);
2367
2368 AstNode *goto_node = trans_create_node(c, NodeTypeGoto);
2369 goto_node->data.goto_expr.name = label_name;
2370 prong_node->data.switch_prong.expr = goto_node;
2371
2372 switch_scope->switch_node->data.switch_expr.prongs.append(prong_node);
2373 }
2374
2375 AstNode *label_node = trans_create_node(c, NodeTypeLabel);
2376 label_node->data.label.name = label_name;
2377
2378 TransScopeBlock *scope_block = trans_scope_block_find(parent_scope);
2379 scope_block->node->data.block.statements.append(label_node);
2380
2381 AstNode *sub_stmt_node;
2382 TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node);
2383 if (new_scope == nullptr)
2384 return ErrorUnexpected;
2385 if (sub_stmt_node != nullptr)
2386 scope_block->node->data.block.statements.append(sub_stmt_node);
2387
2388 *out_scope = new_scope;
2389 return ErrorNone;
2390}
2391
2392static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node,
2393 TransScope **out_scope)
2394{
2395 *out_node = nullptr;
2396
2397 TransScopeSwitch *switch_scope = trans_scope_switch_find(parent_scope);
2398 assert(switch_scope != nullptr);
2399
2400 Buf *label_name = buf_sprintf("default");
2401
2402 AstNode *label_node = trans_create_node(c, NodeTypeLabel);
2403 label_node->data.label.name = label_name;
2404
2405 {
2406 // Add the prong
2407 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
2408
2409 AstNode *goto_node = trans_create_node(c, NodeTypeGoto);
2410 goto_node->data.goto_expr.name = label_name;
2411 prong_node->data.switch_prong.expr = goto_node;
2412
2413 switch_scope->switch_node->data.switch_expr.prongs.append(prong_node);
2414 switch_scope->found_default = true;
2415 }
2416
2417 TransScopeBlock *scope_block = trans_scope_block_find(parent_scope);
2418 scope_block->node->data.block.statements.append(label_node);
2419
2420 AstNode *sub_stmt_node;
2421 TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node);
2422 if (new_scope == nullptr)
2423 return ErrorUnexpected;
2424 if (sub_stmt_node != nullptr)
2425 scope_block->node->data.block.statements.append(sub_stmt_node);
2426
2427 *out_scope = new_scope;
2428 return ErrorNone;
2429}
22912430
2292static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) {2431static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) {
2293 AstNode *loop_block_node;2432 AstNode *loop_block_node;
2294 TransScope *inner_scope;2433 TransScopeWhile *while_scope;
2295 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);2434 TransScope *cond_scope;
2296 const Stmt *init_stmt = stmt->getInit();2435 const Stmt *init_stmt = stmt->getInit();
2297 if (init_stmt == nullptr) {2436 if (init_stmt == nullptr) {
2298 loop_block_node = while_node;2437 while_scope = trans_scope_while_create(c, parent_scope);
2299 inner_scope = parent_scope;2438 loop_block_node = while_scope->node;
2439 cond_scope = parent_scope;
2300 } else {2440 } else {
2301 TransScopeBlock *child_scope = trans_scope_block_create(c, parent_scope);2441 TransScopeBlock *child_scope = trans_scope_block_create(c, parent_scope);
2302 loop_block_node = child_scope->node;2442 loop_block_node = child_scope->node;
2303 inner_scope = &child_scope->base;
23042443
2305 AstNode *vars_node;2444 AstNode *vars_node;
2306 inner_scope = trans_stmt(c, &child_scope->base, init_stmt, &vars_node);2445 cond_scope = trans_stmt(c, &child_scope->base, init_stmt, &vars_node);
2307 if (inner_scope == nullptr)2446 if (cond_scope == nullptr)
2308 return nullptr;2447 return nullptr;
2309 if (vars_node != nullptr)2448 if (vars_node != nullptr)
2310 child_scope->node->data.block.statements.append(vars_node);2449 child_scope->node->data.block.statements.append(vars_node);
23112450
2312 child_scope->node->data.block.statements.append(while_node);2451 while_scope = trans_scope_while_create(c, cond_scope);
2452
2453 child_scope->node->data.block.statements.append(while_scope->node);
2313 }2454 }
23142455
2315 const Stmt *cond_stmt = stmt->getCond();2456 const Stmt *cond_stmt = stmt->getCond();
2316 if (cond_stmt == nullptr) {2457 if (cond_stmt == nullptr) {
2317 AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral);2458 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2318 true_node->data.bool_literal.value = true;
2319 while_node->data.while_expr.condition = true_node;
2320 } else {2459 } else {
2321 TransScope *cond_scope = trans_stmt(c, inner_scope, cond_stmt, &while_node->data.while_expr.condition);2460 TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
2322 if (cond_scope == nullptr)2461 &while_scope->node->data.while_expr.condition);
2462 if (end_cond_scope == nullptr)
2323 return nullptr;2463 return nullptr;
2324 }2464 }
23252465
2326 const Stmt *inc_stmt = stmt->getInc();2466 const Stmt *inc_stmt = stmt->getInc();
2327 if (inc_stmt != nullptr) {2467 if (inc_stmt != nullptr) {
2328 AstNode *inc_node;2468 AstNode *inc_node;
2329 TransScope *inc_scope = trans_stmt(c, inner_scope, inc_stmt, &inc_node);2469 TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);
2330 if (inc_scope == nullptr)2470 if (inc_scope == nullptr)
2331 return nullptr;2471 return nullptr;
2332 while_node->data.while_expr.continue_expr = inc_node;2472 while_scope->node->data.while_expr.continue_expr = inc_node;
2333 }2473 }
23342474
2335 AstNode *child_statement;2475 AstNode *body_statement;
2336 TransScope *body_scope = trans_stmt(c, inner_scope, stmt->getBody(), &child_statement);2476 TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), &body_statement);
2337 if (body_scope == nullptr)2477 if (body_scope == nullptr)
2338 return nullptr;2478 return nullptr;
2339 while_node->data.while_expr.body = child_statement;2479 while_scope->node->data.while_expr.body = body_statement;
23402480
2341 return loop_block_node;2481 return loop_block_node;
2342}2482}
...@@ -2371,9 +2511,8 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_...@@ -2371,9 +2511,8 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
2371 if (result_node == nullptr)2511 if (result_node == nullptr)
2372 return ErrorUnexpected;2512 return ErrorUnexpected;
2373 *out_node = result_node;2513 *out_node = result_node;
2374 if (out_scope != nullptr) {2514 if (out_scope != nullptr)
2375 *out_scope = in_scope;2515 *out_scope = in_scope;
2376 }
2377 return ErrorNone;2516 return ErrorNone;
2378}2517}
23792518
...@@ -2456,18 +2595,13 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,...@@ -2456,18 +2595,13 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
2456 case Stmt::ParenExprClass:2595 case Stmt::ParenExprClass:
2457 return wrap_stmt(out_node, out_child_scope, scope,2596 return wrap_stmt(out_node, out_child_scope, scope,
2458 trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));2597 trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));
2459// case Stmt::SwitchStmtClass:
2460// return wrap_stmt(out_node, out_child_scope, scope,
2461// trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));
2462 case Stmt::SwitchStmtClass:2598 case Stmt::SwitchStmtClass:
2463 emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass");2599 return wrap_stmt(out_node, out_child_scope, scope,
2464 return ErrorUnexpected;2600 trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));
2465 case Stmt::CaseStmtClass:2601 case Stmt::CaseStmtClass:
2466 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");2602 return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);
2467 return ErrorUnexpected;
2468 case Stmt::DefaultStmtClass:2603 case Stmt::DefaultStmtClass:
2469 emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass");2604 return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);
2470 return ErrorUnexpected;
2471 case Stmt::NoStmtClass:2605 case Stmt::NoStmtClass:
2472 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");2606 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");
2473 return ErrorUnexpected;2607 return ErrorUnexpected;
...@@ -2981,7 +3115,8 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope...@@ -2981,7 +3115,8 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
2981 TransLRValue lrval)3115 TransLRValue lrval)
2982{3116{
2983 AstNode *result_node;3117 AstNode *result_node;
2984 if (trans_stmt_extra(c, scope, expr, result_used, lrval, &result_node, nullptr, nullptr)) {3118 TransScope *result_scope;
3119 if (trans_stmt_extra(c, scope, expr, result_used, lrval, &result_node, &result_scope, nullptr)) {
2985 return nullptr;3120 return nullptr;
2986 }3121 }
2987 return result_node;3122 return result_node;
...@@ -3536,6 +3671,14 @@ static TransScopeRoot *trans_scope_root_create(Context *c) {...@@ -3536,6 +3671,14 @@ static TransScopeRoot *trans_scope_root_create(Context *c) {
3536 return result;3671 return result;
3537}3672}
35383673
3674static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope) {
3675 TransScopeWhile *result = allocate<TransScopeWhile>(1);
3676 result->base.id = TransScopeIdWhile;
3677 result->base.parent = parent_scope;
3678 result->node = trans_create_node(c, NodeTypeWhileExpr);
3679 return result;
3680}
3681
3539static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope) {3682static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope) {
3540 TransScopeBlock *result = allocate<TransScopeBlock>(1);3683 TransScopeBlock *result = allocate<TransScopeBlock>(1);
3541 result->base.id = TransScopeIdBlock;3684 result->base.id = TransScopeIdBlock;
...@@ -3553,13 +3696,13 @@ static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scop...@@ -3553,13 +3696,13 @@ static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scop
3553 return result;3696 return result;
3554}3697}
35553698
3556//static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope) {3699static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope) {
3557// TransScopeSwitch *result = allocate<TransScopeSwitch>(1);3700 TransScopeSwitch *result = allocate<TransScopeSwitch>(1);
3558// result->base.id = TransScopeIdSwitch;3701 result->base.id = TransScopeIdSwitch;
3559// result->base.parent = parent_scope;3702 result->base.parent = parent_scope;
3560// result->switch_node = trans_create_node(c, NodeTypeSwitchExpr);3703 result->switch_node = trans_create_node(c, NodeTypeSwitchExpr);
3561// return result;3704 return result;
3562//}3705}
35633706
3564static TransScopeBlock *trans_scope_block_find(TransScope *scope) {3707static TransScopeBlock *trans_scope_block_find(TransScope *scope) {
3565 while (scope != nullptr) {3708 while (scope != nullptr) {
...@@ -3571,6 +3714,16 @@ static TransScopeBlock *trans_scope_block_find(TransScope *scope) {...@@ -3571,6 +3714,16 @@ static TransScopeBlock *trans_scope_block_find(TransScope *scope) {
3571 return nullptr;3714 return nullptr;
3572}3715}
35733716
3717static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
3718 while (scope != nullptr) {
3719 if (scope->id == TransScopeIdSwitch) {
3720 return (TransScopeSwitch *)scope;
3721 }
3722 scope = scope->parent;
3723 }
3724 return nullptr;
3725}
3726
3574static void render_aliases(Context *c) {3727static void render_aliases(Context *c) {
3575 for (size_t i = 0; i < c->aliases.length; i += 1) {3728 for (size_t i = 0; i < c->aliases.length; i += 1) {
3576 Alias *alias = &c->aliases.at(i);3729 Alias *alias = &c->aliases.at(i);
test/translate_c.zig+40-40
...@@ -1001,46 +1001,46 @@ pub fn addCases(cases: &tests.TranslateCContext) {...@@ -1001,46 +1001,46 @@ pub fn addCases(cases: &tests.TranslateCContext) {
1001 \\}1001 \\}
1002 );1002 );
10031003
1004 //cases.add("switch statement",1004 cases.add("switch statement",
1005 // \\int foo(int x) {1005 \\int foo(int x) {
1006 // \\ switch (x) {1006 \\ switch (x) {
1007 // \\ case 1:1007 \\ case 1:
1008 // \\ x += 1;1008 \\ x += 1;
1009 // \\ case 2:1009 \\ case 2:
1010 // \\ break;1010 \\ break;
1011 // \\ case 3:1011 \\ case 3:
1012 // \\ case 4:1012 \\ case 4:
1013 // \\ return x + 1;1013 \\ return x + 1;
1014 // \\ default:1014 \\ default:
1015 // \\ return 10;1015 \\ return 10;
1016 // \\ }1016 \\ }
1017 // \\ return x + 13;1017 \\ return x + 13;
1018 // \\}1018 \\}
1019 //,1019 ,
1020 // \\fn foo(_x: i32) -> i32 {1020 \\fn foo(_arg_x: c_int) -> c_int {
1021 // \\ var x = _x;1021 \\ var x = _arg_x;
1022 // \\ switch (x) {1022 \\ while (true) {
1023 // \\ 1 => goto switch_case_1;1023 \\ switch (x) {
1024 // \\ 2 => goto switch_case_2;1024 \\ 1 => goto case_0,
1025 // \\ 3 => goto switch_case_3;1025 \\ 2 => goto case_1,
1026 // \\ 4 => goto switch_case_4;1026 \\ 3 => goto case_2,
1027 // \\ else => goto switch_default;1027 \\ 4 => goto case_3,
1028 // \\ }1028 \\ else => goto default,
1029 // \\switch_case_1:1029 \\ };
1030 // \\ x += 1;1030 \\ case_0:
1031 // \\ goto switch_case_2;1031 \\ x += 1;
1032 // \\switch_case_2:1032 \\ case_1:
1033 // \\ goto switch_end;1033 \\ break;
1034 // \\switch_case_3:1034 \\ case_2:
1035 // \\ goto switch_case_4;1035 \\ case_3:
1036 // \\switch_case_4:1036 \\ return x + 1;
1037 // \\ return x += 1;1037 \\ default:
1038 // \\switch_default:1038 \\ return 10;
1039 // \\ return 10;1039 \\ break;
1040 // \\switch_end:1040 \\ };
1041 // \\ return x + 13;1041 \\ return x + 13;
1042 // \\}1042 \\}
1043 //);1043 );
1044}1044}
10451045
10461046