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 {...@@ -3512,86 +3512,48 @@ fn transCreateNodeNumber(c: *Context, int: anytype) !Node {
3512 return Node.int_literal.create(c.arena, str);3512 return Node.int_literal.create(c.arena, str);
3513}3513}
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 {
3516 const scope = &c.global_scope.base;3516 const scope = &c.global_scope.base;
35173517
3518 const pub_tok = try appendToken(c, .Keyword_pub, "pub");3518 var fn_params = std.ArrayList(Node).init(c.gpa);
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);
3524 defer fn_params.deinit();3519 defer fn_params.deinit();
35253520
3526 for (proto_alias.params()) |param, i| {3521 for (proto_alias.params()) |param, i| {
3527 if (i != 0) {3522 const param_name = param.name orelse
3528 _ = try appendToken(c, .Comma, ",");3523 try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()});
3529 }
3530 const param_name_tok = param.name_token orelse
3531 try appendTokenFmt(c, .Identifier, "arg_{d}", .{c.getMangle()});
35323524
3533 _ = try appendToken(c, .Colon, ":");3525 try fn_params.append(.{
35343526 .name = param_name,
3535 (try fn_params.addOne()).* = .{3527 .type = param.type,
3536 .doc_comments = null,3528 .is_noalias = param.is_noalias,
3537 .comptime_token = null,3529 });
3538 .noalias_token = param.noalias_token,
3539 .name_token = param_name_tok,
3540 .param_type = param.param_type,
3541 };
3542 }3530 }
35433531
3544 _ = try appendToken(c, .RParen, ")");3532 const init = if (value.castTag(.var_decl)) |v|
35453533 v.data.init
3546 _ = try appendToken(c, .Keyword_callconv, "callconv");3534 else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
3547 _ = try appendToken(c, .LParen, "(");3535 v.data.init
3548 const callconv_expr = try transCreateNodeEnumLiteral(c, "Inline");3536 else
3549 _ = try appendToken(c, .RParen, ")");3537 unreachable;
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();
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);
3559 for (fn_params.items) |param, i| {3541 for (fn_params.items) |param, i| {
3560 if (i != 0) {3542 call_params[i] = try Node.identifier.create(c.arena, param.name);
3561 _ = try appendToken(c, .Comma, ",");
3562 }
3563 call_params[i] = try transCreateNodeIdentifier(c, tokenSlice(c, param.name_token.?));
3564 }3543 }
3565 call_expr.rtoken = try appendToken(c, .RParen, ")");3544 const call_expr = try Node.call.create(c.arean, .{
35663545 .lhs = unwrap_expr,
3567 const return_expr = try ast.Node.ControlFlowExpression.create(c.arena, .{3546 .args = call_params,
3568 .ltoken = return_kw,
3569 .tag = .Return,
3570 }, .{
3571 .rhs = &call_expr.base,
3572 });3547 });
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);3551 return Node.pub_inline_fn.create(c.arena, .{
3576 block.* = .{3552 .name = name,
3577 .lbrace = block_lbrace,3553 .params = try c.arena.dupe(ast.Node.Param, fn_params.items),
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,
3586 .return_type = proto_alias.return_type,3554 .return_type = proto_alias.return_type,
3587 }, .{3555 .body = block,
3588 .visib_token = pub_tok,
3589 .name_token = name_tok,
3590 .body_node = &block.base,
3591 .callconv_expr = callconv_expr,
3592 });3556 });
3593 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
3594 return &fn_proto.base;
3595}3557}
35963558
3597fn transCreateNodeShiftOp(3559fn transCreateNodeShiftOp(
...@@ -4108,27 +4070,13 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {...@@ -4108,27 +4070,13 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
4108fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {4070fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
4109 const scope = &c.global_scope.base;4071 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
4116 const init_node = try parseCExpr(c, m, scope);4073 const init_node = try parseCExpr(c, m, scope);
4117 const last = m.next().?;4074 const last = m.next().?;
4118 if (last != .Eof and last != .Nl)4075 if (last != .Eof and last != .Nl)
4119 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});4076 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
41204077
4121 const semicolon_token = try appendToken(c, .Semicolon, ";");4078 const var_decl = try Node.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
4122 const node = try ast.Node.VarDecl.create(c.arena, .{4079 _ = try c.global_scope.macro_table.put(m.name, var_decl);
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);
4132}4080}
41334081
4134fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {4082fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
...@@ -4136,16 +4084,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4136,16 +4084,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
4136 defer block_scope.deinit();4084 defer block_scope.deinit();
4137 const scope = &block_scope.base;4085 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
4144 if (m.next().? != .LParen) {4087 if (m.next().? != .LParen) {
4145 return m.fail(c, "unable to translate C expr: expected '('", .{});4088 return m.fail(c, "unable to translate C expr: expected '('", .{});
4146 }4089 }
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);
4149 defer fn_params.deinit();4092 defer fn_params.deinit();
41504093
4151 while (true) {4094 while (true) {
...@@ -4153,120 +4096,78 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4153,120 +4096,78 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
4153 _ = m.next();4096 _ = m.next();
41544097
4155 const mangled_name = try block_scope.makeMangledName(c, m.slice());4098 const mangled_name = try block_scope.makeMangledName(c, m.slice());
4156 const param_name_tok = try appendIdentifier(c, mangled_name);4099 try fn_params.append(.{
4157 _ = try appendToken(c, .Colon, ":");4100 .is_noalias = false,
41584101 .name = mangled_name,
4159 const any_type = try c.arena.create(ast.Node.OneToken);4102 .type = Node.@"anytype".init(),
4160 any_type.* = .{4103 });
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 };
41724104
4173 if (m.peek().? != .Comma) break;4105 if (m.peek().? != .Comma) break;
4174 _ = m.next();4106 _ = m.next();
4175 _ = try appendToken(c, .Comma, ",");
4176 }4107 }
41774108
4178 if (m.next().? != .RParen) {4109 if (m.next().? != .RParen) {
4179 return m.fail(c, "unable to translate C expr: expected ')'", .{});4110 return m.fail(c, "unable to translate C expr: expected ')'", .{});
4180 }4111 }
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");
4192 const expr = try parseCExpr(c, m, scope);4113 const expr = try parseCExpr(c, m, scope);
4193 const last = m.next().?;4114 const last = m.next().?;
4194 if (last != .Eof and last != .Nl)4115 if (last != .Eof and last != .Nl)
4195 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});4116 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);
4212 try block_scope.statements.append(&return_expr.base);4126 try block_scope.statements.append(&return_expr.base);
4213 const block_node = try block_scope.complete(c);4127
4214 const fn_proto = try ast.Node.FnProto.create(c.arena, .{4128 const fn_decl = try Node.pub_inline_fn.create(c.arena, .{
4215 .fn_token = fn_tok,4129 .name = m.name,
4216 .params_len = fn_params.items.len,4130 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
4217 .return_type = .{ .Explicit = &type_of.base },4131 .return_type = typeof,
4218 }, .{4132 .body = try block_scope.complete(c),
4219 .visib_token = pub_tok,
4220 .name_token = name_tok,
4221 .body_node = block_node,
4222 .callconv_expr = callconv_expr,
4223 });4133 });
4224 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
4225
4226 _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);4134 _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);
4227}4135}
42284136
4229const ParseError = Error || error{ParseError};4137const 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 {
4232 // TODO parseCAssignExpr here4140 // TODO parseCAssignExpr here
4233 const node = try parseCCondExpr(c, m, scope);4141 const node = try parseCCondExpr(c, m, scope);
4234 if (m.next().? != .Comma) {4142 if (m.next().? != .Comma) {
4235 m.i -= 1;4143 m.i -= 1;
4236 return node;4144 return node;
4237 }4145 }
4238 _ = try appendToken(c, .Semicolon, ";");
4239 var block_scope = try Scope.Block.init(c, scope, true);4146 var block_scope = try Scope.Block.init(c, scope, true);
4240 defer block_scope.deinit();4147 defer block_scope.deinit();
42414148
4242 var last = node;4149 var last = node;
4243 while (true) {4150 while (true) {
4244 // suppress result4151 // suppress result
4245 const lhs = try transCreateNodeIdentifier(c, "_");4152 const ignore = try Node.ignore.create(c.arena, last);
4246 const op_token = try appendToken(c, .Equal, "=");4153 try block_scope.statements.append(ignore);
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);
42554154
4256 last = try parseCCondExpr(c, m, scope);4155 last = try parseCCondExpr(c, m, scope);
4257 _ = try appendToken(c, .Semicolon, ";");
4258 if (m.next().? != .Comma) {4156 if (m.next().? != .Comma) {
4259 m.i -= 1;4157 m.i -= 1;
4260 break;4158 break;
4261 }4159 }
4262 }4160 }
42634161
4264 const break_node = try transCreateNodeBreak(c, block_scope.label, last);4162 const break_node = try Node.break_val.create(c.arena, .{
4265 try block_scope.statements.append(&break_node.base);4163 .label = block_scope.label,
4164 .val = last,
4165 });
4166 try block_scope.statements.append(break_node);
4266 return try block_scope.complete(c);4167 return try block_scope.complete(c);
4267}4168}
42684169
4269fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {4170fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
4270 var lit_bytes = m.slice();4171 var lit_bytes = m.slice();
42714172
4272 switch (m.list[m.i].id) {4173 switch (m.list[m.i].id) {
...@@ -4286,11 +4187,10 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {...@@ -4286,11 +4187,10 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
4286 }4187 }
42874188
4288 if (suffix == .none) {4189 if (suffix == .none) {
4289 return transCreateNodeInt(c, lit_bytes);4190 return transCreateNodeNumber(c, lit_bytes);
4290 }4191 }
42914192
4292 const cast_node = try c.createBuiltinCall("@as", 2);4193 const type_node = try Node.type.create(c.arena, switch (suffix) {
4293 cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) {
4294 .u => "c_uint",4194 .u => "c_uint",
4295 .l => "c_long",4195 .l => "c_long",
4296 .lu => "c_ulong",4196 .lu => "c_ulong",
...@@ -4304,27 +4204,22 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {...@@ -4304,27 +4204,22 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
4304 .llu => 3,4204 .llu => 3,
4305 else => unreachable,4205 else => unreachable,
4306 }];4206 }];
4307 _ = try appendToken(c, .Comma, ",");4207 const rhs = try transCreateNodeNumber(c, lit_bytes);
4308 cast_node.params()[1] = try transCreateNodeInt(c, lit_bytes);4208 return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
4309 cast_node.rparen_token = try appendToken(c, .RParen, ")");
4310 return &cast_node.base;
4311 },4209 },
4312 .FloatLiteral => |suffix| {4210 .FloatLiteral => |suffix| {
4313 if (lit_bytes[0] == '.')4211 if (lit_bytes[0] == '.')
4314 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});4212 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
4315 if (suffix == .none) {4213 if (suffix == .none) {
4316 return transCreateNodeFloat(c, lit_bytes);4214 return transCreateNodeNumber(c, lit_bytes);
4317 }4215 }
4318 const cast_node = try c.createBuiltinCall("@as", 2);4216 const type_node = try Node.type.create(c.arena, switch (suffix) {
4319 cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) {
4320 .f => "f32",4217 .f => "f32",
4321 .l => "c_longdouble",4218 .l => "c_longdouble",
4322 else => unreachable,4219 else => unreachable,
4323 });4220 });
4324 _ = try appendToken(c, .Comma, ",");4221 const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1]);
4325 cast_node.params()[1] = try transCreateNodeFloat(c, lit_bytes[0 .. lit_bytes.len - 1]);4222 return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
4326 cast_node.rparen_token = try appendToken(c, .RParen, ")");
4327 return &cast_node.base;
4328 },4223 },
4329 else => unreachable,4224 else => unreachable,
4330 }4225 }
...@@ -4490,79 +4385,62 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -4490,79 +4385,62 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
4490 return bytes[0..i];4385 return bytes[0..i];
4491}4386}
44924387
4493fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4388fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4494 const tok = m.next().?;4389 const tok = m.next().?;
4495 const slice = m.slice();4390 const slice = m.slice();
4496 switch (tok) {4391 switch (tok) {
4497 .CharLiteral => {4392 .CharLiteral => {
4498 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {4393 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
4499 const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, m));4394 return Node.char_literal.create(c.arena, 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;
4506 } else {4395 } else {
4507 const token = try appendTokenFmt(c, .IntegerLiteral, "0x{x}", .{slice[1 .. slice.len - 1]});4396 const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
4508 const node = try c.arena.create(ast.Node.OneToken);4397 return Node.int_literal.create(c.arena, str);
4509 node.* = .{
4510 .base = .{ .tag = .IntegerLiteral },
4511 .token = token,
4512 };
4513 return &node.base;
4514 }4398 }
4515 },4399 },
4516 .StringLiteral => {4400 .StringLiteral => {
4517 const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, m));4401 return Node.string_literal.create(c.arena, 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;
4524 },4402 },
4525 .IntegerLiteral, .FloatLiteral => {4403 .IntegerLiteral, .FloatLiteral => {
4526 return parseCNumLit(c, m);4404 return parseCNumLit(c, m);
4527 },4405 },
4528 // eventually this will be replaced by std.c.parse which will handle these correctly4406 // eventually this will be replaced by std.c.parse which will handle these correctly
4529 .Keyword_void => return transCreateNodeIdentifierUnchecked(c, "c_void"),4407 .Keyword_void => return Node.type.create(c.arena, "c_void"),
4530 .Keyword_bool => return transCreateNodeIdentifierUnchecked(c, "bool"),4408 .Keyword_bool => return Node.type.create(c.arena, "bool"),
4531 .Keyword_double => return transCreateNodeIdentifierUnchecked(c, "f64"),4409 .Keyword_double => return Node.type.create(c.arena, "f64"),
4532 .Keyword_long => return transCreateNodeIdentifierUnchecked(c, "c_long"),4410 .Keyword_long => return Node.type.create(c.arena, "c_long"),
4533 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),4411 .Keyword_int => return Node.type.create(c.arena, "c_int"),
4534 .Keyword_float => return transCreateNodeIdentifierUnchecked(c, "f32"),4412 .Keyword_float => return Node.type.create(c.arena, "f32"),
4535 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),4413 .Keyword_short => return Node.type.create(c.arena, "c_short"),
4536 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),4414 .Keyword_char => return Node.type.create(c.arena, "u8"),
4537 .Keyword_unsigned => if (m.next()) |t| switch (t) {4415 .Keyword_unsigned => if (m.next()) |t| switch (t) {
4538 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),4416 .Keyword_char => return Node.type.create(c.arena, "u8"),
4539 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_ushort"),4417 .Keyword_short => return Node.type.create(c.arena, "c_ushort"),
4540 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_uint"),4418 .Keyword_int => return Node.type.create(c.arena, "c_uint"),
4541 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {4419 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
4542 _ = m.next();4420 _ = m.next();
4543 return transCreateNodeIdentifierUnchecked(c, "c_ulonglong");4421 return Node.type.create(c.arena, "c_ulonglong");
4544 } else return transCreateNodeIdentifierUnchecked(c, "c_ulong"),4422 } else return Node.type.create(c.arena, "c_ulong"),
4545 else => {4423 else => {
4546 m.i -= 1;4424 m.i -= 1;
4547 return transCreateNodeIdentifierUnchecked(c, "c_uint");4425 return Node.type.create(c.arena, "c_uint");
4548 },4426 },
4549 } else {4427 } else {
4550 return transCreateNodeIdentifierUnchecked(c, "c_uint");4428 return Node.type.create(c.arena, "c_uint");
4551 },4429 },
4552 .Keyword_signed => if (m.next()) |t| switch (t) {4430 .Keyword_signed => if (m.next()) |t| switch (t) {
4553 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "i8"),4431 .Keyword_char => return Node.type.create(c.arena, "i8"),
4554 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),4432 .Keyword_short => return Node.type.create(c.arena, "c_short"),
4555 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),4433 .Keyword_int => return Node.type.create(c.arena, "c_int"),
4556 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {4434 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
4557 _ = m.next();4435 _ = m.next();
4558 return transCreateNodeIdentifierUnchecked(c, "c_longlong");4436 return Node.type.create(c.arena, "c_longlong");
4559 } else return transCreateNodeIdentifierUnchecked(c, "c_long"),4437 } else return Node.type.create(c.arena, "c_long"),
4560 else => {4438 else => {
4561 m.i -= 1;4439 m.i -= 1;
4562 return transCreateNodeIdentifierUnchecked(c, "c_int");4440 return Node.type.create(c.arena, "c_int");
4563 },4441 },
4564 } else {4442 } else {
4565 return transCreateNodeIdentifierUnchecked(c, "c_int");4443 return Node.type.create(c.arena, "c_int");
4566 },4444 },
4567 .Keyword_enum, .Keyword_struct, .Keyword_union => {4445 .Keyword_enum, .Keyword_struct, .Keyword_union => {
4568 // struct Foo will be declared as struct_Foo by transRecordDecl4446 // struct Foo will be declared as struct_Foo by transRecordDecl
...@@ -4572,17 +4450,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*...@@ -4572,17 +4450,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
4572 return error.ParseError;4450 return error.ParseError;
4573 }4451 }
45744452
4575 const ident_token = try appendTokenFmt(c, .Identifier, "{s}_{s}", .{ slice, m.slice() });4453 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
4576 const identifier = try c.arena.create(ast.Node.OneToken);4454 return Node.identifier.create(c.arena, name);
4577 identifier.* = .{
4578 .base = .{ .tag = .Identifier },
4579 .token = ident_token,
4580 };
4581 return &identifier.base;
4582 },4455 },
4583 .Identifier => {4456 .Identifier => {
4584 const mangled_name = scope.getAlias(slice);4457 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);
4586 },4459 },
4587 .LParen => {4460 .LParen => {
4588 const inner_node = try parseCExpr(c, m, scope);4461 const inner_node = try parseCExpr(c, m, scope);
...@@ -4612,10 +4485,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*...@@ -4612,10 +4485,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
4612 },4485 },
4613 else => return inner_node,4486 else => return inner_node,
4614 }4487 }
4615
4616 // hack to get zig fmt to render a comma in builtin calls
4617 _ = try appendToken(c, .Comma, ",");
4618
4619 const node_to_cast = try parseCExpr(c, m, scope);4488 const node_to_cast = try parseCExpr(c, m, scope);
46204489
4621 if (saw_l_paren and m.next().? != .RParen) {4490 if (saw_l_paren and m.next().? != .RParen) {
...@@ -4623,28 +4492,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*...@@ -4623,28 +4492,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
4623 return error.ParseError;4492 return error.ParseError;
4624 }4493 }
46254494
4626 const lparen = try appendToken(c, .LParen, "(");4495 return Node.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
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;
4648 },4496 },
4649 else => {4497 else => {
4650 try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});4498 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!*...@@ -4653,447 +4501,255 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*
4653 }4501 }
4654}4502}
46554503
4656fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4504fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4657 var node = try parseCPrimaryExprInner(c, m, scope);4505 var node = try parseCPrimaryExprInner(c, m, scope);
4658 // In C the preprocessor would handle concatting strings while expanding macros.4506 // In C the preprocessor would handle concatting strings while expanding macros.
4659 // This should do approximately the same by concatting any strings and identifiers4507 // This should do approximately the same by concatting any strings and identifiers
4660 // after a primary expression.4508 // after a primary expression.
4661 while (true) {4509 while (true) {
4662 var op_token: ast.TokenIndex = undefined;
4663 var op_id: ast.Node.Tag = undefined;
4664 switch (m.peek().?) {4510 switch (m.peek().?) {
4665 .StringLiteral, .Identifier => {},4511 .StringLiteral, .Identifier => {},
4666 else => break,4512 else => break,
4667 }4513 }
4668 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);4514 node = try Node.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });
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;
4676 }4515 }
4677 return node;4516 return node;
4678}4517}
46794518
4680fn nodeIsInfixOp(tag: ast.Node.Tag) bool {4519fn macroBoolToInt(c: *Context, node: Node) !Node {
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 {
4732 if (!isBoolRes(node)) {4520 if (!isBoolRes(node)) {
4733 if (!nodeIsInfixOp(node.tag)) return node;4521 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;
4742 }4522 }
47434523
4744 const builtin_node = try c.createBuiltinCall("@boolToInt", 1);4524 return Node.bool_to_int.create(c.arena, node);
4745 builtin_node.params()[0] = node;
4746 builtin_node.rparen_token = try appendToken(c, .RParen, ")");
4747 return &builtin_node.base;
4748}4525}
47494526
4750fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {4527fn macroIntToBool(c: *Context, node: Node) !Node {
4751 if (isBoolRes(node)) {4528 if (isBoolRes(node)) {
4752 if (!nodeIsInfixOp(node.tag)) return node;4529 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;
4761 }4530 }
47624531
4763 const op_token = try appendToken(c, .BangEqual, "!=");4532 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
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;
4791}4533}
47924534
4793fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4535fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4794 const node = try parseCOrExpr(c, m, scope);4536 const node = try parseCOrExpr(c, m, scope);
4795 if (m.peek().? != .QuestionMark) {4537 if (m.peek().? != .QuestionMark) {
4796 return node;4538 return node;
4797 }4539 }
4798 _ = m.next();4540 _ = m.next();
47994541
4800 // must come immediately after expr4542 const then_body = try parseCOrExpr(c, m, scope);
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);
4805 if (m.next().? != .Colon) {4543 if (m.next().? != .Colon) {
4806 try m.fail(c, "unable to translate C expr: expected ':'", .{});4544 try m.fail(c, "unable to translate C expr: expected ':'", .{});
4807 return error.ParseError;4545 return error.ParseError;
4808 }4546 }
4809 if_node.@"else" = try transCreateNodeElse(c);4547 const else_body = try parseCCondExpr(c, m, scope);
4810 if_node.@"else".?.body = try parseCCondExpr(c, m, scope);4548 return Node.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
4811 return &if_node.base;
4812}4549}
48134550
4814fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4551fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4815 var node = try parseCAndExpr(c, m, scope);4552 var node = try parseCAndExpr(c, m, scope);
4816 while (m.next().? == .PipePipe) {4553 while (m.next().? == .PipePipe) {
4817 const lhs_node = try macroIntToBool(c, node);4554 const lhs = try macroIntToBool(c, node);
4818 const op_token = try appendToken(c, .Keyword_or, "or");4555 const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope));
4819 const rhs_node = try parseCAndExpr(c, m, scope);4556 node = try Node.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
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;
4828 }4557 }
4829 m.i -= 1;4558 m.i -= 1;
4830 return node;4559 return node;
4831}4560}
48324561
4833fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4562fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4834 var node = try parseCBitOrExpr(c, m, scope);4563 var node = try parseCBitOrExpr(c, m, scope);
4835 while (m.next().? == .AmpersandAmpersand) {4564 while (m.next().? == .AmpersandAmpersand) {
4836 const lhs_node = try macroIntToBool(c, node);4565 const lhs = try macroIntToBool(c, node);
4837 const op_token = try appendToken(c, .Keyword_and, "and");4566 const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope));
4838 const rhs_node = try parseCBitOrExpr(c, m, scope);4567 node = try Node.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
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;
4847 }4568 }
4848 m.i -= 1;4569 m.i -= 1;
4849 return node;4570 return node;
4850}4571}
48514572
4852fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4573fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4853 var node = try parseCBitXorExpr(c, m, scope);4574 var node = try parseCBitXorExpr(c, m, scope);
4854 while (m.next().? == .Pipe) {4575 while (m.next().? == .Pipe) {
4855 const lhs_node = try macroBoolToInt(c, node);4576 const lhs = try macroBoolToInt(c, node);
4856 const op_token = try appendToken(c, .Pipe, "|");4577 const rhs = try macroBoolToInt(c, try parseCBitXorExpr(c, m, scope));
4857 const rhs_node = try parseCBitXorExpr(c, m, scope);4578 node = try Node.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
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;
4866 }4579 }
4867 m.i -= 1;4580 m.i -= 1;
4868 return node;4581 return node;
4869}4582}
48704583
4871fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4584fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4872 var node = try parseCBitAndExpr(c, m, scope);4585 var node = try parseCBitAndExpr(c, m, scope);
4873 while (m.next().? == .Caret) {4586 while (m.next().? == .Caret) {
4874 const lhs_node = try macroBoolToInt(c, node);4587 const lhs = try macroBoolToInt(c, node);
4875 const op_token = try appendToken(c, .Caret, "^");4588 const rhs = try macroBoolToInt(c, try parseCBitAndExpr(c, m, scope));
4876 const rhs_node = try parseCBitAndExpr(c, m, scope);4589 node = try Node.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
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;
4885 }4590 }
4886 m.i -= 1;4591 m.i -= 1;
4887 return node;4592 return node;
4888}4593}
48894594
4890fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4595fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4891 var node = try parseCEqExpr(c, m, scope);4596 var node = try parseCEqExpr(c, m, scope);
4892 while (m.next().? == .Ampersand) {4597 while (m.next().? == .Ampersand) {
4893 const lhs_node = try macroBoolToInt(c, node);4598 const lhs = try macroBoolToInt(c, node);
4894 const op_token = try appendToken(c, .Ampersand, "&");4599 const rhs = try macroBoolToInt(c, try parseCEqExpr(c, m, scope));
4895 const rhs_node = try parseCEqExpr(c, m, scope);4600 node = try Node.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
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;
4904 }4601 }
4905 m.i -= 1;4602 m.i -= 1;
4906 return node;4603 return node;
4907}4604}
49084605
4909fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4606fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4910 var node = try parseCRelExpr(c, m, scope);4607 var node = try parseCRelExpr(c, m, scope);
4911 while (true) {4608 while (true) {
4912 var op_token: ast.TokenIndex = undefined;
4913 var op_id: ast.Node.Tag = undefined;
4914 switch (m.peek().?) {4609 switch (m.peek().?) {
4915 .BangEqual => {4610 .BangEqual => {
4916 op_token = try appendToken(c, .BangEqual, "!=");4611 _ = m.next();
4917 op_id = .BangEqual;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 });
4918 },4615 },
4919 .EqualEqual => {4616 .EqualEqual => {
4920 op_token = try appendToken(c, .EqualEqual, "==");4617 _ = m.next();
4921 op_id = .EqualEqual;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 });
4922 },4621 },
4923 else => return node,4622 else => return node,
4924 }4623 }
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;
4936 }4624 }
4937}4625}
49384626
4939fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4627fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4940 var node = try parseCShiftExpr(c, m, scope);4628 var node = try parseCShiftExpr(c, m, scope);
4941 while (true) {4629 while (true) {
4942 var op_token: ast.TokenIndex = undefined;
4943 var op_id: ast.Node.Tag = undefined;
4944 switch (m.peek().?) {4630 switch (m.peek().?) {
4945 .AngleBracketRight => {4631 .AngleBracketRight => {
4946 op_token = try appendToken(c, .AngleBracketRight, ">");4632 _ = m.next();
4947 op_id = .GreaterThan;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 });
4948 },4636 },
4949 .AngleBracketRightEqual => {4637 .AngleBracketRightEqual => {
4950 op_token = try appendToken(c, .AngleBracketRightEqual, ">=");4638 _ = m.next();
4951 op_id = .GreaterOrEqual;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 });
4952 },4642 },
4953 .AngleBracketLeft => {4643 .AngleBracketLeft => {
4954 op_token = try appendToken(c, .AngleBracketLeft, "<");4644 _ = m.next();
4955 op_id = .LessThan;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 });
4956 },4648 },
4957 .AngleBracketLeftEqual => {4649 .AngleBracketLeftEqual => {
4958 op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");4650 _ = m.next();
4959 op_id = .LessOrEqual;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 });
4960 },4654 },
4961 else => return node,4655 else => return node,
4962 }4656 }
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;
4974 }4657 }
4975}4658}
49764659
4977fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4660fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4978 var node = try parseCAddSubExpr(c, m, scope);4661 var node = try parseCAddSubExpr(c, m, scope);
4979 while (true) {4662 while (true) {
4980 var op_token: ast.TokenIndex = undefined;
4981 var op_id: ast.Node.Tag = undefined;
4982 switch (m.peek().?) {4663 switch (m.peek().?) {
4983 .AngleBracketAngleBracketLeft => {4664 .AngleBracketAngleBracketLeft => {
4984 op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");4665 _ = m.next();
4985 op_id = .BitShiftLeft;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 });
4986 },4669 },
4987 .AngleBracketAngleBracketRight => {4670 .AngleBracketAngleBracketRight => {
4988 op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");4671 _ = m.next();
4989 op_id = .BitShiftRight;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 });
4990 },4675 },
4991 else => return node,4676 else => return node,
4992 }4677 }
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;
5004 }4678 }
5005}4679}
50064680
5007fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4681fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5008 var node = try parseCMulExpr(c, m, scope);4682 var node = try parseCMulExpr(c, m, scope);
5009 while (true) {4683 while (true) {
5010 var op_token: ast.TokenIndex = undefined;
5011 var op_id: ast.Node.Tag = undefined;
5012 switch (m.peek().?) {4684 switch (m.peek().?) {
5013 .Plus => {4685 .Plus => {
5014 op_token = try appendToken(c, .Plus, "+");4686 _ = m.next();
5015 op_id = .Add;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 });
5016 },4690 },
5017 .Minus => {4691 .Minus => {
5018 op_token = try appendToken(c, .Minus, "-");4692 _ = m.next();
5019 op_id = .Sub;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 });
5020 },4696 },
5021 else => return node,4697 else => return node,
5022 }4698 }
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;
5034 }4699 }
5035}4700}
50364701
5037fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4702fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5038 var node = try parseCUnaryExpr(c, m, scope);4703 var node = try parseCUnaryExpr(c, m, scope);
5039 while (true) {4704 while (true) {
5040 var op_token: ast.TokenIndex = undefined;
5041 var op_id: ast.Node.Tag = undefined;
5042 switch (m.next().?) {4705 switch (m.next().?) {
5043 .Asterisk => {4706 .Asterisk => {
5044 if (m.peek().? == .RParen) {4707 if (m.peek().? == .RParen) {
5045 // type *)4708 // type *)
50464709
5047 // hack to get zig fmt to render a comma in builtin calls
5048 _ = try appendToken(c, .Comma, ",");
5049
5050 // last token of `node`4710 // last token of `node`
5051 const prev_id = m.list[m.i - 1].id;4711 const prev_id = m.list[m.i - 1].id;
50524712
5053 if (prev_id == .Keyword_void) {4713 if (prev_id == .Keyword_void) {
5054 const ptr = try transCreateNodePtrType(c, false, false, .Asterisk);4714 const ptr = try Node.single_pointer.create(c.arena, .{
5055 ptr.rhs = node;4715 .is_const = false,
5056 const optional_node = try transCreateNodeSimplePrefixOp(c, .OptionalType, .QuestionMark, "?");4716 .is_volatile = false,
5057 optional_node.rhs = &ptr.base;4717 .elem_type = node,
5058 return &optional_node.base;4718 });
4719 return Node.optional_type.create(c.arena, ptr);
5059 } else {4720 } else {
5060 const ptr = try transCreateNodePtrType(c, false, false, Token.Id.Identifier);4721 return Node.c_pointer.create(c.arena, .{
5061 ptr.rhs = node;4722 .is_const = false,
5062 return &ptr.base;4723 .is_volatile = false,
4724 .elem_type = node,
4725 });
5063 }4726 }
5064 } else {4727 } else {
5065 // expr * expr4728 // expr * expr
5066 op_token = try appendToken(c, .Asterisk, "*");4729 const lhs = try macroBoolToInt(c, node);
5067 op_id = .BitShiftLeft;4730 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4731 node = try Node.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
5068 }4732 }
5069 },4733 },
5070 .Slash => {4734 .Slash => {
5071 op_id = .Div;4735 const lhs = try macroBoolToInt(c, node);
5072 op_token = try appendToken(c, .Slash, "/");4736 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4737 node = try Node.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
5073 },4738 },
5074 .Percent => {4739 .Percent => {
5075 op_id = .Mod;4740 const lhs = try macroBoolToInt(c, node);
5076 op_token = try appendToken(c, .Percent, "%");4741 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4742 node = try Node.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
5077 },4743 },
5078 else => {4744 else => {
5079 m.i -= 1;4745 m.i -= 1;
5080 return node;4746 return node;
5081 },4747 },
5082 }4748 }
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;
5093 }4749 }
5094}4750}
50954751
5096fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4752fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5097 var node = try parseCPrimaryExpr(c, m, scope);4753 var node = try parseCPrimaryExpr(c, m, scope);
5098 while (true) {4754 while (true) {
5099 switch (m.next().?) {4755 switch (m.next().?) {
...@@ -5103,38 +4759,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N...@@ -5103,38 +4759,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
5103 return error.ParseError;4759 return error.ParseError;
5104 }4760 }
51054761
5106 node = try transCreateNodeFieldAccess(c, node, m.slice());4762 const ident = try Node.identifier.create(c.arena, m.slice());
5107 continue;4763 node = try Node.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
5108 },4764 },
5109 .Arrow => {4765 .Arrow => {
5110 if (m.next().? != .Identifier) {4766 if (m.next().? != .Identifier) {
5111 try m.fail(c, "unable to translate C expr: expected identifier", .{});4767 try m.fail(c, "unable to translate C expr: expected identifier", .{});
5112 return error.ParseError;4768 return error.ParseError;
5113 }4769 }
5114 const deref = try transCreateNodePtrDeref(c, node);4770
5115 node = try transCreateNodeFieldAccess(c, deref, m.slice());4771 const deref = try Node.deref.create(c.arena, node);
5116 continue;4772 const ident = try Node.identifier.create(c.arena, m.slice());
4773 node = try Node.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });
5117 },4774 },
5118 .LBracket => {4775 .LBracket => {
5119 const arr_node = try transCreateNodeArrayAccess(c, node);4776 const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
5120 arr_node.index_expr = try parseCExpr(c, m, scope);4777 node = try Node.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
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;
5128 },4778 },
5129 .LParen => {4779 .LParen => {
5130 _ = try appendToken(c, .LParen, "(");4780 var call_params = std.ArrayList(Node).init(c.gpa);
5131 var call_params = std.ArrayList(*ast.Node).init(c.gpa);
5132 defer call_params.deinit();4781 defer call_params.deinit();
5133 while (true) {4782 while (true) {
5134 const arg = try parseCCondExpr(c, m, scope);4783 const arg = try parseCCondExpr(c, m, scope);
5135 try call_params.append(arg);4784 try call_params.append(arg);
5136 switch (m.next().?) {4785 switch (m.next().?) {
5137 .Comma => _ = try appendToken(c, .Comma, ","),4786 .Comma => {},
5138 .RParen => break,4787 .RParen => break,
5139 else => {4788 else => {
5140 try m.fail(c, "unable to translate C expr: expected ',' or ')'", .{});4789 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...@@ -5142,32 +4791,17 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
5142 },4791 },
5143 }4792 }
5144 }4793 }
5145 const call_node = try ast.Node.Call.alloc(c.arena, call_params.items.len);4794 node = try Node.call.create(c.arena, .{ .lhs = node, .rhs = try c.arena.dupe(Node, call_params.items) });
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;
5155 },4795 },
5156 .LBrace => {4796 .LBrace => {
5157 // must come immediately after `node`4797 var init_vals = std.ArrayList(Node).init(c.gpa);
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);
5164 defer init_vals.deinit();4798 defer init_vals.deinit();
51654799
5166 while (true) {4800 while (true) {
5167 const val = try parseCCondExpr(c, m, scope);4801 const val = try parseCCondExpr(c, m, scope);
5168 try init_vals.append(val);4802 try init_vals.append(val);
5169 switch (m.next().?) {4803 switch (m.next().?) {
5170 .Comma => _ = try appendToken(c, .Comma, ","),4804 .Comma => {},
5171 .RBrace => break,4805 .RBrace => break,
5172 else => {4806 else => {
5173 try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});4807 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...@@ -5175,29 +4809,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
5175 },4809 },
5176 }4810 }
5177 }4811 }
5178 const tuple_node = try ast.Node.StructInitializerDot.alloc(c.arena, init_vals.items.len);4812 const tuple_node = try Node.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));
5179 tuple_node.* = .{4813 node = try Node.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = 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;
5201 },4814 },
5202 .PlusPlus, .MinusMinus => {4815 .PlusPlus, .MinusMinus => {
5203 try m.fail(c, "TODO postfix inc/dec expr", .{});4816 try m.fail(c, "TODO postfix inc/dec expr", .{});
...@@ -5211,35 +4824,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N...@@ -5211,35 +4824,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
5211 }4824 }
5212}4825}
52134826
5214fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {4827fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5215 switch (m.next().?) {4828 switch (m.next().?) {
5216 .Bang => {4829 .Bang => {
5217 const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!");4830 const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
5218 node.rhs = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));4831 return Node.not.create(c.arena, operand);
5219 return &node.base;
5220 },4832 },
5221 .Minus => {4833 .Minus => {
5222 const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-");4834 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
5223 node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4835 return Node.negate.create(c.arena, operand);
5224 return &node.base;
5225 },4836 },
5226 .Plus => return try parseCUnaryExpr(c, m, scope),4837 .Plus => return try parseCUnaryExpr(c, m, scope),
5227 .Tilde => {4838 .Tilde => {
5228 const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~");4839 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
5229 node.rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4840 return Node.bit_not.create(c.arena, operand);
5230 return &node.base;
5231 },4841 },
5232 .Asterisk => {4842 .Asterisk => {
5233 const node = try macroGroup(c, try parseCUnaryExpr(c, m, scope));4843 const operand = try parseCUnaryExpr(c, m, scope);
5234 return try transCreateNodePtrDeref(c, node);4844 return Node.deref.create(c.arena, operand);
5235 },4845 },
5236 .Ampersand => {4846 .Ampersand => {
5237 const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&");4847 const operand = try parseCUnaryExpr(c, m, scope);
5238 node.rhs = try macroGroup(c, try parseCUnaryExpr(c, m, scope));4848 return Node.address_of.create(c.arena, operand);
5239 return &node.base;
5240 },4849 },
5241 .Keyword_sizeof => {4850 .Keyword_sizeof => {
5242 const inner = if (m.peek().? == .LParen) blk: {4851 const operand = if (m.peek().? == .LParen) blk: {
5243 _ = m.next();4852 _ = m.next();
5244 // C grammar says this should be 'type-name' but we have to4853 // C grammar says this should be 'type-name' but we have to
5245 // use parseCMulExpr to correctly handle pointer types.4854 // use parseCMulExpr to correctly handle pointer types.
...@@ -5251,18 +4860,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod...@@ -5251,18 +4860,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
5251 break :blk inner;4860 break :blk inner;
5252 } else try parseCUnaryExpr(c, m, scope);4861 } else try parseCUnaryExpr(c, m, scope);
52534862
5254 //(@import("std").meta.sizeof(dest, x))4863 return Node.std_meta_sizeof.create(c.arena, operand);
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;
5266 },4864 },
5267 .Keyword_alignof => {4865 .Keyword_alignof => {
5268 // TODO this won't work if using <stdalign.h>'s4866 // 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...@@ -5273,16 +4871,13 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
5273 }4871 }
5274 // C grammar says this should be 'type-name' but we have to4872 // C grammar says this should be 'type-name' but we have to
5275 // use parseCMulExpr to correctly handle pointer types.4873 // use parseCMulExpr to correctly handle pointer types.
5276 const inner = try parseCMulExpr(c, m, scope);4874 const operand = try parseCMulExpr(c, m, scope);
5277 if (m.next().? != .RParen) {4875 if (m.next().? != .RParen) {
5278 try m.fail(c, "unable to translate C expr: expected ')'", .{});4876 try m.fail(c, "unable to translate C expr: expected ')'", .{});
5279 return error.ParseError;4877 return error.ParseError;
5280 }4878 }
52814879
5282 const builtin_call = try c.createBuiltinCall("@alignOf", 1);4880 return Node.alignof.create(c.arena, operand);
5283 builtin_call.params()[0] = inner;
5284 builtin_call.rparen_token = try appendToken(c, .RParen, ")");
5285 return &builtin_call.base;
5286 },4881 },
5287 .PlusPlus, .MinusMinus => {4882 .PlusPlus, .MinusMinus => {
5288 try m.fail(c, "TODO unary inc/dec expr", .{});4883 try m.fail(c, "TODO unary inc/dec expr", .{});
...@@ -5295,50 +4890,40 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod...@@ -5295,50 +4890,40 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod
5295 }4890 }
5296}4891}
52974892
5298fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {4893fn getContainer(c: *Context, node: Node) ?Node {
5299 const tok = c.token_locs.items[token];4894 switch (node.tag()) {
5300 const slice = c.source_buffer.items[tok.start..tok.end];4895 .@"union",
5301 return if (mem.startsWith(u8, slice, "@\""))4896 .@"struct",
5302 slice[2 .. slice.len - 1]4897 .@"enum",
5303 else4898 .address_of,
5304 slice;4899 .bit_not,
5305}4900 .not,
53064901 .optional_type,
5307fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {4902 .negate,
5308 switch (node.tag) {4903 .negate_wrap,
5309 .ContainerDecl,4904 .array_type,
5310 .AddressOf,4905 .c_pointer,
5311 .Await,4906 .single_pointer,
5312 .BitNot,
5313 .BoolNot,
5314 .OptionalType,
5315 .Negation,
5316 .NegationWrap,
5317 .Resume,
5318 .Try,
5319 .ArrayType,
5320 .ArrayTypeSentinel,
5321 .PtrType,
5322 .SliceType,
5323 => return node,4907 => return node,
53244908
5325 .Identifier => {4909 .identifier => {
5326 const ident = node.castTag(.Identifier).?;4910 const ident = node.castTag(.identifier).?;
5327 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {4911 if (c.global_scope.sym_table.get(ident.data)) |value| {
5328 if (value.cast(ast.Node.VarDecl)) |var_decl|4912 if (value.castTag(.var_decl)) |var_decl|
5329 return getContainer(c, var_decl.getInitNode().?);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);
5330 }4916 }
5331 },4917 },
53324918
5333 .Period => {4919 .field_access => {
5334 const infix = node.castTag(.Period).?;4920 const infix = node.castTag(.field_access).?;
53354921
5336 if (getContainerTypeOf(c, infix.lhs)) |ty_node| {4922 if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
5337 if (ty_node.cast(ast.Node.ContainerDecl)) |container| {4923 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
5338 for (container.fieldsAndDecls()) |field_ref| {4924 for (container.data.fields) |field| {
5339 const field = field_ref.cast(ast.Node.ContainerField).?;4925 const ident = infix.data.rhs.castTag(.identifier).?;
5340 const ident = infix.rhs.castTag(.Identifier).?;4926 if (mem.eql(u8, field.data.name, field.data)) {
5341 if (mem.eql(u8, tokenSlice(c, field.name_token), tokenSlice(c, ident.token))) {
5342 return getContainer(c, field.type_expr.?);4927 return getContainer(c, field.type_expr.?);
5343 }4928 }
5344 }4929 }
...@@ -5351,22 +4936,20 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {...@@ -5351,22 +4936,20 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
5351 return null;4936 return null;
5352}4937}
53534938
5354fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {4939fn getContainerTypeOf(c: *Context, ref: Node) ?Node {
5355 if (ref.castTag(.Identifier)) |ident| {4940 if (ref.castTag(.identifier)) |ident| {
5356 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {4941 if (c.global_scope.sym_table.get(ident.data)) |value| {
5357 if (value.cast(ast.Node.VarDecl)) |var_decl| {4942 if (value.castTag(.var_decl)) |var_decl| {
5358 if (var_decl.getTypeNode()) |ty|4943 return getContainer(c, var_decl.data.type);
5359 return getContainer(c, ty);
5360 }4944 }
5361 }4945 }
5362 } else if (ref.castTag(.Period)) |infix| {4946 } else if (ref.castTag(.field_access)) |infix| {
5363 if (getContainerTypeOf(c, infix.lhs)) |ty_node| {4947 if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
5364 if (ty_node.cast(ast.Node.ContainerDecl)) |container| {4948 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
5365 for (container.fieldsAndDecls()) |field_ref| {4949 for (container.data.fields) |field| {
5366 const field = field_ref.cast(ast.Node.ContainerField).?;4950 const ident = infix.data.rhs.castTag(.identifier).?;
5367 const ident = infix.rhs.castTag(.Identifier).?;4951 if (mem.eql(u8, field.name, ident.data)) {
5368 if (mem.eql(u8, tokenSlice(c, field.name_token), tokenSlice(c, ident.token))) {4952 return getContainer(c, field.type);
5369 return getContainer(c, field.type_expr.?);
5370 }4953 }
5371 }4954 }
5372 } else4955 } else
...@@ -5376,11 +4959,16 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {...@@ -5376,11 +4959,16 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
5376 return null;4959 return null;
5377}4960}
53784961
5379fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto {4962fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
5380 const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getInitNode().? else return null;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;
5381 if (getContainerTypeOf(c, init)) |ty_node| {4969 if (getContainerTypeOf(c, init)) |ty_node| {
5382 if (ty_node.castTag(.OptionalType)) |prefix| {4970 if (ty_node.castTag(.optional_type)) |prefix| {
5383 if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| {4971 if (prefix.data.castTag(.func)) |fn_proto| {
5384 return fn_proto;4972 return fn_proto;
5385 }4973 }
5386 }4974 }
src/translate_c/ast.zig+33-8
...@@ -47,7 +47,6 @@ pub const Node = extern union {...@@ -47,7 +47,6 @@ pub const Node = extern union {
47 field_access,47 field_access,
48 array_access,48 array_access,
49 call,49 call,
50 std_mem_zeroes,
51 var_decl,50 var_decl,
52 func,51 func,
53 warning,52 warning,
...@@ -57,6 +56,7 @@ pub const Node = extern union {...@@ -57,6 +56,7 @@ pub const Node = extern union {
57 @"struct",56 @"struct",
58 @"union",57 @"union",
59 array_init,58 array_init,
59 tuple,
60 container_init,60 container_init,
61 std_meta_cast,61 std_meta_cast,
62 discard,62 discard,
...@@ -162,6 +162,8 @@ pub const Node = extern union {...@@ -162,6 +162,8 @@ pub const Node = extern union {
162 deref,162 deref,
163163
164 block,164 block,
165 /// { operand }
166 block_single,
165 @"break",167 @"break",
166168
167 sizeof,169 sizeof,
...@@ -173,8 +175,12 @@ pub const Node = extern union {...@@ -173,8 +175,12 @@ pub const Node = extern union {
173 single_pointer,175 single_pointer,
174 array_type,176 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)
177 std_mem_zeroes,181 std_mem_zeroes,
182 /// @import("std").mem.zeroInit(lhs, rhs)
183 std_mem_zeroinit,
178 // pub const name = @compileError(msg);184 // pub const name = @compileError(msg);
179 fail_decl,185 fail_decl,
180 // var actual = mangled;186 // var actual = mangled;
...@@ -188,6 +194,9 @@ pub const Node = extern union {...@@ -188,6 +194,9 @@ pub const Node = extern union {
188 /// pub const enum_field_name = @enumToInt(enum_name.field_name);194 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
189 enum_redecl,195 enum_redecl,
190196
197 /// pub inline fn name(params) return_type body
198 pub_inline_fn,
199
191 /// [0]type{}200 /// [0]type{}
192 empty_array,201 empty_array,
193 /// [1]type{val} ** count202 /// [1]type{val} ** count
...@@ -195,6 +204,7 @@ pub const Node = extern union {...@@ -195,6 +204,7 @@ pub const Node = extern union {
195204
196 /// _ = operand;205 /// _ = operand;
197 ignore,206 ignore,
207 @"anytype",
198208
199 pub const last_no_payload_tag = Tag.usingnamespace_builtins;209 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
200 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;210 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -213,6 +223,7 @@ pub const Node = extern union {...@@ -213,6 +223,7 @@ pub const Node = extern union {
213 .one_literal,223 .one_literal,
214 .void_type,224 .void_type,
215 .noreturn_type,225 .noreturn_type,
226 .@"anytype",
216 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),227 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
217228
218 .std_mem_zeroes,229 .std_mem_zeroes,
...@@ -234,6 +245,7 @@ pub const Node = extern union {...@@ -234,6 +245,7 @@ pub const Node = extern union {
234 .if_not_break,245 .if_not_break,
235 .switch_else,246 .switch_else,
236 .ignore,247 .ignore,
248 .block_single,
237 => Payload.UnOp,249 => Payload.UnOp,
238250
239 .add,251 .add,
...@@ -302,6 +314,8 @@ pub const Node = extern union {...@@ -302,6 +314,8 @@ pub const Node = extern union {
302 .field_access,314 .field_access,
303 .assign,315 .assign,
304 .align_cast,316 .align_cast,
317 .array_access,
318 .std_mem_zeroinit,
305 => Payload.BinOp,319 => Payload.BinOp,
306320
307 .number_literal,321 .number_literal,
...@@ -325,7 +339,7 @@ pub const Node = extern union {...@@ -325,7 +339,7 @@ pub const Node = extern union {
325 .func => Payload.Func,339 .func => Payload.Func,
326 .@"enum" => Payload.Enum,340 .@"enum" => Payload.Enum,
327 .@"struct", .@"union" => Payload.Record,341 .@"struct", .@"union" => Payload.Record,
328 .array_init => Payload.ArrayInit,342 .array_init, .tuple => Payload.ArrayInit,
329 .container_init => Payload.ContainerInit,343 .container_init => Payload.ContainerInit,
330 .std_meta_cast => Payload.Infix,344 .std_meta_cast => Payload.Infix,
331 .block => Payload.Block,345 .block => Payload.Block,
...@@ -336,6 +350,7 @@ pub const Node = extern union {...@@ -336,6 +350,7 @@ pub const Node = extern union {
336 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,350 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
337 .enum_redecl => Payload.EnumRedecl,351 .enum_redecl => Payload.EnumRedecl,
338 .array_filler => Payload.ArrayFiller,352 .array_filler => Payload.ArrayFiller,
353 .pub_inline_fn => Payload.PubInlineFn,
339 };354 };
340 }355 }
341356
...@@ -488,12 +503,12 @@ pub const Payload = struct {...@@ -488,12 +503,12 @@ pub const Payload = struct {
488 body: ?Node,503 body: ?Node,
489 alignment: ?c_uint,504 alignment: ?c_uint,
490 },505 },
506 };
491507
492 pub const Param = struct {508 pub const Param = struct {
493 is_noalias: bool,509 is_noalias: bool,
494 name: ?[]const u8,510 name: ?[]const u8,
495 type: Node,511 type: Node,
496 };
497 };512 };
498513
499 pub const Enum = struct {514 pub const Enum = struct {
...@@ -598,6 +613,16 @@ pub const Payload = struct {...@@ -598,6 +613,16 @@ pub const Payload = struct {
598 count: usize,613 count: usize,
599 },614 },
600 };615 };
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 };
601};626};
602627
603/// Converts the nodes into a Zig ast.628/// Converts the nodes into a Zig ast.