| ... | @@ -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 | } |
| 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 | const scope = &c.global_scope.base; | 3516 | const scope = &c.global_scope.base; |
| 3517 | | 3517 | |
| 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(); |
| 3525 | | 3520 | |
| 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()}); | | |
| 3532 | | 3524 | |
| 3533 | _ = try appendToken(c, .Colon, ":"); | 3525 | try fn_params.append(.{ |
| 3534 | | 3526 | .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 | } |
| 3543 | | 3531 | |
| 3544 | _ = try appendToken(c, .RParen, ")"); | 3532 | const init = if (value.castTag(.var_decl)) |v| |
| 3545 | | 3533 | 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(); | | |
| 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 | 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, .{ |
| 3566 | | 3545 | .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); |
| 3574 | | 3550 | |
| 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 | } |
| 3596 | | 3558 | |
| 3597 | fn transCreateNodeShiftOp( | 3559 | fn 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 { |
| 4108 | fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | 4070 | fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4109 | const scope = &c.global_scope.base; | 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 | 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)}); |
| 4120 | | 4077 | |
| 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 | } |
| 4133 | | 4081 | |
| 4134 | fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | 4082 | fn 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; |
| 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 | 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 | } |
| 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 | defer fn_params.deinit(); | 4092 | defer fn_params.deinit(); |
| 4150 | | 4093 | |
| 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(); |
| 4154 | | 4097 | |
| 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, |
| 4158 | | 4101 | .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 | }; | | |
| 4172 | | 4104 | |
| 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 | } |
| 4177 | | 4108 | |
| 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 | } |
| 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 | 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 | }); | | |
| 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 | 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 | } |
| 4228 | | 4136 | |
| 4229 | const ParseError = Error || error{ParseError}; | 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 | // TODO parseCAssignExpr here | 4140 | // 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(); |
| 4241 | | 4148 | |
| 4242 | var last = node; | 4149 | var last = node; |
| 4243 | while (true) { | 4150 | while (true) { |
| 4244 | // suppress result | 4151 | // 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); | | |
| 4255 | | 4154 | |
| 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 | } |
| 4263 | | 4161 | |
| 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 | } |
| 4268 | | 4169 | |
| 4269 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node { | 4170 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 4270 | var lit_bytes = m.slice(); | 4171 | var lit_bytes = m.slice(); |
| 4271 | | 4172 | |
| 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 | } |
| 4287 | | 4188 | |
| 4288 | if (suffix == .none) { | 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); | 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 | } |
| 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 | 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 correctly | 4406 | // 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 transRecordDecl | 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,17 +4450,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!* |
| 4572 | return error.ParseError; | 4450 | return error.ParseError; |
| 4573 | } | 4451 | } |
| 4574 | | 4452 | |
| 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); |
| 4620 | | 4489 | |
| 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 | } |
| 4625 | | 4494 | |
| 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 | } |
| 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 | 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 identifiers | 4507 | // 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 | } |
| 4679 | | 4518 | |
| 4680 | fn nodeIsInfixOp(tag: ast.Node.Tag) bool { | 4519 | fn 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 | | | |
| 4731 | fn 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 | } |
| 4743 | | 4523 | |
| 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 | } |
| 4749 | | 4526 | |
| 4750 | fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { | 4527 | fn 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 | } |
| 4762 | | 4531 | |
| 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 | | | |
| 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; | | |
| 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 | 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(); |
| 4799 | | 4541 | |
| 4800 | // must come immediately after expr | 4542 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 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 | 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 *) |
| 5046 | | 4709 | |
| 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; |
| 5052 | | 4712 | |
| 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 * expr | 4728 | // 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 | } |
| 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 | 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 | } |
| 5105 | | 4761 | |
| 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(); |
| 5165 | | 4799 | |
| 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 | } |
| 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 | 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 to | 4853 | // 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); |
| 5253 | | 4862 | |
| 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>'s | 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,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 to | 4872 | // 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 | } |
| 5281 | | 4879 | |
| 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 | } |
| 5297 | | 4892 | |
| 5298 | fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 { | 4893 | fn 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 | else | 4898 | .address_of, |
| 5304 | slice; | 4899 | .bit_not, |
| 5305 | } | 4900 | .not, |
| 5306 | | 4901 | .optional_type, |
| 5307 | fn 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, |
| 5324 | | 4908 | |
| 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 | }, |
| 5332 | | 4918 | |
| 5333 | .Period => { | 4919 | .field_access => { |
| 5334 | const infix = node.castTag(.Period).?; | 4920 | const infix = node.castTag(.field_access).?; |
| 5335 | | 4921 | |
| 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 | } |
| 5353 | | 4938 | |
| 5354 | fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { | 4939 | fn 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 | } else | 4955 | } 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 | } |
| 5378 | | 4961 | |
| 5379 | fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto { | 4962 | fn 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 | } |