| ... | @@ -207,9 +207,10 @@ const Scope = struct { | ... | @@ -207,9 +207,10 @@ const Scope = struct { |
| 207 | }; | 207 | }; |
| 208 | } | 208 | } |
| 209 | | 209 | |
| 210 | fn getBreakableScope(scope: *Scope) *Scope { | 210 | fn getBreakableScope(inner: *Scope) *Scope { |
| 211 | var scope = inner; | 211 | var scope = inner; |
| 212 | while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {} | 212 | while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {} |
| | 213 | return scope; |
| 213 | } | 214 | } |
| 214 | }; | 215 | }; |
| 215 | | 216 | |
| ... | @@ -626,8 +627,9 @@ fn transStmt( | ... | @@ -626,8 +627,9 @@ fn transStmt( |
| 626 | block.rbrace = try appendToken(rp.c, .RBrace, "}"); | 627 | block.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 627 | return &block.base; | 628 | return &block.base; |
| 628 | }, | 629 | }, |
| 629 | .ContinueStmtClass => return transCreateNodeContinue(rp.c), | 630 | .ContinueStmtClass => return try transCreateNodeContinue(rp.c), |
| 630 | .BreakStmtClass => return transBreak(rp, scope), | 631 | .BreakStmtClass => return transBreak(rp, scope), |
| | 632 | .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)), |
| 631 | else => { | 633 | else => { |
| 632 | return revertAndWarn( | 634 | return revertAndWarn( |
| 633 | rp, | 635 | rp, |
| ... | @@ -795,7 +797,7 @@ fn transCompoundStmtInline( | ... | @@ -795,7 +797,7 @@ fn transCompoundStmtInline( |
| 795 | | 797 | |
| 796 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { | 798 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { |
| 797 | const block_scope = try Scope.Block.init(rp.c, scope, false); | 799 | const block_scope = try Scope.Block.init(rp.c, scope, false); |
| 798 | block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); | 800 | block_scope.block_node = try transCreateNodeBlock(rp.c, null); |
| 799 | try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); | 801 | try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); |
| 800 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); | 802 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 801 | return &block_scope.block_node.base; | 803 | return &block_scope.block_node.base; |
| ... | @@ -1267,7 +1269,7 @@ fn transDoWhileLoop( | ... | @@ -1267,7 +1269,7 @@ fn transDoWhileLoop( |
| 1267 | // zig: b; | 1269 | // zig: b; |
| 1268 | // zig: if (!cond) break; | 1270 | // zig: if (!cond) break; |
| 1269 | // zig: } | 1271 | // zig: } |
| 1270 | break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).? | 1272 | break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?; |
| 1271 | } else blk: { | 1273 | } else blk: { |
| 1272 | // the C statement is without a block, so we need to create a block to contain it. | 1274 | // the C statement is without a block, so we need to create a block to contain it. |
| 1273 | // c: do | 1275 | // c: do |
| ... | @@ -1305,6 +1307,50 @@ fn transDoWhileLoop( | ... | @@ -1305,6 +1307,50 @@ fn transDoWhileLoop( |
| 1305 | return &while_node.base; | 1307 | return &while_node.base; |
| 1306 | } | 1308 | } |
| 1307 | | 1309 | |
| | 1310 | fn transForLoop( |
| | 1311 | rp: RestorePoint, |
| | 1312 | scope: *Scope, |
| | 1313 | stmt: *const ZigClangForStmt, |
| | 1314 | ) TransError!*ast.Node { |
| | 1315 | var inner = scope; |
| | 1316 | var block = false; |
| | 1317 | var block_scope: ?*Scope.Block = null; |
| | 1318 | if (ZigClangForStmt_getInit(stmt)) |init| { |
| | 1319 | block_scope = try Scope.Block.init(rp.c, scope, false); |
| | 1320 | block_scope.?.block_node = try transCreateNodeBlock(rp.c, null); |
| | 1321 | inner = &block_scope.?.base; |
| | 1322 | _ = try transStmt(rp, inner, init, .unused, .r_value); |
| | 1323 | } |
| | 1324 | var cond_scope = Scope.Condition{ |
| | 1325 | .base = .{ |
| | 1326 | .parent = inner, |
| | 1327 | .id = .Condition, |
| | 1328 | }, |
| | 1329 | }; |
| | 1330 | |
| | 1331 | const while_node = try transCreateNodeWhile(rp.c); |
| | 1332 | while_node.condition = if (ZigClangForStmt_getCond(stmt)) |cond| |
| | 1333 | try transBoolExpr(rp, &cond_scope.base, cond, .used, .r_value, false) |
| | 1334 | else |
| | 1335 | try transCreateNodeBoolLiteral(rp.c, true); |
| | 1336 | _ = try appendToken(rp.c, .RParen, ")"); |
| | 1337 | |
| | 1338 | if (ZigClangForStmt_getInc(stmt)) |incr| { |
| | 1339 | _ = try appendToken(rp.c, .Colon, ":"); |
| | 1340 | _ = try appendToken(rp.c, .LParen, "("); |
| | 1341 | while_node.continue_expr = try transExpr(rp, &cond_scope.base, incr, .unused, .r_value); |
| | 1342 | _ = try appendToken(rp.c, .RParen, ")"); |
| | 1343 | } |
| | 1344 | |
| | 1345 | while_node.body = try transStmt(rp, inner, ZigClangForStmt_getBody(stmt), .unused, .r_value); |
| | 1346 | if (block_scope != null) { |
| | 1347 | try block_scope.?.block_node.statements.push(&while_node.base); |
| | 1348 | block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| | 1349 | return &block_scope.?.block_node.base; |
| | 1350 | } else |
| | 1351 | return &while_node.base; |
| | 1352 | } |
| | 1353 | |
| 1308 | fn transCPtrCast( | 1354 | fn transCPtrCast( |
| 1309 | rp: RestorePoint, | 1355 | rp: RestorePoint, |
| 1310 | loc: ZigClangSourceLocation, | 1356 | loc: ZigClangSourceLocation, |
| ... | @@ -1358,12 +1404,20 @@ fn maybeSuppressResult( | ... | @@ -1358,12 +1404,20 @@ fn maybeSuppressResult( |
| 1358 | result: *ast.Node, | 1404 | result: *ast.Node, |
| 1359 | ) TransError!*ast.Node { | 1405 | ) TransError!*ast.Node { |
| 1360 | if (used == .used) return result; | 1406 | if (used == .used) return result; |
| 1361 | // NOTE: This is backwards, but the semicolon must immediately follow the node. | 1407 | if (scope.id != .Condition) { |
| 1362 | _ = try appendToken(rp.c, .Semicolon, ";"); | 1408 | // NOTE: This is backwards, but the semicolon must immediately follow the node. |
| | 1409 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| | 1410 | } else { // TODO is there a way to avoid this hack? |
| | 1411 | // this parenthesis must come immediately following the node |
| | 1412 | _ = try appendToken(rp.c, .RParen, ")"); |
| | 1413 | // these need to come before _ |
| | 1414 | _ = try appendToken(rp.c, .Colon, ":"); |
| | 1415 | _ = try appendToken(rp.c, .LParen, "("); |
| | 1416 | } |
| 1363 | const lhs = try transCreateNodeIdentifier(rp.c, "_"); | 1417 | const lhs = try transCreateNodeIdentifier(rp.c, "_"); |
| 1364 | const op_token = try appendToken(rp.c, .Equal, "="); | 1418 | const op_token = try appendToken(rp.c, .Equal, "="); |
| 1365 | const op_node = try rp.c.a().create(ast.Node.InfixOp); | 1419 | const op_node = try rp.c.a().create(ast.Node.InfixOp); |
| 1366 | op_node.* = ast.Node.InfixOp{ | 1420 | op_node.* = .{ |
| 1367 | .op_token = op_token, | 1421 | .op_token = op_token, |
| 1368 | .lhs = lhs, | 1422 | .lhs = lhs, |
| 1369 | .op = .Assign, | 1423 | .op = .Assign, |
| ... | @@ -1728,7 +1782,8 @@ fn transCreateNodeAssign( | ... | @@ -1728,7 +1782,8 @@ fn transCreateNodeAssign( |
| 1728 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); | 1782 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| 1729 | const eq_token = try appendToken(rp.c, .Equal, "="); | 1783 | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 1730 | const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); | 1784 | const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); |
| 1731 | _ = try appendToken(rp.c, .Semicolon, ";"); | 1785 | if (scope.id != .Condition) |
| | 1786 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 1732 | | 1787 | |
| 1733 | const node = try rp.c.a().create(ast.Node.InfixOp); | 1788 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| 1734 | node.* = .{ | 1789 | node.* = .{ |
| ... | @@ -2196,7 +2251,7 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node { | ... | @@ -2196,7 +2251,7 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node { |
| 2196 | .kind = .{ .Continue = null }, | 2251 | .kind = .{ .Continue = null }, |
| 2197 | .rhs = null, | 2252 | .rhs = null, |
| 2198 | }; | 2253 | }; |
| 2199 | _ = try appendToken(rp.c, .Semicolon, ";"); | 2254 | _ = try appendToken(c, .Semicolon, ";"); |
| 2200 | return &node.base; | 2255 | return &node.base; |
| 2201 | } | 2256 | } |
| 2202 | | 2257 | |