| ... | ... | @@ -2039,7 +2039,7 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node { |
| 2039 | 2039 | _ = try appendToken(c, .Period, "."); |
| 2040 | 2040 | const qm = try appendToken(c, .QuestionMark, "?"); |
| 2041 | 2041 | const node = try c.a().create(ast.Node.SuffixOp); |
| 2042 | | node.* = ast.Node.SuffixOp{ |
| 2042 | node.* = .{ |
| 2043 | 2043 | .op = .UnwrapOptional, |
| 2044 | 2044 | .lhs = .{ .node = wrapped }, |
| 2045 | 2045 | .rtoken = qm, |
| ... | ... | @@ -2047,6 +2047,39 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node { |
| 2047 | 2047 | return &node.base; |
| 2048 | 2048 | } |
| 2049 | 2049 | |
| 2050 | fn 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 | |
| 2059 | fn 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 | |
| 2073 | fn 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 | |
| 2050 | 2083 | const RestorePoint = struct { |
| 2051 | 2084 | c: *Context, |
| 2052 | 2085 | token_index: ast.TokenIndex, |
| ... | ... | @@ -2722,26 +2755,102 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: |
| 2722 | 2755 | }; |
| 2723 | 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 | 2758 | .NumLitInt, .NumLitFloat => { |
| 2736 | 2759 | return parseCNumLit(rp, tok, source_loc); |
| 2737 | 2760 | }, |
| 2738 | 2761 | .Identifier => return transCreateNodeIdentifier(rp.c, tok.bytes), |
| 2739 | 2762 | .LParen => { |
| 2740 | | _ = try appendToken(rp.c, .LParen, "("); |
| 2741 | 2763 | const inner_node = try parseCExpr(rp, it, source_loc); |
| 2742 | | _ = try appendToken(rp.c, .RParen, ")"); |
| 2743 | 2764 | |
| 2744 | | return inner_node; // TODO |
| 2765 | // 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 | 2855 | else => return revertAndWarn( |
| 2747 | 2856 | rp, |
| ... | ... | @@ -2780,6 +2889,30 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 2780 | 2889 | }; |
| 2781 | 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 | 2916 | .Shl => { |
| 2784 | 2917 | const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<"); |
| 2785 | 2918 | const rhs = try parseCPrimaryExpr(rp, it, source_loc); |
| ... | ... | @@ -2819,6 +2952,16 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 2819 | 2952 | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc); |
| 2820 | 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 | 2965 | else => { |
| 2823 | 2966 | _ = it.prev(); |
| 2824 | 2967 | return try parseCSuffixOpExpr(rp, it, source_loc); |
| ... | ... | @@ -2833,7 +2976,7 @@ fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 { |
| 2833 | 2976 | |
| 2834 | 2977 | fn getFnDecl(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 2835 | 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 | 2980 | tokenSlice(c, id.token) |
| 2838 | 2981 | else |
| 2839 | 2982 | return null; |