roan_engine/interpreter/
structs.rs1use 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 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 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 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 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 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}