Skip to main content

lisette_syntax/program/
resolution.rs

1//! Resolution metadata attached to `Expression::Call` and
2//! `Expression::DotAccess` during type checking. Inference populates these
3//! so downstream consumers (the emitter in particular) do not re-derive the
4//! classification from the typed AST.
5
6use crate::types::Type;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ReceiverCoercion {
10    /// Insert `&` to convert `T` to `Ref<T>`
11    AutoAddress,
12    /// Insert `*` to convert `Ref<T>` to `T`
13    AutoDeref,
14}
15
16/// What a dot access resolved to during type checking.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum DotAccessKind {
19    /// Named struct field access
20    StructField { is_exported: bool },
21    /// Tuple struct field access (e.g., `point.0` on `struct Point(int, int)`).
22    /// `is_newtype` is true when the struct has exactly 1 field and no generics,
23    /// meaning access should emit a type cast rather than `.F0`.
24    TupleStructField { is_newtype: bool },
25    /// Tuple element access (e.g., `t.0`, `t.1`)
26    TupleElement,
27    /// Module member access (e.g., `mod.func`)
28    ModuleMember,
29    /// Value enum variant (Go constant, e.g., `reflect.String`)
30    ValueEnumVariant,
31    /// ADT enum variant constructor (e.g., `makeColorRed[T]()`)
32    EnumVariant,
33    /// Instance method (has `self` receiver)
34    InstanceMethod { is_exported: bool },
35    /// Instance method used as a first-class value (not called).
36    /// E.g., `Point.area` used as a callback. The emitter needs to know
37    /// whether the receiver is a pointer to emit Go method expression syntax.
38    InstanceMethodValue {
39        is_exported: bool,
40        is_pointer_receiver: bool,
41    },
42    /// Static method (no `self` receiver)
43    StaticMethod { is_exported: bool },
44}
45
46/// What kind of native built-in type (Slice, Map, Channel, etc.) a call targets.
47/// Defined here so semantics can classify calls without depending on
48/// emit-specific types. The emitter maps this to its internal `NativeGoType`.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum NativeTypeKind {
51    Slice,
52    EnumeratedSlice,
53    Map,
54    Channel,
55    Sender,
56    Receiver,
57    String,
58}
59
60impl NativeTypeKind {
61    pub fn from_type(ty: &Type) -> Option<Self> {
62        let resolved = ty.strip_refs();
63        // Skip module namespaces and Go-imported types: their leaf name can
64        // collide with a native type (e.g. `Slice`), but they are not native.
65        if resolved.as_import_namespace().is_some() {
66            return None;
67        }
68        if let Type::Nominal { ref id, .. } = resolved
69            && id.as_str().starts_with("go:")
70        {
71            return None;
72        }
73        let name = resolved.get_name()?;
74        Self::from_name(name)
75    }
76
77    pub fn from_name(name: &str) -> Option<Self> {
78        match name {
79            "Slice" => Some(Self::Slice),
80            "EnumeratedSlice" => Some(Self::EnumeratedSlice),
81            "Map" => Some(Self::Map),
82            "Channel" => Some(Self::Channel),
83            "Sender" => Some(Self::Sender),
84            "Receiver" => Some(Self::Receiver),
85            "string" => Some(Self::String),
86            _ => None,
87        }
88    }
89}
90
91/// What a call expression resolved to during type checking.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum CallKind {
94    /// Regular function or method call
95    Regular,
96    /// Tuple struct constructor (e.g., `Point(1, 2)`)
97    TupleStructConstructor,
98    /// Type assertion (`assert_type`)
99    AssertType,
100    /// UFCS method call: `receiver.method()` where method is a free function
101    UfcsMethod,
102    /// Native type constructor (e.g., `Channel.new`, `Map.new`, `Slice.new`)
103    NativeConstructor(NativeTypeKind),
104    /// Native type instance method via dot access (e.g., `slice.append(x)`)
105    NativeMethod(NativeTypeKind),
106    /// Native type method via identifier (e.g., `Slice.contains(s, x)`)
107    NativeMethodIdentifier(NativeTypeKind),
108    /// Receiver method in UFCS syntax: `Type.method(receiver, args)`
109    ReceiverMethodUfcs { is_public: bool },
110}