authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 13:30:34+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 13:32:19+02:00
log62bfff5e8774413856d0c548f0fd73a4b5134f7f
tree0283bf0ea4ea0d679125327ecdfaef532d7b8061
parentf54e7d6c99b6fbeedcaf91e643e4e3a02e8f1d81
signature Commit is signed but in an unrecognized format.

translate-c-2 fix expression grouping bugs


3 files changed, 88 insertions(+), 66 deletions(-)

lib/std/zig/render.zig+1-1
...@@ -1629,7 +1629,7 @@ fn renderExpression(...@@ -1629,7 +1629,7 @@ fn renderExpression(
1629 .If => {1629 .If => {
1630 const if_node = @fieldParentPtr(ast.Node.If, "base", base);1630 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
16311631
1632 const lparen = tree.prevToken(if_node.condition.firstToken());1632 const lparen = tree.nextToken(if_node.if_token);
1633 const rparen = tree.nextToken(if_node.condition.lastToken());1633 const rparen = tree.nextToken(if_node.condition.lastToken());
16341634
1635 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if1635 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
src-self-hosted/translate_c.zig+35-26
...@@ -954,13 +954,6 @@ fn transBinaryOperator(...@@ -954,13 +954,6 @@ fn transBinaryOperator(
954 }954 }
955 const lhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);955 const lhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
956 switch (op) {956 switch (op) {
957 .PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
958 rp,
959 error.UnsupportedTranslation,
960 ZigClangBinaryOperator_getBeginLoc(stmt),
961 "TODO: handle more C binary operators: {}",
962 .{op},
963 ),
964 .Add => {957 .Add => {
965 if (cIsUnsignedInteger(qt)) {958 if (cIsUnsignedInteger(qt)) {
966 op_token = try appendToken(rp.c, .PlusPercent, "+%");959 op_token = try appendToken(rp.c, .PlusPercent, "+%");
...@@ -1205,6 +1198,26 @@ fn transBoolExpr(...@@ -1205,6 +1198,26 @@ fn transBoolExpr(
1205 undefined;1198 undefined;
1206 var res = try transExpr(rp, scope, expr, used, lrvalue);1199 var res = try transExpr(rp, scope, expr, used, lrvalue);
12071200
1201 if (isBoolRes(res))
1202 return res;
1203 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
1204 const node = try finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used);
1205
1206 if (grouped) {
1207 const rparen = try appendToken(rp.c, .RParen, ")");
1208 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
1209 grouped_expr.* = .{
1210 .lparen = lparen,
1211 .expr = node,
1212 .rparen = rparen,
1213 };
1214 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
1215 } else {
1216 return maybeSuppressResult(rp, scope, used, node);
1217 }
1218}
1219
1220fn isBoolRes(res: *ast.Node) bool {
1208 switch (res.id) {1221 switch (res.id) {
1209 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {1222 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
1210 .BoolOr,1223 .BoolOr,
...@@ -1215,23 +1228,20 @@ fn transBoolExpr(...@@ -1215,23 +1228,20 @@ fn transBoolExpr(
1215 .GreaterThan,1228 .GreaterThan,
1216 .LessOrEqual,1229 .LessOrEqual,
1217 .GreaterOrEqual,1230 .GreaterOrEqual,
1218 => return res,1231 => return true,
12191232
1220 else => {},1233 else => {},
1221 },1234 },
1222
1223 .PrefixOp => switch (@fieldParentPtr(ast.Node.PrefixOp, "base", res).op) {1235 .PrefixOp => switch (@fieldParentPtr(ast.Node.PrefixOp, "base", res).op) {
1224 .BoolNot => return res,1236 .BoolNot => return true,
12251237
1226 else => {},1238 else => {},
1227 },1239 },
12281240 .BoolLiteral => return true,
1229 .BoolLiteral => return res,1241 .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
1230
1231 else => {},1242 else => {},
1232 }1243 }
1233 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));1244 return false;
1234 return finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used, grouped);
1235}1245}
12361246
1237fn finishBoolExpr(1247fn finishBoolExpr(
...@@ -1241,14 +1251,13 @@ fn finishBoolExpr(...@@ -1241,14 +1251,13 @@ fn finishBoolExpr(
1241 ty: *const ZigClangType,1251 ty: *const ZigClangType,
1242 node: *ast.Node,1252 node: *ast.Node,
1243 used: ResultUsed,1253 used: ResultUsed,
1244 grouped: bool,
1245) TransError!*ast.Node {1254) TransError!*ast.Node {
1246 switch (ZigClangType_getTypeClass(ty)) {1255 switch (ZigClangType_getTypeClass(ty)) {
1247 .Builtin => {1256 .Builtin => {
1248 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);1257 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
12491258
1250 switch (ZigClangBuiltinType_getKind(builtin_ty)) {1259 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
1251 .Bool,1260 .Bool => return node,
1252 .Char_U,1261 .Char_U,
1253 .UChar,1262 .UChar,
1254 .Char_S,1263 .Char_S,
...@@ -1276,12 +1285,12 @@ fn finishBoolExpr(...@@ -1276,12 +1285,12 @@ fn finishBoolExpr(
1276 => {1285 => {
1277 const op_token = try appendToken(rp.c, .BangEqual, "!=");1286 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1278 const rhs_node = try transCreateNodeInt(rp.c, 0);1287 const rhs_node = try transCreateNodeInt(rp.c, 0);
1279 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);1288 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1280 },1289 },
1281 .NullPtr => {1290 .NullPtr => {
1282 const op_token = try appendToken(rp.c, .EqualEqual, "==");1291 const op_token = try appendToken(rp.c, .EqualEqual, "==");
1283 const rhs_node = try transCreateNodeNullLiteral(rp.c);1292 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1284 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, grouped);1293 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, false);
1285 },1294 },
1286 else => {},1295 else => {},
1287 }1296 }
...@@ -1289,13 +1298,13 @@ fn finishBoolExpr(...@@ -1289,13 +1298,13 @@ fn finishBoolExpr(
1289 .Pointer => {1298 .Pointer => {
1290 const op_token = try appendToken(rp.c, .BangEqual, "!=");1299 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1291 const rhs_node = try transCreateNodeNullLiteral(rp.c);1300 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1292 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);1301 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1293 },1302 },
1294 .Typedef => {1303 .Typedef => {
1295 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);1304 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
1296 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);1305 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1297 const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);1306 const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
1298 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used, grouped);1307 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used);
1299 },1308 },
1300 .Enum => {1309 .Enum => {
1301 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);1310 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
...@@ -1305,12 +1314,12 @@ fn finishBoolExpr(...@@ -1305,12 +1314,12 @@ fn finishBoolExpr(
13051314
1306 const op_token = try appendToken(rp.c, .BangEqual, "!=");1315 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1307 const rhs_node = try transCreateNodeInt(rp.c, 0);1316 const rhs_node = try transCreateNodeInt(rp.c, 0);
1308 return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, grouped);1317 return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, false);
1309 },1318 },
1310 .Elaborated => {1319 .Elaborated => {
1311 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);1320 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1312 const named_type = ZigClangElaboratedType_getNamedType(elaborated_ty);1321 const named_type = ZigClangElaboratedType_getNamedType(elaborated_ty);
1313 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used, grouped);1322 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used);
1314 },1323 },
1315 else => {},1324 else => {},
1316 }1325 }
...@@ -2009,8 +2018,8 @@ fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangFl...@@ -2009,8 +2018,8 @@ fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangFl
2009}2018}
20102019
2011fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangConditionalOperator, used: ResultUsed) TransError!*ast.Node {2020fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangConditionalOperator, used: ResultUsed) TransError!*ast.Node {
2012 const gropued = scope.id == .Condition;2021 const grouped = scope.id == .Condition;
2013 const lparen = if (gropued) try appendToken(rp.c, .LParen, "(") else undefined;2022 const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
2014 const if_node = try transCreateNodeIf(rp.c);2023 const if_node = try transCreateNodeIf(rp.c);
2015 var cond_scope = Scope{2024 var cond_scope = Scope{
2016 .parent = scope,2025 .parent = scope,
...@@ -2029,7 +2038,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla...@@ -2029,7 +2038,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla
2029 if_node.@"else" = try transCreateNodeElse(rp.c);2038 if_node.@"else" = try transCreateNodeElse(rp.c);
2030 if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value);2039 if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value);
20312040
2032 if (gropued) {2041 if (grouped) {
2033 const rparen = try appendToken(rp.c, .RParen, ")");2042 const rparen = try appendToken(rp.c, .RParen, ")");
2034 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);2043 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
2035 grouped_expr.* = .{2044 grouped_expr.* = .{
test/translate_c.zig+52-39
...@@ -1400,17 +1400,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1400,17 +1400,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1400 \\pub const Bar = enum_Bar;1400 \\pub const Bar = enum_Bar;
1401 });1401 });
14021402
1403 cases.add_2("bitwise binary operators, simpler parens", // TODO can combine with "bitwise binary operators" when parens are correctly preserved/not added in translate-c-21403 cases.add_2("bitwise binary operators, simpler parens",
1404 \\int max(int a, int b) {1404 \\int max(int a, int b) {
1405 \\ int c = (a & b);1405 \\ return (a & b) ^ (a | b);
1406 \\ int d = (a | b);
1407 \\ return (c ^ d);
1408 \\}1406 \\}
1409 , &[_][]const u8{1407 , &[_][]const u8{
1410 \\pub export fn max(a: c_int, b: c_int) c_int {1408 \\pub export fn max(a: c_int, b: c_int) c_int {
1411 \\ var c: c_int = (a & b);1409 \\ return ((a & b) ^ (a | b));
1412 \\ var d: c_int = (a | b);
1413 \\ return (c ^ d);
1414 \\}1410 \\}
1415 });1411 });
14161412
...@@ -1438,17 +1434,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1438,17 +1434,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1438 \\}1434 \\}
1439 });1435 });
14401436
1441 cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both1437 cases.add_2("==, !=",
1442 \\int max(int a, int b) {1438 \\int max(int a, int b) {
1443 \\ int c = (a == b);1439 \\ if (a == b)
1444 \\ int d = (a != b);1440 \\ return a;
1445 \\ return (c != d);1441 \\ if (a != b)
1442 \\ return b;
1443 \\ return a;
1446 \\}1444 \\}
1447 , &[_][]const u8{1445 , &[_][]const u8{
1448 \\pub export fn max(a: c_int, b: c_int) c_int {1446 \\pub export fn max(a: c_int, b: c_int) c_int {
1449 \\ var c: c_int = (a == b);1447 \\ if ((a == b)) return a;
1450 \\ var d: c_int = (a != b);1448 \\ if ((a != b)) return b;
1451 \\ return (c != d);1449 \\ return a;
1452 \\}1450 \\}
1453 });1451 });
14541452
...@@ -1464,6 +1462,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1464,6 +1462,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1464 \\}1462 \\}
1465 });1463 });
14661464
1465 cases.add_2("typedeffed bool expression",
1466 \\typedef char* yes;
1467 \\void foo(void) {
1468 \\ yes a;
1469 \\ if (a) 2;
1470 \\}
1471 , &[_][]const u8{
1472 \\pub const yes = [*c]u8;
1473 \\pub export fn foo() void {
1474 \\ var a: yes = undefined;
1475 \\ if (a != null) _ = 2;
1476 \\}
1477 });
1478
1467 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////1479 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
14681480
1469 cases.addAllowWarnings("simple data types",1481 cases.addAllowWarnings("simple data types",
...@@ -1575,31 +1587,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1575,31 +1587,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1575 \\}1587 \\}
1576 });1588 });
15771589
1578 cases.addC("==, !=",
1579 \\int max(int a, int b) {
1580 \\ if (a == b)
1581 \\ return a;
1582 \\ if (a != b)
1583 \\ return b;
1584 \\ return a;
1585 \\}
1586 , &[_][]const u8{
1587 \\pub export fn max(a: c_int, b: c_int) c_int {
1588 \\ if (a == b) return a;
1589 \\ if (a != b) return b;
1590 \\ return a;
1591 \\}
1592 });
1593 cases.addC("bitwise binary operators",
1594 \\int max(int a, int b) {
1595 \\ return (a & b) ^ (a | b);
1596 \\}
1597 , &[_][]const u8{
1598 \\pub export fn max(a: c_int, b: c_int) c_int {
1599 \\ return (a & b) ^ (a | b);
1600 \\}
1601 });
1602
1603 cases.addC("logical and, logical or",1590 cases.addC("logical and, logical or",
1604 \\int max(int a, int b) {1591 \\int max(int a, int b) {
1605 \\ if (a < b || a == b)1592 \\ if (a < b || a == b)
...@@ -2596,4 +2583,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2596,4 +2583,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2596 \\ }2583 \\ }
2597 \\}2584 \\}
2598 });2585 });
2586
2587 cases.addC("==, !=",
2588 \\int max(int a, int b) {
2589 \\ if (a == b)
2590 \\ return a;
2591 \\ if (a != b)
2592 \\ return b;
2593 \\ return a;
2594 \\}
2595 , &[_][]const u8{
2596 \\pub export fn max(a: c_int, b: c_int) c_int {
2597 \\ if (a == b) return a;
2598 \\ if (a != b) return b;
2599 \\ return a;
2600 \\}
2601 });
2602
2603 cases.addC("bitwise binary operators",
2604 \\int max(int a, int b) {
2605 \\ return (a & b) ^ (a | b);
2606 \\}
2607 , &[_][]const u8{
2608 \\pub export fn max(a: c_int, b: c_int) c_int {
2609 \\ return (a & b) ^ (a | b);
2610 \\}
2611 });
2599}2612}