authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-16 21:45:38+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-16 22:10:17+02:00
log6a3d48353b14ff234484887258cfab5ef51fdea0
treeaf843d9a65fc9aa8f0b3d3f346dd7e9a38f1bb7c
parente3f1bfe48388b3c585792367a898a25c58324000
signature Commit is signed but in an unrecognized format.

translate-c-2 while loops


3 files changed, 166 insertions(+), 17 deletions(-)

src-self-hosted/clang.zig+9
...@@ -1040,3 +1040,12 @@ pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getEnd(*const ZigClan...@@ -1040,3 +1040,12 @@ pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getEnd(*const ZigClan
1040pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt;1040pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt;
1041pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt;1041pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt;
1042pub extern fn ZigClangIfStmt_getCond(*const ZigClangIfStmt) *const ZigClangStmt;1042pub extern fn ZigClangIfStmt_getCond(*const ZigClangIfStmt) *const ZigClangStmt;
1043
1044pub extern fn ZigClangWhileStmt_getCond(*const ZigClangWhileStmt) *const ZigClangExpr;
1045pub extern fn ZigClangWhileStmt_getBody(*const ZigClangWhileStmt) *const ZigClangStmt;
1046
1047pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
1048pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
1049
1050pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
1051pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
src-self-hosted/translate_c.zig+117-17
...@@ -172,7 +172,7 @@ const Scope = struct {...@@ -172,7 +172,7 @@ const Scope = struct {
172 // comma operator used172 // 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) t1190 // if (c) t
1190 // if (c) t else e1191 // 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, ")");
12011202
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}
12111212
1213fn 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
1233fn 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
1212fn transCPtrCast(1294fn 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 args1770 .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
1693fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {1775fn 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 {
1811fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression {1893fn 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 {
1822fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {1904fn 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 {
1831fn transCreateNodeNullLiteral(c: *Context) !*ast.Node {1913fn 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 else1925 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);
20472129
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}
20672149
2150fn 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
2068const RestorePoint = struct {2168const RestorePoint = struct {
2069 c: *Context,2169 c: *Context,
2070 token_index: ast.TokenIndex,2170 token_index: ast.TokenIndex,
test/translate_c.zig+40
...@@ -755,6 +755,46 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -755,6 +755,46 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
755 \\}755 \\}
756 });756 });
757757
758 cases.add_2("while loops",
759 \\int foo() {
760 \\ int a = 5;
761 \\ while (2)
762 \\ a = 2;
763 \\ while (4) {
764 \\ int a = 4;
765 \\ a = 9;
766 \\ return 6, a;
767 \\ }
768 \\ do {
769 \\ int a = 2;
770 \\ a = 12;
771 \\ } while (4);
772 \\ do
773 \\ a = 7;
774 \\ while (4);
775 \\}
776 , &[_][]const u8{
777 \\pub export fn foo() c_int {
778 \\ var a: c_int = 5;
779 \\ while (2 != 0) a = 2;
780 \\ while (4 != 0) {
781 \\ var a: c_int = 4;
782 \\ a = 9;
783 \\ _ = 6;
784 \\ return a;
785 \\ }
786 \\ while (true) {
787 \\ var a: c_int = 2;
788 \\ a = 12;
789 \\ if (!4 != 0) break;
790 \\ }
791 \\ while (true) {
792 \\ a = 7;
793 \\ if (!4 != 0) break;
794 \\ }
795 \\}
796 });
797
758 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////798 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
759799
760 if (builtin.os != builtin.Os.windows) {800 if (builtin.os != builtin.Os.windows) {