translate-c more macro ops

This commit is contained in:
Vexu 2020-03-06 11:03:56 +02:00 committed by Andrew Kelley
parent 7df9169081
commit 83d27f71ef
2 changed files with 103 additions and 150 deletions

View File

@ -610,7 +610,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
try transCreateNodeUndefinedLiteral(c);
} else if (storage_class != .Extern) {
eq_tok = try appendToken(c, .Equal, "=");
init_node = try transCreateNodeTypeIdentifier(c, "undefined");
init_node = try transCreateNodeIdentifierUnchecked(c, "undefined");
}
const linksection_expr = blk: {
@ -4814,7 +4814,7 @@ fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node {
return &identifier.base;
}
fn transCreateNodeTypeIdentifier(c: *Context, name: []const u8) !*ast.Node {
fn transCreateNodeIdentifierUnchecked(c: *Context, name: []const u8) !*ast.Node {
const token_index = try appendTokenFmt(c, .Identifier, "{}", .{name});
const identifier = try c.a().create(ast.Node.Identifier);
identifier.* = .{
@ -5368,15 +5368,15 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return parseCNumLit(c, tok, source, source_loc);
},
// eventually this will be replaced by std.c.parse which will handle these correctly
.Keyword_void => return transCreateNodeTypeIdentifier(c, "c_void"),
.Keyword_bool => return transCreateNodeTypeIdentifier(c, "bool"),
.Keyword_double => return transCreateNodeTypeIdentifier(c, "f64"),
.Keyword_long => return transCreateNodeTypeIdentifier(c, "c_long"),
.Keyword_int => return transCreateNodeTypeIdentifier(c, "c_int"),
.Keyword_float => return transCreateNodeTypeIdentifier(c, "f32"),
.Keyword_short => return transCreateNodeTypeIdentifier(c, "c_short"),
.Keyword_char => return transCreateNodeTypeIdentifier(c, "c_char"),
.Keyword_unsigned => return transCreateNodeTypeIdentifier(c, "c_uint"),
.Keyword_void => return transCreateNodeIdentifierUnchecked(c, "c_void"),
.Keyword_bool => return transCreateNodeIdentifierUnchecked(c, "bool"),
.Keyword_double => return transCreateNodeIdentifierUnchecked(c, "f64"),
.Keyword_long => return transCreateNodeIdentifierUnchecked(c, "c_long"),
.Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),
.Keyword_float => return transCreateNodeIdentifierUnchecked(c, "f32"),
.Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
.Keyword_char => return transCreateNodeIdentifierUnchecked(c, "c_char"),
.Keyword_unsigned => return transCreateNodeIdentifierUnchecked(c, "c_uint"),
.Identifier => {
const mangled_name = scope.getAlias(source[tok.start..tok.end]);
return transCreateNodeIdentifier(c, mangled_name);
@ -5512,6 +5512,8 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
var node = try parseCPrimaryExpr(c, it, source, source_loc, scope);
while (true) {
const tok = it.next().?;
var op_token: ast.TokenIndex = undefined;
var op_id: ast.Node.InfixOp.Op = undefined;
switch (tok.id) {
.Period => {
const name_tok = it.next().?;
@ -5528,6 +5530,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}
node = try transCreateNodeFieldAccess(c, node, source[name_tok.start..name_tok.end]);
continue;
},
.Arrow => {
const name_tok = it.next().?;
@ -5542,9 +5545,16 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
);
return error.ParseError;
}
const deref = try transCreateNodePtrDeref(c, node);
// deref is often used together with casts so we group the lhs expression
const group = try c.a().create(ast.Node.GroupedExpression);
group.* = .{
.lparen = try appendToken(c, .LParen, "("),
.expr = node,
.rparen = try appendToken(c, .RParen, ")"),
};
const deref = try transCreateNodePtrDeref(c, &group.base);
node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]);
continue;
},
.Asterisk => {
if (it.peek().?.id == .RParen) {
@ -5568,161 +5578,57 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return &ptr.base;
} else {
// expr * expr
const op_token = try appendToken(c, .Asterisk, "*");
const rhs = try parseCPrimaryExpr(c, it, source, source_loc, scope);
const mul_node = try c.a().create(ast.Node.InfixOp);
mul_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BitShiftLeft,
.rhs = rhs,
};
node = &mul_node.base;
op_token = try appendToken(c, .Asterisk, "*");
op_id = .BitShiftLeft;
}
},
.AngleBracketAngleBracketLeft => {
const op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const bitshift_node = try c.a().create(ast.Node.InfixOp);
bitshift_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BitShiftLeft,
.rhs = rhs,
};
node = &bitshift_node.base;
op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
op_id = .BitShiftLeft;
},
.AngleBracketAngleBracketRight => {
const op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const bitshift_node = try c.a().create(ast.Node.InfixOp);
bitshift_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BitShiftRight,
.rhs = rhs,
};
node = &bitshift_node.base;
op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
op_id = .BitShiftRight;
},
.Pipe => {
const op_token = try appendToken(c, .Pipe, "|");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const or_node = try c.a().create(ast.Node.InfixOp);
or_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BitOr,
.rhs = rhs,
};
node = &or_node.base;
op_token = try appendToken(c, .Pipe, "|");
op_id = .BitOr;
},
.Ampersand => {
const op_token = try appendToken(c, .Ampersand, "&");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const bitand_node = try c.a().create(ast.Node.InfixOp);
bitand_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BitAnd,
.rhs = rhs,
};
node = &bitand_node.base;
op_token = try appendToken(c, .Ampersand, "&");
op_id .BitAnd;
},
.Plus => {
const op_token = try appendToken(c, .Plus, "+");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const add_node = try c.a().create(ast.Node.InfixOp);
add_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .Add,
.rhs = rhs,
};
node = &add_node.base;
op_token = try appendToken(c, .Plus, "+");
op_id = .Add;
},
.Minus => {
const op_token = try appendToken(c, .Minus, "-");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const sub_node = try c.a().create(ast.Node.InfixOp);
sub_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .Sub,
.rhs = rhs,
};
node = &sub_node.base;
op_token = try appendToken(c, .Minus, "-");
op_id .Sub;
},
.AmpersandAmpersand => {
const op_token = try appendToken(c, .Keyword_and, "and");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const and_node = try c.a().create(ast.Node.InfixOp);
and_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BoolAnd,
.rhs = rhs,
};
node = &and_node.base;
op_token = try appendToken(c, .Keyword_and, "and");
op_id = .BoolAnd;
},
.PipePipe => {
const op_token = try appendToken(c, .Keyword_or, "or");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const or_node = try c.a().create(ast.Node.InfixOp);
or_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .BoolOr,
.rhs = rhs,
};
node = &or_node.base;
op_token = try appendToken(c, .Keyword_or, "or");
op_id = .BoolOr;
},
.AngleBracketRight => {
const op_token = try appendToken(c, .AngleBracketRight, ">");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const and_node = try c.a().create(ast.Node.InfixOp);
and_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .GreaterThan,
.rhs = rhs,
};
node = &and_node.base;
op_token = try appendToken(c, .AngleBracketRight, ">");
op_id = .GreaterThan;
},
.AngleBracketRightEqual => {
const op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const and_node = try c.a().create(ast.Node.InfixOp);
and_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .GreaterOrEqual,
.rhs = rhs,
};
node = &and_node.base;
op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
op_id = .GreaterOrEqual;
},
.AngleBracketLeft => {
const op_token = try appendToken(c, .AngleBracketLeft, "<");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const and_node = try c.a().create(ast.Node.InfixOp);
and_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .LessThan,
.rhs = rhs,
};
node = &and_node.base;
op_token = try appendToken(c, .AngleBracketLeft, "<");
op_id = .LessThan;
},
.AngleBracketLeftEqual => {
const op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const and_node = try c.a().create(ast.Node.InfixOp);
and_node.* = .{
.op_token = op_token,
.lhs = node,
.op = .LessOrEqual,
.rhs = rhs,
};
node = &and_node.base;
op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
op_id = .LessOrEqual;
},
.LBracket => {
const arr_node = try transCreateNodeArrayAccess(c, node);
@ -5740,6 +5646,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
);
return error.ParseError;
}
continue;
},
.LParen => {
const call_node = try transCreateNodeFnCall(c, node);
@ -5765,12 +5672,39 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}
call_node.rtoken = try appendToken(c, .RParen, ")");
node = &call_node.base;
continue;
},
.BangEqual => {
op_token = try appendToken(c, .BangEqual, "!=");
op_id = .BangEqual;
},
.EqualEqual => {
op_token = try appendToken(c, .EqualEqual, "==");
op_id = .EqualEqual;
},
.Slash => {
// unsigned/float division uses the operator
op_id = .Div;
op_token = try appendToken(c, .Slash, "/");
},
.Percent => {
// unsigned/float division uses the operator
op_id = .Mod;
op_token = try appendToken(c, .Percent, "%");
},
else => {
_ = it.prev();
return node;
},
}
const op_node = try c.a().create(ast.Node.InfixOp);
op_node.* = .{
.op_token = op_token,
.lhs = node,
.op = op_id,
.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
};
node = &op_node.base;
}
}
@ -5788,14 +5722,33 @@ fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
return &node.base;
},
.Plus => return try parseCPrefixOpExpr(c, it, source, source_loc, scope),
.Tilde => {
const node = try transCreateNodePrefixOp(c, .BitNot, .Tilde, "~");
node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
return &node.base;
},
.Asterisk => {
const prefix_op_expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
return try transCreateNodePtrDeref(c, prefix_op_expr);
// deref is often used together with casts so we group the lhs expression
const group = try c.a().create(ast.Node.GroupedExpression);
group.* = .{
.lparen = try appendToken(c, .LParen, "("),
.expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
.rparen = try appendToken(c, .RParen, ")"),
};
return try transCreateNodePtrDeref(c, &group.base);
},
.Ampersand => {
// address of is often used together with casts so we group the rhs expression
const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&");
const group = try c.a().create(ast.Node.GroupedExpression);
group.* = .{
.lparen = try appendToken(c, .LParen, "("),
.expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
.rparen = try appendToken(c, .RParen, ")"),
};
node.rhs = &group.base;
return &node.base;
},
else => {
_ = it.prev();

View File

@ -5,7 +5,7 @@ const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro comma operator",
\\#define foo (foo, bar)
\\#define bar(x) (x, 3, 4, 5 * 6, baz(1, 2), 2, baz(1,2))
\\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
, &[_][]const u8{
\\pub const foo = blk: {
\\ _ = foo;
@ -14,12 +14,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
\\ return blk: {
\\ _ = x;
\\ _ = &(x);
\\ _ = 3;
\\ _ = 4;
\\ _ = 4 == 4;
\\ _ = 5 * 6;
\\ _ = baz(1, 2);
\\ _ = 2;
\\ _ = 2 % 2;
\\ break :blk baz(1, 2);
\\ };
\\}
@ -1993,7 +1993,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const DOT = a.b;
,
\\pub const ARROW = a.*.b;
\\pub const ARROW = (a).*.b;
});
cases.add("array access",