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
10401040pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt;
10411041pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt;
10421042pub 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 {
172172 // comma operator used
173173 return try Block.init(c, scope, true);
174174 },
175 else => scope = inner,
175 else => scope = scope.parent.?,
176176 }
177177 }
178178 }
......@@ -610,7 +610,9 @@ fn transStmt(
610610 .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
611611 .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
612612 .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)),
614616 else => {
615617 return revertAndWarn(
616618 rp,
......@@ -1184,7 +1186,6 @@ fn transIfStmt(
11841186 rp: RestorePoint,
11851187 scope: *Scope,
11861188 stmt: *const ZigClangIfStmt,
1187 used: ResultUsed,
11881189) TransError!*ast.Node {
11891190 // if (c) t
11901191 // if (c) t else e
......@@ -1196,7 +1197,7 @@ fn transIfStmt(
11961197 .id = .Condition,
11971198 },
11981199 };
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);
12001201 _ = try appendToken(rp.c, .RParen, ")");
12011202
12021203 if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value);
......@@ -1209,6 +1210,87 @@ fn transIfStmt(
12091210 return &if_node.base;
12101211}
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
12121294fn transCPtrCast(
12131295 rp: RestorePoint,
12141296 loc: ZigClangSourceLocation,
......@@ -1682,7 +1764,7 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti
16821764 const builtin_token = try appendToken(c, .Builtin, name);
16831765 _ = try appendToken(c, .LParen, "(");
16841766 const node = try c.a().create(ast.Node.BuiltinCall);
1685 node.* = ast.Node.BuiltinCall{
1767 node.* = .{
16861768 .builtin_token = builtin_token,
16871769 .params = ast.Node.BuiltinCall.ParamList.init(c.a()),
16881770 .rparen_token = undefined, // set after appending args
......@@ -1693,10 +1775,10 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti
16931775fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {
16941776 _ = try appendToken(c, .LParen, "(");
16951777 const node = try c.a().create(ast.Node.SuffixOp);
1696 node.* = ast.Node.SuffixOp{
1778 node.* = .{
16971779 .lhs = .{ .node = fn_expr },
1698 .op = ast.Node.SuffixOp.Op{
1699 .Call = ast.Node.SuffixOp.Op.Call{
1780 .op = .{
1781 .Call = .{
17001782 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()),
17011783 .async_token = null,
17021784 },
......@@ -1744,7 +1826,7 @@ fn transCreateNodeInfixOp(
17441826 if (!grouped) return &node.base;
17451827 const rparen = try appendToken(rp.c, .RParen, ")");
17461828 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
1747 grouped_expr.* = ast.Node.GroupedExpression{
1829 grouped_expr.* = .{
17481830 .lparen = lparen,
17491831 .expr = &node.base,
17501832 .rparen = rparen,
......@@ -1776,9 +1858,9 @@ fn transCreateNodePtrType(
17761858 .Asterisk => try appendToken(c, .Asterisk, "*"),
17771859 else => unreachable,
17781860 };
1779 node.* = ast.Node.PrefixOp{
1861 node.* = .{
17801862 .op_token = op_token,
1781 .op = ast.Node.PrefixOp.Op{
1863 .op = .{
17821864 .PtrType = .{
17831865 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
17841866 .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 {
18111893fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression {
18121894 const ltoken = try appendToken(c, .Keyword_return, "return");
18131895 const node = try c.a().create(ast.Node.ControlFlowExpression);
1814 node.* = ast.Node.ControlFlowExpression{
1896 node.* = .{
18151897 .ltoken = ltoken,
18161898 .kind = .Return,
18171899 .rhs = null,
......@@ -1822,7 +1904,7 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression {
18221904fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
18231905 const token = try appendToken(c, .Keyword_undefined, "undefined");
18241906 const node = try c.a().create(ast.Node.UndefinedLiteral);
1825 node.* = ast.Node.UndefinedLiteral{
1907 node.* = .{
18261908 .token = token,
18271909 };
18281910 return &node.base;
......@@ -1831,7 +1913,7 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
18311913fn transCreateNodeNullLiteral(c: *Context) !*ast.Node {
18321914 const token = try appendToken(c, .Keyword_null, "null");
18331915 const node = try c.a().create(ast.Node.NullLiteral);
1834 node.* = ast.Node.NullLiteral{
1916 node.* = .{
18351917 .token = token,
18361918 };
18371919 return &node.base;
......@@ -1843,7 +1925,7 @@ fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node {
18431925 else
18441926 try appendToken(c, .Keyword_false, "false");
18451927 const node = try c.a().create(ast.Node.BoolLiteral);
1846 node.* = ast.Node.BoolLiteral{
1928 node.* = .{
18471929 .token = token,
18481930 };
18491931 return &node.base;
......@@ -2032,7 +2114,7 @@ fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowE
20322114 break :blk try transCreateNodeIdentifier(c, l);
20332115 } else null;
20342116 const node = try c.a().create(ast.Node.ControlFlowExpression);
2035 node.* = ast.Node.ControlFlowExpression{
2117 node.* = .{
20362118 .ltoken = ltoken,
20372119 .kind = .{ .Break = label_node },
20382120 .rhs = null,
......@@ -2046,7 +2128,7 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con
20462128 const name_tok = try appendIdentifier(c, name);
20472129
20482130 const node = try c.a().create(ast.Node.VarDecl);
2049 node.* = ast.Node.VarDecl{
2131 node.* = .{
20502132 .doc_comments = null,
20512133 .visib_token = visib_tok,
20522134 .thread_local_token = null,
......@@ -2065,6 +2147,24 @@ fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []con
20652147 return node;
20662148}
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
20682168const RestorePoint = struct {
20692169 c: *Context,
20702170 token_index: ast.TokenIndex,
test/translate_c.zig+40
......@@ -755,6 +755,46 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
755755 \\}
756756 });
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
758798 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
759799
760800 if (builtin.os != builtin.Os.windows) {