From 0283ab8a1a27c9d3a7a6d88960418485a7125d1d Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 17 Dec 2019 12:06:28 +0200 Subject: [PATCH] translate-c-2 conditional operator --- src-self-hosted/clang.zig | 4 ++++ src-self-hosted/translate_c.zig | 42 +++++++++++++++++++++++++++++++-- test/translate_c.zig | 12 ++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 559a4ad0e5..dcb830df69 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -1055,3 +1055,7 @@ pub extern fn ZigClangForStmt_getBody(*const ZigClangForStmt) *const ZigClangStm pub extern fn ZigClangAPFloat_toString(self: *const ZigClangAPFloat, precision: c_uint, maxPadding: c_uint, truncateZero: bool) [*:0]const u8; pub extern fn ZigClangAPFloat_getValueAsApproximateDouble(*const ZigClangFloatingLiteral) f64; + +pub extern fn ZigClangConditionalOperator_getCond(*const ZigClangConditionalOperator) *const ZigClangExpr; +pub extern fn ZigClangConditionalOperator_getTrueExpr(*const ZigClangConditionalOperator) *const ZigClangExpr; +pub extern fn ZigClangConditionalOperator_getFalseExpr(*const ZigClangConditionalOperator) *const ZigClangExpr; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 4cdef9f805..79b32c2fa2 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -633,6 +633,7 @@ fn transStmt( .BreakStmtClass => return transBreak(rp, scope), .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)), .FloatingLiteralClass => return transFloatingLiteral(rp, scope, @ptrCast(*const ZigClangFloatingLiteral, stmt), result_used), + .ConditionalOperatorClass => return transConditionalOperator(rp, scope, @ptrCast(*const ZigClangConditionalOperator, stmt), result_used), else => { return revertAndWarn( rp, @@ -1239,11 +1240,11 @@ fn transIfStmt( if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value, false); _ = try appendToken(rp.c, .RParen, ")"); - if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value); + if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .unused, .r_value); if (ZigClangIfStmt_getElse(stmt)) |expr| { if_node.@"else" = try transCreateNodeElse(rp.c); - if_node.@"else".?.body = try transStmt(rp, scope, expr, .used, .r_value); + if_node.@"else".?.body = try transStmt(rp, scope, expr, .unused, .r_value); } _ = try appendToken(rp.c, .Semicolon, ";"); return &if_node.base; @@ -1429,6 +1430,43 @@ fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangFl return maybeSuppressResult(rp, scope, used, &node.base); } +fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangConditionalOperator, used: ResultUsed) TransError!*ast.Node { + const gropued = scope.id == .Condition; + const lparen = if (gropued) try appendToken(rp.c, .LParen, "(") else undefined; + const if_node = try transCreateNodeIf(rp.c); + var cond_scope = Scope.Condition{ + .base = .{ + .parent = scope, + .id = .Condition, + }, + }; + + const cond_expr = ZigClangConditionalOperator_getCond(stmt); + const true_expr = ZigClangConditionalOperator_getTrueExpr(stmt); + const false_expr = ZigClangConditionalOperator_getFalseExpr(stmt); + + if_node.condition = try transBoolExpr(rp, &cond_scope.base, cond_expr, .used, .r_value, false); + _ = try appendToken(rp.c, .RParen, ")"); + + if_node.body = try transExpr(rp, scope, true_expr, .used, .r_value); + + if_node.@"else" = try transCreateNodeElse(rp.c); + if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value); + + if (gropued) { + const rparen = try appendToken(rp.c, .RParen, ")"); + const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); + grouped_expr.* = .{ + .lparen = lparen, + .expr = &if_node.base, + .rparen = rparen, + }; + return maybeSuppressResult(rp, scope, used, &grouped_expr.base); + } else { + return maybeSuppressResult(rp, scope, used, &if_node.base); + } +} + fn maybeSuppressResult( rp: RestorePoint, scope: *Scope, diff --git a/test/translate_c.zig b/test/translate_c.zig index 02ba62a471..c4fb63799c 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -837,6 +837,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub export var d: f64 = @intToFloat(f64, 3); }); + cases.add_2("conditional operator", + \\int bar(void) { + \\ if (2 ? 5 : 5 ? 4 : 6) 2; + \\ return 2 ? 5 : 5 ? 4 : 6; + \\} + , &[_][]const u8{ + \\pub export fn bar() c_int { + \\ if ((if (2 != 0) 5 else (if (5 != 0) 4 else 6)) != 0) _ = 2; + \\ return if (2 != 0) 5 else if (5 != 0) 4 else 6; + \\} + }); + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// if (builtin.os != builtin.Os.windows) {