| ... | ... | @@ -2438,11 +2438,11 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: |
| 2438 | 2438 | return block_scope.complete(c); |
| 2439 | 2439 | } |
| 2440 | 2440 | |
| 2441 | | fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!*ast.Node { |
| 2442 | | var container_node = try transExpr(rp, scope, stmt.getBase(), .used, .r_value); |
| 2441 | fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node { |
| 2442 | var container_node = try transExpr(c, scope, stmt.getBase(), .used, .r_value); |
| 2443 | 2443 | |
| 2444 | 2444 | if (stmt.isArrow()) { |
| 2445 | | container_node = try transCreateNodePtrDeref(rp.c, container_node); |
| 2445 | container_node = try Node.deref.create(c.arena, container_node); |
| 2446 | 2446 | } |
| 2447 | 2447 | |
| 2448 | 2448 | const member_decl = stmt.getMemberDecl(); |
| ... | ... | @@ -2453,19 +2453,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExp |
| 2453 | 2453 | if (decl_kind == .Field) { |
| 2454 | 2454 | const field_decl = @ptrCast(*const clang.FieldDecl, member_decl); |
| 2455 | 2455 | if (field_decl.isAnonymousStructOrUnion()) { |
| 2456 | | const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; |
| 2457 | | break :blk try mem.dupe(rp.c.arena, u8, name); |
| 2456 | const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; |
| 2457 | break :blk try mem.dupe(c.arena, u8, name); |
| 2458 | 2458 | } |
| 2459 | 2459 | } |
| 2460 | 2460 | const decl = @ptrCast(*const clang.NamedDecl, member_decl); |
| 2461 | | break :blk try rp.c.str(decl.getName_bytes_begin()); |
| 2461 | break :blk try c.str(decl.getName_bytes_begin()); |
| 2462 | 2462 | }; |
| 2463 | 2463 | |
| 2464 | | const node = try transCreateNodeFieldAccess(rp.c, container_node, name); |
| 2465 | | return maybeSuppressResult(rp, scope, result_used, node); |
| 2464 | const node = try Node.field_access.create(c.arena, .{ .container = container_node, .name = name}); |
| 2465 | return maybeSuppressResult(c, scope, result_used, node); |
| 2466 | 2466 | } |
| 2467 | 2467 | |
| 2468 | | fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const clang.ArraySubscriptExpr, result_used: ResultUsed) TransError!*ast.Node { |
| 2468 | fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscriptExpr, result_used: ResultUsed) TransError!Node { |
| 2469 | 2469 | var base_stmt = stmt.getBase(); |
| 2470 | 2470 | |
| 2471 | 2471 | // Unwrap the base statement if it's an array decayed to a bare pointer type |
| ... | ... | @@ -2478,30 +2478,23 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const clang.ArraySub |
| 2478 | 2478 | } |
| 2479 | 2479 | } |
| 2480 | 2480 | |
| 2481 | | const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value); |
| 2482 | | const node = try transCreateNodeArrayAccess(rp.c, container_node); |
| 2481 | const container_node = try transExpr(c, scope, base_stmt, .used, .r_value); |
| 2483 | 2482 | |
| 2484 | 2483 | // cast if the index is long long or signed |
| 2485 | 2484 | const subscr_expr = stmt.getIdx(); |
| 2486 | | const qt = getExprQualType(rp.c, subscr_expr); |
| 2485 | const qt = getExprQualType(c, subscr_expr); |
| 2487 | 2486 | const is_longlong = cIsLongLongInteger(qt); |
| 2488 | 2487 | const is_signed = cIsSignedInteger(qt); |
| 2489 | 2488 | |
| 2490 | | if (is_longlong or is_signed) { |
| 2491 | | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); |
| 2489 | |
| 2490 | const node = try Node.array_access.create(c.arena, .{ .lhs = container_node, .rhs = if (is_longlong or is_signed) blk: { |
| 2491 | const cast_node = try c.createBuiltinCall("@intCast", 2); |
| 2492 | 2492 | // check if long long first so that signed long long doesn't just become unsigned long long |
| 2493 | | var typeid_node = if (is_longlong) try transCreateNodeIdentifier(rp.c, "usize") else try transQualTypeIntWidthOf(rp.c, qt, false); |
| 2494 | | cast_node.params()[0] = typeid_node; |
| 2495 | | _ = try appendToken(rp.c, .Comma, ","); |
| 2496 | | cast_node.params()[1] = try transExpr(rp, scope, subscr_expr, .used, .r_value); |
| 2497 | | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 2498 | | node.rtoken = try appendToken(rp.c, .RBrace, "]"); |
| 2499 | | node.index_expr = &cast_node.base; |
| 2500 | | } else { |
| 2501 | | node.index_expr = try transExpr(rp, scope, subscr_expr, .used, .r_value); |
| 2502 | | node.rtoken = try appendToken(rp.c, .RBrace, "]"); |
| 2503 | | } |
| 2504 | | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 2493 | var typeid_node = if (is_longlong) try transCreateNodeIdentifier(c, "usize") else try transQualTypeIntWidthOf(c, qt, false); |
| 2494 | break :blk try Node.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used, .r_value)}); |
| 2495 | } else |
| 2496 | try transExpr(c, scope, subscr_expr, .used, .r_value)}); |
| 2497 | return maybeSuppressResult(c, scope, result_used, node); |
| 2505 | 2498 | } |
| 2506 | 2499 | |
| 2507 | 2500 | /// Check if an expression is ultimately a reference to a function declaration |
| ... | ... | @@ -2536,9 +2529,9 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool { |
| 2536 | 2529 | } |
| 2537 | 2530 | } |
| 2538 | 2531 | |
| 2539 | | fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!*ast.Node { |
| 2532 | fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!Node { |
| 2540 | 2533 | const callee = stmt.getCallee(); |
| 2541 | | var raw_fn_expr = try transExpr(rp, scope, callee, .used, .r_value); |
| 2534 | var raw_fn_expr = try transExpr(c, scope, callee, .used, .r_value); |
| 2542 | 2535 | |
| 2543 | 2536 | var is_ptr = false; |
| 2544 | 2537 | const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr); |
| ... | ... | @@ -2549,16 +2542,12 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r |
| 2549 | 2542 | raw_fn_expr; |
| 2550 | 2543 | |
| 2551 | 2544 | const num_args = stmt.getNumArgs(); |
| 2552 | | const node = try rp.c.createCall(fn_expr, num_args); |
| 2553 | | const call_params = node.params(); |
| 2545 | const call_params = try c.arena.alloc(Node, num_args); |
| 2554 | 2546 | |
| 2555 | 2547 | const args = stmt.getArgs(); |
| 2556 | 2548 | var i: usize = 0; |
| 2557 | 2549 | while (i < num_args) : (i += 1) { |
| 2558 | | if (i != 0) { |
| 2559 | | _ = try appendToken(rp.c, .Comma, ","); |
| 2560 | | } |
| 2561 | | var call_param = try transExpr(rp, scope, args[i], .used, .r_value); |
| 2550 | var call_param = try transExpr(c, scope, args[i], .used, .r_value); |
| 2562 | 2551 | |
| 2563 | 2552 | // In C the result type of a boolean expression is int. If this result is passed as |
| 2564 | 2553 | // an argument to a function whose parameter is also int, there is no cast. Therefore |
| ... | ... | @@ -2570,10 +2559,7 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r |
| 2570 | 2559 | if (i < param_count) { |
| 2571 | 2560 | const param_qt = fn_proto.getParamType(@intCast(c_uint, i)); |
| 2572 | 2561 | if (isBoolRes(call_param) and cIsNativeInt(param_qt)) { |
| 2573 | | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); |
| 2574 | | builtin_node.params()[0] = call_param; |
| 2575 | | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 2576 | | call_param = &builtin_node.base; |
| 2562 | call_param = try Node.bool_to_int.create(c.arena, call_param); |
| 2577 | 2563 | } |
| 2578 | 2564 | } |
| 2579 | 2565 | }, |
| ... | ... | @@ -2582,18 +2568,16 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r |
| 2582 | 2568 | } |
| 2583 | 2569 | call_params[i] = call_param; |
| 2584 | 2570 | } |
| 2585 | | node.rtoken = try appendToken(rp.c, .RParen, ")"); |
| 2586 | | |
| 2571 | const node = try Node.call.create(c.arena, .{ .lhs = fn_expr, .args = call_params }); |
| 2587 | 2572 | if (fn_ty) |ty| { |
| 2588 | 2573 | const canon = ty.getReturnType().getCanonicalType(); |
| 2589 | 2574 | const ret_ty = canon.getTypePtr(); |
| 2590 | 2575 | if (ret_ty.isVoidType()) { |
| 2591 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2592 | | return &node.base; |
| 2576 | return node; |
| 2593 | 2577 | } |
| 2594 | 2578 | } |
| 2595 | 2579 | |
| 2596 | | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 2580 | return maybeSuppressResult(c, scope, result_used, node); |
| 2597 | 2581 | } |
| 2598 | 2582 | |
| 2599 | 2583 | const ClangFunctionType = union(enum) { |
| ... | ... | @@ -2667,21 +2651,21 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat |
| 2667 | 2651 | const op_expr = stmt.getSubExpr(); |
| 2668 | 2652 | switch (stmt.getOpcode()) { |
| 2669 | 2653 | .PostInc => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2670 | | return transCreatePostCrement(c, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used) |
| 2654 | return transCreatePostCrement(c, scope, stmt, .assign_add_wrap, used) |
| 2671 | 2655 | else |
| 2672 | | return transCreatePostCrement(c, scope, stmt, .AssignAdd, .PlusEqual, "+=", used), |
| 2656 | return transCreatePostCrement(c, scope, stmt, .assign_add, used), |
| 2673 | 2657 | .PostDec => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2674 | | return transCreatePostCrement(c, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used) |
| 2658 | return transCreatePostCrement(c, scope, stmt, .assign_sub_wrap, used) |
| 2675 | 2659 | else |
| 2676 | | return transCreatePostCrement(c, scope, stmt, .AssignSub, .MinusEqual, "-=", used), |
| 2660 | return transCreatePostCrement(c, scope, stmt, .assign_sub, used), |
| 2677 | 2661 | .PreInc => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2678 | | return transCreatePreCrement(c, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used) |
| 2662 | return transCreatePreCrement(c, scope, stmt, .assign_add_wrap, used) |
| 2679 | 2663 | else |
| 2680 | | return transCreatePreCrement(c, scope, stmt, .AssignAdd, .PlusEqual, "+=", used), |
| 2664 | return transCreatePreCrement(c, scope, stmt, .assign_add, used), |
| 2681 | 2665 | .PreDec => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2682 | | return transCreatePreCrement(c, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used) |
| 2666 | return transCreatePreCrement(c, scope, stmt, .assign_sub_wrap, used) |
| 2683 | 2667 | else |
| 2684 | | return transCreatePreCrement(c, scope, stmt, .AssignSub, .MinusEqual, "-=", used), |
| 2668 | return transCreatePreCrement(c, scope, stmt, .assign_sub, used), |
| 2685 | 2669 | .AddrOf => { |
| 2686 | 2670 | if (cIsFunctionDeclRef(op_expr)) { |
| 2687 | 2671 | return transExpr(rp, scope, op_expr, used, .r_value); |
| ... | ... | @@ -2704,7 +2688,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat |
| 2704 | 2688 | // use -% x for unsigned integers |
| 2705 | 2689 | return Node.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value)); |
| 2706 | 2690 | } else |
| 2707 | | return revertAndWarn(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{}); |
| 2691 | return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{}); |
| 2708 | 2692 | }, |
| 2709 | 2693 | .Not => { |
| 2710 | 2694 | return Node.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value)); |
| ... | ... | @@ -2715,31 +2699,32 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat |
| 2715 | 2699 | .Extension => { |
| 2716 | 2700 | return transExpr(c, scope, stmt.getSubExpr(), used, .l_value); |
| 2717 | 2701 | }, |
| 2718 | | else => return revertAndWarn(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}), |
| 2702 | else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}), |
| 2719 | 2703 | } |
| 2720 | 2704 | } |
| 2721 | 2705 | |
| 2722 | 2706 | fn transCreatePreCrement( |
| 2723 | | rp: RestorePoint, |
| 2707 | c: *Context, |
| 2724 | 2708 | scope: *Scope, |
| 2725 | 2709 | stmt: *const clang.UnaryOperator, |
| 2726 | | op: ast.Node.Tag, |
| 2727 | | op_tok_id: std.zig.Token.Id, |
| 2728 | | bytes: []const u8, |
| 2710 | op: Node.Tag, |
| 2729 | 2711 | used: ResultUsed, |
| 2730 | | ) TransError!*ast.Node { |
| 2712 | ) TransError!Node { |
| 2731 | 2713 | const op_expr = stmt.getSubExpr(); |
| 2732 | 2714 | |
| 2733 | 2715 | if (used == .unused) { |
| 2734 | 2716 | // common case |
| 2735 | 2717 | // c: ++expr |
| 2736 | 2718 | // zig: expr += 1 |
| 2737 | | const expr = try transExpr(rp, scope, op_expr, .used, .r_value); |
| 2738 | | const token = try appendToken(rp.c, op_tok_id, bytes); |
| 2739 | | const one = try transCreateNodeInt(rp.c, 1); |
| 2740 | | if (scope.id != .Condition) |
| 2741 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2742 | | return transCreateNodeInfixOp(rp, scope, expr, op, token, one, .used, false); |
| 2719 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 2720 | payload.* = .{ |
| 2721 | .base = .{ .tag = op }, |
| 2722 | .data = .{ |
| 2723 | .lhs = try transExpr(c, scope, op_expr, .used, .r_value), |
| 2724 | .rhs = Node.one_literal.init(), |
| 2725 | } |
| 2726 | }; |
| 2727 | return Node.initPayload(&payload.base); |
| 2743 | 2728 | } |
| 2744 | 2729 | // worst case |
| 2745 | 2730 | // c: ++expr |
| ... | ... | @@ -2748,71 +2733,55 @@ fn transCreatePreCrement( |
| 2748 | 2733 | // zig: _ref.* += 1; |
| 2749 | 2734 | // zig: break :blk _ref.* |
| 2750 | 2735 | // zig: }) |
| 2751 | | var block_scope = try Scope.Block.init(rp.c, scope, true); |
| 2736 | var block_scope = try Scope.Block.init(c, scope, true); |
| 2752 | 2737 | defer block_scope.deinit(); |
| 2753 | | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 2738 | const ref = try block_scope.makeMangledName(c, "ref"); |
| 2754 | 2739 | |
| 2755 | | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 2756 | | const name_tok = try appendIdentifier(rp.c, ref); |
| 2757 | | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 2758 | | const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); |
| 2759 | | rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); |
| 2760 | | const init_node = &rhs_node.base; |
| 2761 | | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 2762 | | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ |
| 2763 | | .name_token = name_tok, |
| 2764 | | .mut_token = mut_tok, |
| 2765 | | .semicolon_token = semicolon_token, |
| 2766 | | }, .{ |
| 2767 | | .eq_token = eq_token, |
| 2768 | | .init_node = init_node, |
| 2769 | | }); |
| 2770 | | try block_scope.statements.append(&node.base); |
| 2740 | const expr = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2741 | const addr_of = try Node.address_of.create(c.arena, expr); |
| 2742 | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of}); |
| 2743 | try block_scope.statements.append(ref_decl); |
| 2771 | 2744 | |
| 2772 | | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| 2773 | | const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); |
| 2774 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2775 | | const token = try appendToken(rp.c, op_tok_id, bytes); |
| 2776 | | const one = try transCreateNodeInt(rp.c, 1); |
| 2777 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2778 | | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false); |
| 2779 | | try block_scope.statements.append(assign); |
| 2780 | | |
| 2781 | | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node); |
| 2782 | | try block_scope.statements.append(&break_node.base); |
| 2783 | | const block_node = try block_scope.complete(rp.c); |
| 2784 | | // semicolon must immediately follow rbrace because it is the last token in a block |
| 2785 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2786 | | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); |
| 2787 | | grouped_expr.* = .{ |
| 2788 | | .lparen = try appendToken(rp.c, .LParen, "("), |
| 2789 | | .expr = block_node, |
| 2790 | | .rparen = try appendToken(rp.c, .RParen, ")"), |
| 2745 | const lhs_node = try Node.identifier.create(c.arena, ref); |
| 2746 | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2747 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 2748 | payload.* = .{ |
| 2749 | .base = .{ .tag = op }, |
| 2750 | .data = .{ |
| 2751 | .lhs = ref_node, |
| 2752 | .rhs = Node.one_literal.init(), |
| 2753 | } |
| 2791 | 2754 | }; |
| 2792 | | return &grouped_expr.base; |
| 2755 | try block_scope.statements.append(Node.initPayload(&payload.base)); |
| 2756 | |
| 2757 | return Node.break_val.create(c.arena, .{ |
| 2758 | .label = block_scope.label, |
| 2759 | .val = ref_node, |
| 2760 | }); |
| 2793 | 2761 | } |
| 2794 | 2762 | |
| 2795 | 2763 | fn transCreatePostCrement( |
| 2796 | | rp: RestorePoint, |
| 2764 | c: *Context, |
| 2797 | 2765 | scope: *Scope, |
| 2798 | 2766 | stmt: *const clang.UnaryOperator, |
| 2799 | | op: ast.Node.Tag, |
| 2800 | | op_tok_id: std.zig.Token.Id, |
| 2801 | | bytes: []const u8, |
| 2767 | op: Node.Tag, |
| 2802 | 2768 | used: ResultUsed, |
| 2803 | | ) TransError!*ast.Node { |
| 2769 | ) TransError!Node { |
| 2804 | 2770 | const op_expr = stmt.getSubExpr(); |
| 2805 | 2771 | |
| 2806 | 2772 | if (used == .unused) { |
| 2807 | 2773 | // common case |
| 2808 | 2774 | // c: ++expr |
| 2809 | 2775 | // zig: expr += 1 |
| 2810 | | const expr = try transExpr(rp, scope, op_expr, .used, .r_value); |
| 2811 | | const token = try appendToken(rp.c, op_tok_id, bytes); |
| 2812 | | const one = try transCreateNodeInt(rp.c, 1); |
| 2813 | | if (scope.id != .Condition) |
| 2814 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2815 | | return transCreateNodeInfixOp(rp, scope, expr, op, token, one, .used, false); |
| 2776 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 2777 | payload.* = .{ |
| 2778 | .base = .{ .tag = op }, |
| 2779 | .data = .{ |
| 2780 | .lhs = try transExpr(c, scope, op_expr, .used, .r_value), |
| 2781 | .rhs = Node.one_literal.init(), |
| 2782 | } |
| 2783 | }; |
| 2784 | return Node.initPayload(&payload.base); |
| 2816 | 2785 | } |
| 2817 | 2786 | // worst case |
| 2818 | 2787 | // c: expr++ |
| ... | ... | @@ -2822,68 +2791,36 @@ fn transCreatePostCrement( |
| 2822 | 2791 | // zig: _ref.* += 1; |
| 2823 | 2792 | // zig: break :blk _tmp |
| 2824 | 2793 | // zig: }) |
| 2825 | | var block_scope = try Scope.Block.init(rp.c, scope, true); |
| 2794 | var block_scope = try Scope.Block.init(c, scope, true); |
| 2826 | 2795 | defer block_scope.deinit(); |
| 2827 | | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 2796 | const ref = try block_scope.makeMangledName(c, "ref"); |
| 2828 | 2797 | |
| 2829 | | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 2830 | | const name_tok = try appendIdentifier(rp.c, ref); |
| 2831 | | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 2832 | | const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); |
| 2833 | | rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); |
| 2834 | | const init_node = &rhs_node.base; |
| 2835 | | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 2836 | | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ |
| 2837 | | .name_token = name_tok, |
| 2838 | | .mut_token = mut_tok, |
| 2839 | | .semicolon_token = semicolon_token, |
| 2840 | | }, .{ |
| 2841 | | .eq_token = eq_token, |
| 2842 | | .init_node = init_node, |
| 2843 | | }); |
| 2844 | | try block_scope.statements.append(&node.base); |
| 2798 | const expr = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2799 | const addr_of = try Node.address_of.create(c.arena, expr); |
| 2800 | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of}); |
| 2801 | try block_scope.statements.append(ref_decl); |
| 2845 | 2802 | |
| 2846 | | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| 2847 | | const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); |
| 2848 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2803 | const lhs_node = try Node.identifier.create(c.arena, ref); |
| 2804 | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2849 | 2805 | |
| 2850 | | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); |
| 2851 | | const tmp_mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 2852 | | const tmp_name_tok = try appendIdentifier(rp.c, tmp); |
| 2853 | | const tmp_eq_token = try appendToken(rp.c, .Equal, "="); |
| 2854 | | const tmp_init_node = ref_node; |
| 2855 | | const tmp_semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 2856 | | const tmp_node = try ast.Node.VarDecl.create(rp.c.arena, .{ |
| 2857 | | .name_token = tmp_name_tok, |
| 2858 | | .mut_token = tmp_mut_tok, |
| 2859 | | .semicolon_token = semicolon_token, |
| 2860 | | }, .{ |
| 2861 | | .eq_token = tmp_eq_token, |
| 2862 | | .init_node = tmp_init_node, |
| 2863 | | }); |
| 2864 | | try block_scope.statements.append(&tmp_node.base); |
| 2806 | const tmp = try block_scope.makeMangledName(c, "tmp"); |
| 2807 | const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node}); |
| 2808 | try block_scope.statements.append(tmp_decl); |
| 2865 | 2809 | |
| 2866 | | const token = try appendToken(rp.c, op_tok_id, bytes); |
| 2867 | | const one = try transCreateNodeInt(rp.c, 1); |
| 2868 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2869 | | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false); |
| 2870 | | try block_scope.statements.append(assign); |
| 2871 | | |
| 2872 | | const break_node = blk: { |
| 2873 | | var tmp_ctrl_flow = try CtrlFlow.initToken(rp.c, .Break, block_scope.label); |
| 2874 | | const rhs = try transCreateNodeIdentifier(rp.c, tmp); |
| 2875 | | break :blk try tmp_ctrl_flow.finish(rhs); |
| 2876 | | }; |
| 2877 | | try block_scope.statements.append(&break_node.base); |
| 2878 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2879 | | const block_node = try block_scope.complete(rp.c); |
| 2880 | | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); |
| 2881 | | grouped_expr.* = .{ |
| 2882 | | .lparen = try appendToken(rp.c, .LParen, "("), |
| 2883 | | .expr = block_node, |
| 2884 | | .rparen = try appendToken(rp.c, .RParen, ")"), |
| 2810 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 2811 | payload.* = .{ |
| 2812 | .base = .{ .tag = op }, |
| 2813 | .data = .{ |
| 2814 | .lhs = ref_node, |
| 2815 | .rhs = Node.one_literal.init(), |
| 2816 | } |
| 2885 | 2817 | }; |
| 2886 | | return &grouped_expr.base; |
| 2818 | try block_scope.statements.append(Node.initPayload(&payload.base)); |
| 2819 | |
| 2820 | return Node.break_val.create(c.arena, .{ |
| 2821 | .label = block_scope.label, |
| 2822 | .val = try Node.identifier.create(c.arena, tmp), |
| 2823 | }); |
| 2887 | 2824 | } |
| 2888 | 2825 | |
| 2889 | 2826 | fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!*ast.Node { |
| ... | ... | @@ -3139,31 +3076,24 @@ fn transCPtrCast( |
| 3139 | 3076 | } |
| 3140 | 3077 | } |
| 3141 | 3078 | |
| 3142 | | fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node { |
| 3079 | fn transBreak(c: *Context, scope: *Scope) TransError!Node { |
| 3143 | 3080 | const break_scope = scope.getBreakableScope(); |
| 3144 | 3081 | const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: { |
| 3145 | 3082 | const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope); |
| 3146 | | const block_scope = try scope.findBlockScope(rp.c); |
| 3147 | | swtch.switch_label = try block_scope.makeMangledName(rp.c, "switch"); |
| 3083 | const block_scope = try scope.findBlockScope(c); |
| 3084 | swtch.switch_label = try block_scope.makeMangledName(c, "switch"); |
| 3148 | 3085 | break :blk swtch.switch_label; |
| 3149 | 3086 | } else |
| 3150 | 3087 | null; |
| 3151 | 3088 | |
| 3152 | | var cf = try CtrlFlow.init(rp.c, .Break, label_text); |
| 3153 | | const br = try cf.finish(null); |
| 3154 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3155 | | return &br.base; |
| 3089 | return Node.@"break".create(c.arena, label_text); |
| 3156 | 3090 | } |
| 3157 | 3091 | |
| 3158 | | fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!*ast.Node { |
| 3092 | fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node { |
| 3159 | 3093 | // TODO use something more accurate |
| 3160 | 3094 | const dbl = stmt.getValueAsApproximateDouble(); |
| 3161 | | const node = try rp.c.arena.create(ast.Node.OneToken); |
| 3162 | | node.* = .{ |
| 3163 | | .base = .{ .tag = .FloatLiteral }, |
| 3164 | | .token = try appendTokenFmt(rp.c, .FloatLiteral, "{d}", .{dbl}), |
| 3165 | | }; |
| 3166 | | return maybeSuppressResult(rp, scope, used, &node.base); |
| 3095 | const node = try Node.float_literal.create(c.arena, try std.fmt.allocPrint(c.arena, "{d}", .{dbl})); |
| 3096 | return maybeSuppressResult(c, scope, used, &node.base); |
| 3167 | 3097 | } |
| 3168 | 3098 | |
| 3169 | 3099 | fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!*ast.Node { |
| ... | ... | @@ -3943,169 +3873,7 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a |
| 3943 | 3873 | return &fn_proto.base; |
| 3944 | 3874 | } |
| 3945 | 3875 | |
| 3946 | | fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node { |
| 3947 | | _ = try appendToken(c, .Period, "."); |
| 3948 | | const qm = try appendToken(c, .QuestionMark, "?"); |
| 3949 | | const node = try c.arena.create(ast.Node.SimpleSuffixOp); |
| 3950 | | node.* = .{ |
| 3951 | | .base = .{ .tag = .UnwrapOptional }, |
| 3952 | | .lhs = wrapped, |
| 3953 | | .rtoken = qm, |
| 3954 | | }; |
| 3955 | | return &node.base; |
| 3956 | | } |
| 3957 | | |
| 3958 | | fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node { |
| 3959 | | const node = try c.arena.create(ast.Node.EnumLiteral); |
| 3960 | | node.* = .{ |
| 3961 | | .dot = try appendToken(c, .Period, "."), |
| 3962 | | .name = try appendIdentifier(c, name), |
| 3963 | | }; |
| 3964 | | return &node.base; |
| 3965 | | } |
| 3966 | | |
| 3967 | | fn transCreateNodeStringLiteral(c: *Context, str: []const u8) !*ast.Node { |
| 3968 | | const node = try c.arena.create(ast.Node.OneToken); |
| 3969 | | node.* = .{ |
| 3970 | | .base = .{ .tag = .StringLiteral }, |
| 3971 | | .token = try appendToken(c, .StringLiteral, str), |
| 3972 | | }; |
| 3973 | | return &node.base; |
| 3974 | | } |
| 3975 | | |
| 3976 | | fn transCreateNodeIf(c: *Context) !*ast.Node.If { |
| 3977 | | const if_tok = try appendToken(c, .Keyword_if, "if"); |
| 3978 | | _ = try appendToken(c, .LParen, "("); |
| 3979 | | const node = try c.arena.create(ast.Node.If); |
| 3980 | | node.* = .{ |
| 3981 | | .if_token = if_tok, |
| 3982 | | .condition = undefined, |
| 3983 | | .payload = null, |
| 3984 | | .body = undefined, |
| 3985 | | .@"else" = null, |
| 3986 | | }; |
| 3987 | | return node; |
| 3988 | | } |
| 3989 | | |
| 3990 | | fn transCreateNodeElse(c: *Context) !*ast.Node.Else { |
| 3991 | | const node = try c.arena.create(ast.Node.Else); |
| 3992 | | node.* = .{ |
| 3993 | | .else_token = try appendToken(c, .Keyword_else, "else"), |
| 3994 | | .payload = null, |
| 3995 | | .body = undefined, |
| 3996 | | }; |
| 3997 | | return node; |
| 3998 | | } |
| 3999 | | |
| 4000 | | fn transCreateNodeBreak( |
| 4001 | | c: *Context, |
| 4002 | | label: ?ast.TokenIndex, |
| 4003 | | rhs: ?*ast.Node, |
| 4004 | | ) !*ast.Node.ControlFlowExpression { |
| 4005 | | var ctrl_flow = try CtrlFlow.init(c, .Break, if (label) |l| tokenSlice(c, l) else null); |
| 4006 | | return ctrl_flow.finish(rhs); |
| 4007 | | } |
| 4008 | | |
| 4009 | | const CtrlFlow = struct { |
| 4010 | | c: *Context, |
| 4011 | | ltoken: ast.TokenIndex, |
| 4012 | | label_token: ?ast.TokenIndex, |
| 4013 | | tag: ast.Node.Tag, |
| 4014 | | |
| 4015 | | /// Does everything except the RHS. |
| 4016 | | fn init(c: *Context, tag: ast.Node.Tag, label: ?[]const u8) !CtrlFlow { |
| 4017 | | const kw: Token.Id = switch (tag) { |
| 4018 | | .Break => .Keyword_break, |
| 4019 | | .Continue => .Keyword_continue, |
| 4020 | | .Return => .Keyword_return, |
| 4021 | | else => unreachable, |
| 4022 | | }; |
| 4023 | | const kw_text = switch (tag) { |
| 4024 | | .Break => "break", |
| 4025 | | .Continue => "continue", |
| 4026 | | .Return => "return", |
| 4027 | | else => unreachable, |
| 4028 | | }; |
| 4029 | | const ltoken = try appendToken(c, kw, kw_text); |
| 4030 | | const label_token = if (label) |l| blk: { |
| 4031 | | _ = try appendToken(c, .Colon, ":"); |
| 4032 | | break :blk try appendIdentifier(c, l); |
| 4033 | | } else null; |
| 4034 | | return CtrlFlow{ |
| 4035 | | .c = c, |
| 4036 | | .ltoken = ltoken, |
| 4037 | | .label_token = label_token, |
| 4038 | | .tag = tag, |
| 4039 | | }; |
| 4040 | | } |
| 4041 | | |
| 4042 | | fn initToken(c: *Context, tag: ast.Node.Tag, label: ?ast.TokenIndex) !CtrlFlow { |
| 4043 | | const other_token = label orelse return init(c, tag, null); |
| 4044 | | const loc = c.token_locs.items[other_token]; |
| 4045 | | const label_name = c.source_buffer.items[loc.start..loc.end]; |
| 4046 | | return init(c, tag, label_name); |
| 4047 | | } |
| 4048 | | |
| 4049 | | fn finish(self: *CtrlFlow, rhs: ?*ast.Node) !*ast.Node.ControlFlowExpression { |
| 4050 | | return ast.Node.ControlFlowExpression.create(self.c.arena, .{ |
| 4051 | | .ltoken = self.ltoken, |
| 4052 | | .tag = self.tag, |
| 4053 | | }, .{ |
| 4054 | | .label = self.label_token, |
| 4055 | | .rhs = rhs, |
| 4056 | | }); |
| 4057 | | } |
| 4058 | | }; |
| 4059 | | |
| 4060 | | fn transCreateNodeWhile(c: *Context) !*ast.Node.While { |
| 4061 | | const while_tok = try appendToken(c, .Keyword_while, "while"); |
| 4062 | | _ = try appendToken(c, .LParen, "("); |
| 4063 | | |
| 4064 | | const node = try c.arena.create(ast.Node.While); |
| 4065 | | node.* = .{ |
| 4066 | | .label = null, |
| 4067 | | .inline_token = null, |
| 4068 | | .while_token = while_tok, |
| 4069 | | .condition = undefined, |
| 4070 | | .payload = null, |
| 4071 | | .continue_expr = null, |
| 4072 | | .body = undefined, |
| 4073 | | .@"else" = null, |
| 4074 | | }; |
| 4075 | | return node; |
| 4076 | | } |
| 4077 | | |
| 4078 | | fn transCreateNodeContinue(c: *Context) !*ast.Node { |
| 4079 | | const ltoken = try appendToken(c, .Keyword_continue, "continue"); |
| 4080 | | const node = try ast.Node.ControlFlowExpression.create(c.arena, .{ |
| 4081 | | .ltoken = ltoken, |
| 4082 | | .tag = .Continue, |
| 4083 | | }, .{}); |
| 4084 | | _ = try appendToken(c, .Semicolon, ";"); |
| 4085 | | return &node.base; |
| 4086 | | } |
| 4087 | | |
| 4088 | | fn transCreateNodeSwitchCase(c: *Context, lhs: *ast.Node) !*ast.Node.SwitchCase { |
| 4089 | | const arrow_tok = try appendToken(c, .EqualAngleBracketRight, "=>"); |
| 4090 | 3876 | |
| 4091 | | const node = try ast.Node.SwitchCase.alloc(c.arena, 1); |
| 4092 | | node.* = .{ |
| 4093 | | .items_len = 1, |
| 4094 | | .arrow_token = arrow_tok, |
| 4095 | | .payload = null, |
| 4096 | | .expr = undefined, |
| 4097 | | }; |
| 4098 | | node.items()[0] = lhs; |
| 4099 | | return node; |
| 4100 | | } |
| 4101 | | |
| 4102 | | fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { |
| 4103 | | const node = try c.arena.create(ast.Node.SwitchElse); |
| 4104 | | node.* = .{ |
| 4105 | | .token = try appendToken(c, .Keyword_else, "else"), |
| 4106 | | }; |
| 4107 | | return &node.base; |
| 4108 | | } |
| 4109 | 3877 | |
| 4110 | 3878 | fn transCreateNodeShiftOp( |
| 4111 | 3879 | c: *Context, |
| ... | ... | @@ -4137,27 +3905,6 @@ fn transCreateNodeShiftOp( |
| 4137 | 3905 | return Node.initPayload(&payload.base); |
| 4138 | 3906 | } |
| 4139 | 3907 | |
| 4140 | | fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node { |
| 4141 | | const node = try c.arena.create(ast.Node.SimpleSuffixOp); |
| 4142 | | node.* = .{ |
| 4143 | | .base = .{ .tag = .Deref }, |
| 4144 | | .lhs = lhs, |
| 4145 | | .rtoken = try appendToken(c, .PeriodAsterisk, ".*"), |
| 4146 | | }; |
| 4147 | | return &node.base; |
| 4148 | | } |
| 4149 | | |
| 4150 | | fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAccess { |
| 4151 | | _ = try appendToken(c, .LBrace, "["); |
| 4152 | | const node = try c.arena.create(ast.Node.ArrayAccess); |
| 4153 | | node.* = .{ |
| 4154 | | .lhs = lhs, |
| 4155 | | .index_expr = undefined, |
| 4156 | | .rtoken = undefined, |
| 4157 | | }; |
| 4158 | | return node; |
| 4159 | | } |
| 4160 | | |
| 4161 | 3908 | fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node { |
| 4162 | 3909 | switch (ty.getTypeClass()) { |
| 4163 | 3910 | .Builtin => { |