authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 17:19:28+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 17:19:28+02:00
log65531c73a909386824697bb16025c363684a3a66
tree3dfce30f21e47fa44b81be8c9471f94ae8b465c4
parent0283ab8a1a27c9d3a7a6d88960418485a7125d1d
signature Commit is signed but in an unrecognized format.

translate-c-2 switch


3 files changed, 321 insertions(+), 50 deletions(-)

src-self-hosted/clang.zig+15
...@@ -77,6 +77,7 @@ pub const struct_ZigClangPredefinedExpr = @OpaqueType();...@@ -77,6 +77,7 @@ pub const struct_ZigClangPredefinedExpr = @OpaqueType();
77pub const struct_ZigClangInitListExpr = @OpaqueType();77pub const struct_ZigClangInitListExpr = @OpaqueType();
78pub const ZigClangPreprocessingRecord = @OpaqueType();78pub const ZigClangPreprocessingRecord = @OpaqueType();
79pub const ZigClangFloatingLiteral = @OpaqueType();79pub const ZigClangFloatingLiteral = @OpaqueType();
80pub const ZigClangConstantExpr = @OpaqueType();
8081
81pub const ZigClangBO = extern enum {82pub const ZigClangBO = extern enum {
82 PtrMemD,83 PtrMemD,
...@@ -1059,3 +1060,17 @@ pub extern fn ZigClangAPFloat_getValueAsApproximateDouble(*const ZigClangFloatin...@@ -1059,3 +1060,17 @@ pub extern fn ZigClangAPFloat_getValueAsApproximateDouble(*const ZigClangFloatin
1059pub extern fn ZigClangConditionalOperator_getCond(*const ZigClangConditionalOperator) *const ZigClangExpr;1060pub extern fn ZigClangConditionalOperator_getCond(*const ZigClangConditionalOperator) *const ZigClangExpr;
1060pub extern fn ZigClangConditionalOperator_getTrueExpr(*const ZigClangConditionalOperator) *const ZigClangExpr;1061pub extern fn ZigClangConditionalOperator_getTrueExpr(*const ZigClangConditionalOperator) *const ZigClangExpr;
1061pub extern fn ZigClangConditionalOperator_getFalseExpr(*const ZigClangConditionalOperator) *const ZigClangExpr;1062pub extern fn ZigClangConditionalOperator_getFalseExpr(*const ZigClangConditionalOperator) *const ZigClangExpr;
1063
1064pub extern fn ZigClangSwitchStmt_getConditionVariableDeclStmt(*const ZigClangSwitchStmt) ?*const ZigClangDeclStmt;
1065pub extern fn ZigClangSwitchStmt_getCond(*const ZigClangSwitchStmt) *const ZigClangExpr;
1066pub extern fn ZigClangSwitchStmt_getBody(*const ZigClangSwitchStmt) *const ZigClangStmt;
1067pub extern fn ZigClangSwitchStmt_isAllEnumCasesCovered(*const ZigClangSwitchStmt) bool;
1068
1069pub extern fn ZigClangCaseStmt_getLHS(*const ZigClangCaseStmt) *const ZigClangExpr;
1070pub extern fn ZigClangCaseStmt_getRHS(*const ZigClangCaseStmt) ?*const ZigClangExpr;
1071pub extern fn ZigClangCaseStmt_getBeginLoc(*const ZigClangCaseStmt) ZigClangSourceLocation;
1072pub extern fn ZigClangCaseStmt_getSubStmt(*const ZigClangCaseStmt) *const ZigClangStmt;
1073
1074pub extern fn ZigClangDefaultStmt_getSubStmt(*const ZigClangDefaultStmt) *const ZigClangStmt;
1075
1076pub extern fn ZigClangExpr_EvaluateAsConstantExpr(*const ZigClangExpr, *ZigClangExprEvalResult, ZigClangExpr_ConstExprUsage, *const ZigClangASTContext) bool;
src-self-hosted/translate_c.zig+222-8
...@@ -54,7 +54,9 @@ const Scope = struct {...@@ -54,7 +54,9 @@ const Scope = struct {
5454
55 const Switch = struct {55 const Switch = struct {
56 base: Scope,56 base: Scope,
57 label: []const u8,57 pending_block: *ast.Node.Block,
58 cases: *ast.Node.Switch.CaseList,
59 has_default: bool = false,
58 };60 };
5961
60 /// used when getting a member `a.b`62 /// used when getting a member `a.b`
...@@ -189,8 +191,8 @@ const Scope = struct {...@@ -189,8 +191,8 @@ const Scope = struct {
189 .Ref => null,191 .Ref => null,
190 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),192 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
191 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),193 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
194 .Switch,
192 .Condition => scope.parent.?.getAlias(name),195 .Condition => scope.parent.?.getAlias(name),
193 else => @panic("TODO Scope.getAlias"),
194 };196 };
195 }197 }
196198
...@@ -200,15 +202,31 @@ const Scope = struct {...@@ -200,15 +202,31 @@ const Scope = struct {
200 .Root => @fieldParentPtr(Root, "base", scope).contains(name),202 .Root => @fieldParentPtr(Root, "base", scope).contains(name),
201 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),203 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
202 .Block => @fieldParentPtr(Block, "base", scope).contains(name),204 .Block => @fieldParentPtr(Block, "base", scope).contains(name),
205 .Switch,
203 .Condition => scope.parent.?.contains(name),206 .Condition => scope.parent.?.contains(name),
204 else => @panic("TODO Scope.contains"),
205 };207 };
206 }208 }
207209
208 fn getBreakableScope(inner: *Scope) *Scope {210 fn getBreakableScope(inner: *Scope) *Scope {
209 var scope = inner;211 var scope = inner;
210 while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {}212 while (true) {
211 return scope;213 switch (scope.id) {
214 .FnDef => unreachable,
215 .Switch => return scope,
216 else => scope = scope.parent.?,
217 }
218 }
219 }
220
221 fn getSwitch(inner: *Scope) *Scope.Switch {
222 var scope = inner;
223 while (true) {
224 switch (scope.id) {
225 .FnDef => unreachable,
226 .Switch => return @fieldParentPtr(Switch, "base", scope),
227 else => scope = scope.parent.?,
228 }
229 }
212 }230 }
213};231};
214232
...@@ -634,6 +652,10 @@ fn transStmt(...@@ -634,6 +652,10 @@ fn transStmt(
634 .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)),652 .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)),
635 .FloatingLiteralClass => return transFloatingLiteral(rp, scope, @ptrCast(*const ZigClangFloatingLiteral, stmt), result_used),653 .FloatingLiteralClass => return transFloatingLiteral(rp, scope, @ptrCast(*const ZigClangFloatingLiteral, stmt), result_used),
636 .ConditionalOperatorClass => return transConditionalOperator(rp, scope, @ptrCast(*const ZigClangConditionalOperator, stmt), result_used),654 .ConditionalOperatorClass => return transConditionalOperator(rp, scope, @ptrCast(*const ZigClangConditionalOperator, stmt), result_used),
655 .SwitchStmtClass => return transSwitch(rp, scope, @ptrCast(*const ZigClangSwitchStmt, stmt)),
656 .CaseStmtClass => return transCase(rp, scope, @ptrCast(*const ZigClangCaseStmt, stmt)),
657 .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const ZigClangDefaultStmt, stmt)),
658 .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
637 else => {659 else => {
638 return revertAndWarn(660 return revertAndWarn(
639 rp,661 rp,
...@@ -1374,6 +1396,154 @@ fn transForLoop(...@@ -1374,6 +1396,154 @@ fn transForLoop(
1374 return &while_node.base;1396 return &while_node.base;
1375}1397}
13761398
1399fn transSwitch(
1400 rp: RestorePoint,
1401 scope: *Scope,
1402 stmt: *const ZigClangSwitchStmt,
1403) TransError!*ast.Node {
1404 const switch_node = try transCreateNodeSwitch(rp.c);
1405 var switch_scope = Scope.Switch{
1406 .base = .{
1407 .id = .Switch,
1408 .parent = scope,
1409 },
1410 .cases = &switch_node.cases,
1411 .pending_block = undefined,
1412 };
1413
1414 var cond_scope = Scope.Condition{
1415 .base = .{
1416 .parent = scope,
1417 .id = .Condition,
1418 },
1419 };
1420 switch_node.expr = try transExpr(rp, &cond_scope.base, ZigClangSwitchStmt_getCond(stmt), .used, .r_value);
1421 _ = try appendToken(rp.c, .RParen, ")");
1422 _ = try appendToken(rp.c, .LBrace, "{");
1423 switch_node.rbrace = try appendToken(rp.c, .RBrace, "}");
1424
1425 const block_scope = try Scope.Block.init(rp.c, &switch_scope.base, null);
1426 // tmp block that all statements will go before being picked up by a case or default
1427 const block = try transCreateNodeBlock(rp.c, null);
1428 block_scope.block_node = block;
1429
1430 const switch_block = try transCreateNodeBlock(rp.c, null);
1431 try switch_block.statements.push(&switch_node.base);
1432 switch_scope.pending_block = switch_block;
1433
1434
1435 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);
1436 _ = try appendToken(rp.c, .Semicolon, ";");
1437
1438 // take all pending statements
1439 var it = last.cast(ast.Node.Block).?.statements.iterator(0);
1440 while (it.next()) |n| {
1441 try switch_scope.pending_block.statements.push(n.*);
1442 }
1443
1444 switch_scope.pending_block.label = try appendIdentifier(rp.c, "__switch");
1445 _ = try appendToken(rp.c, .Colon, ":");
1446 if (!switch_scope.has_default) {
1447 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
1448 else_prong.expr = &(try transCreateNodeBreak(rp.c, "__switch")).base;
1449 _ = try appendToken(rp.c, .Comma, ",");
1450 try switch_node.cases.push(&else_prong.base);
1451 }
1452 switch_scope.pending_block.rbrace = try appendToken(rp.c, .RBrace, "}");
1453 return &switch_scope.pending_block.base;
1454}
1455
1456
1457fn transCase(
1458 rp: RestorePoint,
1459 scope: *Scope,
1460 stmt: *const ZigClangCaseStmt,
1461) TransError!*ast.Node {
1462 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
1463 const switch_scope = scope.getSwitch();
1464 const label = try std.fmt.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
1465 _ = try appendToken(rp.c, .Semicolon, ";");
1466
1467 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
1468 const lhs_node = try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
1469 const ellips = try appendToken(rp.c, .Ellipsis3, "...");
1470 const rhs_node = try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
1471
1472 const node = try rp.c.a().create(ast.Node.InfixOp);
1473 node.* = .{
1474 .op_token = ellips,
1475 .lhs = lhs_node,
1476 .op = .Range,
1477 .rhs = rhs_node,
1478 };
1479 break :blk &node.base;
1480 } else
1481 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
1482
1483
1484 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);
1485 switch_prong.expr = &(try transCreateNodeBreak(rp.c, label)).base;
1486 _ = try appendToken(rp.c, .Comma, ",");
1487 try switch_scope.cases.push(&switch_prong.base);
1488
1489 const block = try transCreateNodeBlock(rp.c, null);
1490 switch_scope.pending_block.label = try appendIdentifier(rp.c, label);
1491 _ = try appendToken(rp.c, .Colon, ":");
1492 switch_scope.pending_block.rbrace = try appendToken(rp.c, .RBrace, "}");
1493 try block.statements.push(&switch_scope.pending_block.base);
1494
1495 // take all pending statements
1496 var it = block_scope.block_node.statements.iterator(0);
1497 while (it.next()) |n| {
1498 try switch_scope.pending_block.statements.push(n.*);
1499 }
1500 block_scope.block_node.statements.shrink(0);
1501
1502 switch_scope.pending_block = block;
1503
1504 return transStmt(rp, scope, ZigClangCaseStmt_getSubStmt(stmt), .unused, .r_value);
1505}
1506
1507fn transDefault(
1508 rp: RestorePoint,
1509 scope: *Scope,
1510 stmt: *const ZigClangDefaultStmt,
1511) TransError!*ast.Node {
1512 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
1513 const switch_scope = scope.getSwitch();
1514 const label = "__default";
1515 switch_scope.has_default = true;
1516 _ = try appendToken(rp.c, .Semicolon, ";");
1517
1518 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
1519 else_prong.expr = &(try transCreateNodeBreak(rp.c, label)).base;
1520 _ = try appendToken(rp.c, .Comma, ",");
1521 try switch_scope.cases.push(&else_prong.base);
1522
1523 const block = try transCreateNodeBlock(rp.c, null);
1524 switch_scope.pending_block.label = try appendIdentifier(rp.c, label);
1525 _ = try appendToken(rp.c, .Colon, ":");
1526 switch_scope.pending_block.rbrace = try appendToken(rp.c, .RBrace, "}");
1527 try block.statements.push(&switch_scope.pending_block.base);
1528
1529 // take all pending statements
1530 var it = block_scope.block_node.statements.iterator(0);
1531 while (it.next()) |n| {
1532 try switch_scope.pending_block.statements.push(n.*);
1533 }
1534 block_scope.block_node.statements.shrink(0);
1535
1536 switch_scope.pending_block = block;
1537 return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);
1538}
1539
1540fn transConstantExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangExpr, used: ResultUsed) TransError!*ast.Node {
1541 var result: ZigClangExprEvalResult = undefined;
1542 if (!ZigClangExpr_EvaluateAsConstantExpr(expr, &result, .EvaluateForCodeGen, rp.c.clang_context))
1543 return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangExpr_getBeginLoc(expr), "invalid constant expression", .{});
1544 return maybeSuppressResult(rp, scope, used, try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&result.Val)));
1545}
1546
1377fn transCPtrCast(1547fn transCPtrCast(
1378 rp: RestorePoint,1548 rp: RestorePoint,
1379 loc: ZigClangSourceLocation,1549 loc: ZigClangSourceLocation,
...@@ -1414,7 +1584,7 @@ fn transCPtrCast(...@@ -1414,7 +1584,7 @@ fn transCPtrCast(
1414fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {1584fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
1415 const break_scope = scope.getBreakableScope();1585 const break_scope = scope.getBreakableScope();
1416 const br = try transCreateNodeBreak(rp.c, if (break_scope.id == .Switch)1586 const br = try transCreateNodeBreak(rp.c, if (break_scope.id == .Switch)
1417 @fieldParentPtr(Scope.Switch, "base", break_scope).label1587 "__switch"
1418 else1588 else
1419 null);1589 null);
1420 return &br.base;1590 return &br.base;
...@@ -2339,6 +2509,42 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node {...@@ -2339,6 +2509,42 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node {
2339 return &node.base;2509 return &node.base;
2340}2510}
23412511
2512fn transCreateNodeSwitch(c: *Context) !*ast.Node.Switch {
2513 const switch_tok = try appendToken(c, .Keyword_switch, "switch");
2514 _ = try appendToken(c, .LParen, "(");
2515
2516 const node = try c.a().create(ast.Node.Switch);
2517 node.* = .{
2518 .switch_token = switch_tok,
2519 .expr = undefined,
2520 .cases = ast.Node.Switch.CaseList.init(c.a()),
2521 .rbrace = undefined,
2522 };
2523 return node;
2524}
2525
2526fn transCreateNodeSwitchCase(c: *Context, lhs: *ast.Node) !*ast.Node.SwitchCase {
2527 const arrow_tok = try appendToken(c, .EqualAngleBracketRight, "=>");
2528
2529 const node = try c.a().create(ast.Node.SwitchCase);
2530 node.* = .{
2531 .items = ast.Node.SwitchCase.ItemList.init(c.a()),
2532 .arrow_token = arrow_tok,
2533 .payload = null,
2534 .expr = undefined,
2535 };
2536 try node.items.push(lhs);
2537 return node;
2538}
2539
2540fn transCreateNodeSwitchElse(c: *Context) !*ast.Node {
2541 const node = try c.a().create(ast.Node.SwitchElse);
2542 node.* = .{
2543 .token = try appendToken(c, .Keyword_else, "else"),
2544 };
2545 return &node.base;
2546}
2547
2342const RestorePoint = struct {2548const RestorePoint = struct {
2343 c: *Context,2549 c: *Context,
2344 token_index: ast.TokenIndex,2550 token_index: ast.TokenIndex,
...@@ -2818,7 +3024,7 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,...@@ -2818,7 +3024,7 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,
28183024
2819// TODO hook up with codegen3025// TODO hook up with codegen
2820fn isZigPrimitiveType(name: []const u8) bool {3026fn isZigPrimitiveType(name: []const u8) bool {
2821 if (name.len > 1 and std.mem.startsWith(u8, name, "u") or std.mem.startsWith(u8, name, "u")) {3027 if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) {
2822 for (name[1..]) |c| {3028 for (name[1..]) |c| {
2823 switch (c) {3029 switch (c) {
2824 '0'...'9' => {},3030 '0'...'9' => {},
...@@ -2840,7 +3046,15 @@ fn isZigPrimitiveType(name: []const u8) bool {...@@ -2840,7 +3046,15 @@ fn isZigPrimitiveType(name: []const u8) bool {
2840 std.mem.eql(u8, name, "c_longdouble") or3046 std.mem.eql(u8, name, "c_longdouble") or
2841 std.mem.eql(u8, name, "noreturn") or3047 std.mem.eql(u8, name, "noreturn") or
2842 std.mem.eql(u8, name, "type") or3048 std.mem.eql(u8, name, "type") or
2843 std.mem.eql(u8, name, "anyerror");3049 std.mem.eql(u8, name, "anyerror") or
3050 std.mem.eql(u8, name, "c_short") or
3051 std.mem.eql(u8, name, "c_ushort") or
3052 std.mem.eql(u8, name, "c_int") or
3053 std.mem.eql(u8, name, "c_uint") or
3054 std.mem.eql(u8, name, "c_long") or
3055 std.mem.eql(u8, name, "c_ulong") or
3056 std.mem.eql(u8, name, "c_longlong") or
3057 std.mem.eql(u8, name, "c_ulonglong");
2844}3058}
28453059
2846fn isValidZigIdentifier(name: []const u8) bool {3060fn isValidZigIdentifier(name: []const u8) bool {
test/translate_c.zig+84-42
...@@ -849,6 +849,48 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -849,6 +849,48 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
849 \\}849 \\}
850 });850 });
851851
852 cases.add_2("switch on int",
853 \\int switch_fn(int i) {
854 \\ int res = 0;
855 \\ switch (i) {
856 \\ case 0:
857 \\ res = 1;
858 \\ case 1:
859 \\ res = 2;
860 \\ default:
861 \\ res = 3 * i;
862 \\ break;
863 \\ case 2:
864 \\ res = 5;
865 \\ }
866 \\}
867 , &[_][]const u8{
868 \\pub export fn switch_fn(i: c_int) c_int {
869 \\ var res: c_int = 0;
870 \\ __switch: {
871 \\ __case_2: {
872 \\ __default: {
873 \\ __case_1: {
874 \\ __case_0: {
875 \\ switch (i) {
876 \\ 0 => break :__case_0,
877 \\ 1 => break :__case_1,
878 \\ else => break :__default,
879 \\ 2 => break :__case_2,
880 \\ }
881 \\ }
882 \\ res = 1;
883 \\ }
884 \\ res = 2;
885 \\ }
886 \\ res = (3 * i);
887 \\ break :__switch;
888 \\ }
889 \\ res = 5;
890 \\ }
891 \\}
892 });
893
852 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////894 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
853895
854 if (builtin.os != builtin.Os.windows) {896 if (builtin.os != builtin.Os.windows) {
...@@ -1938,48 +1980,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1938,48 +1980,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1938 \\}1980 \\}
1939 });1981 });
19401982
1941 cases.add("switch on int",
1942 \\int switch_fn(int i) {
1943 \\ int res = 0;
1944 \\ switch (i) {
1945 \\ case 0:
1946 \\ res = 1;
1947 \\ case 1:
1948 \\ res = 2;
1949 \\ default:
1950 \\ res = 3 * i;
1951 \\ break;
1952 \\ case 2:
1953 \\ res = 5;
1954 \\ }
1955 \\}
1956 , &[_][]const u8{
1957 \\pub fn switch_fn(i: c_int) c_int {
1958 \\ var res: c_int = 0;
1959 \\ __switch: {
1960 \\ __case_2: {
1961 \\ __default: {
1962 \\ __case_1: {
1963 \\ __case_0: {
1964 \\ switch (i) {
1965 \\ 0 => break :__case_0,
1966 \\ 1 => break :__case_1,
1967 \\ else => break :__default,
1968 \\ 2 => break :__case_2,
1969 \\ }
1970 \\ }
1971 \\ res = 1;
1972 \\ }
1973 \\ res = 2;
1974 \\ }
1975 \\ res = (3 * i);
1976 \\ break :__switch;
1977 \\ }
1978 \\ res = 5;
1979 \\ }
1980 \\}
1981 });
1982
1983 cases.addC("implicit casts",1983 cases.addC("implicit casts",
1984 \\#include <stdbool.h>1984 \\#include <stdbool.h>
1985 \\1985 \\
...@@ -2237,4 +2237,46 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2237,4 +2237,46 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2237 , &[_][]const u8{2237 , &[_][]const u8{
2238 \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);2238 \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
2239 });2239 });
2240
2241 cases.add("switch on int",
2242 \\int switch_fn(int i) {
2243 \\ int res = 0;
2244 \\ switch (i) {
2245 \\ case 0:
2246 \\ res = 1;
2247 \\ case 1:
2248 \\ res = 2;
2249 \\ default:
2250 \\ res = 3 * i;
2251 \\ break;
2252 \\ case 2:
2253 \\ res = 5;
2254 \\ }
2255 \\}
2256 , &[_][]const u8{
2257 \\pub fn switch_fn(i: c_int) c_int {
2258 \\ var res: c_int = 0;
2259 \\ __switch: {
2260 \\ __case_2: {
2261 \\ __default: {
2262 \\ __case_1: {
2263 \\ __case_0: {
2264 \\ switch (i) {
2265 \\ 0 => break :__case_0,
2266 \\ 1 => break :__case_1,
2267 \\ else => break :__default,
2268 \\ 2 => break :__case_2,
2269 \\ }
2270 \\ }
2271 \\ res = 1;
2272 \\ }
2273 \\ res = 2;
2274 \\ }
2275 \\ res = (3 * i);
2276 \\ break :__switch;
2277 \\ }
2278 \\ res = 5;
2279 \\ }
2280 \\}
2281 });
2240}2282}