translate-c: render unary ops

This commit is contained in:
Veikka Tuominen 2021-02-13 21:24:40 +02:00
parent 1147ecc5fd
commit 685778c5a7
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 234 additions and 32 deletions

View File

@ -3049,7 +3049,7 @@ fn maybeSuppressResult(
result: Node,
) TransError!Node {
if (used == .used) return result;
return Tag.ignore.create(c.arena, result);
return Tag.discard.create(c.arena, result);
}
fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
@ -4127,7 +4127,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var last = node;
while (true) {
// suppress result
const ignore = try Tag.ignore.create(c.arena, last);
const ignore = try Tag.discard.create(c.arena, last);
try block_scope.statements.append(ignore);
last = try parseCCondExpr(c, m, scope);

View File

@ -60,6 +60,7 @@ pub const Node = extern union {
tuple,
container_init,
std_meta_cast,
/// _ = operand;
discard,
// a + b
@ -67,43 +68,30 @@ pub const Node = extern union {
// a = b
add_assign,
// c = (a = b)
add_assign_value,
add_wrap,
add_wrap_assign,
add_wrap_assign_value,
sub,
sub_assign,
sub_assign_value,
sub_wrap,
sub_wrap_assign,
sub_wrap_assign_value,
mul,
mul_assign,
mul_assign_value,
mul_wrap,
mul_wrap_assign,
mul_wrap_assign_value,
div,
div_assign,
div_assign_value,
shl,
shl_assign,
shl_assign_value,
shr,
shr_assign,
shr_assign_value,
mod,
mod_assign,
mod_assign_value,
@"and",
and_assign,
and_assign_value,
@"or",
or_assign,
or_assign_value,
xor,
xor_assign,
xor_assign_value,
less_than,
less_than_equal,
greater_than,
@ -207,9 +195,6 @@ pub const Node = extern union {
/// [1]type{val} ** count
array_filler,
/// _ = operand;
ignore,
pub const last_no_payload_tag = Tag.usingnamespace_builtins;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@ -249,7 +234,6 @@ pub const Node = extern union {
.while_true,
.if_not_break,
.switch_else,
.ignore,
.block_single,
.std_meta_sizeof,
.bool_to_int,
@ -260,43 +244,30 @@ pub const Node = extern union {
.add,
.add_assign,
.add_assign_value,
.add_wrap,
.add_wrap_assign,
.add_wrap_assign_value,
.sub,
.sub_assign,
.sub_assign_value,
.sub_wrap,
.sub_wrap_assign,
.sub_wrap_assign_value,
.mul,
.mul_assign,
.mul_assign_value,
.mul_wrap,
.mul_wrap_assign,
.mul_wrap_assign_value,
.div,
.div_assign,
.div_assign_value,
.shl,
.shl_assign,
.shl_assign_value,
.shr,
.shr_assign,
.shr_assign_value,
.mod,
.mod_assign,
.mod_assign_value,
.@"and",
.and_assign,
.and_assign_value,
.@"or",
.or_assign,
.or_assign_value,
.xor,
.xor_assign,
.xor_assign_value,
.less_than,
.less_than_equal,
.greater_than,
@ -869,6 +840,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.rhs = undefined,
},
}),
.noreturn_type => return try c.addNode(.{
.tag = .identifier,
.main_token = try c.addToken(.identifier, "noreturn"),
.data = .{
.lhs = undefined,
.rhs = undefined,
},
}),
.type => {
const payload = node.castTag(.type).?.data;
return c.addNode(.{
@ -880,6 +859,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
},
});
},
.log2_int_type => {
const payload = node.castTag(.log2_int_type).?.data;
return c.addNode(.{
.tag = .identifier,
.main_token = try c.addTokenFmt(.identifier, "u{d}", .{payload}),
.data = .{
.lhs = undefined,
.rhs = undefined,
},
});
},
.identifier => {
const payload = node.castTag(.identifier).?.data;
return c.addNode(.{
@ -1058,6 +1048,51 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.ptr_cast).?.data;
return renderBuiltinCall(c, "@ptrCast", &.{ payload.lhs, payload.rhs });
},
.sizeof => {
const payload = node.castTag(.sizeof).?.data;
return renderBuiltinCall(c, "@sizeOf", &.{payload});
},
.alignof => {
const payload = node.castTag(.alignof).?.data;
return renderBuiltinCall(c, "@alignOf", &.{payload});
},
.typeof => {
const payload = node.castTag(.typeof).?.data;
return renderBuiltinCall(c, "@TypeOf", &.{payload});
},
.negate => return renderPrefixOp(c, node, .negation, .minus, "-"),
.negate_wrap => return renderPrefixOp(c, node, .negation_wrap, .minus_percent, "-%"),
.bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"),
.not => return renderPrefixOp(c, node, .bool_not, .bang, "!"),
.optional_type => return renderPrefixOp(c, node, .optional_type, .question_mark, "?"),
.address_of => return renderPrefixOp(c, node, .address_of, .ampersand, "&"),
.deref => {
const payload = node.castTag(.deref).?.data;
const operand = try renderNodeGrouped(c, payload);
const deref_tok = try c.addToken(.period_asterisk, ".*");
return c.addNode(.{
.tag = .deref,
.main_token = deref_tok,
.data = .{
.lhs = operand,
.rhs = undefined,
},
});
},
.unwrap => {
const payload = node.castTag(.unwrap).?.data;
const operand = try renderNodeGrouped(c, payload);
const period = try c.addToken(.period, ".");
const question_mark = try c.addToken(.question_mark, "?");
return c.addNode(.{
.tag = .unwrap_optional,
.main_token = period,
.data = .{
.lhs = operand,
.rhs = question_mark,
},
});
},
else => return c.addNode(.{
.tag = .identifier,
.main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}),
@ -1069,6 +1104,173 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
}
}
fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
switch (node.tag()) {
.null_literal,
.undefined_literal,
.true_literal,
.false_literal,
.return_void,
.zero_literal,
.one_literal,
.void_type,
.noreturn_type,
.@"anytype",
.div_trunc,
.rem,
.int_cast,
.as,
.truncate,
.bit_cast,
.float_cast,
.float_to_int,
.int_to_float,
.int_to_enum,
.int_to_ptr,
.std_mem_zeroes,
.std_math_Log2Int,
.log2_int_type,
.ptr_to_int,
.enum_to_int,
.sizeof,
.alignof,
.typeof,
.std_meta_sizeof,
.std_meta_cast,
.std_mem_zeroinit,
.integer_literal,
.float_literal,
.string_literal,
.char_literal,
.identifier,
.field_access,
.ptr_cast,
.type,
.array_access,
.align_cast,
=> {
// no grouping needed
return renderNode(c, node);
},
.negate,
.negate_wrap,
.bit_not,
.opaque_literal,
.not,
.optional_type,
.address_of,
.unwrap,
.deref,
.empty_array,
.block_single,
.bool_to_int,
.add,
.add_wrap,
.sub,
.sub_wrap,
.mul,
.mul_wrap,
.div,
.shl,
.shr,
.mod,
.@"and",
.@"or",
.xor,
.less_than,
.less_than_equal,
.greater_than,
.greater_than_equal,
.equal,
.not_equal,
.bit_and,
.bit_or,
.bit_xor,
.empty_block,
.array_cat,
.array_filler,
.@"if",
.call,
.@"enum",
.@"struct",
.@"union",
.array_init,
.tuple,
.container_init,
.block,
.c_pointer,
.single_pointer,
.array_type,
=> return c.addNode(.{
.tag = .grouped_expression,
.main_token = try c.addToken(.l_paren, "("),
.data = .{
.lhs = try renderNode(c, node),
.rhs = try c.addToken(.r_paren, ")"),
},
}),
.ellipsis3,
.switch_prong,
.warning,
.var_decl,
.func,
.fail_decl,
.arg_redecl,
.alias,
.var_simple,
.pub_var_simple,
.enum_redecl,
.@"while",
.@"switch",
.@"break",
.break_val,
.pub_inline_fn,
.discard,
.@"continue",
.@"return",
.usingnamespace_builtins,
.while_true,
.if_not_break,
.switch_else,
.add_assign,
.add_wrap_assign,
.sub_assign,
.sub_wrap_assign,
.mul_assign,
.mul_wrap_assign,
.div_assign,
.shl_assign,
.shr_assign,
.mod_assign,
.and_assign,
.or_assign,
.xor_assign,
.bit_and_assign,
.bit_or_assign,
.bit_xor_assign,
.assign,
=> {
// these should never appear in places where grouping might be needed.
unreachable;
},
}
}
fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex {
const payload = @fieldParentPtr(Payload.UnOp, "base", node.ptr_otherwise).data;
const tok = try c.addToken(tok_tag, bytes);
const operand = try renderNodeGrouped(c, payload);
return c.addNode(.{
.tag = tag,
.main_token = tok,
.data = .{
.lhs = operand,
.rhs = undefined,
},
});
}
fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeIndex {
const import_tok = try c.addToken(.builtin, "@import");
_ = try c.addToken(.l_paren, "(");