| ... | @@ -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 | } |
| 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 | const RestorePoint = struct { | 2083 | const 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, ")"); | | |
| 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 | 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 { |
| 2833 | | 2976 | |
| 2834 | fn getFnDecl(c: *Context, ref: *ast.Node) ?*ast.Node { | 2977 | fn 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 | else | 2981 | else |
| 2839 | return null; | 2982 | return null; |