| ... | @@ -172,7 +172,7 @@ const Scope = struct { | ... | @@ -172,7 +172,7 @@ const Scope = struct { |
| 172 | // comma operator used | 172 | // comma operator used |
| 173 | return try Block.init(c, scope, true); | 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,7 +610,9 @@ fn transStmt( |
| 610 | .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), | 610 | .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), |
| 611 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), | 611 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), |
| 612 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used), | 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 | else => { | 616 | else => { |
| 615 | return revertAndWarn( | 617 | return revertAndWarn( |
| 616 | rp, | 618 | rp, |
| ... | @@ -1184,7 +1186,6 @@ fn transIfStmt( | ... | @@ -1184,7 +1186,6 @@ fn transIfStmt( |
| 1184 | rp: RestorePoint, | 1186 | rp: RestorePoint, |
| 1185 | scope: *Scope, | 1187 | scope: *Scope, |
| 1186 | stmt: *const ZigClangIfStmt, | 1188 | stmt: *const ZigClangIfStmt, |
| 1187 | used: ResultUsed, | | |
| 1188 | ) TransError!*ast.Node { | 1189 | ) TransError!*ast.Node { |
| 1189 | // if (c) t | 1190 | // if (c) t |
| 1190 | // if (c) t else e | 1191 | // if (c) t else e |
| ... | @@ -1196,7 +1197,7 @@ fn transIfStmt( | ... | @@ -1196,7 +1197,7 @@ fn transIfStmt( |
| 1196 | .id = .Condition, | 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 | _ = try appendToken(rp.c, .RParen, ")"); | 1201 | _ = try appendToken(rp.c, .RParen, ")"); |
| 1201 | | 1202 | |
| 1202 | if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value); | 1203 | if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value); |
| ... | @@ -1209,6 +1210,87 @@ fn transIfStmt( | ... | @@ -1209,6 +1210,87 @@ fn transIfStmt( |
| 1209 | return &if_node.base; | 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 | fn transCPtrCast( | 1294 | fn transCPtrCast( |
| 1213 | rp: RestorePoint, | 1295 | rp: RestorePoint, |
| 1214 | loc: ZigClangSourceLocation, | 1296 | loc: ZigClangSourceLocation, |
| ... | @@ -1682,7 +1764,7 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti | ... | @@ -1682,7 +1764,7 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti |
| 1682 | const builtin_token = try appendToken(c, .Builtin, name); | 1764 | const builtin_token = try appendToken(c, .Builtin, name); |
| 1683 | _ = try appendToken(c, .LParen, "("); | 1765 | _ = try appendToken(c, .LParen, "("); |
| 1684 | const node = try c.a().create(ast.Node.BuiltinCall); | 1766 | const node = try c.a().create(ast.Node.BuiltinCall); |
| 1685 | node.* = ast.Node.BuiltinCall{ | 1767 | node.* = .{ |
| 1686 | .builtin_token = builtin_token, | 1768 | .builtin_token = builtin_token, |
| 1687 | .params = ast.Node.BuiltinCall.ParamList.init(c.a()), | 1769 | .params = ast.Node.BuiltinCall.ParamList.init(c.a()), |
| 1688 | .rparen_token = undefined, // set after appending args | 1770 | .rparen_token = undefined, // set after appending args |
| ... | @@ -1693,10 +1775,10 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti | ... | @@ -1693,10 +1775,10 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti |
| 1693 | fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { | 1775 | fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 1694 | _ = try appendToken(c, .LParen, "("); | 1776 | _ = try appendToken(c, .LParen, "("); |
| 1695 | const node = try c.a().create(ast.Node.SuffixOp); | 1777 | const node = try c.a().create(ast.Node.SuffixOp); |
| 1696 | node.* = ast.Node.SuffixOp{ | 1778 | node.* = .{ |
| 1697 | .lhs = .{ .node = fn_expr }, | 1779 | .lhs = .{ .node = fn_expr }, |
| 1698 | .op = ast.Node.SuffixOp.Op{ | 1780 | .op = .{ |
| 1699 | .Call = ast.Node.SuffixOp.Op.Call{ | 1781 | .Call = .{ |
| 1700 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), | 1782 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), |
| 1701 | .async_token = null, | 1783 | .async_token = null, |
| 1702 | }, | 1784 | }, |
| ... | @@ -1744,7 +1826,7 @@ fn transCreateNodeInfixOp( | ... | @@ -1744,7 +1826,7 @@ fn transCreateNodeInfixOp( |
| 1744 | if (!grouped) return &node.base; | 1826 | if (!grouped) return &node.base; |
| 1745 | const rparen = try appendToken(rp.c, .RParen, ")"); | 1827 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| 1746 | const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); | 1828 | const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); |
| 1747 | grouped_expr.* = ast.Node.GroupedExpression{ | 1829 | grouped_expr.* = .{ |
| 1748 | .lparen = lparen, | 1830 | .lparen = lparen, |
| 1749 | .expr = &node.base, | 1831 | .expr = &node.base, |
| 1750 | .rparen = rparen, | 1832 | .rparen = rparen, |
| ... | @@ -1776,9 +1858,9 @@ fn transCreateNodePtrType( | ... | @@ -1776,9 +1858,9 @@ fn transCreateNodePtrType( |
| 1776 | .Asterisk => try appendToken(c, .Asterisk, "*"), | 1858 | .Asterisk => try appendToken(c, .Asterisk, "*"), |
| 1777 | else => unreachable, | 1859 | else => unreachable, |
| 1778 | }; | 1860 | }; |
| 1779 | node.* = ast.Node.PrefixOp{ | 1861 | node.* = .{ |
| 1780 | .op_token = op_token, | 1862 | .op_token = op_token, |
| 1781 | .op = ast.Node.PrefixOp.Op{ | 1863 | .op = .{ |
| 1782 | .PtrType = .{ | 1864 | .PtrType = .{ |
| 1783 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, | 1865 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, |
| 1784 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, | 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,7 +1893,7 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { |
| 1811 | fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { | 1893 | fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { |
| 1812 | const ltoken = try appendToken(c, .Keyword_return, "return"); | 1894 | const ltoken = try appendToken(c, .Keyword_return, "return"); |
| 1813 | const node = try c.a().create(ast.Node.ControlFlowExpression); | 1895 | const node = try c.a().create(ast.Node.ControlFlowExpression); |
| 1814 | node.* = ast.Node.ControlFlowExpression{ | 1896 | node.* = .{ |
| 1815 | .ltoken = ltoken, | 1897 | .ltoken = ltoken, |
| 1816 | .kind = .Return, | 1898 | .kind = .Return, |
| 1817 | .rhs = null, | 1899 | .rhs = null, |
| ... | @@ -1822,7 +1904,7 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { | ... | @@ -1822,7 +1904,7 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { |
| 1822 | fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { | 1904 | fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| 1823 | const token = try appendToken(c, .Keyword_undefined, "undefined"); | 1905 | const token = try appendToken(c, .Keyword_undefined, "undefined"); |
| 1824 | const node = try c.a().create(ast.Node.UndefinedLiteral); | 1906 | const node = try c.a().create(ast.Node.UndefinedLiteral); |
| 1825 | node.* = ast.Node.UndefinedLiteral{ | 1907 | node.* = .{ |
| 1826 | .token = token, | 1908 | .token = token, |
| 1827 | }; | 1909 | }; |
| 1828 | return &node.base; | 1910 | return &node.base; |
| ... | @@ -1831,7 +1913,7 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { | ... | @@ -1831,7 +1913,7 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| 1831 | fn transCreateNodeNullLiteral(c: *Context) !*ast.Node { | 1913 | fn transCreateNodeNullLiteral(c: *Context) !*ast.Node { |
| 1832 | const token = try appendToken(c, .Keyword_null, "null"); | 1914 | const token = try appendToken(c, .Keyword_null, "null"); |
| 1833 | const node = try c.a().create(ast.Node.NullLiteral); | 1915 | const node = try c.a().create(ast.Node.NullLiteral); |
| 1834 | node.* = ast.Node.NullLiteral{ | 1916 | node.* = .{ |
| 1835 | .token = token, | 1917 | .token = token, |
| 1836 | }; | 1918 | }; |
| 1837 | return &node.base; | 1919 | return &node.base; |
| ... | @@ -1843,7 +1925,7 @@ fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node { | ... | @@ -1843,7 +1925,7 @@ fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node { |
| 1843 | else | 1925 | else |
| 1844 | try appendToken(c, .Keyword_false, "false"); | 1926 | try appendToken(c, .Keyword_false, "false"); |
| 1845 | const node = try c.a().create(ast.Node.BoolLiteral); | 1927 | const node = try c.a().create(ast.Node.BoolLiteral); |
| 1846 | node.* = ast.Node.BoolLiteral{ | 1928 | node.* = .{ |
| 1847 | .token = token, | 1929 | .token = token, |
| 1848 | }; | 1930 | }; |
| 1849 | return &node.base; | 1931 | return &node.base; |
| ... | @@ -2032,7 +2114,7 @@ fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowE | ... | @@ -2032,7 +2114,7 @@ fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowE |
| 2032 | break :blk try transCreateNodeIdentifier(c, l); | 2114 | break :blk try transCreateNodeIdentifier(c, l); |
| 2033 | } else null; | 2115 | } else null; |
| 2034 | const node = try c.a().create(ast.Node.ControlFlowExpression); | 2116 | const node = try c.a().create(ast.Node.ControlFlowExpression); |
| 2035 | node.* = ast.Node.ControlFlowExpression{ | 2117 | node.* = .{ |
| 2036 | .ltoken = ltoken, | 2118 | .ltoken = ltoken, |
| 2037 | .kind = .{ .Break = label_node }, | 2119 | .kind = .{ .Break = label_node }, |
| 2038 | .rhs = null, | 2120 | .rhs = null, |
| ... | @@ -2046,7 +2128,7 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con | ... | @@ -2046,7 +2128,7 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con |
| 2046 | const name_tok = try appendIdentifier(c, name); | 2128 | const name_tok = try appendIdentifier(c, name); |
| 2047 | | 2129 | |
| 2048 | const node = try c.a().create(ast.Node.VarDecl); | 2130 | const node = try c.a().create(ast.Node.VarDecl); |
| 2049 | node.* = ast.Node.VarDecl{ | 2131 | node.* = .{ |
| 2050 | .doc_comments = null, | 2132 | .doc_comments = null, |
| 2051 | .visib_token = visib_tok, | 2133 | .visib_token = visib_tok, |
| 2052 | .thread_local_token = null, | 2134 | .thread_local_token = null, |
| ... | @@ -2065,6 +2147,24 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con | ... | @@ -2065,6 +2147,24 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con |
| 2065 | return node; | 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 | const RestorePoint = struct { | 2168 | const RestorePoint = struct { |
| 2069 | c: *Context, | 2169 | c: *Context, |
| 2070 | token_index: ast.TokenIndex, | 2170 | token_index: ast.TokenIndex, |