Skip to content

Commit d3e985d

Browse files
committed
refine hir and block APIs
1 parent 41946ae commit d3e985d

19 files changed

Lines changed: 135 additions & 138 deletions

File tree

crates/llmcc-collect/src/collect.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ pub fn collect_nodes(project: &ProjectGraph) -> Vec<RenderNode> {
5050
let symbol_opt = block
5151
.node()
5252
.as_scope()
53-
.and_then(|scope_node| scope_node.opt_scope())
54-
.and_then(|scope| scope.opt_symbol());
53+
.and_then(|scope_node| scope_node.try_scope())
54+
.and_then(|scope| scope.try_symbol());
5555

5656
let sym_kind = symbol_opt.map(|s| s.kind());
5757

crates/llmcc-core/src/block.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use parking_lot::RwLock;
44
use std::collections::HashSet;
55
use std::fmt;
6-
use std::sync::atomic::{AtomicBool, Ordering};
76
use strum_macros::{Display, EnumIter, EnumString, FromRepr};
87

98
use crate::context::CompileUnit;
@@ -592,13 +591,8 @@ pub struct BlockFunc<'blk> {
592591
name: String,
593592
pub parameters: RwLock<Vec<BlockId>>,
594593
pub returns: RwLock<Option<BlockId>>,
595-
/// Types used inside function body (excludes parameter/return types)
596-
/// Examples: local variable types, static method receivers (Foo::method)
597-
pub type_deps: RwLock<HashSet<BlockId>>,
598594
/// Functions/methods called by this function
599595
pub func_deps: RwLock<HashSet<BlockId>>,
600-
/// Whether this is a method (inside impl block) vs a free function
601-
pub is_method: AtomicBool,
602596
}
603597

604598
impl<'blk> BlockFunc<'blk> {
@@ -627,22 +621,16 @@ impl<'blk> BlockFunc<'blk> {
627621
name,
628622
parameters: RwLock::new(Vec::new()),
629623
returns: RwLock::new(None),
630-
type_deps: RwLock::new(HashSet::new()),
631624
func_deps: RwLock::new(HashSet::new()),
632-
is_method: AtomicBool::new(false),
633625
}
634626
}
635627

636628
pub fn name(&self) -> Option<&str> {
637629
(!self.name.is_empty()).then_some(&self.name)
638630
}
639631

640-
pub fn set_is_method(&self, is_method: bool) {
641-
self.is_method.store(is_method, Ordering::Relaxed);
642-
}
643-
644632
pub fn is_method(&self) -> bool {
645-
self.is_method.load(Ordering::Relaxed)
633+
self.base.kind == BlockKind::Method
646634
}
647635

