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