| author | |
| committer | |
| log | 44bd0a267096b54ac4dd40af31138bab1919e4d7 |
| tree | 1f21c21caf7648df1c23e27c53bf0fc54e36f7e8 |
| parent | 65ef74e2cdc87888d16ad207371cfd3ff8c0dce1 |
| parent | 8c15cfe3dabe736754b138f16de905e6487bd8b5 |
| signature |
Adds std.meta.cast and uses it to simplify translate-c3 files changed, 103 insertions(+), 159 deletions(-)
lib/std/meta.zig+82| ... | @@ -693,3 +693,85 @@ pub fn Vector(comptime len: u32, comptime child: type) type { | ... | @@ -693,3 +693,85 @@ pub fn Vector(comptime len: u32, comptime child: type) type { |
| 693 | }, | 693 | }, |
| 694 | }); | 694 | }); |
| 695 | } | 695 | } |
| 696 | |||
| 697 | /// Given a type and value, cast the value to the type as c would. | ||
| 698 | /// This is for translate-c and is not intended for general use. | ||
| 699 | pub fn cast(comptime DestType: type, target: var) DestType { | ||
| 700 | const TargetType = @TypeOf(target); | ||
| 701 | switch (@typeInfo(DestType)) { | ||
| 702 | .Pointer => { | ||
| 703 | switch (@typeInfo(TargetType)) { | ||
| 704 | .Int, .ComptimeInt => { | ||
| 705 | return @intToPtr(DestType, target); | ||
| 706 | }, | ||
| 707 | .Pointer => |ptr| { | ||
| 708 | return @ptrCast(DestType, @alignCast(ptr.alignment, target)); | ||
| 709 | }, | ||
| 710 | .Optional => |opt| { | ||
| 711 | if (@typeInfo(opt.child) == .Pointer) { | ||
| 712 | return @ptrCast(DestType, @alignCast(@alignOf(opt.child.Child), target)); | ||
| 713 | } | ||
| 714 | }, | ||
| 715 | else => {}, | ||
| 716 | } | ||
| 717 | }, | ||
| 718 | .Optional => |opt| { | ||
| 719 | if (@typeInfo(opt.child) == .Pointer) { | ||
| 720 | switch (@typeInfo(TargetType)) { | ||
| 721 | .Int, .ComptimeInt => { | ||
| 722 | return @intToPtr(DestType, target); | ||
| 723 | }, | ||
| 724 | .Pointer => |ptr| { | ||
| 725 | return @ptrCast(DestType, @alignCast(ptr.alignment, target)); | ||
| 726 | }, | ||
| 727 | .Optional => |target_opt| { | ||
| 728 | if (@typeInfo(target_opt.child) == .Pointer) { | ||
| 729 | return @ptrCast(DestType, @alignCast(@alignOf(target_opt.child.Child), target)); | ||
| 730 | } | ||
| 731 | }, | ||
| 732 | else => {}, | ||
| 733 | } | ||
| 734 | } | ||
| 735 | }, | ||
| 736 | .Enum, .EnumLiteral => { | ||
| 737 | if (@typeInfo(TargetType) == .Int or @typeInfo(TargetType) == .ComptimeInt) { | ||
| 738 | return @intToEnum(DestType, target); | ||
| 739 | } | ||
| 740 | }, | ||
| 741 | .Int, .ComptimeInt => { | ||
| 742 | switch (@typeInfo(TargetType)) { | ||
| 743 | .Pointer => { | ||
| 744 | return @as(DestType, @ptrToInt(target)); | ||
| 745 | }, | ||
| 746 | .Optional => |opt| { | ||
| 747 | if (@typeInfo(opt.child) == .Pointer) { | ||
| 748 | return @as(DestType, @ptrToInt(target)); | ||
| 749 | } | ||
| 750 | }, | ||
| 751 | .Enum, .EnumLiteral => { | ||
| 752 | return @as(DestType, @enumToInt(target)); | ||
| 753 | }, | ||
| 754 | else => {}, | ||
| 755 | } | ||
| 756 | }, | ||
| 757 | else => {}, | ||
| 758 | } | ||
| 759 | return @as(DestType, target); | ||
| 760 | } | ||
| 761 | |||
| 762 | test "std.meta.cast" { | ||
| 763 | const E = enum(u2) { | ||
| 764 | Zero, | ||
| 765 | One, | ||
| 766 | Two, | ||
| 767 | }; | ||
| 768 | |||
| 769 | var i = @as(i64, 10); | ||
| 770 | |||
| 771 | testing.expect(cast(?*c_void, 0) == @intToPtr(?*c_void, 0)); | ||
| 772 | testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16)); | ||
| 773 | testing.expect(cast(u64, @as(u32, 10)) == @as(u64, 10)); | ||
| 774 | testing.expect(cast(E, 1) == .One); | ||
| 775 | testing.expect(cast(u8, E.Two) == 2); | ||
| 776 | testing.expect(cast(*u64, &i).* == @as(u64, 10)); | ||
| 777 | } |
src-self-hosted/translate_c.zig+13-151| ... | @@ -5668,161 +5668,23 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -5668,161 +5668,23 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5668 | 5668 | ||
| 5669 | const lparen = try appendToken(c, .LParen, "("); | 5669 | const lparen = try appendToken(c, .LParen, "("); |
| 5670 | 5670 | ||
| 5671 | if (saw_integer_literal) { | 5671 | //(@import("std").meta.cast(dest, x)) |
| 5672 | //( if (@typeInfo(dest) == .Pointer)) | 5672 | const import_fn_call = try c.createBuiltinCall("@import", 1); |
| 5673 | // @intToPtr(dest, x) | 5673 | const std_node = try transCreateNodeStringLiteral(c, "\"std\""); |
| 5674 | //else | 5674 | import_fn_call.params()[0] = std_node; |
| 5675 | // @as(dest, x) ) | 5675 | import_fn_call.rparen_token = try appendToken(c, .RParen, ")"); |
| 5676 | const if_node = try transCreateNodeIf(c); | 5676 | const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta"); |
| 5677 | const type_info_node = try c.createBuiltinCall("@typeInfo", 1); | 5677 | const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "cast"); |
| 5678 | type_info_node.params()[0] = inner_node; | 5678 | |
| 5679 | type_info_node.rparen_token = try appendToken(c, .LParen, ")"); | 5679 | const cast_fn_call = try c.createCall(outer_field_access, 2); |
| 5680 | const cmp_node = try c.arena.create(ast.Node.InfixOp); | 5680 | cast_fn_call.params()[0] = inner_node; |
| 5681 | cmp_node.* = .{ | 5681 | cast_fn_call.params()[1] = node_to_cast; |
| 5682 | .op_token = try appendToken(c, .EqualEqual, "=="), | 5682 | cast_fn_call.rtoken = try appendToken(c, .RParen, ")"); |
| 5683 | .lhs = &type_info_node.base, | ||
| 5684 | .op = .EqualEqual, | ||
| 5685 | .rhs = try transCreateNodeEnumLiteral(c, "Pointer"), | ||
| 5686 | }; | ||
| 5687 | if_node.condition = &cmp_node.base; | ||
| 5688 | _ = try appendToken(c, .RParen, ")"); | ||
| 5689 | |||
| 5690 | const int_to_ptr = try c.createBuiltinCall("@intToPtr", 2); | ||
| 5691 | int_to_ptr.params()[0] = inner_node; | ||
| 5692 | int_to_ptr.params()[1] = node_to_cast; | ||
| 5693 | int_to_ptr.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5694 | if_node.body = &int_to_ptr.base; | ||
| 5695 | |||
| 5696 | const else_node = try transCreateNodeElse(c); | ||
| 5697 | if_node.@"else" = else_node; | ||
| 5698 | |||
| 5699 | const as_node = try c.createBuiltinCall("@as", 2); | ||
| 5700 | as_node.params()[0] = inner_node; | ||
| 5701 | as_node.params()[1] = node_to_cast; | ||
| 5702 | as_node.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5703 | else_node.body = &as_node.base; | ||
| 5704 | |||
| 5705 | const group_node = try c.arena.create(ast.Node.GroupedExpression); | ||
| 5706 | group_node.* = .{ | ||
| 5707 | .lparen = lparen, | ||
| 5708 | .expr = &if_node.base, | ||
| 5709 | .rparen = try appendToken(c, .RParen, ")"), | ||
| 5710 | }; | ||
| 5711 | return &group_node.base; | ||
| 5712 | } | ||
| 5713 | |||
| 5714 | //( if (@typeInfo(@TypeOf(x)) == .Pointer) | ||
| 5715 | // @ptrCast(dest, @alignCast(@alignOf(dest.Child), x)) | ||
| 5716 | //else if (@typeInfo(@TypeOf(x)) == .Int and @typeInfo(dest) == .Pointer)) | ||
| 5717 | // @intToPtr(dest, x) | ||
| 5718 | //else | ||
| 5719 | // @as(dest, x) ) | ||
| 5720 | |||
| 5721 | const if_1 = try transCreateNodeIf(c); | ||
| 5722 | const type_info_1 = try c.createBuiltinCall("@typeInfo", 1); | ||
| 5723 | const type_of_1 = try c.createBuiltinCall("@TypeOf", 1); | ||
| 5724 | type_info_1.params()[0] = &type_of_1.base; | ||
| 5725 | type_of_1.params()[0] = node_to_cast; | ||
| 5726 | type_of_1.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5727 | type_info_1.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5728 | |||
| 5729 | const cmp_1 = try c.arena.create(ast.Node.InfixOp); | ||
| 5730 | cmp_1.* = .{ | ||
| 5731 | .op_token = try appendToken(c, .EqualEqual, "=="), | ||
| 5732 | .lhs = &type_info_1.base, | ||
| 5733 | .op = .EqualEqual, | ||
| 5734 | .rhs = try transCreateNodeEnumLiteral(c, "Pointer"), | ||
| 5735 | }; | ||
| 5736 | if_1.condition = &cmp_1.base; | ||
| 5737 | _ = try appendToken(c, .RParen, ")"); | ||
| 5738 | |||
| 5739 | const period_tok = try appendToken(c, .Period, "."); | ||
| 5740 | const child_ident = try transCreateNodeIdentifier(c, "Child"); | ||
| 5741 | const inner_node_child = try c.arena.create(ast.Node.InfixOp); | ||
| 5742 | inner_node_child.* = .{ | ||
| 5743 | .op_token = period_tok, | ||
| 5744 | .lhs = inner_node, | ||
| 5745 | .op = .Period, | ||
| 5746 | .rhs = child_ident, | ||
| 5747 | }; | ||
| 5748 | |||
| 5749 | const align_of = try c.createBuiltinCall("@alignOf", 1); | ||
| 5750 | align_of.params()[0] = &inner_node_child.base; | ||
| 5751 | align_of.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5752 | // hack to get zig fmt to render a comma in builtin calls | ||
| 5753 | _ = try appendToken(c, .Comma, ","); | ||
| 5754 | |||
| 5755 | const align_cast = try c.createBuiltinCall("@alignCast", 2); | ||
| 5756 | align_cast.params()[0] = &align_of.base; | ||
| 5757 | align_cast.params()[1] = node_to_cast; | ||
| 5758 | align_cast.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5759 | |||
| 5760 | const ptr_cast = try c.createBuiltinCall("@ptrCast", 2); | ||
| 5761 | ptr_cast.params()[0] = inner_node; | ||
| 5762 | ptr_cast.params()[1] = &align_cast.base; | ||
| 5763 | ptr_cast.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5764 | if_1.body = &ptr_cast.base; | ||
| 5765 | |||
| 5766 | const else_1 = try transCreateNodeElse(c); | ||
| 5767 | if_1.@"else" = else_1; | ||
| 5768 | |||
| 5769 | const if_2 = try transCreateNodeIf(c); | ||
| 5770 | const type_info_2 = try c.createBuiltinCall("@typeInfo", 1); | ||
| 5771 | const type_of_2 = try c.createBuiltinCall("@TypeOf", 1); | ||
| 5772 | type_info_2.params()[0] = &type_of_2.base; | ||
| 5773 | type_of_2.params()[0] = node_to_cast; | ||
| 5774 | type_of_2.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5775 | type_info_2.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5776 | |||
| 5777 | const cmp_2 = try c.arena.create(ast.Node.InfixOp); | ||
| 5778 | cmp_2.* = .{ | ||
| 5779 | .op_token = try appendToken(c, .EqualEqual, "=="), | ||
| 5780 | .lhs = &type_info_2.base, | ||
| 5781 | .op = .EqualEqual, | ||
| 5782 | .rhs = try transCreateNodeEnumLiteral(c, "Int"), | ||
| 5783 | }; | ||
| 5784 | if_2.condition = &cmp_2.base; | ||
| 5785 | const cmp_4 = try c.arena.create(ast.Node.InfixOp); | ||
| 5786 | cmp_4.* = .{ | ||
| 5787 | .op_token = try appendToken(c, .Keyword_and, "and"), | ||
| 5788 | .lhs = &cmp_2.base, | ||
| 5789 | .op = .BoolAnd, | ||
| 5790 | .rhs = undefined, | ||
| 5791 | }; | ||
| 5792 | const type_info_3 = try c.createBuiltinCall("@typeInfo", 1); | ||
| 5793 | type_info_3.params()[0] = inner_node; | ||
| 5794 | type_info_3.rparen_token = try appendToken(c, .LParen, ")"); | ||
| 5795 | const cmp_3 = try c.arena.create(ast.Node.InfixOp); | ||
| 5796 | cmp_3.* = .{ | ||
| 5797 | .op_token = try appendToken(c, .EqualEqual, "=="), | ||
| 5798 | .lhs = &type_info_3.base, | ||
| 5799 | .op = .EqualEqual, | ||
| 5800 | .rhs = try transCreateNodeEnumLiteral(c, "Pointer"), | ||
| 5801 | }; | ||
| 5802 | cmp_4.rhs = &cmp_3.base; | ||
| 5803 | if_2.condition = &cmp_4.base; | ||
| 5804 | else_1.body = &if_2.base; | ||
| 5805 | _ = try appendToken(c, .RParen, ")"); | ||
| 5806 | |||
| 5807 | const int_to_ptr = try c.createBuiltinCall("@intToPtr", 2); | ||
| 5808 | int_to_ptr.params()[0] = inner_node; | ||
| 5809 | int_to_ptr.params()[1] = node_to_cast; | ||
| 5810 | int_to_ptr.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5811 | if_2.body = &int_to_ptr.base; | ||
| 5812 | |||
| 5813 | const else_2 = try transCreateNodeElse(c); | ||
| 5814 | if_2.@"else" = else_2; | ||
| 5815 | |||
| 5816 | const as = try c.createBuiltinCall("@as", 2); | ||
| 5817 | as.params()[0] = inner_node; | ||
| 5818 | as.params()[1] = node_to_cast; | ||
| 5819 | as.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 5820 | else_2.body = &as.base; | ||
| 5821 | 5683 | ||
| 5822 | const group_node = try c.arena.create(ast.Node.GroupedExpression); | 5684 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| 5823 | group_node.* = .{ | 5685 | group_node.* = .{ |
| 5824 | .lparen = lparen, | 5686 | .lparen = lparen, |
| 5825 | .expr = &if_1.base, | 5687 | .expr = &cast_fn_call.base, |
| 5826 | .rparen = try appendToken(c, .RParen, ")"), | 5688 | .rparen = try appendToken(c, .RParen, ")"), |
| 5827 | }; | 5689 | }; |
| 5828 | return &group_node.base; | 5690 | return &group_node.base; |
test/translate_c.zig+8-8| ... | @@ -1473,7 +1473,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1473,7 +1473,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1473 | cases.add("macro pointer cast", | 1473 | cases.add("macro pointer cast", |
| 1474 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) | 1474 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) |
| 1475 | , &[_][]const u8{ | 1475 | , &[_][]const u8{ |
| 1476 | \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, @alignCast(@alignOf([*c]NRF_GPIO_Type.Child), NRF_GPIO_BASE)) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int and @typeInfo([*c]NRF_GPIO_Type) == .Pointer) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE)); | 1476 | \\pub const NRF_GPIO = (@import("std").meta.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE)); |
| 1477 | }); | 1477 | }); |
| 1478 | 1478 | ||
| 1479 | cases.add("basic macro function", | 1479 | cases.add("basic macro function", |
| ... | @@ -2683,11 +2683,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -2683,11 +2683,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2683 | \\#define FOO(bar) baz((void *)(baz)) | 2683 | \\#define FOO(bar) baz((void *)(baz)) |
| 2684 | \\#define BAR (void*) a | 2684 | \\#define BAR (void*) a |
| 2685 | , &[_][]const u8{ | 2685 | , &[_][]const u8{ |
| 2686 | \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(?*c_void, @alignCast(@alignOf(?*c_void.Child), baz)) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, baz) else @as(?*c_void, baz)))) { | 2686 | \\pub inline fn FOO(bar: var) @TypeOf(baz((@import("std").meta.cast(?*c_void, baz)))) { |
| 2687 | \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(?*c_void, @alignCast(@alignOf(?*c_void.Child), baz)) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, baz) else @as(?*c_void, baz))); | 2687 | \\ return baz((@import("std").meta.cast(?*c_void, baz))); |
| 2688 | \\} | 2688 | \\} |
| 2689 | , | 2689 | , |
| 2690 | \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(?*c_void, @alignCast(@alignOf(?*c_void.Child), a)) else if (@typeInfo(@TypeOf(a)) == .Int and @typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, a) else @as(?*c_void, a)); | 2690 | \\pub const BAR = (@import("std").meta.cast(?*c_void, a)); |
| 2691 | }); | 2691 | }); |
| 2692 | 2692 | ||
| 2693 | cases.add("macro conditional operator", | 2693 | cases.add("macro conditional operator", |
| ... | @@ -2905,8 +2905,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -2905,8 +2905,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2905 | \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) | 2905 | \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) |
| 2906 | \\ | 2906 | \\ |
| 2907 | , &[_][]const u8{ | 2907 | , &[_][]const u8{ |
| 2908 | \\pub inline fn DefaultScreen(dpy: var) @TypeOf((if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int and @typeInfo(_XPrivDisplay) == .Pointer) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen) { | 2908 | \\pub inline fn DefaultScreen(dpy: var) @TypeOf((@import("std").meta.cast(_XPrivDisplay, dpy)).*.default_screen) { |
| 2909 | \\ return (if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int and @typeInfo(_XPrivDisplay) == .Pointer) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen; | 2909 | \\ return (@import("std").meta.cast(_XPrivDisplay, dpy)).*.default_screen; |
| 2910 | \\} | 2910 | \\} |
| 2911 | }); | 2911 | }); |
| 2912 | 2912 | ||
| ... | @@ -2914,9 +2914,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -2914,9 +2914,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2914 | \\#define NULL ((void*)0) | 2914 | \\#define NULL ((void*)0) |
| 2915 | \\#define FOO ((int)0x8000) | 2915 | \\#define FOO ((int)0x8000) |
| 2916 | , &[_][]const u8{ | 2916 | , &[_][]const u8{ |
| 2917 | \\pub const NULL = (if (@typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, 0) else @as(?*c_void, 0)); | 2917 | \\pub const NULL = (@import("std").meta.cast(?*c_void, 0)); |
| 2918 | , | 2918 | , |
| 2919 | \\pub const FOO = (if (@typeInfo(c_int) == .Pointer) @intToPtr(c_int, 0x8000) else @as(c_int, 0x8000)); | 2919 | \\pub const FOO = (@import("std").meta.cast(c_int, 0x8000)); |
| 2920 | }); | 2920 | }); |
| 2921 | 2921 | ||
| 2922 | if (std.Target.current.abi == .msvc) { | 2922 | if (std.Target.current.abi == .msvc) { |