648636
pub fn add_parameter(&self, param: BlockId) {
@@ -662,11 +650,11 @@ impl<'blk> BlockFunc<'blk> {
662650
}
663651

664652
pub fn add_type_dep(&self, type_id: BlockId) {
665-
self.type_deps.write().insert(type_id);
653+
self.base.add_type_dep(type_id);
666654
}
667655

668656
pub fn type_deps(&self) -> HashSet<BlockId> {
669-
self.type_deps.read().clone()
657+
self.base.type_deps()
670658
}
671659

672660
pub fn add_func_dep(&self, func_id: BlockId) {

crates/llmcc-core/src/graph_builder.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
128128
.into_iter()
129129
.find(|ident| {
130130
ident
131-
.opt_symbol()
131+
.try_symbol()
132132
.is_some_and(|sym| matches!(sym.kind(), crate::symbol::SymKind::Variable))
133133
})
134134
.map(|ident| ident.name.to_string())
@@ -157,7 +157,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
157157
// The scope's symbol is authoritative - if a scope is set, it means
158158
// the collector intentionally created this as a defining scope
159159
if let Some(scope) = node.as_scope()
160-
&& let Some(sym) = scope.opt_symbol()
160+
&& let Some(sym) = scope.try_symbol()
161161
{
162162
return Some(sym);
163163
}
@@ -172,7 +172,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
172172
// For fields, use the language's name_field to avoid finding decorator identifiers
173173
if kind == BlockKind::Field
174174
&& let Some(ident) = node.query(&self.unit).ident_with_field(L::name_field())
175-
&& let Some(sym) = ident.opt_symbol()
175+
&& let Some(sym) = ident.try_symbol()
176176
{
177177
return Some(sym);
178178
}
@@ -181,7 +181,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
181181
// This avoids cases like `handle(@inject req: string)` where `find_ident` returns `inject`.
182182
if kind == BlockKind::Parameter {
183183
for ident in node.query(&self.unit).identifiers() {
184-
if let Some(sym) = ident.opt_symbol()
184+
if let Some(sym) = ident.try_symbol()
185185
&& matches!(sym.kind(), SymKind::Variable)
186186
{
187187
return Some(sym);
@@ -191,15 +191,15 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
191191

192192
// Try identifier (for parameters, etc.)
193193
if let Some(ident) = node.query(&self.unit).first_ident()
194-
&& let Some(sym) = ident.opt_symbol()
194+
&& let Some(sym) = ident.try_symbol()
195195
{
196196
return Some(sym);
197197
}
198198

199199
// Try children's identifiers (for self_parameter where the identifier is a child)
200200
for child in node.children(&self.unit) {
201201
if let Some(ident) = child.as_ident()
202-
&& let Some(sym) = ident.opt_symbol()
202+
&& let Some(sym) = ident.try_symbol()
203203
{
204204
return Some(sym);
205205
}
@@ -241,7 +241,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
241241
// Populate crate_name and module_path from scope chain.
242242
// The binding phase sets up proper parent scopes with Module/Crate symbols.
243243
if let Some(scope_node) = node.as_scope()
244-
&& let Some(scope) = scope_node.opt_scope()
244+
&& let Some(scope) = scope_node.try_scope()
245245
{
246246
use crate::symbol::SymKind;
247247

@@ -289,9 +289,6 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
289289
}
290290
BlockKind::Func | BlockKind::Method => {
291291
let block = BlockFunc::new_with_symbol(id, node, kind, parent, children, symbol);
292-
if kind == BlockKind::Method {
293-
block.set_is_method(true);
294-
}
295292
let block_ref = self
296293
.unit
297294
.context()
@@ -375,7 +372,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
375372

376373
// Get target type from the "type" field (e.g., `impl Foo` or `impl Trait for Foo`)
377374
if let Some(target_ident) = node.query(&self.unit).ident_with_field(L::type_field())
378-
&& let Some(sym) = target_ident.opt_symbol()
375+
&& let Some(sym) = target_ident.try_symbol()
379376
{
380377
// Follow type_of chain to get the actual type symbol for block_id
381378
let resolved = sym
@@ -388,7 +385,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
388385

389386
// Get trait from the "trait" field (e.g., `impl Trait for Foo`)
390387
if let Some(trait_ident) = node.query(&self.unit).ident_with_field(L::trait_field())
391-
&& let Some(sym) = trait_ident.opt_symbol()
388+
&& let Some(sym) = trait_ident.try_symbol()
392389
{
393390
// Follow type_of chain to get the actual trait symbol
394391
let resolved = sym
@@ -608,7 +605,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
608605
let mut type_symbol = node
609606
.query(&self.unit)
610607
.first_ident()
611-
.and_then(|ident| ident.opt_symbol());
608+
.and_then(|ident| ident.try_symbol());
612609

613610
// Strategy 2: Look at children for symbol
614611
if type_symbol.is_none() {
@@ -624,7 +621,7 @@ impl<'tcx, L: Language> GraphBuilder<'tcx, L> {
624621
&& let Some(scope) = node.as_scope()
625622
&& let Some(ident) = *scope.ident.read()
626623
{
627-
type_symbol = ident.opt_symbol();
624+
type_symbol = ident.try_symbol();
628625
}
629626
// Strategy 4: Node's own symbol
630627
if type_symbol.is_none() {
@@ -804,8 +801,8 @@ impl<'tcx, L: Language> HirVisitor<'tcx> for GraphBuilder<'tcx, L> {
804801
if matches!(kind, BlockKind::Func | BlockKind::Method) {
805802
let has_symbol = node
806803
.as_scope()
807-
.and_then(|scope| scope.opt_scope())
808-
.and_then(|scope| scope.opt_symbol())
804+
.and_then(|scope| scope.try_scope())
805+
.and_then(|scope| scope.try_symbol())
809806
.is_some();
810807
if !has_symbol {
811808
// No symbol means this is a function pointer variable, not a function declaration

crates/llmcc-core/src/ir.rs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ pub enum HirNode<'hir> {
9191
impl<'hir> HirNode<'hir> {
9292
#[inline]
9393
fn expect_base(&self, method: &'static str) -> &HirBase {
94-
self.base()
94+
self.try_base()
9595
.unwrap_or_else(|| panic!("HirNode::{method} called on Undefined"))
9696
}
9797

9898
pub fn label(&self) -> String {
99-
self.base()
99+
self.try_base()
100100
.map(|base| format!("{}:{}", base.kind, base.id))
101101
.unwrap_or_else(|| "undefined".to_string())
102102
}
@@ -107,7 +107,7 @@ impl<'hir> HirNode<'hir> {
107107
}
108108

109109
/// Shared metadata for this node, if it is not `Undefined`.
110-
pub fn base(&self) -> Option<&HirBase> {
110+
pub fn try_base(&self) -> Option<&HirBase> {
111111
match self {
112112
HirNode::Undefined => None,
113113
HirNode::Root(node) => Some(&node.base),
@@ -119,9 +119,14 @@ impl<'hir> HirNode<'hir> {
119119
}
120120
}
121121

122+
/// Shared metadata for this node, panicking if it is `Undefined`.
123+
pub fn base(&self) -> &HirBase {
124+
self.expect_base("base")
125+
}
126+
122127
/// Coarse HIR kind used by llmcc visitors and builders.
123128
pub fn kind(&self) -> HirKind {
124-
self.base().map_or(HirKind::Undefined, |base| base.kind)
129+
self.try_base().map_or(HirKind::Undefined, |base| base.kind)
125130
}
126131

127132
/// Returns true when this node has the given coarse HIR kind.
@@ -131,17 +136,17 @@ impl<'hir> HirNode<'hir> {
131136

132137
/// HIR id if this node is not `Undefined`.
133138
pub fn try_id(&self) -> Option<HirId> {
134-
self.base().map(|base| base.id)
139+
self.try_base().map(|base| base.id)
135140
}
136141

137142
/// Tree-sitter field id if this node is not `Undefined`.
138143
pub fn try_field_id(&self) -> Option<u16> {
139-
self.base().map(|base| base.field_id)
144+
self.try_base().map(|base| base.field_id)
140145
}
141146

142147
/// Tree-sitter kind id if this node is not `Undefined`.
143148
pub fn try_kind_id(&self) -> Option<u16> {
144-
self.base().map(|base| base.kind_id)
149+
self.try_base().map(|base| base.kind_id)
145150
}
146151

147152
/// Tree-sitter field id assigned by the parent cursor.
@@ -151,12 +156,12 @@ impl<'hir> HirNode<'hir> {
151156

152157
/// Child node ids in source order.
153158
pub fn child_ids(&self) -> &[HirId] {
154-
self.base().map_or(&[], |base| &base.children)
159+
self.try_base().map_or(&[], |base| &base.children)
155160
}
156161

157162
/// Child nodes in source order.
158163
pub fn children(&self, unit: &CompileUnit<'hir>) -> SmallVec<[HirNode<'hir>; 8]> {
159-
self.base().map_or(SmallVec::new(), |base| {
164+
self.try_base().map_or(SmallVec::new(), |base| {
160165
base.children.iter().map(|id| unit.hir_node(*id)).collect()
161166
})
162167
}
@@ -193,19 +198,19 @@ impl<'hir> HirNode<'hir> {
193198

194199
/// Parent node id, if this is not the root.
195200
pub fn parent(&self) -> Option<HirId> {
196-
self.base().and_then(|base| base.parent)
201+
self.try_base().and_then(|base| base.parent)
197202
}
198203

199204
/// Direct child with the given tree-sitter field id.
200205
pub fn child_by_field(&self, unit: &CompileUnit<'hir>, field_id: u16) -> Option<HirNode<'hir>> {
201-
self.base()?.child_by_field(unit, field_id)
206+
self.try_base()?.child_by_field(unit, field_id)
202207
}
203208

204209
/// Direct child with the given tree-sitter kind id.
205210
pub fn child_by_kind(&self, unit: &CompileUnit<'hir>, kind_id: u16) -> Option<HirNode<'hir>> {
206211
self.children(unit)
207212
.into_iter()
208-
.find(|child| child.base().is_some_and(|base| base.kind_id == kind_id))
213+
.find(|child| child.try_base().is_some_and(|base| base.kind_id == kind_id))
209214
}
210215

211216
#[inline]
@@ -298,7 +303,11 @@ impl HirBase {
298303
self.children
299304
.iter()
300305
.map(|id| unit.hir_node(*id))
301-
.find(|child| child.base().is_some_and(|base| base.field_id == field_id))
306+
.find(|child| {
307+
child
308+
.try_base()
309+
.is_some_and(|base| base.field_id == field_id)
310+
})
302311
}
303312
}
304313

@@ -399,7 +408,7 @@ impl<'hir> HirScope<'hir> {
399408
}
400409

401410
/// Semantic scope if it has been attached.
402-
pub fn opt_scope(&self) -> Option<&'hir Scope<'hir>> {
411+
pub fn try_scope(&self) -> Option<&'hir Scope<'hir>> {
403412
*self.scope.read()
404413
}
405414

@@ -409,7 +418,7 @@ impl<'hir> HirScope<'hir> {
409418
}
410419

411420
/// Identifier that names this scope, if present.
412-
pub fn opt_ident(&self) -> Option<&'hir HirIdent<'hir>> {
421+
pub fn try_ident(&self) -> Option<&'hir HirIdent<'hir>> {
413422
*self.ident.read()
414423
}
415424

@@ -421,8 +430,8 @@ impl<'hir> HirScope<'hir> {
421430
}
422431

423432
/// Symbol associated with this scope through its semantic `Scope`.
424-
pub fn opt_symbol(&self) -> Option<&'hir Symbol> {
425-
self.opt_scope().and_then(|scope| scope.opt_symbol())
433+
pub fn try_symbol(&self) -> Option<&'hir Symbol> {
434+
self.try_scope().and_then(|scope| scope.try_symbol())
426435
}
427436
}
428437

@@ -476,7 +485,7 @@ impl<'hir> HirIdent<'hir> {
476485

477486
/// Resolved symbol if one has been attached.
478487
#[inline]
479-
pub fn opt_symbol(&self) -> Option<&'hir Symbol> {
488+
pub fn try_symbol(&self) -> Option<&'hir Symbol> {
480489
let ptr = self.symbol.load(Ordering::Acquire);
481490
if ptr.is_null() {
482491
None

0 commit comments

Comments
 (0)