| ... | ... | @@ -577,7 +577,13 @@ const DocData = struct { |
| 577 | 577 | is_extern: bool = false, |
| 578 | 578 | }, |
| 579 | 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 | 587 | Frame: struct { name: []const u8 }, |
| 582 | 588 | AnyFrame: struct { name: []const u8 }, |
| 583 | 589 | Vector: struct { name: []const u8 }, |
| ... | ... | @@ -2433,6 +2439,14 @@ fn walkInstruction( |
| 2433 | 2439 | return result; |
| 2434 | 2440 | }, |
| 2435 | 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 | 2450 | const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small); |
| 2437 | 2451 | var extra_index: usize = extended.operand; |
| 2438 | 2452 | |
| ... | ... | @@ -2453,22 +2467,63 @@ fn walkInstruction( |
| 2453 | 2467 | extra_index += 1; |
| 2454 | 2468 | break :blk decls_len; |
| 2455 | 2469 | } else 0; |
| 2456 | | _ = decls_len; |
| 2457 | | |
| 2458 | | const decls_bits = file.zir.extra[extra_index]; |
| 2459 | | _ = decls_bits; |
| 2460 | | |
| 2461 | | // const sep = "=" ** 200; |
| 2462 | | // log.debug("{s}", .{sep}); |
| 2463 | | // log.debug("small = {any}", .{small}); |
| 2464 | | // log.debug("src_node = {}", .{src_node}); |
| 2465 | | // log.debug("decls_len = {}", .{decls_len}); |
| 2466 | | // log.debug("decls_bit = {}", .{decls_bits}); |
| 2467 | | // log.debug("{s}", .{sep}); |
| 2468 | | const type_slot_index = self.types.items.len - 1; |
| 2469 | | try self.types.append(self.arena, .{ .Opaque = .{ .name = "TODO" } }); |
| 2470 | |
| 2471 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 2472 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 2473 | |
| 2474 | const decls_first_index = self.decls.items.len; |
| 2475 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| 2476 | // Done to make sure that all decl refs can be resolved correctly, |
| 2477 | // even if we haven't fully analyzed the decl yet. |
| 2478 | { |
| 2479 | var it = file.zir.declIterator(@intCast(u32, inst_index)); |
| 2480 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| 2481 | for (self.decls.items[decls_first_index..]) |*slot| { |
| 2482 | slot._analyzed = false; |
| 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 | 2525 | return DocData.WalkResult{ |
| 2471 | | .typeRef = .{ .type = @enumToInt(Ref.anyopaque_type) }, |
| 2526 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 2472 | 2527 | .expr = .{ .type = type_slot_index }, |
| 2473 | 2528 | }; |
| 2474 | 2529 | }, |
| ... | ... | @@ -3428,6 +3483,37 @@ fn tryResolveRefPath( |
| 3428 | 3483 | path[i + 1] = (try self.cteTodo(child_string)).expr; |
| 3429 | 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 | } |