authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-28 23:38:07+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-28 23:38:07+02:00
log1e52b7d690071104544aaae5bef2760aee84c38e
tree5f6648c3b2be421da9857aaa5f13072617a5567b
parentaea46dcd7e8521fc04bc1980a596c748961804ab
signature Commit is signed but in an unrecognized format.

translate-c-2 improve macro errors


2 files changed, 246 insertions(+), 162 deletions(-)

src-self-hosted/c_tokenizer.zig+57-21
......@@ -1,5 +1,8 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const ZigClangSourceLocation = @import("clang.zig").ZigClangSourceLocation;
4const Context = @import("translate_c.zig").Context;
5const failDecl = @import("translate_c.zig").failDecl;
36
47pub const TokenList = std.SegmentedList(CToken, 32);
58
......@@ -46,13 +49,13 @@ pub const CToken = struct {
4649 };
4750};
4851
49pub fn tokenizeCMacro(tl: *TokenList, chars: [*:0]const u8) !void {
52pub fn tokenizeCMacro(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, tl: *TokenList, chars: [*:0]const u8) !void {
5053 var index: usize = 0;
5154 var first = true;
5255 while (true) {
53 const tok = try next(chars, &index);
56 const tok = try next(ctx, loc, name, chars, &index);
5457 if (tok.id == .StrLit or tok.id == .CharLit)
55 try tl.push(try zigifyEscapeSequences(tl.allocator, tok))
58 try tl.push(try zigifyEscapeSequences(ctx, loc, name, tl.allocator, tok))
5659 else
5760 try tl.push(tok);
5861 if (tok.id == .Eof)
......@@ -70,7 +73,7 @@ pub fn tokenizeCMacro(tl: *TokenList, chars: [*:0]const u8) !void {
7073 }
7174}
7275
73fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
76fn zigifyEscapeSequences(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, allocator: *std.mem.Allocator, tok: CToken) !CToken {
7477 for (tok.bytes) |c| {
7578 if (c == '\\') {
7679 break;
......@@ -136,11 +139,11 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
136139 bytes[i] = '?';
137140 },
138141 'u', 'U' => {
139 // TODO unicode escape sequences
142 try failDecl(ctx, loc, name, "macro tokenizing failed: TODO unicode escape sequences", .{});
140143 return error.TokenizingFailed;
141144 },
142145 else => {
143 // unknown escape sequence
146 try failDecl(ctx, loc, name, "macro tokenizing failed: unknown escape sequence", .{});
144147 return error.TokenizingFailed;
145148 },
146149 }
......@@ -158,19 +161,28 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
158161 .Hex => {
159162 switch (c) {
160163 '0'...'9' => {
161 num = std.math.mul(u8, num, 16) catch return error.TokenizingFailed;
164 num = std.math.mul(u8, num, 16) catch {
165 try failDecl(ctx, loc, name, "macro tokenizing failed: hex literal overflowed", .{});
166 return error.TokenizingFailed;
167 };
162168 num += c - '0';
163169 },
164170 'a'...'f' => {
165 num = std.math.mul(u8, num, 16) catch return error.TokenizingFailed;
171 num = std.math.mul(u8, num, 16) catch {
172 try failDecl(ctx, loc, name, "macro tokenizing failed: hex literal overflowed", .{});
173 return error.TokenizingFailed;
174 };
166175 num += c - 'a' + 10;
167176 },
168177 'A'...'F' => {
169 num = std.math.mul(u8, num, 16) catch return error.TokenizingFailed;
178 num = std.math.mul(u8, num, 16) catch {
179 try failDecl(ctx, loc, name, "macro tokenizing failed: hex literal overflowed", .{});
180 return error.TokenizingFailed;
181 };
170182 num += c - 'A' + 10;
171183 },
172184 else => {
173 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{.fill = '0', .width = 2});
185 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
174186 num = 0;
175187 if (c == '\\')
176188 state = .Escape
......@@ -185,14 +197,17 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
185197 switch (c) {
186198 '0'...'7' => {
187199 count += 1;
188 num = std.math.mul(u8, num, 8) catch return error.TokenizingFailed;
200 num = std.math.mul(u8, num, 8) catch {
201 try failDecl(ctx, loc, name, "macro tokenizing failed: octal literal overflowed", .{});
202 return error.TokenizingFailed;
203 };
189204 num += c - '0';
190205 if (count < 3)
191206 continue;
192207 },
193208 else => {},
194209 }
195 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{.fill = '0', .width = 2});
210 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
196211 state = .Start;
197212 count = 0;
198213 num = 0;
......@@ -200,14 +215,14 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
200215 }
201216 }
202217 if (state == .Hex or state == .Octal)
203 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{.fill = '0', .width = 2});
218 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
204219 return CToken{
205220 .id = tok.id,
206221 .bytes = bytes[0..i],
207222 };
208223}
209224
210fn next(chars: [*:0]const u8, i: *usize) !CToken {
225fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:0]const u8, i: *usize) !CToken {
211226 var state: enum {
212227 Start,
213228 GotLt,
......@@ -278,7 +293,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
278293 .String,
279294 .ExpSign,
280295 .FloatExpFirst,
281 => return error.TokenizingFailed,
296 => {
297 try failDecl(ctx, loc, name, "macro tokenizing failed: unexpected EOF", .{});
298 return error.TokenizingFailed;
299 },
282300 }
283301 }
284302 switch (state) {
......@@ -375,7 +393,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
375393 result.id = .Colon;
376394 state = .Done;
377395 },
378 else => return error.TokenizingFailed,
396 else => {
397 try failDecl(ctx, loc, name, "macro tokenizing failed: unexpected character '{c}'", .{c});
398 return error.TokenizingFailed;
399 },
379400 }
380401 },
381402 .Done => return result,
......@@ -433,7 +454,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
433454 '0'...'9' => {
434455 state = .FloatExp;
435456 },
436 else => return error.TokenizingFailed,
457 else => {
458 try failDecl(ctx, loc, name, "macro tokenizing failed: expected a digit or '+' or '-'", .{});
459 return error.TokenizingFailed;
460 },
437461 }
438462 },
439463 .FloatExpFirst => {
......@@ -441,7 +465,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
441465 '0'...'9' => {
442466 state = .FloatExp;
443467 },
444 else => return error.TokenizingFailed,
468 else => {
469 try failDecl(ctx, loc, name, "macro tokenizing failed: expected a digit", .{});
470 return error.TokenizingFailed;
471 },
445472 }
446473 },
447474 .FloatExp => {
......@@ -518,7 +545,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
518545 .Octal => {
519546 switch (c) {
520547 '0'...'7' => {},
521 '8', '9' => return error.TokenizingFailed,
548 '8', '9' => {
549 try failDecl(ctx, loc, name, "macro tokenizing failed: invalid digit '{c}' in octal number", .{c});
550 return error.TokenizingFailed;
551 },
522552 else => {
523553 result.bytes = chars[begin_index..i.*];
524554 return result;
......@@ -549,7 +579,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
549579 .Bin => {
550580 switch (c) {
551581 '0'...'1' => {},
552 '2'...'9' => return error.TokenizingFailed,
582 '2'...'9' => {
583 try failDecl(ctx, loc, name, "macro tokenizing failed: invalid digit '{c}' in binary number", .{c});
584 return error.TokenizingFailed;
585 },
553586 'u', 'U' => {
554587 // marks the number literal as unsigned
555588 state = .NumLitIntSuffixU;
......@@ -681,7 +714,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
681714 '\n', '\r' => {
682715 state = .Start;
683716 },
684 else => return error.TokenizingFailed,
717 else => {
718 try failDecl(ctx, loc, name, "macro tokenizing failed: expected whitespace", .{});
719 return error.TokenizingFailed;
720 },
685721 }
686722 },
687723 }
src-self-hosted/translate_c.zig+189-141
......@@ -182,7 +182,7 @@ const Scope = struct {
182182 }
183183};
184184
185const Context = struct {
185pub const Context = struct {
186186 tree: *ast.Tree,
187187 source_buffer: *std.Buffer,
188188 err: Error,
......@@ -3921,7 +3921,7 @@ fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []cons
39213921 _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, args_prefix ++ args);
39223922}
39233923
3924fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: var) !void {
3924pub fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: var) !void {
39253925 // const name = @compileError(msg);
39263926 const const_tok = try appendToken(c, .Keyword_const, "const");
39273927 const name_tok = try appendIdentifier(c, name);
......@@ -4091,10 +4091,9 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
40914091 continue;
40924092 }
40934093 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) {
40954095 error.OutOfMemory => |e| return e,
40964096 else => {
4097 try failDecl(c, begin_loc, checked_name, "unable to tokenize macro definition", .{});
40984097 continue;
40994098 },
41004099 };
......@@ -4127,9 +4126,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
41274126 transMacroFnDefine(c, &tok_it, checked_name, begin_loc)
41284127 else
41294128 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,
41334130 error.OutOfMemory => |e| return e,
41344131 };
41354132 },
......@@ -4139,20 +4136,19 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
41394136}
41404137
41414138fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {
4142 const rp = makeRestorePoint(c);
41434139 const scope = &c.global_scope.base;
41444140
41454141 const node = try transCreateNodeVarDecl(c, true, true, name);
41464142 node.eq_token = try appendToken(c, .Equal, "=");
41474143
4148 node.init_node = try parseCExpr(rp, it, source_loc, scope);
4144 node.init_node = try parseCExpr(c, it, source_loc, scope);
41494145 const last = it.next().?;
41504146 if (last.id != .Eof)
4151 return revertAndWarn(
4152 rp,
4153 error.UnsupportedTranslation,
4147 return failDecl(
4148 c,
41544149 source_loc,
4155 "unable to translate C expr, unexpected token: {}",
4150 name,
4151 "unable to translate C expr: unexpected token {}",
41564152 .{last.id},
41574153 );
41584154
......@@ -4161,7 +4157,6 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8,
41614157}
41624158
41634159fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {
4164 const rp = makeRestorePoint(c);
41654160 const block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
41664161 const scope = &block_scope.base;
41674162
......@@ -4172,13 +4167,26 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
41724167 _ = try appendToken(c, .LParen, "(");
41734168
41744169 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 );
41764177 }
41774178 var fn_params = ast.Node.FnProto.ParamList.init(c.a());
41784179 while (true) {
41794180 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 }
41824190
41834191 const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {
41844192 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
42134221 }
42144222
42154223 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 );
42174231 }
42184232
42194233 _ = try appendToken(c, .RParen, ")");
......@@ -4241,14 +4255,14 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
42414255 const block = try transCreateNodeBlock(c, null);
42424256
42434257 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);
42454259 const last = it.next().?;
42464260 if (last.id != .Eof)
4247 return revertAndWarn(
4248 rp,
4249 error.UnsupportedTranslation,
4261 return failDecl(
4262 c,
42504263 source_loc,
4251 "unable to translate C expr, unexpected token: {}",
4264 name,
4265 "unable to translate C expr: unexpected token {}",
42524266 .{last.id},
42534267 );
42544268 _ = try appendToken(c, .Semicolon, ";");
......@@ -4261,31 +4275,28 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
42614275 _ = try c.global_scope.macro_table.put(name, &fn_proto.base);
42624276}
42634277
4264const ParseError = Error || error{
4265 ParseError,
4266 UnsupportedTranslation,
4267};
4278const ParseError = Error || error{ParseError};
42684279
4269fn parseCExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4270 return parseCPrefixOpExpr(rp, it, source_loc, scope);
4280fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4281 return parseCPrefixOpExpr(c, it, source_loc, scope);
42714282}
42724283
4273fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {
4284fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {
42744285 if (tok.id == .NumLitInt) {
42754286 if (tok.num_lit_suffix == .None) {
42764287 if (tok.bytes.len > 2 and tok.bytes[0] == '0') {
42774288 switch (tok.bytes[1]) {
42784289 '0'...'7' => {
42794290 // 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}));
42814292 },
42824293 else => {},
42834294 }
42844295 }
4285 return transCreateNodeInt(rp.c, tok.bytes);
4296 return transCreateNodeInt(c, tok.bytes);
42864297 }
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) {
42894300 .U => "c_uint",
42904301 .L => "c_long",
42914302 .LU => "c_ulong",
......@@ -4293,62 +4304,55 @@ fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocati
42934304 .LLU => "c_ulonglong",
42944305 else => unreachable,
42954306 }));
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, ")");
42994310 return &cast_node.base;
43004311 } else if (tok.id == .NumLitFloat) {
43014312 if (tok.num_lit_suffix == .None) {
4302 return transCreateNodeFloat(rp.c, tok.bytes);
4313 return transCreateNodeFloat(c, tok.bytes);
43034314 }
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) {
43064317 .F => "f32",
43074318 .L => "f64",
43084319 else => unreachable,
43094320 }));
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, ")");
43134324 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;
43224326}
43234327
4324fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4328fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
43254329 const tok = it.next().?;
43264330 switch (tok.id) {
43274331 .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);
43304334 node.* = ast.Node.CharLiteral{
43314335 .token = token,
43324336 };
43334337 return &node.base;
43344338 },
43354339 .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);
43384342 node.* = ast.Node.StringLiteral{
43394343 .token = token,
43404344 };
43414345 return &node.base;
43424346 },
43434347 .NumLitInt, .NumLitFloat => {
4344 return parseCNumLit(rp, tok, source_loc);
4348 return parseCNumLit(c, tok, source_loc);
43454349 },
43464350 .Identifier => {
43474351 const name = if (scope.getAlias(tok.bytes)) |a| a else tok.bytes;
4348 return transCreateNodeIdentifier(rp.c, name);
4352 return transCreateNodeIdentifier(c, name);
43494353 },
43504354 .LParen => {
4351 const inner_node = try parseCExpr(rp, it, source_loc, scope);
4355 const inner_node = try parseCExpr(c, it, source_loc, scope);
43524356
43534357 if (it.peek().?.id == .RParen) {
43544358 _ = it.next();
......@@ -4359,18 +4363,19 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:
43594363 }
43604364
43614365 // hack to get zig fmt to render a comma in builtin calls
4362 _ = try appendToken(rp.c, .Comma, ",");
4366 _ = try appendToken(c, .Comma, ",");
43634367
4364 const node_to_cast = try parseCExpr(rp, it, source_loc, scope);
4368 const node_to_cast = try parseCExpr(c, it, source_loc, scope);
43654369
43664370 if (it.next().?.id != .RParen) {
4367 return revertAndWarn(
4368 rp,
4369 error.ParseError,
4371 try failDecl(
4372 c,
43704373 source_loc,
4371 "unable to translate C expr",
4374 it.list.at(0).*.bytes,
4375 "unable to translate C expr: expected ')''",
43724376 .{},
43734377 );
4378 return error.ParseError;
43744379 }
43754380
43764381 //if (@typeId(@TypeOf(x)) == .Pointer)
......@@ -4380,114 +4385,133 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:
43804385 //else
43814386 // @as(dest, x)
43824387
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");
43864391 try type_id_1.params.push(&type_of_1.base);
43874392 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, ")");
43904395
4391 const cmp_1 = try rp.c.a().create(ast.Node.InfixOp);
4396 const cmp_1 = try c.a().create(ast.Node.InfixOp);
43924397 cmp_1.* = .{
4393 .op_token = try appendToken(rp.c, .EqualEqual, "=="),
4398 .op_token = try appendToken(c, .EqualEqual, "=="),
43944399 .lhs = &type_id_1.base,
43954400 .op = .EqualEqual,
4396 .rhs = try transCreateNodeEnumLiteral(rp.c, "Pointer"),
4401 .rhs = try transCreateNodeEnumLiteral(c, "Pointer"),
43974402 };
43984403 if_1.condition = &cmp_1.base;
4399 _ = try appendToken(rp.c, .LParen, ")");
4404 _ = try appendToken(c, .LParen, ")");
44004405
4401 const ptr_cast = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
4406 const ptr_cast = try transCreateNodeBuiltinFnCall(c, "@ptrCast");
44024407 try ptr_cast.params.push(inner_node);
44034408 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, ")");
44054410 if_1.body = &ptr_cast.base;
44064411
4407 const else_1 = try transCreateNodeElse(rp.c);
4412 const else_1 = try transCreateNodeElse(c);
44084413 if_1.@"else" = else_1;
44094414
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");
44134418 try type_id_2.params.push(&type_of_2.base);
44144419 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, ")");
44174422
4418 const cmp_2 = try rp.c.a().create(ast.Node.InfixOp);
4423 const cmp_2 = try c.a().create(ast.Node.InfixOp);
44194424 cmp_2.* = .{
4420 .op_token = try appendToken(rp.c, .EqualEqual, "=="),
4425 .op_token = try appendToken(c, .EqualEqual, "=="),
44214426 .lhs = &type_id_2.base,
44224427 .op = .EqualEqual,
4423 .rhs = try transCreateNodeEnumLiteral(rp.c, "Int"),
4428 .rhs = try transCreateNodeEnumLiteral(c, "Int"),
44244429 };
44254430 if_2.condition = &cmp_2.base;
44264431 else_1.body = &if_2.base;
4427 _ = try appendToken(rp.c, .LParen, ")");
4432 _ = try appendToken(c, .LParen, ")");
44284433
4429 const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
4434 const int_to_ptr = try transCreateNodeBuiltinFnCall(c, "@intToPtr");
44304435 try int_to_ptr.params.push(inner_node);
44314436 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, ")");
44334438 if_2.body = &int_to_ptr.base;
44344439
4435 const else_2 = try transCreateNodeElse(rp.c);
4440 const else_2 = try transCreateNodeElse(c);
44364441 if_2.@"else" = else_2;
44374442
4438 const as = try transCreateNodeBuiltinFnCall(rp.c, "@as");
4443 const as = try transCreateNodeBuiltinFnCall(c, "@as");
44394444 try as.params.push(inner_node);
44404445 try as.params.push(node_to_cast);
4441 as.rparen_token = try appendToken(rp.c, .LParen, ")");
4446 as.rparen_token = try appendToken(c, .LParen, ")");
44424447 else_2.body = &as.base;
44434448
44444449 return &if_1.base;
44454450 },
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 },
44534461 }
44544462}
44554463
4456fn 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);
4464fn 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);
44584466 while (true) {
44594467 const tok = it.next().?;
44604468 switch (tok.id) {
44614469 .Dot => {
44624470 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 );
44644479 return error.ParseError;
4480 }
44654481
4466 node = try transCreateNodeFieldAccess(rp.c, node, name_tok.bytes);
4482 node = try transCreateNodeFieldAccess(c, node, name_tok.bytes);
44674483 },
44684484 .Arrow => {
44694485 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 );
44714494 return error.ParseError;
4495 }
44724496
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);
44754499 },
44764500 .Asterisk => {
44774501 if (it.peek().?.id == .RParen) {
44784502 // type *)
44794503
44804504 // hack to get zig fmt to render a comma in builtin calls
4481 _ = try appendToken(rp.c, .Comma, ",");
4505 _ = try appendToken(c, .Comma, ",");
44824506
4483 const ptr = try transCreateNodePtrType(rp.c, false, false, .Identifier);
4507 const ptr = try transCreateNodePtrType(c, false, false, .Identifier);
44844508 ptr.rhs = node;
44854509 return &ptr.base;
44864510 } else {
44874511 // 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);
44914515 mul_node.* = .{
44924516 .op_token = op_token,
44934517 .lhs = node,
......@@ -4498,9 +4522,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
44984522 }
44994523 },
45004524 .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);
45044528 bitshift_node.* = .{
45054529 .op_token = op_token,
45064530 .lhs = node,
......@@ -4510,9 +4534,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
45104534 node = &bitshift_node.base;
45114535 },
45124536 .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);
45164540 or_node.* = .{
45174541 .op_token = op_token,
45184542 .lhs = node,
......@@ -4522,39 +4546,63 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
45224546 node = &or_node.base;
45234547 },
45244548 .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, "]");
45284552 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 );
45304561 return error.ParseError;
4562 }
45314563 },
45324564 .LParen => {
4533 const call_node = try transCreateNodeFnCall(rp.c, node);
4565 const call_node = try transCreateNodeFnCall(c, node);
45344566 while (true) {
4535 const arg = try parseCExpr(rp, it, source_loc, scope);
4567 const arg = try parseCExpr(c, it, source_loc, scope);
45364568 try call_node.op.Call.params.push(arg);
45374569 const next = it.next().?;
45384570 if (next.id == .Comma)
4539 _ = try appendToken(rp.c, .Comma, ",")
4571 _ = try appendToken(c, .Comma, ",")
45404572 else if (next.id == .RParen)
45414573 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 );
45434582 return error.ParseError;
4583 }
45444584 }
4545 call_node.rtoken = try appendToken(rp.c, .RParen, ")");
4585 call_node.rtoken = try appendToken(c, .RParen, ")");
45464586 node = &call_node.base;
45474587 },
45484588 .QuestionMark => {
45494589 // 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);
45524592 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 );
45554602 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);
45584606 node = &if_node.base;
45594607 },
45604608 else => {
......@@ -4565,32 +4613,32 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
45654613 }
45664614}
45674615
4568fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4616fn parseCPrefixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
45694617 const op_tok = it.next().?;
45704618
45714619 switch (op_tok.id) {
45724620 .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);
45754623 return &node.base;
45764624 },
45774625 .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);
45804628 return &node.base;
45814629 },
45824630 .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);
45854633 return &node.base;
45864634 },
45874635 .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);
45904638 },
45914639 else => {
45924640 _ = it.prev();
4593 return try parseCSuffixOpExpr(rp, it, source_loc, scope);
4641 return try parseCSuffixOpExpr(c, it, source_loc, scope);
45944642 },
45954643 }
45964644}