aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/translate_c.zig960
-rw-r--r--src/translate_c/ast.zig41
2 files changed, 307 insertions, 694 deletions
diff --git a/src/translate_c.zig b/src/translate_c.zig
index 0a20d5e6d5..9ef4788ba7 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -3512,86 +3512,48 @@ fn transCreateNodeNumber(c: *Context, int: anytype) !Node {
return Node.int_literal.create(c.arena, str);
}
-fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_alias: *ast.Node.FnProto) !*ast.Node {
+fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node {
const scope = &c.global_scope.base;
- const pub_tok = try appendToken(c, .Keyword_pub, "pub");
- const fn_tok = try appendToken(c, .Keyword_fn, "fn");
- const name_tok = try appendIdentifier(c, name);
- _ = try appendToken(c, .LParen, "(");
-
- var fn_params = std.ArrayList(ast.Node.FnProto.ParamDecl).init(c.gpa);
+ var fn_params = std.ArrayList(Node).init(c.gpa);
defer fn_params.deinit();
for (proto_alias.params()) |param, i| {
- if (i != 0) {
- _ = try appendToken(c, .Comma, ",");
- }
- const param_name_tok = param.name_token orelse
- try appendTokenFmt(c, .Identifier, "arg_{d}", .{c.getMangle()});
+ const param_name = param.name orelse
+ try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()});
- _ = try appendToken(c, .Colon, ":");
-
- (try fn_params.addOne()).* = .{
- .doc_comments = null,
- .comptime_token = null,
- .noalias_token = param.noalias_token,
- .name_token = param_name_tok,
- .param_type = param.param_type,
- };
+ try fn_params.append(.{
+ .name = param_name,
+ .type = param.type,
+ .is_noalias = param.is_noalias,
+ });
}
- _ = try appendToken(c, .RParen, ")");
-
- _ = try appendToken(c, .Keyword_callconv, "callconv");
- _ = try appendToken(c, .LParen, "(");
- const callconv_expr = try transCreateNodeEnumLiteral(c, "Inline");
- _ = try appendToken(c, .RParen, ")");
-
- const block_lbrace = try appendToken(c, .LBrace, "{");
-
- const return_kw = try appendToken(c, .Keyword_return, "return");
- const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.getInitNode().?);
-
- const call_expr = try c.createCall(unwrap_expr, fn_params.items.len);
- const call_params = call_expr.params();
+ const init = if (value.castTag(.var_decl)) |v|
+ v.data.init
+ else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
+ v.data.init
+ else
+ unreachable;
+ const unwrap_expr = try Node.unwrap.create(c.arena, init);
+ const call_params = try c.arena.alloc(Node, fn_params.items.len);
for (fn_params.items) |param, i| {
- if (i != 0) {
- _ = try appendToken(c, .Comma, ",");
- }
- call_params[i] = try transCreateNodeIdentifier(c, tokenSlice(c, param.name_token.?));
+ call_params[i] = try Node.identifier.create(c.arena, param.name);
}
- call_expr.rtoken = try appendToken(c, .RParen, ")");
-
- const return_expr = try ast.Node.ControlFlowExpression.create(c.arena, .{
- .ltoken = return_kw,
- .tag = .Return,
- }, .{
- .rhs = &call_expr.base,
+ const call_expr = try Node.call.create(c.arean, .{
+ .lhs = unwrap_expr,
+ .args = call_params,
});
- _ = try appendToken(c, .Semicolon, ";");
+ const return_expr = try Node.@"return".create(c.arean, call_expr);
+ const block = try Node.block_single.create(c.arean, return_expr);
- const block = try ast.Node.Block.alloc(c.arena, 1);
- block.* = .{
- .lbrace = block_lbrace,
- .statements_len = 1,
- .rbrace = try appendToken(c, .RBrace, "}"),
- };
- block.statements()[0] = &return_expr.base;
-
- const fn_proto = try ast.Node.FnProto.create(c.arena, .{
- .params_len = fn_params.items.len,
- .fn_token = fn_tok,
+ return Node.pub_inline_fn.create(c.arena, .{
+ .name = name,
+ .params = try c.arena.dupe(ast.Node.Param, fn_params.items),
.return_type = proto_alias.return_type,
- }, .{
- .visib_token = pub_tok,
- .name_token = name_tok,
- .body_node = &block.base,
- .callconv_expr = callconv_expr,
+ .body = block,
});
- mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
- return &fn_proto.base;
}
fn transCreateNodeShiftOp(
@@ -4108,27 +4070,13 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
const scope = &c.global_scope.base;
- const visib_tok = try appendToken(c, .Keyword_pub, "pub");
- const mut_tok = try appendToken(c, .Keyword_const, "const");
- const name_tok = try appendIdentifier(c, m.name);
- const eq_token = try appendToken(c, .Equal, "=");
-
const init_node = try parseCExpr(c, m, scope);
const last = m.next().?;
if (last != .Eof and last != .Nl)
return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
- const semicolon_token = try appendToken(c, .Semicolon, ";");
- const node = try ast.Node.VarDecl.create(c.arena, .{
- .name_token = name_tok,
- .mut_token = mut_tok,
- .semicolon_token = semicolon_token,
- }, .{
- .visib_token = visib_tok,
- .eq_token = eq_token,
- .init_node = init_node,
- });
- _ = try c.global_scope.macro_table.put(m.name, &node.base);
+ const var_decl = try Node.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
+ _ = try c.global_scope.macro_table.put(m.name, var_decl);
}
fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
@@ -4136,16 +4084,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
defer block_scope.deinit();
const scope = &block_scope.base;
- const pub_tok = try appendToken(c, .Keyword_pub, "pub");
- const fn_tok = try appendToken(c, .Keyword_fn, "fn");
- const name_tok = try appendIdentifier(c, m.name);
- _ = try appendToken(c, .LParen, "(");
-
if (m.next().? != .LParen) {
return m.fail(c, "unable to translate C expr: expected '('", .{});
}
- var fn_params = std.ArrayList(ast.Node.FnProto.ParamDecl).init(c.gpa);
+ var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
defer fn_params.deinit();
while (true) {
@@ -4153,120 +4096,78 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
_ = m.next();
const mangled_name = try block_scope.makeMangledName(c, m.slice());
- const param_name_tok = try appendIdentifier(c, mangled_name);
- _ = try appendToken(c, .Colon, ":");
-
- const any_type = try c.arena.create(ast.Node.OneToken);
- any_type.* = .{
- .base = .{ .tag = .AnyType },
- .token = try appendToken(c, .Keyword_anytype, "anytype"),
- };
-
- (try fn_params.addOne()).* = .{
- .doc_comments = null,
- .comptime_token = null,
- .noalias_token = null,
- .name_token = param_name_tok,
- .param_type = .{ .any_type = &any_type.base },
- };
+ try fn_params.append(.{
+ .is_noalias = false,
+ .name = mangled_name,
+ .type = Node.@"anytype".init(),
+ });
if (m.peek().? != .Comma) break;
_ = m.next();
- _ = try appendToken(c, .Comma, ",");
}
if (m.next().? != .RParen) {
return m.fail(c, "unable to translate C expr: expected ')'", .{});
}
- _ = try appendToken(c, .RParen, ")");
-
- _ = try appendToken(c, .Keyword_callconv, "callconv");
- _ = try appendToken(c, .LParen, "(");
- const callconv_expr = try transCreateNodeEnumLiteral(c, "Inline");
- _ = try appendToken(c, .RParen, ")");
-
- const type_of = try c.createBuiltinCall("@TypeOf", 1);
-
- const return_kw = try appendToken(c, .Keyword_return, "return");
const expr = try parseCExpr(c, m, scope);
const last = m.next().?;
if (last != .Eof and last != .Nl)
return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
- _ = try appendToken(c, .Semicolon, ";");
- const type_of_arg = if (!expr.tag.isBlock()) expr else blk: {
- const stmts = expr.blockStatements();
- const blk_last = stmts[stmts.len - 1];
- const br = blk_last.cast(ast.Node.ControlFlowExpression).?;
- break :blk br.getRHS().?;
- };
- type_of.params()[0] = type_of_arg;
- type_of.rparen_token = try appendToken(c, .RParen, ")");
- const return_expr = try ast.Node.ControlFlowExpression.create(c.arena, .{
- .ltoken = return_kw,
- .tag = .Return,
- }, .{
- .rhs = expr,
- });
+ const typeof_arg = if (expr.castTag(.block)) |some| blk: {
+ const stmts = some.data.stmts;
+ const blk_last = stmts[stmts.len - 1];
+ const br = blk_last.castTag(.break_val).?;
+ break :blk br.data;
+ } else expr;
+ const typeof = try Node.typeof.create(c.arean, typeof_arg);
+ const return_expr = try Node.@"return".create(c.arena, expr);
try block_scope.statements.append(&return_expr.base);
- const block_node = try block_scope.complete(c);
- const fn_proto = try ast.Node.FnProto.create(c.arena, .{
- .fn_token = fn_tok,
- .params_len = fn_params.items.len,
- .return_type = .{ .Explicit = &type_of.base },
- }, .{
- .visib_token = pub_tok,
- .name_token = name_tok,
- .body_node = block_node,
- .callconv_expr = callconv_expr,
+
+ const fn_decl = try Node.pub_inline_fn.create(c.arena, .{
+ .name = m.name,
+ .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
+ .return_type = typeof,
+ .body = try block_scope.complete(c),
});
- mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
-
_ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);
}
const ParseError = Error || error{ParseError};
-fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
// TODO parseCAssignExpr here
const node = try parseCCondExpr(c, m, scope);
if (m.next().? != .Comma) {
m.i -= 1;
return node;
}
- _ = try appendToken(c, .Semicolon, ";");
var block_scope = try Scope.Block.init(c, scope, true);
defer block_scope.deinit();
var last = node;
while (true) {
// suppress result
- const lhs = try transCreateNodeIdentifier(c, "_");
- const op_token = try appendToken(c, .Equal, "=");
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .Assign },
- .op_token = op_token,
- .lhs = lhs,
- .rhs = last,
- };
- try block_scope.statements.append(&op_node.base);
+ const ignore = try Node.ignore.create(c.arena, last);
+ try block_scope.statements.append(ignore);
last = try parseCCondExpr(c, m, scope);
- _ = try appendToken(c, .Semicolon, ";");
if (m.next().? != .Comma) {
m.i -= 1;
break;
}
}
- const break_node = try transCreateNodeBreak(c, block_scope.label, last);
- try block_scope.statements.append(&break_node.base);
+ const break_node = try Node.break_val.create(c.arena, .{
+ .label = block_scope.label,
+ .val = last,
+ });
+ try block_scope.statements.append(break_node);
return try block_scope.complete(c);
}
-fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
+fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
var lit_bytes = m.slice();
switch (m.list[m.i].id) {
@@ -4286,11 +4187,10 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
}
if (suffix == .none) {
- return transCreateNodeInt(c, lit_bytes);
+ return transCreateNodeNumber(c, lit_bytes);
}
- const cast_node = try c.createBuiltinCall("@as", 2);
- cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) {
+ const type_node = try Node.type.create(c.arena, switch (suffix) {
.u => "c_uint",
.l => "c_long",
.lu => "c_ulong",
@@ -4304,27 +4204,22 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
.llu => 3,
else => unreachable,
}];
- _ = try appendToken(c, .Comma, ",");
- cast_node.params()[1] = try transCreateNodeInt(c, lit_bytes);
- cast_node.rparen_token = try appendToken(c, .RParen, ")");
- return &cast_node.base;
+ const rhs = try transCreateNodeNumber(c, lit_bytes);
+ return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
},
.FloatLiteral => |suffix| {
if (lit_bytes[0] == '.')
lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
if (suffix == .none) {
- return transCreateNodeFloat(c, lit_bytes);
+ return transCreateNodeNumber(c, lit_bytes);
}
- const cast_node = try c.createBuiltinCall("@as", 2);
- cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) {
+ const type_node = try Node.type.create(c.arena, switch (suffix) {
.f => "f32",
.l => "c_longdouble",
else => unreachable,
});
- _ = try appendToken(c, .Comma, ",");
- cast_node.params()[1] = try transCreateNodeFloat(c, lit_bytes[0 .. lit_bytes.len - 1]);
- cast_node.rparen_token = try appendToken(c, .RParen, ")");
- return &cast_node.base;
+ const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1]);
+ return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
},
else => unreachable,
}
@@ -4490,79 +4385,62 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
return bytes[0..i];
}
-fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
const tok = m.next().?;
const slice = m.slice();
switch (tok) {
.CharLiteral => {
if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
- const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, m));
- const node = try c.arena.create(ast.Node.OneToken);
- node.* = .{
- .base = .{ .tag = .CharLiteral },
- .token = token,
- };
- return &node.base;
+ return Node.char_literal.create(c.arena, try zigifyEscapeSequences(c, m));
} else {
- const token = try appendTokenFmt(c, .IntegerLiteral, "0x{x}", .{slice[1 .. slice.len - 1]});
- const node = try c.arena.create(ast.Node.OneToken);
- node.* = .{
- .base = .{ .tag = .IntegerLiteral },
- .token = token,
- };
- return &node.base;
+ const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
+ return Node.int_literal.create(c.arena, str);
}
},
.StringLiteral => {
- const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, m));
- const node = try c.arena.create(ast.Node.OneToken);
- node.* = .{
- .base = .{ .tag = .StringLiteral },
- .token = token,
- };
- return &node.base;
+ return Node.string_literal.create(c.arena, try zigifyEscapeSequences(c, m));
},
.IntegerLiteral, .FloatLiteral => {
return parseCNumLit(c, m);
},
// eventually this will be replaced by std.c.parse which will handle these correctly
- .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, "u8"),
+ .Keyword_void => return Node.type.create(c.arena, "c_void"),
+ .Keyword_bool => return Node.type.create(c.arena, "bool"),
+ .Keyword_double => return Node.type.create(c.arena, "f64"),
+ .Keyword_long => return Node.type.create(c.arena, "c_long"),
+ .Keyword_int => return Node.type.create(c.arena, "c_int"),
+ .Keyword_float => return Node.type.create(c.arena, "f32"),
+ .Keyword_short => return Node.type.create(c.arena, "c_short"),
+ .Keyword_char => return Node.type.create(c.arena, "u8"),
.Keyword_unsigned => if (m.next()) |t| switch (t) {
- .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),
- .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_ushort"),
- .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_uint"),
+ .Keyword_char => return Node.type.create(c.arena, "u8"),
+ .Keyword_short => return Node.type.create(c.arena, "c_ushort"),
+ .Keyword_int => return Node.type.create(c.arena, "c_uint"),
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
_ = m.next();
- return transCreateNodeIdentifierUnchecked(c, "c_ulonglong");
- } else return transCreateNodeIdentifierUnchecked(c, "c_ulong"),
+ return Node.type.create(c.arena, "c_ulonglong");
+ } else return Node.type.create(c.arena, "c_ulong"),
else => {
m.i -= 1;
- return transCreateNodeIdentifierUnchecked(c, "c_uint");
+ return Node.type.create(c.arena, "c_uint");
},
} else {
- return transCreateNodeIdentifierUnchecked(c, "c_uint");
+ return Node.type.create(c.arena, "c_uint");
},
.Keyword_signed => if (m.next()) |t| switch (t) {
- .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "i8"),
- .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
- .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),
+ .Keyword_char => return Node.type.create(c.arena, "i8"),
+ .Keyword_short => return Node.type.create(c.arena, "c_short"),
+ .Keyword_int => return Node.type.create(c.arena, "c_int"),
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
_ = m.next();
- return transCreateNodeIdentifierUnchecked(c, "c_longlong");
- } else return transCreateNodeIdentifierUnchecked(c, "c_long"),
+ return Node.type.create(c.arena, "c_longlong");
+ } else return Node.type.create(c.arena, "c_long"),
else => {
m.i -= 1;
- return transCreateNodeIdentifierUnchecked(c, "c_int");
+ return Node.type.create(c.arena, "c_int");
},
} else {
- return transCreateNodeIdentifierUnchecked(c, "c_int");
+ return Node.type.create(c.arena, "c_int");
},
.Keyword_enum, .Keyword_struct, .Keyword_union => {
// struct Foo will be declared as struct_Foo by transRecordDecl
@@ -4572,17 +4450,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
return error.ParseError;
}
- const ident_token = try appendTokenFmt(c, .Identifier, "{s}_{s}", .{ slice, m.slice() });
- const identifier = try c.arena.create(ast.Node.OneToken);
- identifier.* = .{
- .base = .{ .tag = .Identifier },
- .token = ident_token,
- };
- return &identifier.base;
+ const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
+ return Node.identifier.create(c.arena, name);
},
.Identifier => {
const mangled_name = scope.getAlias(slice);
- return transCreateNodeIdentifier(c, checkForBuiltinTypedef(mangled_name) orelse mangled_name);
+ return Node.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
},
.LParen => {
const inner_node = try parseCExpr(c, m, scope);
@@ -4612,10 +4485,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
},
else => return inner_node,
}
-
- // hack to get zig fmt to render a comma in builtin calls
- _ = try appendToken(c, .Comma, ",");
-
const node_to_cast = try parseCExpr(c, m, scope);
if (saw_l_paren and m.next().? != .RParen) {
@@ -4623,28 +4492,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
return error.ParseError;
}
- const lparen = try appendToken(c, .LParen, "(");
-
- //(@import("std").meta.cast(dest, x))
- const import_fn_call = try c.createBuiltinCall("@import", 1);
- const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
- import_fn_call.params()[0] = std_node;
- import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
- const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta");
- const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "cast");
-
- const cast_fn_call = try c.createCall(outer_field_access, 2);
- cast_fn_call.params()[0] = inner_node;
- cast_fn_call.params()[1] = node_to_cast;
- cast_fn_call.rtoken = try appendToken(c, .RParen, ")");
-
- const group_node = try c.arena.create(ast.Node.GroupedExpression);
- group_node.* = .{
- .lparen = lparen,
- .expr = &cast_fn_call.base,
- .rparen = try appendToken(c, .RParen, ")"),
- };
- return &group_node.base;
+ return Node.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
},
else => {
try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});
@@ -4653,447 +4501,255 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
}
}
-fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCPrimaryExprInner(c, m, scope);
// In C the preprocessor would handle concatting strings while expanding macros.
// This should do approximately the same by concatting any strings and identifiers
// after a primary expression.
while (true) {
- var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.Tag = undefined;
switch (m.peek().?) {
.StringLiteral, .Identifier => {},
else => break,
}
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .ArrayCat },
- .op_token = try appendToken(c, .PlusPlus, "++"),
- .lhs = node,
- .rhs = try parseCPrimaryExprInner(c, m, scope),
- };
- node = &op_node.base;
+ node = try Node.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });
}
return node;
}
-fn nodeIsInfixOp(tag: ast.Node.Tag) bool {
- return switch (tag) {
- .Add,
- .AddWrap,
- .ArrayCat,
- .ArrayMult,
- .Assign,
- .AssignBitAnd,
- .AssignBitOr,
- .AssignBitShiftLeft,
- .AssignBitShiftRight,
- .AssignBitXor,
- .AssignDiv,
- .AssignSub,
- .AssignSubWrap,
- .AssignMod,
- .AssignAdd,
- .AssignAddWrap,
- .AssignMul,
- .AssignMulWrap,
- .BangEqual,
- .BitAnd,
- .BitOr,
- .BitShiftLeft,
- .BitShiftRight,
- .BitXor,
- .BoolAnd,
- .BoolOr,
- .Div,
- .EqualEqual,
- .ErrorUnion,
- .GreaterOrEqual,
- .GreaterThan,
- .LessOrEqual,
- .LessThan,
- .MergeErrorSets,
- .Mod,
- .Mul,
- .MulWrap,
- .Period,
- .Range,
- .Sub,
- .SubWrap,
- .UnwrapOptional,
- .Catch,
- => true,
-
- else => false,
- };
-}
-
-fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
+fn macroBoolToInt(c: *Context, node: Node) !Node {
if (!isBoolRes(node)) {
- if (!nodeIsInfixOp(node.tag)) return node;
-
- const group_node = try c.arena.create(ast.Node.GroupedExpression);
- group_node.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = node,
- .rparen = try appendToken(c, .RParen, ")"),
- };
- return &group_node.base;
+ return node;
}
- const builtin_node = try c.createBuiltinCall("@boolToInt", 1);
- builtin_node.params()[0] = node;
- builtin_node.rparen_token = try appendToken(c, .RParen, ")");
- return &builtin_node.base;
+ return Node.bool_to_int.create(c.arena, node);
}
-fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
+fn macroIntToBool(c: *Context, node: Node) !Node {
if (isBoolRes(node)) {
- if (!nodeIsInfixOp(node.tag)) return node;
-
- const group_node = try c.arena.create(ast.Node.GroupedExpression);
- group_node.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = node,
- .rparen = try appendToken(c, .RParen, ")"),
- };
- return &group_node.base;
+ return node;
}
- const op_token = try appendToken(c, .BangEqual, "!=");
- const zero = try transCreateNodeInt(c, 0);
- const res = try c.arena.create(ast.Node.SimpleInfixOp);
- res.* = .{
- .base = .{ .tag = .BangEqual },
- .op_token = op_token,
- .lhs = node,
- .rhs = zero,
- };
- const group_node = try c.arena.create(ast.Node.GroupedExpression);
- group_node.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = &res.base,
- .rparen = try appendToken(c, .RParen, ")"),
- };
- return &group_node.base;
-}
-
-fn macroGroup(c: *Context, node: *ast.Node) !*ast.Node {
- if (!nodeIsInfixOp(node.tag)) return node;
-
- const group_node = try c.arena.create(ast.Node.GroupedExpression);
- group_node.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = node,
- .rparen = try appendToken(c, .RParen, ")"),
- };
- return &group_node.base;
+ return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
}
-fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
const node = try parseCOrExpr(c, m, scope);
if (m.peek().? != .QuestionMark) {
return node;
}
_ = m.next();
- // must come immediately after expr
- _ = try appendToken(c, .RParen, ")");
- const if_node = try transCreateNodeIf(c);
- if_node.condition = node;
- if_node.body = try parseCOrExpr(c, m, scope);
+ const then_body = try parseCOrExpr(c, m, scope);
if (m.next().? != .Colon) {
try m.fail(c, "unable to translate C expr: expected ':'", .{});
return error.ParseError;
}
- if_node.@"else" = try transCreateNodeElse(c);
- if_node.@"else".?.body = try parseCCondExpr(c, m, scope);
- return &if_node.base;
+ const else_body = try parseCCondExpr(c, m, scope);
+ return Node.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
}
-fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCAndExpr(c, m, scope);
while (m.next().? == .PipePipe) {
- const lhs_node = try macroIntToBool(c, node);
- const op_token = try appendToken(c, .Keyword_or, "or");
- const rhs_node = try parseCAndExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .BoolOr },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroIntToBool(c, rhs_node),
- };
- node = &op_node.base;
+ const lhs = try macroIntToBool(c, node);
+ const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope));
+ node = try Node.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
}
-fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCBitOrExpr(c, m, scope);
while (m.next().? == .AmpersandAmpersand) {
- const lhs_node = try macroIntToBool(c, node);
- const op_token = try appendToken(c, .Keyword_and, "and");
- const rhs_node = try parseCBitOrExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .BoolAnd },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroIntToBool(c, rhs_node),
- };
- node = &op_node.base;
+ const lhs = try macroIntToBool(c, node);
+ const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope));
+ node = try Node.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
}
-fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCBitXorExpr(c, m, scope);
while (m.next().? == .Pipe) {
- const lhs_node = try macroBoolToInt(c, node);
- const op_token = try appendToken(c, .Pipe, "|");
- const rhs_node = try parseCBitXorExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .BitOr },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCBitXorExpr(c, m, scope));
+ node = try Node.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
}
-fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCBitAndExpr(c, m, scope);
while (m.next().? == .Caret) {
- const lhs_node = try macroBoolToInt(c, node);
- const op_token = try appendToken(c, .Caret, "^");
- const rhs_node = try parseCBitAndExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .BitXor },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCBitAndExpr(c, m, scope));
+ node = try Node.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
}
-fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCEqExpr(c, m, scope);
while (m.next().? == .Ampersand) {
- const lhs_node = try macroBoolToInt(c, node);
- const op_token = try appendToken(c, .Ampersand, "&");
- const rhs_node = try parseCEqExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = .BitAnd },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCEqExpr(c, m, scope));
+ node = try Node.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
}
-fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCRelExpr(c, m, scope);
while (true) {
- var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.Tag = undefined;
switch (m.peek().?) {
.BangEqual => {
- op_token = try appendToken(c, .BangEqual, "!=");
- op_id = .BangEqual;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
+ node = try Node.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.EqualEqual => {
- op_token = try appendToken(c, .EqualEqual, "==");
- op_id = .EqualEqual;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
+ node = try Node.equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
- _ = m.next();
- const lhs_node = try macroBoolToInt(c, node);
- const rhs_node = try parseCRelExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = op_id },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
}
}
-fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCShiftExpr(c, m, scope);
while (true) {
- var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.Tag = undefined;
switch (m.peek().?) {
.AngleBracketRight => {
- op_token = try appendToken(c, .AngleBracketRight, ">");
- op_id = .GreaterThan;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
+ node = try Node.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketRightEqual => {
- op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
- op_id = .GreaterOrEqual;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
+ node = try Node.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketLeft => {
- op_token = try appendToken(c, .AngleBracketLeft, "<");
- op_id = .LessThan;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
+ node = try Node.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketLeftEqual => {
- op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
- op_id = .LessOrEqual;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
+ node = try Node.less_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
- _ = m.next();
- const lhs_node = try macroBoolToInt(c, node);
- const rhs_node = try parseCShiftExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = op_id },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
}
}
-fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCAddSubExpr(c, m, scope);
while (true) {
- var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.Tag = undefined;
switch (m.peek().?) {
.AngleBracketAngleBracketLeft => {
- op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
- op_id = .BitShiftLeft;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
+ node = try Node.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketAngleBracketRight => {
- op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
- op_id = .BitShiftRight;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
+ node = try Node.shr.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
- _ = m.next();
- const lhs_node = try macroBoolToInt(c, node);
- const rhs_node = try parseCAddSubExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = op_id },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
}
}
-fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCMulExpr(c, m, scope);
while (true) {
- var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.Tag = undefined;
switch (m.peek().?) {
.Plus => {
- op_token = try appendToken(c, .Plus, "+");
- op_id = .Add;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
+ node = try Node.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.Minus => {
- op_token = try appendToken(c, .Minus, "-");
- op_id = .Sub;
+ _ = m.next();
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
+ node = try Node.sub.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
- _ = m.next();
- const lhs_node = try macroBoolToInt(c, node);
- const rhs_node = try parseCMulExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = op_id },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
}
}
-fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCUnaryExpr(c, m, scope);
while (true) {
- var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.Tag = undefined;
switch (m.next().?) {
.Asterisk => {
if (m.peek().? == .RParen) {
// type *)
- // hack to get zig fmt to render a comma in builtin calls
- _ = try appendToken(c, .Comma, ",");
-
// last token of `node`
const prev_id = m.list[m.i - 1].id;
if (prev_id == .Keyword_void) {
- const ptr = try transCreateNodePtrType(c, false, false, .Asterisk);
- ptr.rhs = node;
- const optional_node = try transCreateNodeSimplePrefixOp(c, .OptionalType, .QuestionMark, "?");
- optional_node.rhs = &ptr.base;
- return &optional_node.base;
+ const ptr = try Node.single_pointer.create(c.arena, .{
+ .is_const = false,
+ .is_volatile = false,
+ .elem_type = node,
+ });
+ return Node.optional_type.create(c.arena, ptr);
} else {
- const ptr = try transCreateNodePtrType(c, false, false, Token.Id.Identifier);
- ptr.rhs = node;
- return &ptr.base;
+ return Node.c_pointer.create(c.arena, .{
+ .is_const = false,
+ .is_volatile = false,
+ .elem_type = node,
+ });
}
} else {
// expr * expr
- op_token = try appendToken(c, .Asterisk, "*");
- op_id = .BitShiftLeft;
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
+ node = try Node.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
},
.Slash => {
- op_id = .Div;
- op_token = try appendToken(c, .Slash, "/");
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
+ node = try Node.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.Percent => {
- op_id = .Mod;
- op_token = try appendToken(c, .Percent, "%");
+ const lhs = try macroBoolToInt(c, node);
+ const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
+ node = try Node.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => {
m.i -= 1;
return node;
},
}
- const lhs_node = try macroBoolToInt(c, node);
- const rhs_node = try parseCUnaryExpr(c, m, scope);
- const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
- op_node.* = .{
- .base = .{ .tag = op_id },
- .op_token = op_token,
- .lhs = lhs_node,
- .rhs = try macroBoolToInt(c, rhs_node),
- };
- node = &op_node.base;
}
}
-fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var node = try parseCPrimaryExpr(c, m, scope);
while (true) {
switch (m.next().?) {
@@ -5103,38 +4759,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
return error.ParseError;
}
- node = try transCreateNodeFieldAccess(c, node, m.slice());
- continue;
+ const ident = try Node.identifier.create(c.arena, m.slice());
+ node = try Node.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
},
.Arrow => {
if (m.next().? != .Identifier) {
try m.fail(c, "unable to translate C expr: expected identifier", .{});
return error.ParseError;
}
- const deref = try transCreateNodePtrDeref(c, node);
- node = try transCreateNodeFieldAccess(c, deref, m.slice());
- continue;
+
+ const deref = try Node.deref.create(c.arena, node);
+ const ident = try Node.identifier.create(c.arena, m.slice());
+ node = try Node.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });
},
.LBracket => {
- const arr_node = try transCreateNodeArrayAccess(c, node);
- arr_node.index_expr = try parseCExpr(c, m, scope);
- arr_node.rtoken = try appendToken(c, .RBracket, "]");
- node = &arr_node.base;
- if (m.next().? != .RBracket) {
- try m.fail(c, "unable to translate C expr: expected ']'", .{});
- return error.ParseError;
- }
- continue;
+ const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
+ node = try Node.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
},
.LParen => {
- _ = try appendToken(c, .LParen, "(");
- var call_params = std.ArrayList(*ast.Node).init(c.gpa);
+ var call_params = std.ArrayList(Node).init(c.gpa);
defer call_params.deinit();
while (true) {
const arg = try parseCCondExpr(c, m, scope);
try call_params.append(arg);
switch (m.next().?) {
- .Comma => _ = try appendToken(c, .Comma, ","),
+ .Comma => {},
.RParen => break,
else => {
try m.fail(c, "unable to translate C expr: expected ',' or ')'", .{});
@@ -5142,32 +4791,17 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
},
}
}
- const call_node = try ast.Node.Call.alloc(c.arena, call_params.items.len);
- call_node.* = .{
- .lhs = node,
- .params_len = call_params.items.len,
- .async_token = null,
- .rtoken = try appendToken(c, .RParen, ")"),
- };
- mem.copy(*ast.Node, call_node.params(), call_params.items);
- node = &call_node.base;
- continue;
+ node = try Node.call.create(c.arena, .{ .lhs = node, .rhs = try c.arena.dupe(Node, call_params.items) });
},
.LBrace => {
- // must come immediately after `node`
- _ = try appendToken(c, .Comma, ",");
-
- const dot = try appendToken(c, .Period, ".");
- _ = try appendToken(c, .LBrace, "{");
-
- var init_vals = std.ArrayList(*ast.Node).init(c.gpa);
+ var init_vals = std.ArrayList(Node).init(c.gpa);
defer init_vals.deinit();
while (true) {
const val = try parseCCondExpr(c, m, scope);
try init_vals.append(val);
switch (m.next().?) {
- .Comma => _ = try appendToken(c, .Comma, ","),
+ .Comma => {},
.RBrace => break,
else => {
try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});
@@ -5175,29 +4809,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
},
}
}
- const tuple_node = try ast.Node.StructInitializerDot.alloc(c.arena, init_vals.items.len);
- tuple_node.* = .{
- .dot = dot,
- .list_len = init_vals.items.len,
- .rtoken = try appendToken(c, .RBrace, "}"),
- };
- mem.copy(*ast.Node, tuple_node.list(), init_vals.items);
-
- //(@import("std").mem.zeroInit(T, .{x}))
- const import_fn_call = try c.createBuiltinCall("@import", 1);
- const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
- import_fn_call.params()[0] = std_node;
- import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
- const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem");
- const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroInit");
-
- const zero_init_call = try c.createCall(outer_field_access, 2);
- zero_init_call.params()[0] = node;
- zero_init_call.params()[1] = &tuple_node.base;
- zero_init_call.rtoken = try appendToken(c, .RParen, ")");
-
- node = &zero_init_call.base;
- continue;
+ const tuple_node = try Node.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));
+ node = try Node.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
},
.PlusPlus, .MinusMinus => {
try m.fail(c, "TODO postfix inc/dec expr", .{});
@@ -5211,35 +4824,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
}
}
-fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
+fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
switch (m.next().?) {
.Bang => {
- const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!");
- node.rhs = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
- return &node.base;
+ const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
+ return Node.not.create(c.arena, operand);
},
.Minus => {
- const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-");
- node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- return &node.base;
+ const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
+ return Node.negate.create(c.arena, operand);
},
.Plus => return try parseCUnaryExpr(c, m, scope),
.Tilde => {
- const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~");
- node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- return &node.base;
+ const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
+ return Node.bit_not.create(c.arena, operand);
},
.Asterisk => {
- const node = try macroGroup(c, try parseCUnaryExpr(c, m, scope));
- return try transCreateNodePtrDeref(c, node);
+ const operand = try parseCUnaryExpr(c, m, scope);
+ return Node.deref.create(c.arena, operand);
},
.Ampersand => {
- const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&");
- node.rhs = try macroGroup(c, try parseCUnaryExpr(c, m, scope));
- return &node.base;
+ const operand = try parseCUnaryExpr(c, m, scope);
+ return Node.address_of.create(c.arena, operand);
},
.Keyword_sizeof => {
- const inner = if (m.peek().? == .LParen) blk: {
+ const operand = if (m.peek().? == .LParen) blk: {
_ = m.next();
// C grammar says this should be 'type-name' but we have to
// use parseCMulExpr to correctly handle pointer types.
@@ -5251,18 +4860,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
break :blk inner;
} else try parseCUnaryExpr(c, m, scope);
- //(@import("std").meta.sizeof(dest, x))
- const import_fn_call = try c.createBuiltinCall("@import", 1);
- const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
- import_fn_call.params()[0] = std_node;
- import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
- const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta");
- const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "sizeof");
-
- const sizeof_call = try c.createCall(outer_field_access, 1);
- sizeof_call.params()[0] = inner;
- sizeof_call.rtoken = try appendToken(c, .RParen, ")");
- return &sizeof_call.base;
+ return Node.std_meta_sizeof.create(c.arena, operand);
},
.Keyword_alignof => {
// TODO this won't work if using <stdalign.h>'s
@@ -5273,16 +4871,13 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
}
// C grammar says this should be 'type-name' but we have to
// use parseCMulExpr to correctly handle pointer types.
- const inner = try parseCMulExpr(c, m, scope);
+ const operand = try parseCMulExpr(c, m, scope);
if (m.next().? != .RParen) {
try m.fail(c, "unable to translate C expr: expected ')'", .{});
return error.ParseError;
}
- const builtin_call = try c.createBuiltinCall("@alignOf", 1);
- builtin_call.params()[0] = inner;
- builtin_call.rparen_token = try appendToken(c, .RParen, ")");
- return &builtin_call.base;
+ return Node.alignof.create(c.arena, operand);
},
.PlusPlus, .MinusMinus => {
try m.fail(c, "TODO unary inc/dec expr", .{});
@@ -5295,50 +4890,40 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
}
}
-fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {
- const tok = c.token_locs.items[token];
- const slice = c.source_buffer.items[tok.start..tok.end];
- return if (mem.startsWith(u8, slice, "@\""))
- slice[2 .. slice.len - 1]
- else
- slice;
-}
-
-fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
- switch (node.tag) {
- .ContainerDecl,
- .AddressOf,
- .Await,
- .BitNot,
- .BoolNot,
- .OptionalType,
- .Negation,
- .NegationWrap,
- .Resume,
- .Try,
- .ArrayType,
- .ArrayTypeSentinel,
- .PtrType,
- .SliceType,
+fn getContainer(c: *Context, node: Node) ?Node {
+ switch (node.tag()) {
+ .@"union",
+ .@"struct",
+ .@"enum",
+ .address_of,
+ .bit_not,
+ .not,
+ .optional_type,
+ .negate,
+ .negate_wrap,
+ .array_type,
+ .c_pointer,
+ .single_pointer,
=> return node,
- .Identifier => {
- const ident = node.castTag(.Identifier).?;
- if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {
- if (value.cast(ast.Node.VarDecl)) |var_decl|
- return getContainer(c, var_decl.getInitNode().?);
+ .identifier => {
+ const ident = node.castTag(.identifier).?;
+ if (c.global_scope.sym_table.get(ident.data)) |value| {
+ if (value.castTag(.var_decl)) |var_decl|
+ return getContainer(c, var_decl.data.init);
+ if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |var_decl|
+ return getContainer(c, var_decl.data.init);
}
},
- .Period => {
- const infix = node.castTag(.Period).?;
+ .field_access => {
+ const infix = node.castTag(.field_access).?;
- if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
- if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
- for (container.fieldsAndDecls()) |field_ref| {
- const field = field_ref.cast(ast.Node.ContainerField).?;
- const ident = infix.rhs.castTag(.Identifier).?;
- if (mem.eql(u8, tokenSlice(c, field.name_token), tokenSlice(c, ident.token))) {
+ if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
+ if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
+ for (container.data.fields) |field| {
+ const ident = infix.data.rhs.castTag(.identifier).?;
+ if (mem.eql(u8, field.data.name, field.data)) {
return getContainer(c, field.type_expr.?);
}
}
@@ -5351,22 +4936,20 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
return null;
}
-fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
- if (ref.castTag(.Identifier)) |ident| {
- if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {
- if (value.cast(ast.Node.VarDecl)) |var_decl| {
- if (var_decl.getTypeNode()) |ty|
- return getContainer(c, ty);
+fn getContainerTypeOf(c: *Context, ref: Node) ?Node {
+ if (ref.castTag(.identifier)) |ident| {
+ if (c.global_scope.sym_table.get(ident.data)) |value| {
+ if (value.castTag(.var_decl)) |var_decl| {
+ return getContainer(c, var_decl.data.type);
}
}
- } else if (ref.castTag(.Period)) |infix| {
- if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
- if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
- for (container.fieldsAndDecls()) |field_ref| {
- const field = field_ref.cast(ast.Node.ContainerField).?;
- const ident = infix.rhs.castTag(.Identifier).?;
- if (mem.eql(u8, tokenSlice(c, field.name_token), tokenSlice(c, ident.token))) {
- return getContainer(c, field.type_expr.?);
+ } else if (ref.castTag(.field_access)) |infix| {
+ if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
+ if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
+ for (container.data.fields) |field| {
+ const ident = infix.data.rhs.castTag(.identifier).?;
+ if (mem.eql(u8, field.name, ident.data)) {
+ return getContainer(c, field.type);
}
}
} else
@@ -5376,11 +4959,16 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
return null;
}
-fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto {
- const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getInitNode().? else return null;
+fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
+ const init = if (value.castTag(.var_decl)) |v|
+ v.data.init
+ else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
+ v.data.init
+ else
+ return null;
if (getContainerTypeOf(c, init)) |ty_node| {
- if (ty_node.castTag(.OptionalType)) |prefix| {
- if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| {
+ if (ty_node.castTag(.optional_type)) |prefix| {
+ if (prefix.data.castTag(.func)) |fn_proto| {
return fn_proto;
}
}
diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig
index d62e83ea6a..1cf014e5dc 100644
--- a/src/translate_c/ast.zig
+++ b/src/translate_c/ast.zig
@@ -47,7 +47,6 @@ pub const Node = extern union {
field_access,
array_access,
call,
- std_mem_zeroes,
var_decl,
func,
warning,
@@ -57,6 +56,7 @@ pub const Node = extern union {
@"struct",
@"union",
array_init,
+ tuple,
container_init,
std_meta_cast,
discard,
@@ -162,6 +162,8 @@ pub const Node = extern union {
deref,
block,
+ /// { operand }
+ block_single,
@"break",
sizeof,
@@ -173,8 +175,12 @@ pub const Node = extern union {
single_pointer,
array_type,
- /// @import("std").mem.zeroes(T)
+ /// @import("std").meta.sizeof(operand)
+ std_meta_sizeof,
+ /// @import("std").mem.zeroes(operand)
std_mem_zeroes,
+ /// @import("std").mem.zeroInit(lhs, rhs)
+ std_mem_zeroinit,
// pub const name = @compileError(msg);
fail_decl,
// var actual = mangled;
@@ -188,6 +194,9 @@ pub const Node = extern union {
/// pub const enum_field_name = @enumToInt(enum_name.field_name);
enum_redecl,
+ /// pub inline fn name(params) return_type body
+ pub_inline_fn,
+
/// [0]type{}
empty_array,
/// [1]type{val} ** count
@@ -195,6 +204,7 @@ pub const Node = extern union {
/// _ = operand;
ignore,
+ @"anytype",
pub const last_no_payload_tag = Tag.usingnamespace_builtins;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -213,6 +223,7 @@ pub const Node = extern union {
.one_literal,
.void_type,
.noreturn_type,
+ .@"anytype",
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
.std_mem_zeroes,
@@ -234,6 +245,7 @@ pub const Node = extern union {
.if_not_break,
.switch_else,
.ignore,
+ .block_single,
=> Payload.UnOp,
.add,
@@ -302,6 +314,8 @@ pub const Node = extern union {
.field_access,
.assign,
.align_cast,
+ .array_access,
+ .std_mem_zeroinit,
=> Payload.BinOp,
.number_literal,
@@ -325,7 +339,7 @@ pub const Node = extern union {
.func => Payload.Func,
.@"enum" => Payload.Enum,
.@"struct", .@"union" => Payload.Record,
- .array_init => Payload.ArrayInit,
+ .array_init, .tuple => Payload.ArrayInit,
.container_init => Payload.ContainerInit,
.std_meta_cast => Payload.Infix,
.block => Payload.Block,
@@ -336,6 +350,7 @@ pub const Node = extern union {
.typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
.enum_redecl => Payload.EnumRedecl,
.array_filler => Payload.ArrayFiller,
+ .pub_inline_fn => Payload.PubInlineFn,
};
}
@@ -488,12 +503,12 @@ pub const Payload = struct {
body: ?Node,
alignment: ?c_uint,
},
+ };
- pub const Param = struct {
- is_noalias: bool,
- name: ?[]const u8,
- type: Node,
- };
+ pub const Param = struct {
+ is_noalias: bool,
+ name: ?[]const u8,
+ type: Node,
};
pub const Enum = struct {
@@ -598,6 +613,16 @@ pub const Payload = struct {
count: usize,
},
};
+
+ pub const PubInlineFn = struct {
+ base: Node,
+ data: struct {
+ name: []const u8,
+ params: []Param,
+ return_type: Node,
+ body: Node,
+ },
+ };
};
/// Converts the nodes into a Zig ast.