| ... | ... | @@ -172,7 +172,7 @@ const Scope = struct { |
| 172 | 172 | // comma operator used |
| 173 | 173 | return try Block.init(c, scope, true); |
| 174 | 174 | }, |
| 175 | | else => scope = inner, |
| 175 | else => scope = scope.parent.?, |
| 176 | 176 | } |
| 177 | 177 | } |
| 178 | 178 | } |
| ... | ... | @@ -610,7 +610,9 @@ fn transStmt( |
| 610 | 610 | .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), |
| 611 | 611 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), |
| 612 | 612 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used), |
| 613 | | .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const ZigClangIfStmt, stmt), result_used), |
| 613 | .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const ZigClangIfStmt, stmt)), |
| 614 | .WhileStmtClass => return transWhileLoop(rp, scope, @ptrCast(*const ZigClangWhileStmt, stmt)), |
| 615 | .DoStmtClass => return transDoWhileLoop(rp, scope, @ptrCast(*const ZigClangDoStmt, stmt)), |
| 614 | 616 | else => { |
| 615 | 617 | return revertAndWarn( |
| 616 | 618 | rp, |
| ... | ... | @@ -1184,7 +1186,6 @@ fn transIfStmt( |
| 1184 | 1186 | rp: RestorePoint, |
| 1185 | 1187 | scope: *Scope, |
| 1186 | 1188 | stmt: *const ZigClangIfStmt, |
| 1187 | | used: ResultUsed, |
| 1188 | 1189 | ) TransError!*ast.Node { |
| 1189 | 1190 | // if (c) t |
| 1190 | 1191 | // if (c) t else e |
| ... | ... | @@ -1196,7 +1197,7 @@ fn transIfStmt( |
| 1196 | 1197 | .id = .Condition, |
| 1197 | 1198 | }, |
| 1198 | 1199 | }; |
| 1199 | | if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value); |
| 1200 | if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value, false); |
| 1200 | 1201 | _ = try appendToken(rp.c, .RParen, ")"); |
| 1201 | 1202 | |
| 1202 | 1203 | if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value); |
| ... | ... | @@ -1209,6 +1210,87 @@ fn transIfStmt( |
| 1209 | 1210 | return &if_node.base; |
| 1210 | 1211 | } |
| 1211 | 1212 | |
| 1213 | fn transWhileLoop( |
| 1214 | rp: RestorePoint, |
| 1215 | scope: *Scope, |
| 1216 | stmt: *const ZigClangWhileStmt, |
| 1217 | ) TransError!*ast.Node { |
| 1218 | const while_node = try transCreateNodeWhile(rp.c); |
| 1219 | |
| 1220 | var cond_scope = Scope.Condition{ |
| 1221 | .base = .{ |
| 1222 | .parent = scope, |
| 1223 | .id = .Condition, |
| 1224 | }, |
| 1225 | }; |
| 1226 | while_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangWhileStmt_getCond(stmt)), .used, .r_value, false); |
| 1227 | _ = try appendToken(rp.c, .RParen, ")"); |
| 1228 | |
| 1229 | while_node.body = try transStmt(rp, scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value); |
| 1230 | return &while_node.base; |
| 1231 | } |
| 1232 | |
| 1233 | fn transDoWhileLoop( |
| 1234 | rp: RestorePoint, |
| 1235 | scope: *Scope, |
| 1236 | stmt: *const ZigClangDoStmt, |
| 1237 | ) TransError!*ast.Node { |
| 1238 | const while_node = try transCreateNodeWhile(rp.c); |
| 1239 | |
| 1240 | while_node.condition = try transCreateNodeBoolLiteral(rp.c, true); |
| 1241 | _ = try appendToken(rp.c, .RParen, ")"); |
| 1242 | var new = false; |
| 1243 | |
| 1244 | const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) |
| 1245 | // there's already a block in C, so we'll append our condition to it. |
| 1246 | // c: do { |
| 1247 | // c: a; |
| 1248 | // c: b; |
| 1249 | // c: } while(c); |
| 1250 | // zig: while (true) { |
| 1251 | // zig: a; |
| 1252 | // zig: b; |
| 1253 | // zig: if (!cond) break; |
| 1254 | // zig: } |
| 1255 | (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).? |
| 1256 | else blk: { |
| 1257 | // the C statement is without a block, so we need to create a block to contain it. |
| 1258 | // c: do |
| 1259 | // c: a; |
| 1260 | // c: while(c); |
| 1261 | // zig: while (true) { |
| 1262 | // zig: a; |
| 1263 | // zig: if (!cond) break; |
| 1264 | // zig: } |
| 1265 | |
| 1266 | new = true; |
| 1267 | const block = try transCreateNodeBlock(rp.c, null); |
| 1268 | try block.statements.push(try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)); |
| 1269 | break :blk block; |
| 1270 | }; |
| 1271 | |
| 1272 | // if (!cond) break; |
| 1273 | const if_node = try transCreateNodeIf(rp.c); |
| 1274 | var cond_scope = Scope.Condition{ |
| 1275 | .base = .{ |
| 1276 | .parent = scope, |
| 1277 | .id = .Condition, |
| 1278 | }, |
| 1279 | }; |
| 1280 | const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); |
| 1281 | prefix_op.rhs = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, false); |
| 1282 | _ = try appendToken(rp.c, .RParen, ")"); |
| 1283 | if_node.condition = &prefix_op.base; |
| 1284 | if_node.body = &(try transCreateNodeBreak(rp.c, null)).base; |
| 1285 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 1286 | |
| 1287 | try body_node.statements.push(&if_node.base); |
| 1288 | if (new) |
| 1289 | body_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 1290 | while_node.body = &body_node.base; |
| 1291 | return &while_node.base; |
| 1292 | } |
| 1293 | |
| 1212 | 1294 | fn transCPtrCast( |
| 1213 | 1295 | rp: RestorePoint, |
| 1214 | 1296 | loc: ZigClangSourceLocation, |
| ... | ... | @@ -1682,7 +1764,7 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti |
| 1682 | 1764 | const builtin_token = try appendToken(c, .Builtin, name); |
| 1683 | 1765 | _ = try appendToken(c, .LParen, "("); |
| 1684 | 1766 | const node = try c.a().create(ast.Node.BuiltinCall); |
| 1685 | | node.* = ast.Node.BuiltinCall{ |
| 1767 | node.* = .{ |
| 1686 | 1768 | .builtin_token = builtin_token, |
| 1687 | 1769 | .params = ast.Node.BuiltinCall.ParamList.init(c.a()), |
| 1688 | 1770 | .rparen_token = undefined, // set after appending args |
| ... | ... | @@ -1693,10 +1775,10 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti |
| 1693 | 1775 | fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 1694 | 1776 | _ = try appendToken(c, .LParen, "("); |
| 1695 | 1777 | const node = try c.a().create(ast.Node.SuffixOp); |
| 1696 | | node.* = ast.Node.SuffixOp{ |
| 1778 | node.* = .{ |
| 1697 | 1779 | .lhs = .{ .node = fn_expr }, |
| 1698 | | .op = ast.Node.SuffixOp.Op{ |
| 1699 | | .Call = ast.Node.SuffixOp.Op.Call{ |
| 1780 | .op = .{ |
| 1781 | .Call = .{ |
| 1700 | 1782 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), |
| 1701 | 1783 | .async_token = null, |
| 1702 | 1784 | }, |
| ... | ... | @@ -1744,7 +1826,7 @@ fn transCreateNodeInfixOp( |
| 1744 | 1826 | if (!grouped) return &node.base; |
| 1745 | 1827 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| 1746 | 1828 | const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); |
| 1747 | | grouped_expr.* = ast.Node.GroupedExpression{ |
| 1829 | grouped_expr.* = .{ |
| 1748 | 1830 | .lparen = lparen, |
| 1749 | 1831 | .expr = &node.base, |
| 1750 | 1832 | .rparen = rparen, |
| ... | ... | @@ -1776,9 +1858,9 @@ fn transCreateNodePtrType( |
| 1776 | 1858 | .Asterisk => try appendToken(c, .Asterisk, "*"), |
| 1777 | 1859 | else => unreachable, |
| 1778 | 1860 | }; |
| 1779 | | node.* = ast.Node.PrefixOp{ |
| 1861 | node.* = .{ |
| 1780 | 1862 | .op_token = op_token, |
| 1781 | | .op = ast.Node.PrefixOp.Op{ |
| 1863 | .op = .{ |
| 1782 | 1864 | .PtrType = .{ |
| 1783 | 1865 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, |
| 1784 | 1866 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, |
| ... | ... | @@ -1811,7 +1893,7 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { |
| 1811 | 1893 | fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { |
| 1812 | 1894 | const ltoken = try appendToken(c, .Keyword_return, "return"); |
| 1813 | 1895 | const node = try c.a().create(ast.Node.ControlFlowExpression); |
| 1814 | | node.* = ast.Node.ControlFlowExpression{ |
| 1896 | node.* = .{ |
| 1815 | 1897 | .ltoken = ltoken, |
| 1816 | 1898 | .kind = .Return, |
| 1817 | 1899 | .rhs = null, |
| ... | ... | @@ -1822,7 +1904,7 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { |
| 1822 | 1904 | fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| 1823 | 1905 | const token = try appendToken(c, .Keyword_undefined, "undefined"); |
| 1824 | 1906 | const node = try c.a().create(ast.Node.UndefinedLiteral); |
| 1825 | | node.* = ast.Node.UndefinedLiteral{ |
| 1907 | node.* = .{ |
| 1826 | 1908 | .token = token, |
| 1827 | 1909 | }; |
| 1828 | 1910 | return &node.base; |
| ... | ... | @@ -1831,7 +1913,7 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| 1831 | 1913 | fn transCreateNodeNullLiteral(c: *Context) !*ast.Node { |
| 1832 | 1914 | const token = try appendToken(c, .Keyword_null, "null"); |
| 1833 | 1915 | const node = try c.a().create(ast.Node.NullLiteral); |
| 1834 | | node.* = ast.Node.NullLiteral{ |
| 1916 | node.* = .{ |
| 1835 | 1917 | .token = token, |
| 1836 | 1918 | }; |
| 1837 | 1919 | return &node.base; |
| ... | ... | @@ -1843,7 +1925,7 @@ fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node { |
| 1843 | 1925 | else |
| 1844 | 1926 | try appendToken(c, .Keyword_false, "false"); |
| 1845 | 1927 | const node = try c.a().create(ast.Node.BoolLiteral); |
| 1846 | | node.* = ast.Node.BoolLiteral{ |
| 1928 | node.* = .{ |
| 1847 | 1929 | .token = token, |
| 1848 | 1930 | }; |
| 1849 | 1931 | return &node.base; |
| ... | ... | @@ -2032,7 +2114,7 @@ fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowE |
| 2032 | 2114 | break :blk try transCreateNodeIdentifier(c, l); |
| 2033 | 2115 | } else null; |
| 2034 | 2116 | const node = try c.a().create(ast.Node.ControlFlowExpression); |
| 2035 | | node.* = ast.Node.ControlFlowExpression{ |
| 2117 | node.* = .{ |
| 2036 | 2118 | .ltoken = ltoken, |
| 2037 | 2119 | .kind = .{ .Break = label_node }, |
| 2038 | 2120 | .rhs = null, |
| ... | ... | @@ -2046,7 +2128,7 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con |
| 2046 | 2128 | const name_tok = try appendIdentifier(c, name); |
| 2047 | 2129 | |
| 2048 | 2130 | const node = try c.a().create(ast.Node.VarDecl); |
| 2049 | | node.* = ast.Node.VarDecl{ |
| 2131 | node.* = .{ |
| 2050 | 2132 | .doc_comments = null, |
| 2051 | 2133 | .visib_token = visib_tok, |
| 2052 | 2134 | .thread_local_token = null, |
| ... | ... | @@ -2065,6 +2147,24 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con |
| 2065 | 2147 | return node; |
| 2066 | 2148 | } |
| 2067 | 2149 | |
| 2150 | fn transCreateNodeWhile(c: *Context) !*ast.Node.While { |
| 2151 | const while_tok = try appendToken(c, .Keyword_while, "while"); |
| 2152 | _ = try appendToken(c, .LParen, "("); |
| 2153 | |
| 2154 | const node = try c.a().create(ast.Node.While); |
| 2155 | node.* = .{ |
| 2156 | .label = null, |
| 2157 | .inline_token = null, |
| 2158 | .while_token = while_tok, |
| 2159 | .condition = undefined, |
| 2160 | .payload = null, |
| 2161 | .continue_expr = null, |
| 2162 | .body = undefined, |
| 2163 | .@"else" = null, |
| 2164 | }; |
| 2165 | return node; |
| 2166 | } |
| 2167 | |
| 2068 | 2168 | const RestorePoint = struct { |
| 2069 | 2169 | c: *Context, |
| 2070 | 2170 | token_index: ast.TokenIndex, |