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
use std::collections::HashMap;

use cranelift_entity::{entity_impl, PrimaryMap};

use crate::{expressions::ExpressionData, PackageName, TypeDefId, TypeDefinition};
use claw_common::Source;

use super::{
    expressions::ExpressionId,
    statements::{Let, Statement, StatementId},
    types::FnType,
    NameId, Span, TypeId, ValType,
};

#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ImportId(u32);
entity_impl!(ImportId, "import");

#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GlobalId(u32);
entity_impl!(GlobalId, "global");

#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FunctionId(u32);
entity_impl!(FunctionId, "func");

/// Each Claw source file represents a Component
/// and this struct represents the root of the AST.
#[derive(Debug)]
pub struct Component {
    pub src: Source,

    // Top level items
    pub imports: PrimaryMap<ImportId, Import>,
    pub type_defs: PrimaryMap<TypeDefId, TypeDefinition>,
    pub globals: PrimaryMap<GlobalId, Global>,
    pub functions: PrimaryMap<FunctionId, Function>,

    // Inner items
    pub types: PrimaryMap<TypeId, ValType>,
    pub type_spans: HashMap<TypeId, Span>,

    pub statements: PrimaryMap<StatementId, Statement>,
    pub statement_spans: HashMap<StatementId, Span>,

    pub expression_data: ExpressionData,

    pub names: PrimaryMap<NameId, String>,
    pub name_spans: HashMap<NameId, Span>,
}

impl Component {
    pub fn new(src: Source) -> Self {
        Self {
            src,
            imports: Default::default(),
            type_defs: Default::default(),
            globals: Default::default(),
            functions: Default::default(),
            types: Default::default(),
            type_spans: Default::default(),
            statements: Default::default(),
            statement_spans: Default::default(),
            expression_data: Default::default(),
            names: Default::default(),
            name_spans: Default::default(),
        }
    }

    pub fn new_name(&mut self, name: String, span: Span) -> NameId {
        let id = self.names.push(name);
        self.name_spans.insert(id, span);
        id
    }

    pub fn get_name(&self, id: NameId) -> &str {
        self.names.get(id).unwrap()
    }

    pub fn name_span(&self, id: NameId) -> Span {
        *self.name_spans.get(&id).unwrap()
    }

    pub fn new_type(&mut self, valtype: ValType, span: Span) -> TypeId {
        let id = self.types.push(valtype);
        self.type_spans.insert(id, span);
        id
    }

    pub fn get_type(&self, id: TypeId) -> &ValType {
        self.types.get(id).unwrap()
    }

    pub fn type_span(&self, id: TypeId) -> Span {
        *self.type_spans.get(&id).unwrap()
    }

    pub fn new_statement(&mut self, statement: Statement, span: Span) -> StatementId {
        let id = self.statements.push(statement);
        self.statement_spans.insert(id, span);
        id
    }

    pub fn get_statement(&self, id: StatementId) -> &Statement {
        self.statements.get(id).unwrap()
    }

    pub fn statement_span(&self, id: StatementId) -> Span {
        *self.statement_spans.get(&id).unwrap()
    }

    pub fn alloc_let(
        &mut self,
        mutable: bool,
        ident: NameId,
        annotation: Option<TypeId>,
        expression: ExpressionId,
        span: Span,
    ) -> StatementId {
        let let_ = Let {
            mutable,
            ident,
            annotation,
            expression,
        };
        self.new_statement(Statement::Let(let_), span)
    }

    pub fn expr(&self) -> &ExpressionData {
        &self.expression_data
    }

    pub fn expr_mut(&mut self) -> &mut ExpressionData {
        &mut self.expression_data
    }
}

///
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Import {
    Plain(PlainImport),
    ImportFrom(ImportFrom),
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct PlainImport {
    pub ident: NameId,
    pub alias: Option<NameId>,
    pub external_type: ExternalType,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ImportFrom {
    /// The first name is the imported item's name
    /// The second optional name is an alias
    pub items: Vec<(NameId, Option<NameId>)>,
    pub package: PackageName,
    pub interface: String,
}

///
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExternalType {
    Function(FnType),
}

///
#[derive(Debug)]
pub struct Function {
    pub exported: bool,
    pub ident: NameId,
    pub params: Vec<(NameId, TypeId)>,
    pub results: Option<TypeId>,
    pub body: Vec<StatementId>,
}

///
#[derive(Debug, Clone)]
pub struct Global {
    pub exported: bool,
    pub mutable: bool,
    pub ident: NameId,
    pub type_id: TypeId,
    pub init_value: ExpressionId,
}