| ... | ... | @@ -3512,86 +3512,48 @@ fn transCreateNodeNumber(c: *Context, int: anytype) !Node { |
| 3512 | 3512 | return Node.int_literal.create(c.arena, str); |
| 3513 | 3513 | } |
| 3514 | 3514 | |
| 3515 | | fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_alias: *ast.Node.FnProto) !*ast.Node { |
| 3515 | fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node { |
| 3516 | 3516 | const scope = &c.global_scope.base; |
| 3517 | 3517 | |
| 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); |
| 3524 | 3519 | defer fn_params.deinit(); |
| 3525 | 3520 | |
| 3526 | 3521 | 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()}); |
| 3532 | 3524 | |
| 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 | }); |
| 3542 | 3530 | } |
| 3543 | 3531 | |
| 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; |
| 3558 | 3538 | |
| 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 | 3541 | 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); |
| 3564 | 3543 | } |
| 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, |
| 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); |
| 3574 | 3550 | |
| 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), |
| 3586 | 3554 | .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, |
| 3592 | 3556 | }); |
| 3593 | | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); |
| 3594 | | return &fn_proto.base; |
| 3595 | 3557 | } |
| 3596 | 3558 | |
| 3597 | 3559 | fn transCreateNodeShiftOp( |
| ... | ... | @@ -4108,27 +4070,13 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 4108 | 4070 | fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4109 | 4071 | const scope = &c.global_scope.base; |
| 4110 | 4072 | |
| 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 | 4073 | const init_node = try parseCExpr(c, m, scope); |
| 4117 | 4074 | const last = m.next().?; |
| 4118 | 4075 | if (last != .Eof and last != .Nl) |
| 4119 | 4076 | return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)}); |
| 4120 | 4077 | |
| 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); |
| 4132 | 4080 | } |
| 4133 | 4081 | |
| 4134 | 4082 | fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| ... | ... | @@ -4136,16 +4084,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4136 | 4084 | defer block_scope.deinit(); |
| 4137 | 4085 | const scope = &block_scope.base; |
| 4138 | 4086 | |
| 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 | 4087 | if (m.next().? != .LParen) { |
| 4145 | 4088 | return m.fail(c, "unable to translate C expr: expected '('", .{}); |
| 4146 | 4089 | } |
| 4147 | 4090 | |
| 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 | 4092 | defer fn_params.deinit(); |
| 4150 | 4093 | |
| 4151 | 4094 | while (true) { |
| ... | ... | @@ -4153,120 +4096,78 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4153 | 4096 | _ = m.next(); |
| 4154 | 4097 | |
| 4155 | 4098 | 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 | }); |
| 4172 | 4104 | |
| 4173 | 4105 | if (m.peek().? != .Comma) break; |
| 4174 | 4106 | _ = m.next(); |
| 4175 | | _ = try appendToken(c, .Comma, ","); |
| 4176 | 4107 | } |
| 4177 | 4108 | |
| 4178 | 4109 | if (m.next().? != .RParen) { |
| 4179 | 4110 | return m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 4180 | 4111 | } |
| 4181 | 4112 | |
| 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 | 4113 | const expr = try parseCExpr(c, m, scope); |
| 4193 | 4114 | const last = m.next().?; |
| 4194 | 4115 | if (last != .Eof and last != .Nl) |
| 4195 | 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 | | }); |
| 4211 | 4117 | |
| 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 | 4126 | 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), |
| 4223 | 4133 | }); |
| 4224 | | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); |
| 4225 | | |
| 4226 | 4134 | _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base); |
| 4227 | 4135 | } |
| 4228 | 4136 | |
| 4229 | 4137 | const ParseError = Error || error{ParseError}; |
| 4230 | 4138 | |
| 4231 | | fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4139 | fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4232 | 4140 | // TODO parseCAssignExpr here |
| 4233 | 4141 | const node = try parseCCondExpr(c, m, scope); |
| 4234 | 4142 | if (m.next().? != .Comma) { |
| 4235 | 4143 | m.i -= 1; |
| 4236 | 4144 | return node; |
| 4237 | 4145 | } |
| 4238 | | _ = try appendToken(c, .Semicolon, ";"); |
| 4239 | 4146 | var block_scope = try Scope.Block.init(c, scope, true); |
| 4240 | 4147 | defer block_scope.deinit(); |
| 4241 | 4148 | |
| 4242 | 4149 | var last = node; |
| 4243 | 4150 | while (true) { |
| 4244 | 4151 | // 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); |
| 4255 | 4154 | |
| 4256 | 4155 | last = try parseCCondExpr(c, m, scope); |
| 4257 | | _ = try appendToken(c, .Semicolon, ";"); |
| 4258 | 4156 | if (m.next().? != .Comma) { |
| 4259 | 4157 | m.i -= 1; |
| 4260 | 4158 | break; |
| 4261 | 4159 | } |
| 4262 | 4160 | } |
| 4263 | 4161 | |
| 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); |
| 4266 | 4167 | return try block_scope.complete(c); |
| 4267 | 4168 | } |
| 4268 | 4169 | |
| 4269 | | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { |
| 4170 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 4270 | 4171 | var lit_bytes = m.slice(); |
| 4271 | 4172 | |
| 4272 | 4173 | switch (m.list[m.i].id) { |
| ... | ... | @@ -4286,11 +4187,10 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { |
| 4286 | 4187 | } |
| 4287 | 4188 | |
| 4288 | 4189 | if (suffix == .none) { |
| 4289 | | return transCreateNodeInt(c, lit_bytes); |
| 4190 | return transCreateNodeNumber(c, lit_bytes); |
| 4290 | 4191 | } |
| 4291 | 4192 | |
| 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) { |
| 4294 | 4194 | .u => "c_uint", |
| 4295 | 4195 | .l => "c_long", |
| 4296 | 4196 | .lu => "c_ulong", |
| ... | ... | @@ -4304,27 +4204,22 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { |
| 4304 | 4204 | .llu => 3, |
| 4305 | 4205 | else => unreachable, |
| 4306 | 4206 | }]; |
| 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 }); |
| 4311 | 4209 | }, |
| 4312 | 4210 | .FloatLiteral => |suffix| { |
| 4313 | 4211 | if (lit_bytes[0] == '.') |
| 4314 | 4212 | lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes}); |
| 4315 | 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); |
| 4319 | | cast_node.params()[0] = try transCreateNodeIdentifier(c, switch (suffix) { |
| 4216 | const type_node = try Node.type.create(c.arena, switch (suffix) { |
| 4320 | 4217 | .f => "f32", |
| 4321 | 4218 | .l => "c_longdouble", |
| 4322 | 4219 | else => unreachable, |
| 4323 | 4220 | }); |
| 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 }); |
| 4328 | 4223 | }, |
| 4329 | 4224 | else => unreachable, |
| 4330 | 4225 | } |
| ... | ... | @@ -4490,79 +4385,62 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 4490 | 4385 | return bytes[0..i]; |
| 4491 | 4386 | } |
| 4492 | 4387 | |
| 4493 | | fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4388 | fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4494 | 4389 | const tok = m.next().?; |
| 4495 | 4390 | const slice = m.slice(); |
| 4496 | 4391 | switch (tok) { |
| 4497 | 4392 | .CharLiteral => { |
| 4498 | 4393 | 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)); |
| 4506 | 4395 | } 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); |
| 4514 | 4398 | } |
| 4515 | 4399 | }, |
| 4516 | 4400 | .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)); |
| 4524 | 4402 | }, |
| 4525 | 4403 | .IntegerLiteral, .FloatLiteral => { |
| 4526 | 4404 | return parseCNumLit(c, m); |
| 4527 | 4405 | }, |
| 4528 | 4406 | // 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"), |
| 4537 | 4415 | .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"), |
| 4541 | 4419 | .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) { |
| 4542 | 4420 | _ = 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"), |
| 4545 | 4423 | else => { |
| 4546 | 4424 | m.i -= 1; |
| 4547 | | return transCreateNodeIdentifierUnchecked(c, "c_uint"); |
| 4425 | return Node.type.create(c.arena, "c_uint"); |
| 4548 | 4426 | }, |
| 4549 | 4427 | } else { |
| 4550 | | return transCreateNodeIdentifierUnchecked(c, "c_uint"); |
| 4428 | return Node.type.create(c.arena, "c_uint"); |
| 4551 | 4429 | }, |
| 4552 | 4430 | .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"), |
| 4556 | 4434 | .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) { |
| 4557 | 4435 | _ = 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"), |
| 4560 | 4438 | else => { |
| 4561 | 4439 | m.i -= 1; |
| 4562 | | return transCreateNodeIdentifierUnchecked(c, "c_int"); |
| 4440 | return Node.type.create(c.arena, "c_int"); |
| 4563 | 4441 | }, |
| 4564 | 4442 | } else { |
| 4565 | | return transCreateNodeIdentifierUnchecked(c, "c_int"); |
| 4443 | return Node.type.create(c.arena, "c_int"); |
| 4566 | 4444 | }, |
| 4567 | 4445 | .Keyword_enum, .Keyword_struct, .Keyword_union => { |
| 4568 | 4446 | // struct Foo will be declared as struct_Foo by transRecordDecl |
| ... | ... | @@ -4572,17 +4450,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!* |
| 4572 | 4450 | return error.ParseError; |
| 4573 | 4451 | } |
| 4574 | 4452 | |
| 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); |
| 4582 | 4455 | }, |
| 4583 | 4456 | .Identifier => { |
| 4584 | 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 | 4460 | .LParen => { |
| 4588 | 4461 | const inner_node = try parseCExpr(c, m, scope); |
| ... | ... | @@ -4612,10 +4485,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!* |
| 4612 | 4485 | }, |
| 4613 | 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 | 4488 | const node_to_cast = try parseCExpr(c, m, scope); |
| 4620 | 4489 | |
| 4621 | 4490 | if (saw_l_paren and m.next().? != .RParen) { |
| ... | ... | @@ -4623,28 +4492,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!* |
| 4623 | 4492 | return error.ParseError; |
| 4624 | 4493 | } |
| 4625 | 4494 | |
| 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 }); |
| 4648 | 4496 | }, |
| 4649 | 4497 | else => { |
| 4650 | 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 | 4501 | } |
| 4654 | 4502 | } |
| 4655 | 4503 | |
| 4656 | | fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4504 | fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4657 | 4505 | var node = try parseCPrimaryExprInner(c, m, scope); |
| 4658 | 4506 | // In C the preprocessor would handle concatting strings while expanding macros. |
| 4659 | 4507 | // This should do approximately the same by concatting any strings and identifiers |
| 4660 | 4508 | // after a primary expression. |
| 4661 | 4509 | while (true) { |
| 4662 | | var op_token: ast.TokenIndex = undefined; |
| 4663 | | var op_id: ast.Node.Tag = undefined; |
| 4664 | 4510 | switch (m.peek().?) { |
| 4665 | 4511 | .StringLiteral, .Identifier => {}, |
| 4666 | 4512 | else => break, |
| 4667 | 4513 | } |
| 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) }); |
| 4676 | 4515 | } |
| 4677 | 4516 | return node; |
| 4678 | 4517 | } |
| 4679 | 4518 | |
| 4680 | | fn 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 | | |
| 4731 | | fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { |
| 4519 | fn macroBoolToInt(c: *Context, node: Node) !Node { |
| 4732 | 4520 | 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; |
| 4742 | 4522 | } |
| 4743 | 4523 | |
| 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); |
| 4748 | 4525 | } |
| 4749 | 4526 | |
| 4750 | | fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { |
| 4527 | fn macroIntToBool(c: *Context, node: Node) !Node { |
| 4751 | 4528 | 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; |
| 4761 | 4530 | } |
| 4762 | 4531 | |
| 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 | | |
| 4781 | | fn 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() }); |
| 4791 | 4533 | } |
| 4792 | 4534 | |
| 4793 | | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4535 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4794 | 4536 | const node = try parseCOrExpr(c, m, scope); |
| 4795 | 4537 | if (m.peek().? != .QuestionMark) { |
| 4796 | 4538 | return node; |
| 4797 | 4539 | } |
| 4798 | 4540 | _ = m.next(); |
| 4799 | 4541 | |
| 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); |
| 4805 | 4543 | if (m.next().? != .Colon) { |
| 4806 | 4544 | try m.fail(c, "unable to translate C expr: expected ':'", .{}); |
| 4807 | 4545 | return error.ParseError; |
| 4808 | 4546 | } |
| 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 }); |
| 4812 | 4549 | } |
| 4813 | 4550 | |
| 4814 | | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4551 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4815 | 4552 | var node = try parseCAndExpr(c, m, scope); |
| 4816 | 4553 | 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 }); |
| 4828 | 4557 | } |
| 4829 | 4558 | m.i -= 1; |
| 4830 | 4559 | return node; |
| 4831 | 4560 | } |
| 4832 | 4561 | |
| 4833 | | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4562 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4834 | 4563 | var node = try parseCBitOrExpr(c, m, scope); |
| 4835 | 4564 | 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 }); |
| 4847 | 4568 | } |
| 4848 | 4569 | m.i -= 1; |
| 4849 | 4570 | return node; |
| 4850 | 4571 | } |
| 4851 | 4572 | |
| 4852 | | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4573 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4853 | 4574 | var node = try parseCBitXorExpr(c, m, scope); |
| 4854 | 4575 | 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 }); |
| 4866 | 4579 | } |
| 4867 | 4580 | m.i -= 1; |
| 4868 | 4581 | return node; |
| 4869 | 4582 | } |
| 4870 | 4583 | |
| 4871 | | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4584 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4872 | 4585 | var node = try parseCBitAndExpr(c, m, scope); |
| 4873 | 4586 | 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 }); |
| 4885 | 4590 | } |
| 4886 | 4591 | m.i -= 1; |
| 4887 | 4592 | return node; |
| 4888 | 4593 | } |
| 4889 | 4594 | |
| 4890 | | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4595 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4891 | 4596 | var node = try parseCEqExpr(c, m, scope); |
| 4892 | 4597 | 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 }); |
| 4904 | 4601 | } |
| 4905 | 4602 | m.i -= 1; |
| 4906 | 4603 | return node; |
| 4907 | 4604 | } |
| 4908 | 4605 | |
| 4909 | | fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4606 | fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4910 | 4607 | var node = try parseCRelExpr(c, m, scope); |
| 4911 | 4608 | while (true) { |
| 4912 | | var op_token: ast.TokenIndex = undefined; |
| 4913 | | var op_id: ast.Node.Tag = undefined; |
| 4914 | 4609 | switch (m.peek().?) { |
| 4915 | 4610 | .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 }); |
| 4918 | 4615 | }, |
| 4919 | 4616 | .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 }); |
| 4922 | 4621 | }, |
| 4923 | 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 | } |
| 4938 | 4626 | |
| 4939 | | fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4627 | fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4940 | 4628 | var node = try parseCShiftExpr(c, m, scope); |
| 4941 | 4629 | while (true) { |
| 4942 | | var op_token: ast.TokenIndex = undefined; |
| 4943 | | var op_id: ast.Node.Tag = undefined; |
| 4944 | 4630 | switch (m.peek().?) { |
| 4945 | 4631 | .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 }); |
| 4948 | 4636 | }, |
| 4949 | 4637 | .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 }); |
| 4952 | 4642 | }, |
| 4953 | 4643 | .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 }); |
| 4956 | 4648 | }, |
| 4957 | 4649 | .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 }); |
| 4960 | 4654 | }, |
| 4961 | 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 | } |
| 4976 | 4659 | |
| 4977 | | fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4660 | fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4978 | 4661 | var node = try parseCAddSubExpr(c, m, scope); |
| 4979 | 4662 | while (true) { |
| 4980 | | var op_token: ast.TokenIndex = undefined; |
| 4981 | | var op_id: ast.Node.Tag = undefined; |
| 4982 | 4663 | switch (m.peek().?) { |
| 4983 | 4664 | .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 }); |
| 4986 | 4669 | }, |
| 4987 | 4670 | .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 }); |
| 4990 | 4675 | }, |
| 4991 | 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 | } |
| 5006 | 4680 | |
| 5007 | | fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4681 | fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5008 | 4682 | var node = try parseCMulExpr(c, m, scope); |
| 5009 | 4683 | while (true) { |
| 5010 | | var op_token: ast.TokenIndex = undefined; |
| 5011 | | var op_id: ast.Node.Tag = undefined; |
| 5012 | 4684 | switch (m.peek().?) { |
| 5013 | 4685 | .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 }); |
| 5016 | 4690 | }, |
| 5017 | 4691 | .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 }); |
| 5020 | 4696 | }, |
| 5021 | 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 | } |
| 5036 | 4701 | |
| 5037 | | fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4702 | fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5038 | 4703 | var node = try parseCUnaryExpr(c, m, scope); |
| 5039 | 4704 | while (true) { |
| 5040 | | var op_token: ast.TokenIndex = undefined; |
| 5041 | | var op_id: ast.Node.Tag = undefined; |
| 5042 | 4705 | switch (m.next().?) { |
| 5043 | 4706 | .Asterisk => { |
| 5044 | 4707 | if (m.peek().? == .RParen) { |
| 5045 | 4708 | // type *) |
| 5046 | 4709 | |
| 5047 | | // hack to get zig fmt to render a comma in builtin calls |
| 5048 | | _ = try appendToken(c, .Comma, ","); |
| 5049 | | |
| 5050 | 4710 | // last token of `node` |
| 5051 | 4711 | const prev_id = m.list[m.i - 1].id; |
| 5052 | 4712 | |
| 5053 | 4713 | 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); |
| 5059 | 4720 | } 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 | }); |
| 5063 | 4726 | } |
| 5064 | 4727 | } else { |
| 5065 | 4728 | // 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 }); |
| 5068 | 4732 | } |
| 5069 | 4733 | }, |
| 5070 | 4734 | .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 }); |
| 5073 | 4738 | }, |
| 5074 | 4739 | .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 }); |
| 5077 | 4743 | }, |
| 5078 | 4744 | else => { |
| 5079 | 4745 | m.i -= 1; |
| 5080 | 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 | } |
| 5095 | 4751 | |
| 5096 | | fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4752 | fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5097 | 4753 | var node = try parseCPrimaryExpr(c, m, scope); |
| 5098 | 4754 | while (true) { |
| 5099 | 4755 | switch (m.next().?) { |
| ... | ... | @@ -5103,38 +4759,31 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N |
| 5103 | 4759 | return error.ParseError; |
| 5104 | 4760 | } |
| 5105 | 4761 | |
| 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 }); |
| 5108 | 4764 | }, |
| 5109 | 4765 | .Arrow => { |
| 5110 | 4766 | if (m.next().? != .Identifier) { |
| 5111 | 4767 | try m.fail(c, "unable to translate C expr: expected identifier", .{}); |
| 5112 | 4768 | return error.ParseError; |
| 5113 | 4769 | } |
| 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 }); |
| 5117 | 4774 | }, |
| 5118 | 4775 | .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 }); |
| 5128 | 4778 | }, |
| 5129 | 4779 | .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); |
| 5132 | 4781 | defer call_params.deinit(); |
| 5133 | 4782 | while (true) { |
| 5134 | 4783 | const arg = try parseCCondExpr(c, m, scope); |
| 5135 | 4784 | try call_params.append(arg); |
| 5136 | 4785 | switch (m.next().?) { |
| 5137 | | .Comma => _ = try appendToken(c, .Comma, ","), |
| 4786 | .Comma => {}, |
| 5138 | 4787 | .RParen => break, |
| 5139 | 4788 | else => { |
| 5140 | 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 | 4791 | }, |
| 5143 | 4792 | } |
| 5144 | 4793 | } |
| 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) }); |
| 5155 | 4795 | }, |
| 5156 | 4796 | .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); |
| 5164 | 4798 | defer init_vals.deinit(); |
| 5165 | 4799 | |
| 5166 | 4800 | while (true) { |
| 5167 | 4801 | const val = try parseCCondExpr(c, m, scope); |
| 5168 | 4802 | try init_vals.append(val); |
| 5169 | 4803 | switch (m.next().?) { |
| 5170 | | .Comma => _ = try appendToken(c, .Comma, ","), |
| 4804 | .Comma => {}, |
| 5171 | 4805 | .RBrace => break, |
| 5172 | 4806 | else => { |
| 5173 | 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 | 4809 | }, |
| 5176 | 4810 | } |
| 5177 | 4811 | } |
| 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 }); |
| 5201 | 4814 | }, |
| 5202 | 4815 | .PlusPlus, .MinusMinus => { |
| 5203 | 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 | 4824 | } |
| 5212 | 4825 | } |
| 5213 | 4826 | |
| 5214 | | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 4827 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5215 | 4828 | switch (m.next().?) { |
| 5216 | 4829 | .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); |
| 5220 | 4832 | }, |
| 5221 | 4833 | .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); |
| 5225 | 4836 | }, |
| 5226 | 4837 | .Plus => return try parseCUnaryExpr(c, m, scope), |
| 5227 | 4838 | .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); |
| 5231 | 4841 | }, |
| 5232 | 4842 | .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); |
| 5235 | 4845 | }, |
| 5236 | 4846 | .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); |
| 5240 | 4849 | }, |
| 5241 | 4850 | .Keyword_sizeof => { |
| 5242 | | const inner = if (m.peek().? == .LParen) blk: { |
| 4851 | const operand = if (m.peek().? == .LParen) blk: { |
| 5243 | 4852 | _ = m.next(); |
| 5244 | 4853 | // C grammar says this should be 'type-name' but we have to |
| 5245 | 4854 | // use parseCMulExpr to correctly handle pointer types. |
| ... | ... | @@ -5251,18 +4860,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Nod |
| 5251 | 4860 | break :blk inner; |
| 5252 | 4861 | } else try parseCUnaryExpr(c, m, scope); |
| 5253 | 4862 | |
| 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); |
| 5266 | 4864 | }, |
| 5267 | 4865 | .Keyword_alignof => { |
| 5268 | 4866 | // 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 | 4871 | } |
| 5274 | 4872 | // C grammar says this should be 'type-name' but we have to |
| 5275 | 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 | 4875 | if (m.next().? != .RParen) { |
| 5278 | 4876 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 5279 | 4877 | return error.ParseError; |
| 5280 | 4878 | } |
| 5281 | 4879 | |
| 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); |
| 5286 | 4881 | }, |
| 5287 | 4882 | .PlusPlus, .MinusMinus => { |
| 5288 | 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 | 4890 | } |
| 5296 | 4891 | } |
| 5297 | 4892 | |
| 5298 | | fn 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 | | |
| 5307 | | fn 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, |
| 4893 | fn 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, |
| 5323 | 4907 | => return node, |
| 5324 | 4908 | |
| 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); |
| 5330 | 4916 | } |
| 5331 | 4917 | }, |
| 5332 | 4918 | |
| 5333 | | .Period => { |
| 5334 | | const infix = node.castTag(.Period).?; |
| 4919 | .field_access => { |
| 4920 | const infix = node.castTag(.field_access).?; |
| 5335 | 4921 | |
| 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)) { |
| 5342 | 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 | 4936 | return null; |
| 5352 | 4937 | } |
| 5353 | 4938 | |
| 5354 | | fn 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); |
| 4939 | fn 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); |
| 5360 | 4944 | } |
| 5361 | 4945 | } |
| 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); |
| 5370 | 4953 | } |
| 5371 | 4954 | } |
| 5372 | 4955 | } else |
| ... | ... | @@ -5376,11 +4959,16 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 5376 | 4959 | return null; |
| 5377 | 4960 | } |
| 5378 | 4961 | |
| 5379 | | fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto { |
| 5380 | | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getInitNode().? else return null; |
| 4962 | fn 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; |
| 5381 | 4969 | 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| { |
| 5384 | 4972 | return fn_proto; |
| 5385 | 4973 | } |
| 5386 | 4974 | } |