| ... | ... | @@ -182,7 +182,7 @@ const Scope = struct { |
| 182 | 182 | } |
| 183 | 183 | }; |
| 184 | 184 | |
| 185 | | const Context = struct { |
| 185 | pub const Context = struct { |
| 186 | 186 | tree: *ast.Tree, |
| 187 | 187 | source_buffer: *std.Buffer, |
| 188 | 188 | err: Error, |
| ... | ... | @@ -3921,7 +3921,7 @@ fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []cons |
| 3921 | 3921 | _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, args_prefix ++ args); |
| 3922 | 3922 | } |
| 3923 | 3923 | |
| 3924 | | fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: var) !void { |
| 3924 | pub fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: var) !void { |
| 3925 | 3925 | // const name = @compileError(msg); |
| 3926 | 3926 | const const_tok = try appendToken(c, .Keyword_const, "const"); |
| 3927 | 3927 | const name_tok = try appendIdentifier(c, name); |
| ... | ... | @@ -4091,10 +4091,9 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4091 | 4091 | continue; |
| 4092 | 4092 | } |
| 4093 | 4093 | const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); |
| 4094 | | ctok.tokenizeCMacro(&tok_list, begin_c) catch |err| switch (err) { |
| 4094 | ctok.tokenizeCMacro(c, begin_loc, checked_name, &tok_list, begin_c) catch |err| switch (err) { |
| 4095 | 4095 | error.OutOfMemory => |e| return e, |
| 4096 | 4096 | else => { |
| 4097 | | try failDecl(c, begin_loc, checked_name, "unable to tokenize macro definition", .{}); |
| 4098 | 4097 | continue; |
| 4099 | 4098 | }, |
| 4100 | 4099 | }; |
| ... | ... | @@ -4127,9 +4126,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4127 | 4126 | transMacroFnDefine(c, &tok_it, checked_name, begin_loc) |
| 4128 | 4127 | else |
| 4129 | 4128 | transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) { |
| 4130 | | error.UnsupportedTranslation, |
| 4131 | | error.ParseError, |
| 4132 | | => try failDecl(c, begin_loc, checked_name, "unable to translate macro", .{}), |
| 4129 | error.ParseError => continue, |
| 4133 | 4130 | error.OutOfMemory => |e| return e, |
| 4134 | 4131 | }; |
| 4135 | 4132 | }, |
| ... | ... | @@ -4139,20 +4136,19 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4139 | 4136 | } |
| 4140 | 4137 | |
| 4141 | 4138 | fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 4142 | | const rp = makeRestorePoint(c); |
| 4143 | 4139 | const scope = &c.global_scope.base; |
| 4144 | 4140 | |
| 4145 | 4141 | const node = try transCreateNodeVarDecl(c, true, true, name); |
| 4146 | 4142 | node.eq_token = try appendToken(c, .Equal, "="); |
| 4147 | 4143 | |
| 4148 | | node.init_node = try parseCExpr(rp, it, source_loc, scope); |
| 4144 | node.init_node = try parseCExpr(c, it, source_loc, scope); |
| 4149 | 4145 | const last = it.next().?; |
| 4150 | 4146 | if (last.id != .Eof) |
| 4151 | | return revertAndWarn( |
| 4152 | | rp, |
| 4153 | | error.UnsupportedTranslation, |
| 4147 | return failDecl( |
| 4148 | c, |
| 4154 | 4149 | source_loc, |
| 4155 | | "unable to translate C expr, unexpected token: {}", |
| 4150 | name, |
| 4151 | "unable to translate C expr: unexpected token {}", |
| 4156 | 4152 | .{last.id}, |
| 4157 | 4153 | ); |
| 4158 | 4154 | |
| ... | ... | @@ -4161,7 +4157,6 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, |
| 4161 | 4157 | } |
| 4162 | 4158 | |
| 4163 | 4159 | fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 4164 | | const rp = makeRestorePoint(c); |
| 4165 | 4160 | const block_scope = try Scope.Block.init(c, &c.global_scope.base, null); |
| 4166 | 4161 | const scope = &block_scope.base; |
| 4167 | 4162 | |
| ... | ... | @@ -4172,13 +4167,26 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 4172 | 4167 | _ = try appendToken(c, .LParen, "("); |
| 4173 | 4168 | |
| 4174 | 4169 | if (it.next().?.id != .LParen) { |
| 4175 | | return error.ParseError; |
| 4170 | return failDecl( |
| 4171 | c, |
| 4172 | source_loc, |
| 4173 | name, |
| 4174 | "unable to translate C expr: expected '('", |
| 4175 | .{}, |
| 4176 | ); |
| 4176 | 4177 | } |
| 4177 | 4178 | var fn_params = ast.Node.FnProto.ParamList.init(c.a()); |
| 4178 | 4179 | while (true) { |
| 4179 | 4180 | const param_tok = it.next().?; |
| 4180 | | if (param_tok.id != .Identifier) |
| 4181 | | return error.ParseError; |
| 4181 | if (param_tok.id != .Identifier) { |
| 4182 | return failDecl( |
| 4183 | c, |
| 4184 | source_loc, |
| 4185 | name, |
| 4186 | "unable to translate C expr: expected identifier", |
| 4187 | .{}, |
| 4188 | ); |
| 4189 | } |
| 4182 | 4190 | |
| 4183 | 4191 | const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: { |
| 4184 | 4192 | try block_scope.variables.push(.{ .name = param_tok.bytes, .alias = alias }); |
| ... | ... | @@ -4213,7 +4221,13 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 4213 | 4221 | } |
| 4214 | 4222 | |
| 4215 | 4223 | if (it.next().?.id != .RParen) { |
| 4216 | | return error.ParseError; |
| 4224 | return failDecl( |
| 4225 | c, |
| 4226 | source_loc, |
| 4227 | name, |
| 4228 | "unable to translate C expr: expected ')'", |
| 4229 | .{}, |
| 4230 | ); |
| 4217 | 4231 | } |
| 4218 | 4232 | |
| 4219 | 4233 | _ = try appendToken(c, .RParen, ")"); |
| ... | ... | @@ -4241,14 +4255,14 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 4241 | 4255 | const block = try transCreateNodeBlock(c, null); |
| 4242 | 4256 | |
| 4243 | 4257 | const return_expr = try transCreateNodeReturnExpr(c); |
| 4244 | | const expr = try parseCExpr(rp, it, source_loc, scope); |
| 4258 | const expr = try parseCExpr(c, it, source_loc, scope); |
| 4245 | 4259 | const last = it.next().?; |
| 4246 | 4260 | if (last.id != .Eof) |
| 4247 | | return revertAndWarn( |
| 4248 | | rp, |
| 4249 | | error.UnsupportedTranslation, |
| 4261 | return failDecl( |
| 4262 | c, |
| 4250 | 4263 | source_loc, |
| 4251 | | "unable to translate C expr, unexpected token: {}", |
| 4264 | name, |
| 4265 | "unable to translate C expr: unexpected token {}", |
| 4252 | 4266 | .{last.id}, |
| 4253 | 4267 | ); |
| 4254 | 4268 | _ = try appendToken(c, .Semicolon, ";"); |
| ... | ... | @@ -4261,31 +4275,28 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 4261 | 4275 | _ = try c.global_scope.macro_table.put(name, &fn_proto.base); |
| 4262 | 4276 | } |
| 4263 | 4277 | |
| 4264 | | const ParseError = Error || error{ |
| 4265 | | ParseError, |
| 4266 | | UnsupportedTranslation, |
| 4267 | | }; |
| 4278 | const ParseError = Error || error{ParseError}; |
| 4268 | 4279 | |
| 4269 | | fn parseCExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4270 | | return parseCPrefixOpExpr(rp, it, source_loc, scope); |
| 4280 | fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4281 | return parseCPrefixOpExpr(c, it, source_loc, scope); |
| 4271 | 4282 | } |
| 4272 | 4283 | |
| 4273 | | fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node { |
| 4284 | fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node { |
| 4274 | 4285 | if (tok.id == .NumLitInt) { |
| 4275 | 4286 | if (tok.num_lit_suffix == .None) { |
| 4276 | 4287 | if (tok.bytes.len > 2 and tok.bytes[0] == '0') { |
| 4277 | 4288 | switch (tok.bytes[1]) { |
| 4278 | 4289 | '0'...'7' => { |
| 4279 | 4290 | // octal |
| 4280 | | return transCreateNodeInt(rp.c, try std.fmt.allocPrint(rp.c.a(), "0o{}", .{tok.bytes})); |
| 4291 | return transCreateNodeInt(c, try std.fmt.allocPrint(c.a(), "0o{}", .{tok.bytes})); |
| 4281 | 4292 | }, |
| 4282 | 4293 | else => {}, |
| 4283 | 4294 | } |
| 4284 | 4295 | } |
| 4285 | | return transCreateNodeInt(rp.c, tok.bytes); |
| 4296 | return transCreateNodeInt(c, tok.bytes); |
| 4286 | 4297 | } |
| 4287 | | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| 4288 | | try cast_node.params.push(try transCreateNodeIdentifier(rp.c, switch (tok.num_lit_suffix) { |
| 4298 | const cast_node = try transCreateNodeBuiltinFnCall(c, "@as"); |
| 4299 | try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) { |
| 4289 | 4300 | .U => "c_uint", |
| 4290 | 4301 | .L => "c_long", |
| 4291 | 4302 | .LU => "c_ulong", |
| ... | ... | @@ -4293,62 +4304,55 @@ fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocati |
| 4293 | 4304 | .LLU => "c_ulonglong", |
| 4294 | 4305 | else => unreachable, |
| 4295 | 4306 | })); |
| 4296 | | _ = try appendToken(rp.c, .Comma, ","); |
| 4297 | | try cast_node.params.push(try transCreateNodeInt(rp.c, tok.bytes)); |
| 4298 | | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 4307 | _ = try appendToken(c, .Comma, ","); |
| 4308 | try cast_node.params.push(try transCreateNodeInt(c, tok.bytes)); |
| 4309 | cast_node.rparen_token = try appendToken(c, .RParen, ")"); |
| 4299 | 4310 | return &cast_node.base; |
| 4300 | 4311 | } else if (tok.id == .NumLitFloat) { |
| 4301 | 4312 | if (tok.num_lit_suffix == .None) { |
| 4302 | | return transCreateNodeFloat(rp.c, tok.bytes); |
| 4313 | return transCreateNodeFloat(c, tok.bytes); |
| 4303 | 4314 | } |
| 4304 | | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| 4305 | | try cast_node.params.push(try transCreateNodeIdentifier(rp.c, switch (tok.num_lit_suffix) { |
| 4315 | const cast_node = try transCreateNodeBuiltinFnCall(c, "@as"); |
| 4316 | try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) { |
| 4306 | 4317 | .F => "f32", |
| 4307 | 4318 | .L => "f64", |
| 4308 | 4319 | else => unreachable, |
| 4309 | 4320 | })); |
| 4310 | | _ = try appendToken(rp.c, .Comma, ","); |
| 4311 | | try cast_node.params.push(try transCreateNodeFloat(rp.c, tok.bytes)); |
| 4312 | | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 4321 | _ = try appendToken(c, .Comma, ","); |
| 4322 | try cast_node.params.push(try transCreateNodeFloat(c, tok.bytes)); |
| 4323 | cast_node.rparen_token = try appendToken(c, .RParen, ")"); |
| 4313 | 4324 | return &cast_node.base; |
| 4314 | | } else |
| 4315 | | return revertAndWarn( |
| 4316 | | rp, |
| 4317 | | error.ParseError, |
| 4318 | | source_loc, |
| 4319 | | "expected number literal", |
| 4320 | | .{}, |
| 4321 | | ); |
| 4325 | } else unreachable; |
| 4322 | 4326 | } |
| 4323 | 4327 | |
| 4324 | | fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4328 | fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4325 | 4329 | const tok = it.next().?; |
| 4326 | 4330 | switch (tok.id) { |
| 4327 | 4331 | .CharLit => { |
| 4328 | | const token = try appendToken(rp.c, .CharLiteral, tok.bytes); |
| 4329 | | const node = try rp.c.a().create(ast.Node.CharLiteral); |
| 4332 | const token = try appendToken(c, .CharLiteral, tok.bytes); |
| 4333 | const node = try c.a().create(ast.Node.CharLiteral); |
| 4330 | 4334 | node.* = ast.Node.CharLiteral{ |
| 4331 | 4335 | .token = token, |
| 4332 | 4336 | }; |
| 4333 | 4337 | return &node.base; |
| 4334 | 4338 | }, |
| 4335 | 4339 | .StrLit => { |
| 4336 | | const token = try appendToken(rp.c, .StringLiteral, tok.bytes); |
| 4337 | | const node = try rp.c.a().create(ast.Node.StringLiteral); |
| 4340 | const token = try appendToken(c, .StringLiteral, tok.bytes); |
| 4341 | const node = try c.a().create(ast.Node.StringLiteral); |
| 4338 | 4342 | node.* = ast.Node.StringLiteral{ |
| 4339 | 4343 | .token = token, |
| 4340 | 4344 | }; |
| 4341 | 4345 | return &node.base; |
| 4342 | 4346 | }, |
| 4343 | 4347 | .NumLitInt, .NumLitFloat => { |
| 4344 | | return parseCNumLit(rp, tok, source_loc); |
| 4348 | return parseCNumLit(c, tok, source_loc); |
| 4345 | 4349 | }, |
| 4346 | 4350 | .Identifier => { |
| 4347 | 4351 | const name = if (scope.getAlias(tok.bytes)) |a| a else tok.bytes; |
| 4348 | | return transCreateNodeIdentifier(rp.c, name); |
| 4352 | return transCreateNodeIdentifier(c, name); |
| 4349 | 4353 | }, |
| 4350 | 4354 | .LParen => { |
| 4351 | | const inner_node = try parseCExpr(rp, it, source_loc, scope); |
| 4355 | const inner_node = try parseCExpr(c, it, source_loc, scope); |
| 4352 | 4356 | |
| 4353 | 4357 | if (it.peek().?.id == .RParen) { |
| 4354 | 4358 | _ = it.next(); |
| ... | ... | @@ -4359,18 +4363,19 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: |
| 4359 | 4363 | } |
| 4360 | 4364 | |
| 4361 | 4365 | // hack to get zig fmt to render a comma in builtin calls |
| 4362 | | _ = try appendToken(rp.c, .Comma, ","); |
| 4366 | _ = try appendToken(c, .Comma, ","); |
| 4363 | 4367 | |
| 4364 | | const node_to_cast = try parseCExpr(rp, it, source_loc, scope); |
| 4368 | const node_to_cast = try parseCExpr(c, it, source_loc, scope); |
| 4365 | 4369 | |
| 4366 | 4370 | if (it.next().?.id != .RParen) { |
| 4367 | | return revertAndWarn( |
| 4368 | | rp, |
| 4369 | | error.ParseError, |
| 4371 | try failDecl( |
| 4372 | c, |
| 4370 | 4373 | source_loc, |
| 4371 | | "unable to translate C expr", |
| 4374 | it.list.at(0).*.bytes, |
| 4375 | "unable to translate C expr: expected ')''", |
| 4372 | 4376 | .{}, |
| 4373 | 4377 | ); |
| 4378 | return error.ParseError; |
| 4374 | 4379 | } |
| 4375 | 4380 | |
| 4376 | 4381 | //if (@typeId(@TypeOf(x)) == .Pointer) |
| ... | ... | @@ -4380,114 +4385,133 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: |
| 4380 | 4385 | //else |
| 4381 | 4386 | // @as(dest, x) |
| 4382 | 4387 | |
| 4383 | | const if_1 = try transCreateNodeIf(rp.c); |
| 4384 | | const type_id_1 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId"); |
| 4385 | | const type_of_1 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf"); |
| 4388 | const if_1 = try transCreateNodeIf(c); |
| 4389 | const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeId"); |
| 4390 | const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf"); |
| 4386 | 4391 | try type_id_1.params.push(&type_of_1.base); |
| 4387 | 4392 | try type_of_1.params.push(node_to_cast); |
| 4388 | | type_of_1.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4389 | | type_id_1.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4393 | type_of_1.rparen_token = try appendToken(c, .LParen, ")"); |
| 4394 | type_id_1.rparen_token = try appendToken(c, .LParen, ")"); |
| 4390 | 4395 | |
| 4391 | | const cmp_1 = try rp.c.a().create(ast.Node.InfixOp); |
| 4396 | const cmp_1 = try c.a().create(ast.Node.InfixOp); |
| 4392 | 4397 | cmp_1.* = .{ |
| 4393 | | .op_token = try appendToken(rp.c, .EqualEqual, "=="), |
| 4398 | .op_token = try appendToken(c, .EqualEqual, "=="), |
| 4394 | 4399 | .lhs = &type_id_1.base, |
| 4395 | 4400 | .op = .EqualEqual, |
| 4396 | | .rhs = try transCreateNodeEnumLiteral(rp.c, "Pointer"), |
| 4401 | .rhs = try transCreateNodeEnumLiteral(c, "Pointer"), |
| 4397 | 4402 | }; |
| 4398 | 4403 | if_1.condition = &cmp_1.base; |
| 4399 | | _ = try appendToken(rp.c, .LParen, ")"); |
| 4404 | _ = try appendToken(c, .LParen, ")"); |
| 4400 | 4405 | |
| 4401 | | const ptr_cast = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast"); |
| 4406 | const ptr_cast = try transCreateNodeBuiltinFnCall(c, "@ptrCast"); |
| 4402 | 4407 | try ptr_cast.params.push(inner_node); |
| 4403 | 4408 | try ptr_cast.params.push(node_to_cast); |
| 4404 | | ptr_cast.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4409 | ptr_cast.rparen_token = try appendToken(c, .LParen, ")"); |
| 4405 | 4410 | if_1.body = &ptr_cast.base; |
| 4406 | 4411 | |
| 4407 | | const else_1 = try transCreateNodeElse(rp.c); |
| 4412 | const else_1 = try transCreateNodeElse(c); |
| 4408 | 4413 | if_1.@"else" = else_1; |
| 4409 | 4414 | |
| 4410 | | const if_2 = try transCreateNodeIf(rp.c); |
| 4411 | | const type_id_2 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId"); |
| 4412 | | const type_of_2 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf"); |
| 4415 | const if_2 = try transCreateNodeIf(c); |
| 4416 | const type_id_2 = try transCreateNodeBuiltinFnCall(c, "@typeId"); |
| 4417 | const type_of_2 = try transCreateNodeBuiltinFnCall(c, "@TypeOf"); |
| 4413 | 4418 | try type_id_2.params.push(&type_of_2.base); |
| 4414 | 4419 | try type_of_2.params.push(node_to_cast); |
| 4415 | | type_of_2.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4416 | | type_id_2.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4420 | type_of_2.rparen_token = try appendToken(c, .LParen, ")"); |
| 4421 | type_id_2.rparen_token = try appendToken(c, .LParen, ")"); |
| 4417 | 4422 | |
| 4418 | | const cmp_2 = try rp.c.a().create(ast.Node.InfixOp); |
| 4423 | const cmp_2 = try c.a().create(ast.Node.InfixOp); |
| 4419 | 4424 | cmp_2.* = .{ |
| 4420 | | .op_token = try appendToken(rp.c, .EqualEqual, "=="), |
| 4425 | .op_token = try appendToken(c, .EqualEqual, "=="), |
| 4421 | 4426 | .lhs = &type_id_2.base, |
| 4422 | 4427 | .op = .EqualEqual, |
| 4423 | | .rhs = try transCreateNodeEnumLiteral(rp.c, "Int"), |
| 4428 | .rhs = try transCreateNodeEnumLiteral(c, "Int"), |
| 4424 | 4429 | }; |
| 4425 | 4430 | if_2.condition = &cmp_2.base; |
| 4426 | 4431 | else_1.body = &if_2.base; |
| 4427 | | _ = try appendToken(rp.c, .LParen, ")"); |
| 4432 | _ = try appendToken(c, .LParen, ")"); |
| 4428 | 4433 | |
| 4429 | | const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr"); |
| 4434 | const int_to_ptr = try transCreateNodeBuiltinFnCall(c, "@intToPtr"); |
| 4430 | 4435 | try int_to_ptr.params.push(inner_node); |
| 4431 | 4436 | try int_to_ptr.params.push(node_to_cast); |
| 4432 | | int_to_ptr.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4437 | int_to_ptr.rparen_token = try appendToken(c, .LParen, ")"); |
| 4433 | 4438 | if_2.body = &int_to_ptr.base; |
| 4434 | 4439 | |
| 4435 | | const else_2 = try transCreateNodeElse(rp.c); |
| 4440 | const else_2 = try transCreateNodeElse(c); |
| 4436 | 4441 | if_2.@"else" = else_2; |
| 4437 | 4442 | |
| 4438 | | const as = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| 4443 | const as = try transCreateNodeBuiltinFnCall(c, "@as"); |
| 4439 | 4444 | try as.params.push(inner_node); |
| 4440 | 4445 | try as.params.push(node_to_cast); |
| 4441 | | as.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| 4446 | as.rparen_token = try appendToken(c, .LParen, ")"); |
| 4442 | 4447 | else_2.body = &as.base; |
| 4443 | 4448 | |
| 4444 | 4449 | return &if_1.base; |
| 4445 | 4450 | }, |
| 4446 | | else => return revertAndWarn( |
| 4447 | | rp, |
| 4448 | | error.UnsupportedTranslation, |
| 4449 | | source_loc, |
| 4450 | | "unable to translate C expr, unexpected token: {}", |
| 4451 | | .{tok.id}, |
| 4452 | | ), |
| 4451 | else => { |
| 4452 | try failDecl( |
| 4453 | c, |
| 4454 | source_loc, |
| 4455 | it.list.at(0).*.bytes, |
| 4456 | "unable to translate C expr: unexpected token {}", |
| 4457 | .{tok.id}, |
| 4458 | ); |
| 4459 | return error.ParseError; |
| 4460 | }, |
| 4453 | 4461 | } |
| 4454 | 4462 | } |
| 4455 | 4463 | |
| 4456 | | fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4457 | | var node = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| 4464 | fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4465 | var node = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 4458 | 4466 | while (true) { |
| 4459 | 4467 | const tok = it.next().?; |
| 4460 | 4468 | switch (tok.id) { |
| 4461 | 4469 | .Dot => { |
| 4462 | 4470 | const name_tok = it.next().?; |
| 4463 | | if (name_tok.id != .Identifier) |
| 4471 | if (name_tok.id != .Identifier) { |
| 4472 | try failDecl( |
| 4473 | c, |
| 4474 | source_loc, |
| 4475 | it.list.at(0).*.bytes, |
| 4476 | "unable to translate C expr: expected identifier", |
| 4477 | .{}, |
| 4478 | ); |
| 4464 | 4479 | return error.ParseError; |
| 4480 | } |
| 4465 | 4481 | |
| 4466 | | node = try transCreateNodeFieldAccess(rp.c, node, name_tok.bytes); |
| 4482 | node = try transCreateNodeFieldAccess(c, node, name_tok.bytes); |
| 4467 | 4483 | }, |
| 4468 | 4484 | .Arrow => { |
| 4469 | 4485 | const name_tok = it.next().?; |
| 4470 | | if (name_tok.id != .Identifier) |
| 4486 | if (name_tok.id != .Identifier) { |
| 4487 | try failDecl( |
| 4488 | c, |
| 4489 | source_loc, |
| 4490 | it.list.at(0).*.bytes, |
| 4491 | "unable to translate C expr: expected identifier", |
| 4492 | .{}, |
| 4493 | ); |
| 4471 | 4494 | return error.ParseError; |
| 4495 | } |
| 4472 | 4496 | |
| 4473 | | const deref = try transCreateNodePtrDeref(rp.c, node); |
| 4474 | | node = try transCreateNodeFieldAccess(rp.c, deref, name_tok.bytes); |
| 4497 | const deref = try transCreateNodePtrDeref(c, node); |
| 4498 | node = try transCreateNodeFieldAccess(c, deref, name_tok.bytes); |
| 4475 | 4499 | }, |
| 4476 | 4500 | .Asterisk => { |
| 4477 | 4501 | if (it.peek().?.id == .RParen) { |
| 4478 | 4502 | // type *) |
| 4479 | 4503 | |
| 4480 | 4504 | // hack to get zig fmt to render a comma in builtin calls |
| 4481 | | _ = try appendToken(rp.c, .Comma, ","); |
| 4505 | _ = try appendToken(c, .Comma, ","); |
| 4482 | 4506 | |
| 4483 | | const ptr = try transCreateNodePtrType(rp.c, false, false, .Identifier); |
| 4507 | const ptr = try transCreateNodePtrType(c, false, false, .Identifier); |
| 4484 | 4508 | ptr.rhs = node; |
| 4485 | 4509 | return &ptr.base; |
| 4486 | 4510 | } else { |
| 4487 | 4511 | // expr * expr |
| 4488 | | const op_token = try appendToken(rp.c, .Asterisk, "*"); |
| 4489 | | const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| 4490 | | const mul_node = try rp.c.a().create(ast.Node.InfixOp); |
| 4512 | const op_token = try appendToken(c, .Asterisk, "*"); |
| 4513 | const rhs = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 4514 | const mul_node = try c.a().create(ast.Node.InfixOp); |
| 4491 | 4515 | mul_node.* = .{ |
| 4492 | 4516 | .op_token = op_token, |
| 4493 | 4517 | .lhs = node, |
| ... | ... | @@ -4498,9 +4522,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 4498 | 4522 | } |
| 4499 | 4523 | }, |
| 4500 | 4524 | .Shl => { |
| 4501 | | const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<"); |
| 4502 | | const rhs = try parseCExpr(rp, it, source_loc, scope); |
| 4503 | | const bitshift_node = try rp.c.a().create(ast.Node.InfixOp); |
| 4525 | const op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<"); |
| 4526 | const rhs = try parseCExpr(c, it, source_loc, scope); |
| 4527 | const bitshift_node = try c.a().create(ast.Node.InfixOp); |
| 4504 | 4528 | bitshift_node.* = .{ |
| 4505 | 4529 | .op_token = op_token, |
| 4506 | 4530 | .lhs = node, |
| ... | ... | @@ -4510,9 +4534,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 4510 | 4534 | node = &bitshift_node.base; |
| 4511 | 4535 | }, |
| 4512 | 4536 | .Pipe => { |
| 4513 | | const op_token = try appendToken(rp.c, .Pipe, "|"); |
| 4514 | | const rhs = try parseCExpr(rp, it, source_loc, scope); |
| 4515 | | const or_node = try rp.c.a().create(ast.Node.InfixOp); |
| 4537 | const op_token = try appendToken(c, .Pipe, "|"); |
| 4538 | const rhs = try parseCExpr(c, it, source_loc, scope); |
| 4539 | const or_node = try c.a().create(ast.Node.InfixOp); |
| 4516 | 4540 | or_node.* = .{ |
| 4517 | 4541 | .op_token = op_token, |
| 4518 | 4542 | .lhs = node, |
| ... | ... | @@ -4522,39 +4546,63 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 4522 | 4546 | node = &or_node.base; |
| 4523 | 4547 | }, |
| 4524 | 4548 | .LBrace => { |
| 4525 | | const arr_node = try transCreateNodeArrayAccess(rp.c, node); |
| 4526 | | arr_node.op.ArrayAccess = try parseCExpr(rp, it, source_loc, scope); |
| 4527 | | arr_node.rtoken = try appendToken(rp.c, .RBrace, "]"); |
| 4549 | const arr_node = try transCreateNodeArrayAccess(c, node); |
| 4550 | arr_node.op.ArrayAccess = try parseCExpr(c, it, source_loc, scope); |
| 4551 | arr_node.rtoken = try appendToken(c, .RBrace, "]"); |
| 4528 | 4552 | node = &arr_node.base; |
| 4529 | | if (it.next().?.id != .RBrace) |
| 4553 | if (it.next().?.id != .RBrace) { |
| 4554 | try failDecl( |
| 4555 | c, |
| 4556 | source_loc, |
| 4557 | it.list.at(0).*.bytes, |
| 4558 | "unable to translate C expr: expected ']'", |
| 4559 | .{}, |
| 4560 | ); |
| 4530 | 4561 | return error.ParseError; |
| 4562 | } |
| 4531 | 4563 | }, |
| 4532 | 4564 | .LParen => { |
| 4533 | | const call_node = try transCreateNodeFnCall(rp.c, node); |
| 4565 | const call_node = try transCreateNodeFnCall(c, node); |
| 4534 | 4566 | while (true) { |
| 4535 | | const arg = try parseCExpr(rp, it, source_loc, scope); |
| 4567 | const arg = try parseCExpr(c, it, source_loc, scope); |
| 4536 | 4568 | try call_node.op.Call.params.push(arg); |
| 4537 | 4569 | const next = it.next().?; |
| 4538 | 4570 | if (next.id == .Comma) |
| 4539 | | _ = try appendToken(rp.c, .Comma, ",") |
| 4571 | _ = try appendToken(c, .Comma, ",") |
| 4540 | 4572 | else if (next.id == .RParen) |
| 4541 | 4573 | break |
| 4542 | | else |
| 4574 | else { |
| 4575 | try failDecl( |
| 4576 | c, |
| 4577 | source_loc, |
| 4578 | it.list.at(0).*.bytes, |
| 4579 | "unable to translate C expr: expected ',' or ')'", |
| 4580 | .{}, |
| 4581 | ); |
| 4543 | 4582 | return error.ParseError; |
| 4583 | } |
| 4544 | 4584 | } |
| 4545 | | call_node.rtoken = try appendToken(rp.c, .RParen, ")"); |
| 4585 | call_node.rtoken = try appendToken(c, .RParen, ")"); |
| 4546 | 4586 | node = &call_node.base; |
| 4547 | 4587 | }, |
| 4548 | 4588 | .QuestionMark => { |
| 4549 | 4589 | // must come immediately after expr |
| 4550 | | _ = try appendToken(rp.c, .RParen, ")"); |
| 4551 | | const if_node = try transCreateNodeIf(rp.c); |
| 4590 | _ = try appendToken(c, .RParen, ")"); |
| 4591 | const if_node = try transCreateNodeIf(c); |
| 4552 | 4592 | if_node.condition = node; |
| 4553 | | if_node.body = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| 4554 | | if (it.next().?.id != .Colon) |
| 4593 | if_node.body = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 4594 | if (it.next().?.id != .Colon) { |
| 4595 | try failDecl( |
| 4596 | c, |
| 4597 | source_loc, |
| 4598 | it.list.at(0).*.bytes, |
| 4599 | "unable to translate C expr: expected ':'", |
| 4600 | .{}, |
| 4601 | ); |
| 4555 | 4602 | return error.ParseError; |
| 4556 | | if_node.@"else" = try transCreateNodeElse(rp.c); |
| 4557 | | if_node.@"else".?.body = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| 4603 | } |
| 4604 | if_node.@"else" = try transCreateNodeElse(c); |
| 4605 | if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source_loc, scope); |
| 4558 | 4606 | node = &if_node.base; |
| 4559 | 4607 | }, |
| 4560 | 4608 | else => { |
| ... | ... | @@ -4565,32 +4613,32 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc |
| 4565 | 4613 | } |
| 4566 | 4614 | } |
| 4567 | 4615 | |
| 4568 | | fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4616 | fn parseCPrefixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| 4569 | 4617 | const op_tok = it.next().?; |
| 4570 | 4618 | |
| 4571 | 4619 | switch (op_tok.id) { |
| 4572 | 4620 | .Bang => { |
| 4573 | | const node = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); |
| 4574 | | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| 4621 | const node = try transCreateNodePrefixOp(c, .BoolNot, .Bang, "!"); |
| 4622 | node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 4575 | 4623 | return &node.base; |
| 4576 | 4624 | }, |
| 4577 | 4625 | .Minus => { |
| 4578 | | const node = try transCreateNodePrefixOp(rp.c, .Negation, .Minus, "-"); |
| 4579 | | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| 4626 | const node = try transCreateNodePrefixOp(c, .Negation, .Minus, "-"); |
| 4627 | node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 4580 | 4628 | return &node.base; |
| 4581 | 4629 | }, |
| 4582 | 4630 | .Tilde => { |
| 4583 | | const node = try transCreateNodePrefixOp(rp.c, .BitNot, .Tilde, "~"); |
| 4584 | | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| 4631 | const node = try transCreateNodePrefixOp(c, .BitNot, .Tilde, "~"); |
| 4632 | node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 4585 | 4633 | return &node.base; |
| 4586 | 4634 | }, |
| 4587 | 4635 | .Asterisk => { |
| 4588 | | const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| 4589 | | return try transCreateNodePtrDeref(rp.c, prefix_op_expr); |
| 4636 | const prefix_op_expr = try parseCPrefixOpExpr(c, it, source_loc, scope); |
| 4637 | return try transCreateNodePtrDeref(c, prefix_op_expr); |
| 4590 | 4638 | }, |
| 4591 | 4639 | else => { |
| 4592 | 4640 | _ = it.prev(); |
| 4593 | | return try parseCSuffixOpExpr(rp, it, source_loc, scope); |
| 4641 | return try parseCSuffixOpExpr(c, it, source_loc, scope); |
| 4594 | 4642 | }, |
| 4595 | 4643 | } |
| 4596 | 4644 | } |