Skip to main content

libperl_macrogen/
semantic.rs

1//! 意味解析モジュール
2//!
3//! スコープ管理と型推論を行う。
4
5use std::collections::{HashMap, HashSet};
6
7use crate::apidoc::ApidocDict;
8use crate::ast::*;
9use crate::fields_dict::FieldsDict;
10use crate::inline_fn::InlineFnDict;
11use crate::intern::{InternedStr, StringInterner};
12use crate::parser::parse_type_from_string;
13use crate::rust_decl::RustDeclDict;
14use crate::source::{FileRegistry, SourceLocation};
15use crate::type_env::{TypeEnv, TypeConstraint as TypeEnvConstraint};
16use crate::type_repr::{
17    CTypeSource, CTypeSpecs, CDerivedType, InferredType,
18    RustTypeRepr, RustTypeSource, TypeRepr,
19};
20use crate::unified_type::{IntSize, UnifiedType};
21
22/// `Member` / `PtrMember` / `Deref` / `Cast` の連鎖を遡って leftmost の Ident
23/// を探す。Ident が macro params に含まれていれば `Some((name, expr_id))` を
24/// 返す。Call や Binary 等で連鎖が中断する場合は `None` を返す(誤推論を避ける)。
25///
26/// GCC StmtExpr による MUTABLE_PTR の展開
27/// `({ void *p_ = (expr); p_; })` も透過する(perl5 の MUTABLE_PTR は
28/// この形に展開されることがある)。
29fn leftmost_param_ident(
30    expr: &Expr,
31    params: &HashSet<InternedStr>,
32) -> Option<(InternedStr, ExprId)> {
33    let mut cur = expr;
34    loop {
35        match &cur.kind {
36            ExprKind::Member { expr: base, .. }
37            | ExprKind::PtrMember { expr: base, .. }
38            | ExprKind::Deref(base)
39            | ExprKind::Cast { expr: base, .. } => cur = base,
40            ExprKind::StmtExpr(compound) => {
41                if let Some(inner) = mutable_ptr_inner_expr(compound) {
42                    cur = inner;
43                } else {
44                    return None;
45                }
46            }
47            ExprKind::Ident(name) if params.contains(name) => {
48                return Some((*name, cur.id));
49            }
50            _ => return None,
51        }
52    }
53}
54
55/// `({ void *p_ = (expr); p_; })` という MUTABLE_PTR の GCC StmtExpr 展開を
56/// 検出し、内側の expr への参照を返す。`detect_mutable_ptr_pattern`
57/// (`src/rust_codegen.rs`) と同等の判定を semantic 側で行う。
58fn mutable_ptr_inner_expr(compound: &CompoundStmt) -> Option<&Expr> {
59    if compound.items.len() != 2 {
60        return None;
61    }
62    let decl = match &compound.items[0] {
63        BlockItem::Decl(d) => d,
64        _ => return None,
65    };
66    if decl.declarators.len() != 1 {
67        return None;
68    }
69    let init_decl = &decl.declarators[0];
70    let declared_name = init_decl.declarator.name?;
71    let init_expr = match init_decl.init.as_ref()? {
72        Initializer::Expr(e) => e.as_ref(),
73        _ => return None,
74    };
75    let last_expr = match &compound.items[1] {
76        BlockItem::Stmt(Stmt::Expr(Some(e), _)) => e,
77        _ => return None,
78    };
79    if let ExprKind::Ident(name) = &last_expr.kind {
80        if *name == declared_name {
81            return Some(init_expr);
82        }
83    }
84    None
85}
86
87/// `TypeRepr` が「無名 struct/union 型のフィールドそのもの」かを判定する。
88///
89/// 例: C で `union { ... } op_pmstashstartu;` のように書かれた anonymous
90/// union を fields_dict に格納すると、`CTypeSpecs::Struct { name: None,
91/// is_union: true }` で derived = [] となる。この場合
92/// `to_display_string` は `"union"` を返してしまい、後続 member access
93/// の base 型として使い物にならない。bindings.rs から bindgen 生成の
94/// named 型(例: `pmop__bindgen_ty_2`)に置き換える必要がある。
95fn is_anonymous_struct_or_union_field(t: &TypeRepr) -> bool {
96    if let TypeRepr::CType { specs, derived, .. } = t {
97        if !derived.is_empty() {
98            return false;
99        }
100        return matches!(
101            specs,
102            crate::type_repr::CTypeSpecs::Struct { name: None, .. }
103        );
104    }
105    false
106}
107
108/// `TypeRepr` から struct/union/typedef 名を文字列として取得する。
109///
110/// `TypeRepr::type_name()` は `InternedStr` を返すが、`RustTypeRepr` 側は
111/// String ベースで保持しているため常に `None` を返す。bindings.rs 由来の
112/// `RustType::Named("pmop__bindgen_ty_2")` のような名前も拾うために、
113/// 個別に String として取り出すヘルパーを提供する。
114fn extract_struct_name_str(t: &TypeRepr, interner: &crate::intern::StringInterner) -> Option<String> {
115    use crate::type_repr::{CTypeSpecs, RustTypeRepr};
116    match t {
117        TypeRepr::CType { specs, derived, .. } if derived.is_empty() => match specs {
118            CTypeSpecs::TypedefName(n) => Some(interner.get(*n).to_string()),
119            CTypeSpecs::Struct { name: Some(n), .. } => Some(interner.get(*n).to_string()),
120            _ => None,
121        },
122        TypeRepr::RustType { repr, .. } => match repr {
123            RustTypeRepr::Named(s) => Some(s.clone()),
124            _ => None,
125        },
126        TypeRepr::Inferred(inferred) => {
127            inferred.resolved_type().and_then(|t| extract_struct_name_str(t, interner))
128        }
129        _ => None,
130    }
131}
132
133/// 既存の `TypeRepr` の最も外側に Pointer derived を一段被せた新しい
134/// `TypeRepr` を返す。flexible array member (`T[1]`) を `T*` として扱う際に使う。
135/// 元が `RustType` や `Inferred` の場合はサポート外として `None` 相当ではなく
136/// 安全側で元をそのまま返す(呼び出し側は CType 由来のみ渡す想定)。
137fn wrap_with_outer_pointer(ty: TypeRepr, is_const: bool) -> TypeRepr {
138    use crate::type_repr::CDerivedType;
139    match ty {
140        TypeRepr::CType { specs, mut derived, source } => {
141            derived.push(CDerivedType::Pointer { is_const, is_volatile: false, is_restrict: false });
142            TypeRepr::CType { specs, derived, source }
143        }
144        other => other,
145    }
146}
147
148/// 型変数 ID (制約ベース型推論用)
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150pub struct TypeVar(usize);
151
152/// 型制約 (マクロ引数の型推論用)
153#[derive(Debug, Clone)]
154pub enum TypeConstraint {
155    /// 関数呼び出しの引数として使用
156    FunctionArg {
157        var: TypeVar,
158        func_name: InternedStr,
159        arg_index: usize,
160    },
161    /// フィールドアクセスの基底として使用
162    HasField {
163        var: TypeVar,
164        field: InternedStr,
165    },
166}
167
168/// 解決済み型
169#[derive(Debug, Clone, PartialEq)]
170pub enum Type {
171    /// void
172    Void,
173    /// char
174    Char,
175    /// signed char
176    SignedChar,
177    /// unsigned char
178    UnsignedChar,
179    /// short
180    Short,
181    /// unsigned short
182    UnsignedShort,
183    /// int
184    Int,
185    /// unsigned int
186    UnsignedInt,
187    /// long
188    Long,
189    /// unsigned long
190    UnsignedLong,
191    /// long long
192    LongLong,
193    /// unsigned long long
194    UnsignedLongLong,
195    /// float
196    Float,
197    /// double
198    Double,
199    /// long double
200    LongDouble,
201    /// _Bool
202    Bool,
203    /// __int128
204    Int128,
205    /// unsigned __int128
206    UnsignedInt128,
207    /// ポインタ型
208    Pointer(Box<Type>, TypeQualifiers),
209    /// 配列型
210    Array(Box<Type>, Option<usize>),
211    /// 関数型
212    Function {
213        return_type: Box<Type>,
214        params: Vec<Type>,
215        variadic: bool,
216    },
217    /// 構造体型
218    Struct {
219        name: Option<InternedStr>,
220        /// メンバー (名前, 型)
221        members: Option<Vec<(InternedStr, Type)>>,
222    },
223    /// 共用体型
224    Union {
225        name: Option<InternedStr>,
226        members: Option<Vec<(InternedStr, Type)>>,
227    },
228    /// 列挙型
229    Enum {
230        name: Option<InternedStr>,
231    },
232    /// typedef名(未解決)
233    TypedefName(InternedStr),
234    /// 不明な型(エラー時)
235    Unknown,
236}
237
238impl Type {
239    /// 型を人間が読める形式で表示
240    pub fn display(&self, interner: &StringInterner) -> String {
241        match self {
242            Type::Void => "void".to_string(),
243            Type::Char => "char".to_string(),
244            Type::SignedChar => "signed char".to_string(),
245            Type::UnsignedChar => "unsigned char".to_string(),
246            Type::Short => "short".to_string(),
247            Type::UnsignedShort => "unsigned short".to_string(),
248            Type::Int => "int".to_string(),
249            Type::UnsignedInt => "unsigned int".to_string(),
250            Type::Long => "long".to_string(),
251            Type::UnsignedLong => "unsigned long".to_string(),
252            Type::LongLong => "long long".to_string(),
253            Type::UnsignedLongLong => "unsigned long long".to_string(),
254            Type::Float => "float".to_string(),
255            Type::Double => "double".to_string(),
256            Type::LongDouble => "long double".to_string(),
257            Type::Bool => "_Bool".to_string(),
258            Type::Int128 => "__int128".to_string(),
259            Type::UnsignedInt128 => "unsigned __int128".to_string(),
260            Type::Pointer(inner, quals) => {
261                let mut s = inner.display(interner);
262                s.push('*');
263                if quals.is_const {
264                    s.push_str(" const");
265                }
266                if quals.is_volatile {
267                    s.push_str(" volatile");
268                }
269                if quals.is_restrict {
270                    s.push_str(" restrict");
271                }
272                s
273            }
274            Type::Array(inner, size) => {
275                let inner_s = inner.display(interner);
276                match size {
277                    Some(n) => format!("{}[{}]", inner_s, n),
278                    None => format!("{}[]", inner_s),
279                }
280            }
281            Type::Function { return_type, params, variadic } => {
282                let params_s: Vec<_> = params.iter()
283                    .map(|p| p.display(interner))
284                    .collect();
285                let mut s = format!("(function {} ({}))", return_type.display(interner), params_s.join(", "));
286                if *variadic {
287                    s = s.replace("))", ", ...))");
288                }
289                s
290            }
291            Type::Struct { name, .. } => {
292                match name {
293                    Some(n) => format!("struct {}", interner.get(*n)),
294                    None => "struct <anonymous>".to_string(),
295                }
296            }
297            Type::Union { name, .. } => {
298                match name {
299                    Some(n) => format!("union {}", interner.get(*n)),
300                    None => "union <anonymous>".to_string(),
301                }
302            }
303            Type::Enum { name } => {
304                match name {
305                    Some(n) => format!("enum {}", interner.get(*n)),
306                    None => "enum <anonymous>".to_string(),
307                }
308            }
309            Type::TypedefName(name) => interner.get(*name).to_string(),
310            Type::Unknown => "<unknown>".to_string(),
311        }
312    }
313
314    /// 整数型かどうか
315    pub fn is_integer(&self) -> bool {
316        matches!(
317            self,
318            Type::Char
319                | Type::SignedChar
320                | Type::UnsignedChar
321                | Type::Short
322                | Type::UnsignedShort
323                | Type::Int
324                | Type::UnsignedInt
325                | Type::Long
326                | Type::UnsignedLong
327                | Type::LongLong
328                | Type::UnsignedLongLong
329                | Type::Bool
330                | Type::Int128
331                | Type::UnsignedInt128
332                | Type::Enum { .. }
333        )
334    }
335
336    /// 浮動小数点型かどうか
337    pub fn is_floating(&self) -> bool {
338        matches!(self, Type::Float | Type::Double | Type::LongDouble)
339    }
340
341    /// 算術型かどうか
342    pub fn is_arithmetic(&self) -> bool {
343        self.is_integer() || self.is_floating()
344    }
345
346    /// ポインタ型かどうか
347    pub fn is_pointer(&self) -> bool {
348        matches!(self, Type::Pointer(_, _))
349    }
350
351    /// UnifiedType に変換
352    pub fn to_unified(&self, interner: &StringInterner) -> UnifiedType {
353        match self {
354            Type::Void => UnifiedType::Void,
355            Type::Bool => UnifiedType::Bool,
356
357            Type::Char => UnifiedType::Char { signed: None },
358            Type::SignedChar => UnifiedType::Char { signed: Some(true) },
359            Type::UnsignedChar => UnifiedType::Char { signed: Some(false) },
360
361            Type::Short => UnifiedType::Int { signed: true, size: IntSize::Short },
362            Type::UnsignedShort => UnifiedType::Int { signed: false, size: IntSize::Short },
363            Type::Int => UnifiedType::Int { signed: true, size: IntSize::Int },
364            Type::UnsignedInt => UnifiedType::Int { signed: false, size: IntSize::Int },
365            Type::Long => UnifiedType::Int { signed: true, size: IntSize::Long },
366            Type::UnsignedLong => UnifiedType::Int { signed: false, size: IntSize::Long },
367            Type::LongLong => UnifiedType::Int { signed: true, size: IntSize::LongLong },
368            Type::UnsignedLongLong => UnifiedType::Int { signed: false, size: IntSize::LongLong },
369            Type::Int128 => UnifiedType::Int { signed: true, size: IntSize::Int128 },
370            Type::UnsignedInt128 => UnifiedType::Int { signed: false, size: IntSize::Int128 },
371
372            Type::Float => UnifiedType::Float,
373            Type::Double => UnifiedType::Double,
374            Type::LongDouble => UnifiedType::LongDouble,
375
376            Type::Pointer(inner, quals) => UnifiedType::Pointer {
377                inner: Box::new(inner.to_unified(interner)),
378                is_const: quals.is_const,
379            },
380
381            Type::Array(inner, size) => UnifiedType::Array {
382                inner: Box::new(inner.to_unified(interner)),
383                size: *size,
384            },
385
386            Type::Struct { name: Some(n), .. } => {
387                UnifiedType::Named(interner.get(*n).to_string())
388            }
389            Type::Struct { name: None, .. } => UnifiedType::Unknown,
390
391            Type::Union { name: Some(n), .. } => {
392                UnifiedType::Named(interner.get(*n).to_string())
393            }
394            Type::Union { name: None, .. } => UnifiedType::Unknown,
395
396            Type::Enum { name: Some(n) } => {
397                UnifiedType::Named(interner.get(*n).to_string())
398            }
399            Type::Enum { name: None } => UnifiedType::Int { signed: true, size: IntSize::Int },
400
401            Type::TypedefName(name) => {
402                UnifiedType::Named(interner.get(*name).to_string())
403            }
404
405            Type::Function { .. } => UnifiedType::Unknown, // 関数型は未サポート
406
407            Type::Unknown => UnifiedType::Unknown,
408        }
409    }
410}
411
412/// シンボル情報
413#[derive(Debug, Clone)]
414pub struct Symbol {
415    /// 名前
416    pub name: InternedStr,
417    /// 型
418    pub ty: Type,
419    /// 定義位置
420    pub loc: SourceLocation,
421    /// シンボルの種類
422    pub kind: SymbolKind,
423}
424
425/// シンボルの種類
426#[derive(Debug, Clone, PartialEq)]
427pub enum SymbolKind {
428    /// 変数
429    Variable,
430    /// 関数
431    Function,
432    /// typedef
433    Typedef,
434    /// 列挙定数
435    EnumConstant(i64),
436}
437
438/// スコープ
439#[derive(Debug)]
440pub struct Scope {
441    /// シンボルテーブル (名前 -> シンボル)
442    symbols: HashMap<InternedStr, Symbol>,
443    /// 親スコープID (グローバルスコープはNone)
444    parent: Option<ScopeId>,
445}
446
447impl Scope {
448    fn new(parent: Option<ScopeId>) -> Self {
449        Self {
450            symbols: HashMap::new(),
451            parent,
452        }
453    }
454}
455
456/// スコープID
457#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
458pub struct ScopeId(usize);
459
460/// 意味解析器
461pub struct SemanticAnalyzer<'a> {
462    /// 文字列インターナー
463    interner: &'a StringInterner,
464    /// スコープスタック
465    scopes: Vec<Scope>,
466    /// 現在のスコープID
467    current_scope: ScopeId,
468    /// 構造体定義 (名前 -> メンバーリスト)
469    struct_defs: HashMap<InternedStr, Vec<(InternedStr, Type)>>,
470    /// 共用体定義
471    union_defs: HashMap<InternedStr, Vec<(InternedStr, Type)>>,
472    /// typedef定義 (名前 -> 型)
473    typedef_defs: HashMap<InternedStr, Type>,
474    /// Apidoc辞書(関数/マクロのシグネチャ情報)
475    apidoc: Option<&'a ApidocDict>,
476    /// フィールド辞書(構造体フィールドの型情報)
477    fields_dict: Option<&'a FieldsDict>,
478    /// RustDeclDict への参照 (bindings.rs の関数型情報)
479    rust_decl_dict: Option<&'a RustDeclDict>,
480    /// InlineFnDict への参照 (inline関数のAST情報)
481    inline_fn_dict: Option<&'a InlineFnDict>,
482    /// 型変数マップ (引数名 -> TypeVar)
483    type_vars: HashMap<InternedStr, TypeVar>,
484    /// 次の型変数ID
485    next_type_var: usize,
486    /// 収集された制約
487    constraints: Vec<TypeConstraint>,
488    /// 制約収集モードか
489    constraint_mode: bool,
490    /// マクロパラメータ名の集合(型制約収集用)
491    macro_params: HashSet<InternedStr>,
492    /// 確定済みマクロの戻り値型(マクロ名 -> 戻り値型)への参照
493    macro_return_types: Option<&'a HashMap<String, String>>,
494    /// 確定済みマクロのパラメータ型(マクロ名 -> [(パラメータ名, 型)])への参照
495    /// ネストしたマクロ呼び出しからの型伝播に使用
496    macro_param_types: Option<&'a HashMap<String, Vec<(String, String)>>>,
497    /// ファイルレジストリ(型文字列パース用)
498    files: Option<&'a FileRegistry>,
499    /// typedef 名の集合(型文字列パース用)
500    parser_typedefs: Option<&'a HashSet<InternedStr>>,
501}
502
503impl<'a> SemanticAnalyzer<'a> {
504    /// 新しい意味解析器を作成
505    pub fn new(
506        interner: &'a StringInterner,
507        apidoc: Option<&'a ApidocDict>,
508        fields_dict: Option<&'a FieldsDict>,
509    ) -> Self {
510        Self::with_rust_decl_dict(interner, apidoc, fields_dict, None, None)
511    }
512
513    /// RustDeclDict と InlineFnDict を指定して意味解析器を作成
514    pub fn with_rust_decl_dict(
515        interner: &'a StringInterner,
516        apidoc: Option<&'a ApidocDict>,
517        fields_dict: Option<&'a FieldsDict>,
518        rust_decl_dict: Option<&'a RustDeclDict>,
519        inline_fn_dict: Option<&'a InlineFnDict>,
520    ) -> Self {
521        let global_scope = Scope::new(None);
522        Self {
523            interner,
524            scopes: vec![global_scope],
525            current_scope: ScopeId(0),
526            struct_defs: HashMap::new(),
527            union_defs: HashMap::new(),
528            typedef_defs: HashMap::new(),
529            apidoc,
530            fields_dict,
531            rust_decl_dict,
532            inline_fn_dict,
533            type_vars: HashMap::new(),
534            next_type_var: 0,
535            constraints: Vec::new(),
536            constraint_mode: false,
537            macro_params: HashSet::new(),
538            macro_return_types: None,
539            macro_param_types: None,
540            files: None,
541            parser_typedefs: None,
542        }
543    }
544
545    /// 確定済みマクロの戻り値型キャッシュへの参照を設定
546    pub fn set_macro_return_types(&mut self, cache: &'a HashMap<String, String>) {
547        self.macro_return_types = Some(cache);
548    }
549
550    /// 確定済みマクロのパラメータ型キャッシュへの参照を設定
551    pub fn set_macro_param_types(&mut self, cache: &'a HashMap<String, Vec<(String, String)>>) {
552        self.macro_param_types = Some(cache);
553    }
554
555    /// マクロの戻り値型を取得
556    pub fn get_macro_return_type(&self, macro_name: &str) -> Option<&str> {
557        self.macro_return_types
558            .and_then(|cache| cache.get(macro_name))
559            .map(|s| s.as_str())
560    }
561
562    /// マクロのパラメータ型を取得
563    pub fn get_macro_param_types(&self, macro_name: &str) -> Option<&Vec<(String, String)>> {
564        self.macro_param_types
565            .and_then(|cache| cache.get(macro_name))
566    }
567
568    /// 新しいスコープを開始
569    pub fn push_scope(&mut self) {
570        let new_scope = Scope::new(Some(self.current_scope));
571        let new_id = ScopeId(self.scopes.len());
572        self.scopes.push(new_scope);
573        self.current_scope = new_id;
574    }
575
576    /// 現在のスコープを終了
577    pub fn pop_scope(&mut self) {
578        if let Some(parent) = self.scopes[self.current_scope.0].parent {
579            self.current_scope = parent;
580        }
581    }
582
583    /// シンボルを現在のスコープに追加
584    pub fn define_symbol(&mut self, symbol: Symbol) {
585        let scope = &mut self.scopes[self.current_scope.0];
586        scope.symbols.insert(symbol.name, symbol);
587    }
588
589    /// シンボルを検索(現在のスコープから親スコープへ)
590    pub fn lookup_symbol(&self, name: InternedStr) -> Option<&Symbol> {
591        let mut scope_id = Some(self.current_scope);
592        while let Some(id) = scope_id {
593            let scope = &self.scopes[id.0];
594            if let Some(sym) = scope.symbols.get(&name) {
595                return Some(sym);
596            }
597            scope_id = scope.parent;
598        }
599        None
600    }
601
602    // ========================================
603    // 制約ベース型推論 (マクロ引数用)
604    // ========================================
605
606    /// 制約収集モードを開始し、パラメータを型変数として登録
607    pub fn begin_param_inference(&mut self, params: &[InternedStr]) {
608        self.constraint_mode = true;
609        self.type_vars.clear();
610        self.constraints.clear();
611        self.next_type_var = 0;
612
613        for &param in params {
614            let var = TypeVar(self.next_type_var);
615            self.next_type_var += 1;
616            self.type_vars.insert(param, var);
617        }
618    }
619
620    /// 制約を解いて引数型を取得し、制約収集モードを終了
621    pub fn end_param_inference(&mut self) -> HashMap<InternedStr, Type> {
622        self.constraint_mode = false;
623        let solutions = self.solve_constraints();
624
625        // 型変数名から Type へのマップを構築
626        let mut result = HashMap::new();
627        for (&name, &var) in &self.type_vars {
628            if let Some(ty) = solutions.get(&var) {
629                result.insert(name, ty.clone());
630            }
631        }
632
633        // クリーンアップ
634        self.type_vars.clear();
635        self.constraints.clear();
636        self.next_type_var = 0;
637
638        result
639    }
640
641    /// 制約を解く
642    fn solve_constraints(&self) -> HashMap<TypeVar, Type> {
643        let mut solutions = HashMap::new();
644
645        for constraint in &self.constraints {
646            match constraint {
647                TypeConstraint::FunctionArg { var, func_name, arg_index } => {
648                    if solutions.contains_key(var) {
649                        continue;
650                    }
651
652                    // RustDeclDict (bindings.rs) から関数シグネチャを取得
653                    if let Some(ty) = self.lookup_rust_decl_param_type(*func_name, *arg_index) {
654                        solutions.insert(*var, ty);
655                    }
656                }
657                TypeConstraint::HasField { var, field } => {
658                    if solutions.contains_key(var) {
659                        continue;
660                    }
661
662                    // FieldsDict からフィールドを持つ構造体を特定
663                    if let Some(fields_dict) = self.fields_dict {
664                        if let Some(struct_name) = fields_dict.lookup_unique(*field) {
665                            // struct_name は既に InternedStr なので直接使用
666                            solutions.insert(
667                                *var,
668                                Type::Pointer(
669                                    Box::new(Type::TypedefName(struct_name)),
670                                    TypeQualifiers::default(),
671                                ),
672                            );
673                        }
674                    }
675                }
676            }
677        }
678
679        solutions
680    }
681
682    /// RustDeclDict から関数の引数型を取得
683    fn lookup_rust_decl_param_type(&self, func_name: InternedStr, arg_index: usize) -> Option<Type> {
684        let rust_decl_dict = self.rust_decl_dict?;
685        let func_name_str = self.interner.get(func_name);
686        let rust_fn = rust_decl_dict.fns.get(func_name_str)?;
687        let param = rust_fn.params.get(arg_index)?;
688        // Rust型文字列 (e.g., "*mut *mut SV") を Type に変換
689        Some(self.parse_rust_type_string(&param.ty))
690    }
691
692    /// InlineFnDict から inline 関数の引数型を取得
693    /// InlineFnDict から inline 関数のパラメータ型を TypeRepr として直接取得
694    ///
695    /// AST (DeclSpecs + Declarator) から TypeRepr を直接構築する。
696    /// 文字列への変換・再パースを経由しないため、修飾子付きポインタ等も正確に処理できる。
697    fn lookup_inline_fn_param_type_repr(
698        &self,
699        func_name: InternedStr,
700        arg_index: usize,
701    ) -> Option<TypeRepr> {
702        let dict = self.inline_fn_dict?;
703        let func_def = dict.get(func_name)?;
704
705        let param_list = func_def.declarator.derived.iter()
706            .find_map(|d| match d {
707                DerivedDecl::Function(params) => Some(params),
708                _ => None,
709            })?;
710
711        let param = param_list.params.get(arg_index)?;
712
713        let specs = CTypeSpecs::from_decl_specs(&param.specs, self.interner);
714        let derived = param.declarator.as_ref()
715            .map(|d| {
716                // Function 派生型より前の部分のみ(パラメータ自体の型)
717                CDerivedType::from_derived_decls(&d.derived)
718                    .into_iter()
719                    .take_while(|d| !matches!(d, CDerivedType::Function { .. }))
720                    .collect()
721            })
722            .unwrap_or_default();
723
724        Some(TypeRepr::CType {
725            specs,
726            derived,
727            source: CTypeSource::InlineFn { func_name },
728        })
729    }
730
731    /// InlineFnDict から inline 関数の戻り値型を TypeRepr として直接取得
732    fn lookup_inline_fn_return_type_repr(&self, func_name: InternedStr) -> Option<TypeRepr> {
733        let dict = self.inline_fn_dict?;
734        let func_def = dict.get(func_name)?;
735
736        let specs = CTypeSpecs::from_decl_specs(&func_def.specs, self.interner);
737
738        // Declarator の Function より前の derived 部分のみ(戻り値のポインタ等)
739        let derived: Vec<_> = CDerivedType::from_derived_decls(&func_def.declarator.derived)
740            .into_iter()
741            .take_while(|d| !matches!(d, CDerivedType::Function { .. }))
742            .collect();
743
744        Some(TypeRepr::CType {
745            specs,
746            derived,
747            source: CTypeSource::InlineFn { func_name },
748        })
749    }
750
751    /// DeclSpecs から Type を構築
752    pub fn resolve_decl_specs(&mut self, specs: &DeclSpecs) -> Type {
753        // 型指定子を集める
754        let mut is_signed = false;
755        let mut is_unsigned = false;
756        let mut is_short = false;
757        let mut is_long = 0u8; // longの個数
758        let mut base_type: Option<Type> = None;
759
760        for spec in &specs.type_specs {
761            match spec {
762                TypeSpec::Void => base_type = Some(Type::Void),
763                TypeSpec::Char => base_type = Some(Type::Char),
764                TypeSpec::Short => is_short = true,
765                TypeSpec::Int => {
766                    if base_type.is_none() {
767                        base_type = Some(Type::Int);
768                    }
769                }
770                TypeSpec::Long => is_long += 1,
771                TypeSpec::Float => base_type = Some(Type::Float),
772                TypeSpec::Double => base_type = Some(Type::Double),
773                TypeSpec::Signed => is_signed = true,
774                TypeSpec::Unsigned => is_unsigned = true,
775                TypeSpec::Bool => base_type = Some(Type::Bool),
776                TypeSpec::Int128 => base_type = Some(Type::Int128),
777                TypeSpec::Struct(s) => {
778                    let members = self.resolve_struct_members(s);
779                    if let (Some(name), Some(m)) = (s.name, &members) {
780                        self.struct_defs.insert(name, m.clone());
781                    }
782                    base_type = Some(Type::Struct {
783                        name: s.name,
784                        members,
785                    });
786                }
787                TypeSpec::Union(s) => {
788                    let members = self.resolve_struct_members(s);
789                    if let (Some(name), Some(m)) = (s.name, &members) {
790                        self.union_defs.insert(name, m.clone());
791                    }
792                    base_type = Some(Type::Union {
793                        name: s.name,
794                        members,
795                    });
796                }
797                TypeSpec::Enum(e) => {
798                    // 列挙定数を登録
799                    self.process_enum(e);
800                    base_type = Some(Type::Enum { name: e.name });
801                }
802                TypeSpec::TypedefName(name) => {
803                    // typedefを解決
804                    if let Some(ty) = self.typedef_defs.get(name) {
805                        base_type = Some(ty.clone());
806                    } else {
807                        base_type = Some(Type::TypedefName(*name));
808                    }
809                }
810                TypeSpec::TypeofExpr(_) => {
811                    // TODO: typeof式の型を推論
812                    base_type = Some(Type::Unknown);
813                }
814                _ => {}
815            }
816        }
817
818        // 型修飾子を組み合わせる
819        match (is_unsigned, is_signed, is_short, is_long, &base_type) {
820            // unsigned指定
821            (true, _, _, 0, None) | (true, _, _, 0, Some(Type::Int)) => Type::UnsignedInt,
822            (true, _, _, 1, _) => Type::UnsignedLong,
823            (true, _, _, 2, _) => Type::UnsignedLongLong,
824            (true, _, true, _, _) => Type::UnsignedShort,
825            (true, _, _, _, Some(Type::Char)) => Type::UnsignedChar,
826            (true, _, _, _, Some(Type::Int128)) => Type::UnsignedInt128,
827            // signed指定
828            (_, true, _, _, Some(Type::Char)) => Type::SignedChar,
829            // long指定
830            (_, _, _, 1, None) | (_, _, _, 1, Some(Type::Int)) => Type::Long,
831            (_, _, _, 2, _) => Type::LongLong,
832            (_, _, _, 1, Some(Type::Double)) => Type::LongDouble,
833            // short指定
834            (_, _, true, _, _) => Type::Short,
835            // デフォルト
836            _ => base_type.unwrap_or(Type::Int),
837        }
838    }
839
840    /// 構造体メンバーを解決
841    fn resolve_struct_members(&mut self, spec: &StructSpec) -> Option<Vec<(InternedStr, Type)>> {
842        spec.members.as_ref().map(|members| {
843            let mut result = Vec::new();
844            for member in members {
845                let base_ty = self.resolve_decl_specs(&member.specs);
846                for decl in &member.declarators {
847                    if let Some(ref d) = decl.declarator {
848                        if let Some(name) = d.name {
849                            let ty = self.apply_declarator(&base_ty, d);
850                            result.push((name, ty));
851                        }
852                    }
853                }
854            }
855            result
856        })
857    }
858
859    /// 列挙型を処理
860    fn process_enum(&mut self, spec: &EnumSpec) {
861        if let Some(ref enumerators) = spec.enumerators {
862            let mut value = 0i64;
863            for e in enumerators {
864                if e.value.is_some() {
865                    // TODO: 定数式を評価
866                    value = 0; // 仮
867                }
868                self.define_symbol(Symbol {
869                    name: e.name,
870                    ty: Type::Int,
871                    loc: spec.loc.clone(),
872                    kind: SymbolKind::EnumConstant(value),
873                });
874                value += 1;
875            }
876        }
877    }
878
879    /// Declarator を適用して型を構築
880    pub fn apply_declarator(&self, base_type: &Type, decl: &Declarator) -> Type {
881        let mut ty = base_type.clone();
882
883        for derived in &decl.derived {
884            ty = match derived {
885                DerivedDecl::Pointer(quals) => Type::Pointer(Box::new(ty), quals.clone()),
886                DerivedDecl::Array(arr) => {
887                    // TODO: サイズを評価
888                    let _size = &arr.size;
889                    Type::Array(Box::new(ty), None)
890                }
891                DerivedDecl::Function(params) => {
892                    let param_types: Vec<_> = params.params
893                        .iter()
894                        .map(|p| {
895                            let base = self.resolve_decl_specs_readonly(&p.specs);
896                            if let Some(ref d) = p.declarator {
897                                self.apply_declarator(&base, d)
898                            } else {
899                                base
900                            }
901                        })
902                        .collect();
903                    Type::Function {
904                        return_type: Box::new(ty),
905                        params: param_types,
906                        variadic: params.is_variadic,
907                    }
908                }
909            };
910        }
911
912        ty
913    }
914
915    /// DeclSpecs を読み取り専用で解決(再帰呼び出し用)
916    fn resolve_decl_specs_readonly(&self, specs: &DeclSpecs) -> Type {
917        // 簡略版: 主要な型のみ処理
918        let mut is_unsigned = false;
919        let mut is_long = 0u8;
920        let mut base_type: Option<Type> = None;
921
922        for spec in &specs.type_specs {
923            match spec {
924                TypeSpec::Void => base_type = Some(Type::Void),
925                TypeSpec::Char => base_type = Some(Type::Char),
926                TypeSpec::Int => base_type = Some(Type::Int),
927                TypeSpec::Long => is_long += 1,
928                TypeSpec::Float => base_type = Some(Type::Float),
929                TypeSpec::Double => base_type = Some(Type::Double),
930                TypeSpec::Unsigned => is_unsigned = true,
931                TypeSpec::Bool => base_type = Some(Type::Bool),
932                TypeSpec::TypedefName(name) => {
933                    if let Some(ty) = self.typedef_defs.get(name) {
934                        base_type = Some(ty.clone());
935                    } else {
936                        base_type = Some(Type::TypedefName(*name));
937                    }
938                }
939                _ => {}
940            }
941        }
942
943        match (is_unsigned, is_long, &base_type) {
944            (true, 0, None) | (true, 0, Some(Type::Int)) => Type::UnsignedInt,
945            (true, 1, _) => Type::UnsignedLong,
946            (_, 1, None) | (_, 1, Some(Type::Int)) => Type::Long,
947            (_, 2, _) => Type::LongLong,
948            _ => base_type.unwrap_or(Type::Int),
949        }
950    }
951
952    /// TypeName から型を解決
953    pub fn resolve_type_name(&self, type_name: &TypeName) -> Type {
954        let base_ty = self.resolve_decl_specs_readonly(&type_name.specs);
955        if let Some(ref abs_decl) = type_name.declarator {
956            self.apply_abstract_declarator(&base_ty, abs_decl)
957        } else {
958            base_ty
959        }
960    }
961
962    /// AbstractDeclarator を適用して型を構築
963    fn apply_abstract_declarator(&self, base_type: &Type, decl: &AbstractDeclarator) -> Type {
964        let mut ty = base_type.clone();
965
966        for derived in &decl.derived {
967            ty = match derived {
968                DerivedDecl::Pointer(quals) => Type::Pointer(Box::new(ty), quals.clone()),
969                DerivedDecl::Array(_) => {
970                    Type::Array(Box::new(ty), None)
971                }
972                DerivedDecl::Function(params) => {
973                    let param_types: Vec<_> = params.params
974                        .iter()
975                        .map(|p| {
976                            let base = self.resolve_decl_specs_readonly(&p.specs);
977                            if let Some(ref d) = p.declarator {
978                                self.apply_declarator(&base, d)
979                            } else {
980                                base
981                            }
982                        })
983                        .collect();
984                    Type::Function {
985                        return_type: Box::new(ty),
986                        params: param_types,
987                        variadic: params.is_variadic,
988                    }
989                }
990            };
991        }
992
993        ty
994    }
995
996    /// 宣言を処理してシンボルを登録
997    pub fn process_declaration(&mut self, decl: &Declaration) {
998        let base_ty = self.resolve_decl_specs(&decl.specs);
999
1000        // typedefの場合
1001        if decl.specs.storage == Some(StorageClass::Typedef) {
1002            for init_decl in &decl.declarators {
1003                if let Some(name) = init_decl.declarator.name {
1004                    let ty = self.apply_declarator(&base_ty, &init_decl.declarator);
1005                    self.typedef_defs.insert(name, ty);
1006                }
1007            }
1008            return;
1009        }
1010
1011        // 通常の変数宣言
1012        for init_decl in &decl.declarators {
1013            if let Some(name) = init_decl.declarator.name {
1014                let ty = self.apply_declarator(&base_ty, &init_decl.declarator);
1015                self.define_symbol(Symbol {
1016                    name,
1017                    ty,
1018                    loc: decl.loc().clone(),
1019                    kind: SymbolKind::Variable,
1020                });
1021            }
1022        }
1023    }
1024
1025    /// 関数定義を処理
1026    pub fn process_function_def(&mut self, func: &FunctionDef) {
1027        let return_ty = self.resolve_decl_specs(&func.specs);
1028        let func_ty = self.apply_declarator(&return_ty, &func.declarator);
1029
1030        // 関数をグローバルスコープに登録
1031        if let Some(name) = func.declarator.name {
1032            self.define_symbol(Symbol {
1033                name,
1034                ty: func_ty.clone(),
1035                loc: func.loc().clone(),
1036                kind: SymbolKind::Function,
1037            });
1038        }
1039
1040        // 関数本体用のスコープを開始
1041        self.push_scope();
1042
1043        // パラメータを登録
1044        if let Type::Function { params, .. } = &func_ty {
1045            for derived in &func.declarator.derived {
1046                if let DerivedDecl::Function(param_list) = derived {
1047                    for (param, param_ty) in param_list.params.iter().zip(params.iter()) {
1048                        if let Some(ref decl) = param.declarator {
1049                            if let Some(name) = decl.name {
1050                                self.define_symbol(Symbol {
1051                                    name,
1052                                    ty: param_ty.clone(),
1053                                    loc: func.loc().clone(),
1054                                    kind: SymbolKind::Variable,
1055                                });
1056                            }
1057                        }
1058                    }
1059                    break;
1060                }
1061            }
1062        }
1063
1064        // 関数本体を処理
1065        self.process_compound_stmt(&func.body);
1066
1067        self.pop_scope();
1068    }
1069
1070    /// 複合文を処理
1071    pub fn process_compound_stmt(&mut self, stmt: &CompoundStmt) {
1072        self.push_scope();
1073        for item in &stmt.items {
1074            match item {
1075                BlockItem::Decl(decl) => self.process_declaration(decl),
1076                BlockItem::Stmt(stmt) => self.process_stmt(stmt),
1077            }
1078        }
1079        self.pop_scope();
1080    }
1081
1082    /// 文を処理
1083    fn process_stmt(&mut self, stmt: &Stmt) {
1084        match stmt {
1085            Stmt::Compound(compound) => self.process_compound_stmt(compound),
1086            Stmt::For { init, .. } => {
1087                self.push_scope();
1088                if let Some(ForInit::Decl(decl)) = init {
1089                    self.process_declaration(decl);
1090                }
1091                // TODO: 本体を処理
1092                self.pop_scope();
1093            }
1094            _ => {}
1095        }
1096    }
1097
1098    // ========================================
1099    // TypeEnv への型制約収集
1100    // ========================================
1101
1102    /// マクロパラメータを設定
1103    pub fn set_macro_params(&mut self, params: &[InternedStr]) {
1104        self.macro_params.clear();
1105        for &param in params {
1106            self.macro_params.insert(param);
1107        }
1108    }
1109
1110    /// マクロパラメータをクリア
1111    pub fn clear_macro_params(&mut self) {
1112        self.macro_params.clear();
1113    }
1114
1115    /// マクロパラメータを apidoc 型情報付きでシンボルテーブルに登録
1116    ///
1117    /// # Arguments
1118    /// * `macro_name` - マクロ名
1119    /// * `params` - パラメータ名のリスト
1120    /// * `files` - ファイルレジストリ
1121    /// * `typedefs` - typedef 名セット
1122    pub fn register_macro_params_from_apidoc(
1123        &mut self,
1124        macro_name: InternedStr,
1125        params: &[InternedStr],
1126        files: &'a FileRegistry,
1127        typedefs: &'a HashSet<InternedStr>,
1128    ) {
1129        // files と typedefs を保存(後で型パース時に使用)
1130        self.files = Some(files);
1131        self.parser_typedefs = Some(typedefs);
1132
1133        // macro_params に名前を登録(既存の動作を維持)
1134        self.macro_params.clear();
1135        for &param in params {
1136            self.macro_params.insert(param);
1137        }
1138
1139        // apidoc からマクロ情報を取得
1140        let macro_name_str = self.interner.get(macro_name);
1141        if let Some(apidoc) = self.apidoc {
1142            if let Some(entry) = apidoc.get(macro_name_str) {
1143                // パラメータをシンボルとして登録
1144                for (i, &param_name) in params.iter().enumerate() {
1145                    if let Some(apidoc_arg) = entry.args.get(i) {
1146                        // parser で型文字列をパース
1147                        match parse_type_from_string(
1148                            &apidoc_arg.ty,
1149                            self.interner,
1150                            files,
1151                            typedefs,
1152                        ) {
1153                            Ok(type_name) => {
1154                                let ty = self.resolve_type_name(&type_name);
1155                                self.define_symbol(Symbol {
1156                                    name: param_name,
1157                                    ty,
1158                                    loc: SourceLocation::default(),
1159                                    kind: SymbolKind::Variable,
1160                                });
1161                            }
1162                            Err(_) => {}
1163                        }
1164                    }
1165                }
1166            }
1167        }
1168    }
1169
1170    /// C 型文字列から TypeRepr を作成
1171    ///
1172    /// `files` と `parser_typedefs` が設定されている場合は完全な C パーサーを使用。
1173    /// 設定されていない場合は簡易パーサーにフォールバック。
1174    fn parse_type_string(&self, s: &str) -> TypeRepr {
1175        if let (Some(files), Some(typedefs)) = (self.files, self.parser_typedefs) {
1176            TypeRepr::from_c_type_string(s, self.interner, files, typedefs)
1177        } else {
1178            TypeRepr::from_apidoc_string(s, self.interner)
1179        }
1180    }
1181
1182    /// 識別子がマクロパラメータかどうか
1183    fn is_macro_param(&self, name: InternedStr) -> bool {
1184        self.macro_params.contains(&name)
1185    }
1186
1187    /// *mut SV を表す TypeRepr を作成
1188    fn make_sv_ptr_type(&self) -> TypeRepr {
1189        let sv_name = self.interner.lookup("SV")
1190            .expect("SV should be interned");
1191        TypeRepr::CType {
1192            specs: CTypeSpecs::TypedefName(sv_name),
1193            derived: vec![CDerivedType::Pointer { is_const: false, is_volatile: false, is_restrict: false }],
1194            source: CTypeSource::SvFamilyCast,
1195        }
1196    }
1197
1198    /// `*mut <typedef>` 形式の SV ファミリー型を作成(共通マクロ由来、tier 3)
1199    fn make_sv_family_ptr_type(&self, typedef_name: InternedStr) -> TypeRepr {
1200        TypeRepr::CType {
1201            specs: CTypeSpecs::TypedefName(typedef_name),
1202            derived: vec![CDerivedType::Pointer { is_const: false, is_volatile: false, is_restrict: false }],
1203            source: CTypeSource::CommonMacroFieldInference,
1204        }
1205    }
1206
1207    /// 共通フィールドマクロ宣言フィールドへのアクセス経路から SV ファミリー
1208    /// パラメータ型を逆推論する。
1209    ///
1210    /// 例: `(cv)->sv_any->xcv_gv_u` の `xcv_gv_u` は `_XPVCV_COMMON` 由来 →
1211    /// 経路を辿って `cv` macro param に `*mut CV` 制約を追加。
1212    fn try_infer_sv_family_from_member(
1213        &self,
1214        member: InternedStr,
1215        base: &Expr,
1216        type_env: &mut TypeEnv,
1217    ) {
1218        let Some(fields_dict) = self.fields_dict else { return };
1219        let Some(macro_id) = fields_dict.defining_macro_of(member) else { return };
1220        let Some(sv_typedef) = fields_dict.sv_family_of_common_macro(macro_id) else { return };
1221        let Some((_param_name, param_node_id)) = leftmost_param_ident(base, &self.macro_params)
1222        else {
1223            return;
1224        };
1225        let sv_type = self.make_sv_family_ptr_type(sv_typedef);
1226        let typedef_str = self.interner.get(sv_typedef);
1227        let member_str = self.interner.get(member);
1228        type_env.add_constraint(TypeEnvConstraint::new(
1229            param_node_id,
1230            sv_type,
1231            format!("common-macro field {} implies {}*", member_str, typedef_str),
1232        ));
1233    }
1234
1235    /// type_env から式の TypeRepr を直接取得
1236    fn get_expr_type_repr(&self, expr_id: ExprId, type_env: &TypeEnv) -> Option<TypeRepr> {
1237        type_env.expr_constraints.get(&expr_id)
1238            .and_then(|c| c.first())
1239            .map(|c| c.ty.clone())
1240    }
1241
1242    /// type_env から式の TypeRepr を取得、無ければ "<unknown>" 由来の Void を返す。
1243    /// 旧 `get_expr_type_str` + `from_apidoc_string` round-trip を置き換える。
1244    /// round-trip だと RustType("*mut T" 等の Rust 表記)が C 専用パーサに
1245    /// 渡されて Void に潰れていたため、TypeRepr を直接保持することで型情報を
1246    /// 維持する。
1247    fn get_expr_type_repr_or_unknown(&self, expr_id: ExprId, type_env: &TypeEnv) -> TypeRepr {
1248        self.get_expr_type_repr(expr_id, type_env)
1249            .unwrap_or_else(|| TypeRepr::from_apidoc_string("<unknown>", self.interner))
1250    }
1251
1252    /// type_env から式の型文字列を取得
1253    fn get_expr_type_str(&self, expr_id: ExprId, type_env: &TypeEnv) -> String {
1254        if let Some(constraints) = type_env.expr_constraints.get(&expr_id) {
1255            if let Some(c) = constraints.first() {
1256                return c.ty.to_display_string(self.interner);
1257            }
1258        }
1259        "<unknown>".to_string()
1260    }
1261
1262    /// 二項演算の結果型を計算(文字列ベース)
1263    fn compute_binary_type_str(&self, op: &BinOp, lhs_id: ExprId, rhs_id: ExprId, type_env: &TypeEnv) -> String {
1264        match op {
1265            // 比較演算子・論理演算子は int を返す
1266            BinOp::Lt | BinOp::Gt | BinOp::Le | BinOp::Ge |
1267            BinOp::Eq | BinOp::Ne | BinOp::LogAnd | BinOp::LogOr => "int".to_string(),
1268            // 算術演算子は通常の型昇格
1269            _ => {
1270                let lhs_ty = self.get_expr_type_str(lhs_id, type_env);
1271                let rhs_ty = self.get_expr_type_str(rhs_id, type_env);
1272                self.usual_arithmetic_conversion_str(&lhs_ty, &rhs_ty)
1273            }
1274        }
1275    }
1276
1277    /// 通常の算術型変換(文字列ベース)
1278    fn usual_arithmetic_conversion_str(&self, lhs: &str, rhs: &str) -> String {
1279        // ポインタ型が含まれる場合はポインタ型を優先
1280        let is_ptr = |ty: &str| ty.contains('*');
1281        if is_ptr(lhs) && !is_ptr(rhs) {
1282            return lhs.to_string();
1283        }
1284        if is_ptr(rhs) && !is_ptr(lhs) {
1285            return rhs.to_string();
1286        }
1287
1288        // 簡易的な実装:ランク付けで大きい方を返す
1289        let rank = |ty: &str| -> u8 {
1290            match ty {
1291                "long double" => 10,
1292                "double" => 9,
1293                "float" => 8,
1294                "unsigned long long" => 7,
1295                "long long" => 6,
1296                "unsigned long" => 5,
1297                "long" => 4,
1298                "unsigned int" => 3,
1299                "int" => 2,
1300                "unsigned short" => 1,
1301                "short" => 1,
1302                _ => 0,
1303            }
1304        };
1305
1306        if rank(lhs) >= rank(rhs) {
1307            lhs.to_string()
1308        } else {
1309            rhs.to_string()
1310        }
1311    }
1312
1313    /// 条件演算の結果型を計算(文字列ベース)
1314    fn compute_conditional_type_str(&self, then_id: ExprId, else_id: ExprId, type_env: &TypeEnv) -> String {
1315        let then_ty = self.get_expr_type_str(then_id, type_env);
1316        let else_ty = self.get_expr_type_str(else_id, type_env);
1317        // void * vs 具体的ポインタ → 具体的な方を優先
1318        let is_void_ptr = |s: &str| s.contains("void") && s.contains('*');
1319        let is_concrete_ptr = |s: &str| !s.contains("void") && s.contains('*');
1320        if is_void_ptr(&then_ty) && is_concrete_ptr(&else_ty) {
1321            return else_ty;
1322        }
1323        if is_void_ptr(&else_ty) && is_concrete_ptr(&then_ty) {
1324            return then_ty;
1325        }
1326        self.usual_arithmetic_conversion_str(&then_ty, &else_ty)
1327    }
1328
1329    /// 文から式の型制約を収集(再帰的に走査)
1330    ///
1331    /// 文に含まれる式に対して `collect_expr_constraints` を呼び出す。
1332    pub fn collect_stmt_constraints(&mut self, stmt: &Stmt, type_env: &mut TypeEnv) {
1333        match stmt {
1334            Stmt::Compound(compound) => {
1335                for item in &compound.items {
1336                    match item {
1337                        BlockItem::Stmt(s) => self.collect_stmt_constraints(s, type_env),
1338                        BlockItem::Decl(_) => {} // 宣言は型制約収集の対象外
1339                    }
1340                }
1341            }
1342            Stmt::Expr(Some(expr), _) => {
1343                self.collect_expr_constraints(expr, type_env);
1344            }
1345            Stmt::If { cond, then_stmt, else_stmt, .. } => {
1346                self.collect_expr_constraints(cond, type_env);
1347                self.collect_stmt_constraints(then_stmt, type_env);
1348                if let Some(else_s) = else_stmt {
1349                    self.collect_stmt_constraints(else_s, type_env);
1350                }
1351            }
1352            Stmt::While { cond, body, .. } => {
1353                self.collect_expr_constraints(cond, type_env);
1354                self.collect_stmt_constraints(body, type_env);
1355            }
1356            Stmt::DoWhile { body, cond, .. } => {
1357                self.collect_stmt_constraints(body, type_env);
1358                self.collect_expr_constraints(cond, type_env);
1359            }
1360            Stmt::For { init, cond, step, body, .. } => {
1361                if let Some(ForInit::Expr(e)) = init {
1362                    self.collect_expr_constraints(e, type_env);
1363                }
1364                if let Some(c) = cond {
1365                    self.collect_expr_constraints(c, type_env);
1366                }
1367                if let Some(s) = step {
1368                    self.collect_expr_constraints(s, type_env);
1369                }
1370                self.collect_stmt_constraints(body, type_env);
1371            }
1372            Stmt::Return(Some(expr), _) => {
1373                self.collect_expr_constraints(expr, type_env);
1374            }
1375            Stmt::Switch { expr, body, .. } => {
1376                self.collect_expr_constraints(expr, type_env);
1377                self.collect_stmt_constraints(body, type_env);
1378            }
1379            Stmt::Case { expr, stmt, .. } => {
1380                self.collect_expr_constraints(expr, type_env);
1381                self.collect_stmt_constraints(stmt, type_env);
1382            }
1383            Stmt::Default { stmt, .. } | Stmt::Label { stmt, .. } => {
1384                self.collect_stmt_constraints(stmt, type_env);
1385            }
1386            _ => {} // Break, Continue, Goto, Asm, Expr(None), Return(None)
1387        }
1388    }
1389
1390    /// `c_field_type` が anonymous struct/union だった場合、bindings.rs
1391    /// (rust_decl_dict) から同じ親 struct + 同名フィールドを引いて、
1392    /// bindgen が生成した named 型 (`pmop__bindgen_ty_2` 等) で置き換える。
1393    ///
1394    /// これは perl の C ヘッダがインライン anonymous union を多用しており
1395    /// (例: `union { HV *op_pmstash; PADOFFSET op_pmstashoff; } op_pmstashstartu;`)、
1396    /// その内部メンバへの member access を解決するために必要。
1397    /// fields_dict 単体では anonymous union のフィールドを引けないが、
1398    /// bindings.rs では bindgen が `pmop__bindgen_ty_2` のような名前を
1399    /// 与えており、そこには `op_pmstash: *mut HV` 等のフィールドが
1400    /// 登録されている。
1401    /// `name` が typedef なら base struct 名へ展開する
1402    /// 例: "PMOP" → "pmop"。base が struct でない、または再帰深度
1403    /// が深すぎる場合は元の名前を返す。
1404    fn resolve_typedef_to_struct_name<'b>(&self, name: &'b str) -> std::borrow::Cow<'b, str> {
1405        let Some(rd) = self.rust_decl_dict else {
1406            return std::borrow::Cow::Borrowed(name);
1407        };
1408        let mut current = std::borrow::Cow::Borrowed(name);
1409        for _ in 0..8 {
1410            // 既に struct として登録されていれば終了
1411            if rd.structs.contains_key(current.as_ref()) {
1412                return current;
1413            }
1414            // typedef を辿る
1415            let Some(alias) = rd.types.get(current.as_ref()) else {
1416                return current;
1417            };
1418            current = std::borrow::Cow::Owned(alias.ty.clone());
1419        }
1420        current
1421    }
1422
1423    fn replace_anonymous_with_bindings(
1424        &self,
1425        parent_struct_name_str: &str,
1426        field_name_str: &str,
1427        c_field_type: TypeRepr,
1428    ) -> TypeRepr {
1429        if !is_anonymous_struct_or_union_field(&c_field_type) {
1430            return c_field_type;
1431        }
1432        let Some(rd) = self.rust_decl_dict else {
1433            return c_field_type;
1434        };
1435        let resolved = self.resolve_typedef_to_struct_name(parent_struct_name_str);
1436        let Some(rust_struct) = rd.structs.get(resolved.as_ref()) else {
1437            return c_field_type;
1438        };
1439        let Some(rust_field) = rust_struct.fields.iter().find(|f| f.name == field_name_str) else {
1440            return c_field_type;
1441        };
1442        // 構造化された RustField.uty (UnifiedType) を直接 TypeRepr に変換。
1443        // 文字列 round-trip (`from_rust_string` / `from_apidoc_string` 経由) は
1444        // prefix 剥がしの累積で破綻するため使わない。
1445        TypeRepr::from_unified_type(&rust_field.uty, self.interner)
1446    }
1447
1448    /// fields_dict (C 由来) でフィールドが見つからなかった場合の
1449    /// bindings.rs フォールバックルックアップ。bindgen 生成の anonymous
1450    /// union (`pmop__bindgen_ty_2` 等) は fields_dict には登録されない
1451    /// ため、その内部メンバアクセスはこの経路でのみ解決できる。
1452    fn lookup_field_in_bindings(
1453        &self,
1454        parent_struct_name_str: &str,
1455        field_name_str: &str,
1456    ) -> Option<TypeRepr> {
1457        let rd = self.rust_decl_dict?;
1458        let resolved = self.resolve_typedef_to_struct_name(parent_struct_name_str);
1459        let rust_struct = rd.structs.get(resolved.as_ref())?;
1460        let rust_field = rust_struct.fields.iter().find(|f| f.name == field_name_str)?;
1461        Some(TypeRepr::from_unified_type(&rust_field.uty, self.interner))
1462    }
1463
1464    /// 式全体から型制約を収集し、全式の型を計算(再帰的に走査)
1465    ///
1466    /// 子式を先に処理し、親式の型を後で計算する。
1467    pub fn collect_expr_constraints(&mut self, expr: &Expr, type_env: &mut TypeEnv) {
1468        match &expr.kind {
1469            // リテラル
1470            ExprKind::IntLit(_) => {
1471                type_env.add_constraint(TypeEnvConstraint::new(
1472                    expr.id,
1473                    TypeRepr::Inferred(InferredType::IntLiteral),
1474                    "integer literal",
1475                ));
1476            }
1477            ExprKind::UIntLit(_) => {
1478                type_env.add_constraint(TypeEnvConstraint::new(
1479                    expr.id,
1480                    TypeRepr::Inferred(InferredType::UIntLiteral),
1481                    "unsigned integer literal",
1482                ));
1483            }
1484            ExprKind::FloatLit(_) => {
1485                type_env.add_constraint(TypeEnvConstraint::new(
1486                    expr.id,
1487                    TypeRepr::Inferred(InferredType::FloatLiteral),
1488                    "float literal",
1489                ));
1490            }
1491            ExprKind::CharLit(_) => {
1492                type_env.add_constraint(TypeEnvConstraint::new(
1493                    expr.id,
1494                    TypeRepr::Inferred(InferredType::CharLiteral),
1495                    "char literal",
1496                ));
1497            }
1498            ExprKind::StringLit(_) => {
1499                type_env.add_constraint(TypeEnvConstraint::new(
1500                    expr.id,
1501                    TypeRepr::Inferred(InferredType::StringLiteral),
1502                    "string literal",
1503                ));
1504            }
1505
1506            // 識別子
1507            ExprKind::Ident(name) => {
1508                let name_str = self.interner.get(*name);
1509
1510                // シンボルテーブルから型を取得
1511                if let Some(sym) = self.lookup_symbol(*name) {
1512                    let ty_str = sym.ty.display(self.interner);
1513                    // シンボル参照を示す TypeRepr を作成
1514                    // resolved_type は文字列からパースした C 型
1515                    let resolved = TypeRepr::from_apidoc_string(&ty_str, self.interner);
1516                    type_env.add_constraint(TypeEnvConstraint::new(
1517                        expr.id,
1518                        TypeRepr::Inferred(InferredType::SymbolLookup {
1519                            name: *name,
1520                            resolved_type: Box::new(resolved),
1521                        }),
1522                        "symbol lookup",
1523                    ));
1524                // RustDeclDict から定数の型を取得
1525                } else if let Some(rust_decl_dict) = self.rust_decl_dict {
1526                    if let Some(rust_const) = rust_decl_dict.lookup_const(name_str) {
1527                        type_env.add_constraint(TypeEnvConstraint::new(
1528                            expr.id,
1529                            TypeRepr::RustType {
1530                                repr: RustTypeRepr::from_type_string(&rust_const.ty),
1531                                source: RustTypeSource::Const {
1532                                    const_name: name_str.to_string(),
1533                                },
1534                            },
1535                            "bindings constant",
1536                        ));
1537                    } else if name_str == "my_perl" {
1538                        // THX 由来の my_perl はデフォルトで *mut PerlInterpreter
1539                        type_env.add_constraint(TypeEnvConstraint::new(
1540                            expr.id,
1541                            TypeRepr::Inferred(InferredType::ThxDefault),
1542                            "THX default type",
1543                        ));
1544                    }
1545                } else if name_str == "my_perl" {
1546                    // THX 由来の my_perl はデフォルトで *mut PerlInterpreter
1547                    type_env.add_constraint(TypeEnvConstraint::new(
1548                        expr.id,
1549                        TypeRepr::Inferred(InferredType::ThxDefault),
1550                        "THX default type",
1551                    ));
1552                }
1553
1554                // パラメータ参照の場合、ExprId とパラメータを紐付け
1555                if self.is_macro_param(*name) {
1556                    type_env.link_expr_to_param(expr.id, *name, "parameter reference");
1557                }
1558            }
1559
1560            // 関数呼び出し
1561            ExprKind::Call { func, args } => {
1562                // 子式を先に処理
1563                self.collect_expr_constraints(func, type_env);
1564                for arg in args {
1565                    self.collect_expr_constraints(arg, type_env);
1566                }
1567                // Call の型制約を追加(RustDeclDict / Apidoc から)
1568                self.collect_call_constraints(expr.id, func, args, type_env);
1569            }
1570
1571            // 二項演算子
1572            ExprKind::Binary { op, lhs, rhs } => {
1573                // 子式を先に処理
1574                self.collect_expr_constraints(lhs, type_env);
1575                self.collect_expr_constraints(rhs, type_env);
1576                // 親式の型を計算
1577                let result_ty_str = self.compute_binary_type_str(op, lhs.id, rhs.id, type_env);
1578                let result_type = TypeRepr::from_apidoc_string(&result_ty_str, self.interner);
1579                type_env.add_constraint(TypeEnvConstraint::new(
1580                    expr.id,
1581                    TypeRepr::Inferred(InferredType::BinaryOp {
1582                        op: *op,
1583                        result_type: Box::new(result_type),
1584                    }),
1585                    "binary expression",
1586                ));
1587            }
1588
1589            // 条件演算子
1590            ExprKind::Conditional { cond, then_expr, else_expr } => {
1591                self.collect_expr_constraints(cond, type_env);
1592                self.collect_expr_constraints(then_expr, type_env);
1593                self.collect_expr_constraints(else_expr, type_env);
1594                let then_type = self.get_expr_type_repr_or_unknown(then_expr.id, type_env);
1595                let else_type = self.get_expr_type_repr_or_unknown(else_expr.id, type_env);
1596                // result_type は void* と具体型の選択など文字列ベースのルールが
1597                // 残っているため当面 from_apidoc_string 経由のままとする
1598                let result_ty_str = self.compute_conditional_type_str(then_expr.id, else_expr.id, type_env);
1599                let result_type = TypeRepr::from_apidoc_string(&result_ty_str, self.interner);
1600                type_env.add_constraint(TypeEnvConstraint::new(
1601                    expr.id,
1602                    TypeRepr::Inferred(InferredType::Conditional {
1603                        then_type: Box::new(then_type),
1604                        else_type: Box::new(else_type),
1605                        result_type: Box::new(result_type),
1606                    }),
1607                    "conditional expression",
1608                ));
1609            }
1610
1611            // キャスト
1612            ExprKind::Cast { type_name, expr: inner } => {
1613                self.collect_expr_constraints(inner, type_env);
1614                // AST → TypeRepr 直接変換(Type→String→TypeRepr roundtrip を排除)
1615                let specs = CTypeSpecs::from_decl_specs(&type_name.specs, self.interner);
1616                let derived: Vec<CDerivedType> = type_name.declarator.as_ref()
1617                    .map(|d| {
1618                        CDerivedType::from_derived_decls(&d.derived)
1619                            .into_iter()
1620                            .take_while(|d| !matches!(d, CDerivedType::Function { .. }))
1621                            .collect()
1622                    })
1623                    .unwrap_or_default();
1624                let target_type = TypeRepr::CType {
1625                    specs: specs.clone(),
1626                    derived: derived.clone(),
1627                    source: CTypeSource::Cast,
1628                };
1629                type_env.add_constraint(TypeEnvConstraint::new(
1630                    expr.id,
1631                    TypeRepr::Inferred(InferredType::Cast {
1632                        target_type: Box::new(target_type),
1633                    }),
1634                    "cast expression",
1635                ));
1636
1637                // SV ファミリーキャストからのパラメータ型推論
1638                // (SV_FAMILY_TYPE *)param → param に *mut SV 制約を追加
1639                if let Some(fields_dict) = self.fields_dict {
1640                    let is_single_ptr = derived.len() == 1
1641                        && matches!(derived[0], CDerivedType::Pointer { .. });
1642                    if is_single_ptr {
1643                        if let Some(type_name_id) = specs.type_name() {
1644                            if fields_dict.is_sv_family_type(type_name_id) {
1645                                if let ExprKind::Ident(param_name) = &inner.kind {
1646                                    if self.is_macro_param(*param_name) {
1647                                        let sv_type = self.make_sv_ptr_type();
1648                                        type_env.add_constraint(TypeEnvConstraint::new(
1649                                            inner.id,
1650                                            sv_type,
1651                                            "SV family cast",
1652                                        ));
1653                                    }
1654                                }
1655                            }
1656                        }
1657                    }
1658                }
1659            }
1660
1661            // 配列添字
1662            ExprKind::Index { expr: base, index } => {
1663                self.collect_expr_constraints(base, type_env);
1664                self.collect_expr_constraints(index, type_env);
1665                // 配列/ポインタの要素型を推論
1666                let base_ty_str = self.get_expr_type_str(base.id, type_env);
1667                let elem_ty_str = if base_ty_str.ends_with('*') {
1668                    base_ty_str.trim_end_matches('*').trim().to_string()
1669                } else if base_ty_str.contains('[') {
1670                    base_ty_str.split('[').next().unwrap_or(&base_ty_str).trim().to_string()
1671                } else {
1672                    "<unknown>".to_string()
1673                };
1674                let base_type = TypeRepr::from_apidoc_string(&base_ty_str, self.interner);
1675                let element_type = TypeRepr::from_apidoc_string(&elem_ty_str, self.interner);
1676                type_env.add_constraint(TypeEnvConstraint::new(
1677                    expr.id,
1678                    TypeRepr::Inferred(InferredType::ArraySubscript {
1679                        base_type: Box::new(base_type),
1680                        element_type: Box::new(element_type),
1681                    }),
1682                    "array subscript",
1683                ));
1684            }
1685
1686            // メンバーアクセス
1687            ExprKind::Member { expr: base, member } => {
1688                self.collect_expr_constraints(base, type_env);
1689
1690                let base_ty = self.get_expr_type_str(base.id, type_env);
1691                let member_name = self.interner.get(*member);
1692
1693                // sv_u フィールドアクセスの特殊処理
1694                // base が ->sv_u パターンの場合、sv_u 辞書から型を解決
1695                // それ以外は FieldsDict から TypeRepr を直接取得
1696                let field_type = if self.is_sv_u_access(base) {
1697                    // sv_u フィールドは C 形式の型文字列で格納されている
1698                    self.lookup_sv_u_field_type(*member)
1699                        .map(|c_type| Box::new(TypeRepr::from_apidoc_string(&c_type, self.interner)))
1700                } else {
1701                    // TypeRepr ベースのフィールドルックアップ
1702                    let base_type_repr = self.get_expr_type_repr(base.id, type_env);
1703                    let struct_name_id = base_type_repr.as_ref().and_then(|t| t.type_name());
1704                    // bindings.rs 由来の RustType::Named (`pmop__bindgen_ty_2` 等) も拾う
1705                    let struct_name_str = base_type_repr.as_ref()
1706                        .and_then(|t| extract_struct_name_str(t, self.interner));
1707                    let field_str = self.interner.get(*member);
1708                    // flexible array member の特別扱い: 配列ではなく要素型へのポインタ
1709                    let flex_ptr = struct_name_id.and_then(|n| {
1710                        self.fields_dict?
1711                            .flexible_array_element(n, *member)
1712                            .map(|elem| Box::new(wrap_with_outer_pointer(elem.clone(), false)))
1713                    });
1714                    // anonymous struct/union の type_repr は bindings.rs の named 型で置換
1715                    let direct = flex_ptr.or_else(|| {
1716                        struct_name_id.and_then(|n| {
1717                            self.fields_dict?.get_field_type(n, *member).map(|ft| {
1718                                let parent_str = self.interner.get(n);
1719                                let patched = self.replace_anonymous_with_bindings(
1720                                    parent_str, field_str, ft.type_repr.clone(),
1721                                );
1722                                Box::new(patched)
1723                            })
1724                        })
1725                    });
1726                    // fields_dict にない場合は bindings.rs から直接引く
1727                    // (bindgen 生成の anonymous union のメンバアクセス用)
1728                    let direct = direct.or_else(|| {
1729                        struct_name_str.as_deref().and_then(|parent_str| {
1730                            self.lookup_field_in_bindings(parent_str, field_str)
1731                                .map(Box::new)
1732                        })
1733                    });
1734                    // フォールバック: 共通フィールドマクロ × bindings.rs マッピング
1735                    // (無名 union メンバ等、上の経路で解決できないケース)
1736                    direct.or_else(|| {
1737                        self.fields_dict
1738                            .and_then(|fd| fd.rust_type_of_common_field(*member))
1739                            .cloned()
1740                            .map(Box::new)
1741                    })
1742                };
1743
1744                type_env.add_constraint(TypeEnvConstraint::new(
1745                    expr.id,
1746                    TypeRepr::Inferred(InferredType::MemberAccess {
1747                        base_type: base_ty.clone(),
1748                        member: *member,
1749                        field_type,
1750                    }),
1751                    format!("{}.{}", base_ty, member_name),
1752                ));
1753
1754                // 共通フィールドマクロ宣言フィールド → SV ファミリー型逆推論
1755                self.try_infer_sv_family_from_member(*member, base, type_env);
1756            }
1757
1758            // ポインタメンバーアクセス
1759            ExprKind::PtrMember { expr: base, member } => {
1760                self.collect_expr_constraints(base, type_env);
1761
1762                // ベース型からメンバー型を推論
1763                let base_ty = self.get_expr_type_str(base.id, type_env);
1764                let member_name = self.interner.get(*member);
1765
1766                // === ベース型の逆推論 ===
1767                // フィールド名から構造体を特定できる場合、ベース型を推論
1768                if let Some(fields_dict) = self.fields_dict {
1769                    // ベース型がまだ不明(unknown または Ident)の場合のみ逆推論を試みる
1770                    if base_ty == "/* unknown */" || self.is_ident_expr(base) {
1771                        // 1. まず一意なフィールドを試す (Phase 1)
1772                        // 2. 次に SV ファミリー共通フィールドを試す (Phase 2)
1773                        let inferred_struct = fields_dict.lookup_unique(*member)
1774                            .or_else(|| fields_dict.get_consistent_base_type(*member, self.interner));
1775
1776                        if let Some(struct_name) = inferred_struct {
1777                            // typedef 名があれば使用(例: sv → SV)
1778                            let type_name = fields_dict.get_typedef_for_struct(struct_name)
1779                                .unwrap_or(struct_name);
1780                            let type_name_str = self.interner.get(type_name);
1781                            let base_type = TypeRepr::CType {
1782                                specs: CTypeSpecs::TypedefName(type_name),
1783                                derived: vec![CDerivedType::Pointer {
1784                                    is_const: false,
1785                                    is_volatile: false,
1786                                    is_restrict: false,
1787                                }],
1788                                source: CTypeSource::FieldInference { field_name: *member },
1789                            };
1790                            type_env.add_constraint(TypeEnvConstraint::new(
1791                                base.id,
1792                                base_type,
1793                                format!("field {} implies {}*", member_name, type_name_str),
1794                            ));
1795                        }
1796                    }
1797                }
1798
1799                // TypeRepr ベースのフィールドルックアップ
1800                let base_type_repr = self.get_expr_type_repr(base.id, type_env);
1801                let pointee = base_type_repr.as_ref().and_then(|t| t.pointee_name());
1802                let (field_type, used_consistent_type) = if let Some(name) = pointee {
1803                    // flexible array member の特別扱い: 配列ではなく要素型へのポインタ
1804                    let flex_ptr = self.fields_dict.and_then(|fd| {
1805                        fd.flexible_array_element(name, *member)
1806                            .map(|elem| Box::new(wrap_with_outer_pointer(elem.clone(), false)))
1807                    });
1808                    let parent_str = self.interner.get(name);
1809                    let field_str = self.interner.get(*member);
1810                    // ベース型が既知のポインタ型:構造体名で直接ルックアップ
1811                    // anonymous struct/union の場合は bindings.rs の named 型で置換
1812                    let direct = flex_ptr.or_else(|| {
1813                        self.fields_dict
1814                            .and_then(|fd| fd.get_field_type(name, *member))
1815                            .map(|ft| {
1816                                let patched = self.replace_anonymous_with_bindings(
1817                                    parent_str, field_str, ft.type_repr.clone(),
1818                                );
1819                                Box::new(patched)
1820                            })
1821                    });
1822                    // fields_dict にない場合は bindings.rs から直接引く
1823                    // (bindgen 生成の anonymous union のメンバアクセス用)
1824                    let direct = direct.or_else(|| {
1825                        self.lookup_field_in_bindings(parent_str, field_str)
1826                            .map(Box::new)
1827                    });
1828                    let ty = direct.or_else(|| {
1829                        // 共通フィールドマクロ × bindings.rs マッピング(無名 union 等)
1830                        self.fields_dict
1831                            .and_then(|fd| fd.rust_type_of_common_field(*member))
1832                            .cloned()
1833                            .map(Box::new)
1834                    });
1835                    (ty, false)
1836                } else if let Some(fields_dict) = self.fields_dict {
1837                    // ベース型が不明な場合:一致型があればそれを使用(O(1))
1838                    let consistent = fields_dict.get_consistent_field_type(*member)
1839                        .cloned()
1840                        .map(Box::new);
1841                    let ty = consistent.or_else(|| {
1842                        fields_dict.rust_type_of_common_field(*member)
1843                            .cloned()
1844                            .map(Box::new)
1845                    });
1846                    (ty, true)
1847                } else {
1848                    (None, false)
1849                };
1850
1851                type_env.add_constraint(TypeEnvConstraint::new(
1852                    expr.id,
1853                    TypeRepr::Inferred(InferredType::PtrMemberAccess {
1854                        base_type: base_ty.clone(),
1855                        member: *member,
1856                        field_type,
1857                        used_consistent_type,
1858                    }),
1859                    format!("{}->{}", base_ty, member_name),
1860                ));
1861
1862                // 共通フィールドマクロ宣言フィールド → SV ファミリー型逆推論
1863                self.try_infer_sv_family_from_member(*member, base, type_env);
1864            }
1865
1866            // 代入演算子
1867            ExprKind::Assign { lhs, rhs, .. } => {
1868                self.collect_expr_constraints(lhs, type_env);
1869                self.collect_expr_constraints(rhs, type_env);
1870                // 代入式の型は左辺の型
1871                let lhs_type = self.get_expr_type_repr_or_unknown(lhs.id, type_env);
1872                type_env.add_constraint(TypeEnvConstraint::new(
1873                    expr.id,
1874                    TypeRepr::Inferred(InferredType::Assignment {
1875                        lhs_type: Box::new(lhs_type),
1876                    }),
1877                    "assignment expression",
1878                ));
1879            }
1880
1881            // コンマ演算子
1882            ExprKind::Comma { lhs, rhs } => {
1883                self.collect_expr_constraints(lhs, type_env);
1884                self.collect_expr_constraints(rhs, type_env);
1885                // コンマ式の型は右辺の型
1886                let rhs_type = self.get_expr_type_repr_or_unknown(rhs.id, type_env);
1887                type_env.add_constraint(TypeEnvConstraint::new(
1888                    expr.id,
1889                    TypeRepr::Inferred(InferredType::Comma {
1890                        rhs_type: Box::new(rhs_type),
1891                    }),
1892                    "comma expression",
1893                ));
1894            }
1895
1896            // 前置/後置インクリメント/デクリメント
1897            ExprKind::PreInc(inner) | ExprKind::PreDec(inner) |
1898            ExprKind::PostInc(inner) | ExprKind::PostDec(inner) => {
1899                self.collect_expr_constraints(inner, type_env);
1900                let inner_type = self.get_expr_type_repr_or_unknown(inner.id, type_env);
1901                type_env.add_constraint(TypeEnvConstraint::new(
1902                    expr.id,
1903                    TypeRepr::Inferred(InferredType::IncDec {
1904                        inner_type: Box::new(inner_type),
1905                    }),
1906                    "increment/decrement",
1907                ));
1908            }
1909
1910            // アドレス取得
1911            ExprKind::AddrOf(inner) => {
1912                self.collect_expr_constraints(inner, type_env);
1913                let inner_type = self.get_expr_type_repr_or_unknown(inner.id, type_env);
1914                type_env.add_constraint(TypeEnvConstraint::new(
1915                    expr.id,
1916                    TypeRepr::Inferred(InferredType::AddressOf {
1917                        inner_type: Box::new(inner_type),
1918                    }),
1919                    "address-of",
1920                ));
1921            }
1922
1923            // 間接参照
1924            ExprKind::Deref(inner) => {
1925                self.collect_expr_constraints(inner, type_env);
1926                let pointer_type = self.get_expr_type_repr_or_unknown(inner.id, type_env);
1927                type_env.add_constraint(TypeEnvConstraint::new(
1928                    expr.id,
1929                    TypeRepr::Inferred(InferredType::Dereference {
1930                        pointer_type: Box::new(pointer_type),
1931                    }),
1932                    "dereference",
1933                ));
1934            }
1935
1936            // 単項プラス/マイナス
1937            ExprKind::UnaryPlus(inner) | ExprKind::UnaryMinus(inner) => {
1938                self.collect_expr_constraints(inner, type_env);
1939                let inner_type = self.get_expr_type_repr_or_unknown(inner.id, type_env);
1940                type_env.add_constraint(TypeEnvConstraint::new(
1941                    expr.id,
1942                    TypeRepr::Inferred(InferredType::UnaryArithmetic {
1943                        inner_type: Box::new(inner_type),
1944                    }),
1945                    "unary plus/minus",
1946                ));
1947            }
1948
1949            // ビット反転
1950            ExprKind::BitNot(inner) => {
1951                self.collect_expr_constraints(inner, type_env);
1952                let inner_type = self.get_expr_type_repr_or_unknown(inner.id, type_env);
1953                type_env.add_constraint(TypeEnvConstraint::new(
1954                    expr.id,
1955                    TypeRepr::Inferred(InferredType::UnaryArithmetic {
1956                        inner_type: Box::new(inner_type),
1957                    }),
1958                    "bitwise not",
1959                ));
1960            }
1961
1962            // 論理否定
1963            ExprKind::LogNot(inner) => {
1964                self.collect_expr_constraints(inner, type_env);
1965                type_env.add_constraint(TypeEnvConstraint::new(
1966                    expr.id,
1967                    TypeRepr::Inferred(InferredType::LogicalNot),
1968                    "logical not",
1969                ));
1970            }
1971
1972            // sizeof(式)
1973            ExprKind::Sizeof(inner) => {
1974                self.collect_expr_constraints(inner, type_env);
1975                type_env.add_constraint(TypeEnvConstraint::new(
1976                    expr.id,
1977                    TypeRepr::Inferred(InferredType::Sizeof),
1978                    "sizeof expression",
1979                ));
1980            }
1981
1982            // sizeof(型)
1983            ExprKind::SizeofType(_) => {
1984                type_env.add_constraint(TypeEnvConstraint::new(
1985                    expr.id,
1986                    TypeRepr::Inferred(InferredType::Sizeof),
1987                    "sizeof type",
1988                ));
1989            }
1990
1991            // alignof
1992            ExprKind::Alignof(_) => {
1993                type_env.add_constraint(TypeEnvConstraint::new(
1994                    expr.id,
1995                    TypeRepr::Inferred(InferredType::Alignof),
1996                    "alignof",
1997                ));
1998            }
1999
2000            // 複合リテラル
2001            ExprKind::CompoundLit { type_name, .. } => {
2002                let ty = self.resolve_type_name(type_name);
2003                let ty_str = ty.display(self.interner);
2004                let type_name_repr = TypeRepr::from_apidoc_string(&ty_str, self.interner);
2005                type_env.add_constraint(TypeEnvConstraint::new(
2006                    expr.id,
2007                    TypeRepr::Inferred(InferredType::CompoundLiteral {
2008                        type_name: Box::new(type_name_repr),
2009                    }),
2010                    "compound literal",
2011                ));
2012            }
2013
2014            // Statement Expression (GCC拡張)
2015            ExprKind::StmtExpr(compound) => {
2016                self.collect_compound_constraints(compound, type_env);
2017                // 最後の式の型を取得
2018                if let Some(last_expr_id) = self.get_last_expr_id(compound) {
2019                    let last_expr_type = self.get_expr_type_repr_or_unknown(last_expr_id, type_env);
2020                    type_env.add_constraint(TypeEnvConstraint::new(
2021                        expr.id,
2022                        TypeRepr::Inferred(InferredType::StmtExpr {
2023                            last_expr_type: Some(Box::new(last_expr_type)),
2024                        }),
2025                        "statement expression",
2026                    ));
2027                } else {
2028                    type_env.add_constraint(TypeEnvConstraint::new(
2029                        expr.id,
2030                        TypeRepr::Inferred(InferredType::StmtExpr {
2031                            last_expr_type: None,
2032                        }),
2033                        "statement expression (empty)",
2034                    ));
2035                }
2036            }
2037
2038            // アサーション式
2039            ExprKind::Assert { condition, .. } => {
2040                self.collect_expr_constraints(condition, type_env);
2041                type_env.add_constraint(TypeEnvConstraint::new(
2042                    expr.id,
2043                    TypeRepr::Inferred(InferredType::Assert),
2044                    "assertion",
2045                ));
2046            }
2047
2048            // ビルトイン呼び出し(offsetof 等)
2049            ExprKind::BuiltinCall { name, args } => {
2050                // 引数内の式の型制約を収集
2051                for arg in args {
2052                    if let crate::ast::BuiltinArg::Expr(e) = arg {
2053                        self.collect_expr_constraints(e, type_env);
2054                    }
2055                }
2056                // offsetof → size_t (same as sizeof)
2057                let func_name = self.interner.get(*name);
2058                if func_name == "offsetof" || func_name == "__builtin_offsetof"
2059                    || func_name == "STRUCT_OFFSET"
2060                {
2061                    type_env.add_constraint(TypeEnvConstraint::new(
2062                        expr.id,
2063                        TypeRepr::Inferred(InferredType::Sizeof),
2064                        "offsetof returns size_t",
2065                    ));
2066                }
2067            }
2068
2069            // マクロ呼び出し(展開結果の型を使用)
2070            ExprKind::MacroCall { name, args, expanded, .. } => {
2071                // 引数の型制約を収集
2072                for arg in args {
2073                    self.collect_expr_constraints(arg, type_env);
2074                }
2075
2076                // 確定済みマクロのパラメータ型を参照(ネストしたマクロ呼び出しからの型伝播)
2077                let macro_name_str = self.interner.get(*name);
2078                if let Some(param_types) = self.get_macro_param_types(macro_name_str) {
2079                    for (i, arg) in args.iter().enumerate() {
2080                        if let Some((param_name, type_str)) = param_types.get(i) {
2081                            // キャッシュには Rust 形式の型文字列が保存されている
2082                            let constraint = TypeEnvConstraint::new(
2083                                arg.id,
2084                                TypeRepr::from_rust_string(type_str),
2085                                format!("arg {} ({}) of macro {}()", i, param_name, macro_name_str),
2086                            );
2087                            type_env.add_constraint(constraint);
2088                        }
2089                    }
2090                }
2091
2092                // 展開結果の型制約を収集
2093                self.collect_expr_constraints(expanded, type_env);
2094                // MacroCall 式全体の型は expanded と同じ
2095                if let Some(constraints) = type_env.get_expr_constraints(expanded.id) {
2096                    if let Some(constraint) = constraints.first() {
2097                        type_env.add_constraint(TypeEnvConstraint::new(
2098                            expr.id,
2099                            constraint.ty.clone(),
2100                            "macro call (expanded)",
2101                        ));
2102                    }
2103                }
2104            }
2105        }
2106    }
2107
2108    /// 複合文の最後の式の ExprId を取得
2109    fn get_last_expr_id(&self, compound: &CompoundStmt) -> Option<ExprId> {
2110        if let Some(BlockItem::Stmt(Stmt::Expr(Some(expr), _))) = compound.items.last() {
2111            Some(expr.id)
2112        } else {
2113            None
2114        }
2115    }
2116
2117    /// base が ->sv_u アクセスかどうかを判定
2118    ///
2119    /// `sv->sv_u.svu_pv` のような式で、`.svu_pv` の base が `sv->sv_u` かどうかを判定する。
2120    fn is_sv_u_access(&self, base: &Expr) -> bool {
2121        if let ExprKind::PtrMember { member, .. } = &base.kind {
2122            let sv_u_id = self.interner.lookup("sv_u");
2123            sv_u_id.map_or(false, |id| *member == id)
2124        } else {
2125            false
2126        }
2127    }
2128
2129    /// 式が単純な識別子かどうかを判定
2130    ///
2131    /// マクロパラメータのように、まだ型が決まっていない識別子の場合に true を返す。
2132    fn is_ident_expr(&self, expr: &Expr) -> bool {
2133        matches!(expr.kind, ExprKind::Ident(_))
2134    }
2135
2136    /// sv_u ユニオンフィールドの型を取得
2137    ///
2138    /// sv_u union のフィールド名から対応する C 型を返す。
2139    /// 例: svu_pv → "char*", svu_hash → "HE**"
2140    fn lookup_sv_u_field_type(&self, field: InternedStr) -> Option<String> {
2141        self.fields_dict?
2142            .get_sv_u_field_type(field)
2143            .map(|s| s.to_string())
2144    }
2145
2146    /// 関数呼び出しから型制約を収集
2147    fn collect_call_constraints(
2148        &mut self,
2149        call_expr_id: ExprId,
2150        func: &Expr,
2151        args: &[Expr],
2152        type_env: &mut TypeEnv,
2153    ) {
2154        // 関数名を取得
2155        let func_name = match &func.kind {
2156            ExprKind::Ident(name) => *name,
2157            _ => return, // 間接呼び出しは未対応
2158        };
2159
2160        let func_name_str = self.interner.get(func_name);
2161
2162        // RustDeclDict から引数の型を取得
2163        if let Some(rust_decl_dict) = self.rust_decl_dict {
2164            if let Some(rust_fn) = rust_decl_dict.fns.get(func_name_str) {
2165                for (i, arg) in args.iter().enumerate() {
2166                    if let Some(param) = rust_fn.params.get(i) {
2167                        let constraint = TypeEnvConstraint::new(
2168                            arg.id,
2169                            TypeRepr::RustType {
2170                                repr: RustTypeRepr::from_type_string(&param.ty),
2171                                source: RustTypeSource::FnParam {
2172                                    func_name: func_name_str.to_string(),
2173                                    param_index: i,
2174                                },
2175                            },
2176                            format!("arg {} of {}()", i, func_name_str),
2177                        );
2178                        type_env.add_constraint(constraint);
2179                    }
2180                }
2181
2182                // 戻り値型も制約として追加
2183                if let Some(ref ret_ty) = rust_fn.ret_ty {
2184                    let return_constraint = TypeEnvConstraint::new(
2185                        call_expr_id,
2186                        TypeRepr::RustType {
2187                            repr: RustTypeRepr::from_type_string(ret_ty),
2188                            source: RustTypeSource::FnReturn {
2189                                func_name: func_name_str.to_string(),
2190                            },
2191                        },
2192                        format!("return type of {}()", func_name_str),
2193                    );
2194                    type_env.add_constraint(return_constraint);
2195                }
2196            }
2197        }
2198
2199        // Apidoc から型を取得
2200        if let Some(apidoc) = self.apidoc {
2201            if let Some(entry) = apidoc.get(func_name_str) {
2202                // 引数の型
2203                for (i, arg) in args.iter().enumerate() {
2204                    if let Some(apidoc_arg) = entry.args.get(i) {
2205                        let constraint = TypeEnvConstraint::new(
2206                            arg.id,
2207                            self.parse_type_string(&apidoc_arg.ty),
2208                            format!("arg {} ({}) of {}()", i, apidoc_arg.name, func_name_str),
2209                        );
2210                        type_env.add_constraint(constraint);
2211                    }
2212                }
2213
2214                // 戻り値型
2215                if let Some(ref return_type) = entry.return_type {
2216                    let return_constraint = TypeEnvConstraint::new(
2217                        call_expr_id,
2218                        self.parse_type_string(return_type),
2219                        format!("return type of {}()", func_name_str),
2220                    );
2221                    type_env.add_constraint(return_constraint);
2222                }
2223            }
2224        }
2225
2226        // InlineFnDict から型を取得(AST から TypeRepr を直接構築)
2227        if self.inline_fn_dict.is_some() {
2228            // 引数の型
2229            for (i, arg) in args.iter().enumerate() {
2230                if let Some(type_repr) = self.lookup_inline_fn_param_type_repr(func_name, i) {
2231                    let constraint = TypeEnvConstraint::new(
2232                        arg.id,
2233                        type_repr,
2234                        format!("arg {} of inline {}()", i, func_name_str),
2235                    );
2236                    type_env.add_constraint(constraint);
2237                }
2238            }
2239
2240            // 戻り値型
2241            if let Some(type_repr) = self.lookup_inline_fn_return_type_repr(func_name) {
2242                let return_constraint = TypeEnvConstraint::new(
2243                    call_expr_id,
2244                    type_repr,
2245                    format!("return type of inline {}()", func_name_str),
2246                );
2247                type_env.add_constraint(return_constraint);
2248            }
2249        }
2250
2251        // 確定済みマクロのパラメータ型を参照(ネストしたマクロ呼び出しからの型伝播)
2252        if let Some(param_types) = self.get_macro_param_types(func_name_str) {
2253            for (i, arg) in args.iter().enumerate() {
2254                if let Some((param_name, type_str)) = param_types.get(i) {
2255                    // キャッシュには Rust 形式の型文字列が保存されている
2256                    let constraint = TypeEnvConstraint::new(
2257                        arg.id,
2258                        TypeRepr::from_rust_string(type_str),
2259                        format!("arg {} ({}) of macro {}()", i, param_name, func_name_str),
2260                    );
2261                    type_env.add_constraint(constraint);
2262                }
2263            }
2264        }
2265
2266        // 確定済みマクロの戻り値型を参照
2267        if let Some(return_type_str) = self.get_macro_return_type(func_name_str) {
2268            // キャッシュには Rust 形式の型文字列が保存されている
2269            let return_constraint = TypeEnvConstraint::new(
2270                call_expr_id,
2271                TypeRepr::from_rust_string(return_type_str),
2272                format!("return type of macro {}()", func_name_str),
2273            );
2274            type_env.add_constraint(return_constraint);
2275        }
2276    }
2277
2278    /// 複合文から型制約を収集
2279    fn collect_compound_constraints(&mut self, compound: &CompoundStmt, type_env: &mut TypeEnv) {
2280        for item in &compound.items {
2281            match item {
2282                BlockItem::Decl(decl) => {
2283                    // 宣言の初期化子内の式を処理
2284                    self.collect_decl_initializer_constraints(decl, type_env);
2285                }
2286                BlockItem::Stmt(Stmt::Expr(Some(expr), _)) => {
2287                    self.collect_expr_constraints(expr, type_env);
2288                }
2289                BlockItem::Stmt(Stmt::Return(Some(expr), _)) => {
2290                    self.collect_expr_constraints(expr, type_env);
2291                }
2292                BlockItem::Stmt(Stmt::Compound(inner)) => {
2293                    self.collect_compound_constraints(inner, type_env);
2294                }
2295                _ => {}
2296            }
2297        }
2298    }
2299
2300    /// 宣言の初期化子から型制約を収集
2301    fn collect_decl_initializer_constraints(&mut self, decl: &Declaration, type_env: &mut TypeEnv) {
2302        for init_decl in &decl.declarators {
2303            if let Some(ref init) = init_decl.init {
2304                self.collect_initializer_constraints(init, type_env);
2305            }
2306        }
2307    }
2308
2309    /// 初期化子から型制約を収集(再帰)
2310    fn collect_initializer_constraints(&mut self, init: &Initializer, type_env: &mut TypeEnv) {
2311        match init {
2312            Initializer::Expr(expr) => {
2313                self.collect_expr_constraints(expr, type_env);
2314            }
2315            Initializer::List(items) => {
2316                for item in items {
2317                    self.collect_initializer_constraints(&item.init, type_env);
2318                }
2319            }
2320        }
2321    }
2322
2323    /// Rust型文字列を Type に変換
2324    fn parse_rust_type_string(&self, type_str: &str) -> Type {
2325        // synのto_token_stream().to_string()は "* mut" のようにスペースを入れるため正規化
2326        let normalized = type_str
2327            .replace("* mut", "*mut")
2328            .replace("* const", "*const");
2329        let trimmed = normalized.trim();
2330
2331        // ポインタ型
2332        if let Some(rest) = trimmed.strip_prefix("*mut ") {
2333            return Type::Pointer(
2334                Box::new(self.parse_rust_type_string(rest)),
2335                TypeQualifiers::default(),
2336            );
2337        }
2338        if let Some(rest) = trimmed.strip_prefix("*const ") {
2339            return Type::Pointer(
2340                Box::new(self.parse_rust_type_string(rest)),
2341                TypeQualifiers { is_const: true, ..Default::default() },
2342            );
2343        }
2344
2345        // 基本型
2346        match trimmed {
2347            "()" => Type::Void,
2348            "c_char" => Type::Char,
2349            "c_int" => Type::Int,
2350            "c_uint" => Type::UnsignedInt,
2351            "c_long" => Type::Long,
2352            "c_ulong" => Type::UnsignedLong,
2353            "bool" => Type::Bool,
2354            "usize" => Type::UnsignedLong,
2355            "isize" => Type::Long,
2356            _ => {
2357                // typedef名として扱う
2358                if let Some(interned) = self.interner.lookup(trimmed) {
2359                    Type::TypedefName(interned)
2360                } else {
2361                    Type::Unknown
2362                }
2363            }
2364        }
2365    }
2366}
2367
2368#[cfg(test)]
2369mod tests {
2370    use super::*;
2371
2372    #[test]
2373    fn test_type_display() {
2374        let interner = StringInterner::new();
2375
2376        assert_eq!(Type::Int.display(&interner), "int");
2377        assert_eq!(Type::UnsignedLong.display(&interner), "unsigned long");
2378        assert_eq!(
2379            Type::Pointer(Box::new(Type::Char), TypeQualifiers::default()).display(&interner),
2380            "char*"
2381        );
2382    }
2383
2384    #[test]
2385    fn test_scope_management() {
2386        let mut interner = StringInterner::new();
2387        let x = interner.intern("x");
2388        let mut analyzer = SemanticAnalyzer::new(&interner, None, None);
2389
2390        // グローバルスコープでxを定義
2391        analyzer.define_symbol(Symbol {
2392            name: x,
2393            ty: Type::Int,
2394            loc: SourceLocation::default(),
2395            kind: SymbolKind::Variable,
2396        });
2397
2398        assert!(analyzer.lookup_symbol(x).is_some());
2399
2400        // 新しいスコープを開始
2401        analyzer.push_scope();
2402
2403        // まだxが見える
2404        assert!(analyzer.lookup_symbol(x).is_some());
2405
2406        // ローカルスコープでxをシャドウイング
2407        analyzer.define_symbol(Symbol {
2408            name: x,
2409            ty: Type::Float, // 異なる型
2410            loc: SourceLocation::default(),
2411            kind: SymbolKind::Variable,
2412        });
2413
2414        // ローカルのxが見える
2415        let sym = analyzer.lookup_symbol(x).unwrap();
2416        assert_eq!(sym.ty, Type::Float);
2417
2418        // スコープを終了
2419        analyzer.pop_scope();
2420
2421        // グローバルのxが見える
2422        let sym = analyzer.lookup_symbol(x).unwrap();
2423        assert_eq!(sym.ty, Type::Int);
2424    }
2425}