Commit 78fba4e021
Changed files (4)
lib
std
src
translate_c
lib/std/zig/parser_test.zig
@@ -3669,12 +3669,12 @@ test "zig fmt: hexadeciaml float literals with underscore separators" {
);
}
-//test "zig fmt: C var args" {
-// try testCanonical(
-// \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
-// \\
-// );
-//}
+test "zig fmt: C var args" {
+ try testCanonical(
+ \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
+ \\
+ );
+}
//test "zig fmt: Only indent multiline string literals in function calls" {
// try testCanonical(
lib/std/zig/render.zig
@@ -1308,7 +1308,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
.r_paren => break,
.comma => {
try renderToken(ais, tree, last_param_token, .space); // ,
- last_param_token += 1;
+ continue;
},
else => {}, // Parameter type without a name.
}
src/translate_c/ast.zig
@@ -491,7 +491,10 @@ pub const Payload = struct {
pub const Enum = struct {
base: Payload,
- data: []Field,
+ data: struct {
+ int_type: Node,
+ fields: []Field,
+ },
pub const Field = struct {
name: []const u8,
@@ -825,11 +828,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.main_token = try c.addToken(.identifier, "void"),
.data = undefined,
}),
- .@"anytype" => return c.addNode(.{
- .tag = .@"anytype",
- .main_token = try c.addToken(.keyword_anytype, "anytype"),
- .data = undefined,
- }),
.noreturn_type => return c.addNode(.{
.tag = .identifier,
.main_token = try c.addToken(.identifier, "noreturn"),
@@ -946,7 +944,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.char_literal).?.data;
return c.addNode(.{
.tag = .identifier,
- .main_token = try c.addToken(.string_literal, payload),
+ .main_token = try c.addToken(.char_literal, payload),
.data = undefined,
});
},
@@ -1268,7 +1266,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const lhs = try c.addNode(.{
.tag = .identifier,
.main_token = try c.addToken(.identifier, "_"),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
return c.addNode(.{
.tag = .assign,
@@ -1510,7 +1508,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.rhs = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{payload.count}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
}),
},
});
@@ -1519,7 +1517,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.empty_array).?.data;
const type_expr = try renderArrayType(c, 0, payload);
- return renderArrayInit(c, 0, &.{});
+ return renderArrayInit(c, type_expr, &.{});
},
.array_init => {
const payload = node.castTag(.array_init).?.data;
@@ -1534,15 +1532,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.@"struct", .@"union" => return renderRecord(c, node),
.@"enum" => {
const payload = node.castTag(.@"enum").?.data;
+ _ = try c.addToken(.keyword_extern, "extern");
const enum_tok = try c.addToken(.keyword_enum, "enum");
-
+ _ = try c.addToken(.l_paren, "(");
+ const arg_expr = try renderNode(c, payload.int_type);
+ _ = try c.addToken(.r_paren, ")");
_ = try c.addToken(.l_brace, "{");
- const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.len + 1, 1));
+ const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.fields.len + 1, 1));
defer c.gpa.free(members);
members[0] = 0;
- members[1] = 0;
- for (payload) |field, i| {
+ for (payload.fields) |field, i| {
const name_tok = try c.addIdentifier(field.name);
const value_expr = if (field.value) |some| blk: {
_ = try c.addToken(.equal, "=");
@@ -1560,7 +1560,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
_ = try c.addToken(.comma, ",");
}
// make non-exhaustive
- members[payload.len] = try c.addNode(.{
+ members[payload.fields.len] = try c.addNode(.{
.tag = .container_field_init,
.main_token = try c.addIdentifier("_"),
.data = .{
@@ -1571,26 +1571,18 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
_ = try c.addToken(.comma, ",");
_ = try c.addToken(.r_brace, "}");
- if (members.len <= 2) {
- return c.addNode(.{
- .tag = .container_decl_two_comma,
- .main_token = enum_tok,
- .data = .{
- .lhs = members[0],
- .rhs = members[1],
- },
- });
- } else {
- const span = try c.listToSpan(members);
- return c.addNode(.{
- .tag = .container_decl_comma,
- .main_token = enum_tok,
- .data = .{
- .lhs = span.start,
- .rhs = span.end,
- },
- });
- }
+ const span = try c.listToSpan(members);
+ return c.addNode(.{
+ .tag = .container_decl_arg_comma,
+ .main_token = enum_tok,
+ .data = .{
+ .lhs = arg_expr,
+ .rhs = try c.addExtra(NodeSubRange{
+ .start = span.start,
+ .end = span.end,
+ }),
+ },
+ });
},
.enum_redecl => {
const payload = node.castTag(.enum_redecl).?.data;
@@ -1701,12 +1693,16 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
});
}
},
+ .@"anytype" => unreachable, // Handled in renderParams
}
}
fn renderRecord(c: *Context, node: Node) !NodeIndex {
const payload = @fieldParentPtr(Payload.Record, "base", node.ptr_otherwise).data;
- if (payload.is_packed) _ = try c.addToken(.keyword_packed, "packed");
+ if (payload.is_packed)
+ _ = try c.addToken(.keyword_packed, "packed")
+ else
+ _ = try c.addToken(.keyword_extern, "extern");
const kind_tok = if (node.tag() == .@"struct")
try c.addToken(.keyword_struct, "struct")
else
@@ -1829,7 +1825,7 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
const len_expr = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{len}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
_ = try c.addToken(.r_bracket, "]");
const elem_type_expr = try renderNode(c, elem_type);
@@ -1920,6 +1916,8 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.negate_wrap,
.bit_not,
.func,
+ .call,
+ .array_type,
=> {
// no grouping needed
return renderNode(c, node);
@@ -1954,7 +1952,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.array_cat,
.array_filler,
.@"if",
- .call,
.@"enum",
.@"struct",
.@"union",
@@ -1962,7 +1959,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.tuple,
.container_init,
.block,
- .array_type,
=> return c.addNode(.{
.tag = .grouped_expression,
.main_token = try c.addToken(.l_paren, "("),
@@ -2161,7 +2157,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@@ -2173,7 +2169,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .string_literal,
.main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@@ -2232,39 +2228,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const fn_token = try c.addToken(.keyword_fn, "fn");
if (payload.name) |some| _ = try c.addIdentifier(some);
- _ = try c.addToken(.l_paren, "(");
- const first = if (payload.params.len != 0) blk: {
- const param = payload.params[0];
- if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
- if (param.name) |some| {
- _ = try c.addIdentifier(some);
- _ = try c.addToken(.colon, ":");
- }
- break :blk try renderNode(c, param.type);
- } else 0;
-
+ const params = try renderParams(c, payload.params, payload.is_var_args);
+ defer params.deinit();
var span: NodeSubRange = undefined;
- if (payload.params.len > 1) {
- var params = try c.gpa.alloc(NodeIndex, payload.params.len);
- defer c.gpa.free(params);
-
- params[0] = first;
- for (payload.params[1..]) |param, i| {
- _ = try c.addToken(.comma, ",");
- if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
- if (param.name) |some| {
- _ = try c.addIdentifier(some);
- _ = try c.addToken(.colon, ":");
- }
- params[i + 1] = try renderNode(c, param.type);
- }
- span = try c.listToSpan(params);
- }
- if (payload.is_var_args) {
- if (payload.params.len != 0) _ = try c.addToken(.comma, ",");
- _ = try c.addToken(.ellipsis3, "...");
- }
- _ = try c.addToken(.r_paren, ")");
+ if (params.items.len > 1) span = try c.listToSpan(params.items);
const align_expr = if (payload.alignment) |some| blk: {
_ = try c.addToken(.keyword_align, "align");
@@ -2272,7 +2239,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@@ -2284,7 +2251,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .string_literal,
.main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@@ -2296,8 +2263,8 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
_ = try c.addToken(.period, ".");
const res = try c.addNode(.{
.tag = .enum_literal,
- .main_token = try c.addTokenFmt(.identifier, "{}", .{some}),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .main_token = try c.addTokenFmt(.identifier, "{s}", .{@tagName(some)}),
+ .data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@@ -2307,12 +2274,12 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const fn_proto = try blk: {
if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
- if (payload.params.len < 2)
+ if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_simple,
.main_token = fn_token,
.data = .{
- .lhs = first,
+ .lhs = params.items[0],
.rhs = return_type_expr,
},
})
@@ -2329,13 +2296,13 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
},
});
}
- if (payload.params.len < 2)
+ if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_one,
.main_token = fn_token,
.data = .{
.lhs = try c.addExtra(std.zig.ast.Node.FnProtoOne{
- .param = first,
+ .param = params.items[0],
.align_expr = align_expr,
.section_expr = section_expr,
.callconv_expr = callconv_expr,
@@ -2383,35 +2350,10 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
const fn_token = try c.addToken(.keyword_fn, "fn");
_ = try c.addIdentifier(payload.name);
- _ = try c.addToken(.l_paren, "(");
- const first = if (payload.params.len != 0) blk: {
- const param = payload.params[0];
- if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
- if (param.name) |some| {
- _ = try c.addIdentifier(some);
- _ = try c.addToken(.colon, ":");
- }
- break :blk try renderNode(c, param.type);
- } else 0;
-
+ const params = try renderParams(c, payload.params, false);
+ defer params.deinit();
var span: NodeSubRange = undefined;
- if (payload.params.len > 1) {
- var params = try c.gpa.alloc(NodeIndex, payload.params.len);
- defer c.gpa.free(params);
-
- params[0] = first;
- for (payload.params[1..]) |param, i| {
- _ = try c.addToken(.comma, ",");
- if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
- if (param.name) |some| {
- _ = try c.addIdentifier(some);
- _ = try c.addToken(.colon, ":");
- }
- params[i + 1] = try renderNode(c, param.type);
- }
- span = try c.listToSpan(params);
- }
- _ = try c.addToken(.r_paren, ")");
+ if (params.items.len > 1) span = try c.listToSpan(params.items);
const callconv_expr = blk: {
_ = try c.addToken(.keyword_callconv, "callconv");
@@ -2420,7 +2362,7 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .enum_literal,
.main_token = try c.addToken(.identifier, "Inline"),
- .data = .{ .lhs = undefined, .rhs = undefined },
+ .data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@@ -2428,13 +2370,13 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
const return_type_expr = try renderNode(c, payload.return_type);
const fn_proto = try blk: {
- if (payload.params.len < 2)
+ if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_one,
.main_token = fn_token,
.data = .{
.lhs = try c.addExtra(std.zig.ast.Node.FnProtoOne{
- .param = first,
+ .param = params.items[0],
.align_expr = 0,
.section_expr = 0,
.callconv_expr = callconv_expr,
@@ -2467,3 +2409,32 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
},
});
}
+
+fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {
+ _ = try c.addToken(.l_paren, "(");
+ var rendered = std.ArrayList(NodeIndex).init(c.gpa);
+ errdefer rendered.deinit();
+ try rendered.ensureCapacity(std.math.max(params.len, 1));
+
+ for (params) |param, i| {
+ if (i != 0) _ = try c.addToken(.comma, ",");
+ if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
+ if (param.name) |some| {
+ _ = try c.addIdentifier(some);
+ _ = try c.addToken(.colon, ":");
+ }
+ if (param.type.tag() == .@"anytype") {
+ _ = try c.addToken(.keyword_anytype, "anytype");
+ continue;
+ }
+ rendered.appendAssumeCapacity(try renderNode(c, param.type));
+ }
+ if (is_var_args) {
+ if (params.len != 0) _ = try c.addToken(.comma, ",");
+ _ = try c.addToken(.ellipsis3, "...");
+ }
+ _ = try c.addToken(.r_paren, ")");
+
+ if (rendered.items.len == 0) rendered.appendAssumeCapacity(0);
+ return rendered;
+}
src/translate_c.zig
@@ -990,7 +990,10 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
}));
}
- break :blk try Tag.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));
+ break :blk try Tag.@"enum".create(c.arena, .{
+ .int_type = init_arg_expr,
+ .fields = try c.arena.dupe(ast.Payload.Enum.Field, fields.items),
+ });
} else blk: {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
break :blk Tag.opaque_literal.init();
@@ -1540,8 +1543,8 @@ fn finishBoolExpr(
}
},
.Pointer => {
- // node == null
- return Tag.equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
+ // node != null
+ return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
},
.Typedef => {
const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
@@ -1675,7 +1678,8 @@ fn transStringLiteralAsArray(
const ty = expr_base.getType().getTypePtr();
const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
- const arr_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());
+ const elem_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());
+ const arr_type = try Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_type });
const init_list = try c.arena.alloc(Node, array_size);
var i: c_uint = 0;
@@ -2668,7 +2672,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
return Tag.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used));
},
.LNot => {
- return Tag.not.create(c.arena, try transExpr(c, scope, op_expr, .used));
+ return Tag.not.create(c.arena, try transBoolExpr(c, scope, op_expr, .used));
},
.Extension => {
return transExpr(c, scope, stmt.getSubExpr(), used);
@@ -2969,8 +2973,15 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node {
fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {
// TODO use something more accurate
- const dbl = stmt.getValueAsApproximateDouble();
- const node = try transCreateNodeNumber(c, dbl, .float);
+ var dbl = stmt.getValueAsApproximateDouble();
+ const is_negative = dbl < 0;
+ if (is_negative) dbl = -dbl;
+ const str = try std.fmt.allocPrint(c.arena, "{d}", .{dbl});
+ var node = if (dbl == std.math.floor(dbl))
+ try Tag.integer_literal.create(c.arena, str)
+ else
+ try Tag.float_literal.create(c.arena, str);
+ if (is_negative) node = try Tag.negate.create(c.arena, node);
return maybeSuppressResult(c, scope, used, node);
}
@@ -3004,8 +3015,11 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang
},
};
defer cond_scope.deinit();
- const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
- var then_body = try Tag.identifier.create(c.arena, mangled_name);
+
+ const cond_ident = try Tag.identifier.create(c.arena, mangled_name);
+ const ty = getExprQualType(c, cond_expr).getTypePtr();
+ const cond_node = try finishBoolExpr(c, &cond_scope.base, cond_expr.getBeginLoc(), ty, cond_ident, .used);
+ var then_body = cond_ident;
if (!res_is_bool and isBoolRes(init_node)) {
then_body = try Tag.bool_to_int.create(c.arena, then_body);
}
@@ -3489,11 +3503,13 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {
else => @compileError("unimplemented"),
}
- const big: math.big.int.Const = .{ .limbs = limbs, .positive = !is_negative };
+ const big: math.big.int.Const = .{ .limbs = limbs, .positive = true };
const str = big.toStringAlloc(c.arena, 10, false) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
};
- return Tag.integer_literal.create(c.arena, str);
+ const res = try Tag.integer_literal.create(c.arena, str);
+ if (is_negative) return Tag.negate.create(c.arena, res);
+ return res;
}
fn transCreateNodeNumber(c: *Context, num: anytype, num_kind: enum { int, float }) !Node {
@@ -3567,7 +3583,7 @@ fn transCreateNodeShiftOp(
const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);
const rhs = try transExprCoercing(c, scope, rhs_expr, .used);
- const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
+ const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs });
return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
}
@@ -3622,7 +3638,8 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
const is_volatile = child_qt.isVolatileQualified();
const elem_type = try transQualType(c, child_qt, source_loc);
if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
- return Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ return Tag.optional_type.create(c.arena, ptr);
}
return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });