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    /// ADT enum variant constructor (e.g., `makeColorRed[T]()`)
30    EnumVariant,
31    /// Instance method (has `self` receiver)
32    InstanceMethod { is_exported: bool },
33    /// Instance method used as a first-class value (not called).
34    /// E.g., `Point.area` used as a callback. The emitter needs to know
35    /// whether the receiver is a pointer to emit Go method expression syntax.
36    InstanceMethodValue {
37        is_exported: bool,
38        is_pointer_receiver: bool,
39    },
40    /// Static method (no `self` receiver)
41    StaticMethod { is_exported: bool },
42}
43
44/// What kind of native built-in type (Slice, Map, Channel, etc.) a call targets.
45/// Defined here so semantics can classify calls without depending on
46/// emit-specific types. The emitter maps this to its internal `NativeGoType`.
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum NativeTypeKind {
49    Slice,
50    EnumeratedSlice,
51    Map,
52    Channel,
53    Sender,
54    Receiver,
55    String,
56}
57
58impl NativeTypeKind {
59    pub fn from_type(ty: &Type) -> Option<Self> {
60        let resolved = ty.strip_refs();
61        // Skip module namespaces and Go-imported types: their leaf name can
62        // collide with a native type (e.g. `Slice`), but they are not native.
63        if resolved.as_import_namespace().is_some() {
64            return None;
65        }
66        if let Type::Nominal { ref id, .. } = resolved
67            && id.as_str().starts_with("go:")
68        {
69            return None;
70        }
71        let name = resolved.get_name()?;
72        Self::from_name(name)
73    }
74
75    pub fn from_name(name: &str) -> Option<Self> {
76        match name {
77            "Slice" => Some(Self::Slice),
78            "EnumeratedSlice" => Some(Self::EnumeratedSlice),
79            "Map" => Some(Self::Map),
80            "Channel" => Some(Self::Channel),
81            "Sender" => Some(Self::Sender),
82            "Receiver" => Some(Self::Receiver),
83            "string" => Some(Self::String),
84            _ => None,
85        }
86    }
87}
88
89/// What a call expression resolved to during type checking.
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub enum CallKind {
92    /// Regular function or method call
93    Regular,
94    /// Tuple struct constructor (e.g., `Point(1, 2)`)
95    TupleStructConstructor,
96    /// Type assertion (`assert_type`)
97    AssertType,
98    /// UFCS method call: `receiver.method()` where method is a free function
99    UfcsMethod,
100    /// Native type constructor (e.g., `Channel.new`, `Map.new`, `Slice.new`)
101    NativeConstructor(NativeTypeKind),
102    /// Native type instance method via dot access (e.g., `slice.append(x)`)
103    NativeMethod(NativeTypeKind),
104    /// Native type method via identifier (e.g., `Slice.contains(s, x)`)
105    NativeMethodIdentifier(NativeTypeKind),
106    /// Receiver method in UFCS syntax: `Type.method(receiver, args)`
107    ReceiverMethodUfcs { is_public: bool },
108}