| ... | @@ -577,7 +577,13 @@ const DocData = struct { | ... | @@ -577,7 +577,13 @@ const DocData = struct { |
| 577 | is_extern: bool = false, | 577 | is_extern: bool = false, |
| 578 | }, | 578 | }, |
| 579 | BoundFn: struct { name: []const u8 }, | 579 | BoundFn: struct { name: []const u8 }, |
| 580 | Opaque: struct { name: []const u8 }, | 580 | Opaque: struct { |
| | 581 | name: []const u8, |
| | 582 | src: usize, // index into astNodes |
| | 583 | privDecls: []usize = &.{}, // index into decls |
| | 584 | pubDecls: []usize = &.{}, // index into decls |
| | 585 | ast: usize, |
| | 586 | }, |
| 581 | Frame: struct { name: []const u8 }, | 587 | Frame: struct { name: []const u8 }, |
| 582 | AnyFrame: struct { name: []const u8 }, | 588 | AnyFrame: struct { name: []const u8 }, |
| 583 | Vector: struct { name: []const u8 }, | 589 | Vector: struct { name: []const u8 }, |
| ... | @@ -2433,6 +2439,14 @@ fn walkInstruction( | ... | @@ -2433,6 +2439,14 @@ fn walkInstruction( |
| 2433 | return result; | 2439 | return result; |
| 2434 | }, | 2440 | }, |
| 2435 | .opaque_decl => { | 2441 | .opaque_decl => { |
| | 2442 | const type_slot_index = self.types.items.len; |
| | 2443 | try self.types.append(self.arena, .{ .Unanalyzed = .{} }); |
| | 2444 | |
| | 2445 | var scope: Scope = .{ |
| | 2446 | .parent = parent_scope, |
| | 2447 | .enclosing_type = type_slot_index, |
| | 2448 | }; |
| | 2449 | |
| 2436 | const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small); | 2450 | const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small); |
| 2437 | var extra_index: usize = extended.operand; | 2451 | var extra_index: usize = extended.operand; |
| 2438 | | 2452 | |
| ... | @@ -2453,22 +2467,63 @@ fn walkInstruction( | ... | @@ -2453,22 +2467,63 @@ fn walkInstruction( |
| 2453 | extra_index += 1; | 2467 | extra_index += 1; |
| 2454 | break :blk decls_len; | 2468 | break :blk decls_len; |
| 2455 | } else 0; | 2469 | } else 0; |
| 2456 | _ = decls_len; | 2470 | |
| 2457 | | 2471 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 2458 | const decls_bits = file.zir.extra[extra_index]; | 2472 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 2459 | _ = decls_bits; | 2473 | |
| 2460 | | 2474 | const decls_first_index = self.decls.items.len; |
| 2461 | // const sep = "=" ** 200; | 2475 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| 2462 | // log.debug("{s}", .{sep}); | 2476 | // Done to make sure that all decl refs can be resolved correctly, |
| 2463 | // log.debug("small = {any}", .{small}); | 2477 | // even if we haven't fully analyzed the decl yet. |
| 2464 | // log.debug("src_node = {}", .{src_node}); | 2478 | { |
| 2465 | // log.debug("decls_len = {}", .{decls_len}); | 2479 | var it = file.zir.declIterator(@intCast(u32, inst_index)); |
| 2466 | // log.debug("decls_bit = {}", .{decls_bits}); | 2480 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| 2467 | // log.debug("{s}", .{sep}); | 2481 | for (self.decls.items[decls_first_index..]) |*slot| { |
| 2468 | const type_slot_index = self.types.items.len - 1; | 2482 | slot._analyzed = false; |
| 2469 | try self.types.append(self.arena, .{ .Opaque = .{ .name = "TODO" } }); | 2483 | } |
| | 2484 | var decls_slot_index = decls_first_index; |
| | 2485 | while (it.next()) |d| : (decls_slot_index += 1) { |
| | 2486 | const decl_name_index = file.zir.extra[d.sub_index + 5]; |
| | 2487 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); |
| | 2488 | } |
| | 2489 | } |
| | 2490 | |
| | 2491 | extra_index = try self.walkDecls( |
| | 2492 | file, |
| | 2493 | &scope, |
| | 2494 | src_info, |
| | 2495 | decls_first_index, |
| | 2496 | decls_len, |
| | 2497 | &decl_indexes, |
| | 2498 | &priv_decl_indexes, |
| | 2499 | extra_index, |
| | 2500 | ); |
| | 2501 | |
| | 2502 | self.types.items[type_slot_index] = .{ |
| | 2503 | .Opaque = .{ |
| | 2504 | .name = "todo_name", |
| | 2505 | .src = self_ast_node_index, |
| | 2506 | .privDecls = priv_decl_indexes.items, |
| | 2507 | .pubDecls = decl_indexes.items, |
| | 2508 | .ast = self_ast_node_index, |
| | 2509 | }, |
| | 2510 | }; |
| | 2511 | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| | 2512 | for (paths.items) |resume_info| { |
| | 2513 | try self.tryResolveRefPath( |
| | 2514 | resume_info.file, |
| | 2515 | inst_index, |
| | 2516 | resume_info.ref_path, |
| | 2517 | ); |
| | 2518 | } |
| | 2519 | |
| | 2520 | _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| | 2521 | // TODO: we should deallocate the arraylist that holds all the |
| | 2522 | // decl paths. not doing it now since it's arena-allocated |
| | 2523 | // anyway, but maybe we should put it elsewhere. |
| | 2524 | } |
| 2470 | return DocData.WalkResult{ | 2525 | return DocData.WalkResult{ |
| 2471 | .typeRef = .{ .type = @enumToInt(Ref.anyopaque_type) }, | 2526 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 2472 | .expr = .{ .type = type_slot_index }, | 2527 | .expr = .{ .type = type_slot_index }, |
| 2473 | }; | 2528 | }; |
| 2474 | }, | 2529 | }, |
| ... | @@ -3428,6 +3483,37 @@ fn tryResolveRefPath( | ... | @@ -3428,6 +3483,37 @@ fn tryResolveRefPath( |
| 3428 | path[i + 1] = (try self.cteTodo(child_string)).expr; | 3483 | path[i + 1] = (try self.cteTodo(child_string)).expr; |
| 3429 | continue :outer; | 3484 | continue :outer; |
| 3430 | }, | 3485 | }, |
| | 3486 | .Opaque => |t_opaque| { |
| | 3487 | for (t_opaque.pubDecls) |d| { |
| | 3488 | // TODO: this could be improved a lot |
| | 3489 | // by having our own string table! |
| | 3490 | const decl = self.decls.items[d]; |
| | 3491 | if (std.mem.eql(u8, decl.name, child_string)) { |
| | 3492 | path[i + 1] = .{ .declRef = d }; |
| | 3493 | continue :outer; |
| | 3494 | } |
| | 3495 | } |
| | 3496 | for (t_opaque.privDecls) |d| { |
| | 3497 | // TODO: this could be improved a lot |
| | 3498 | // by having our own string table! |
| | 3499 | const decl = self.decls.items[d]; |
| | 3500 | if (std.mem.eql(u8, decl.name, child_string)) { |
| | 3501 | path[i + 1] = .{ .declRef = d }; |
| | 3502 | continue :outer; |
| | 3503 | } |
| | 3504 | } |
| | 3505 | |
| | 3506 | // if we got here, our search failed |
| | 3507 | printWithContext( |
| | 3508 | file, |
| | 3509 | inst_index, |
| | 3510 | "failed to match `{s}` in opaque", |
| | 3511 | .{child_string}, |
| | 3512 | ); |
| | 3513 | |
| | 3514 | path[i + 1] = (try self.cteTodo("match failure")).expr; |
| | 3515 | continue :outer; |
| | 3516 | }, |
| 3431 | }, | 3517 | }, |
| 3432 | } | 3518 | } |
| 3433 | } | 3519 | } |