feature. See also
. The project being documented here (as the example) is the Zig library itself.
Translator.transCall
fn transCall(
t: *Translator,
scope: *Scope,
call: Node.Call,
used: ResultUsed,
) TransError!ZigNode
File
Code
fn transCall(
t: *Translator,
scope: *Scope,
call: Node.Call,
used: ResultUsed,
) TransError!ZigNode {
const raw_fn_expr = try t.transExpr(scope, call.callee, .used);
const fn_expr = blk: {
loop: switch (call.callee.get(t.tree)) {
.paren_expr => |paren_expr| {
continue :loop paren_expr.operand.get(t.tree);
},
.decl_ref_expr => |decl_ref| {
if (decl_ref.qt.is(t.comp, .func)) break :blk raw_fn_expr;
},
.cast => |cast| {
if (cast.kind == .function_to_pointer) {
continue :loop cast.operand.get(t.tree);
}
},
.deref_expr, .addr_of_expr => |un| {
continue :loop un.operand.get(t.tree);
},
.generic_expr => |generic| {
continue :loop generic.chosen.get(t.tree);
},
.generic_association_expr => |generic| {
continue :loop generic.expr.get(t.tree);
},
.generic_default_expr => |generic| {
continue :loop generic.expr.get(t.tree);
},
else => {},
}
break :blk try ZigTag.unwrap.create(t.arena, raw_fn_expr);
};
const callee_qt = call.callee.qt(t.tree);
const maybe_ptr_ty = callee_qt.get(t.comp, .pointer);
const func_qt = if (maybe_ptr_ty) |ptr| ptr.child else callee_qt;
const func_ty = func_qt.get(t.comp, .func).?;
const arg_nodes = try t.arena.alloc(ZigNode, call.args.len);
for (call.args, arg_nodes, 0..) |c_arg, *zig_arg, i| {
if (i < func_ty.params.len) {
zig_arg.* = try t.transExprCoercing(scope, c_arg, .used);
if (zig_arg.isBoolRes() and !func_ty.params[i].qt.is(t.comp, .bool)) {
// an argument to a function whose parameter is also int, there is no cast. Therefore
// in Zig we'll need to cast it from bool to u1 (which will safely coerce to c_int).
zig_arg.* = try ZigTag.int_from_bool.create(t.arena, zig_arg.*);
}
} else {
zig_arg.* = try t.transExpr(scope, c_arg, .used);
if (zig_arg.isBoolRes()) {
const u1_node = try ZigTag.int_from_bool.create(t.arena, zig_arg.*);
const c_int_node = try ZigTag.type.create(t.arena, "c_int");
zig_arg.* = try ZigTag.as.create(t.arena, .{ .lhs = c_int_node, .rhs = u1_node });
}
}
}
const res = try ZigTag.call.create(t.arena, .{
.lhs = fn_expr,
.args = arg_nodes,
});
if (call.qt.is(t.comp, .void)) return res;
return t.maybeSuppressResult(used, res);
}