Skip to main content

libperl_macrogen/
type_repr.rs

1//! 型表現モジュール
2//!
3//! TypeConstraint で使用する構造化された型表現を提供する。
4//! C 型、Rust 型、推論結果を統一的に表現し、文字列ベースの型比較を排除する。
5
6use std::fmt;
7
8use crate::ast::BinOp;
9use crate::intern::InternedStr;
10
11// ============================================================================
12// TypeRepr: トップレベル型表現
13// ============================================================================
14
15/// 型表現(出所情報を含む)
16#[derive(Debug, Clone)]
17pub enum TypeRepr {
18    /// C 言語の型(CHeader, Apidoc, InlineFn 共通)
19    CType {
20        /// 型指定子(int, char, struct X, など)
21        specs: CTypeSpecs,
22        /// 派生型(ポインタ、配列など)
23        derived: Vec<CDerivedType>,
24        /// 出所(デバッグ用)
25        source: CTypeSource,
26    },
27
28    /// Rust バインディングからの型(syn::Type 由来)
29    RustType {
30        /// 型表現
31        repr: RustTypeRepr,
32        /// 出所(関数名など)
33        source: RustTypeSource,
34    },
35
36    /// 推論で導出
37    Inferred(InferredType),
38}
39
40// ============================================================================
41// C 型の出所
42// ============================================================================
43
44/// C 型の出所
45#[derive(Debug, Clone)]
46pub enum CTypeSource {
47    /// C ヘッダーのパース結果
48    Header,
49    /// apidoc(embed.fnc 等)- 元の文字列を保持
50    Apidoc { raw: String },
51    /// inline 関数の AST
52    InlineFn { func_name: InternedStr },
53    /// parser.rs の parse_type_from_string を使用して解析
54    Parser,
55    /// フィールドアクセスからの逆推論
56    FieldInference { field_name: InternedStr },
57    /// キャスト式の型名(AST から直接変換)
58    Cast,
59    /// SV ファミリーキャストからの型推論
60    SvFamilyCast,
61    /// 共通フィールドマクロ宣言フィールドへのアクセス経路から逆推論された
62    /// SV ファミリー型(例: `xcv_gv_u` (in `_XPVCV_COMMON`) アクセス →
63    /// 引数 `cv` は `*mut CV`)。総称的な `SvFamilyCast` 由来の `*mut SV`
64    /// より優先するため、`confidence_tier` で 3 を返す。
65    CommonMacroFieldInference,
66}
67
68// ============================================================================
69// Rust 型の出所
70// ============================================================================
71
72/// Rust 型の出所
73#[derive(Debug, Clone)]
74pub enum RustTypeSource {
75    /// bindings.rs の関数引数
76    FnParam { func_name: String, param_index: usize },
77    /// bindings.rs の関数戻り値
78    FnReturn { func_name: String },
79    /// bindings.rs の定数
80    Const { const_name: String },
81    /// 文字列からパースされた型(具体的な出所は不明)
82    Parsed { raw: String },
83    /// 確定済みマクロのパラメータ型キャッシュから伝播した型。
84    /// 中身は推論結果なので確度は Tier 4 (apidoc 等の宣言情報より弱い)。
85    Propagated { raw: String },
86}
87
88// ============================================================================
89// C 型の構造化表現
90// ============================================================================
91
92/// C 型指定子(DeclSpecs から抽出)
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub enum CTypeSpecs {
95    /// void
96    Void,
97    /// char (signed: None = plain char, Some(true) = signed, Some(false) = unsigned)
98    Char { signed: Option<bool> },
99    /// 整数型
100    Int { signed: bool, size: IntSize },
101    /// float
102    Float,
103    /// double (is_long: long double かどうか)
104    Double { is_long: bool },
105    /// _Bool
106    Bool,
107    /// 構造体/共用体
108    Struct { name: Option<InternedStr>, is_union: bool },
109    /// enum
110    Enum { name: Option<InternedStr> },
111    /// typedef 名
112    TypedefName(InternedStr),
113    /// 未解決の typedef 名(interner に登録されていない場合)
114    UnknownTypedef(String),
115}
116
117/// 整数サイズ
118#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub enum IntSize {
120    /// short
121    Short,
122    /// int (default)
123    Int,
124    /// long
125    Long,
126    /// long long
127    LongLong,
128    /// __int128
129    Int128,
130}
131
132/// C 派生型
133#[derive(Debug, Clone, PartialEq, Eq)]
134pub enum CDerivedType {
135    /// ポインタ
136    Pointer {
137        is_const: bool,
138        is_volatile: bool,
139        is_restrict: bool,
140    },
141    /// 配列
142    Array { size: Option<usize> },
143    /// 関数
144    Function {
145        params: Vec<CTypeSpecs>,
146        variadic: bool,
147    },
148}
149
150// ============================================================================
151// Rust 型の構造化表現
152// ============================================================================
153
154/// Rust 型表現(syn::Type から変換)
155#[derive(Debug, Clone, PartialEq, Eq)]
156pub enum RustTypeRepr {
157    /// C互換基本型 (c_int, c_char, etc.)
158    CPrimitive(CPrimitiveKind),
159    /// Rust基本型 (i32, u64, bool, etc.)
160    RustPrimitive(RustPrimitiveKind),
161    /// ポインタ (*mut T, *const T)
162    Pointer {
163        inner: Box<RustTypeRepr>,
164        is_const: bool,
165    },
166    /// 参照 (&T, &mut T)
167    Reference {
168        inner: Box<RustTypeRepr>,
169        is_mut: bool,
170    },
171    /// 名前付き型 (SV, AV, PerlInterpreter, etc.)
172    Named(String),
173    /// Option<T>
174    Option(Box<RustTypeRepr>),
175    /// 関数ポインタ
176    FnPointer {
177        params: Vec<RustTypeRepr>,
178        ret: Option<Box<RustTypeRepr>>,
179    },
180    /// ユニット ()
181    Unit,
182    /// パース不能だった型(文字列で保持)
183    Unknown(String),
184}
185
186/// C互換基本型
187#[derive(Debug, Clone, Copy, PartialEq, Eq)]
188pub enum CPrimitiveKind {
189    CChar,
190    CSchar,
191    CUchar,
192    CShort,
193    CUshort,
194    CInt,
195    CUint,
196    CLong,
197    CUlong,
198    CLongLong,
199    CUlongLong,
200    CFloat,
201    CDouble,
202}
203
204/// Rust基本型
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206pub enum RustPrimitiveKind {
207    I8,
208    I16,
209    I32,
210    I64,
211    I128,
212    Isize,
213    U8,
214    U16,
215    U32,
216    U64,
217    U128,
218    Usize,
219    F32,
220    F64,
221    Bool,
222}
223
224// ============================================================================
225// 推論の根拠 (InferredType)
226// ============================================================================
227
228/// 推論で導出された型
229#[derive(Debug, Clone)]
230pub enum InferredType {
231    // ==================== リテラル ====================
232    /// 整数リテラル (42, 0x1F, etc.)
233    IntLiteral,
234    /// 符号なし整数リテラル (42u, etc.)
235    UIntLiteral,
236    /// 浮動小数点リテラル (3.14, etc.)
237    FloatLiteral,
238    /// 文字リテラル ('a')
239    CharLiteral,
240    /// 文字列リテラル ("hello")
241    StringLiteral,
242
243    // ==================== 識別子参照 ====================
244    /// シンボルテーブルからの参照
245    SymbolLookup {
246        name: InternedStr,
247        /// 解決された型
248        resolved_type: Box<TypeRepr>,
249    },
250    /// THX (my_perl) のデフォルト型
251    ThxDefault,
252
253    // ==================== 演算子 ====================
254    /// 二項演算の結果
255    BinaryOp {
256        op: BinOp,
257        /// 左右オペランドの型から計算された結果型
258        result_type: Box<TypeRepr>,
259    },
260    /// 単項演算 (+, -, ~)
261    UnaryArithmetic {
262        /// 内部式の型をそのまま継承
263        inner_type: Box<TypeRepr>,
264    },
265    /// 論理否定 (!) - 常に int
266    LogicalNot,
267    /// アドレス取得 (&x)
268    AddressOf { inner_type: Box<TypeRepr> },
269    /// 間接参照 (*p)
270    Dereference { pointer_type: Box<TypeRepr> },
271    /// インクリメント/デクリメント (++, --)
272    IncDec { inner_type: Box<TypeRepr> },
273
274    // ==================== メンバーアクセス ====================
275    /// 直接メンバーアクセス (expr.member)
276    MemberAccess {
277        base_type: String,
278        member: InternedStr,
279        /// 解決されたフィールド型
280        field_type: Option<Box<TypeRepr>>,
281    },
282    /// ポインタメンバーアクセス (expr->member)
283    PtrMemberAccess {
284        base_type: String,
285        member: InternedStr,
286        /// 解決されたフィールド型
287        field_type: Option<Box<TypeRepr>>,
288        /// 一致型を使用した場合(ベース型が不明時)
289        used_consistent_type: bool,
290    },
291
292    // ==================== 配列/添字 ====================
293    /// 配列添字 (arr[i])
294    ArraySubscript {
295        base_type: Box<TypeRepr>,
296        /// 要素型
297        element_type: Box<TypeRepr>,
298    },
299
300    // ==================== 条件・制御 ====================
301    /// 条件演算子 (cond ? then : else)
302    Conditional {
303        then_type: Box<TypeRepr>,
304        else_type: Box<TypeRepr>,
305        /// 計算された共通型
306        result_type: Box<TypeRepr>,
307    },
308    /// コンマ式 (a, b)
309    Comma {
310        /// 右辺の型
311        rhs_type: Box<TypeRepr>,
312    },
313    /// 代入式 (a = b)
314    Assignment {
315        /// 左辺の型
316        lhs_type: Box<TypeRepr>,
317    },
318
319    // ==================== 型操作 ====================
320    /// キャスト式 ((type)expr)
321    Cast { target_type: Box<TypeRepr> },
322    /// sizeof 式/型 - 常に unsigned long
323    Sizeof,
324    /// alignof - 常に unsigned long
325    Alignof,
326    /// 複合リテラル ((type){...})
327    CompoundLiteral { type_name: Box<TypeRepr> },
328
329    // ==================== その他 ====================
330    /// 文式 ({ ... })
331    StmtExpr {
332        /// 最後の式の型
333        last_expr_type: Option<Box<TypeRepr>>,
334    },
335    /// アサーション - 常に void
336    Assert,
337    /// 関数呼び出しの戻り値(RustBindings/Apidoc から取得できなかった場合)
338    FunctionReturn { func_name: InternedStr },
339}
340
341// ============================================================================
342// 変換関数
343// ============================================================================
344
345impl CTypeSpecs {
346    /// DeclSpecs から CTypeSpecs を抽出
347    pub fn from_decl_specs(specs: &crate::ast::DeclSpecs, _interner: &crate::intern::StringInterner) -> Self {
348        use crate::ast::TypeSpec;
349
350        let mut has_signed = false;
351        let mut has_unsigned = false;
352        let mut has_short = false;
353        let mut has_long: u8 = 0;
354        let mut base_type: Option<CTypeSpecs> = None;
355
356        for type_spec in &specs.type_specs {
357            match type_spec {
358                TypeSpec::Void => base_type = Some(CTypeSpecs::Void),
359                TypeSpec::Char => {
360                    // char の signed/unsigned は後で決定
361                    if base_type.is_none() {
362                        base_type = Some(CTypeSpecs::Char { signed: None });
363                    }
364                }
365                TypeSpec::Short => has_short = true,
366                TypeSpec::Int => {
367                    if base_type.is_none() {
368                        base_type = Some(CTypeSpecs::Int {
369                            signed: true,
370                            size: IntSize::Int,
371                        });
372                    }
373                }
374                TypeSpec::Long => has_long += 1,
375                TypeSpec::Float => base_type = Some(CTypeSpecs::Float),
376                TypeSpec::Double => base_type = Some(CTypeSpecs::Double { is_long: false }),
377                TypeSpec::Signed => has_signed = true,
378                TypeSpec::Unsigned => has_unsigned = true,
379                TypeSpec::Bool => base_type = Some(CTypeSpecs::Bool),
380                TypeSpec::Int128 => {
381                    base_type = Some(CTypeSpecs::Int {
382                        signed: !has_unsigned,
383                        size: IntSize::Int128,
384                    });
385                }
386                TypeSpec::Struct(s) => {
387                    base_type = Some(CTypeSpecs::Struct {
388                        name: s.name,
389                        is_union: false,
390                    });
391                }
392                TypeSpec::Union(s) => {
393                    base_type = Some(CTypeSpecs::Struct {
394                        name: s.name,
395                        is_union: true,
396                    });
397                }
398                TypeSpec::Enum(e) => {
399                    base_type = Some(CTypeSpecs::Enum { name: e.name });
400                }
401                TypeSpec::TypedefName(name) => {
402                    base_type = Some(CTypeSpecs::TypedefName(*name));
403                }
404                _ => {}
405            }
406        }
407
408        // signed/unsigned と short/long の組み合わせを処理
409        if has_short {
410            return CTypeSpecs::Int {
411                signed: !has_unsigned,
412                size: IntSize::Short,
413            };
414        }
415
416        if has_long >= 2 {
417            return CTypeSpecs::Int {
418                signed: !has_unsigned,
419                size: IntSize::LongLong,
420            };
421        }
422
423        if has_long == 1 {
424            if let Some(CTypeSpecs::Double { .. }) = base_type {
425                return CTypeSpecs::Double { is_long: true };
426            }
427            return CTypeSpecs::Int {
428                signed: !has_unsigned,
429                size: IntSize::Long,
430            };
431        }
432
433        // char の signed/unsigned を確定
434        if let Some(CTypeSpecs::Char { .. }) = base_type {
435            if has_signed {
436                return CTypeSpecs::Char { signed: Some(true) };
437            } else if has_unsigned {
438                return CTypeSpecs::Char { signed: Some(false) };
439            }
440            return CTypeSpecs::Char { signed: None };
441        }
442
443        // 単独の signed/unsigned
444        if has_unsigned && base_type.is_none() {
445            return CTypeSpecs::Int {
446                signed: false,
447                size: IntSize::Int,
448            };
449        }
450        if has_signed && base_type.is_none() {
451            return CTypeSpecs::Int {
452                signed: true,
453                size: IntSize::Int,
454            };
455        }
456
457        // int の unsigned
458        if has_unsigned {
459            if let Some(CTypeSpecs::Int { size, .. }) = base_type {
460                return CTypeSpecs::Int {
461                    signed: false,
462                    size,
463                };
464            }
465        }
466
467        base_type.unwrap_or(CTypeSpecs::Int {
468            signed: true,
469            size: IntSize::Int,
470        })
471    }
472}
473
474impl CDerivedType {
475    /// DerivedDecl のリストから CDerivedType のリストを作成
476    pub fn from_derived_decls(derived: &[crate::ast::DerivedDecl]) -> Vec<Self> {
477        use crate::ast::ExprKind;
478
479        derived
480            .iter()
481            .map(|d| match d {
482                crate::ast::DerivedDecl::Pointer(quals) => CDerivedType::Pointer {
483                    is_const: quals.is_const,
484                    is_volatile: quals.is_volatile,
485                    is_restrict: quals.is_restrict,
486                },
487                crate::ast::DerivedDecl::Array(array_decl) => {
488                    // 配列サイズが定数リテラルの場合のみ抽出
489                    let size = array_decl.size.as_ref().and_then(|expr| {
490                        match &expr.kind {
491                            ExprKind::IntLit(n) => Some(*n as usize),
492                            ExprKind::UIntLit(n) => Some(*n as usize),
493                            _ => None,
494                        }
495                    });
496                    CDerivedType::Array { size }
497                }
498                crate::ast::DerivedDecl::Function(_params) => {
499                    // 関数パラメータの詳細は簡略化
500                    CDerivedType::Function {
501                        params: vec![],
502                        variadic: false,
503                    }
504                }
505            })
506            .collect()
507    }
508}
509
510impl RustTypeRepr {
511    /// 型文字列から RustTypeRepr をパース
512    pub fn from_type_string(s: &str) -> Self {
513        let s = s.trim();
514
515        // ユニット型
516        if s == "()" {
517            return RustTypeRepr::Unit;
518        }
519
520        // ポインタ型
521        if let Some(rest) = s.strip_prefix("*mut ") {
522            return RustTypeRepr::Pointer {
523                inner: Box::new(Self::from_type_string(rest)),
524                is_const: false,
525            };
526        }
527        if let Some(rest) = s.strip_prefix("* mut ") {
528            return RustTypeRepr::Pointer {
529                inner: Box::new(Self::from_type_string(rest)),
530                is_const: false,
531            };
532        }
533        if let Some(rest) = s.strip_prefix("*const ") {
534            return RustTypeRepr::Pointer {
535                inner: Box::new(Self::from_type_string(rest)),
536                is_const: true,
537            };
538        }
539        if let Some(rest) = s.strip_prefix("* const ") {
540            return RustTypeRepr::Pointer {
541                inner: Box::new(Self::from_type_string(rest)),
542                is_const: true,
543            };
544        }
545
546        // 参照型
547        if let Some(rest) = s.strip_prefix("&mut ") {
548            return RustTypeRepr::Reference {
549                inner: Box::new(Self::from_type_string(rest)),
550                is_mut: true,
551            };
552        }
553        if let Some(rest) = s.strip_prefix("& mut ") {
554            return RustTypeRepr::Reference {
555                inner: Box::new(Self::from_type_string(rest)),
556                is_mut: true,
557            };
558        }
559        if let Some(rest) = s.strip_prefix('&') {
560            return RustTypeRepr::Reference {
561                inner: Box::new(Self::from_type_string(rest.trim())),
562                is_mut: false,
563            };
564        }
565
566        // C 互換基本型
567        if let Some(kind) = Self::parse_c_primitive(s) {
568            return RustTypeRepr::CPrimitive(kind);
569        }
570
571        // Rust 基本型
572        if let Some(kind) = Self::parse_rust_primitive(s) {
573            return RustTypeRepr::RustPrimitive(kind);
574        }
575
576        // Option<T>
577        if s.starts_with("Option<") || s.starts_with(":: std :: option :: Option<") {
578            if let Some(inner) = Self::extract_generic_param(s, "Option") {
579                return RustTypeRepr::Option(Box::new(Self::from_type_string(&inner)));
580            }
581        }
582
583        // 名前付き型(識別子)
584        if s.chars().next().map(|c| c.is_alphabetic() || c == '_').unwrap_or(false) {
585            // パスセパレータを含む場合は最後の部分を使用
586            let name = s.split("::").last().unwrap_or(s).trim();
587            return RustTypeRepr::Named(name.to_string());
588        }
589
590        // パース不能
591        RustTypeRepr::Unknown(s.to_string())
592    }
593
594    /// C 互換基本型をパース
595    fn parse_c_primitive(s: &str) -> Option<CPrimitiveKind> {
596        // :: std :: os :: raw :: c_* 形式にも対応
597        let s = s.trim();
598        let name = if s.contains("::") {
599            s.split("::").last()?.trim()
600        } else {
601            s
602        };
603
604        match name {
605            "c_char" => Some(CPrimitiveKind::CChar),
606            "c_schar" => Some(CPrimitiveKind::CSchar),
607            "c_uchar" => Some(CPrimitiveKind::CUchar),
608            "c_short" => Some(CPrimitiveKind::CShort),
609            "c_ushort" => Some(CPrimitiveKind::CUshort),
610            "c_int" => Some(CPrimitiveKind::CInt),
611            "c_uint" => Some(CPrimitiveKind::CUint),
612            "c_long" => Some(CPrimitiveKind::CLong),
613            "c_ulong" => Some(CPrimitiveKind::CUlong),
614            "c_longlong" => Some(CPrimitiveKind::CLongLong),
615            "c_ulonglong" => Some(CPrimitiveKind::CUlongLong),
616            "c_float" => Some(CPrimitiveKind::CFloat),
617            "c_double" => Some(CPrimitiveKind::CDouble),
618            _ => None,
619        }
620    }
621
622    /// Rust 基本型をパース
623    fn parse_rust_primitive(s: &str) -> Option<RustPrimitiveKind> {
624        match s.trim() {
625            "i8" => Some(RustPrimitiveKind::I8),
626            "i16" => Some(RustPrimitiveKind::I16),
627            "i32" => Some(RustPrimitiveKind::I32),
628            "i64" => Some(RustPrimitiveKind::I64),
629            "i128" => Some(RustPrimitiveKind::I128),
630            "isize" => Some(RustPrimitiveKind::Isize),
631            "u8" => Some(RustPrimitiveKind::U8),
632            "u16" => Some(RustPrimitiveKind::U16),
633            "u32" => Some(RustPrimitiveKind::U32),
634            "u64" => Some(RustPrimitiveKind::U64),
635            "u128" => Some(RustPrimitiveKind::U128),
636            "usize" => Some(RustPrimitiveKind::Usize),
637            "f32" => Some(RustPrimitiveKind::F32),
638            "f64" => Some(RustPrimitiveKind::F64),
639            "bool" => Some(RustPrimitiveKind::Bool),
640            _ => None,
641        }
642    }
643
644    /// ジェネリック型のパラメータを抽出
645    fn extract_generic_param(s: &str, type_name: &str) -> Option<String> {
646        // "Option<T>" または ":: std :: option :: Option<T>" から T を抽出
647        let start = s.find(&format!("{}<", type_name))?;
648        let after_open = start + type_name.len() + 1;
649        let content = &s[after_open..];
650
651        // 対応する > を探す(ネストを考慮)
652        let mut depth = 1;
653        let mut end = 0;
654        for (i, c) in content.char_indices() {
655            match c {
656                '<' => depth += 1,
657                '>' => {
658                    depth -= 1;
659                    if depth == 0 {
660                        end = i;
661                        break;
662                    }
663                }
664                _ => {}
665            }
666        }
667
668        if end > 0 {
669            Some(content[..end].trim().to_string())
670        } else {
671            None
672        }
673    }
674}
675
676impl TypeRepr {
677    /// 出所の表示用文字列を取得
678    pub fn source_display(&self) -> &'static str {
679        match self {
680            TypeRepr::CType { source, .. } => match source {
681                CTypeSource::Header => "c-header",
682                CTypeSource::Apidoc { .. } => "apidoc",
683                CTypeSource::InlineFn { .. } => "inline-fn",
684                CTypeSource::Parser => "parser",
685                CTypeSource::FieldInference { .. } => "field-inference",
686                CTypeSource::Cast => "cast",
687                CTypeSource::SvFamilyCast => "sv-family-cast",
688                CTypeSource::CommonMacroFieldInference => "common-macro-field-inference",
689            },
690            TypeRepr::RustType { .. } => "rust-bindings",
691            TypeRepr::Inferred(_) => "inferred",
692        }
693    }
694
695    /// void 型かどうかを判定
696    ///
697    /// ポインタを含まない void 型の場合に true を返す。
698    /// `void *` は false を返す(有効なポインタ型のため)。
699    /// bindings.rs の FnParam ソースかどうか
700    pub fn is_fn_param_source(&self) -> bool {
701        matches!(self, TypeRepr::RustType { source: RustTypeSource::FnParam { .. }, .. })
702    }
703
704    /// 型情報の確度 Tier を返す
705    ///
706    /// - Tier 1: bindings.rs (bindgen生成、変更不可)
707    /// - Tier 2: C ヘッダー宣言 / inline 関数パラメータ (変更不可)
708    /// - Tier 3: apidoc (embed.fnc 等、参考情報)
709    /// - Tier 4: 推論結果 (変更可能)
710    pub fn confidence_tier(&self) -> u8 {
711        match self {
712            TypeRepr::RustType { source, .. } => match source {
713                RustTypeSource::FnParam { .. }
714                | RustTypeSource::FnReturn { .. }
715                | RustTypeSource::Const { .. } => 1,
716                RustTypeSource::Parsed { .. } => 3,
717                RustTypeSource::Propagated { .. } => 4,
718            },
719            TypeRepr::CType { source, .. } => match source {
720                CTypeSource::InlineFn { .. } | CTypeSource::Header => 2,
721                CTypeSource::Apidoc { .. }
722                | CTypeSource::CommonMacroFieldInference => 3,
723                CTypeSource::Cast
724                | CTypeSource::SvFamilyCast
725                | CTypeSource::FieldInference { .. }
726                | CTypeSource::Parser => 4,
727            },
728            TypeRepr::Inferred(_) => 4,
729        }
730    }
731
732    pub fn is_void(&self) -> bool {
733        match self {
734            TypeRepr::CType { specs, derived, .. } => {
735                // ポインタや配列がない純粋な void のみ true
736                derived.is_empty() && matches!(specs, CTypeSpecs::Void)
737            }
738            TypeRepr::RustType { repr, .. } => {
739                matches!(repr, RustTypeRepr::Unit)
740            }
741            TypeRepr::Inferred(inferred) => {
742                match inferred {
743                    InferredType::SymbolLookup { resolved_type, .. } => {
744                        resolved_type.is_void()
745                    }
746                    _ => false,
747                }
748            }
749        }
750    }
751
752    /// 最外ポインタの is_const を true に変更する
753    /// 最外ポインタの is_const を false に変更する(must-mut 用)
754    pub fn make_outer_pointer_mut(&mut self) {
755        match self {
756            TypeRepr::CType { derived, .. } => {
757                for d in derived.iter_mut().rev() {
758                    if let CDerivedType::Pointer { is_const, .. } = d {
759                        *is_const = false;
760                        return;
761                    }
762                }
763            }
764            TypeRepr::RustType { repr, .. } => {
765                if let RustTypeRepr::Pointer { is_const, .. } = repr {
766                    *is_const = false;
767                }
768            }
769            _ => {}
770        }
771    }
772
773    pub fn make_outer_pointer_const(&mut self) {
774        match self {
775            TypeRepr::CType { derived, .. } => {
776                // derived の最後(最外側)のポインタを const に
777                for d in derived.iter_mut().rev() {
778                    if let CDerivedType::Pointer { is_const, .. } = d {
779                        *is_const = true;
780                        return;
781                    }
782                }
783            }
784            TypeRepr::RustType { repr, .. } => {
785                repr.make_outer_pointer_const();
786            }
787            TypeRepr::Inferred(inferred) => {
788                match inferred {
789                    InferredType::SymbolLookup { resolved_type, .. } => {
790                        resolved_type.make_outer_pointer_const();
791                    }
792                    InferredType::Cast { target_type } => {
793                        target_type.make_outer_pointer_const();
794                    }
795                    _ => {}
796                }
797            }
798        }
799    }
800
801    /// ポインタ型かどうか (`has_outer_pointer` のエイリアス)。
802    ///
803    /// `Inferred` ラッパは `resolved_type()` を経由して中身を再帰参照する点で
804    /// `has_outer_pointer` と挙動が異なる (本メソッドは構造的「実体型」判定に
805    /// 使う)。`has_outer_pointer` 自体は既存の使用箇所が `Inferred` を別扱い
806    /// しているため挙動を変えない。
807    pub fn is_pointer_type(&self) -> bool {
808        match self {
809            TypeRepr::CType { derived, .. } => {
810                derived.iter().any(|d| matches!(d, CDerivedType::Pointer { .. }))
811            }
812            TypeRepr::RustType { repr, .. } => repr.has_outer_pointer(),
813            TypeRepr::Inferred(inferred) => inferred
814                .resolved_type()
815                .is_some_and(|t| t.is_pointer_type()),
816        }
817    }
818
819    /// `void *` / `*mut c_void` / `*const c_void` かどうかを **構造的に** 判定する。
820    ///
821    /// 文字列 `contains("void")` ではなく specs/derived の構造で判定するので、
822    /// `*mut struct void_table` のような偽陽性に引っかからない。
823    /// `Inferred` ラッパは `resolved_type()` 経由で中身を再帰参照する。
824    pub fn is_void_pointer(&self) -> bool {
825        match self {
826            TypeRepr::CType { specs, derived, .. } => {
827                derived.iter().any(|d| matches!(d, CDerivedType::Pointer { .. }))
828                    && matches!(specs, CTypeSpecs::Void)
829            }
830            TypeRepr::RustType { repr, .. } => match repr {
831                RustTypeRepr::Pointer { inner, .. } => {
832                    matches!(inner.as_ref(), RustTypeRepr::Unit)
833                        || matches!(inner.as_ref(), RustTypeRepr::Named(n) if n == "c_void")
834                }
835                _ => false,
836            },
837            TypeRepr::Inferred(inferred) => inferred
838                .resolved_type()
839                .is_some_and(|t| t.is_void_pointer()),
840        }
841    }
842
843    /// 具体的なポインタ (`void *` ではないポインタ型) かどうか
844    pub fn is_concrete_pointer(&self) -> bool {
845        self.is_pointer_type() && !self.is_void_pointer()
846    }
847
848    /// 最外ポインタを持つかどうか
849    ///
850    /// 既存呼出側の挙動を変えないため `Inferred` は false を返す
851    /// (再帰判定が必要な場合は `is_pointer_type` を使うこと)。
852    pub fn has_outer_pointer(&self) -> bool {
853        match self {
854            TypeRepr::CType { derived, .. } => {
855                derived.iter().any(|d| matches!(d, CDerivedType::Pointer { .. }))
856            }
857            TypeRepr::RustType { repr, .. } => repr.has_outer_pointer(),
858            _ => false,
859        }
860    }
861
862    /// Apidoc の型文字列から TypeRepr を作成
863    pub fn from_apidoc_string(s: &str, interner: &crate::intern::StringInterner) -> Self {
864        // C 型文字列をパース
865        let (specs, derived) = Self::parse_c_type_string(s, interner);
866        TypeRepr::CType {
867            specs,
868            derived,
869            source: CTypeSource::Apidoc { raw: s.to_string() },
870        }
871    }
872
873    /// Rust 形式の型文字列から TypeRepr を作成
874    ///
875    /// `*mut T`, `*const T`, `c_int` などの Rust 形式の型文字列をパースする。
876    /// rust_decl.rs からの型情報の読み込みに使用する。
877    pub fn from_rust_string(s: &str) -> Self {
878        let repr = RustTypeRepr::from_type_string(s);
879        TypeRepr::RustType {
880            repr,
881            source: RustTypeSource::Parsed {
882                raw: s.to_string(),
883            },
884        }
885    }
886
887    /// **伝播型用**: 確定済みマクロのパラメータ型キャッシュから取り出した
888    /// Rust 形式の型文字列をパースする。`from_rust_string` と同じ表現に
889    /// なるが、出所が推論結果であることを保持し Tier 4 として扱う
890    /// (apidoc の宣言 (Tier 3) を上書きしない)。
891    pub fn from_rust_string_propagated(s: &str) -> Self {
892        let repr = RustTypeRepr::from_type_string(s);
893        TypeRepr::RustType {
894            repr,
895            source: RustTypeSource::Propagated {
896                raw: s.to_string(),
897            },
898        }
899    }
900
901    /// **構造ベース**: `UnifiedType` から `TypeRepr` を直接構築する。
902    ///
903    /// bindings.rs (`syn::File`) → `RustField.uty` (`UnifiedType`) で得た
904    /// 構造化情報を、文字列を経由せず TypeRepr に変換する。
905    /// Pointer / Array / Named / 基本型は `CType` として表現し、
906    /// FnPtr / Verbatim / Unknown は表現できないので `RustType` の
907    /// `Unknown(canonical_string)` にフォールバックする。
908    ///
909    /// Source は `CTypeSource::Apidoc { raw }` で記録する (tier 3 相当)。
910    /// bindings は本来 tier 1 だが、本メソッドの呼出元 (anonymous union
911    /// メンバ解決) は元の C-side フィールド型を補完する用途なので、tier 3
912    /// で十分。tier 1 が必要な経路ができたら別 source variant を追加する。
913    pub fn from_unified_type(
914        ut: &crate::unified_type::UnifiedType,
915        interner: &crate::intern::StringInterner,
916    ) -> Self {
917        let raw = ut.to_rust_string();
918        if let Some((specs, derived)) = unified_to_c(ut, interner) {
919            return TypeRepr::CType {
920                specs,
921                derived,
922                source: CTypeSource::Apidoc { raw },
923            };
924        }
925        TypeRepr::RustType {
926            repr: RustTypeRepr::Unknown(raw.clone()),
927            source: RustTypeSource::Parsed { raw },
928        }
929    }
930
931    /// DeclSpecs と Declarator から TypeRepr を作成
932    ///
933    /// C ヘッダーのパース結果から直接 TypeRepr を生成する。
934    /// fields_dict.rs でのフィールド型収集に使用する。
935    pub fn from_decl(
936        specs: &crate::ast::DeclSpecs,
937        declarator: &crate::ast::Declarator,
938        _interner: &crate::intern::StringInterner,
939    ) -> Self {
940        let c_specs = CTypeSpecs::from_decl_specs(specs, _interner);
941        let derived = CDerivedType::from_derived_decls(&declarator.derived);
942        TypeRepr::CType {
943            specs: c_specs,
944            derived,
945            source: CTypeSource::Header,
946        }
947    }
948
949    /// TypeName (パーサー出力) から TypeRepr を作成
950    ///
951    /// `parser::parse_type_from_string` の結果から TypeRepr を生成する。
952    /// `from_apidoc_string` の代替として使用し、完全な C パーサーを活用する。
953    pub fn from_type_name(
954        type_name: &crate::ast::TypeName,
955        interner: &crate::intern::StringInterner,
956    ) -> Self {
957        let c_specs = CTypeSpecs::from_decl_specs(&type_name.specs, interner);
958        let derived = type_name.declarator
959            .as_ref()
960            .map(|d| CDerivedType::from_derived_decls(&d.derived))
961            .unwrap_or_default();
962        TypeRepr::CType {
963            specs: c_specs,
964            derived,
965            source: CTypeSource::Parser,
966        }
967    }
968
969    /// C 型文字列から TypeRepr を作成(パーサー版)
970    ///
971    /// `parser.rs` の `parse_type_from_string` を使用して完全な C パーサーで解析する。
972    /// `files` と `typedefs` が必要なため、`SemanticAnalyzer` など型情報が揃っている
973    /// コンテキストでの使用を推奨。
974    ///
975    /// パースに失敗した場合は `from_apidoc_string` と同じ簡易パーサーにフォールバックする。
976    pub fn from_c_type_string(
977        s: &str,
978        interner: &crate::intern::StringInterner,
979        files: &crate::source::FileRegistry,
980        typedefs: &std::collections::HashSet<crate::intern::InternedStr>,
981    ) -> Self {
982        use crate::parser::parse_type_from_string;
983
984        match parse_type_from_string(s, interner, files, typedefs) {
985            Ok(type_name) => Self::from_type_name(&type_name, interner),
986            Err(_) => {
987                // フォールバック: 既存の簡易パーサーを使用
988                let (specs, derived) = Self::parse_c_type_string(s, interner);
989                TypeRepr::CType {
990                    specs,
991                    derived,
992                    source: CTypeSource::Apidoc { raw: s.to_string() },
993                }
994            }
995        }
996    }
997
998    /// C 型文字列をパース(簡易版)
999    fn parse_c_type_string(s: &str, interner: &crate::intern::StringInterner) -> (CTypeSpecs, Vec<CDerivedType>) {
1000        let s = s.trim();
1001
1002        // Rust 形式 (`*mut T` / `*const T`) は先頭から prefix で剥がす。
1003        // bindings.rs (`RustField.ty`) 由来の文字列が経由する経路で必要。
1004        // 通常の C 形式 (`T *`) と混在しないよう、先頭プレフィクスがある間
1005        // 繰り返し処理する。
1006        let mut prefix_pointers: Vec<bool> = Vec::new(); // is_const
1007        let mut current = s;
1008        loop {
1009            if let Some(rest) = current.strip_prefix("*mut ") {
1010                prefix_pointers.push(false);
1011                current = rest.trim();
1012            } else if let Some(rest) = current.strip_prefix("*const ") {
1013                prefix_pointers.push(true);
1014                current = rest.trim();
1015            } else {
1016                break;
1017            }
1018        }
1019
1020        // ポインタ数をカウント
1021        let mut ptr_count = 0;
1022        let mut is_const = false;
1023        let mut base = current;
1024
1025        // 末尾の * をカウント
1026        while base.ends_with('*') {
1027            ptr_count += 1;
1028            base = base[..base.len() - 1].trim();
1029        }
1030
1031        // "const" をチェック
1032        if base.starts_with("const ") {
1033            is_const = true;
1034            base = base[6..].trim();
1035        }
1036        if base.ends_with(" const") {
1037            is_const = true;
1038            base = base[..base.len() - 6].trim();
1039        }
1040
1041        // 基本型をパース
1042        let specs = Self::parse_c_base_type(base, interner);
1043
1044        // 派生型を構築
1045        // 内側の Rust prefix ポインタを最初に積み、続いて C 形式 trailing
1046        // ポインタを積む。`*mut HV` (Rust) は `HV *` (C) と等価なので
1047        // 出力 derived は同じ並びになる。
1048        let mut derived: Vec<CDerivedType> = Vec::with_capacity(prefix_pointers.len() + ptr_count);
1049        for is_const_p in prefix_pointers.iter().rev() {
1050            derived.push(CDerivedType::Pointer {
1051                is_const: *is_const_p,
1052                is_volatile: false,
1053                is_restrict: false,
1054            });
1055        }
1056        for i in 0..ptr_count {
1057            derived.push(CDerivedType::Pointer {
1058                is_const: i == 0 && is_const,
1059                is_volatile: false,
1060                is_restrict: false,
1061            });
1062        }
1063
1064        (specs, derived)
1065    }
1066
1067    /// C 基本型文字列をパース
1068    fn parse_c_base_type(s: &str, interner: &crate::intern::StringInterner) -> CTypeSpecs {
1069        match s {
1070            "void" => CTypeSpecs::Void,
1071            "char" => CTypeSpecs::Char { signed: None },
1072            "signed char" => CTypeSpecs::Char { signed: Some(true) },
1073            "unsigned char" => CTypeSpecs::Char { signed: Some(false) },
1074            "short" | "short int" | "signed short" | "signed short int" => {
1075                CTypeSpecs::Int { signed: true, size: IntSize::Short }
1076            }
1077            "unsigned short" | "unsigned short int" => {
1078                CTypeSpecs::Int { signed: false, size: IntSize::Short }
1079            }
1080            "int" | "signed" | "signed int" => {
1081                CTypeSpecs::Int { signed: true, size: IntSize::Int }
1082            }
1083            "unsigned" | "unsigned int" => {
1084                CTypeSpecs::Int { signed: false, size: IntSize::Int }
1085            }
1086            "long" | "long int" | "signed long" | "signed long int" => {
1087                CTypeSpecs::Int { signed: true, size: IntSize::Long }
1088            }
1089            "unsigned long" | "unsigned long int" => {
1090                CTypeSpecs::Int { signed: false, size: IntSize::Long }
1091            }
1092            "long long" | "long long int" | "signed long long" | "signed long long int" => {
1093                CTypeSpecs::Int { signed: true, size: IntSize::LongLong }
1094            }
1095            "unsigned long long" | "unsigned long long int" => {
1096                CTypeSpecs::Int { signed: false, size: IntSize::LongLong }
1097            }
1098            "float" => CTypeSpecs::Float,
1099            "double" => CTypeSpecs::Double { is_long: false },
1100            "long double" => CTypeSpecs::Double { is_long: true },
1101            "_Bool" | "bool" => CTypeSpecs::Bool,
1102            _ => {
1103                // 構造体/共用体/typedef 名として扱う
1104                if let Some(rest) = s.strip_prefix("struct ") {
1105                    if let Some(name) = interner.lookup(rest.trim()) {
1106                        return CTypeSpecs::Struct { name: Some(name), is_union: false };
1107                    }
1108                    return CTypeSpecs::Struct { name: None, is_union: false };
1109                }
1110                if let Some(rest) = s.strip_prefix("union ") {
1111                    if let Some(name) = interner.lookup(rest.trim()) {
1112                        return CTypeSpecs::Struct { name: Some(name), is_union: true };
1113                    }
1114                    return CTypeSpecs::Struct { name: None, is_union: true };
1115                }
1116                if let Some(rest) = s.strip_prefix("enum ") {
1117                    if let Some(name) = interner.lookup(rest.trim()) {
1118                        return CTypeSpecs::Enum { name: Some(name) };
1119                    }
1120                    return CTypeSpecs::Enum { name: None };
1121                }
1122                // typedef 名
1123                if let Some(name) = interner.lookup(s) {
1124                    CTypeSpecs::TypedefName(name)
1125                } else {
1126                    // 未知の型は typedef 名として扱う(文字列で保持できないので)
1127                    // この場合は interner に登録されていないため、後で解決する必要がある
1128                    CTypeSpecs::Void // フォールバック
1129                }
1130            }
1131        }
1132    }
1133
1134    /// 後方互換: 文字列に変換(デバッグ用)
1135    pub fn to_display_string(&self, interner: &crate::intern::StringInterner) -> String {
1136        match self {
1137            TypeRepr::CType { specs, derived, .. } => {
1138                let base = specs.to_display_string(interner);
1139                let mut result = base;
1140                for d in derived {
1141                    match d {
1142                        CDerivedType::Pointer { is_const: true, .. } => result.push_str(" *const"),
1143                        CDerivedType::Pointer { .. } => result.push_str(" *"),
1144                        CDerivedType::Array { size: Some(n) } => {
1145                            result.push_str(&format!("[{}]", n));
1146                        }
1147                        CDerivedType::Array { size: None } => result.push_str("[]"),
1148                        CDerivedType::Function { .. } => result.push_str("()"),
1149                    }
1150                }
1151                result
1152            }
1153            TypeRepr::RustType { repr, .. } => repr.to_display_string(),
1154            TypeRepr::Inferred(inferred) => inferred.to_display_string(interner),
1155        }
1156    }
1157
1158    /// Rust コード生成用の型文字列に変換
1159    pub fn to_rust_string(&self, interner: &crate::intern::StringInterner) -> String {
1160        match self {
1161            TypeRepr::CType { specs, derived, .. } => {
1162                let base = specs.to_rust_string(interner);
1163                // ポインタは逆順に適用(Rustの表記に合わせる)
1164                let mut result = base;
1165                for d in derived.iter().rev() {
1166                    // void ポインタの場合は c_void を使用
1167                    if result == "()" && matches!(d, CDerivedType::Pointer { .. } | CDerivedType::Array { .. }) {
1168                        result = "c_void".to_string();
1169                    }
1170                    result = match d {
1171                        CDerivedType::Pointer { is_const: true, .. } => format!("*const {}", result),
1172                        CDerivedType::Pointer { .. } => format!("*mut {}", result),
1173                        CDerivedType::Array { size: Some(n) } => format!("[{}; {}]", result, n),
1174                        CDerivedType::Array { size: None } => format!("*mut {}", result),
1175                        CDerivedType::Function { .. } => format!("/* fn */"),
1176                    };
1177                }
1178                result
1179            }
1180            TypeRepr::RustType { repr, .. } => repr.to_display_string(),
1181            TypeRepr::Inferred(inferred) => inferred.to_rust_string(interner),
1182        }
1183    }
1184}
1185
1186// ============================================================================
1187// `UnifiedType` → `(CTypeSpecs, Vec<CDerivedType>)` 構造的変換
1188// ============================================================================
1189
1190/// `UnifiedType` を C 型表現 (specs + derived) に分解する。
1191/// FnPtr / Verbatim / Unknown は C 表現に落とせないので `None` を返す。
1192fn unified_to_c(
1193    ut: &crate::unified_type::UnifiedType,
1194    interner: &crate::intern::StringInterner,
1195) -> Option<(CTypeSpecs, Vec<CDerivedType>)> {
1196    use crate::unified_type::{UnifiedType as UT, IntSize as UIS};
1197
1198    match ut {
1199        UT::Void => Some((CTypeSpecs::Void, vec![])),
1200        UT::Bool => Some((CTypeSpecs::Bool, vec![])),
1201        UT::Char { signed } => Some((CTypeSpecs::Char { signed: *signed }, vec![])),
1202        UT::Int { signed, size } => {
1203            // UnifiedType::IntSize::Char は C の signed/unsigned char に倒す
1204            // (TypeRepr::IntSize には Char バリアントが無い)
1205            if matches!(size, UIS::Char) {
1206                return Some((CTypeSpecs::Char { signed: Some(*signed) }, vec![]));
1207            }
1208            let target = match size {
1209                UIS::Char => unreachable!(),
1210                UIS::Short => IntSize::Short,
1211                UIS::Int => IntSize::Int,
1212                UIS::Long => IntSize::Long,
1213                UIS::LongLong => IntSize::LongLong,
1214                UIS::Int128 => IntSize::Int128,
1215            };
1216            Some((CTypeSpecs::Int { signed: *signed, size: target }, vec![]))
1217        }
1218        UT::Float => Some((CTypeSpecs::Float, vec![])),
1219        UT::Double => Some((CTypeSpecs::Double { is_long: false }, vec![])),
1220        UT::LongDouble => Some((CTypeSpecs::Double { is_long: true }, vec![])),
1221        UT::Pointer { inner, is_const } => {
1222            let (specs, mut derived) = unified_to_c(inner, interner)?;
1223            // 最も外側の derived として Pointer を追加 (derived 配列は外→内順)
1224            derived.insert(
1225                0,
1226                CDerivedType::Pointer {
1227                    is_const: *is_const,
1228                    is_volatile: false,
1229                    is_restrict: false,
1230                },
1231            );
1232            Some((specs, derived))
1233        }
1234        UT::Array { inner, size } => {
1235            let (specs, mut derived) = unified_to_c(inner, interner)?;
1236            derived.insert(0, CDerivedType::Array { size: *size });
1237            Some((specs, derived))
1238        }
1239        UT::Named(name) => {
1240            let specs = match interner.lookup(name) {
1241                Some(id) => CTypeSpecs::TypedefName(id),
1242                None => CTypeSpecs::UnknownTypedef(name.clone()),
1243            };
1244            Some((specs, vec![]))
1245        }
1246        UT::FnPtr { .. } | UT::Verbatim(_) | UT::Unknown => None,
1247    }
1248}
1249
1250// ============================================================================
1251// 型名抽出メソッド(文字列ラウンドトリップ廃止用)
1252// ============================================================================
1253
1254impl TypeRepr {
1255    /// ポインタ型の参照先の構造体/typedef 名を InternedStr で取得
1256    ///
1257    /// PtrMember (->) の base 型から構造体名を抽出するために使用。
1258    /// 例: `*mut SV` → `Some(SV)`, `XPVHV *` → `Some(XPVHV)`
1259    pub fn pointee_name(&self) -> Option<InternedStr> {
1260        match self {
1261            TypeRepr::CType { specs, derived, .. } => {
1262                if derived.iter().any(|d| matches!(d, CDerivedType::Pointer { .. })) {
1263                    specs.type_name()
1264                } else {
1265                    None
1266                }
1267            }
1268            TypeRepr::RustType { repr, .. } => repr.pointee_name(),
1269            TypeRepr::Inferred(inferred) => inferred.resolved_type()?.pointee_name(),
1270        }
1271    }
1272
1273    /// 非ポインタ型の構造体/typedef 名を InternedStr で取得
1274    ///
1275    /// Member (.) の base 型から構造体名を抽出するために使用。
1276    /// 例: `union _xhvnameu` → `Some(_xhvnameu)`, `SV` → `Some(SV)`
1277    pub fn type_name(&self) -> Option<InternedStr> {
1278        match self {
1279            TypeRepr::CType { specs, .. } => specs.type_name(),
1280            TypeRepr::RustType { repr, .. } => repr.type_name(),
1281            TypeRepr::Inferred(inferred) => inferred.resolved_type()?.type_name(),
1282        }
1283    }
1284}
1285
1286impl CTypeSpecs {
1287    /// 構造体/typedef/enum 名を InternedStr で取得
1288    pub fn type_name(&self) -> Option<InternedStr> {
1289        match self {
1290            CTypeSpecs::Struct { name: Some(n), .. } => Some(*n),
1291            CTypeSpecs::TypedefName(n) => Some(*n),
1292            CTypeSpecs::Enum { name: Some(n) } => Some(*n),
1293            _ => None,
1294        }
1295    }
1296}
1297
1298impl InferredType {
1299    /// Inferred ラッパーを解決して内側の TypeRepr を返す
1300    ///
1301    /// 各 InferredType バリアントが保持する「結果の型」を取得する。
1302    /// `pointee_name()` / `type_name()` から再帰的に呼ばれる。
1303    pub fn resolved_type(&self) -> Option<&TypeRepr> {
1304        match self {
1305            InferredType::Cast { target_type } => Some(target_type),
1306            InferredType::PtrMemberAccess { field_type: Some(ft), .. } => Some(ft),
1307            InferredType::MemberAccess { field_type: Some(ft), .. } => Some(ft),
1308            InferredType::ArraySubscript { element_type, .. } => Some(element_type),
1309            InferredType::AddressOf { inner_type } => Some(inner_type),
1310            InferredType::Dereference { pointer_type } => Some(pointer_type),
1311            InferredType::SymbolLookup { resolved_type, .. } => Some(resolved_type),
1312            InferredType::IncDec { inner_type } => Some(inner_type),
1313            InferredType::Assignment { lhs_type } => Some(lhs_type),
1314            InferredType::Comma { rhs_type } => Some(rhs_type),
1315            InferredType::Conditional { result_type, .. } => Some(result_type),
1316            InferredType::BinaryOp { result_type, .. } => Some(result_type),
1317            InferredType::UnaryArithmetic { inner_type } => Some(inner_type),
1318            InferredType::CompoundLiteral { type_name } => Some(type_name),
1319            InferredType::StmtExpr { last_expr_type } => last_expr_type.as_deref(),
1320            _ => None,
1321        }
1322    }
1323}
1324
1325impl RustTypeRepr {
1326    /// ポインタ型の参照先の型名を InternedStr で取得
1327    ///
1328    /// RustTypeRepr は String ベースで型名を格納しているため、
1329    /// InternedStr の取得には interner が必要。当面は None を返す。
1330    fn pointee_name(&self) -> Option<InternedStr> {
1331        // RustTypeRepr は String ベースのため InternedStr を直接取得できない。
1332        // 将来的に RustTypeRepr 自体を InternedStr ベースに改修する際に対応する。
1333        None
1334    }
1335
1336    /// 型名を InternedStr で取得
1337    fn type_name(&self) -> Option<InternedStr> {
1338        None
1339    }
1340}
1341
1342// ============================================================================
1343// Display 実装
1344// ============================================================================
1345
1346impl CTypeSpecs {
1347    /// 表示用文字列に変換
1348    pub fn to_display_string(&self, interner: &crate::intern::StringInterner) -> String {
1349        match self {
1350            CTypeSpecs::Void => "void".to_string(),
1351            CTypeSpecs::Char { signed: None } => "char".to_string(),
1352            CTypeSpecs::Char { signed: Some(true) } => "signed char".to_string(),
1353            CTypeSpecs::Char { signed: Some(false) } => "unsigned char".to_string(),
1354            CTypeSpecs::Int { signed: true, size: IntSize::Short } => "short".to_string(),
1355            CTypeSpecs::Int { signed: false, size: IntSize::Short } => "unsigned short".to_string(),
1356            CTypeSpecs::Int { signed: true, size: IntSize::Int } => "int".to_string(),
1357            CTypeSpecs::Int { signed: false, size: IntSize::Int } => "unsigned int".to_string(),
1358            CTypeSpecs::Int { signed: true, size: IntSize::Long } => "long".to_string(),
1359            CTypeSpecs::Int { signed: false, size: IntSize::Long } => "unsigned long".to_string(),
1360            CTypeSpecs::Int { signed: true, size: IntSize::LongLong } => "long long".to_string(),
1361            CTypeSpecs::Int { signed: false, size: IntSize::LongLong } => "unsigned long long".to_string(),
1362            CTypeSpecs::Int { signed: true, size: IntSize::Int128 } => "__int128".to_string(),
1363            CTypeSpecs::Int { signed: false, size: IntSize::Int128 } => "unsigned __int128".to_string(),
1364            CTypeSpecs::Float => "float".to_string(),
1365            CTypeSpecs::Double { is_long: false } => "double".to_string(),
1366            CTypeSpecs::Double { is_long: true } => "long double".to_string(),
1367            CTypeSpecs::Bool => "_Bool".to_string(),
1368            CTypeSpecs::Struct { name: Some(n), is_union: false } => {
1369                format!("struct {}", interner.get(*n))
1370            }
1371            CTypeSpecs::Struct { name: None, is_union: false } => "struct".to_string(),
1372            CTypeSpecs::Struct { name: Some(n), is_union: true } => {
1373                format!("union {}", interner.get(*n))
1374            }
1375            CTypeSpecs::Struct { name: None, is_union: true } => "union".to_string(),
1376            CTypeSpecs::Enum { name: Some(n) } => format!("enum {}", interner.get(*n)),
1377            CTypeSpecs::Enum { name: None } => "enum".to_string(),
1378            CTypeSpecs::TypedefName(n) => interner.get(*n).to_string(),
1379            CTypeSpecs::UnknownTypedef(s) => s.clone(),
1380        }
1381    }
1382
1383    /// Rust コード生成用の型文字列に変換
1384    pub fn to_rust_string(&self, interner: &crate::intern::StringInterner) -> String {
1385        match self {
1386            CTypeSpecs::Void => "()".to_string(),
1387            CTypeSpecs::Char { signed: None } => "c_char".to_string(),
1388            CTypeSpecs::Char { signed: Some(true) } => "c_schar".to_string(),
1389            CTypeSpecs::Char { signed: Some(false) } => "c_uchar".to_string(),
1390            CTypeSpecs::Int { signed: true, size: IntSize::Short } => "c_short".to_string(),
1391            CTypeSpecs::Int { signed: false, size: IntSize::Short } => "c_ushort".to_string(),
1392            CTypeSpecs::Int { signed: true, size: IntSize::Int } => "c_int".to_string(),
1393            CTypeSpecs::Int { signed: false, size: IntSize::Int } => "c_uint".to_string(),
1394            CTypeSpecs::Int { signed: true, size: IntSize::Long } => "c_long".to_string(),
1395            CTypeSpecs::Int { signed: false, size: IntSize::Long } => "c_ulong".to_string(),
1396            CTypeSpecs::Int { signed: true, size: IntSize::LongLong } => "c_longlong".to_string(),
1397            CTypeSpecs::Int { signed: false, size: IntSize::LongLong } => "c_ulonglong".to_string(),
1398            CTypeSpecs::Int { signed: true, size: IntSize::Int128 } => "i128".to_string(),
1399            CTypeSpecs::Int { signed: false, size: IntSize::Int128 } => "u128".to_string(),
1400            CTypeSpecs::Float => "c_float".to_string(),
1401            CTypeSpecs::Double { is_long: false } => "c_double".to_string(),
1402            CTypeSpecs::Double { is_long: true } => "c_double".to_string(), // long double → c_double
1403            CTypeSpecs::Bool => "bool".to_string(),
1404            CTypeSpecs::Struct { name: Some(n), .. } => interner.get(*n).to_string(),
1405            CTypeSpecs::Struct { name: None, .. } => "/* anonymous struct */".to_string(),
1406            CTypeSpecs::Enum { name: Some(n) } => interner.get(*n).to_string(),
1407            CTypeSpecs::Enum { name: None } => "/* anonymous enum */".to_string(),
1408            CTypeSpecs::TypedefName(n) => interner.get(*n).to_string(),
1409            CTypeSpecs::UnknownTypedef(s) => s.clone(),
1410        }
1411    }
1412}
1413
1414impl RustTypeRepr {
1415    /// 最外ポインタの is_const を true に変更する
1416    pub fn make_outer_pointer_const(&mut self) {
1417        if let RustTypeRepr::Pointer { is_const, .. } = self {
1418            *is_const = true;
1419        }
1420    }
1421
1422    /// 最外ポインタを持つかどうか
1423    pub fn has_outer_pointer(&self) -> bool {
1424        matches!(self, RustTypeRepr::Pointer { .. })
1425    }
1426}
1427
1428impl RustTypeRepr {
1429    /// 表示用文字列に変換
1430    pub fn to_display_string(&self) -> String {
1431        match self {
1432            RustTypeRepr::CPrimitive(kind) => kind.to_string(),
1433            RustTypeRepr::RustPrimitive(kind) => kind.to_string(),
1434            RustTypeRepr::Pointer { inner, is_const: true } => {
1435                format!("*const {}", inner.to_display_string())
1436            }
1437            RustTypeRepr::Pointer { inner, is_const: false } => {
1438                format!("*mut {}", inner.to_display_string())
1439            }
1440            RustTypeRepr::Reference { inner, is_mut: true } => {
1441                format!("&mut {}", inner.to_display_string())
1442            }
1443            RustTypeRepr::Reference { inner, is_mut: false } => {
1444                format!("&{}", inner.to_display_string())
1445            }
1446            RustTypeRepr::Named(name) => name.clone(),
1447            RustTypeRepr::Option(inner) => format!("Option<{}>", inner.to_display_string()),
1448            RustTypeRepr::FnPointer { params, ret } => {
1449                let params_str: Vec<_> = params.iter().map(|p| p.to_display_string()).collect();
1450                let ret_str = ret
1451                    .as_ref()
1452                    .map(|r| format!(" -> {}", r.to_display_string()))
1453                    .unwrap_or_default();
1454                format!("fn({}){}", params_str.join(", "), ret_str)
1455            }
1456            RustTypeRepr::Unit => "()".to_string(),
1457            RustTypeRepr::Unknown(s) => s.clone(),
1458        }
1459    }
1460}
1461
1462impl fmt::Display for CPrimitiveKind {
1463    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1464        let s = match self {
1465            CPrimitiveKind::CChar => "c_char",
1466            CPrimitiveKind::CSchar => "c_schar",
1467            CPrimitiveKind::CUchar => "c_uchar",
1468            CPrimitiveKind::CShort => "c_short",
1469            CPrimitiveKind::CUshort => "c_ushort",
1470            CPrimitiveKind::CInt => "c_int",
1471            CPrimitiveKind::CUint => "c_uint",
1472            CPrimitiveKind::CLong => "c_long",
1473            CPrimitiveKind::CUlong => "c_ulong",
1474            CPrimitiveKind::CLongLong => "c_longlong",
1475            CPrimitiveKind::CUlongLong => "c_ulonglong",
1476            CPrimitiveKind::CFloat => "c_float",
1477            CPrimitiveKind::CDouble => "c_double",
1478        };
1479        write!(f, "{}", s)
1480    }
1481}
1482
1483impl fmt::Display for RustPrimitiveKind {
1484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1485        let s = match self {
1486            RustPrimitiveKind::I8 => "i8",
1487            RustPrimitiveKind::I16 => "i16",
1488            RustPrimitiveKind::I32 => "i32",
1489            RustPrimitiveKind::I64 => "i64",
1490            RustPrimitiveKind::I128 => "i128",
1491            RustPrimitiveKind::Isize => "isize",
1492            RustPrimitiveKind::U8 => "u8",
1493            RustPrimitiveKind::U16 => "u16",
1494            RustPrimitiveKind::U32 => "u32",
1495            RustPrimitiveKind::U64 => "u64",
1496            RustPrimitiveKind::U128 => "u128",
1497            RustPrimitiveKind::Usize => "usize",
1498            RustPrimitiveKind::F32 => "f32",
1499            RustPrimitiveKind::F64 => "f64",
1500            RustPrimitiveKind::Bool => "bool",
1501        };
1502        write!(f, "{}", s)
1503    }
1504}
1505
1506impl InferredType {
1507    /// 表示用文字列に変換
1508    pub fn to_display_string(&self, interner: &crate::intern::StringInterner) -> String {
1509        match self {
1510            InferredType::IntLiteral => "int".to_string(),
1511            InferredType::UIntLiteral => "unsigned int".to_string(),
1512            InferredType::FloatLiteral => "double".to_string(),
1513            InferredType::CharLiteral => "int".to_string(),
1514            InferredType::StringLiteral => "char *".to_string(),
1515            InferredType::SymbolLookup { resolved_type, .. } => {
1516                resolved_type.to_display_string(interner)
1517            }
1518            InferredType::ThxDefault => "*mut PerlInterpreter".to_string(),
1519            InferredType::BinaryOp { result_type, .. } => result_type.to_display_string(interner),
1520            InferredType::UnaryArithmetic { inner_type } => inner_type.to_display_string(interner),
1521            InferredType::LogicalNot => "int".to_string(),
1522            InferredType::AddressOf { inner_type } => {
1523                format!("{} *", inner_type.to_display_string(interner))
1524            }
1525            InferredType::Dereference { pointer_type } => {
1526                let s = pointer_type.to_display_string(interner);
1527                s.trim_end_matches(" *").to_string()
1528            }
1529            InferredType::IncDec { inner_type } => inner_type.to_display_string(interner),
1530            InferredType::MemberAccess { field_type: Some(ft), .. } => {
1531                ft.to_display_string(interner)
1532            }
1533            InferredType::MemberAccess { base_type, member, .. } => {
1534                format!("{}.{}", base_type, interner.get(*member))
1535            }
1536            InferredType::PtrMemberAccess { field_type: Some(ft), .. } => {
1537                ft.to_display_string(interner)
1538            }
1539            InferredType::PtrMemberAccess { base_type, member, .. } => {
1540                format!("{}->{}", base_type, interner.get(*member))
1541            }
1542            InferredType::ArraySubscript { element_type, .. } => {
1543                element_type.to_display_string(interner)
1544            }
1545            InferredType::Conditional { result_type, .. } => {
1546                result_type.to_display_string(interner)
1547            }
1548            InferredType::Comma { rhs_type } => rhs_type.to_display_string(interner),
1549            InferredType::Assignment { lhs_type } => lhs_type.to_display_string(interner),
1550            InferredType::Cast { target_type } => target_type.to_display_string(interner),
1551            InferredType::Sizeof | InferredType::Alignof => "unsigned long".to_string(),
1552            InferredType::CompoundLiteral { type_name } => type_name.to_display_string(interner),
1553            InferredType::StmtExpr { last_expr_type: Some(t) } => t.to_display_string(interner),
1554            InferredType::StmtExpr { last_expr_type: None } => "void".to_string(),
1555            InferredType::Assert => "void".to_string(),
1556            InferredType::FunctionReturn { func_name } => {
1557                format!("{}()", interner.get(*func_name))
1558            }
1559        }
1560    }
1561
1562    /// Rust コード生成用の型文字列に変換
1563    pub fn to_rust_string(&self, interner: &crate::intern::StringInterner) -> String {
1564        match self {
1565            InferredType::IntLiteral => "c_int".to_string(),
1566            InferredType::UIntLiteral => "c_uint".to_string(),
1567            InferredType::FloatLiteral => "c_double".to_string(),
1568            InferredType::CharLiteral => "c_int".to_string(),
1569            InferredType::StringLiteral => "*const c_char".to_string(),
1570            InferredType::SymbolLookup { resolved_type, .. } => {
1571                resolved_type.to_rust_string(interner)
1572            }
1573            InferredType::ThxDefault => "*mut PerlInterpreter".to_string(),
1574            InferredType::BinaryOp { result_type, .. } => result_type.to_rust_string(interner),
1575            InferredType::UnaryArithmetic { inner_type } => inner_type.to_rust_string(interner),
1576            InferredType::LogicalNot => "c_int".to_string(),
1577            InferredType::AddressOf { inner_type } => {
1578                format!("*mut {}", inner_type.to_rust_string(interner))
1579            }
1580            InferredType::Dereference { pointer_type } => {
1581                let s = pointer_type.to_rust_string(interner);
1582                // *mut T → T
1583                s.strip_prefix("*mut ").or_else(|| s.strip_prefix("*const "))
1584                    .unwrap_or(&s).to_string()
1585            }
1586            InferredType::IncDec { inner_type } => inner_type.to_rust_string(interner),
1587            InferredType::MemberAccess { field_type: Some(ft), .. } => {
1588                ft.to_rust_string(interner)
1589            }
1590            InferredType::MemberAccess { base_type, member, .. } => {
1591                format!("/* {}.{} */", base_type, interner.get(*member))
1592            }
1593            InferredType::PtrMemberAccess { field_type: Some(ft), .. } => {
1594                ft.to_rust_string(interner)
1595            }
1596            InferredType::PtrMemberAccess { base_type, member, .. } => {
1597                format!("/* {}->{} */", base_type, interner.get(*member))
1598            }
1599            InferredType::ArraySubscript { element_type, .. } => {
1600                element_type.to_rust_string(interner)
1601            }
1602            InferredType::Conditional { result_type, .. } => {
1603                result_type.to_rust_string(interner)
1604            }
1605            InferredType::Comma { rhs_type } => rhs_type.to_rust_string(interner),
1606            InferredType::Assignment { lhs_type } => lhs_type.to_rust_string(interner),
1607            InferredType::Cast { target_type } => target_type.to_rust_string(interner),
1608            InferredType::Sizeof | InferredType::Alignof => "c_ulong".to_string(),
1609            InferredType::CompoundLiteral { type_name } => type_name.to_rust_string(interner),
1610            InferredType::StmtExpr { last_expr_type: Some(t) } => t.to_rust_string(interner),
1611            InferredType::StmtExpr { last_expr_type: None } => "()".to_string(),
1612            InferredType::Assert => "()".to_string(),
1613            InferredType::FunctionReturn { func_name } => {
1614                format!("/* {}() ret */", interner.get(*func_name))
1615            }
1616        }
1617    }
1618}
1619
1620// ============================================================================
1621// テスト
1622// ============================================================================
1623
1624#[cfg(test)]
1625mod tests {
1626    use super::*;
1627
1628    #[test]
1629    fn test_rust_type_repr_from_string() {
1630        assert!(matches!(
1631            RustTypeRepr::from_type_string("c_int"),
1632            RustTypeRepr::CPrimitive(CPrimitiveKind::CInt)
1633        ));
1634
1635        assert!(matches!(
1636            RustTypeRepr::from_type_string("i32"),
1637            RustTypeRepr::RustPrimitive(RustPrimitiveKind::I32)
1638        ));
1639
1640        assert!(matches!(
1641            RustTypeRepr::from_type_string("()"),
1642            RustTypeRepr::Unit
1643        ));
1644
1645        if let RustTypeRepr::Pointer { inner, is_const: false } =
1646            RustTypeRepr::from_type_string("*mut SV")
1647        {
1648            assert!(matches!(*inner, RustTypeRepr::Named(ref n) if n == "SV"));
1649        } else {
1650            panic!("Expected *mut SV");
1651        }
1652
1653        if let RustTypeRepr::Pointer { inner, is_const: true } =
1654            RustTypeRepr::from_type_string("*const c_char")
1655        {
1656            assert!(matches!(*inner, RustTypeRepr::CPrimitive(CPrimitiveKind::CChar)));
1657        } else {
1658            panic!("Expected *const c_char");
1659        }
1660    }
1661
1662    #[test]
1663    fn test_rust_type_repr_from_string_with_spaces() {
1664        // syn の出力形式(スペースあり)
1665        if let RustTypeRepr::Pointer { inner, is_const: false } =
1666            RustTypeRepr::from_type_string("* mut SV")
1667        {
1668            assert!(matches!(*inner, RustTypeRepr::Named(ref n) if n == "SV"));
1669        } else {
1670            panic!("Expected * mut SV");
1671        }
1672    }
1673
1674    #[test]
1675    fn test_c_primitive_display() {
1676        assert_eq!(CPrimitiveKind::CInt.to_string(), "c_int");
1677        assert_eq!(CPrimitiveKind::CUlong.to_string(), "c_ulong");
1678    }
1679
1680    #[test]
1681    fn test_rust_primitive_display() {
1682        assert_eq!(RustPrimitiveKind::I32.to_string(), "i32");
1683        assert_eq!(RustPrimitiveKind::Usize.to_string(), "usize");
1684    }
1685
1686    // === Stage 5: 構造的 pointer 判定 (`is_pointer_type` / `is_void_pointer`) ===
1687
1688    fn make_void_ptr() -> TypeRepr {
1689        TypeRepr::CType {
1690            specs: CTypeSpecs::Void,
1691            derived: vec![CDerivedType::Pointer {
1692                is_const: false,
1693                is_volatile: false,
1694                is_restrict: false,
1695            }],
1696            source: CTypeSource::Apidoc { raw: "void *".to_string() },
1697        }
1698    }
1699
1700    fn make_concrete_ptr() -> TypeRepr {
1701        TypeRepr::CType {
1702            specs: CTypeSpecs::Char { signed: None },
1703            derived: vec![CDerivedType::Pointer {
1704                is_const: false,
1705                is_volatile: false,
1706                is_restrict: false,
1707            }],
1708            source: CTypeSource::Apidoc { raw: "char *".to_string() },
1709        }
1710    }
1711
1712    #[test]
1713    fn test_void_pointer_structural() {
1714        let vp = make_void_ptr();
1715        assert!(vp.is_pointer_type());
1716        assert!(vp.is_void_pointer());
1717        assert!(!vp.is_concrete_pointer());
1718    }
1719
1720    #[test]
1721    fn test_concrete_pointer_structural() {
1722        let cp = make_concrete_ptr();
1723        assert!(cp.is_pointer_type());
1724        assert!(!cp.is_void_pointer());
1725        assert!(cp.is_concrete_pointer());
1726    }
1727
1728    #[test]
1729    fn test_inferred_member_access_pointer_recursive() {
1730        // bindings.rs 経由で MemberAccess の field_type が `*mut c_char` のとき、
1731        // `is_pointer_type` は Inferred を再帰参照して true を返すべき。
1732        // (Stage 4 までの `has_outer_pointer` は false を返してしまう)
1733        let inner = make_concrete_ptr();
1734        let inferred = TypeRepr::Inferred(InferredType::MemberAccess {
1735            base_type: "xpvcv".to_string(),
1736            member: crate::intern::StringInterner::new().intern("foo"),
1737            field_type: Some(Box::new(inner)),
1738        });
1739        assert!(inferred.is_pointer_type());
1740        assert!(!inferred.is_void_pointer());
1741        assert!(inferred.is_concrete_pointer());
1742        // 一方、has_outer_pointer は既存挙動 (Inferred → false) を維持
1743        assert!(!inferred.has_outer_pointer());
1744    }
1745}