roan_engine/interpreter/
structs.rs

1use crate::{
2    context::Context,
3    module::{ExportType, Module, StoredImpl, StoredStruct, StoredTraitImpl},
4    value::Value,
5    vm::VM,
6};
7use anyhow::Result;
8use log::debug;
9use roan_ast::{Struct, StructConstructor, StructImpl, TraitDef, TraitImpl};
10use roan_error::{error::RoanError, TextSpan};
11use std::collections::HashMap;
12
13impl Module {
14    /// Interpret a struct implementation.
15    ///
16    /// # Arguments
17    /// * `impl_stmt` - [`StructImpl`] - The struct implementation to interpret.
18    pub fn interpret_struct_impl(
19        &mut self,
20        impl_stmt: StructImpl,
21        ctx: &mut Context,
22    ) -> Result<()> {
23        let struct_name = impl_stmt.struct_name.literal();
24
25        let mut found_struct = self.get_struct(&struct_name, impl_stmt.struct_name.span.clone())?;
26        let stored_impl = StoredImpl {
27            def: impl_stmt.clone(),
28            defining_module: self.id(),
29        };
30        found_struct.impls.push(stored_impl.clone());
31
32        if let Some(existing_struct) = self
33            .structs
34            .iter_mut()
35            .find(|s| s.name.literal() == struct_name)
36        {
37            *existing_struct = found_struct;
38
39            if let Some(export) = self.exports.iter_mut().find(|(n, _)| n == &struct_name) {
40                if let ExportType::Struct(s) = &mut export.1 {
41                    s.impls.push(stored_impl);
42                }
43            }
44        }
45
46        ctx.upsert_module(self.id().clone(), self.clone());
47
48        Ok(())
49    }
50
51    /// Interpret a trait implementation.
52    ///
53    /// # Arguments
54    /// * `impl_stmt` - [`TraitImpl`] - The trait implementation to interpret.
55    pub fn interpret_trait_impl(&mut self, impl_stmt: TraitImpl, ctx: &mut Context) -> Result<()> {
56        let for_name = impl_stmt.struct_name.literal();
57        let trait_name = impl_stmt.trait_name.literal();
58
59        let mut struct_def = self.get_struct(&for_name, impl_stmt.struct_name.span.clone())?;
60        let trait_def = self.get_trait(&trait_name, impl_stmt.trait_name.span.clone())?;
61        if struct_def
62            .trait_impls
63            .iter()
64            .any(|t| t.def.trait_name.literal() == trait_name)
65        {
66            return Err(RoanError::StructAlreadyImplementsTrait(
67                for_name,
68                trait_name,
69                impl_stmt.trait_name.span.clone(),
70            )
71            .into());
72        }
73
74        let missing_methods: Vec<String> = trait_def
75            .methods
76            .iter()
77            .filter(|m| !impl_stmt.methods.iter().any(|i| i.name == m.name))
78            .map(|m| m.name.clone())
79            .collect();
80
81        if !missing_methods.is_empty() {
82            return Err(RoanError::TraitMethodNotImplemented(
83                trait_name,
84                missing_methods,
85                impl_stmt.trait_name.span.clone(),
86            )
87            .into());
88        }
89
90        let stored_trait_impl = StoredTraitImpl {
91            def: impl_stmt.clone(),
92            defining_module: self.id(),
93        };
94
95        struct_def.trait_impls.push(stored_trait_impl.clone());
96
97        if let Some(existing_struct) = self
98            .structs
99            .iter_mut()
100            .find(|s| s.name.literal() == for_name)
101        {
102            *existing_struct = struct_def;
103
104            if let Some(export) = self.exports.iter_mut().find(|(n, _)| n == &for_name) {
105                if let ExportType::Struct(s) = &mut export.1 {
106                    s.trait_impls.push(stored_trait_impl);
107                }
108            }
109        }
110
111        ctx.upsert_module(self.id().clone(), self.clone());
112
113        Ok(())
114    }
115
116    pub fn get_trait(&self, name: &str, span: TextSpan) -> Result<TraitDef> {
117        Ok(self
118            .traits
119            .iter()
120            .find(|t| t.name.literal() == name)
121            .cloned()
122            .ok_or_else(|| RoanError::TraitNotFoundError(name.into(), span))?)
123    }
124
125    pub fn get_struct(&self, name: &str, span: TextSpan) -> Result<StoredStruct> {
126        let x = self.structs.iter().find(|s| s.name.literal() == name);
127
128        Ok(x.cloned()
129            .ok_or_else(|| RoanError::StructNotFoundError(name.into(), span))?)
130    }
131
132    /// Interpret a struct definition.
133    ///
134    /// # Arguments
135    /// * `struct_def` - [`Struct`] - The struct definition to interpret.
136    /// * `ctx` - [`Context`] - The context in which to interpret the struct definition.
137    ///
138    /// # Returns
139    /// The result of interpreting the struct definition.
140    pub fn interpret_struct(&mut self, struct_stmt: Struct, ctx: &mut Context) -> Result<()> {
141        let def = struct_stmt.clone();
142        let stored_struct = StoredStruct {
143            defining_module: self.id(),
144            struct_token: def.struct_token,
145            name: def.name,
146            fields: def.fields,
147            public: def.public,
148            impls: vec![],
149            trait_impls: vec![],
150        };
151
152        self.structs.push(stored_struct.clone());
153
154        if struct_stmt.public {
155            self.exports.push((
156                struct_stmt.name.literal(),
157                ExportType::Struct(stored_struct),
158            ));
159        }
160
161        ctx.upsert_module(self.id().clone(), self.clone());
162
163        Ok(())
164    }
165
166    /// Interpret trait definition.
167    ///
168    /// # Arguments
169    /// * `trait_def` - [`TraitDef`] - The trait definition to interpret.
170    /// * `ctx` - [`Context`] - The context in which to interpret the trait definition.
171    ///
172    /// # Returns
173    /// The result of interpreting the trait definition.
174    pub fn interpret_trait(&mut self, trait_stmt: TraitDef, ctx: &mut Context) -> Result<()> {
175        self.traits.push(trait_stmt.clone());
176
177        if trait_stmt.public {
178            self.exports.push((
179                trait_stmt.name.literal(),
180                ExportType::Trait(trait_stmt.clone()),
181            ));
182        }
183
184        ctx.upsert_module(self.id().clone(), self.clone());
185
186        Ok(())
187    }
188
189    /// Interpret a struct constructor expression.
190    ///
191    /// # Arguments
192    /// * `constructor` - [StructConstructor] expression to interpret.
193    /// * `ctx` - The context in which to interpret the struct constructor expression.
194    /// * `vm` - The virtual machine to use.
195    ///
196    /// # Returns
197    /// The result of the struct constructor expression.
198    pub fn interpret_struct_constructor(
199        &mut self,
200        constructor: StructConstructor,
201        ctx: &mut Context,
202        vm: &mut VM,
203    ) -> Result<Value> {
204        debug!("Interpreting struct constructor");
205        let found = self.get_struct(&constructor.name, constructor.token.span.clone())?;
206
207        let mut fields = HashMap::new();
208
209        for (field_name, expr) in constructor.fields.iter() {
210            self.interpret_expr(expr, ctx, vm)?;
211            fields.insert(field_name.clone(), vm.pop().unwrap());
212        }
213
214        Ok(Value::Struct(found, fields))
215    }
216}