authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-15 21:32:30+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-15 21:32:30+02:00
loged2a19dcecf5470ae2529e0fc7f86bf89d532162
treec38c28b8cec7fe3168959381eedbad354dfc04fc
parent57170f9eb662f17f361ebf4cd19f86283a80b74f
signature Commit is signed but in an unrecognized format.

translate-c-2 macro cast


3 files changed, 169 insertions(+), 15 deletions(-)

src-self-hosted/c_tokenizer.zig+5
...@@ -25,6 +25,7 @@ pub const CToken = struct {...@@ -25,6 +25,7 @@ pub const CToken = struct {
25 Tilde,25 Tilde,
26 Shl,26 Shl,
27 Lt,27 Lt,
28 Comma,
28 };29 };
2930
30 pub const NumLitSuffix = enum {31 pub const NumLitSuffix = enum {
...@@ -191,6 +192,10 @@ fn next(chars: [*]const u8, i: *usize) !CToken {...@@ -191,6 +192,10 @@ fn next(chars: [*]const u8, i: *usize) !CToken {
191 result.id = .Tilde;192 result.id = .Tilde;
192 return result;193 return result;
193 },194 },
195 ',' => {
196 result.id = .Comma;
197 return result;
198 },
194 else => return error.TokenizingFailed,199 else => return error.TokenizingFailed,
195 }200 }
196 },201 },
src-self-hosted/translate_c.zig+158-15
...@@ -2039,7 +2039,7 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {...@@ -2039,7 +2039,7 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {
2039 _ = try appendToken(c, .Period, ".");2039 _ = try appendToken(c, .Period, ".");
2040 const qm = try appendToken(c, .QuestionMark, "?");2040 const qm = try appendToken(c, .QuestionMark, "?");
2041 const node = try c.a().create(ast.Node.SuffixOp);2041 const node = try c.a().create(ast.Node.SuffixOp);
2042 node.* = ast.Node.SuffixOp{2042 node.* = .{
2043 .op = .UnwrapOptional,2043 .op = .UnwrapOptional,
2044 .lhs = .{ .node = wrapped },2044 .lhs = .{ .node = wrapped },
2045 .rtoken = qm,2045 .rtoken = qm,
...@@ -2047,6 +2047,39 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {...@@ -2047,6 +2047,39 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {
2047 return &node.base;2047 return &node.base;
2048}2048}
20492049
2050fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node {
2051 const node = try c.a().create(ast.Node.EnumLiteral);
2052 node.* = .{
2053 .dot = try appendToken(c, .Period, "."),
2054 .name = try appendIdentifier(c, name),
2055 };
2056 return &node.base;
2057}
2058
2059fn transCreateNodeIf(c: *Context) !*ast.Node.If {
2060 const if_tok = try appendToken(c, .Keyword_if, "if");
2061 _ = try appendToken(c, .LParen, "(");
2062 const node = try c.a().create(ast.Node.If);
2063 node.* = .{
2064 .if_token = if_tok,
2065 .condition = undefined,
2066 .payload = null,
2067 .body = undefined,
2068 .@"else" = null,
2069 };
2070 return node;
2071}
2072
2073fn transCreateNodeElse(c: *Context) !*ast.Node.Else {
2074 const node = try c.a().create(ast.Node.Else);
2075 node.* = .{
2076 .else_token = try appendToken(c, .Keyword_else, "else"),
2077 .payload = null,
2078 .body = undefined,
2079 };
2080 return node;
2081}
2082
2050const RestorePoint = struct {2083const RestorePoint = struct {
2051 c: *Context,2084 c: *Context,
2052 token_index: ast.TokenIndex,2085 token_index: ast.TokenIndex,
...@@ -2722,26 +2755,102 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:...@@ -2722,26 +2755,102 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:
2722 };2755 };
2723 return &node.base;2756 return &node.base;
2724 },2757 },
2725 .Minus => {
2726 const node = try transCreateNodePrefixOp(
2727 rp.c,
2728 .Negation,
2729 .Minus,
2730 "-",
2731 );
2732 node.rhs = try parseCNumLit(rp, it.next().?, source_loc);
2733 return &node.base;
2734 },
2735 .NumLitInt, .NumLitFloat => {2758 .NumLitInt, .NumLitFloat => {
2736 return parseCNumLit(rp, tok, source_loc);2759 return parseCNumLit(rp, tok, source_loc);
2737 },2760 },
2738 .Identifier => return transCreateNodeIdentifier(rp.c, tok.bytes),2761 .Identifier => return transCreateNodeIdentifier(rp.c, tok.bytes),
2739 .LParen => {2762 .LParen => {
2740 _ = try appendToken(rp.c, .LParen, "(");
2741 const inner_node = try parseCExpr(rp, it, source_loc);2763 const inner_node = try parseCExpr(rp, it, source_loc);
2742 _ = try appendToken(rp.c, .RParen, ")");
27432764
2744 return inner_node; // TODO2765 // hack to get zig fmt to render a comma in builtin calls
2766 _ = try appendToken(rp.c, .Comma, ",");
2767
2768 if (it.peek().?.id == .RParen) {
2769 _ = it.next();
2770 return inner_node;
2771 }
2772
2773 const node_to_cast = try parseCExpr(rp, it, source_loc);
2774
2775 if (it.next().?.id != .RParen) {
2776 return revertAndWarn(
2777 rp,
2778 error.ParseError,
2779 source_loc,
2780 "unable to translate C expr",
2781 .{},
2782 );
2783 }
2784
2785 //if (@typeId(@TypeOf(x)) == .Pointer)
2786 // @ptrCast(dest, x)
2787 //else if (@typeId(@TypeOf(x)) == .Integer)
2788 // @intToPtr(dest, x)
2789 //else
2790 // @as(dest, x)
2791
2792 const if_1 = try transCreateNodeIf(rp.c);
2793 const type_id_1 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId");
2794 const type_of_1 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf");
2795 try type_id_1.params.push(&type_of_1.base);
2796 try type_of_1.params.push(node_to_cast);
2797 type_of_1.rparen_token = try appendToken(rp.c, .LParen, ")");
2798 type_id_1.rparen_token = try appendToken(rp.c, .LParen, ")");
2799
2800 const cmp_1 = try rp.c.a().create(ast.Node.InfixOp);
2801 cmp_1.* = .{
2802 .op_token = try appendToken(rp.c, .EqualEqual, "=="),
2803 .lhs = &type_id_1.base,
2804 .op = .EqualEqual,
2805 .rhs = try transCreateNodeEnumLiteral(rp.c, "Pointer"),
2806 };
2807 if_1.condition = &cmp_1.base;
2808 _ = try appendToken(rp.c, .LParen, ")");
2809
2810 const ptr_cast = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
2811 try ptr_cast.params.push(inner_node);
2812 try ptr_cast.params.push(node_to_cast);
2813 ptr_cast.rparen_token = try appendToken(rp.c, .LParen, ")");
2814 if_1.body = &ptr_cast.base;
2815
2816 const else_1 = try transCreateNodeElse(rp.c);
2817 if_1.@"else" = else_1;
2818
2819 const if_2 = try transCreateNodeIf(rp.c);
2820 const type_id_2 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId");
2821 const type_of_2 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf");
2822 try type_id_2.params.push(&type_of_2.base);
2823 try type_of_2.params.push(node_to_cast);
2824 type_of_2.rparen_token = try appendToken(rp.c, .LParen, ")");
2825 type_id_2.rparen_token = try appendToken(rp.c, .LParen, ")");
2826
2827 const cmp_2 = try rp.c.a().create(ast.Node.InfixOp);
2828 cmp_2.* = .{
2829 .op_token = try appendToken(rp.c, .EqualEqual, "=="),
2830 .lhs = &type_id_2.base,
2831 .op = .EqualEqual,
2832 .rhs = try transCreateNodeEnumLiteral(rp.c, "Int"),
2833 };
2834 if_2.condition = &cmp_2.base;
2835 else_1.body = &if_2.base;
2836 _ = try appendToken(rp.c, .LParen, ")");
2837
2838 const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
2839 try int_to_ptr.params.push(inner_node);
2840 try int_to_ptr.params.push(node_to_cast);
2841 int_to_ptr.rparen_token = try appendToken(rp.c, .LParen, ")");
2842 if_2.body = &int_to_ptr.base;
2843
2844 const else_2 = try transCreateNodeElse(rp.c);
2845 if_2.@"else" = else_2;
2846
2847 const as = try transCreateNodeBuiltinFnCall(rp.c, "@as");
2848 try as.params.push(inner_node);
2849 try as.params.push(node_to_cast);
2850 as.rparen_token = try appendToken(rp.c, .LParen, ")");
2851 else_2.body = &as.base;
2852
2853 return &if_1.base;
2745 },2854 },
2746 else => return revertAndWarn(2855 else => return revertAndWarn(
2747 rp,2856 rp,
...@@ -2780,6 +2889,30 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -2780,6 +2889,30 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
2780 };2889 };
2781 node = &access_node.base;2890 node = &access_node.base;
2782 },2891 },
2892 .Asterisk => {
2893 if (it.peek().?.id == .RParen) {
2894 // type *)
2895
2896 // hack to get zig fmt to render a comma in builtin calls
2897 _ = try appendToken(rp.c, .Comma, ",");
2898
2899 const ptr = try transCreateNodePtrType(rp.c, false, false, .Identifier);
2900 ptr.rhs = node;
2901 return &ptr.base;
2902 } else {
2903 // expr * expr
2904 const op_token = try appendToken(rp.c, .Asterisk, "*");
2905 const rhs = try parseCPrimaryExpr(rp, it, source_loc);
2906 const bitshift_node = try rp.c.a().create(ast.Node.InfixOp);
2907 bitshift_node.* = .{
2908 .op_token = op_token,
2909 .lhs = node,
2910 .op = .BitShiftLeft,
2911 .rhs = rhs,
2912 };
2913 node = &bitshift_node.base;
2914 }
2915 },
2783 .Shl => {2916 .Shl => {
2784 const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<");2917 const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<");
2785 const rhs = try parseCPrimaryExpr(rp, it, source_loc);2918 const rhs = try parseCPrimaryExpr(rp, it, source_loc);
...@@ -2819,6 +2952,16 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -2819,6 +2952,16 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
2819 node.rhs = try parseCPrefixOpExpr(rp, it, source_loc);2952 node.rhs = try parseCPrefixOpExpr(rp, it, source_loc);
2820 return &node.base;2953 return &node.base;
2821 },2954 },
2955 .Asterisk => {
2956 const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc);
2957 const node = try rp.c.a().create(ast.Node.SuffixOp);
2958 node.* = .{
2959 .lhs = .{ .node = prefix_op_expr },
2960 .op = .Deref,
2961 .rtoken = try appendToken(rp.c, .PeriodAsterisk, ".*"),
2962 };
2963 return &node.base;
2964 },
2822 else => {2965 else => {
2823 _ = it.prev();2966 _ = it.prev();
2824 return try parseCSuffixOpExpr(rp, it, source_loc);2967 return try parseCSuffixOpExpr(rp, it, source_loc);
...@@ -2833,7 +2976,7 @@ fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 {...@@ -2833,7 +2976,7 @@ fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 {
28332976
2834fn getFnDecl(c: *Context, ref: *ast.Node) ?*ast.Node {2977fn getFnDecl(c: *Context, ref: *ast.Node) ?*ast.Node {
2835 const init = ref.cast(ast.Node.VarDecl).?.init_node.?;2978 const init = ref.cast(ast.Node.VarDecl).?.init_node.?;
2836 const name = if (init.cast(ast.Node.Identifier)) |id| 2979 const name = if (init.cast(ast.Node.Identifier)) |id|
2837 tokenSlice(c, id.token)2980 tokenSlice(c, id.token)
2838 else2981 else
2839 return null;2982 return null;
test/translate_c.zig+6
...@@ -397,6 +397,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -397,6 +397,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
397 \\pub const OpenGLProcs = union_OpenGLProcs;397 \\pub const OpenGLProcs = union_OpenGLProcs;
398 });398 });
399399
400 cases.add_2("macro pointer cast",
401 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
402 , &[_][]const u8{
403 \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
404 });
405
400 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////406 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
401407
402 cases.add_both("typedef of function in struct field",408 cases.add_both("typedef of function in struct field",