1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
use crate::{
    key::DefID,
    module::Module,
    node::{Node, NodeSource},
};
use cl_ast::{Meta, Sym, Visibility};
use std::{fmt::Debug, str::FromStr};

mod display;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Def<'a> {
    pub node: Node<'a>,
    pub kind: DefKind,
    pub module: Module,
}

impl<'a> Def<'a> {
    pub fn with_node(node: Node<'a>) -> Self {
        Self { node, kind: DefKind::Undecided, module: Default::default() }
    }
}

impl Def<'_> {
    pub fn name(&self) -> Option<Sym> {
        match self.node.kind {
            Some(source) => source.name(),
            None => None,
        }
    }
}

mod builder_functions {
    use super::*;

    impl<'a> Def<'a> {
        pub fn set_vis(&mut self, vis: Visibility) -> &mut Self {
            self.node.vis = vis;
            self
        }
        pub fn set_meta(&mut self, meta: &'a [Meta]) -> &mut Self {
            self.node.meta = meta;
            self
        }
        pub fn set_kind(&mut self, kind: DefKind) -> &mut Self {
            self.kind = kind;
            self
        }
        pub fn set_source(&mut self, source: NodeSource<'a>) -> &mut Self {
            self.node.kind = Some(source);
            self
        }
        pub fn set_module(&mut self, module: Module) -> &mut Self {
            self.module = module;
            self
        }
    }
}

#[derive(Clone, Default, Debug, PartialEq, Eq)]
pub enum DefKind {
    /// An unevaluated definition
    #[default]
    Undecided,
    /// An impl block
    Impl(DefID),
    /// A use tree, and its parent
    Use(DefID),
    /// A type, such as a `type`, `struct`, or `enum`
    Type(TypeKind),
    /// A value, such as a `const`, `static`, or `fn`
    Value(ValueKind),
}

/// A [ValueKind] represents an item in the Value Namespace
/// (a component of a [Project](crate::project::Project)).
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ValueKind {
    Const(DefID),
    Static(DefID),
    Local(DefID),
    Fn(DefID),
}
/// A [TypeKind] represents an item in the Type Namespace
/// (a component of a [Project](crate::project::Project)).
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum TypeKind {
    /// An alias for an already-defined type
    Alias(Option<DefID>),
    /// A primitive type, built-in to the compiler
    Intrinsic(Intrinsic),
    /// A user-defined aromatic data type
    Adt(Adt),
    /// A reference to an already-defined type: &T
    Ref(u16, DefID),
    /// A contiguous view of dynamically sized memory
    Slice(DefID),
    /// A contiguous view of statically sized memory
    Array(DefID, usize),
    /// A tuple of existing types
    Tuple(Vec<DefID>),
    /// A function which accepts multiple inputs and produces an output
    FnSig { args: DefID, rety: DefID },
    /// The unit type
    Empty,
    /// The never type
    Never,
    /// The Self type
    SelfTy,
    /// An untyped module
    Module,
}

/// A user-defined Aromatic Data Type
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Adt {
    /// A union-like enum type
    Enum(Vec<(Sym, Option<DefID>)>),
    /// A C-like enum
    CLikeEnum(Vec<(Sym, u128)>),
    /// An enum with no fields, which can never be constructed
    FieldlessEnum,

    /// A structural product type with named members
    Struct(Vec<(Sym, Visibility, DefID)>),
    /// A structural product type with unnamed members
    TupleStruct(Vec<(Visibility, DefID)>),
    /// A structural product type of neither named nor unnamed members
    UnitStruct,

    /// A choose your own undefined behavior type
    /// TODO: should unions be a language feature?
    Union(Vec<(Sym, DefID)>),
}

/// The set of compiler-intrinsic types.
/// These primitive types have native implementations of the basic operations.
#[allow(non_camel_case_types)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Intrinsic {
    /// An 8-bit signed integer: `#[intrinsic = "i8"]`
    I8,
    /// A 16-bit signed integer: `#[intrinsic = "i16"]`
    I16,
    /// A 32-bit signed integer: `#[intrinsic = "i32"]`
    I32,
    /// A 64-bit signed integer: `#[intrinsic = "i32"]`
    I64,
    // /// A 128-bit signed integer: `#[intrinsic = "i32"]`
    // I128,
    /// A ptr-len signed integer: `#[intrinsic = "isize"]`
    Isize,
    /// An 8-bit unsigned integer: `#[intrinsic = "u8"]`
    U8,
    /// A 16-bit unsigned integer: `#[intrinsic = "u16"]`
    U16,
    /// A 32-bit unsigned integer: `#[intrinsic = "u32"]`
    U32,
    /// A 64-bit unsigned integer: `#[intrinsic = "u64"]`
    U64,
    // /// A 128-bit unsigned integer: `#[intrinsic = "u128"]`
    // U128,
    /// A ptr-len unsigned integer: `#[intrinsic = "isize"]`
    Usize,
    /// A boolean (`true` or `false`): `#[intrinsic = "bool"]`
    Bool,
    /// The unicode codepoint type: #[intrinsic = "char"]
    Char,
}

impl FromStr for Intrinsic {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(match s {
            "i8" => Intrinsic::I8,
            "i16" => Intrinsic::I16,
            "i32" => Intrinsic::I32,
            "i64" => Intrinsic::I64,
            "isize" => Intrinsic::Isize,
            "u8" => Intrinsic::U8,
            "u16" => Intrinsic::U16,
            "u32" => Intrinsic::U32,
            "u64" => Intrinsic::U64,
            "usize" => Intrinsic::Usize,
            "bool" => Intrinsic::Bool,
            "char" => Intrinsic::Char,
            _ => Err(())?,
        })
    }
}