authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-11 17:44:04+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:06+02:00
log66bbd75a8346b8a292f0d95d4b60a5d7d11b73b2
tree5fcf37036c3dd1c35db561115906cf0d76bc76ca
parentc30c2f7c133861a8749a9ffbc2bf6a49d9c6283e
signature Commit is signed but in an unrecognized format.

translate-c: convert macro translation


2 files changed, 307 insertions(+), 694 deletions(-)

src/translate_c.zig+274-686
......@@ -3512,86 +3512,48 @@ fn transCreateNodeNumber(c: *Context, int: anytype) !Node {
35123512 return Node.int_literal.create(c.arena, str);
35133513}
35143514
3515fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_alias: *ast.Node.FnProto) !*ast.Node {
3515fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node {
35163516 const scope = &c.global_scope.base;
35173517
3518 const pub_tok = try appendToken(c, .Keyword_pub, "pub");
3519 const fn_tok = try appendToken(c, .Keyword_fn, "fn");
3520 const name_tok = try appendIdentifier(c, name);
3521 _ = try appendToken(c, .LParen, "(");
3522
3523 var fn_params = std.ArrayList(ast.Node.FnProto.ParamDecl).init(c.gpa);
3518 var fn_params = std.ArrayList(Node).init(c.gpa);
35243519 defer fn_params.deinit();
35253520
35263521 for (proto_alias.params()) |param, i| {
3527 if (i != 0) {
3528 _ = try appendToken(c, .Comma, ",");
3529 }
3530 const param_name_tok = param.name_token orelse
3531 try appendTokenFmt(c, .Identifier, "arg_{d}", .{c.getMangle()});
3522 const param_name = param.name orelse
3523 try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()});
35323524
3533 _ = try appendToken(c, .Colon, ":");
3534
3535 (try fn_params.addOne()).* = .{
3536 .doc_comments = null,
3537 .comptime_token = null,
3538 .noalias_token = param.noalias_token,
3539 .name_token = param_name_tok,
3540 .param_type = param.param_type,
3541 };
3525 try fn_params.append(.{
3526 .name = param_name,
3527 .type = param.type,
3528 .is_noalias = param.is_noalias,
3529 });
35423530 }
35433531
3544 _ = try appendToken(c, .RParen, ")");
3545
3546 _ = try appendToken(c, .Keyword_callconv, "callconv");
3547 _ = try appendToken(c, .LParen, "(");
3548 const callconv_expr = try transCreateNodeEnumLiteral(c, "Inline");
3549 _ = try appendToken(c, .RParen, ")");
3550
3551 const block_lbrace = try appendToken(c, .LBrace, "{");
3552
3553 const return_kw = try appendToken(c, .Keyword_return, "return");
3554 const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.getInitNode().?);
3555
3556 const call_expr = try c.createCall(unwrap_expr, fn_params.items.len);
3557 const call_params = call_expr.params();
3532 const init = if (value.castTag(.var_decl)) |v|
3533 v.data.init
3534 else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
3535 v.data.init
3536 else
3537 unreachable;
35583538
3539 const unwrap_expr = try Node.unwrap.create(c.arena, init);
3540 const call_params = try c.arena.alloc(Node, fn_params.items.len);
35593541 for (fn_params.items) |param, i| {
3560 if (i != 0) {
3561 _ = try appendToken(c, .Comma, ",");
3562 }
3563 call_params[i] = try transCreateNodeIdentifier(c, tokenSlice(c, param.name_token.?));
3542 call_params[i] = try Node.identifier.create(c.arena, param.name);
35643543 }
3565 call_expr.rtoken = try appendToken(c, .RParen, ")");
3566
3567 const return_expr = try ast.Node.ControlFlowExpression.create(c.arena, .{
3568 .ltoken = return_kw,
3569 .tag = .Return,
3570 }, .{
3571 .rhs = &call_expr.base,
3544 const call_expr = try Node.call.create(c.arean, .{
3545 .lhs = unwrap_expr,
3546 .args = call_params,
35723547 });
3573 _ = try appendToken(c, .Semicolon, ";");
3548 const return_expr = try Node.@"return".create(c.arean, call_expr);
3549 const block = try Node.block_single.create(c.arean, return_expr);
35743550
3575 const block = try ast.Node.Block.alloc(c.arena, 1);
3576 block.* = .{
3577 .lbrace = block_lbrace,
3578 .statements_len = 1,
3579 .rbrace = try appendToken(c, .RBrace, "}"),
3580 };
3581 block.statements()[0] = &return_expr.base;
3582
3583 const fn_proto = try ast.Node.FnProto.create(c.arena, .{
3584 .params_len = fn_params.items.len,
3585 .fn_token = fn_tok,
3551 return Node.pub_inline_fn.create(c.arena, .{
3552 .name = name,
3553 .params = try c.arena.dupe(ast.Node.Param, fn_params.items),
35863554 .return_type = proto_alias.return_type,
3587 }, .{
3588 .visib_token = pub_tok,
3589 .name_token = name_tok,
3590 .body_node = &block.base,
3591 .callconv_expr = callconv_expr,
3555 .body = block,
35923556 });
3593 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
3594 return &fn_proto.base;
35953557}
35963558
35973559fn transCreateNodeShiftOp(
......@@ -4108,27 +4070,13 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
41084070fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
41094071 const scope = &c.global_scope.base;
41104072
4111 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
4112 const mut_tok = try appendToken(c, .Keyword_const, "const");
4113 const name_tok = try appendIdentifier(c, m.name);
4114 const eq_token = try appendToken(c, .Equal, "=");
4115
41164073 const init_node = try parseCExpr(c, m, scope);
41174074 const last = m.next().?;
41184075 if (last != .Eof and last != .Nl)
41194076 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
41204077
4121 const semicolon_token = try appendToken(c, .Semicolon, ";");
4122 const node = try ast.Node.VarDecl.create(c.arena, .{
4123 .name_token = name_tok,
4124 .mut_token = mut_tok,
4125 .semicolon_token = semicolon_token,
4126 }, .{
4127 .visib_token = visib_tok,
4128 .eq_token = eq_token,
4129 .init_node = init_node,
4130 });
4131 _ = try c.global_scope.macro_table.put(m.name, &node.base);
4078 const var_decl = try Node.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
4079 _ = try c.global_scope.macro_table.put(m.name, var_decl);
41324080}
41334081
41344082fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
......@@ -4136,16 +4084,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
41364084 defer block_scope.deinit();
41374085 const scope = &block_scope.base;
41384086
4139 const pub_tok = try appendToken(c, .Keyword_pub, "pub");
4140 const fn_tok = try appendToken(c, .Keyword_fn, "fn");
4141 const name_tok = try appendIdentifier(c, m.name);
4142 _ = try appendToken(c, .LParen, "(");
4143
41444087 if (m.next().? != .LParen) {
41454088 return m.fail(c, "unable to translate C expr: expected '('", .{});
41464089 }
41474090
4148 var fn_params = std.ArrayList(ast.Node.FnProto.ParamDecl).init(c.gpa);
4091 var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
41494092 defer fn_params.deinit();
41504093
41514094 while (true) {
......@@ -4153,120 +4096,78 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
41534096 _ = m.next();
41544097
41554098 const mangled_name = try block_scope.makeMangledName(c, m.slice());
4156 const param_name_tok = try appendIdentifier(c, mangled_name);
4157 _ = try appendToken(c, .Colon, ":");
4158
4159 const any_type = try c.arena.create(ast.Node.OneToken);
4160 any_type.* = .{
4161 .base = .{ .tag = .AnyType },
4162 .token = try appendToken(c, .Keyword_anytype, "anytype"),
4163 };
4164
4165 (try fn_params.addOne()).* = .{
4166 .doc_comments = null,
4167 .comptime_token = null,
4168 .noalias_token = null,
4169 .name_token = param_name_tok,
4170 .param_type = .{ .any_type = &any_type.base },
4171 };
4099 try fn_params.append(.{
4100 .is_noalias = false,
4101 .name = mangled_name,
4102 .type = Node.@"anytype".init(),
4103 });
41724104
41734105 if (m.peek().? != .Comma) break;
41744106 _ = m.next();
4175 _ = try appendToken(c, .Comma, ",");
41764107 }
41774108
41784109 if (m.next().? != .RParen) {
41794110 return m.fail(c, "unable to translate C expr: expected ')'", .{});
41804111 }
41814112
4182 _ = try appendToken(c, .RParen, ")");
4183
4184 _ = try appendToken(c, .Keyword_callconv, "callconv");
4185 _ = try appendToken(c, .LParen, "(");
4186 const callconv_expr = try transCreateNodeEnumLiteral(c, "Inline");
4187 _ = try appendToken(c, .RParen, ")");
4188
4189 const type_of = try c.createBuiltinCall("@TypeOf", 1);
4190
4191 const return_kw = try appendToken(c, .Keyword_return, "return");
41924113 const expr = try parseCExpr(c, m, scope);
41934114 const last = m.next().?;
41944115 if (last != .Eof and last != .Nl)
41954116 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
4196 _ = try appendToken(c, .Semicolon, ";");
4197 const type_of_arg = if (!expr.tag.isBlock()) expr else blk: {
4198 const stmts = expr.blockStatements();
4199 const blk_last = stmts[stmts.len - 1];
4200 const br = blk_last.cast(ast.Node.ControlFlowExpression).?;
4201 break :blk br.getRHS().?;
4202 };
4203 type_of.params()[0] = type_of_arg;
4204 type_of.rparen_token = try appendToken(c, .RParen, ")");
4205 const return_expr = try ast.Node.ControlFlowExpression.create(c.arena, .{
4206 .ltoken = return_kw,
4207 .tag = .Return,
4208 }, .{
4209 .rhs = expr,
4210 });
42114117
4118 const typeof_arg = if (expr.castTag(.block)) |some| blk: {
4119 const stmts = some.data.stmts;
4120 const blk_last = stmts[stmts.len - 1];
4121 const br = blk_last.castTag(.break_val).?;
4122 break :blk br.data;
4123 } else expr;
4124 const typeof = try Node.typeof.create(c.arean, typeof_arg);
4125 const return_expr = try Node.@"return".create(c.arena, expr);
42124126 try block_scope.statements.append(&return_expr.base);
4213 const block_node = try block_scope.complete(c);
4214 const fn_proto = try ast.Node.FnProto.create(c.arena, .{
4215 .fn_token = fn_tok,
4216 .params_len = fn_params.items.len,
4217 .return_type = .{ .Explicit = &type_of.base },
4218 }, .{
4219 .visib_token = pub_tok,
4220 .name_token = name_tok,
4221 .body_node = block_node,
4222 .callconv_expr = callconv_expr,
4127
4128 const fn_decl = try Node.pub_inline_fn.create(c.arena, .{
4129 .name = m.name,
4130 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
4131 .return_type = typeof,
4132 .body = try block_scope.complete(c),
42234133 });
4224 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
4225
42264134 _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);
42274135}
42284136
42294137const ParseError = Error || error{ParseError};
42304138
4231fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4139fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
42324140 // TODO parseCAssignExpr here
42334141 const node = try parseCCondExpr(c, m, scope);
42344142 if (m.next().? != .Comma) {
42354143 m.i -= 1;
42364144 return node;
42374145 }
4238 _ = try appendToken(c, .Semicolon, ";");
42394146 var block_scope = try Scope.Block.init(c, scope, true);
42404147 defer block_scope.deinit();
42414148
42424149 var last = node;
42434150 while (true) {
42444151 // suppress result
4245 const lhs = try transCreateNodeIdentifier(c, "_");
4246 const op_token = try appendToken(c, .Equal, "=");
4247 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4248 op_node.* = .{
4249 .base = .{ .tag = .Assign },
4250 .op_token = op_token,
4251 .lhs = lhs,
4252 .rhs = last,
4253 };
4254 try block_scope.statements.append(&op_node.base);
4152 const ignore = try Node.ignore.create(c.arena, last);
4153 try block_scope.statements.append(ignore);
42554154
42564155 last = try parseCCondExpr(c, m, scope);
4257 _ = try appendToken(c, .Semicolon, ";");
42584156 if (m.next().? != .Comma) {
42594157 m.i -= 1;
42604158 break;
42614159 }
42624160 }
42634161
4264 const break_node = try transCreateNodeBreak(c, block_scope.label, last);
4265 try block_scope.statements.append(&break_node.base);
4162 const break_node = try Node.break_val.create(c.arena, .{
4163 .label = block_scope.label,
4164 .val = last,
4165 });
4166 try block_scope.statements.append(break_node);
42664167 return try block_scope.complete(c);
42674168}
42684169
4269fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
4170fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
42704171 var lit_bytes = m.slice();
42714172
42724173 switch (m.list[m.i].id) {
......@@ -4286,11 +4187,10 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
42864187 }
42874188
42884189 if (suffix == .none) {
4289 return transCreateNodeInt(c, lit_bytes);
4190 return transCreateNodeNumber(c, lit_bytes);
42904191 }
42914192
4292 const cast_node = try c.createBuiltinCall("@as", 2);
4293 cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) {
4193 const type_node = try Node.type.create(c.arena, switch (suffix) {
42944194 .u => "c_uint",
42954195 .l => "c_long",
42964196 .lu => "c_ulong",
......@@ -4304,27 +4204,22 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
43044204 .llu => 3,
43054205 else => unreachable,
43064206 }];
4307 _ = try appendToken(c, .Comma, ",");
4308 cast_node.params()[1] = try transCreateNodeInt(c, lit_bytes);
4309 cast_node.rparen_token = try appendToken(c, .RParen, ")");
4310 return &cast_node.base;
4207 const rhs = try transCreateNodeNumber(c, lit_bytes);
4208 return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
43114209 },
43124210 .FloatLiteral => |suffix| {
43134211 if (lit_bytes[0] == '.')
43144212 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
43154213 if (suffix == .none) {
4316 return transCreateNodeFloat(c, lit_bytes);
4214 return transCreateNodeNumber(c, lit_bytes);
43174215 }
4318 const cast_node = try c.createBuiltinCall("@as", 2);
4319 cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) {
4216 const type_node = try Node.type.create(c.arena, switch (suffix) {
43204217 .f => "f32",
43214218 .l => "c_longdouble",
43224219 else => unreachable,
43234220 });
4324 _ = try appendToken(c, .Comma, ",");
4325 cast_node.params()[1] = try transCreateNodeFloat(c, lit_bytes[0 .. lit_bytes.len - 1]);
4326 cast_node.rparen_token = try appendToken(c, .RParen, ")");
4327 return &cast_node.base;
4221 const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1]);
4222 return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
43284223 },
43294224 else => unreachable,
43304225 }
......@@ -4490,79 +4385,62 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
44904385 return bytes[0..i];
44914386}
44924387
4493fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4388fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
44944389 const tok = m.next().?;
44954390 const slice = m.slice();
44964391 switch (tok) {
44974392 .CharLiteral => {
44984393 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
4499 const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, m));
4500 const node = try c.arena.create(ast.Node.OneToken);
4501 node.* = .{
4502 .base = .{ .tag = .CharLiteral },
4503 .token = token,
4504 };
4505 return &node.base;
4394 return Node.char_literal.create(c.arena, try zigifyEscapeSequences(c, m));
45064395 } else {
4507 const token = try appendTokenFmt(c, .IntegerLiteral, "0x{x}", .{slice[1 .. slice.len - 1]});
4508 const node = try c.arena.create(ast.Node.OneToken);
4509 node.* = .{
4510 .base = .{ .tag = .IntegerLiteral },
4511 .token = token,
4512 };
4513 return &node.base;
4396 const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
4397 return Node.int_literal.create(c.arena, str);
45144398 }
45154399 },
45164400 .StringLiteral => {
4517 const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, m));
4518 const node = try c.arena.create(ast.Node.OneToken);
4519 node.* = .{
4520 .base = .{ .tag = .StringLiteral },
4521 .token = token,
4522 };
4523 return &node.base;
4401 return Node.string_literal.create(c.arena, try zigifyEscapeSequences(c, m));
45244402 },
45254403 .IntegerLiteral, .FloatLiteral => {
45264404 return parseCNumLit(c, m);
45274405 },
45284406 // eventually this will be replaced by std.c.parse which will handle these correctly
4529 .Keyword_void => return transCreateNodeIdentifierUnchecked(c, "c_void"),
4530 .Keyword_bool => return transCreateNodeIdentifierUnchecked(c, "bool"),
4531 .Keyword_double => return transCreateNodeIdentifierUnchecked(c, "f64"),
4532 .Keyword_long => return transCreateNodeIdentifierUnchecked(c, "c_long"),
4533 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),
4534 .Keyword_float => return transCreateNodeIdentifierUnchecked(c, "f32"),
4535 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
4536 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),
4407 .Keyword_void => return Node.type.create(c.arena, "c_void"),
4408 .Keyword_bool => return Node.type.create(c.arena, "bool"),
4409 .Keyword_double => return Node.type.create(c.arena, "f64"),
4410 .Keyword_long => return Node.type.create(c.arena, "c_long"),
4411 .Keyword_int => return Node.type.create(c.arena, "c_int"),
4412 .Keyword_float => return Node.type.create(c.arena, "f32"),
4413 .Keyword_short => return Node.type.create(c.arena, "c_short"),
4414 .Keyword_char => return Node.type.create(c.arena, "u8"),
45374415 .Keyword_unsigned => if (m.next()) |t| switch (t) {
4538 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),
4539 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_ushort"),
4540 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_uint"),
4416 .Keyword_char => return Node.type.create(c.arena, "u8"),
4417 .Keyword_short => return Node.type.create(c.arena, "c_ushort"),
4418 .Keyword_int => return Node.type.create(c.arena, "c_uint"),
45414419 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
45424420 _ = m.next();
4543 return transCreateNodeIdentifierUnchecked(c, "c_ulonglong");
4544 } else return transCreateNodeIdentifierUnchecked(c, "c_ulong"),
4421 return Node.type.create(c.arena, "c_ulonglong");
4422 } else return Node.type.create(c.arena, "c_ulong"),
45454423 else => {
45464424 m.i -= 1;
4547 return transCreateNodeIdentifierUnchecked(c, "c_uint");
4425 return Node.type.create(c.arena, "c_uint");
45484426 },
45494427 } else {
4550 return transCreateNodeIdentifierUnchecked(c, "c_uint");
4428 return Node.type.create(c.arena, "c_uint");
45514429 },
45524430 .Keyword_signed => if (m.next()) |t| switch (t) {
4553 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "i8"),
4554 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
4555 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),
4431 .Keyword_char => return Node.type.create(c.arena, "i8"),
4432 .Keyword_short => return Node.type.create(c.arena, "c_short"),
4433 .Keyword_int => return Node.type.create(c.arena, "c_int"),
45564434 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
45574435 _ = m.next();
4558 return transCreateNodeIdentifierUnchecked(c, "c_longlong");
4559 } else return transCreateNodeIdentifierUnchecked(c, "c_long"),
4436 return Node.type.create(c.arena, "c_longlong");
4437 } else return Node.type.create(c.arena, "c_long"),
45604438 else => {
45614439 m.i -= 1;
4562 return transCreateNodeIdentifierUnchecked(c, "c_int");
4440 return Node.type.create(c.arena, "c_int");
45634441 },
45644442 } else {
4565 return transCreateNodeIdentifierUnchecked(c, "c_int");
4443 return Node.type.create(c.arena, "c_int");
45664444 },
45674445 .Keyword_enum, .Keyword_struct, .Keyword_union => {
45684446 // struct Foo will be declared as struct_Foo by transRecordDecl
......@@ -4572,17 +4450,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
45724450 return error.ParseError;
45734451 }
45744452
4575 const ident_token = try appendTokenFmt(c, .Identifier, "{s}_{s}", .{ slice, m.slice() });
4576 const identifier = try c.arena.create(ast.Node.OneToken);
4577 identifier.* = .{
4578 .base = .{ .tag = .Identifier },
4579 .token = ident_token,
4580 };
4581 return &identifier.base;
4453 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
4454 return Node.identifier.create(c.arena, name);
45824455 },
45834456 .Identifier => {
45844457 const mangled_name = scope.getAlias(slice);
4585 return transCreateNodeIdentifier(c, checkForBuiltinTypedef(mangled_name) orelse mangled_name);
4458 return Node.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
45864459 },
45874460 .LParen => {
45884461 const inner_node = try parseCExpr(c, m, scope);
......@@ -4612,10 +4485,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
46124485 },
46134486 else => return inner_node,
46144487 }
4615
4616 // hack to get zig fmt to render a comma in builtin calls
4617 _ = try appendToken(c, .Comma, ",");
4618
46194488 const node_to_cast = try parseCExpr(c, m, scope);
46204489
46214490 if (saw_l_paren and m.next().? != .RParen) {
......@@ -4623,28 +4492,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
46234492 return error.ParseError;
46244493 }
46254494
4626 const lparen = try appendToken(c, .LParen, "(");
4627
4628 //(@import("std").meta.cast(dest, x))
4629 const import_fn_call = try c.createBuiltinCall("@import", 1);
4630 const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
4631 import_fn_call.params()[0] = std_node;
4632 import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
4633 const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta");
4634 const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "cast");
4635
4636 const cast_fn_call = try c.createCall(outer_field_access, 2);
4637 cast_fn_call.params()[0] = inner_node;
4638 cast_fn_call.params()[1] = node_to_cast;
4639 cast_fn_call.rtoken = try appendToken(c, .RParen, ")");
4640
4641 const group_node = try c.arena.create(ast.Node.GroupedExpression);
4642 group_node.* = .{
4643 .lparen = lparen,
4644 .expr = &cast_fn_call.base,
4645 .rparen = try appendToken(c, .RParen, ")"),
4646 };
4647 return &group_node.base;
4495 return Node.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
46484496 },
46494497 else => {
46504498 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!*
46534501 }
46544502}
46554503
4656fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4504fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
46574505 var node = try parseCPrimaryExprInner(c, m, scope);
46584506 // In C the preprocessor would handle concatting strings while expanding macros.
46594507 // This should do approximately the same by concatting any strings and identifiers
46604508 // after a primary expression.
46614509 while (true) {
4662 var op_token: ast.TokenIndex = undefined;
4663 var op_id: ast.Node.Tag = undefined;
46644510 switch (m.peek().?) {
46654511 .StringLiteral, .Identifier => {},
46664512 else => break,
46674513 }
4668 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4669 op_node.* = .{
4670 .base = .{ .tag = .ArrayCat },
4671 .op_token = try appendToken(c, .PlusPlus, "++"),
4672 .lhs = node,
4673 .rhs = try parseCPrimaryExprInner(c, m, scope),
4674 };
4675 node = &op_node.base;
4514 node = try Node.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });
46764515 }
46774516 return node;
46784517}
46794518
4680fn nodeIsInfixOp(tag: ast.Node.Tag) bool {
4681 return switch (tag) {
4682 .Add,
4683 .AddWrap,
4684 .ArrayCat,
4685 .ArrayMult,
4686 .Assign,
4687 .AssignBitAnd,
4688 .AssignBitOr,
4689 .AssignBitShiftLeft,
4690 .AssignBitShiftRight,
4691 .AssignBitXor,
4692 .AssignDiv,
4693 .AssignSub,
4694 .AssignSubWrap,
4695 .AssignMod,
4696 .AssignAdd,
4697 .AssignAddWrap,
4698 .AssignMul,
4699 .AssignMulWrap,
4700 .BangEqual,
4701 .BitAnd,
4702 .BitOr,
4703 .BitShiftLeft,
4704 .BitShiftRight,
4705 .BitXor,
4706 .BoolAnd,
4707 .BoolOr,
4708 .Div,
4709 .EqualEqual,
4710 .ErrorUnion,
4711 .GreaterOrEqual,
4712 .GreaterThan,
4713 .LessOrEqual,
4714 .LessThan,
4715 .MergeErrorSets,
4716 .Mod,
4717 .Mul,
4718 .MulWrap,
4719 .Period,
4720 .Range,
4721 .Sub,
4722 .SubWrap,
4723 .UnwrapOptional,
4724 .Catch,
4725 => true,
4726
4727 else => false,
4728 };
4729}
4730
4731fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
4519fn macroBoolToInt(c: *Context, node: Node) !Node {
47324520 if (!isBoolRes(node)) {
4733 if (!nodeIsInfixOp(node.tag)) return node;
4734
4735 const group_node = try c.arena.create(ast.Node.GroupedExpression);
4736 group_node.* = .{
4737 .lparen = try appendToken(c, .LParen, "("),
4738 .expr = node,
4739 .rparen = try appendToken(c, .RParen, ")"),
4740 };
4741 return &group_node.base;
4521 return node;
47424522 }
47434523
4744 const builtin_node = try c.createBuiltinCall("@boolToInt", 1);
4745 builtin_node.params()[0] = node;
4746 builtin_node.rparen_token = try appendToken(c, .RParen, ")");
4747 return &builtin_node.base;
4524 return Node.bool_to_int.create(c.arena, node);
47484525}
47494526
4750fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
4527fn macroIntToBool(c: *Context, node: Node) !Node {
47514528 if (isBoolRes(node)) {
4752 if (!nodeIsInfixOp(node.tag)) return node;
4753
4754 const group_node = try c.arena.create(ast.Node.GroupedExpression);
4755 group_node.* = .{
4756 .lparen = try appendToken(c, .LParen, "("),
4757 .expr = node,
4758 .rparen = try appendToken(c, .RParen, ")"),
4759 };
4760 return &group_node.base;
4529 return node;
47614530 }
47624531
4763 const op_token = try appendToken(c, .BangEqual, "!=");
4764 const zero = try transCreateNodeInt(c, 0);
4765 const res = try c.arena.create(ast.Node.SimpleInfixOp);
4766 res.* = .{
4767 .base = .{ .tag = .BangEqual },
4768 .op_token = op_token,
4769 .lhs = node,
4770 .rhs = zero,
4771 };
4772 const group_node = try c.arena.create(ast.Node.GroupedExpression);
4773 group_node.* = .{
4774 .lparen = try appendToken(c, .LParen, "("),
4775 .expr = &res.base,
4776 .rparen = try appendToken(c, .RParen, ")"),
4777 };
4778 return &group_node.base;
4779}
4780
4781fn macroGroup(c: *Context, node: *ast.Node) !*ast.Node {
4782 if (!nodeIsInfixOp(node.tag)) return node;
4783
4784 const group_node = try c.arena.create(ast.Node.GroupedExpression);
4785 group_node.* = .{
4786 .lparen = try appendToken(c, .LParen, "("),
4787 .expr = node,
4788 .rparen = try appendToken(c, .RParen, ")"),
4789 };
4790 return &group_node.base;
4532 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
47914533}
47924534
4793fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4535fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
47944536 const node = try parseCOrExpr(c, m, scope);
47954537 if (m.peek().? != .QuestionMark) {
47964538 return node;
47974539 }
47984540 _ = m.next();
47994541
4800 // must come immediately after expr
4801 _ = try appendToken(c, .RParen, ")");
4802 const if_node = try transCreateNodeIf(c);
4803 if_node.condition = node;
4804 if_node.body = try parseCOrExpr(c, m, scope);
4542 const then_body = try parseCOrExpr(c, m, scope);
48054543 if (m.next().? != .Colon) {
48064544 try m.fail(c, "unable to translate C expr: expected ':'", .{});
48074545 return error.ParseError;
48084546 }
4809 if_node.@"else" = try transCreateNodeElse(c);
4810 if_node.@"else".?.body = try parseCCondExpr(c, m, scope);
4811 return &if_node.base;
4547 const else_body = try parseCCondExpr(c, m, scope);
4548 return Node.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
48124549}
48134550
4814fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4551fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
48154552 var node = try parseCAndExpr(c, m, scope);
48164553 while (m.next().? == .PipePipe) {
4817 const lhs_node = try macroIntToBool(c, node);
4818 const op_token = try appendToken(c, .Keyword_or, "or");
4819 const rhs_node = try parseCAndExpr(c, m, scope);
4820 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4821 op_node.* = .{
4822 .base = .{ .tag = .BoolOr },
4823 .op_token = op_token,
4824 .lhs = lhs_node,
4825 .rhs = try macroIntToBool(c, rhs_node),
4826 };
4827 node = &op_node.base;
4554 const lhs = try macroIntToBool(c, node);
4555 const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope));
4556 node = try Node.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
48284557 }
48294558 m.i -= 1;
48304559 return node;
48314560}
48324561
4833fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4562fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
48344563 var node = try parseCBitOrExpr(c, m, scope);
48354564 while (m.next().? == .AmpersandAmpersand) {
4836 const lhs_node = try macroIntToBool(c, node);
4837 const op_token = try appendToken(c, .Keyword_and, "and");
4838 const rhs_node = try parseCBitOrExpr(c, m, scope);
4839 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4840 op_node.* = .{
4841 .base = .{ .tag = .BoolAnd },
4842 .op_token = op_token,
4843 .lhs = lhs_node,
4844 .rhs = try macroIntToBool(c, rhs_node),
4845 };
4846 node = &op_node.base;
4565 const lhs = try macroIntToBool(c, node);
4566 const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope));
4567 node = try Node.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
48474568 }
48484569 m.i -= 1;
48494570 return node;
48504571}
48514572
4852fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4573fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
48534574 var node = try parseCBitXorExpr(c, m, scope);
48544575 while (m.next().? == .Pipe) {
4855 const lhs_node = try macroBoolToInt(c, node);
4856 const op_token = try appendToken(c, .Pipe, "|");
4857 const rhs_node = try parseCBitXorExpr(c, m, scope);
4858 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4859 op_node.* = .{
4860 .base = .{ .tag = .BitOr },
4861 .op_token = op_token,
4862 .lhs = lhs_node,
4863 .rhs = try macroBoolToInt(c, rhs_node),
4864 };
4865 node = &op_node.base;
4576 const lhs = try macroBoolToInt(c, node);
4577 const rhs = try macroBoolToInt(c, try parseCBitXorExpr(c, m, scope));
4578 node = try Node.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
48664579 }
48674580 m.i -= 1;
48684581 return node;
48694582}
48704583
4871fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4584fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
48724585 var node = try parseCBitAndExpr(c, m, scope);
48734586 while (m.next().? == .Caret) {
4874 const lhs_node = try macroBoolToInt(c, node);
4875 const op_token = try appendToken(c, .Caret, "^");
4876 const rhs_node = try parseCBitAndExpr(c, m, scope);
4877 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4878 op_node.* = .{
4879 .base = .{ .tag = .BitXor },
4880 .op_token = op_token,
4881 .lhs = lhs_node,
4882 .rhs = try macroBoolToInt(c, rhs_node),
4883 };
4884 node = &op_node.base;
4587 const lhs = try macroBoolToInt(c, node);
4588 const rhs = try macroBoolToInt(c, try parseCBitAndExpr(c, m, scope));
4589 node = try Node.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
48854590 }
48864591 m.i -= 1;
48874592 return node;
48884593}
48894594
4890fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4595fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
48914596 var node = try parseCEqExpr(c, m, scope);
48924597 while (m.next().? == .Ampersand) {
4893 const lhs_node = try macroBoolToInt(c, node);
4894 const op_token = try appendToken(c, .Ampersand, "&");
4895 const rhs_node = try parseCEqExpr(c, m, scope);
4896 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4897 op_node.* = .{
4898 .base = .{ .tag = .BitAnd },
4899 .op_token = op_token,
4900 .lhs = lhs_node,
4901 .rhs = try macroBoolToInt(c, rhs_node),
4902 };
4903 node = &op_node.base;
4598 const lhs = try macroBoolToInt(c, node);
4599 const rhs = try macroBoolToInt(c, try parseCEqExpr(c, m, scope));
4600 node = try Node.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49044601 }
49054602 m.i -= 1;
49064603 return node;
49074604}
49084605
4909fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4606fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
49104607 var node = try parseCRelExpr(c, m, scope);
49114608 while (true) {
4912 var op_token: ast.TokenIndex = undefined;
4913 var op_id: ast.Node.Tag = undefined;
49144609 switch (m.peek().?) {
49154610 .BangEqual => {
4916 op_token = try appendToken(c, .BangEqual, "!=");
4917 op_id = .BangEqual;
4611 _ = m.next();
4612 const lhs = try macroBoolToInt(c, node);
4613 const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
4614 node = try Node.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49184615 },
49194616 .EqualEqual => {
4920 op_token = try appendToken(c, .EqualEqual, "==");
4921 op_id = .EqualEqual;
4617 _ = m.next();
4618 const lhs = try macroBoolToInt(c, node);
4619 const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
4620 node = try Node.equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49224621 },
49234622 else => return node,
49244623 }
4925 _ = m.next();
4926 const lhs_node = try macroBoolToInt(c, node);
4927 const rhs_node = try parseCRelExpr(c, m, scope);
4928 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4929 op_node.* = .{
4930 .base = .{ .tag = op_id },
4931 .op_token = op_token,
4932 .lhs = lhs_node,
4933 .rhs = try macroBoolToInt(c, rhs_node),
4934 };
4935 node = &op_node.base;
49364624 }
49374625}
49384626
4939fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4627fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
49404628 var node = try parseCShiftExpr(c, m, scope);
49414629 while (true) {
4942 var op_token: ast.TokenIndex = undefined;
4943 var op_id: ast.Node.Tag = undefined;
49444630 switch (m.peek().?) {
49454631 .AngleBracketRight => {
4946 op_token = try appendToken(c, .AngleBracketRight, ">");
4947 op_id = .GreaterThan;
4632 _ = m.next();
4633 const lhs = try macroBoolToInt(c, node);
4634 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4635 node = try Node.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49484636 },
49494637 .AngleBracketRightEqual => {
4950 op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
4951 op_id = .GreaterOrEqual;
4638 _ = m.next();
4639 const lhs = try macroBoolToInt(c, node);
4640 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4641 node = try Node.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49524642 },
49534643 .AngleBracketLeft => {
4954 op_token = try appendToken(c, .AngleBracketLeft, "<");
4955 op_id = .LessThan;
4644 _ = m.next();
4645 const lhs = try macroBoolToInt(c, node);
4646 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4647 node = try Node.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49564648 },
49574649 .AngleBracketLeftEqual => {
4958 op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
4959 op_id = .LessOrEqual;
4650 _ = m.next();
4651 const lhs = try macroBoolToInt(c, node);
4652 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4653 node = try Node.less_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49604654 },
49614655 else => return node,
49624656 }
4963 _ = m.next();
4964 const lhs_node = try macroBoolToInt(c, node);
4965 const rhs_node = try parseCShiftExpr(c, m, scope);
4966 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4967 op_node.* = .{
4968 .base = .{ .tag = op_id },
4969 .op_token = op_token,
4970 .lhs = lhs_node,
4971 .rhs = try macroBoolToInt(c, rhs_node),
4972 };
4973 node = &op_node.base;
49744657 }
49754658}
49764659
4977fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4660fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
49784661 var node = try parseCAddSubExpr(c, m, scope);
49794662 while (true) {
4980 var op_token: ast.TokenIndex = undefined;
4981 var op_id: ast.Node.Tag = undefined;
49824663 switch (m.peek().?) {
49834664 .AngleBracketAngleBracketLeft => {
4984 op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
4985 op_id = .BitShiftLeft;
4665 _ = m.next();
4666 const lhs = try macroBoolToInt(c, node);
4667 const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
4668 node = try Node.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49864669 },
49874670 .AngleBracketAngleBracketRight => {
4988 op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
4989 op_id = .BitShiftRight;
4671 _ = m.next();
4672 const lhs = try macroBoolToInt(c, node);
4673 const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
4674 node = try Node.shr.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
49904675 },
49914676 else => return node,
49924677 }
4993 _ = m.next();
4994 const lhs_node = try macroBoolToInt(c, node);
4995 const rhs_node = try parseCAddSubExpr(c, m, scope);
4996 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
4997 op_node.* = .{
4998 .base = .{ .tag = op_id },
4999 .op_token = op_token,
5000 .lhs = lhs_node,
5001 .rhs = try macroBoolToInt(c, rhs_node),
5002 };
5003 node = &op_node.base;
50044678 }
50054679}
50064680
5007fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4681fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
50084682 var node = try parseCMulExpr(c, m, scope);
50094683 while (true) {
5010 var op_token: ast.TokenIndex = undefined;
5011 var op_id: ast.Node.Tag = undefined;
50124684 switch (m.peek().?) {
50134685 .Plus => {
5014 op_token = try appendToken(c, .Plus, "+");
5015 op_id = .Add;
4686 _ = m.next();
4687 const lhs = try macroBoolToInt(c, node);
4688 const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
4689 node = try Node.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
50164690 },
50174691 .Minus => {
5018 op_token = try appendToken(c, .Minus, "-");
5019 op_id = .Sub;
4692 _ = m.next();
4693 const lhs = try macroBoolToInt(c, node);
4694 const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
4695 node = try Node.sub.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
50204696 },
50214697 else => return node,
50224698 }
5023 _ = m.next();
5024 const lhs_node = try macroBoolToInt(c, node);
5025 const rhs_node = try parseCMulExpr(c, m, scope);
5026 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
5027 op_node.* = .{
5028 .base = .{ .tag = op_id },
5029 .op_token = op_token,
5030 .lhs = lhs_node,
5031 .rhs = try macroBoolToInt(c, rhs_node),
5032 };
5033 node = &op_node.base;
50344699 }
50354700}
50364701
5037fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4702fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
50384703 var node = try parseCUnaryExpr(c, m, scope);
50394704 while (true) {
5040 var op_token: ast.TokenIndex = undefined;
5041 var op_id: ast.Node.Tag = undefined;
50424705 switch (m.next().?) {
50434706 .Asterisk => {
50444707 if (m.peek().? == .RParen) {
50454708 // type *)
50464709
5047 // hack to get zig fmt to render a comma in builtin calls
5048 _ = try appendToken(c, .Comma, ",");
5049
50504710 // last token of `node`
50514711 const prev_id = m.list[m.i - 1].id;
50524712
50534713 if (prev_id == .Keyword_void) {
5054 const ptr = try transCreateNodePtrType(c, false, false, .Asterisk);
5055 ptr.rhs = node;
5056 const optional_node = try transCreateNodeSimplePrefixOp(c, .OptionalType, .QuestionMark, "?");
5057 optional_node.rhs = &ptr.base;
5058 return &optional_node.base;
4714 const ptr = try Node.single_pointer.create(c.arena, .{
4715 .is_const = false,
4716 .is_volatile = false,
4717 .elem_type = node,
4718 });
4719 return Node.optional_type.create(c.arena, ptr);
50594720 } else {
5060 const ptr = try transCreateNodePtrType(c, false, false, Token.Id.Identifier);
5061 ptr.rhs = node;
5062 return &ptr.base;
4721 return Node.c_pointer.create(c.arena, .{
4722 .is_const = false,
4723 .is_volatile = false,
4724 .elem_type = node,
4725 });
50634726 }
50644727 } else {
50654728 // expr * expr
5066 op_token = try appendToken(c, .Asterisk, "*");
5067 op_id = .BitShiftLeft;
4729 const lhs = try macroBoolToInt(c, node);
4730 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4731 node = try Node.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
50684732 }
50694733 },
50704734 .Slash => {
5071 op_id = .Div;
5072 op_token = try appendToken(c, .Slash, "/");
4735 const lhs = try macroBoolToInt(c, node);
4736 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4737 node = try Node.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
50734738 },
50744739 .Percent => {
5075 op_id = .Mod;
5076 op_token = try appendToken(c, .Percent, "%");
4740 const lhs = try macroBoolToInt(c, node);
4741 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4742 node = try Node.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
50774743 },
50784744 else => {
50794745 m.i -= 1;
50804746 return node;
50814747 },
50824748 }
5083 const lhs_node = try macroBoolToInt(c, node);
5084 const rhs_node = try parseCUnaryExpr(c, m, scope);
5085 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
5086 op_node.* = .{
5087 .base = .{ .tag = op_id },
5088 .op_token = op_token,
5089 .lhs = lhs_node,
5090 .rhs = try macroBoolToInt(c, rhs_node),
5091 };
5092 node = &op_node.base;
50934749 }
50944750}
50954751
5096fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4752fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
50974753 var node = try parseCPrimaryExpr(c, m, scope);
50984754 while (true) {
50994755 switch (m.next().?) {
......@@ -5103,38 +4759,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
51034759 return error.ParseError;
51044760 }
51054761
5106 node = try transCreateNodeFieldAccess(c, node, m.slice());
5107 continue;
4762 const ident = try Node.identifier.create(c.arena, m.slice());
4763 node = try Node.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
51084764 },
51094765 .Arrow => {
51104766 if (m.next().? != .Identifier) {
51114767 try m.fail(c, "unable to translate C expr: expected identifier", .{});
51124768 return error.ParseError;
51134769 }
5114 const deref = try transCreateNodePtrDeref(c, node);
5115 node = try transCreateNodeFieldAccess(c, deref, m.slice());
5116 continue;
4770
4771 const deref = try Node.deref.create(c.arena, node);
4772 const ident = try Node.identifier.create(c.arena, m.slice());
4773 node = try Node.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });
51174774 },
51184775 .LBracket => {
5119 const arr_node = try transCreateNodeArrayAccess(c, node);
5120 arr_node.index_expr = try parseCExpr(c, m, scope);
5121 arr_node.rtoken = try appendToken(c, .RBracket, "]");
5122 node = &arr_node.base;
5123 if (m.next().? != .RBracket) {
5124 try m.fail(c, "unable to translate C expr: expected ']'", .{});
5125 return error.ParseError;
5126 }
5127 continue;
4776 const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
4777 node = try Node.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
51284778 },
51294779 .LParen => {
5130 _ = try appendToken(c, .LParen, "(");
5131 var call_params = std.ArrayList(*ast.Node).init(c.gpa);
4780 var call_params = std.ArrayList(Node).init(c.gpa);
51324781 defer call_params.deinit();
51334782 while (true) {
51344783 const arg = try parseCCondExpr(c, m, scope);
51354784 try call_params.append(arg);
51364785 switch (m.next().?) {
5137 .Comma => _ = try appendToken(c, .Comma, ","),
4786 .Comma => {},
51384787 .RParen => break,
51394788 else => {
51404789 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
51424791 },
51434792 }
51444793 }
5145 const call_node = try ast.Node.Call.alloc(c.arena, call_params.items.len);
5146 call_node.* = .{
5147 .lhs = node,
5148 .params_len = call_params.items.len,
5149 .async_token = null,
5150 .rtoken = try appendToken(c, .RParen, ")"),
5151 };
5152 mem.copy(*ast.Node, call_node.params(), call_params.items);
5153 node = &call_node.base;
5154 continue;
4794 node = try Node.call.create(c.arena, .{ .lhs = node, .rhs = try c.arena.dupe(Node, call_params.items) });
51554795 },
51564796 .LBrace => {
5157 // must come immediately after `node`
5158 _ = try appendToken(c, .Comma, ",");
5159
5160 const dot = try appendToken(c, .Period, ".");
5161 _ = try appendToken(c, .LBrace, "{");
5162
5163 var init_vals = std.ArrayList(*ast.Node).init(c.gpa);
4797 var init_vals = std.ArrayList(Node).init(c.gpa);
51644798 defer init_vals.deinit();
51654799
51664800 while (true) {
51674801 const val = try parseCCondExpr(c, m, scope);
51684802 try init_vals.append(val);
51694803 switch (m.next().?) {
5170 .Comma => _ = try appendToken(c, .Comma, ","),
4804 .Comma => {},
51714805 .RBrace => break,
51724806 else => {
51734807 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
51754809 },
51764810 }
51774811 }
5178 const tuple_node = try ast.Node.StructInitializerDot.alloc(c.arena, init_vals.items.len);
5179 tuple_node.* = .{
5180 .dot = dot,
5181 .list_len = init_vals.items.len,
5182 .rtoken = try appendToken(c, .RBrace, "}"),
5183 };
5184 mem.copy(*ast.Node, tuple_node.list(), init_vals.items);
5185
5186 //(@import("std").mem.zeroInit(T, .{x}))
5187 const import_fn_call = try c.createBuiltinCall("@import", 1);
5188 const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
5189 import_fn_call.params()[0] = std_node;
5190 import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
5191 const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem");
5192 const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroInit");
5193
5194 const zero_init_call = try c.createCall(outer_field_access, 2);
5195 zero_init_call.params()[0] = node;
5196 zero_init_call.params()[1] = &tuple_node.base;
5197 zero_init_call.rtoken = try appendToken(c, .RParen, ")");
5198
5199 node = &zero_init_call.base;
5200 continue;
4812 const tuple_node = try Node.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));
4813 node = try Node.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
52014814 },
52024815 .PlusPlus, .MinusMinus => {
52034816 try m.fail(c, "TODO postfix inc/dec expr", .{});
......@@ -5211,35 +4824,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
52114824 }
52124825}
52134826
5214fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
4827fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
52154828 switch (m.next().?) {
52164829 .Bang => {
5217 const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!");
5218 node.rhs = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
5219 return &node.base;
4830 const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
4831 return Node.not.create(c.arena, operand);
52204832 },
52214833 .Minus => {
5222 const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-");
5223 node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
5224 return &node.base;
4834 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4835 return Node.negate.create(c.arena, operand);
52254836 },
52264837 .Plus => return try parseCUnaryExpr(c, m, scope),
52274838 .Tilde => {
5228 const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~");
5229 node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
5230 return &node.base;
4839 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4840 return Node.bit_not.create(c.arena, operand);
52314841 },
52324842 .Asterisk => {
5233 const node = try macroGroup(c, try parseCUnaryExpr(c, m, scope));
5234 return try transCreateNodePtrDeref(c, node);
4843 const operand = try parseCUnaryExpr(c, m, scope);
4844 return Node.deref.create(c.arena, operand);
52354845 },
52364846 .Ampersand => {
5237 const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&");
5238 node.rhs = try macroGroup(c, try parseCUnaryExpr(c, m, scope));
5239 return &node.base;
4847 const operand = try parseCUnaryExpr(c, m, scope);
4848 return Node.address_of.create(c.arena, operand);
52404849 },
52414850 .Keyword_sizeof => {
5242 const inner = if (m.peek().? == .LParen) blk: {
4851 const operand = if (m.peek().? == .LParen) blk: {
52434852 _ = m.next();
52444853 // C grammar says this should be 'type-name' but we have to
52454854 // use parseCMulExpr to correctly handle pointer types.
......@@ -5251,18 +4860,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
52514860 break :blk inner;
52524861 } else try parseCUnaryExpr(c, m, scope);
52534862
5254 //(@import("std").meta.sizeof(dest, x))
5255 const import_fn_call = try c.createBuiltinCall("@import", 1);
5256 const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
5257 import_fn_call.params()[0] = std_node;
5258 import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
5259 const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta");
5260 const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "sizeof");
5261
5262 const sizeof_call = try c.createCall(outer_field_access, 1);
5263 sizeof_call.params()[0] = inner;
5264 sizeof_call.rtoken = try appendToken(c, .RParen, ")");
5265 return &sizeof_call.base;
4863 return Node.std_meta_sizeof.create(c.arena, operand);
52664864 },
52674865 .Keyword_alignof => {
52684866 // 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
52734871 }
52744872 // C grammar says this should be 'type-name' but we have to
52754873 // use parseCMulExpr to correctly handle pointer types.
5276 const inner = try parseCMulExpr(c, m, scope);
4874 const operand = try parseCMulExpr(c, m, scope);
52774875 if (m.next().? != .RParen) {
52784876 try m.fail(c, "unable to translate C expr: expected ')'", .{});
52794877 return error.ParseError;
52804878 }
52814879
5282 const builtin_call = try c.createBuiltinCall("@alignOf", 1);
5283 builtin_call.params()[0] = inner;
5284 builtin_call.rparen_token = try appendToken(c, .RParen, ")");
5285 return &builtin_call.base;
4880 return Node.alignof.create(c.arena, operand);
52864881 },
52874882 .PlusPlus, .MinusMinus => {
52884883 try m.fail(c, "TODO unary inc/dec expr", .{});
......@@ -5295,50 +4890,40 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
52954890 }
52964891}
52974892
5298fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {
5299 const tok = c.token_locs.items[token];
5300 const slice = c.source_buffer.items[tok.start..tok.end];
5301 return if (mem.startsWith(u8, slice, "@\""))
5302 slice[2 .. slice.len - 1]
5303 else
5304 slice;
5305}
5306
5307fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
5308 switch (node.tag) {
5309 .ContainerDecl,
5310 .AddressOf,
5311 .Await,
5312 .BitNot,
5313 .BoolNot,
5314 .OptionalType,
5315 .Negation,
5316 .NegationWrap,
5317 .Resume,
5318 .Try,
5319 .ArrayType,
5320 .ArrayTypeSentinel,
5321 .PtrType,
5322 .SliceType,
4893fn getContainer(c: *Context, node: Node) ?Node {
4894 switch (node.tag()) {
4895 .@"union",
4896 .@"struct",
4897 .@"enum",
4898 .address_of,
4899 .bit_not,
4900 .not,
4901 .optional_type,
4902 .negate,
4903 .negate_wrap,
4904 .array_type,
4905 .c_pointer,
4906 .single_pointer,
53234907 => return node,
53244908
5325 .Identifier => {
5326 const ident = node.castTag(.Identifier).?;
5327 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {
5328 if (value.cast(ast.Node.VarDecl)) |var_decl|
5329 return getContainer(c, var_decl.getInitNode().?);
4909 .identifier => {
4910 const ident = node.castTag(.identifier).?;
4911 if (c.global_scope.sym_table.get(ident.data)) |value| {
4912 if (value.castTag(.var_decl)) |var_decl|
4913 return getContainer(c, var_decl.data.init);
4914 if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |var_decl|
4915 return getContainer(c, var_decl.data.init);
53304916 }
53314917 },
53324918
5333 .Period => {
5334 const infix = node.castTag(.Period).?;
4919 .field_access => {
4920 const infix = node.castTag(.field_access).?;
53354921
5336 if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
5337 if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
5338 for (container.fieldsAndDecls()) |field_ref| {
5339 const field = field_ref.cast(ast.Node.ContainerField).?;
5340 const ident = infix.rhs.castTag(.Identifier).?;
5341 if (mem.eql(u8, tokenSlice(c, field.name_token), tokenSlice(c, ident.token))) {
4922 if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
4923 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
4924 for (container.data.fields) |field| {
4925 const ident = infix.data.rhs.castTag(.identifier).?;
4926 if (mem.eql(u8, field.data.name, field.data)) {
53424927 return getContainer(c, field.type_expr.?);
53434928 }
53444929 }
......@@ -5351,22 +4936,20 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
53514936 return null;
53524937}
53534938
5354fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
5355 if (ref.castTag(.Identifier)) |ident| {
5356 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {
5357 if (value.cast(ast.Node.VarDecl)) |var_decl| {
5358 if (var_decl.getTypeNode()) |ty|
5359 return getContainer(c, ty);
4939fn getContainerTypeOf(c: *Context, ref: Node) ?Node {
4940 if (ref.castTag(.identifier)) |ident| {
4941 if (c.global_scope.sym_table.get(ident.data)) |value| {
4942 if (value.castTag(.var_decl)) |var_decl| {
4943 return getContainer(c, var_decl.data.type);
53604944 }
53614945 }
5362 } else if (ref.castTag(.Period)) |infix| {
5363 if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
5364 if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
5365 for (container.fieldsAndDecls()) |field_ref| {
5366 const field = field_ref.cast(ast.Node.ContainerField).?;
5367 const ident = infix.rhs.castTag(.Identifier).?;
5368 if (mem.eql(u8, tokenSlice(c, field.name_token), tokenSlice(c, ident.token))) {
5369 return getContainer(c, field.type_expr.?);
4946 } else if (ref.castTag(.field_access)) |infix| {
4947 if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
4948 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
4949 for (container.data.fields) |field| {
4950 const ident = infix.data.rhs.castTag(.identifier).?;
4951 if (mem.eql(u8, field.name, ident.data)) {
4952 return getContainer(c, field.type);
53704953 }
53714954 }
53724955 } else
......@@ -5376,11 +4959,16 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
53764959 return null;
53774960}
53784961
5379fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto {
5380 const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getInitNode().? else return null;
4962fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
4963 const init = if (value.castTag(.var_decl)) |v|
4964 v.data.init
4965 else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
4966 v.data.init
4967 else
4968 return null;
53814969 if (getContainerTypeOf(c, init)) |ty_node| {
5382 if (ty_node.castTag(.OptionalType)) |prefix| {
5383 if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| {
4970 if (ty_node.castTag(.optional_type)) |prefix| {
4971 if (prefix.data.castTag(.func)) |fn_proto| {
53844972 return fn_proto;
53854973 }
53864974 }
src/translate_c/ast.zig+33-8
......@@ -47,7 +47,6 @@ pub const Node = extern union {
4747 field_access,
4848 array_access,
4949 call,
50 std_mem_zeroes,
5150 var_decl,
5251 func,
5352 warning,
......@@ -57,6 +56,7 @@ pub const Node = extern union {
5756 @"struct",
5857 @"union",
5958 array_init,
59 tuple,
6060 container_init,
6161 std_meta_cast,
6262 discard,
......@@ -162,6 +162,8 @@ pub const Node = extern union {
162162 deref,
163163
164164 block,
165 /// { operand }
166 block_single,
165167 @"break",
166168
167169 sizeof,
......@@ -173,8 +175,12 @@ pub const Node = extern union {
173175 single_pointer,
174176 array_type,
175177
176 /// @import("std").mem.zeroes(T)
178 /// @import("std").meta.sizeof(operand)
179 std_meta_sizeof,
180 /// @import("std").mem.zeroes(operand)
177181 std_mem_zeroes,
182 /// @import("std").mem.zeroInit(lhs, rhs)
183 std_mem_zeroinit,
178184 // pub const name = @compileError(msg);
179185 fail_decl,
180186 // var actual = mangled;
......@@ -188,6 +194,9 @@ pub const Node = extern union {
188194 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
189195 enum_redecl,
190196
197 /// pub inline fn name(params) return_type body
198 pub_inline_fn,
199
191200 /// [0]type{}
192201 empty_array,
193202 /// [1]type{val} ** count
......@@ -195,6 +204,7 @@ pub const Node = extern union {
195204
196205 /// _ = operand;
197206 ignore,
207 @"anytype",
198208
199209 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
200210 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -213,6 +223,7 @@ pub const Node = extern union {
213223 .one_literal,
214224 .void_type,
215225 .noreturn_type,
226 .@"anytype",
216227 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
217228
218229 .std_mem_zeroes,
......@@ -234,6 +245,7 @@ pub const Node = extern union {
234245 .if_not_break,
235246 .switch_else,
236247 .ignore,
248 .block_single,
237249 => Payload.UnOp,
238250
239251 .add,
......@@ -302,6 +314,8 @@ pub const Node = extern union {
302314 .field_access,
303315 .assign,
304316 .align_cast,
317 .array_access,
318 .std_mem_zeroinit,
305319 => Payload.BinOp,
306320
307321 .number_literal,
......@@ -325,7 +339,7 @@ pub const Node = extern union {
325339 .func => Payload.Func,
326340 .@"enum" => Payload.Enum,
327341 .@"struct", .@"union" => Payload.Record,
328 .array_init => Payload.ArrayInit,
342 .array_init, .tuple => Payload.ArrayInit,
329343 .container_init => Payload.ContainerInit,
330344 .std_meta_cast => Payload.Infix,
331345 .block => Payload.Block,
......@@ -336,6 +350,7 @@ pub const Node = extern union {
336350 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
337351 .enum_redecl => Payload.EnumRedecl,
338352 .array_filler => Payload.ArrayFiller,
353 .pub_inline_fn => Payload.PubInlineFn,
339354 };
340355 }
341356
......@@ -488,12 +503,12 @@ pub const Payload = struct {
488503 body: ?Node,
489504 alignment: ?c_uint,
490505 },
506 };
491507
492 pub const Param = struct {
493 is_noalias: bool,
494 name: ?[]const u8,
495 type: Node,
496 };
508 pub const Param = struct {
509 is_noalias: bool,
510 name: ?[]const u8,
511 type: Node,
497512 };
498513
499514 pub const Enum = struct {
......@@ -598,6 +613,16 @@ pub const Payload = struct {
598613 count: usize,
599614 },
600615 };
616
617 pub const PubInlineFn = struct {
618 base: Node,
619 data: struct {
620 name: []const u8,
621 params: []Param,
622 return_type: Node,
623 body: Node,
624 },
625 };
601626};
602627
603628/// Converts the nodes into a Zig ast.