| ... | @@ -6,6 +6,8 @@ const assert = std.debug.assert; | ... | @@ -6,6 +6,8 @@ const assert = std.debug.assert; |
| 6 | const ast = std.zig.ast; | 6 | const ast = std.zig.ast; |
| 7 | const Token = std.zig.Token; | 7 | const Token = std.zig.Token; |
| 8 | usingnamespace @import("clang.zig"); | 8 | usingnamespace @import("clang.zig"); |
| | 9 | const ctok = @import("c_tokenizer.zig"); |
| | 10 | const CToken = ctok.CToken; |
| 9 | | 11 | |
| 10 | const CallingConvention = std.builtin.TypeInfo.CallingConvention; | 12 | const CallingConvention = std.builtin.TypeInfo.CallingConvention; |
| 11 | | 13 | |
| ... | @@ -31,7 +33,7 @@ fn addrEql(a: usize, b: usize) bool { | ... | @@ -31,7 +33,7 @@ fn addrEql(a: usize, b: usize) bool { |
| 31 | return a == b; | 33 | return a == b; |
| 32 | } | 34 | } |
| 33 | | 35 | |
| 34 | const SymbolTable = std.StringHashMap(void); | 36 | const SymbolTable = std.StringHashMap(*ast.Node); |
| 35 | const AliasList = std.SegmentedList(struct { | 37 | const AliasList = std.SegmentedList(struct { |
| 36 | alias: []const u8, | 38 | alias: []const u8, |
| 37 | name: []const u8, | 39 | name: []const u8, |
| ... | @@ -43,59 +45,151 @@ const Scope = struct { | ... | @@ -43,59 +45,151 @@ const Scope = struct { |
| 43 | | 45 | |
| 44 | const Id = enum { | 46 | const Id = enum { |
| 45 | Switch, | 47 | Switch, |
| 46 | Var, | | |
| 47 | Block, | 48 | Block, |
| 48 | Root, | 49 | Root, |
| 49 | While, | 50 | While, |
| | 51 | FnDef, |
| | 52 | Ref, |
| 50 | }; | 53 | }; |
| | 54 | |
| 51 | const Switch = struct { | 55 | const Switch = struct { |
| 52 | base: Scope, | 56 | base: Scope, |
| 53 | }; | 57 | }; |
| 54 | | 58 | |
| 55 | const Var = struct { | 59 | /// used when getting a member `a.b` |
| | 60 | const Ref = struct { |
| 56 | base: Scope, | 61 | base: Scope, |
| 57 | c_name: []const u8, | | |
| 58 | zig_name: []const u8, | | |
| 59 | }; | 62 | }; |
| 60 | | 63 | |
| 61 | const Block = struct { | 64 | const Block = struct { |
| 62 | base: Scope, | 65 | base: Scope, |
| 63 | block_node: *ast.Node.Block, | 66 | block_node: *ast.Node.Block, |
| | 67 | variables: AliasList, |
| 64 | | 68 | |
| 65 | /// Don't forget to set rbrace token later | 69 | /// Don't forget to set rbrace token later |
| 66 | fn create(c: *Context, parent: *Scope, lbrace_tok: ast.TokenIndex) !*Block { | 70 | fn init(c: *Context, parent: *Scope, block_node: *ast.Node.Block) !*Block { |
| 67 | const block = try c.a().create(Block); | 71 | const block = try c.a().create(Block); |
| 68 | block.* = Block{ | 72 | block.* = .{ |
| 69 | .base = Scope{ | 73 | .base = .{ |
| 70 | .id = Id.Block, | 74 | .id = .Block, |
| 71 | .parent = parent, | 75 | .parent = parent, |
| 72 | }, | 76 | }, |
| 73 | .block_node = try c.a().create(ast.Node.Block), | 77 | .block_node = block_node, |
| 74 | }; | 78 | .variables = AliasList.init(c.a()), |
| 75 | block.block_node.* = ast.Node.Block{ | | |
| 76 | .base = ast.Node{ .id = ast.Node.Id.Block }, | | |
| 77 | .label = null, | | |
| 78 | .lbrace = lbrace_tok, | | |
| 79 | .statements = ast.Node.Block.StatementList.init(c.a()), | | |
| 80 | .rbrace = undefined, | | |
| 81 | }; | 79 | }; |
| 82 | return block; | 80 | return block; |
| 83 | } | 81 | } |
| | 82 | |
| | 83 | fn getAlias(scope: *Block, name: []const u8) ?[]const u8 { |
| | 84 | var it = scope.variables.iterator(0); |
| | 85 | while (it.next()) |p| { |
| | 86 | if (std.mem.eql(u8, p.name, name)) |
| | 87 | return p.alias; |
| | 88 | } |
| | 89 | return scope.base.parent.?.getAlias(name); |
| | 90 | } |
| | 91 | |
| | 92 | fn contains(scope: *Block, name: []const u8) bool { |
| | 93 | var it = scope.variables.iterator(0); |
| | 94 | while (it.next()) |p| { |
| | 95 | if (std.mem.eql(u8, p.name, name)) |
| | 96 | return true; |
| | 97 | } |
| | 98 | return scope.base.parent.?.contains(name); |
| | 99 | } |
| 84 | }; | 100 | }; |
| 85 | | 101 | |
| 86 | const Root = struct { | 102 | const Root = struct { |
| 87 | base: Scope, | 103 | base: Scope, |
| | 104 | sym_table: SymbolTable, |
| | 105 | macro_table: SymbolTable, |
| | 106 | |
| | 107 | fn init(c: *Context) Root { |
| | 108 | return .{ |
| | 109 | .base = .{ |
| | 110 | .id = .Root, |
| | 111 | .parent = null, |
| | 112 | }, |
| | 113 | .sym_table = SymbolTable.init(c.a()), |
| | 114 | .macro_table = SymbolTable.init(c.a()), |
| | 115 | }; |
| | 116 | } |
| | 117 | |
| | 118 | fn contains(scope: *Root, name: []const u8) bool { |
| | 119 | return scope.sym_table.contains(name) or scope.macro_table.contains(name); |
| | 120 | } |
| 88 | }; | 121 | }; |
| 89 | | 122 | |
| 90 | const While = struct { | 123 | const While = struct { |
| 91 | base: Scope, | 124 | base: Scope, |
| 92 | }; | 125 | }; |
| 93 | }; | | |
| 94 | | 126 | |
| 95 | const TransResult = struct { | 127 | const FnDef = struct { |
| 96 | node: *ast.Node, | 128 | base: Scope, |
| 97 | node_scope: *Scope, | 129 | params: AliasList, |
| 98 | child_scope: *Scope, | 130 | |
| | 131 | fn init(c: *Context) FnDef { |
| | 132 | return .{ |
| | 133 | .base = .{ |
| | 134 | .id = .FnDef, |
| | 135 | .parent = &c.global_scope.base, |
| | 136 | }, |
| | 137 | .params = AliasList.init(c.a()), |
| | 138 | }; |
| | 139 | } |
| | 140 | |
| | 141 | fn getAlias(scope: *FnDef, name: []const u8) ?[]const u8 { |
| | 142 | var it = scope.params.iterator(0); |
| | 143 | while (it.next()) |p| { |
| | 144 | if (std.mem.eql(u8, p.name, name)) |
| | 145 | return p.alias; |
| | 146 | } |
| | 147 | return scope.base.parent.?.getAlias(name); |
| | 148 | } |
| | 149 | |
| | 150 | fn contains(scope: *FnDef, name: []const u8) bool { |
| | 151 | var it = scope.params.iterator(0); |
| | 152 | while (it.next()) |p| { |
| | 153 | if (std.mem.eql(u8, p.name, name)) |
| | 154 | return true; |
| | 155 | } |
| | 156 | return scope.base.parent.?.contains(name); |
| | 157 | } |
| | 158 | }; |
| | 159 | |
| | 160 | fn findBlockScope(inner: *Scope) *Scope.Block { |
| | 161 | var scope = inner; |
| | 162 | while (true) : (scope = scope.parent orelse unreachable) { |
| | 163 | if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope); |
| | 164 | } |
| | 165 | } |
| | 166 | |
| | 167 | fn createAlias(scope: *Scope, c: *Context, name: []const u8) !?[]const u8 { |
| | 168 | if (scope.contains(name)) { |
| | 169 | return try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }); |
| | 170 | } |
| | 171 | return null; |
| | 172 | } |
| | 173 | |
| | 174 | fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 { |
| | 175 | return switch (scope.id) { |
| | 176 | .Root => null, |
| | 177 | .Ref => null, |
| | 178 | .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name), |
| | 179 | .Block => @fieldParentPtr(Block, "base", scope).getAlias(name), |
| | 180 | else => @panic("TODO Scope.getAlias"), |
| | 181 | }; |
| | 182 | } |
| | 183 | |
| | 184 | fn contains(scope: *Scope, name: []const u8) bool { |
| | 185 | return switch (scope.id) { |
| | 186 | .Ref => false, |
| | 187 | .Root => @fieldParentPtr(Root, "base", scope).contains(name), |
| | 188 | .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name), |
| | 189 | .Block => @fieldParentPtr(Block, "base", scope).contains(name), |
| | 190 | else => @panic("TODO Scope.contains"), |
| | 191 | }; |
| | 192 | } |
| 99 | }; | 193 | }; |
| 100 | | 194 | |
| 101 | const Context = struct { | 195 | const Context = struct { |
| ... | @@ -105,7 +199,6 @@ const Context = struct { | ... | @@ -105,7 +199,6 @@ const Context = struct { |
| 105 | source_manager: *ZigClangSourceManager, | 199 | source_manager: *ZigClangSourceManager, |
| 106 | decl_table: DeclTable, | 200 | decl_table: DeclTable, |
| 107 | alias_list: AliasList, | 201 | alias_list: AliasList, |
| 108 | sym_table: SymbolTable, | | |
| 109 | global_scope: *Scope.Root, | 202 | global_scope: *Scope.Root, |
| 110 | ptr_params: std.BufSet, | 203 | ptr_params: std.BufSet, |
| 111 | clang_context: *ZigClangASTContext, | 204 | clang_context: *ZigClangASTContext, |
| ... | @@ -142,7 +235,7 @@ pub fn translate( | ... | @@ -142,7 +235,7 @@ pub fn translate( |
| 142 | args_begin: [*]?[*]const u8, | 235 | args_begin: [*]?[*]const u8, |
| 143 | args_end: [*]?[*]const u8, | 236 | args_end: [*]?[*]const u8, |
| 144 | errors: *[]ClangErrMsg, | 237 | errors: *[]ClangErrMsg, |
| 145 | resources_path: [*]const u8, | 238 | resources_path: [*:0]const u8, |
| 146 | ) !*ast.Tree { | 239 | ) !*ast.Tree { |
| 147 | const ast_unit = ZigClangLoadFromCommandLine( | 240 | const ast_unit = ZigClangLoadFromCommandLine( |
| 148 | args_begin, | 241 | args_begin, |
| ... | @@ -192,24 +285,22 @@ pub fn translate( | ... | @@ -192,24 +285,22 @@ pub fn translate( |
| 192 | .err = undefined, | 285 | .err = undefined, |
| 193 | .decl_table = DeclTable.init(arena), | 286 | .decl_table = DeclTable.init(arena), |
| 194 | .alias_list = AliasList.init(arena), | 287 | .alias_list = AliasList.init(arena), |
| 195 | .sym_table = SymbolTable.init(arena), | | |
| 196 | .global_scope = try arena.create(Scope.Root), | 288 | .global_scope = try arena.create(Scope.Root), |
| 197 | .ptr_params = std.BufSet.init(arena), | 289 | .ptr_params = std.BufSet.init(arena), |
| 198 | .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, | 290 | .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, |
| 199 | }; | 291 | }; |
| 200 | context.global_scope.* = Scope.Root{ | 292 | context.global_scope.* = Scope.Root.init(&context); |
| 201 | .base = Scope{ | | |
| 202 | .id = Scope.Id.Root, | | |
| 203 | .parent = null, | | |
| 204 | }, | | |
| 205 | }; | | |
| 206 | | 293 | |
| 207 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { | 294 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { |
| 208 | return context.err; | 295 | return context.err; |
| 209 | } | 296 | } |
| | 297 | |
| | 298 | try transPreprocessorEntities(&context, ast_unit); |
| | 299 | |
| | 300 | try addMacros(&context); |
| 210 | var it = context.alias_list.iterator(0); | 301 | var it = context.alias_list.iterator(0); |
| 211 | while (it.next()) |alias| { | 302 | while (it.next()) |alias| { |
| 212 | if (!context.sym_table.contains(alias.alias)) { | 303 | if (!context.global_scope.sym_table.contains(alias.alias)) { |
| 213 | try createAlias(&context, alias); | 304 | try createAlias(&context, alias); |
| 214 | } | 305 | } |
| 215 | } | 306 | } |
| ... | @@ -268,7 +359,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -268,7 +359,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 268 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); | 359 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); |
| 269 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); | 360 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); |
| 270 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); | 361 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); |
| 271 | var scope = &c.global_scope.base; | 362 | var fndef_scope = Scope.FnDef.init(c); |
| | 363 | var scope = &fndef_scope.base; |
| 272 | const has_body = ZigClangFunctionDecl_hasBody(fn_decl); | 364 | const has_body = ZigClangFunctionDecl_hasBody(fn_decl); |
| 273 | const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl); | 365 | const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl); |
| 274 | const decl_ctx = FnDeclContext{ | 366 | const decl_ctx = FnDeclContext{ |
| ... | @@ -314,14 +406,14 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -314,14 +406,14 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 314 | | 406 | |
| 315 | // actual function definition with body | 407 | // actual function definition with body |
| 316 | const body_stmt = ZigClangFunctionDecl_getBody(fn_decl); | 408 | const body_stmt = ZigClangFunctionDecl_getBody(fn_decl); |
| 317 | const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) { | 409 | const body_node = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) { |
| 318 | error.OutOfMemory => |e| return e, | 410 | error.OutOfMemory => |e| return e, |
| 319 | error.UnsupportedTranslation, | 411 | error.UnsupportedTranslation, |
| 320 | error.UnsupportedType, | 412 | error.UnsupportedType, |
| 321 | => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}), | 413 | => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}), |
| 322 | }; | 414 | }; |
| 323 | assert(result.node.id == ast.Node.Id.Block); | 415 | assert(body_node.id == .Block); |
| 324 | proto_node.body_node = result.node; | 416 | proto_node.body_node = body_node; |
| 325 | | 417 | |
| 326 | return addTopLevelDecl(c, fn_name, &proto_node.base); | 418 | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| 327 | } | 419 | } |
| ... | @@ -336,7 +428,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -336,7 +428,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 336 | else | 428 | else |
| 337 | try appendToken(c, .Keyword_threadlocal, "threadlocal"); | 429 | try appendToken(c, .Keyword_threadlocal, "threadlocal"); |
| 338 | | 430 | |
| 339 | var scope = &c.global_scope.base; | 431 | const scope = &c.global_scope.base; |
| 340 | const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); | 432 | const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); |
| 341 | _ = try c.decl_table.put(@ptrToInt(var_decl), var_name); | 433 | _ = try c.decl_table.put(@ptrToInt(var_decl), var_name); |
| 342 | const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); | 434 | const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); |
| ... | @@ -372,17 +464,16 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -372,17 +464,16 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 372 | | 464 | |
| 373 | if (ZigClangVarDecl_hasInit(var_decl)) { | 465 | if (ZigClangVarDecl_hasInit(var_decl)) { |
| 374 | eq_tok = try appendToken(c, .Equal, "="); | 466 | eq_tok = try appendToken(c, .Equal, "="); |
| 375 | init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| blk: { | 467 | init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| |
| 376 | var res = transExpr(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) { | 468 | transExpr(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) { |
| 377 | error.UnsupportedTranslation, | 469 | error.UnsupportedTranslation, |
| 378 | error.UnsupportedType, | 470 | error.UnsupportedType, |
| 379 | => { | 471 | => { |
| 380 | return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{}); | 472 | return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{}); |
| 381 | }, | 473 | }, |
| 382 | error.OutOfMemory => |e| return e, | 474 | error.OutOfMemory => |e| return e, |
| 383 | }; | 475 | } |
| 384 | break :blk res.node; | 476 | else |
| 385 | } else | | |
| 386 | try transCreateNodeUndefinedLiteral(c); | 477 | try transCreateNodeUndefinedLiteral(c); |
| 387 | } else if (storage_class != .Extern) { | 478 | } else if (storage_class != .Extern) { |
| 388 | return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{}); | 479 | return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{}); |
| ... | @@ -548,7 +639,7 @@ fn transStmt( | ... | @@ -548,7 +639,7 @@ fn transStmt( |
| 548 | stmt: *const ZigClangStmt, | 639 | stmt: *const ZigClangStmt, |
| 549 | result_used: ResultUsed, | 640 | result_used: ResultUsed, |
| 550 | lrvalue: LRValue, | 641 | lrvalue: LRValue, |
| 551 | ) TransError!TransResult { | 642 | ) TransError!*ast.Node { |
| 552 | const sc = ZigClangStmt_getStmtClass(stmt); | 643 | const sc = ZigClangStmt_getStmtClass(stmt); |
| 553 | switch (sc) { | 644 | switch (sc) { |
| 554 | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used), | 645 | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used), |
| ... | @@ -580,7 +671,7 @@ fn transBinaryOperator( | ... | @@ -580,7 +671,7 @@ fn transBinaryOperator( |
| 580 | scope: *Scope, | 671 | scope: *Scope, |
| 581 | stmt: *const ZigClangBinaryOperator, | 672 | stmt: *const ZigClangBinaryOperator, |
| 582 | result_used: ResultUsed, | 673 | result_used: ResultUsed, |
| 583 | ) TransError!TransResult { | 674 | ) TransError!*ast.Node { |
| 584 | const op = ZigClangBinaryOperator_getOpcode(stmt); | 675 | const op = ZigClangBinaryOperator_getOpcode(stmt); |
| 585 | const qt = ZigClangBinaryOperator_getType(stmt); | 676 | const qt = ZigClangBinaryOperator_getType(stmt); |
| 586 | switch (op) { | 677 | switch (op) { |
| ... | @@ -591,67 +682,43 @@ fn transBinaryOperator( | ... | @@ -591,67 +682,43 @@ fn transBinaryOperator( |
| 591 | "TODO: handle more C binary operators: {}", | 682 | "TODO: handle more C binary operators: {}", |
| 592 | .{op}, | 683 | .{op}, |
| 593 | ), | 684 | ), |
| 594 | .Assign => return TransResult{ | 685 | .Assign => return &(try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt))).base, |
| 595 | .node = &(try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt))).base, | | |
| 596 | .child_scope = scope, | | |
| 597 | .node_scope = scope, | | |
| 598 | }, | | |
| 599 | .Add => { | 686 | .Add => { |
| 600 | const node = if (cIsUnsignedInteger(qt)) | 687 | const node = if (cIsUnsignedInteger(qt)) |
| 601 | try transCreateNodeInfixOp(rp, scope, stmt, .AddWrap, .PlusPercent, "+%", true) | 688 | try transCreateNodeInfixOp(rp, scope, stmt, .AddWrap, .PlusPercent, "+%", true) |
| 602 | else | 689 | else |
| 603 | try transCreateNodeInfixOp(rp, scope, stmt, .Add, .Plus, "+", true); | 690 | try transCreateNodeInfixOp(rp, scope, stmt, .Add, .Plus, "+", true); |
| 604 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 691 | return maybeSuppressResult(rp, scope, result_used, node); |
| 605 | .node = node, | | |
| 606 | .child_scope = scope, | | |
| 607 | .node_scope = scope, | | |
| 608 | }); | | |
| 609 | }, | 692 | }, |
| 610 | .Sub => { | 693 | .Sub => { |
| 611 | const node = if (cIsUnsignedInteger(qt)) | 694 | const node = if (cIsUnsignedInteger(qt)) |
| 612 | try transCreateNodeInfixOp(rp, scope, stmt, .SubWrap, .MinusPercent, "-%", true) | 695 | try transCreateNodeInfixOp(rp, scope, stmt, .SubWrap, .MinusPercent, "-%", true) |
| 613 | else | 696 | else |
| 614 | try transCreateNodeInfixOp(rp, scope, stmt, .Sub, .Minus, "-", true); | 697 | try transCreateNodeInfixOp(rp, scope, stmt, .Sub, .Minus, "-", true); |
| 615 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 698 | return maybeSuppressResult(rp, scope, result_used, node); |
| 616 | .node = node, | | |
| 617 | .child_scope = scope, | | |
| 618 | .node_scope = scope, | | |
| 619 | }); | | |
| 620 | }, | 699 | }, |
| 621 | .Mul => { | 700 | .Mul => { |
| 622 | const node = if (cIsUnsignedInteger(qt)) | 701 | const node = if (cIsUnsignedInteger(qt)) |
| 623 | try transCreateNodeInfixOp(rp, scope, stmt, .MultWrap, .AsteriskPercent, "*%", true) | 702 | try transCreateNodeInfixOp(rp, scope, stmt, .MultWrap, .AsteriskPercent, "*%", true) |
| 624 | else | 703 | else |
| 625 | try transCreateNodeInfixOp(rp, scope, stmt, .Mult, .Asterisk, "*", true); | 704 | try transCreateNodeInfixOp(rp, scope, stmt, .Mult, .Asterisk, "*", true); |
| 626 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 705 | return maybeSuppressResult(rp, scope, result_used, node); |
| 627 | .node = node, | | |
| 628 | .child_scope = scope, | | |
| 629 | .node_scope = scope, | | |
| 630 | }); | | |
| 631 | }, | 706 | }, |
| 632 | .Div => { | 707 | .Div => { |
| 633 | if (!cIsUnsignedInteger(qt)) { | 708 | if (!cIsUnsignedInteger(qt)) { |
| 634 | // signed integer division uses @divTrunc | 709 | // signed integer division uses @divTrunc |
| 635 | const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc"); | 710 | const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc"); |
| 636 | const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value); | 711 | const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value); |
| 637 | try div_trunc_node.params.push(lhs.node); | 712 | try div_trunc_node.params.push(lhs); |
| 638 | _ = try appendToken(rp.c, .Comma, ","); | 713 | _ = try appendToken(rp.c, .Comma, ","); |
| 639 | const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); | 714 | const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); |
| 640 | try div_trunc_node.params.push(rhs.node); | 715 | try div_trunc_node.params.push(rhs); |
| 641 | div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 716 | div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 642 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 717 | return maybeSuppressResult(rp, scope, result_used, &div_trunc_node.base); |
| 643 | .node = &div_trunc_node.base, | | |
| 644 | .child_scope = scope, | | |
| 645 | .node_scope = scope, | | |
| 646 | }); | | |
| 647 | } else { | 718 | } else { |
| 648 | // unsigned/float division uses the operator | 719 | // unsigned/float division uses the operator |
| 649 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .Div, .Slash, "/", true); | 720 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .Div, .Slash, "/", true); |
| 650 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 721 | return maybeSuppressResult(rp, scope, result_used, node); |
| 651 | .node = node, | | |
| 652 | .child_scope = scope, | | |
| 653 | .node_scope = scope, | | |
| 654 | }); | | |
| 655 | } | 722 | } |
| 656 | }, | 723 | }, |
| 657 | .Rem => { | 724 | .Rem => { |
| ... | @@ -659,24 +726,16 @@ fn transBinaryOperator( | ... | @@ -659,24 +726,16 @@ fn transBinaryOperator( |
| 659 | // signed integer division uses @rem | 726 | // signed integer division uses @rem |
| 660 | const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem"); | 727 | const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem"); |
| 661 | const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value); | 728 | const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value); |
| 662 | try rem_node.params.push(lhs.node); | 729 | try rem_node.params.push(lhs); |
| 663 | _ = try appendToken(rp.c, .Comma, ","); | 730 | _ = try appendToken(rp.c, .Comma, ","); |
| 664 | const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); | 731 | const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); |
| 665 | try rem_node.params.push(rhs.node); | 732 | try rem_node.params.push(rhs); |
| 666 | rem_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 733 | rem_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 667 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 734 | return maybeSuppressResult(rp, scope, result_used, &rem_node.base); |
| 668 | .node = &rem_node.base, | | |
| 669 | .child_scope = scope, | | |
| 670 | .node_scope = scope, | | |
| 671 | }); | | |
| 672 | } else { | 735 | } else { |
| 673 | // unsigned/float division uses the operator | 736 | // unsigned/float division uses the operator |
| 674 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .Mod, .Percent, "%", true); | 737 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .Mod, .Percent, "%", true); |
| 675 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 738 | return maybeSuppressResult(rp, scope, result_used, node); |
| 676 | .node = node, | | |
| 677 | .child_scope = scope, | | |
| 678 | .node_scope = scope, | | |
| 679 | }); | | |
| 680 | } | 739 | } |
| 681 | }, | 740 | }, |
| 682 | .Shl, | 741 | .Shl, |
| ... | @@ -720,33 +779,22 @@ fn transCompoundStmtInline( | ... | @@ -720,33 +779,22 @@ fn transCompoundStmtInline( |
| 720 | parent_scope: *Scope, | 779 | parent_scope: *Scope, |
| 721 | stmt: *const ZigClangCompoundStmt, | 780 | stmt: *const ZigClangCompoundStmt, |
| 722 | block_node: *ast.Node.Block, | 781 | block_node: *ast.Node.Block, |
| 723 | ) TransError!TransResult { | 782 | ) TransError!void { |
| 724 | var it = ZigClangCompoundStmt_body_begin(stmt); | 783 | var it = ZigClangCompoundStmt_body_begin(stmt); |
| 725 | const end_it = ZigClangCompoundStmt_body_end(stmt); | 784 | const end_it = ZigClangCompoundStmt_body_end(stmt); |
| 726 | var scope = parent_scope; | | |
| 727 | while (it != end_it) : (it += 1) { | 785 | while (it != end_it) : (it += 1) { |
| 728 | const result = try transStmt(rp, parent_scope, it.*, .unused, .r_value); | 786 | const result = try transStmt(rp, parent_scope, it[0], .unused, .r_value); |
| 729 | scope = result.child_scope; | 787 | if (result != &block_node.base) |
| 730 | if (result.node != &block_node.base) | 788 | try block_node.statements.push(result); |
| 731 | try block_node.statements.push(result.node); | | |
| 732 | } | 789 | } |
| 733 | return TransResult{ | | |
| 734 | .node = &block_node.base, | | |
| 735 | .child_scope = scope, | | |
| 736 | .node_scope = scope, | | |
| 737 | }; | | |
| 738 | } | 790 | } |
| 739 | | 791 | |
| 740 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) !TransResult { | 792 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { |
| 741 | const lbrace_tok = try appendToken(rp.c, .LBrace, "{"); | 793 | const block_node = try transCreateNodeBlock(rp.c, null); |
| 742 | const block_scope = try Scope.Block.create(rp.c, scope, lbrace_tok); | 794 | const block_scope = try Scope.Block.init(rp.c, scope, block_node); |
| 743 | const inline_result = try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); | 795 | try transCompoundStmtInline(rp, &block_scope.base, stmt, block_node); |
| 744 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); | 796 | block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 745 | return TransResult{ | 797 | return &block_node.base; |
| 746 | .node = &block_scope.block_node.base, | | |
| 747 | .node_scope = inline_result.node_scope, | | |
| 748 | .child_scope = inline_result.child_scope, | | |
| 749 | }; | | |
| 750 | } | 798 | } |
| 751 | | 799 | |
| 752 | fn transCStyleCastExprClass( | 800 | fn transCStyleCastExprClass( |
| ... | @@ -755,7 +803,7 @@ fn transCStyleCastExprClass( | ... | @@ -755,7 +803,7 @@ fn transCStyleCastExprClass( |
| 755 | stmt: *const ZigClangCStyleCastExpr, | 803 | stmt: *const ZigClangCStyleCastExpr, |
| 756 | result_used: ResultUsed, | 804 | result_used: ResultUsed, |
| 757 | lrvalue: LRValue, | 805 | lrvalue: LRValue, |
| 758 | ) !TransResult { | 806 | ) TransError!*ast.Node { |
| 759 | const sub_expr = ZigClangCStyleCastExpr_getSubExpr(stmt); | 807 | const sub_expr = ZigClangCStyleCastExpr_getSubExpr(stmt); |
| 760 | const cast_node = (try transCCast( | 808 | const cast_node = (try transCCast( |
| 761 | rp, | 809 | rp, |
| ... | @@ -763,27 +811,21 @@ fn transCStyleCastExprClass( | ... | @@ -763,27 +811,21 @@ fn transCStyleCastExprClass( |
| 763 | ZigClangCStyleCastExpr_getBeginLoc(stmt), | 811 | ZigClangCStyleCastExpr_getBeginLoc(stmt), |
| 764 | ZigClangCStyleCastExpr_getType(stmt), | 812 | ZigClangCStyleCastExpr_getType(stmt), |
| 765 | ZigClangExpr_getType(sub_expr), | 813 | ZigClangExpr_getType(sub_expr), |
| 766 | (try transExpr(rp, scope, sub_expr, .used, lrvalue)).node, | 814 | try transExpr(rp, scope, sub_expr, .used, lrvalue), |
| 767 | )); | 815 | )); |
| 768 | const cast_res = TransResult{ | 816 | return maybeSuppressResult(rp, scope, result_used, cast_node); |
| 769 | .node = cast_node, | | |
| 770 | .child_scope = scope, | | |
| 771 | .node_scope = scope, | | |
| 772 | }; | | |
| 773 | return maybeSuppressResult(rp, scope, result_used, cast_res); | | |
| 774 | } | 817 | } |
| 775 | | 818 | |
| 776 | fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDeclStmt) !TransResult { | 819 | fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node { |
| 777 | const c = rp.c; | 820 | const c = rp.c; |
| 778 | const block_scope = findBlockScope(parent_scope); | 821 | const block_scope = scope.findBlockScope(); |
| 779 | var scope = parent_scope; | | |
| 780 | | 822 | |
| 781 | var it = ZigClangDeclStmt_decl_begin(stmt); | 823 | var it = ZigClangDeclStmt_decl_begin(stmt); |
| 782 | const end_it = ZigClangDeclStmt_decl_end(stmt); | 824 | const end_it = ZigClangDeclStmt_decl_end(stmt); |
| 783 | while (it != end_it) : (it += 1) { | 825 | while (it != end_it) : (it += 1) { |
| 784 | switch (ZigClangDecl_getKind(it.*)) { | 826 | switch (ZigClangDecl_getKind(it[0])) { |
| 785 | .Var => { | 827 | .Var => { |
| 786 | const var_decl = @ptrCast(*const ZigClangVarDecl, it.*); | 828 | const var_decl = @ptrCast(*const ZigClangVarDecl, it[0]); |
| 787 | | 829 | |
| 788 | const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) | 830 | const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) |
| 789 | null | 831 | null |
| ... | @@ -794,18 +836,14 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe | ... | @@ -794,18 +836,14 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe |
| 794 | try appendToken(c, .Keyword_const, "const") | 836 | try appendToken(c, .Keyword_const, "const") |
| 795 | else | 837 | else |
| 796 | try appendToken(c, .Keyword_var, "var"); | 838 | try appendToken(c, .Keyword_var, "var"); |
| 797 | const c_name = try c.str(ZigClangDecl_getName_bytes_begin( | 839 | const name = try c.str(ZigClangDecl_getName_bytes_begin( |
| 798 | @ptrCast(*const ZigClangDecl, var_decl), | 840 | @ptrCast(*const ZigClangDecl, var_decl), |
| 799 | )); | 841 | )); |
| 800 | const name_token = try appendIdentifier(c, c_name); | 842 | const checked_name = if (try scope.createAlias(c, name)) |a| blk: { |
| 801 | | 843 | try block_scope.variables.push(.{ .name = name, .alias = a }); |
| 802 | const var_scope = try c.a().create(Scope.Var); | 844 | break :blk a; |
| 803 | var_scope.* = Scope.Var{ | 845 | } else name; |
| 804 | .base = Scope{ .id = .Var, .parent = scope }, | 846 | const name_token = try appendIdentifier(c, checked_name); |
| 805 | .c_name = c_name, | | |
| 806 | .zig_name = c_name, // TODO: getWantedName | | |
| 807 | }; | | |
| 808 | scope = &var_scope.base; | | |
| 809 | | 847 | |
| 810 | const colon_token = try appendToken(c, .Colon, ":"); | 848 | const colon_token = try appendToken(c, .Colon, ":"); |
| 811 | const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)); | 849 | const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)); |
| ... | @@ -813,7 +851,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe | ... | @@ -813,7 +851,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe |
| 813 | | 851 | |
| 814 | const eq_token = try appendToken(c, .Equal, "="); | 852 | const eq_token = try appendToken(c, .Equal, "="); |
| 815 | const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| | 853 | const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| |
| 816 | (try transExpr(rp, scope, expr, .used, .r_value)).node | 854 | try transExpr(rp, scope, expr, .used, .r_value) |
| 817 | else | 855 | else |
| 818 | try transCreateNodeUndefinedLiteral(c); | 856 | try transCreateNodeUndefinedLiteral(c); |
| 819 | const semicolon_token = try appendToken(c, .Semicolon, ";"); | 857 | const semicolon_token = try appendToken(c, .Semicolon, ";"); |
| ... | @@ -837,7 +875,6 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe | ... | @@ -837,7 +875,6 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe |
| 837 | }; | 875 | }; |
| 838 | try block_scope.block_node.statements.push(&node.base); | 876 | try block_scope.block_node.statements.push(&node.base); |
| 839 | }, | 877 | }, |
| 840 | | | |
| 841 | else => |kind| return revertAndWarn( | 878 | else => |kind| return revertAndWarn( |
| 842 | rp, | 879 | rp, |
| 843 | error.UnsupportedTranslation, | 880 | error.UnsupportedTranslation, |
| ... | @@ -847,12 +884,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe | ... | @@ -847,12 +884,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe |
| 847 | ), | 884 | ), |
| 848 | } | 885 | } |
| 849 | } | 886 | } |
| 850 | | 887 | return &block_scope.block_node.base; |
| 851 | return TransResult{ | | |
| 852 | .node = &block_scope.block_node.base, | | |
| 853 | .node_scope = scope, | | |
| 854 | .child_scope = scope, | | |
| 855 | }; | | |
| 856 | } | 888 | } |
| 857 | | 889 | |
| 858 | fn transDeclRefExpr( | 890 | fn transDeclRefExpr( |
| ... | @@ -860,17 +892,12 @@ fn transDeclRefExpr( | ... | @@ -860,17 +892,12 @@ fn transDeclRefExpr( |
| 860 | scope: *Scope, | 892 | scope: *Scope, |
| 861 | expr: *const ZigClangDeclRefExpr, | 893 | expr: *const ZigClangDeclRefExpr, |
| 862 | lrvalue: LRValue, | 894 | lrvalue: LRValue, |
| 863 | ) !TransResult { | 895 | ) TransError!*ast.Node { |
| 864 | const value_decl = ZigClangDeclRefExpr_getDecl(expr); | 896 | const value_decl = ZigClangDeclRefExpr_getDecl(expr); |
| 865 | const c_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl))); | 897 | const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl))); |
| 866 | const zig_name = transLookupZigIdentifier(scope, c_name); | 898 | const checked_name = if (scope.getAlias(name)) |a| a else name; |
| 867 | if (lrvalue == .l_value) try rp.c.ptr_params.put(zig_name); | 899 | if (lrvalue == .l_value) try rp.c.ptr_params.put(checked_name); |
| 868 | const node = try transCreateNodeIdentifier(rp.c, zig_name); | 900 | return transCreateNodeIdentifier(rp.c, checked_name); |
| 869 | return TransResult{ | | |
| 870 | .node = node, | | |
| 871 | .node_scope = scope, | | |
| 872 | .child_scope = scope, | | |
| 873 | }; | | |
| 874 | } | 901 | } |
| 875 | | 902 | |
| 876 | fn transImplicitCastExpr( | 903 | fn transImplicitCastExpr( |
| ... | @@ -878,7 +905,7 @@ fn transImplicitCastExpr( | ... | @@ -878,7 +905,7 @@ fn transImplicitCastExpr( |
| 878 | scope: *Scope, | 905 | scope: *Scope, |
| 879 | expr: *const ZigClangImplicitCastExpr, | 906 | expr: *const ZigClangImplicitCastExpr, |
| 880 | result_used: ResultUsed, | 907 | result_used: ResultUsed, |
| 881 | ) !TransResult { | 908 | ) TransError!*ast.Node { |
| 882 | const c = rp.c; | 909 | const c = rp.c; |
| 883 | const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr); | 910 | const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr); |
| 884 | const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value); | 911 | const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value); |
| ... | @@ -886,20 +913,12 @@ fn transImplicitCastExpr( | ... | @@ -886,20 +913,12 @@ fn transImplicitCastExpr( |
| 886 | .BitCast => { | 913 | .BitCast => { |
| 887 | const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr)); | 914 | const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr)); |
| 888 | const src_type = getExprQualType(c, sub_expr); | 915 | const src_type = getExprQualType(c, sub_expr); |
| 889 | return TransResult{ | 916 | return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node); |
| 890 | .node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node.node), | | |
| 891 | .node_scope = scope, | | |
| 892 | .child_scope = scope, | | |
| 893 | }; | | |
| 894 | }, | 917 | }, |
| 895 | .IntegralCast => { | 918 | .IntegralCast => { |
| 896 | const dest_type = ZigClangExpr_getType(@ptrCast(*const ZigClangExpr, expr)); | 919 | const dest_type = ZigClangExpr_getType(@ptrCast(*const ZigClangExpr, expr)); |
| 897 | const src_type = ZigClangExpr_getType(sub_expr); | 920 | const src_type = ZigClangExpr_getType(sub_expr); |
| 898 | return TransResult{ | 921 | return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node); |
| 899 | .node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node.node), | | |
| 900 | .node_scope = scope, | | |
| 901 | .child_scope = scope, | | |
| 902 | }; | | |
| 903 | }, | 922 | }, |
| 904 | .FunctionToPointerDecay, .ArrayToPointerDecay => { | 923 | .FunctionToPointerDecay, .ArrayToPointerDecay => { |
| 905 | return maybeSuppressResult(rp, scope, result_used, sub_expr_node); | 924 | return maybeSuppressResult(rp, scope, result_used, sub_expr_node); |
| ... | @@ -908,11 +927,7 @@ fn transImplicitCastExpr( | ... | @@ -908,11 +927,7 @@ fn transImplicitCastExpr( |
| 908 | return transExpr(rp, scope, sub_expr, .used, .r_value); | 927 | return transExpr(rp, scope, sub_expr, .used, .r_value); |
| 909 | }, | 928 | }, |
| 910 | .NullToPointer => { | 929 | .NullToPointer => { |
| 911 | return TransResult{ | 930 | return transCreateNodeNullLiteral(rp.c); |
| 912 | .node = try transCreateNodeNullLiteral(rp.c), | | |
| 913 | .node_scope = scope, | | |
| 914 | .child_scope = scope, | | |
| 915 | }; | | |
| 916 | }, | 931 | }, |
| 917 | else => |kind| return revertAndWarn( | 932 | else => |kind| return revertAndWarn( |
| 918 | rp, | 933 | rp, |
| ... | @@ -929,37 +944,27 @@ fn transIntegerLiteral( | ... | @@ -929,37 +944,27 @@ fn transIntegerLiteral( |
| 929 | scope: *Scope, | 944 | scope: *Scope, |
| 930 | expr: *const ZigClangIntegerLiteral, | 945 | expr: *const ZigClangIntegerLiteral, |
| 931 | result_used: ResultUsed, | 946 | result_used: ResultUsed, |
| 932 | ) !TransResult { | 947 | ) TransError!*ast.Node { |
| 933 | var eval_result: ZigClangExprEvalResult = undefined; | 948 | var eval_result: ZigClangExprEvalResult = undefined; |
| 934 | if (!ZigClangIntegerLiteral_EvaluateAsInt(expr, &eval_result, rp.c.clang_context)) { | 949 | if (!ZigClangIntegerLiteral_EvaluateAsInt(expr, &eval_result, rp.c.clang_context)) { |
| 935 | const loc = ZigClangIntegerLiteral_getBeginLoc(expr); | 950 | const loc = ZigClangIntegerLiteral_getBeginLoc(expr); |
| 936 | return revertAndWarn(rp, error.UnsupportedTranslation, loc, "invalid integer literal", .{}); | 951 | return revertAndWarn(rp, error.UnsupportedTranslation, loc, "invalid integer literal", .{}); |
| 937 | } | 952 | } |
| 938 | const node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val)); | 953 | const node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val)); |
| 939 | const res = TransResult{ | 954 | return maybeSuppressResult(rp, scope, result_used, node); |
| 940 | .node = node, | | |
| 941 | .child_scope = scope, | | |
| 942 | .node_scope = scope, | | |
| 943 | }; | | |
| 944 | return maybeSuppressResult(rp, scope, result_used, res); | | |
| 945 | } | 955 | } |
| 946 | | 956 | |
| 947 | fn transReturnStmt( | 957 | fn transReturnStmt( |
| 948 | rp: RestorePoint, | 958 | rp: RestorePoint, |
| 949 | scope: *Scope, | 959 | scope: *Scope, |
| 950 | expr: *const ZigClangReturnStmt, | 960 | expr: *const ZigClangReturnStmt, |
| 951 | ) !TransResult { | 961 | ) TransError!*ast.Node { |
| 952 | const node = try transCreateNodeReturnExpr(rp.c); | 962 | const node = try transCreateNodeReturnExpr(rp.c); |
| 953 | if (ZigClangReturnStmt_getRetValue(expr)) |val_expr| { | 963 | if (ZigClangReturnStmt_getRetValue(expr)) |val_expr| { |
| 954 | const ret_node = node.cast(ast.Node.ControlFlowExpression).?; | 964 | node.rhs = try transExpr(rp, scope, val_expr, .used, .r_value); |
| 955 | ret_node.rhs = (try transExpr(rp, scope, val_expr, .used, .r_value)).node; | | |
| 956 | } | 965 | } |
| 957 | _ = try appendToken(rp.c, .Semicolon, ";"); | 966 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 958 | return TransResult{ | 967 | return &node.base; |
| 959 | .node = node, | | |
| 960 | .child_scope = scope, | | |
| 961 | .node_scope = scope, | | |
| 962 | }; | | |
| 963 | } | 968 | } |
| 964 | | 969 | |
| 965 | fn transStringLiteral( | 970 | fn transStringLiteral( |
| ... | @@ -967,7 +972,7 @@ fn transStringLiteral( | ... | @@ -967,7 +972,7 @@ fn transStringLiteral( |
| 967 | scope: *Scope, | 972 | scope: *Scope, |
| 968 | stmt: *const ZigClangStringLiteral, | 973 | stmt: *const ZigClangStringLiteral, |
| 969 | result_used: ResultUsed, | 974 | result_used: ResultUsed, |
| 970 | ) !TransResult { | 975 | ) TransError!*ast.Node { |
| 971 | const kind = ZigClangStringLiteral_getKind(stmt); | 976 | const kind = ZigClangStringLiteral_getKind(stmt); |
| 972 | switch (kind) { | 977 | switch (kind) { |
| 973 | .Ascii, .UTF8 => { | 978 | .Ascii, .UTF8 => { |
| ... | @@ -989,12 +994,7 @@ fn transStringLiteral( | ... | @@ -989,12 +994,7 @@ fn transStringLiteral( |
| 989 | node.* = ast.Node.StringLiteral{ | 994 | node.* = ast.Node.StringLiteral{ |
| 990 | .token = token, | 995 | .token = token, |
| 991 | }; | 996 | }; |
| 992 | const res = TransResult{ | 997 | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 993 | .node = &node.base, | | |
| 994 | .child_scope = scope, | | |
| 995 | .node_scope = scope, | | |
| 996 | }; | | |
| 997 | return maybeSuppressResult(rp, scope, result_used, res); | | |
| 998 | }, | 998 | }, |
| 999 | .UTF16, .UTF32, .Wide => return revertAndWarn( | 999 | .UTF16, .UTF32, .Wide => return revertAndWarn( |
| 1000 | rp, | 1000 | rp, |
| ... | @@ -1088,7 +1088,7 @@ fn transExpr( | ... | @@ -1088,7 +1088,7 @@ fn transExpr( |
| 1088 | expr: *const ZigClangExpr, | 1088 | expr: *const ZigClangExpr, |
| 1089 | used: ResultUsed, | 1089 | used: ResultUsed, |
| 1090 | lrvalue: LRValue, | 1090 | lrvalue: LRValue, |
| 1091 | ) TransError!TransResult { | 1091 | ) TransError!*ast.Node { |
| 1092 | return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue); | 1092 | return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue); |
| 1093 | } | 1093 | } |
| 1094 | | 1094 | |
| ... | @@ -1097,7 +1097,7 @@ fn transInitListExpr( | ... | @@ -1097,7 +1097,7 @@ fn transInitListExpr( |
| 1097 | scope: *Scope, | 1097 | scope: *Scope, |
| 1098 | expr: *const ZigClangInitListExpr, | 1098 | expr: *const ZigClangInitListExpr, |
| 1099 | used: ResultUsed, | 1099 | used: ResultUsed, |
| 1100 | ) TransError!TransResult { | 1100 | ) TransError!*ast.Node { |
| 1101 | const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr)); | 1101 | const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr)); |
| 1102 | const qual_type = ZigClangQualType_getTypePtr(qt); | 1102 | const qual_type = ZigClangQualType_getTypePtr(qt); |
| 1103 | const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr)); | 1103 | const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr)); |
| ... | @@ -1128,16 +1128,12 @@ fn transInitListExpr( | ... | @@ -1128,16 +1128,12 @@ fn transInitListExpr( |
| 1128 | var i: c_uint = 0; | 1128 | var i: c_uint = 0; |
| 1129 | while (i < init_count) : (i += 1) { | 1129 | while (i < init_count) : (i += 1) { |
| 1130 | const elem_expr = ZigClangInitListExpr_getInit(expr, i); | 1130 | const elem_expr = ZigClangInitListExpr_getInit(expr, i); |
| 1131 | try init_node.op.ArrayInitializer.push((try transExpr(rp, scope, elem_expr, .used, .r_value)).node); | 1131 | try init_node.op.ArrayInitializer.push(try transExpr(rp, scope, elem_expr, .used, .r_value)); |
| 1132 | _ = try appendToken(rp.c, .Comma, ","); | 1132 | _ = try appendToken(rp.c, .Comma, ","); |
| 1133 | } | 1133 | } |
| 1134 | init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | 1134 | init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); |
| 1135 | if (leftover_count == 0) { | 1135 | if (leftover_count == 0) { |
| 1136 | return TransResult{ | 1136 | return &init_node.base; |
| 1137 | .node = &init_node.base, | | |
| 1138 | .child_scope = scope, | | |
| 1139 | .node_scope = scope, | | |
| 1140 | }; | | |
| 1141 | } | 1137 | } |
| 1142 | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); | 1138 | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); |
| 1143 | } | 1139 | } |
| ... | @@ -1145,7 +1141,7 @@ fn transInitListExpr( | ... | @@ -1145,7 +1141,7 @@ fn transInitListExpr( |
| 1145 | const dot_tok = try appendToken(rp.c, .Period, "."); | 1141 | const dot_tok = try appendToken(rp.c, .Period, "."); |
| 1146 | var filler_init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok); | 1142 | var filler_init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok); |
| 1147 | const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr); | 1143 | const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr); |
| 1148 | try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node); | 1144 | try filler_init_node.op.ArrayInitializer.push(try transExpr(rp, scope, filler_val_expr, .used, .r_value)); |
| 1149 | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | 1145 | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); |
| 1150 | | 1146 | |
| 1151 | const rhs_node = if (leftover_count == 1) | 1147 | const rhs_node = if (leftover_count == 1) |
| ... | @@ -1163,11 +1159,7 @@ fn transInitListExpr( | ... | @@ -1163,11 +1159,7 @@ fn transInitListExpr( |
| 1163 | }; | 1159 | }; |
| 1164 | | 1160 | |
| 1165 | if (init_count == 0) { | 1161 | if (init_count == 0) { |
| 1166 | return TransResult{ | 1162 | return rhs_node; |
| 1167 | .node = rhs_node, | | |
| 1168 | .child_scope = scope, | | |
| 1169 | .node_scope = scope, | | |
| 1170 | }; | | |
| 1171 | } | 1163 | } |
| 1172 | | 1164 | |
| 1173 | const cat_node = try rp.c.a().create(ast.Node.InfixOp); | 1165 | const cat_node = try rp.c.a().create(ast.Node.InfixOp); |
| ... | @@ -1177,11 +1169,7 @@ fn transInitListExpr( | ... | @@ -1177,11 +1169,7 @@ fn transInitListExpr( |
| 1177 | .op = .ArrayCat, | 1169 | .op = .ArrayCat, |
| 1178 | .rhs = rhs_node, | 1170 | .rhs = rhs_node, |
| 1179 | }; | 1171 | }; |
| 1180 | return TransResult{ | 1172 | return &cat_node.base; |
| 1181 | .node = &cat_node.base, | | |
| 1182 | .child_scope = scope, | | |
| 1183 | .node_scope = scope, | | |
| 1184 | }; | | |
| 1185 | } | 1173 | } |
| 1186 | | 1174 | |
| 1187 | fn transImplicitValueInitExpr( | 1175 | fn transImplicitValueInitExpr( |
| ... | @@ -1189,7 +1177,7 @@ fn transImplicitValueInitExpr( | ... | @@ -1189,7 +1177,7 @@ fn transImplicitValueInitExpr( |
| 1189 | scope: *Scope, | 1177 | scope: *Scope, |
| 1190 | expr: *const ZigClangExpr, | 1178 | expr: *const ZigClangExpr, |
| 1191 | used: ResultUsed, | 1179 | used: ResultUsed, |
| 1192 | ) TransError!TransResult { | 1180 | ) TransError!*ast.Node { |
| 1193 | const source_loc = ZigClangExpr_getBeginLoc(expr); | 1181 | const source_loc = ZigClangExpr_getBeginLoc(expr); |
| 1194 | const qt = getExprQualType(rp.c, expr); | 1182 | const qt = getExprQualType(rp.c, expr); |
| 1195 | const ty = ZigClangQualType_getTypePtr(qt); | 1183 | const ty = ZigClangQualType_getTypePtr(qt); |
| ... | @@ -1197,9 +1185,7 @@ fn transImplicitValueInitExpr( | ... | @@ -1197,9 +1185,7 @@ fn transImplicitValueInitExpr( |
| 1197 | .Builtin => blk: { | 1185 | .Builtin => blk: { |
| 1198 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); | 1186 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 1199 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | 1187 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 1200 | .Bool => { | 1188 | .Bool => return transCreateNodeBoolLiteral(rp.c, false), |
| 1201 | break :blk try transCreateNodeBoolLiteral(rp.c, false); | | |
| 1202 | }, | | |
| 1203 | .Char_U, | 1189 | .Char_U, |
| 1204 | .UChar, | 1190 | .UChar, |
| 1205 | .Char_S, | 1191 | .Char_S, |
| ... | @@ -1220,37 +1206,13 @@ fn transImplicitValueInitExpr( | ... | @@ -1220,37 +1206,13 @@ fn transImplicitValueInitExpr( |
| 1220 | .Float128, | 1206 | .Float128, |
| 1221 | .Float16, | 1207 | .Float16, |
| 1222 | .LongDouble, | 1208 | .LongDouble, |
| 1223 | => { | 1209 | => return transCreateNodeInt(rp.c, 0), |
| 1224 | break :blk try transCreateNodeInt(rp.c, 0); | | |
| 1225 | }, | | |
| 1226 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}), | 1210 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}), |
| 1227 | } | 1211 | } |
| 1228 | }, | 1212 | }, |
| 1229 | .Pointer => try transCreateNodeNullLiteral(rp.c), | 1213 | .Pointer => return transCreateNodeNullLiteral(rp.c), |
| 1230 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}), | 1214 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}), |
| 1231 | }; | 1215 | }; |
| 1232 | return TransResult{ | | |
| 1233 | .node = node, | | |
| 1234 | .child_scope = scope, | | |
| 1235 | .node_scope = scope, | | |
| 1236 | }; | | |
| 1237 | } | | |
| 1238 | | | |
| 1239 | fn findBlockScope(inner: *Scope) *Scope.Block { | | |
| 1240 | var scope = inner; | | |
| 1241 | while (true) : (scope = scope.parent orelse unreachable) { | | |
| 1242 | if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope); | | |
| 1243 | } | | |
| 1244 | } | | |
| 1245 | | | |
| 1246 | fn transLookupZigIdentifier(inner: *Scope, c_name: []const u8) []const u8 { | | |
| 1247 | var scope = inner; | | |
| 1248 | while (true) : (scope = scope.parent orelse return c_name) { | | |
| 1249 | if (scope.id == .Var) { | | |
| 1250 | const var_scope = @ptrCast(*const Scope.Var, scope); | | |
| 1251 | if (std.mem.eql(u8, var_scope.c_name, c_name)) return var_scope.zig_name; | | |
| 1252 | } | | |
| 1253 | } | | |
| 1254 | } | 1216 | } |
| 1255 | | 1217 | |
| 1256 | fn transCPtrCast( | 1218 | fn transCPtrCast( |
| ... | @@ -1294,8 +1256,8 @@ fn maybeSuppressResult( | ... | @@ -1294,8 +1256,8 @@ fn maybeSuppressResult( |
| 1294 | rp: RestorePoint, | 1256 | rp: RestorePoint, |
| 1295 | scope: *Scope, | 1257 | scope: *Scope, |
| 1296 | used: ResultUsed, | 1258 | used: ResultUsed, |
| 1297 | result: TransResult, | 1259 | result: *ast.Node, |
| 1298 | ) !TransResult { | 1260 | ) TransError!*ast.Node { |
| 1299 | if (used == .used) return result; | 1261 | if (used == .used) return result; |
| 1300 | // NOTE: This is backwards, but the semicolon must immediately follow the node. | 1262 | // NOTE: This is backwards, but the semicolon must immediately follow the node. |
| 1301 | _ = try appendToken(rp.c, .Semicolon, ";"); | 1263 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| ... | @@ -1306,18 +1268,14 @@ fn maybeSuppressResult( | ... | @@ -1306,18 +1268,14 @@ fn maybeSuppressResult( |
| 1306 | .op_token = op_token, | 1268 | .op_token = op_token, |
| 1307 | .lhs = lhs, | 1269 | .lhs = lhs, |
| 1308 | .op = .Assign, | 1270 | .op = .Assign, |
| 1309 | .rhs = result.node, | 1271 | .rhs = result, |
| 1310 | }; | | |
| 1311 | return TransResult{ | | |
| 1312 | .node = &op_node.base, | | |
| 1313 | .child_scope = scope, | | |
| 1314 | .node_scope = scope, | | |
| 1315 | }; | 1272 | }; |
| | 1273 | return &op_node.base; |
| 1316 | } | 1274 | } |
| 1317 | | 1275 | |
| 1318 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { | 1276 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { |
| 1319 | try c.tree.root_node.decls.push(decl_node); | 1277 | try c.tree.root_node.decls.push(decl_node); |
| 1320 | _ = try c.sym_table.put(name, {}); | 1278 | _ = try c.global_scope.sym_table.put(name, decl_node); |
| 1321 | } | 1279 | } |
| 1322 | | 1280 | |
| 1323 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node { | 1281 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node { |
| ... | @@ -1716,11 +1674,11 @@ fn transCreateNodeAssign( | ... | @@ -1716,11 +1674,11 @@ fn transCreateNodeAssign( |
| 1716 | _ = try appendToken(rp.c, .Semicolon, ";"); | 1674 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 1717 | | 1675 | |
| 1718 | const node = try rp.c.a().create(ast.Node.InfixOp); | 1676 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| 1719 | node.* = ast.Node.InfixOp{ | 1677 | node.* = .{ |
| 1720 | .op_token = eq_token, | 1678 | .op_token = eq_token, |
| 1721 | .lhs = lhs_node.node, | 1679 | .lhs = lhs_node, |
| 1722 | .op = .Assign, | 1680 | .op = .Assign, |
| 1723 | .rhs = rhs_node.node, | 1681 | .rhs = rhs_node, |
| 1724 | }; | 1682 | }; |
| 1725 | return node; | 1683 | return node; |
| 1726 | } | 1684 | } |
| ... | @@ -1757,7 +1715,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { | ... | @@ -1757,7 +1715,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 1757 | _ = try appendToken(c, .LParen, "("); | 1715 | _ = try appendToken(c, .LParen, "("); |
| 1758 | const node = try c.a().create(ast.Node.SuffixOp); | 1716 | const node = try c.a().create(ast.Node.SuffixOp); |
| 1759 | node.* = ast.Node.SuffixOp{ | 1717 | node.* = ast.Node.SuffixOp{ |
| 1760 | .lhs = fn_expr, | 1718 | .lhs = .{ .node = fn_expr }, |
| 1761 | .op = ast.Node.SuffixOp.Op{ | 1719 | .op = ast.Node.SuffixOp.Op{ |
| 1762 | .Call = ast.Node.SuffixOp.Op.Call{ | 1720 | .Call = ast.Node.SuffixOp.Op.Call{ |
| 1763 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), | 1721 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), |
| ... | @@ -1800,9 +1758,9 @@ fn transCreateNodeInfixOp( | ... | @@ -1800,9 +1758,9 @@ fn transCreateNodeInfixOp( |
| 1800 | const node = try rp.c.a().create(ast.Node.InfixOp); | 1758 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| 1801 | node.* = ast.Node.InfixOp{ | 1759 | node.* = ast.Node.InfixOp{ |
| 1802 | .op_token = op_token, | 1760 | .op_token = op_token, |
| 1803 | .lhs = lhs.node, | 1761 | .lhs = lhs, |
| 1804 | .op = op, | 1762 | .op = op, |
| 1805 | .rhs = rhs.node, | 1763 | .rhs = rhs, |
| 1806 | }; | 1764 | }; |
| 1807 | if (!grouped) return &node.base; | 1765 | if (!grouped) return &node.base; |
| 1808 | const rparen = try appendToken(rp.c, .RParen, ")"); | 1766 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| ... | @@ -1871,7 +1829,7 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { | ... | @@ -1871,7 +1829,7 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { |
| 1871 | return &node.base; | 1829 | return &node.base; |
| 1872 | } | 1830 | } |
| 1873 | | 1831 | |
| 1874 | fn transCreateNodeReturnExpr(c: *Context) !*ast.Node { | 1832 | fn transCreateNodeReturnExpr(c: *Context) !*ast.Node.ControlFlowExpression { |
| 1875 | const ltoken = try appendToken(c, .Keyword_return, "return"); | 1833 | const ltoken = try appendToken(c, .Keyword_return, "return"); |
| 1876 | const node = try c.a().create(ast.Node.ControlFlowExpression); | 1834 | const node = try c.a().create(ast.Node.ControlFlowExpression); |
| 1877 | node.* = ast.Node.ControlFlowExpression{ | 1835 | node.* = ast.Node.ControlFlowExpression{ |
| ... | @@ -1879,7 +1837,7 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node { | ... | @@ -1879,7 +1837,7 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node { |
| 1879 | .kind = .Return, | 1837 | .kind = .Return, |
| 1880 | .rhs = null, | 1838 | .rhs = null, |
| 1881 | }; | 1839 | }; |
| 1882 | return &node.base; | 1840 | return node; |
| 1883 | } | 1841 | } |
| 1884 | | 1842 | |
| 1885 | fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { | 1843 | fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| ... | @@ -1934,19 +1892,158 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { | ... | @@ -1934,19 +1892,158 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { |
| 1934 | return &node.base; | 1892 | return &node.base; |
| 1935 | } | 1893 | } |
| 1936 | | 1894 | |
| | 1895 | fn transCreateNodeFloat(c: *Context, int: var) !*ast.Node { |
| | 1896 | const token = try appendTokenFmt(c, .FloatLiteral, "{}", .{int}); |
| | 1897 | const node = try c.a().create(ast.Node.FloatLiteral); |
| | 1898 | node.* = .{ |
| | 1899 | .token = token, |
| | 1900 | }; |
| | 1901 | return &node.base; |
| | 1902 | } |
| | 1903 | |
| 1937 | fn transCreateNodeOpaqueType(c: *Context) !*ast.Node { | 1904 | fn transCreateNodeOpaqueType(c: *Context) !*ast.Node { |
| 1938 | const builtin_tok = try appendToken(c, .Builtin, "@OpaqueType"); | 1905 | const call_node = try transCreateNodeBuiltinFnCall(c, "@OpaqueType"); |
| | 1906 | call_node.rparen_token = try appendToken(c, .RParen, ")"); |
| | 1907 | return &call_node.base; |
| | 1908 | } |
| | 1909 | |
| | 1910 | fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_alias_node: *ast.Node) !*ast.Node { |
| | 1911 | const scope = &c.global_scope.base; |
| | 1912 | |
| | 1913 | const pub_tok = try appendToken(c, .Keyword_pub, "pub"); |
| | 1914 | const inline_tok = try appendToken(c, .Keyword_inline, "inline"); |
| | 1915 | const fn_tok = try appendToken(c, .Keyword_fn, "fn"); |
| | 1916 | const name_tok = try appendIdentifier(c, name); |
| 1939 | _ = try appendToken(c, .LParen, "("); | 1917 | _ = try appendToken(c, .LParen, "("); |
| 1940 | const rparen_tok = try appendToken(c, .RParen, ")"); | | |
| 1941 | | 1918 | |
| 1942 | const call_node = try c.a().create(ast.Node.BuiltinCall); | 1919 | const proto_alias = proto_alias_node.cast(ast.Node.FnProto).?; |
| 1943 | call_node.* = ast.Node.BuiltinCall{ | 1920 | |
| 1944 | .base = ast.Node{ .id = ast.Node.Id.BuiltinCall }, | 1921 | var fn_params = ast.Node.FnProto.ParamList.init(c.a()); |
| 1945 | .builtin_token = builtin_tok, | 1922 | var it = proto_alias.params.iterator(0); |
| 1946 | .params = ast.Node.BuiltinCall.ParamList.init(c.a()), | 1923 | while (it.next()) |pn| { |
| 1947 | .rparen_token = rparen_tok, | 1924 | if (it.index != 0) { |
| | 1925 | _ = try appendToken(c, .Comma, ","); |
| | 1926 | } |
| | 1927 | const param = pn.*.cast(ast.Node.ParamDecl).?; |
| | 1928 | |
| | 1929 | const param_name_tok = param.name_token orelse |
| | 1930 | try appendTokenFmt(c, .Identifier, "arg_{}", .{c.getMangle()}); |
| | 1931 | |
| | 1932 | _ = try appendToken(c, .Colon, ":"); |
| | 1933 | |
| | 1934 | const param_node = try c.a().create(ast.Node.ParamDecl); |
| | 1935 | param_node.* = .{ |
| | 1936 | .doc_comments = null, |
| | 1937 | .comptime_token = null, |
| | 1938 | .noalias_token = param.noalias_token, |
| | 1939 | .name_token = param_name_tok, |
| | 1940 | .type_node = param.type_node, |
| | 1941 | .var_args_token = null, |
| | 1942 | }; |
| | 1943 | try fn_params.push(&param_node.base); |
| | 1944 | } |
| | 1945 | |
| | 1946 | _ = try appendToken(c, .RParen, ")"); |
| | 1947 | |
| | 1948 | const fn_proto = try c.a().create(ast.Node.FnProto); |
| | 1949 | fn_proto.* = .{ |
| | 1950 | .doc_comments = null, |
| | 1951 | .visib_token = pub_tok, |
| | 1952 | .fn_token = fn_tok, |
| | 1953 | .name_token = name_tok, |
| | 1954 | .params = fn_params, |
| | 1955 | .return_type = proto_alias.return_type, |
| | 1956 | .var_args_token = null, |
| | 1957 | .extern_export_inline_token = inline_tok, |
| | 1958 | .cc_token = null, |
| | 1959 | .body_node = null, |
| | 1960 | .lib_name = null, |
| | 1961 | .align_expr = null, |
| | 1962 | .section_expr = null, |
| 1948 | }; | 1963 | }; |
| 1949 | return &call_node.base; | 1964 | |
| | 1965 | const block = try transCreateNodeBlock(c, null); |
| | 1966 | |
| | 1967 | const return_expr = try transCreateNodeReturnExpr(c); |
| | 1968 | const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.init_node.?); |
| | 1969 | const call_expr = try transCreateNodeFnCall(c, unwrap_expr); |
| | 1970 | it = fn_params.iterator(0); |
| | 1971 | while (it.next()) |pn| { |
| | 1972 | if (it.index != 0) { |
| | 1973 | _ = try appendToken(c, .Comma, ","); |
| | 1974 | } |
| | 1975 | const param = pn.*.cast(ast.Node.ParamDecl).?; |
| | 1976 | try call_expr.op.Call.params.push(try transCreateNodeIdentifier(c, tokenSlice(c, param.name_token.?))); |
| | 1977 | } |
| | 1978 | call_expr.rtoken = try appendToken(c, .RParen, ")"); |
| | 1979 | return_expr.rhs = &call_expr.base; |
| | 1980 | _ = try appendToken(c, .Semicolon, ";"); |
| | 1981 | |
| | 1982 | block.rbrace = try appendToken(c, .RBrace, "}"); |
| | 1983 | try block.statements.push(&return_expr.base); |
| | 1984 | fn_proto.body_node = &block.base; |
| | 1985 | return &fn_proto.base; |
| | 1986 | } |
| | 1987 | |
| | 1988 | fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node { |
| | 1989 | _ = try appendToken(c, .Period, "."); |
| | 1990 | const qm = try appendToken(c, .QuestionMark, "?"); |
| | 1991 | const node = try c.a().create(ast.Node.SuffixOp); |
| | 1992 | node.* = .{ |
| | 1993 | .op = .UnwrapOptional, |
| | 1994 | .lhs = .{ .node = wrapped }, |
| | 1995 | .rtoken = qm, |
| | 1996 | }; |
| | 1997 | return &node.base; |
| | 1998 | } |
| | 1999 | |
| | 2000 | fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node { |
| | 2001 | const node = try c.a().create(ast.Node.EnumLiteral); |
| | 2002 | node.* = .{ |
| | 2003 | .dot = try appendToken(c, .Period, "."), |
| | 2004 | .name = try appendIdentifier(c, name), |
| | 2005 | }; |
| | 2006 | return &node.base; |
| | 2007 | } |
| | 2008 | |
| | 2009 | fn transCreateNodeIf(c: *Context) !*ast.Node.If { |
| | 2010 | const if_tok = try appendToken(c, .Keyword_if, "if"); |
| | 2011 | _ = try appendToken(c, .LParen, "("); |
| | 2012 | const node = try c.a().create(ast.Node.If); |
| | 2013 | node.* = .{ |
| | 2014 | .if_token = if_tok, |
| | 2015 | .condition = undefined, |
| | 2016 | .payload = null, |
| | 2017 | .body = undefined, |
| | 2018 | .@"else" = null, |
| | 2019 | }; |
| | 2020 | return node; |
| | 2021 | } |
| | 2022 | |
| | 2023 | fn transCreateNodeElse(c: *Context) !*ast.Node.Else { |
| | 2024 | const node = try c.a().create(ast.Node.Else); |
| | 2025 | node.* = .{ |
| | 2026 | .else_token = try appendToken(c, .Keyword_else, "else"), |
| | 2027 | .payload = null, |
| | 2028 | .body = undefined, |
| | 2029 | }; |
| | 2030 | return node; |
| | 2031 | } |
| | 2032 | |
| | 2033 | fn transCreateNodeBlock(c: *Context, label: ?[]const u8) !*ast.Node.Block { |
| | 2034 | const label_node = if (label) |l| blk: { |
| | 2035 | const ll = try appendIdentifier(c, l); |
| | 2036 | _ = try appendToken(c, .Colon, ":"); |
| | 2037 | break :blk ll; |
| | 2038 | } else null; |
| | 2039 | const block_node = try c.a().create(ast.Node.Block); |
| | 2040 | block_node.* = .{ |
| | 2041 | .label = label_node, |
| | 2042 | .lbrace = try appendToken(c, .LBrace, "{"), |
| | 2043 | .statements = ast.Node.Block.StatementList.init(c.a()), |
| | 2044 | .rbrace = undefined, |
| | 2045 | }; |
| | 2046 | return block_node; |
| 1950 | } | 2047 | } |
| 1951 | | 2048 | |
| 1952 | const RestorePoint = struct { | 2049 | const RestorePoint = struct { |
| ... | @@ -1972,28 +2069,28 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1972,28 +2069,28 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1972 | switch (ZigClangType_getTypeClass(ty)) { | 2069 | switch (ZigClangType_getTypeClass(ty)) { |
| 1973 | .Builtin => { | 2070 | .Builtin => { |
| 1974 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); | 2071 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 1975 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | 2072 | return transCreateNodeIdentifier(rp.c, switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 1976 | .Void => return transCreateNodeIdentifier(rp.c, "c_void"), | 2073 | .Void => "c_void", |
| 1977 | .Bool => return transCreateNodeIdentifier(rp.c, "bool"), | 2074 | .Bool => "bool", |
| 1978 | .Char_U, .UChar, .Char_S, .Char8 => return transCreateNodeIdentifier(rp.c, "u8"), | 2075 | .Char_U, .UChar, .Char_S, .Char8 => "u8", |
| 1979 | .SChar => return transCreateNodeIdentifier(rp.c, "i8"), | 2076 | .SChar => "i8", |
| 1980 | .UShort => return transCreateNodeIdentifier(rp.c, "c_ushort"), | 2077 | .UShort => "c_ushort", |
| 1981 | .UInt => return transCreateNodeIdentifier(rp.c, "c_uint"), | 2078 | .UInt => "c_uint", |
| 1982 | .ULong => return transCreateNodeIdentifier(rp.c, "c_ulong"), | 2079 | .ULong => "c_ulong", |
| 1983 | .ULongLong => return transCreateNodeIdentifier(rp.c, "c_ulonglong"), | 2080 | .ULongLong => "c_ulonglong", |
| 1984 | .Short => return transCreateNodeIdentifier(rp.c, "c_short"), | 2081 | .Short => "c_short", |
| 1985 | .Int => return transCreateNodeIdentifier(rp.c, "c_int"), | 2082 | .Int => "c_int", |
| 1986 | .Long => return transCreateNodeIdentifier(rp.c, "c_long"), | 2083 | .Long => "c_long", |
| 1987 | .LongLong => return transCreateNodeIdentifier(rp.c, "c_longlong"), | 2084 | .LongLong => "c_longlong", |
| 1988 | .UInt128 => return transCreateNodeIdentifier(rp.c, "u128"), | 2085 | .UInt128 => "u128", |
| 1989 | .Int128 => return transCreateNodeIdentifier(rp.c, "i128"), | 2086 | .Int128 => "i128", |
| 1990 | .Float => return transCreateNodeIdentifier(rp.c, "f32"), | 2087 | .Float => "f32", |
| 1991 | .Double => return transCreateNodeIdentifier(rp.c, "f64"), | 2088 | .Double => "f64", |
| 1992 | .Float128 => return transCreateNodeIdentifier(rp.c, "f128"), | 2089 | .Float128 => "f128", |
| 1993 | .Float16 => return transCreateNodeIdentifier(rp.c, "f16"), | 2090 | .Float16 => "f16", |
| 1994 | .LongDouble => return transCreateNodeIdentifier(rp.c, "c_longdouble"), | 2091 | .LongDouble => "c_longdouble", |
| 1995 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}), | 2092 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}), |
| 1996 | } | 2093 | }); |
| 1997 | }, | 2094 | }, |
| 1998 | .FunctionProto => { | 2095 | .FunctionProto => { |
| 1999 | const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty); | 2096 | const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty); |
| ... | @@ -2076,6 +2173,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -2076,6 +2173,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 2076 | .Record => { | 2173 | .Record => { |
| 2077 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); | 2174 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); |
| 2078 | | 2175 | |
| | 2176 | // TODO this sould get the name from decl_table |
| | 2177 | // struct Foo { |
| | 2178 | // struct Bar{ |
| | 2179 | // int b; |
| | 2180 | // }; |
| | 2181 | // struct Bar c; |
| | 2182 | // }; |
| 2079 | const record_decl = ZigClangRecordType_getDecl(record_ty); | 2183 | const record_decl = ZigClangRecordType_getDecl(record_ty); |
| 2080 | if (try getContainerName(rp, record_decl)) |name| | 2184 | if (try getContainerName(rp, record_decl)) |name| |
| 2081 | return transCreateNodeIdentifier(rp.c, name) | 2185 | return transCreateNodeIdentifier(rp.c, name) |
| ... | @@ -2203,6 +2307,9 @@ fn finishTransFnProto( | ... | @@ -2203,6 +2307,9 @@ fn finishTransFnProto( |
| 2203 | // TODO check for always_inline attribute | 2307 | // TODO check for always_inline attribute |
| 2204 | // TODO check for align attribute | 2308 | // TODO check for align attribute |
| 2205 | | 2309 | |
| | 2310 | var fndef_scope = Scope.FnDef.init(rp.c); |
| | 2311 | const scope = &fndef_scope.base; |
| | 2312 | |
| 2206 | // pub extern fn name(...) T | 2313 | // pub extern fn name(...) T |
| 2207 | const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null; | 2314 | const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null; |
| 2208 | const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null; | 2315 | const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null; |
| ... | @@ -2228,13 +2335,17 @@ fn finishTransFnProto( | ... | @@ -2228,13 +2335,17 @@ fn finishTransFnProto( |
| 2228 | const param_name_tok: ?ast.TokenIndex = blk: { | 2335 | const param_name_tok: ?ast.TokenIndex = blk: { |
| 2229 | if (fn_decl != null) { | 2336 | if (fn_decl != null) { |
| 2230 | const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i)); | 2337 | const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i)); |
| 2231 | const param_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param))); | 2338 | var param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param))); |
| 2232 | if (param_name.len > 0) { | 2339 | if (param_name.len < 1) |
| 2233 | // TODO: If len == 0, auto-generate arg1, arg2, etc? Or leave the name blank? | 2340 | param_name = "arg"[0..]; |
| 2234 | const result = try appendIdentifier(rp.c, param_name); | 2341 | const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: { |
| 2235 | _ = try appendToken(rp.c, .Colon, ":"); | 2342 | try fndef_scope.params.push(.{ .name = param_name, .alias = a }); |
| 2236 | break :blk result; | 2343 | break :blk a; |
| 2237 | } | 2344 | } else param_name; |
| | 2345 | |
| | 2346 | const result = try appendIdentifier(rp.c, checked_param_name); |
| | 2347 | _ = try appendToken(rp.c, .Colon, ":"); |
| | 2348 | break :blk result; |
| 2238 | } | 2349 | } |
| 2239 | break :blk null; | 2350 | break :blk null; |
| 2240 | }; | 2351 | }; |
| ... | @@ -2444,3 +2555,530 @@ fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node { | ... | @@ -2444,3 +2555,530 @@ fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node { |
| 2444 | pub fn freeErrors(errors: []ClangErrMsg) void { | 2555 | pub fn freeErrors(errors: []ClangErrMsg) void { |
| 2445 | ZigClangErrorMsg_delete(errors.ptr, errors.len); | 2556 | ZigClangErrorMsg_delete(errors.ptr, errors.len); |
| 2446 | } | 2557 | } |
| | 2558 | |
| | 2559 | fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| | 2560 | // TODO if we see #undef, delete it from the table |
| | 2561 | var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(unit); |
| | 2562 | const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(unit); |
| | 2563 | var tok_list = ctok.TokenList.init(c.a()); |
| | 2564 | const scope = &c.global_scope.base; |
| | 2565 | |
| | 2566 | while (it.I != it_end.I) : (it.I += 1) { |
| | 2567 | const entity = ZigClangPreprocessingRecord_iterator_deref(it); |
| | 2568 | tok_list.shrink(0); |
| | 2569 | switch (ZigClangPreprocessedEntity_getKind(entity)) { |
| | 2570 | .MacroDefinitionKind => { |
| | 2571 | const macro = @ptrCast(*ZigClangMacroDefinitionRecord, entity); |
| | 2572 | const raw_name = ZigClangMacroDefinitionRecord_getName_getNameStart(macro); |
| | 2573 | const begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro); |
| | 2574 | |
| | 2575 | const name = try c.str(raw_name); |
| | 2576 | if (scope.contains(name)) { |
| | 2577 | continue; |
| | 2578 | } |
| | 2579 | const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); |
| | 2580 | ctok.tokenizeCMacro(&tok_list, begin_c) catch |err| switch (err) { |
| | 2581 | error.OutOfMemory => |e| return e, |
| | 2582 | else => { |
| | 2583 | try failDecl(c, begin_loc, name, "unable to tokenize macro definition", .{}); |
| | 2584 | continue; |
| | 2585 | }, |
| | 2586 | }; |
| | 2587 | |
| | 2588 | var tok_it = tok_list.iterator(0); |
| | 2589 | const first_tok = tok_it.next().?; |
| | 2590 | assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, name)); |
| | 2591 | const next = tok_it.peek().?; |
| | 2592 | switch (next.id) { |
| | 2593 | .Identifier => { |
| | 2594 | // if it equals itself, ignore. for example, from stdio.h: |
| | 2595 | // #define stdin stdin |
| | 2596 | if (std.mem.eql(u8, name, next.bytes)) { |
| | 2597 | continue; |
| | 2598 | } |
| | 2599 | }, |
| | 2600 | .Eof => { |
| | 2601 | // this means it is a macro without a value |
| | 2602 | // we don't care about such things |
| | 2603 | continue; |
| | 2604 | }, |
| | 2605 | else => {}, |
| | 2606 | } |
| | 2607 | const macro_fn = if (tok_it.peek().?.id == .Fn) blk: { |
| | 2608 | _ = tok_it.next(); |
| | 2609 | break :blk true; |
| | 2610 | } else false; |
| | 2611 | |
| | 2612 | (if (macro_fn) |
| | 2613 | transMacroFnDefine(c, &tok_it, name, begin_loc) |
| | 2614 | else |
| | 2615 | transMacroDefine(c, &tok_it, name, begin_loc)) catch |err| switch (err) { |
| | 2616 | error.UnsupportedTranslation, |
| | 2617 | error.ParseError, |
| | 2618 | => try failDecl(c, begin_loc, name, "unable to translate macro", .{}), |
| | 2619 | error.OutOfMemory => |e| return e, |
| | 2620 | }; |
| | 2621 | }, |
| | 2622 | else => {}, |
| | 2623 | } |
| | 2624 | } |
| | 2625 | } |
| | 2626 | |
| | 2627 | fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| | 2628 | const rp = makeRestorePoint(c); |
| | 2629 | const scope = &c.global_scope.base; |
| | 2630 | |
| | 2631 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| | 2632 | const mut_tok = try appendToken(c, .Keyword_const, "const"); |
| | 2633 | const name_tok = try appendIdentifier(c, name); |
| | 2634 | const eq_tok = try appendToken(c, .Equal, "="); |
| | 2635 | |
| | 2636 | const init_node = try parseCExpr(rp, it, source_loc, scope); |
| | 2637 | |
| | 2638 | const node = try c.a().create(ast.Node.VarDecl); |
| | 2639 | node.* = ast.Node.VarDecl{ |
| | 2640 | .doc_comments = null, |
| | 2641 | .visib_token = visib_tok, |
| | 2642 | .thread_local_token = null, |
| | 2643 | .name_token = name_tok, |
| | 2644 | .eq_token = eq_tok, |
| | 2645 | .mut_token = mut_tok, |
| | 2646 | .comptime_token = null, |
| | 2647 | .extern_export_token = null, |
| | 2648 | .lib_name = null, |
| | 2649 | .type_node = null, |
| | 2650 | .align_node = null, |
| | 2651 | .section_node = null, |
| | 2652 | .init_node = init_node, |
| | 2653 | .semicolon_token = try appendToken(c, .Semicolon, ";"), |
| | 2654 | }; |
| | 2655 | _ = try c.global_scope.macro_table.put(name, &node.base); |
| | 2656 | } |
| | 2657 | |
| | 2658 | fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| | 2659 | const rp = makeRestorePoint(c); |
| | 2660 | var fndef_scope = Scope.FnDef.init(c); |
| | 2661 | const scope = &fndef_scope.base; |
| | 2662 | |
| | 2663 | const pub_tok = try appendToken(c, .Keyword_pub, "pub"); |
| | 2664 | const inline_tok = try appendToken(c, .Keyword_inline, "inline"); |
| | 2665 | const fn_tok = try appendToken(c, .Keyword_fn, "fn"); |
| | 2666 | const name_tok = try appendIdentifier(c, name); |
| | 2667 | _ = try appendToken(c, .LParen, "("); |
| | 2668 | |
| | 2669 | if (it.next().?.id != .LParen) { |
| | 2670 | return error.ParseError; |
| | 2671 | } |
| | 2672 | var fn_params = ast.Node.FnProto.ParamList.init(c.a()); |
| | 2673 | while (true) { |
| | 2674 | const param_tok = it.next().?; |
| | 2675 | if (param_tok.id != .Identifier) |
| | 2676 | return error.ParseError; |
| | 2677 | |
| | 2678 | const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: { |
| | 2679 | try fndef_scope.params.push(.{ .name = param_tok.bytes, .alias = alias }); |
| | 2680 | break :blk alias; |
| | 2681 | } else param_tok.bytes; |
| | 2682 | |
| | 2683 | const param_name_tok = try appendIdentifier(c, checked_name); |
| | 2684 | _ = try appendToken(c, .Colon, ":"); |
| | 2685 | |
| | 2686 | const token_index = try appendToken(c, .Keyword_var, "var"); |
| | 2687 | const identifier = try c.a().create(ast.Node.Identifier); |
| | 2688 | identifier.* = ast.Node.Identifier{ |
| | 2689 | .base = ast.Node{ .id = ast.Node.Id.Identifier }, |
| | 2690 | .token = token_index, |
| | 2691 | }; |
| | 2692 | |
| | 2693 | const param_node = try c.a().create(ast.Node.ParamDecl); |
| | 2694 | param_node.* = .{ |
| | 2695 | .doc_comments = null, |
| | 2696 | .comptime_token = null, |
| | 2697 | .noalias_token = null, |
| | 2698 | .name_token = param_name_tok, |
| | 2699 | .type_node = &identifier.base, |
| | 2700 | .var_args_token = null, |
| | 2701 | }; |
| | 2702 | try fn_params.push(&param_node.base); |
| | 2703 | |
| | 2704 | if (it.peek().?.id != .Comma) |
| | 2705 | break; |
| | 2706 | _ = it.next(); |
| | 2707 | _ = try appendToken(c, .Comma, ","); |
| | 2708 | } |
| | 2709 | |
| | 2710 | if (it.next().?.id != .RParen) { |
| | 2711 | return error.ParseError; |
| | 2712 | } |
| | 2713 | |
| | 2714 | _ = try appendToken(c, .RParen, ")"); |
| | 2715 | |
| | 2716 | const type_of = try transCreateNodeBuiltinFnCall(c, "@TypeOf"); |
| | 2717 | type_of.rparen_token = try appendToken(c, .LParen, ")"); |
| | 2718 | |
| | 2719 | const fn_proto = try c.a().create(ast.Node.FnProto); |
| | 2720 | fn_proto.* = .{ |
| | 2721 | .visib_token = pub_tok, |
| | 2722 | .extern_export_inline_token = inline_tok, |
| | 2723 | .fn_token = fn_tok, |
| | 2724 | .name_token = name_tok, |
| | 2725 | .params = fn_params, |
| | 2726 | .return_type = .{ .Explicit = &type_of.base }, |
| | 2727 | .doc_comments = null, |
| | 2728 | .var_args_token = null, |
| | 2729 | .cc_token = null, |
| | 2730 | .body_node = null, |
| | 2731 | .lib_name = null, |
| | 2732 | .align_expr = null, |
| | 2733 | .section_expr = null, |
| | 2734 | }; |
| | 2735 | |
| | 2736 | const block = try transCreateNodeBlock(c, null); |
| | 2737 | |
| | 2738 | const return_expr = try transCreateNodeReturnExpr(c); |
| | 2739 | const expr = try parseCExpr(rp, it, source_loc, scope); |
| | 2740 | _ = try appendToken(c, .Semicolon, ";"); |
| | 2741 | try type_of.params.push(expr); |
| | 2742 | return_expr.rhs = expr; |
| | 2743 | |
| | 2744 | block.rbrace = try appendToken(c, .RBrace, "}"); |
| | 2745 | try block.statements.push(&return_expr.base); |
| | 2746 | fn_proto.body_node = &block.base; |
| | 2747 | _ = try c.global_scope.macro_table.put(name, &fn_proto.base); |
| | 2748 | } |
| | 2749 | |
| | 2750 | const ParseError = Error || error{ |
| | 2751 | ParseError, |
| | 2752 | UnsupportedTranslation, |
| | 2753 | }; |
| | 2754 | |
| | 2755 | fn parseCExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| | 2756 | return parseCPrefixOpExpr(rp, it, source_loc, scope); |
| | 2757 | } |
| | 2758 | |
| | 2759 | fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node { |
| | 2760 | if (tok.id == .NumLitInt) { |
| | 2761 | if (tok.num_lit_suffix == .None) { |
| | 2762 | if (tok.bytes.len > 2 and tok.bytes[0] == '0') { |
| | 2763 | switch (tok.bytes[1]) { |
| | 2764 | '0'...'7' => { |
| | 2765 | // octal |
| | 2766 | return transCreateNodeInt(rp.c, try std.fmt.allocPrint(rp.c.a(), "0o{}", .{tok.bytes})); |
| | 2767 | }, |
| | 2768 | else => {}, |
| | 2769 | } |
| | 2770 | } |
| | 2771 | return transCreateNodeInt(rp.c, tok.bytes); |
| | 2772 | } |
| | 2773 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| | 2774 | try cast_node.params.push(try transCreateNodeIdentifier(rp.c, switch (tok.num_lit_suffix) { |
| | 2775 | .U => "c_uint", |
| | 2776 | .L => "c_long", |
| | 2777 | .LU => "c_ulong", |
| | 2778 | .LL => "c_longlong", |
| | 2779 | .LLU => "c_ulonglong", |
| | 2780 | else => unreachable, |
| | 2781 | })); |
| | 2782 | _ = try appendToken(rp.c, .Comma, ","); |
| | 2783 | try cast_node.params.push(try transCreateNodeInt(rp.c, tok.bytes)); |
| | 2784 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| | 2785 | return &cast_node.base; |
| | 2786 | } else if (tok.id == .NumLitFloat) { |
| | 2787 | if (tok.num_lit_suffix == .None) { |
| | 2788 | return transCreateNodeFloat(rp.c, tok.bytes); |
| | 2789 | } |
| | 2790 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| | 2791 | try cast_node.params.push(try transCreateNodeIdentifier(rp.c, switch (tok.num_lit_suffix) { |
| | 2792 | .F => "f32", |
| | 2793 | .L => "f64", |
| | 2794 | else => unreachable, |
| | 2795 | })); |
| | 2796 | _ = try appendToken(rp.c, .Comma, ","); |
| | 2797 | try cast_node.params.push(try transCreateNodeFloat(rp.c, tok.bytes)); |
| | 2798 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| | 2799 | return &cast_node.base; |
| | 2800 | } else |
| | 2801 | return revertAndWarn( |
| | 2802 | rp, |
| | 2803 | error.ParseError, |
| | 2804 | source_loc, |
| | 2805 | "expected number literal", |
| | 2806 | .{}, |
| | 2807 | ); |
| | 2808 | } |
| | 2809 | |
| | 2810 | fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| | 2811 | const tok = it.next().?; |
| | 2812 | switch (tok.id) { |
| | 2813 | .CharLit => { |
| | 2814 | const token = try appendToken(rp.c, .CharLiteral, tok.bytes); |
| | 2815 | const node = try rp.c.a().create(ast.Node.CharLiteral); |
| | 2816 | node.* = ast.Node.CharLiteral{ |
| | 2817 | .token = token, |
| | 2818 | }; |
| | 2819 | return &node.base; |
| | 2820 | }, |
| | 2821 | .StrLit => { |
| | 2822 | const token = try appendToken(rp.c, .StringLiteral, tok.bytes); |
| | 2823 | const node = try rp.c.a().create(ast.Node.StringLiteral); |
| | 2824 | node.* = ast.Node.StringLiteral{ |
| | 2825 | .token = token, |
| | 2826 | }; |
| | 2827 | return &node.base; |
| | 2828 | }, |
| | 2829 | .NumLitInt, .NumLitFloat => { |
| | 2830 | return parseCNumLit(rp, tok, source_loc); |
| | 2831 | }, |
| | 2832 | .Identifier => { |
| | 2833 | const name = if (scope.getAlias(tok.bytes)) |a| a else tok.bytes; |
| | 2834 | return transCreateNodeIdentifier(rp.c, name); |
| | 2835 | }, |
| | 2836 | .LParen => { |
| | 2837 | const inner_node = try parseCExpr(rp, it, source_loc, scope); |
| | 2838 | |
| | 2839 | if (it.peek().?.id == .RParen) { |
| | 2840 | _ = it.next(); |
| | 2841 | return inner_node; |
| | 2842 | } |
| | 2843 | |
| | 2844 | // hack to get zig fmt to render a comma in builtin calls |
| | 2845 | _ = try appendToken(rp.c, .Comma, ","); |
| | 2846 | |
| | 2847 | const node_to_cast = try parseCExpr(rp, it, source_loc, scope); |
| | 2848 | |
| | 2849 | if (it.next().?.id != .RParen) { |
| | 2850 | return revertAndWarn( |
| | 2851 | rp, |
| | 2852 | error.ParseError, |
| | 2853 | source_loc, |
| | 2854 | "unable to translate C expr", |
| | 2855 | .{}, |
| | 2856 | ); |
| | 2857 | } |
| | 2858 | |
| | 2859 | //if (@typeId(@TypeOf(x)) == .Pointer) |
| | 2860 | // @ptrCast(dest, x) |
| | 2861 | //else if (@typeId(@TypeOf(x)) == .Integer) |
| | 2862 | // @intToPtr(dest, x) |
| | 2863 | //else |
| | 2864 | // @as(dest, x) |
| | 2865 | |
| | 2866 | const if_1 = try transCreateNodeIf(rp.c); |
| | 2867 | const type_id_1 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId"); |
| | 2868 | const type_of_1 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf"); |
| | 2869 | try type_id_1.params.push(&type_of_1.base); |
| | 2870 | try type_of_1.params.push(node_to_cast); |
| | 2871 | type_of_1.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2872 | type_id_1.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2873 | |
| | 2874 | const cmp_1 = try rp.c.a().create(ast.Node.InfixOp); |
| | 2875 | cmp_1.* = .{ |
| | 2876 | .op_token = try appendToken(rp.c, .EqualEqual, "=="), |
| | 2877 | .lhs = &type_id_1.base, |
| | 2878 | .op = .EqualEqual, |
| | 2879 | .rhs = try transCreateNodeEnumLiteral(rp.c, "Pointer"), |
| | 2880 | }; |
| | 2881 | if_1.condition = &cmp_1.base; |
| | 2882 | _ = try appendToken(rp.c, .LParen, ")"); |
| | 2883 | |
| | 2884 | const ptr_cast = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast"); |
| | 2885 | try ptr_cast.params.push(inner_node); |
| | 2886 | try ptr_cast.params.push(node_to_cast); |
| | 2887 | ptr_cast.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2888 | if_1.body = &ptr_cast.base; |
| | 2889 | |
| | 2890 | const else_1 = try transCreateNodeElse(rp.c); |
| | 2891 | if_1.@"else" = else_1; |
| | 2892 | |
| | 2893 | const if_2 = try transCreateNodeIf(rp.c); |
| | 2894 | const type_id_2 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId"); |
| | 2895 | const type_of_2 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf"); |
| | 2896 | try type_id_2.params.push(&type_of_2.base); |
| | 2897 | try type_of_2.params.push(node_to_cast); |
| | 2898 | type_of_2.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2899 | type_id_2.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2900 | |
| | 2901 | const cmp_2 = try rp.c.a().create(ast.Node.InfixOp); |
| | 2902 | cmp_2.* = .{ |
| | 2903 | .op_token = try appendToken(rp.c, .EqualEqual, "=="), |
| | 2904 | .lhs = &type_id_2.base, |
| | 2905 | .op = .EqualEqual, |
| | 2906 | .rhs = try transCreateNodeEnumLiteral(rp.c, "Int"), |
| | 2907 | }; |
| | 2908 | if_2.condition = &cmp_2.base; |
| | 2909 | else_1.body = &if_2.base; |
| | 2910 | _ = try appendToken(rp.c, .LParen, ")"); |
| | 2911 | |
| | 2912 | const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr"); |
| | 2913 | try int_to_ptr.params.push(inner_node); |
| | 2914 | try int_to_ptr.params.push(node_to_cast); |
| | 2915 | int_to_ptr.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2916 | if_2.body = &int_to_ptr.base; |
| | 2917 | |
| | 2918 | const else_2 = try transCreateNodeElse(rp.c); |
| | 2919 | if_2.@"else" = else_2; |
| | 2920 | |
| | 2921 | const as = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| | 2922 | try as.params.push(inner_node); |
| | 2923 | try as.params.push(node_to_cast); |
| | 2924 | as.rparen_token = try appendToken(rp.c, .LParen, ")"); |
| | 2925 | else_2.body = &as.base; |
| | 2926 | |
| | 2927 | return &if_1.base; |
| | 2928 | }, |
| | 2929 | else => return revertAndWarn( |
| | 2930 | rp, |
| | 2931 | error.UnsupportedTranslation, |
| | 2932 | source_loc, |
| | 2933 | "unable to translate C expr", |
| | 2934 | .{}, |
| | 2935 | ), |
| | 2936 | } |
| | 2937 | } |
| | 2938 | |
| | 2939 | fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| | 2940 | var node = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| | 2941 | while (true) { |
| | 2942 | const tok = it.next().?; |
| | 2943 | switch (tok.id) { |
| | 2944 | .Dot => { |
| | 2945 | const name_tok = it.next().?; |
| | 2946 | if (name_tok.id != .Identifier) |
| | 2947 | return revertAndWarn( |
| | 2948 | rp, |
| | 2949 | error.ParseError, |
| | 2950 | source_loc, |
| | 2951 | "unable to translate C expr", |
| | 2952 | .{}, |
| | 2953 | ); |
| | 2954 | |
| | 2955 | const op_token = try appendToken(rp.c, .Period, "."); |
| | 2956 | const rhs = try transCreateNodeIdentifier(rp.c, name_tok.bytes); |
| | 2957 | const access_node = try rp.c.a().create(ast.Node.InfixOp); |
| | 2958 | access_node.* = .{ |
| | 2959 | .op_token = op_token, |
| | 2960 | .lhs = node, |
| | 2961 | .op = .Period, |
| | 2962 | .rhs = rhs, |
| | 2963 | }; |
| | 2964 | node = &access_node.base; |
| | 2965 | }, |
| | 2966 | .Asterisk => { |
| | 2967 | if (it.peek().?.id == .RParen) { |
| | 2968 | // type *) |
| | 2969 | |
| | 2970 | // hack to get zig fmt to render a comma in builtin calls |
| | 2971 | _ = try appendToken(rp.c, .Comma, ","); |
| | 2972 | |
| | 2973 | const ptr = try transCreateNodePtrType(rp.c, false, false, .Identifier); |
| | 2974 | ptr.rhs = node; |
| | 2975 | return &ptr.base; |
| | 2976 | } else { |
| | 2977 | // expr * expr |
| | 2978 | const op_token = try appendToken(rp.c, .Asterisk, "*"); |
| | 2979 | const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| | 2980 | const bitshift_node = try rp.c.a().create(ast.Node.InfixOp); |
| | 2981 | bitshift_node.* = .{ |
| | 2982 | .op_token = op_token, |
| | 2983 | .lhs = node, |
| | 2984 | .op = .BitShiftLeft, |
| | 2985 | .rhs = rhs, |
| | 2986 | }; |
| | 2987 | node = &bitshift_node.base; |
| | 2988 | } |
| | 2989 | }, |
| | 2990 | .Shl => { |
| | 2991 | const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<"); |
| | 2992 | const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope); |
| | 2993 | const bitshift_node = try rp.c.a().create(ast.Node.InfixOp); |
| | 2994 | bitshift_node.* = .{ |
| | 2995 | .op_token = op_token, |
| | 2996 | .lhs = node, |
| | 2997 | .op = .BitShiftLeft, |
| | 2998 | .rhs = rhs, |
| | 2999 | }; |
| | 3000 | node = &bitshift_node.base; |
| | 3001 | }, |
| | 3002 | else => { |
| | 3003 | _ = it.prev(); |
| | 3004 | return node; |
| | 3005 | }, |
| | 3006 | } |
| | 3007 | } |
| | 3008 | } |
| | 3009 | |
| | 3010 | fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { |
| | 3011 | const op_tok = it.next().?; |
| | 3012 | |
| | 3013 | switch (op_tok.id) { |
| | 3014 | .Bang => { |
| | 3015 | const node = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); |
| | 3016 | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| | 3017 | return &node.base; |
| | 3018 | }, |
| | 3019 | .Minus => { |
| | 3020 | const node = try transCreateNodePrefixOp(rp.c, .Negation, .Minus, "-"); |
| | 3021 | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| | 3022 | return &node.base; |
| | 3023 | }, |
| | 3024 | .Tilde => { |
| | 3025 | const node = try transCreateNodePrefixOp(rp.c, .BitNot, .Tilde, "~"); |
| | 3026 | node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| | 3027 | return &node.base; |
| | 3028 | }, |
| | 3029 | .Asterisk => { |
| | 3030 | const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc, scope); |
| | 3031 | const node = try rp.c.a().create(ast.Node.SuffixOp); |
| | 3032 | node.* = .{ |
| | 3033 | .lhs = .{ .node = prefix_op_expr }, |
| | 3034 | .op = .Deref, |
| | 3035 | .rtoken = try appendToken(rp.c, .PeriodAsterisk, ".*"), |
| | 3036 | }; |
| | 3037 | return &node.base; |
| | 3038 | }, |
| | 3039 | else => { |
| | 3040 | _ = it.prev(); |
| | 3041 | return try parseCSuffixOpExpr(rp, it, source_loc, scope); |
| | 3042 | }, |
| | 3043 | } |
| | 3044 | } |
| | 3045 | |
| | 3046 | fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 { |
| | 3047 | const tok = c.tree.tokens.at(token); |
| | 3048 | return c.source_buffer.toSliceConst()[tok.start..tok.end]; |
| | 3049 | } |
| | 3050 | |
| | 3051 | fn getFnDecl(c: *Context, ref: *ast.Node) ?*ast.Node { |
| | 3052 | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.init_node.? else return null; |
| | 3053 | const name = if (init.cast(ast.Node.Identifier)) |id| |
| | 3054 | tokenSlice(c, id.token) |
| | 3055 | else |
| | 3056 | return null; |
| | 3057 | // TODO a.b.c |
| | 3058 | if (c.global_scope.sym_table.get(name)) |kv| { |
| | 3059 | if (kv.value.cast(ast.Node.VarDecl)) |val| { |
| | 3060 | if (val.type_node) |type_node| { |
| | 3061 | if (type_node.cast(ast.Node.PrefixOp)) |casted| { |
| | 3062 | if (casted.rhs.id == .FnProto) { |
| | 3063 | return casted.rhs; |
| | 3064 | } |
| | 3065 | } |
| | 3066 | } |
| | 3067 | } |
| | 3068 | } |
| | 3069 | return null; |
| | 3070 | } |
| | 3071 | |
| | 3072 | fn addMacros(c: *Context) !void { |
| | 3073 | var macro_it = c.global_scope.macro_table.iterator(); |
| | 3074 | while (macro_it.next()) |kv| { |
| | 3075 | if (getFnDecl(c, kv.value)) |proto_node| { |
| | 3076 | // If a macro aliases a global variable which is a function pointer, we conclude that |
| | 3077 | // the macro is intended to represent a function that assumes the function pointer |
| | 3078 | // variable is non-null and calls it. |
| | 3079 | try addTopLevelDecl(c, kv.key, try transCreateNodeMacroFn(c, kv.key, kv.value, proto_node)); |
| | 3080 | } else { |
| | 3081 | try addTopLevelDecl(c, kv.key, kv.value); |
| | 3082 | } |
| | 3083 | } |
| | 3084 | } |