Skip to main content

libperl_macrogen/
fields_dict.rs

1//! 構造体フィールド名辞書
2//!
3//! マクロの引数型推論のため、フィールド名から構造体名への
4//! マッピングと、フィールドの型情報を記録する。
5
6use std::collections::{HashMap, HashSet};
7
8use crate::ast::{Declaration, DeclSpecs, Declarator, DerivedDecl, ExternalDecl, StorageClass, StructMember, StructSpec, TypeSpec};
9use crate::intern::{InternedStr, StringInterner};
10use crate::type_repr::TypeRepr;
11
12/// 共通フィールドマクロが宣言する 1 つのフィールドの最小情報
13#[derive(Debug, Clone)]
14pub struct CommonField {
15    /// フィールド名(最も内側、例: `xcv_xsub`)
16    pub name: InternedStr,
17    /// 関数ポインタ(`void (*name)(...)` 等)かどうか
18    pub is_fn_pointer: bool,
19    /// マクロ本体内での出現位置の素性
20    pub origin: CommonFieldOrigin,
21}
22
23/// `CommonField` の出現位置素性
24#[derive(Debug, Clone)]
25pub enum CommonFieldOrigin {
26    /// 直接のフィールド
27    Direct,
28    /// 無名 union/struct の中のフィールド(外側のフィールド名を持つ)
29    InsideUnion { union_field: InternedStr },
30}
31
32/// 共通フィールドマクロが定義するフィールド集合
33#[derive(Debug, Clone)]
34pub struct CommonFieldMacro {
35    pub name: InternedStr,
36    pub fields: Vec<CommonField>,
37}
38
39/// `Declarator.derived` から関数ポインタを判定する。
40///
41/// C の関数ポインタ宣言 `void (*name)(args)` の `derived` は典型的に
42/// `[Function(...), Pointer(...)]` の順で並ぶ(最内側が先頭)。
43/// 関数自体(fn pointer ではなく fn 型)と区別するため、Pointer と
44/// Function の両方が出現することを要求する。
45fn is_fn_pointer_declarator(derived: &[DerivedDecl]) -> bool {
46    let has_fn = derived.iter().any(|d| matches!(d, DerivedDecl::Function(_)));
47    let has_ptr = derived.iter().any(|d| matches!(d, DerivedDecl::Pointer(_)));
48    has_fn && has_ptr
49}
50
51/// `TypeRepr` が C 慣用句の flexible array member 型(`T[1]`、`T[0]`、または
52/// C99 `T[]`)かを判定し、該当すれば配列を剥がした要素型を返す。
53///
54/// 検出条件: 最も外側の derived が `Array { size: Some(0|1) | None }`。
55/// (`Array { size: Some(N>=2) }` は通常の固定長配列なので除外)
56fn flexible_array_element_type(ty: &TypeRepr) -> Option<TypeRepr> {
57    use crate::type_repr::CDerivedType;
58    let TypeRepr::CType { specs, derived, source } = ty else {
59        return None;
60    };
61    let last = derived.last()?;
62    let is_flex = match last {
63        CDerivedType::Array { size: None } => true,
64        CDerivedType::Array { size: Some(0) } | CDerivedType::Array { size: Some(1) } => true,
65        _ => false,
66    };
67    if !is_flex {
68        return None;
69    }
70    let mut new_derived = derived.clone();
71    new_derived.pop();
72    Some(TypeRepr::CType {
73        specs: specs.clone(),
74        derived: new_derived,
75        source: source.clone(),
76    })
77}
78
79/// フィールドの型情報
80#[derive(Debug, Clone)]
81pub struct FieldType {
82    /// 型情報(構造化された表現)
83    pub type_repr: TypeRepr,
84}
85
86/// フィールド名から構造体名へのマッピング
87#[derive(Debug, Default)]
88pub struct FieldsDict {
89    /// フィールド名 -> 構造体名のセット
90    /// (同じフィールド名が複数の構造体で使われる可能性があるためHashSet)
91    field_to_structs: HashMap<InternedStr, HashSet<InternedStr>>,
92    /// (構造体名, フィールド名) -> フィールド型
93    field_types: HashMap<(InternedStr, InternedStr), FieldType>,
94    /// typedef名 -> 構造体名のマッピング (例: XPV -> xpv)
95    typedef_to_struct: HashMap<InternedStr, InternedStr>,
96    /// 一致型キャッシュ: フィールド名 -> 一致型(全バリアントで型が同じ場合のみ Some)
97    consistent_type_cache: HashMap<InternedStr, Option<TypeRepr>>,
98    /// SV ファミリーメンバー(_SV_HEAD マクロを使用する構造体)
99    /// 動的に検出される
100    sv_family_members: HashSet<InternedStr>,
101    /// _SV_HEAD(typeName) の typeName → 構造体名のマッピング
102    /// 例: "XPVAV" → av, "XPVCV" → cv
103    /// SvANY キャストパターンによる型推論に使用
104    sv_head_type_to_struct: HashMap<String, InternedStr>,
105    /// sv_u ユニオンフィールドの型マッピング
106    /// key: フィールド名 (例: svu_pv, svu_hash)
107    /// value: フィールドの C 型文字列 (例: "char*", "HE**")
108    sv_u_field_types: HashMap<InternedStr, String>,
109    /// 構造体名 → そこで展開された共通フィールドマクロ集合
110    /// 例: xpvcv → {_XPV_HEAD, _XPVCV_COMMON}
111    struct_to_common_macros: HashMap<InternedStr, Vec<InternedStr>>,
112    /// 共通フィールドマクロ → それを使う構造体集合
113    /// 例: _XPVCV_COMMON → [xpvcv, xpvfm]
114    common_macro_to_structs: HashMap<InternedStr, Vec<InternedStr>>,
115    /// 共通フィールドマクロ名 → そこで宣言されるフィールド情報
116    /// 例: _XPVCV_COMMON → [{ name: xcv_xsub, is_fn_pointer: true, ... }, ...]
117    common_macros: HashMap<InternedStr, CommonFieldMacro>,
118    /// フィールド名 → そのフィールドを定義している共通マクロ名
119    /// 例: xcv_xsub → _XPVCV_COMMON
120    /// (無名 union 内のフィールドも含む)
121    field_to_defining_macro: HashMap<InternedStr, InternedStr>,
122    /// 共通フィールドマクロが宣言したフィールド名 → 整合性のある Rust 型
123    /// (bindings.rs 由来)。`build_common_field_rust_types` で構築。
124    common_field_rust_types: HashMap<InternedStr, TypeRepr>,
125    /// 共通フィールドマクロ → 一意な SV ファミリー typedef 名
126    /// 例: `_XPVCV_COMMON` → `CV` (xpvcv ボディ → struct cv → typedef CV、
127    /// xpvfm 側は対応 SV 構造体無しで除外、結果一意)
128    /// `build_common_macro_sv_family` で構築。
129    common_macro_to_sv_family: HashMap<InternedStr, InternedStr>,
130    /// 構造体最終メンバーが flexible array member(`char foo[1]` や `[0]`、`[]`)
131    /// である場合の (struct_name, field_name) → 要素型(配列を剥がした TypeRepr)。
132    /// C 慣用句で可変長バッファとして使われ、ポインタとして扱うべきもの。
133    /// 例: `(struct hek, hek_key)` → `char` の TypeRepr
134    flexible_array_fields: HashMap<(InternedStr, InternedStr), TypeRepr>,
135    /// 構造体・union 定義の順序付き取得用。
136    /// bindings.rs に存在しない struct(例: `body_details`、`ALIGNED_TYPE` 系
137    /// typedef union)の Rust 定義生成に使う。メンバー順を保持し、bitfield 幅も
138    /// 持つ。同名 struct/union を複数回見た場合は最初の定義を保持する。
139    struct_defs: HashMap<InternedStr, StructDef>,
140}
141
142/// 構造体・union 定義の順序付き表現(`StructEmitter` 用)。
143///
144/// `FieldsDict.field_types` は HashMap でメンバー順が失われるため、こちらに
145/// `Vec` で順序付き保存する。bitfield 幅は `bitfield_width` で表現する。
146#[derive(Debug, Clone)]
147pub struct StructDef {
148    pub name: InternedStr,
149    pub is_union: bool,
150    pub members: Vec<StructMemberInfo>,
151}
152
153/// `StructDef` のメンバー要素
154#[derive(Debug, Clone)]
155pub struct StructMemberInfo {
156    pub name: InternedStr,
157    pub type_repr: TypeRepr,
158    /// `T name : N` 形式のときの N。通常メンバーは None。
159    pub bitfield_width: Option<u32>,
160}
161
162impl FieldsDict {
163    /// 新しい辞書を作成
164    pub fn new() -> Self {
165        Self::default()
166    }
167
168    /// 外部宣言からフィールド情報を収集
169    /// is_target: この宣言がターゲットディレクトリ内で定義されたかどうか
170    pub fn collect_from_external_decl(
171        &mut self,
172        decl: &ExternalDecl,
173        is_target: bool,
174        interner: &StringInterner,
175    ) {
176        // ターゲットディレクトリ内の宣言のみ収集
177        if !is_target {
178            return;
179        }
180
181        if let ExternalDecl::Declaration(d) = decl {
182            self.collect_from_declaration(d, interner);
183        }
184    }
185
186    /// 宣言からフィールド情報を収集
187    fn collect_from_declaration(&mut self, decl: &Declaration, interner: &StringInterner) {
188        // typedef struct xpv XPV; のような宣言を検出して typedef マッピングを登録
189        if decl.specs.storage == Some(StorageClass::Typedef) {
190            self.collect_typedef_aliases(decl, interner);
191            // typedef union { ... } NAME; のような anonymous struct/union 定義は
192            // 通常の collect_from_struct_spec が name=None で early-return するため
193            // 取り逃がす。declarator の typedef 名を struct 名として登録する。
194            self.collect_typedef_anonymous_struct(decl, interner);
195        }
196
197        for type_spec in &decl.specs.type_specs {
198            match type_spec {
199                TypeSpec::Struct(spec) => {
200                    self.collect_from_struct_spec_with_kind(spec, false, interner);
201                }
202                TypeSpec::Union(spec) => {
203                    // 共用体も同様に収集
204                    self.collect_from_struct_spec_with_kind(spec, true, interner);
205                }
206                _ => {}
207            }
208        }
209    }
210
211    /// `typedef union { ... } NAME;` のような anonymous struct/union 定義から
212    /// typedef 名を struct 名として `struct_defs` に登録する。
213    /// 例: `typedef union { regexp align_me; NV nv; IV iv; } regexp_aligned;`
214    /// これは sv_inline.h の `ALIGNED_TYPE` マクロ展開で多用される。
215    fn collect_typedef_anonymous_struct(&mut self, decl: &Declaration, interner: &StringInterner) {
216        // type_specs から anonymous struct/union を探す
217        let (anon_spec, is_union) = {
218            let mut found = None;
219            for ts in &decl.specs.type_specs {
220                match ts {
221                    TypeSpec::Struct(s) if s.name.is_none() && s.members.is_some() => {
222                        found = Some((s, false));
223                        break;
224                    }
225                    TypeSpec::Union(s) if s.name.is_none() && s.members.is_some() => {
226                        found = Some((s, true));
227                        break;
228                    }
229                    _ => {}
230                }
231            }
232            match found {
233                Some(v) => v,
234                None => return,
235            }
236        };
237
238        // declarator から typedef 名を取得(pointer/array 修飾無しのみ)
239        for init_decl in &decl.declarators {
240            if !init_decl.declarator.derived.is_empty() {
241                continue;
242            }
243            let typedef_name = match init_decl.declarator.name {
244                Some(n) => n,
245                None => continue,
246            };
247            // 同名 spec として登録(`name` を持つ spec を仮構築して既存ロジックを再利用)
248            let synthetic_spec = StructSpec {
249                name: Some(typedef_name),
250                members: anon_spec.members.clone(),
251                loc: anon_spec.loc.clone(),
252            };
253            self.collect_from_struct_spec_with_kind(&synthetic_spec, is_union, interner);
254        }
255    }
256
257    /// typedef 宣言から typedef名 -> 構造体名 のマッピングを収集
258    /// 例: typedef struct xpv XPV; → XPV -> xpv
259    fn collect_typedef_aliases(&mut self, decl: &Declaration, _interner: &StringInterner) {
260        // 構造体/共用体の名前を取得
261        let mut struct_name: Option<InternedStr> = None;
262        for type_spec in &decl.specs.type_specs {
263            match type_spec {
264                TypeSpec::Struct(spec) | TypeSpec::Union(spec) => {
265                    if let Some(name) = spec.name {
266                        struct_name = Some(name);
267                        break;
268                    }
269                }
270                _ => {}
271            }
272        }
273
274        // 構造体名がある場合、宣言子から typedef 名を取得
275        if let Some(s_name) = struct_name {
276            for init_decl in &decl.declarators {
277                // ポインタなしの直接typedef のみ対象
278                // 例: typedef struct xpv XPV; は対象
279                //     typedef struct xpv *XPV; は対象外
280                if init_decl.declarator.derived.is_empty() {
281                    if let Some(typedef_name) = init_decl.declarator.name {
282                        self.typedef_to_struct.insert(typedef_name, s_name);
283                    }
284                }
285            }
286        }
287    }
288
289    /// `collect_from_struct_spec` の本体。union 識別を呼び出し側から受け取る。
290    fn collect_from_struct_spec_with_kind(
291        &mut self, spec: &StructSpec, is_union: bool, interner: &StringInterner,
292    ) {
293        // 名前付き構造体のみ対象
294        let struct_name = match spec.name {
295            Some(name) => name,
296            None => return,
297        };
298
299        // メンバーがある場合のみ処理
300        let members = match &spec.members {
301            Some(m) => m,
302            None => return,
303        };
304
305        // 順序付き struct_def を構築(既存があれば後で skip)
306        let mut ordered_members: Vec<StructMemberInfo> = Vec::new();
307
308        let last_idx = members.len().saturating_sub(1);
309        for (m_idx, member) in members.iter().enumerate() {
310            // メンバーの型指定子にネストした構造体があれば再帰的に処理
311            for type_spec in &member.specs.type_specs {
312                match type_spec {
313                    TypeSpec::Struct(nested) => {
314                        self.collect_from_struct_spec_with_kind(nested, false, interner);
315                    }
316                    TypeSpec::Union(nested) => {
317                        self.collect_from_struct_spec_with_kind(nested, true, interner);
318                        // sv_u union を検出して C 型を収集
319                        if self.is_sv_u_union_member(member, interner) {
320                            self.collect_sv_u_union_fields(nested, interner);
321                        }
322                    }
323                    _ => {}
324                }
325            }
326
327            // フィールド名と型を収集
328            let is_last_member = m_idx == last_idx;
329            let last_decl_idx = member.declarators.len().saturating_sub(1);
330            for (d_idx, decl) in member.declarators.iter().enumerate() {
331                if let Some(ref declarator) = decl.declarator {
332                    if let Some(field_name) = declarator.name {
333                        // フィールド名 -> 構造体名のマッピング
334                        self.field_to_structs
335                            .entry(field_name)
336                            .or_insert_with(HashSet::new)
337                            .insert(struct_name);
338
339                        // フィールド型の収集
340                        if let Some(type_repr) = self.extract_field_type(&member.specs, declarator, interner) {
341                            // 順序付き struct_def 用に追加(bitfield 幅も保持)
342                            let bitfield_width = decl.bitfield.as_ref().and_then(|e| {
343                                if let crate::ast::ExprKind::IntLit(n) = &e.kind {
344                                    Some(*n as u32)
345                                } else { None }
346                            });
347                            ordered_members.push(StructMemberInfo {
348                                name: field_name,
349                                type_repr: type_repr.clone(),
350                                bitfield_width,
351                            });
352
353                            // flexible array member の検出: 構造体の真の末尾メンバーで
354                            // size 1 / 0 の固定長配列、または C99 [] 構文の可変長配列
355                            let is_struct_last = is_last_member && d_idx == last_decl_idx;
356                            if is_struct_last {
357                                if let Some(elem) = flexible_array_element_type(&type_repr) {
358                                    self.flexible_array_fields
359                                        .insert((struct_name, field_name), elem);
360                                }
361                            }
362                            self.field_types.insert(
363                                (struct_name, field_name),
364                                FieldType { type_repr },
365                            );
366                        }
367                    }
368                }
369            }
370        }
371
372        // 順序付き struct_def を登録(先勝ち)
373        if !ordered_members.is_empty() {
374            self.struct_defs.entry(struct_name).or_insert_with(|| StructDef {
375                name: struct_name,
376                is_union,
377                members: ordered_members,
378            });
379        }
380    }
381
382    /// 構造体・union 定義(順序付き)を取得
383    pub fn get_struct_def(&self, name: InternedStr) -> Option<&StructDef> {
384        self.struct_defs.get(&name)
385    }
386
387    /// 指定 struct のメンバ型を取得。typedef 経由も考慮する。
388    pub fn member_type(&self, struct_name: InternedStr, member: InternedStr)
389        -> Option<&TypeRepr>
390    {
391        // まず直接ヒット
392        if let Some(def) = self.struct_defs.get(&struct_name) {
393            for m in &def.members {
394                if m.name == member {
395                    return Some(&m.type_repr);
396                }
397            }
398        }
399        // typedef で別名になっている可能性を追跡
400        let resolved = self.typedef_to_struct.get(&struct_name).copied().unwrap_or(struct_name);
401        if resolved != struct_name {
402            if let Some(def) = self.struct_defs.get(&resolved) {
403                for m in &def.members {
404                    if m.name == member {
405                        return Some(&m.type_repr);
406                    }
407                }
408            }
409        }
410        None
411    }
412
413    /// 全 struct/union 定義を返す(順序付き struct_defs に登録されたもの)
414    pub fn iter_struct_defs(&self) -> impl Iterator<Item = (&InternedStr, &StructDef)> {
415        self.struct_defs.iter()
416    }
417
418    /// メンバーが sv_u という名前の union かどうかを判定
419    fn is_sv_u_union_member(&self, member: &crate::ast::StructMember, interner: &StringInterner) -> bool {
420        // declarators に sv_u という名前があるか確認
421        for decl in &member.declarators {
422            if let Some(ref declarator) = decl.declarator {
423                if let Some(name) = declarator.name {
424                    if interner.get(name) == "sv_u" {
425                        return true;
426                    }
427                }
428            }
429        }
430        false
431    }
432
433    /// sv_u union の内部フィールドから C 型を収集
434    ///
435    /// union のメンバーを走査し、フィールド名と C 型を sv_u_field_types に登録する。
436    fn collect_sv_u_union_fields(&mut self, union_spec: &StructSpec, interner: &StringInterner) {
437        let members = match &union_spec.members {
438            Some(m) => m,
439            None => return,
440        };
441
442        for member in members {
443            for struct_decl in &member.declarators {
444                if let Some(ref declarator) = struct_decl.declarator {
445                    if let Some(field_name) = declarator.name {
446                        // C 型を抽出
447                        if let Some(c_type) = self.extract_c_type(&member.specs, declarator, interner) {
448                            self.register_sv_u_field(field_name, c_type);
449                        }
450                    }
451                }
452            }
453        }
454    }
455
456    /// DeclSpecs と Declarator から C 型文字列を抽出
457    fn extract_c_type(&self, specs: &DeclSpecs, declarator: &Declarator, interner: &StringInterner) -> Option<String> {
458        // 基本型を取得
459        let base_type = self.extract_c_base_type(specs, interner)?;
460
461        // ポインタを適用
462        let mut result = base_type;
463        for derived in &declarator.derived {
464            if let DerivedDecl::Pointer { .. } = derived {
465                result = format!("{}*", result);
466            }
467        }
468
469        Some(result)
470    }
471
472    /// DeclSpecs から C 基本型を抽出
473    fn extract_c_base_type(&self, specs: &DeclSpecs, interner: &StringInterner) -> Option<String> {
474        for type_spec in &specs.type_specs {
475            match type_spec {
476                TypeSpec::Void => return Some("void".to_string()),
477                TypeSpec::Char => return Some("char".to_string()),
478                TypeSpec::Int => return Some("int".to_string()),
479                TypeSpec::Short => return Some("short".to_string()),
480                TypeSpec::Long => return Some("long".to_string()),
481                TypeSpec::Float => return Some("float".to_string()),
482                TypeSpec::Double => return Some("double".to_string()),
483                TypeSpec::Unsigned => continue, // 修飾子、次のループで処理
484                TypeSpec::Signed => continue,
485                TypeSpec::Struct(s) | TypeSpec::Union(s) => {
486                    if let Some(name) = s.name {
487                        return Some(interner.get(name).to_string());
488                    }
489                }
490                TypeSpec::TypedefName(name) => {
491                    return Some(interner.get(*name).to_string());
492                }
493                _ => {}
494            }
495        }
496        None
497    }
498
499    /// DeclSpecs と Declarator からフィールドの TypeRepr を抽出
500    fn extract_field_type(&self, specs: &DeclSpecs, declarator: &Declarator, interner: &StringInterner) -> Option<TypeRepr> {
501        // TypeRepr::from_decl を使用して構造化された型情報を生成
502        Some(TypeRepr::from_decl(specs, declarator, interner))
503    }
504
505    /// 一意に構造体を特定できるフィールド名から構造体名を取得
506    pub fn lookup_unique(&self, field_name: InternedStr) -> Option<InternedStr> {
507        self.field_to_structs.get(&field_name).and_then(|structs| {
508            if structs.len() == 1 {
509                structs.iter().next().copied()
510            } else {
511                None
512            }
513        })
514    }
515
516    /// フィールドを持つ構造体群の共通親型を取得
517    ///
518    /// 複数の構造体がフィールドを持つ場合、それらの共通の親型を返す。
519    /// 現在は SV ファミリーのみ対応:
520    /// - フィールドを持つ全構造体が SV ファミリーメンバーの場合、"sv" を返す
521    /// - それ以外の場合は None
522    ///
523    /// # 例
524    ///
525    /// `sv_flags` は `sv`, `av`, `hv`, `cv` 等に存在 → 共通親型は "sv"
526    pub fn get_consistent_base_type(&self, field_name: InternedStr, interner: &StringInterner) -> Option<InternedStr> {
527        let structs = self.field_to_structs.get(&field_name)?;
528
529        // フィールドを持つ構造体がない場合は None
530        if structs.is_empty() {
531            return None;
532        }
533
534        // 全ての構造体が SV ファミリーメンバーかチェック
535        let all_sv_family = structs.iter().all(|s| self.sv_family_members.contains(s));
536
537        if all_sv_family {
538            // "sv" を intern して返す
539            // Note: interner.lookup は既存の文字列のみ返すので、
540            // "sv" が未登録の場合は None になる可能性がある
541            interner.lookup("sv")
542        } else {
543            None
544        }
545    }
546
547    /// フィールド名から一意にフィールド型を特定(構造体が1つしかない場合)
548    pub fn get_unique_field_type(&self, field_name: InternedStr) -> Option<&FieldType> {
549        let struct_name = self.lookup_unique(field_name)?;
550        self.field_types.get(&(struct_name, field_name))
551    }
552
553    /// InternedStr で直接フィールド型を取得(typedef 解決付き)
554    pub fn get_field_type(
555        &self,
556        struct_name: InternedStr,
557        field_name: InternedStr,
558    ) -> Option<&FieldType> {
559        // 直接検索
560        if let Some(ft) = self.field_types.get(&(struct_name, field_name)) {
561            return Some(ft);
562        }
563        // typedef 解決して再検索
564        let resolved = self.resolve_typedef(struct_name)?;
565        self.field_types.get(&(resolved, field_name))
566    }
567
568    /// 構造体名(文字列)とフィールド名からフィールド型を取得
569    /// StringInterner が immutable な場合に使用する
570    /// typedef 名でも検索可能(例: XPV で検索すると xpv のフィールドを返す)
571    pub fn get_field_type_by_name(
572        &self,
573        struct_name_str: &str,
574        field_name: InternedStr,
575        interner: &StringInterner,
576    ) -> Option<&FieldType> {
577        // まず直接検索
578        for ((s_name, f_name), field_type) in &self.field_types {
579            if interner.get(*s_name) == struct_name_str && *f_name == field_name {
580                return Some(field_type);
581            }
582        }
583
584        // typedef 名から構造体名を解決して再検索
585        if let Some(resolved_struct_name) = self.resolve_typedef_by_name(struct_name_str, interner) {
586            let resolved_str = interner.get(resolved_struct_name);
587            for ((s_name, f_name), field_type) in &self.field_types {
588                if interner.get(*s_name) == resolved_str && *f_name == field_name {
589                    return Some(field_type);
590                }
591            }
592        }
593
594        None
595    }
596
597    /// typedef 名から構造体名を解決(InternedStr ベース)
598    pub fn resolve_typedef(&self, typedef_name: InternedStr) -> Option<InternedStr> {
599        self.typedef_to_struct.get(&typedef_name).copied()
600    }
601
602    /// typedef 名から構造体名を解決(文字列ベース)
603    fn resolve_typedef_by_name(&self, typedef_name_str: &str, interner: &StringInterner) -> Option<InternedStr> {
604        for (typedef_name, struct_name) in &self.typedef_to_struct {
605            if interner.get(*typedef_name) == typedef_name_str {
606                return Some(*struct_name);
607            }
608        }
609        None
610    }
611
612    /// 構造体名から typedef 名を取得(逆引き)
613    ///
614    /// 同じ構造体に複数の typedef がある場合は最初に見つかったものを返す。
615    /// typedef が登録されていない場合は None。
616    pub fn get_typedef_for_struct(&self, struct_name: InternedStr) -> Option<InternedStr> {
617        for (typedef_name, s_name) in &self.typedef_to_struct {
618            if *s_name == struct_name {
619                return Some(*typedef_name);
620            }
621        }
622        None
623    }
624
625    /// 登録された typedef の数を取得
626    pub fn typedef_count(&self) -> usize {
627        self.typedef_to_struct.len()
628    }
629
630    /// 全 typedef → struct マッピングを順に列挙
631    pub fn iter_typedefs(&self) -> impl Iterator<Item = (&InternedStr, &InternedStr)> {
632        self.typedef_to_struct.iter()
633    }
634
635    /// 収集されたフィールド型の数を取得
636    pub fn field_types_count(&self) -> usize {
637        self.field_types.len()
638    }
639
640    // ==================== SV Family Detection ====================
641
642    /// SV ファミリーメンバーと typeName を同時に登録
643    ///
644    /// _SV_HEAD(typeName) マクロの引数から、typeName → 構造体名のマッピングを構築する。
645    /// 例: add_sv_family_member_with_type(av, "XPVAV*") → "XPVAV" → av
646    ///
647    /// void* は汎用型のためマッピングには含めない。
648    pub fn add_sv_family_member_with_type(&mut self, struct_name: InternedStr, type_name: &str) {
649        self.sv_family_members.insert(struct_name);
650
651        // ポインタ記号を除去して正規化
652        let normalized = type_name.trim().trim_end_matches('*').trim();
653        if !normalized.is_empty() && normalized != "void" {
654            self.sv_head_type_to_struct.insert(normalized.to_string(), struct_name);
655        }
656    }
657
658    /// typeName から構造体名を取得
659    ///
660    /// _SV_HEAD(typeName) で登録された typeName から対応する構造体名を取得する。
661    /// SvANY キャストパターン (例: (XPVAV*) SvANY(av)) の型推論に使用。
662    pub fn get_struct_for_sv_head_type(&self, type_name: &str) -> Option<InternedStr> {
663        let normalized = type_name.trim().trim_end_matches('*').trim();
664        self.sv_head_type_to_struct.get(normalized).copied()
665    }
666
667    /// 型名(typedef 名または構造体名)が SV ファミリーかどうかを判定
668    pub fn is_sv_family_type(&self, type_name: InternedStr) -> bool {
669        // 構造体名で直接チェック
670        if self.sv_family_members.contains(&type_name) {
671            return true;
672        }
673        // typedef 名 → 構造体名に解決してチェック
674        if let Some(struct_name) = self.typedef_to_struct.get(&type_name) {
675            return self.sv_family_members.contains(struct_name);
676        }
677        false
678    }
679
680    /// 動的に検出された SV ファミリーメンバーの数を取得
681    pub fn sv_family_members_count(&self) -> usize {
682        self.sv_family_members.len()
683    }
684
685    /// typeName → 構造体名マッピングの数を取得
686    pub fn sv_head_type_mapping_count(&self) -> usize {
687        self.sv_head_type_to_struct.len()
688    }
689
690    /// typeName → 構造体名マッピングをイテレート
691    pub fn sv_head_type_to_struct_iter(&self) -> impl Iterator<Item = (&String, &InternedStr)> {
692        self.sv_head_type_to_struct.iter()
693    }
694
695    // ==================== Common Field Macros ====================
696    //
697    // perl5 の `_XPV_HEAD` / `_XPVCV_COMMON` のような object-like macro を
698    // 通じた共通フィールド宣言を構造体↔マクロのレベルで記録する
699    // (`_SV_HEAD` の sv_family サポートを一般化したもの)。
700
701    /// 構造体がある共通フィールドマクロを使用していることを記録する。
702    pub fn add_struct_uses_common_macro(
703        &mut self,
704        struct_name: InternedStr,
705        macro_name: InternedStr,
706    ) {
707        let v = self.struct_to_common_macros.entry(struct_name).or_default();
708        if !v.contains(&macro_name) {
709            v.push(macro_name);
710        }
711        let v = self.common_macro_to_structs.entry(macro_name).or_default();
712        if !v.contains(&struct_name) {
713            v.push(struct_name);
714        }
715    }
716
717    /// あるマクロを使用している構造体一覧
718    pub fn structs_using_common_macro(&self, macro_name: InternedStr) -> &[InternedStr] {
719        self.common_macro_to_structs
720            .get(&macro_name)
721            .map(|v| v.as_slice())
722            .unwrap_or(&[])
723    }
724
725    /// ある構造体が使用している共通フィールドマクロ一覧
726    pub fn common_macros_used_by_struct(&self, struct_name: InternedStr) -> &[InternedStr] {
727        self.struct_to_common_macros
728            .get(&struct_name)
729            .map(|v| v.as_slice())
730            .unwrap_or(&[])
731    }
732
733    /// 観測対象の共通フィールドマクロ数(テスト・デバッグ用)
734    pub fn common_macro_count(&self) -> usize {
735        self.common_macro_to_structs.len()
736    }
737
738    /// あるフィールド名を宣言している共通マクロ(B-2 で構築)
739    pub fn defining_macro_of(&self, field_name: InternedStr) -> Option<InternedStr> {
740        self.field_to_defining_macro.get(&field_name).copied()
741    }
742
743    /// マクロ名から `CommonFieldMacro` を取得
744    pub fn common_macro(&self, macro_name: InternedStr) -> Option<&CommonFieldMacro> {
745        self.common_macros.get(&macro_name)
746    }
747
748    /// フィールド名から定義マクロと該当 `CommonField` をまとめて取得
749    pub fn canonical_field(
750        &self,
751        field_name: InternedStr,
752    ) -> Option<(&CommonFieldMacro, &CommonField)> {
753        let macro_name = *self.field_to_defining_macro.get(&field_name)?;
754        let cm = self.common_macros.get(&macro_name)?;
755        let cf = cm.fields.iter().find(|f| f.name == field_name)?;
756        Some((cm, cf))
757    }
758
759    /// 共通フィールドマクロ宣言フィールドの bindings.rs 由来 Rust 型
760    /// (`build_common_field_rust_types` で構築)
761    pub fn rust_type_of_common_field(&self, field_name: InternedStr) -> Option<&TypeRepr> {
762        self.common_field_rust_types.get(&field_name)
763    }
764
765    /// 共通フィールドマクロから一意な SV ファミリー typedef 名を取得
766    /// (`build_common_macro_sv_family` で構築)
767    pub fn sv_family_of_common_macro(&self, macro_name: InternedStr) -> Option<InternedStr> {
768        self.common_macro_to_sv_family.get(&macro_name).copied()
769    }
770
771    /// (struct_name, field_name) が flexible array member であれば、
772    /// その要素型 (`T[1]` の `T`) を返す。typedef 解決付き
773    /// (例: 引数に `HEK` を渡しても `hek` のエントリを返す)。
774    /// `collect_from_struct_spec` で構造体最終メンバーが size 1/0 配列、または
775    /// C99 `[]` の場合に登録される。
776    pub fn flexible_array_element(&self, struct_name: InternedStr, field_name: InternedStr)
777        -> Option<&TypeRepr>
778    {
779        if let Some(t) = self.flexible_array_fields.get(&(struct_name, field_name)) {
780            return Some(t);
781        }
782        let resolved = self.resolve_typedef(struct_name)?;
783        self.flexible_array_fields.get(&(resolved, field_name))
784    }
785
786    /// `flexible_array_element` の便利版(要素型が不要な場合)
787    pub fn is_flexible_array_field(&self, struct_name: InternedStr, field_name: InternedStr) -> bool {
788        self.flexible_array_element(struct_name, field_name).is_some()
789    }
790
791    /// 共通フィールドマクロ → 対応する SV ファミリー typedef 名の事前マッピング
792    /// を構築する。
793    ///
794    /// 各 xpv ボディ構造体(例 xpvcv)について:
795    ///   xpv struct → typedef "XPVCV" → sv_head_type_to_struct で SV 構造体 cv
796    ///     → typedef "CV"
797    /// と辿り、全ての xpv について typedef が一意に決まる場合のみ登録する。
798    pub fn build_common_macro_sv_family(&mut self, interner: &StringInterner) {
799        let mut new_map: HashMap<InternedStr, InternedStr> = HashMap::new();
800        for (&macro_id, struct_names) in &self.common_macro_to_structs {
801            let mut sv_typedefs: HashSet<InternedStr> = HashSet::new();
802            for &xpv_struct in struct_names {
803                let xpv_typedef = match self.get_typedef_for_struct(xpv_struct) {
804                    Some(td) => td,
805                    None => continue,
806                };
807                let xpv_typedef_str = interner.get(xpv_typedef);
808                let sv_struct = match self.sv_head_type_to_struct.get(xpv_typedef_str) {
809                    Some(&s) => s,
810                    None => continue, // 対応する SV ファミリー無し
811                };
812                if let Some(td) = self.get_typedef_for_struct(sv_struct) {
813                    sv_typedefs.insert(td);
814                }
815            }
816            if sv_typedefs.len() == 1 {
817                new_map.insert(macro_id, *sv_typedefs.iter().next().unwrap());
818            }
819        }
820        self.common_macro_to_sv_family = new_map;
821    }
822
823    /// `RustDeclDict.structs` (bindgen の Item::Struct と Item::Union を含む)
824    /// を走査し、共通フィールドマクロ宣言フィールドについて整合性のある Rust 型を
825    /// 収集する。
826    ///
827    /// あるフィールド名が複数の bindings.rs エントリで異なる型を持つ場合、
828    /// マップから除外する(`build_field_type_map` と同じポリシー)。
829    pub fn build_common_field_rust_types(
830        &mut self,
831        rust_dict: &crate::rust_decl::RustDeclDict,
832        interner: &mut StringInterner,
833    ) {
834        use std::collections::hash_map::Entry;
835        // 関心対象: 共通マクロ宣言フィールド名集合
836        let target_names: HashSet<InternedStr> = self
837            .common_macros
838            .values()
839            .flat_map(|m| m.fields.iter().map(|f| f.name))
840            .collect();
841        if target_names.is_empty() {
842            return;
843        }
844
845        let mut acc: HashMap<InternedStr, String> = HashMap::new();
846        let mut conflicts: HashSet<InternedStr> = HashSet::new();
847
848        for rust_struct in rust_dict.structs.values() {
849            for field in &rust_struct.fields {
850                let id = interner.intern(&field.name);
851                if !target_names.contains(&id) {
852                    continue;
853                }
854                if conflicts.contains(&id) {
855                    continue;
856                }
857                match acc.entry(id) {
858                    Entry::Vacant(e) => {
859                        e.insert(field.ty.clone());
860                    }
861                    Entry::Occupied(e) => {
862                        if e.get() != &field.ty {
863                            conflicts.insert(id);
864                            e.remove();
865                        }
866                    }
867                }
868            }
869        }
870
871        for (id, ty_str) in acc {
872            let repr = TypeRepr::RustType {
873                repr: crate::type_repr::RustTypeRepr::from_type_string(&ty_str),
874                source: crate::type_repr::RustTypeSource::Parsed { raw: ty_str },
875            };
876            self.common_field_rust_types.insert(id, repr);
877        }
878    }
879
880    /// 共通フィールドマクロの canonical field set を構築する。
881    ///
882    /// B-1 で `add_struct_uses_common_macro` により記録された各共通マクロに
883    /// ついて、`MacroDef.body` を struct member 列としてパースし、
884    /// `CommonFieldMacro` と `field_to_defining_macro` を構築する。
885    ///
886    /// `parse_struct_members` は呼び出し側に委ねる関数(典型的には
887    /// `crate::parser::parse_struct_members_from_tokens_ref` をラップしたもの)。
888    /// これは `FieldsDict` が `Preprocessor` への直接依存を避けるため。
889    pub fn build_common_macro_fields<F>(
890        &mut self,
891        macro_bodies: &[(InternedStr, Vec<crate::token::Token>)],
892        mut parse_struct_members: F,
893    ) where
894        F: FnMut(Vec<crate::token::Token>) -> Result<Vec<StructMember>, crate::error::CompileError>,
895    {
896        for (macro_name, body) in macro_bodies {
897            let members = match parse_struct_members(body.clone()) {
898                Ok(m) => m,
899                Err(_) => continue, // 解析失敗は黙殺
900            };
901            let mut fields = Vec::new();
902            for member in &members {
903                Self::collect_common_fields_from_member(member, CommonFieldOrigin::Direct, &mut fields);
904            }
905            for f in &fields {
906                self.field_to_defining_macro.insert(f.name, *macro_name);
907            }
908            self.common_macros.insert(
909                *macro_name,
910                CommonFieldMacro { name: *macro_name, fields },
911            );
912        }
913    }
914
915    /// `StructMember` から `CommonField` を抽出(無名 union/struct を再帰)
916    fn collect_common_fields_from_member(
917        member: &StructMember,
918        outer_origin: CommonFieldOrigin,
919        out: &mut Vec<CommonField>,
920    ) {
921        // 直下の declarator を見る
922        for decl in &member.declarators {
923            let Some(declarator) = decl.declarator.as_ref() else { continue };
924            let Some(field_name) = declarator.name else { continue };
925            let is_fn_pointer = is_fn_pointer_declarator(&declarator.derived);
926            out.push(CommonField {
927                name: field_name,
928                is_fn_pointer,
929                origin: outer_origin.clone(),
930            });
931
932            // この declarator が無名 union/struct の名前なら、その中身も収集する
933            // (例: `union { ... } xcv_root_u` の `xcv_root_u`)
934            for type_spec in &member.specs.type_specs {
935                let nested = match type_spec {
936                    TypeSpec::Struct(s) | TypeSpec::Union(s) => s,
937                    _ => continue,
938                };
939                if nested.name.is_some() {
940                    continue; // 名前付き struct/union(typedef 経由など)はスキップ
941                }
942                let Some(inner_members) = &nested.members else { continue };
943                for inner in inner_members {
944                    Self::collect_common_fields_from_member(
945                        inner,
946                        CommonFieldOrigin::InsideUnion { union_field: field_name },
947                        out,
948                    );
949                }
950            }
951        }
952    }
953
954    // ==================== sv_u Union Field Types ====================
955
956    /// sv_u ユニオンフィールドの型を登録
957    ///
958    /// SV ファミリー構造体に共通の sv_u union のフィールド型を登録する。
959    /// 例: svu_pv → "char*", svu_hash → "HE**"
960    pub fn register_sv_u_field(&mut self, field_name: InternedStr, c_type: String) {
961        self.sv_u_field_types.insert(field_name, c_type);
962    }
963
964    /// sv_u ユニオンフィールドの型を取得
965    ///
966    /// フィールド名から対応する C 型を返す。
967    /// 登録されていないフィールドの場合は None。
968    pub fn get_sv_u_field_type(&self, field_name: InternedStr) -> Option<&str> {
969        self.sv_u_field_types.get(&field_name).map(|s| s.as_str())
970    }
971
972    /// sv_u フィールド型の登録数を取得
973    pub fn sv_u_field_types_count(&self) -> usize {
974        self.sv_u_field_types.len()
975    }
976
977    // ==================== Consistent Type Cache ====================
978
979    /// 一致型キャッシュを構築
980    ///
981    /// 全フィールドについて、全バリアントで型が一致するかを事前計算する。
982    /// パース完了後、型推論前に1回呼び出す。
983    pub fn build_consistent_type_cache(&mut self, interner: &StringInterner) {
984        self.consistent_type_cache.clear();
985
986        // field_to_structs を先にクローンして borrow を分離
987        let field_structs: Vec<_> = self.field_to_structs.iter()
988            .map(|(&k, v)| (k, v.clone()))
989            .collect();
990
991        for (field_name, structs) in field_structs {
992            let consistent_type = self.compute_consistent_type(field_name, &structs, interner);
993            self.consistent_type_cache.insert(field_name, consistent_type);
994        }
995    }
996
997    /// 一致型を計算(内部用)
998    ///
999    /// TypeRepr を保持しつつ、型の比較には to_rust_string() を使用する
1000    /// (source が異なっても型が同じなら一致とみなす)
1001    fn compute_consistent_type(
1002        &self,
1003        field_name: InternedStr,
1004        structs: &HashSet<InternedStr>,
1005        interner: &StringInterner,
1006    ) -> Option<TypeRepr> {
1007        if structs.is_empty() {
1008            return None;
1009        }
1010
1011        let mut first_type: Option<(&TypeRepr, String)> = None;
1012
1013        for struct_name in structs {
1014            if let Some(ft) = self.field_types.get(&(*struct_name, field_name)) {
1015                let type_str = ft.type_repr.to_rust_string(interner);
1016                match &first_type {
1017                    None => first_type = Some((&ft.type_repr, type_str)),
1018                    Some((_, first_str)) if first_str != &type_str => return None, // 不一致
1019                    Some(_) => {} // 一致、続行
1020                }
1021            }
1022        }
1023
1024        first_type.map(|(tr, _)| tr.clone())
1025    }
1026
1027    /// キャッシュから一致型を取得(O(1))
1028    ///
1029    /// フィールドが全バリアントで同じ型を持つ場合、その型を返す。
1030    /// 型が不一致、またはフィールドが存在しない場合は None。
1031    pub fn get_consistent_field_type(&self, field_name: InternedStr) -> Option<&TypeRepr> {
1032        self.consistent_type_cache
1033            .get(&field_name)
1034            .and_then(|opt| opt.as_ref())
1035    }
1036
1037    // ==================== Dump and Debug ====================
1038
1039    /// 辞書をダンプ
1040    pub fn dump(&self, interner: &StringInterner) -> String {
1041        let mut result = String::new();
1042
1043        // フィールド名でソートして出力
1044        let mut entries: Vec<_> = self.field_to_structs.iter().collect();
1045        entries.sort_by_key(|(field, _)| interner.get(**field));
1046
1047        for (field_name, struct_names) in entries {
1048            let field_str = interner.get(*field_name);
1049
1050            // 構造体名もソート
1051            let mut struct_strs: Vec<_> = struct_names
1052                .iter()
1053                .map(|s| interner.get(*s))
1054                .collect();
1055            struct_strs.sort();
1056
1057            result.push_str(&format!(
1058                "{} -> {}\n",
1059                field_str,
1060                struct_strs.join(", ")
1061            ));
1062        }
1063
1064        result
1065    }
1066
1067    /// 一意なフィールドのみをダンプ
1068    pub fn dump_unique(&self, interner: &StringInterner) -> String {
1069        let mut result = String::new();
1070
1071        // フィールド名でソートして出力
1072        let mut entries: Vec<_> = self.field_to_structs
1073            .iter()
1074            .filter(|(_, structs)| structs.len() == 1)
1075            .collect();
1076        entries.sort_by_key(|(field, _)| interner.get(**field));
1077
1078        for (field_name, struct_names) in entries {
1079            let field_str = interner.get(*field_name);
1080            let struct_str = interner.get(*struct_names.iter().next().unwrap());
1081            result.push_str(&format!("{} -> {}\n", field_str, struct_str));
1082        }
1083
1084        result
1085    }
1086
1087    /// 統計情報を取得
1088    pub fn stats(&self) -> FieldsDictStats {
1089        let total_fields = self.field_to_structs.len();
1090        let unique_fields = self.field_to_structs
1091            .values()
1092            .filter(|s| s.len() == 1)
1093            .count();
1094        let ambiguous_fields = total_fields - unique_fields;
1095
1096        FieldsDictStats {
1097            total_fields,
1098            unique_fields,
1099            ambiguous_fields,
1100        }
1101    }
1102
1103    /// フィールド型情報をダンプ(デバッグ用)
1104    pub fn dump_field_types(&self, interner: &StringInterner) -> String {
1105        let mut result = String::new();
1106
1107        // (構造体名, フィールド名) でソートして出力
1108        let mut entries: Vec<_> = self.field_types.iter().collect();
1109        entries.sort_by_key(|((struct_name, field_name), _)| {
1110            (interner.get(*struct_name), interner.get(*field_name))
1111        });
1112
1113        for ((struct_name, field_name), field_type) in entries {
1114            let struct_str = interner.get(*struct_name);
1115            let field_str = interner.get(*field_name);
1116            let type_str = field_type.type_repr.to_rust_string(interner);
1117            result.push_str(&format!(
1118                "{}.{}: {}\n",
1119                struct_str, field_str, type_str
1120            ));
1121        }
1122
1123        result
1124    }
1125
1126    /// typedef マッピング情報をダンプ(デバッグ用)
1127    pub fn dump_typedefs(&self, interner: &StringInterner) -> String {
1128        let mut result = String::new();
1129
1130        // typedef 名でソートして出力
1131        let mut entries: Vec<_> = self.typedef_to_struct.iter().collect();
1132        entries.sort_by_key(|(typedef_name, _)| interner.get(**typedef_name));
1133
1134        for (typedef_name, struct_name) in entries {
1135            let typedef_str = interner.get(*typedef_name);
1136            let struct_str = interner.get(*struct_name);
1137            result.push_str(&format!("typedef {} = struct {}\n", typedef_str, struct_str));
1138        }
1139
1140        result
1141    }
1142}
1143
1144/// 辞書の統計情報
1145#[derive(Debug)]
1146pub struct FieldsDictStats {
1147    pub total_fields: usize,
1148    pub unique_fields: usize,
1149    pub ambiguous_fields: usize,
1150}
1151
1152#[cfg(test)]
1153mod tests {
1154    use super::*;
1155
1156    #[test]
1157    fn test_fields_dict() {
1158        // 基本的なテストは実際のパース結果で行う
1159    }
1160}