1use crate::{
2 context::Context,
3 natives::get_stored_function,
4 value::Value,
5 vm::{native_fn::NativeFunction, VM},
6};
7use anyhow::Result;
8use roan_ast::{
9 source::Source, Ast, Expr, Fn, Lexer, Parser, StructField, StructImpl, Token, TraitDef,
10 TraitImpl,
11};
12use roan_error::{error::RoanError::VariableNotFoundError, print_diagnostic, TextSpan};
13use std::{
14 collections::HashMap,
15 fmt::Debug,
16 path::{Path, PathBuf},
17};
18use tracing::debug;
19use uuid::Uuid;
20
21pub mod loaders;
22
23#[derive(Clone, Debug)]
24pub struct StoredStruct {
25 pub defining_module: String,
26 pub struct_token: Token,
27 pub name: Token,
28 pub fields: Vec<StructField>,
29 pub public: bool,
30 pub impls: Vec<StoredImpl>,
31 pub trait_impls: Vec<StoredTraitImpl>,
32}
33
34impl StoredStruct {
35 fn find_method_internal(&self, name: &str, is_static: bool) -> Option<&Fn> {
36 self.impls
37 .iter()
38 .flat_map(|impl_stmt| impl_stmt.def.methods.iter())
39 .chain(
40 self.trait_impls
41 .iter()
42 .flat_map(|impl_stmt| impl_stmt.def.methods.iter()),
43 )
44 .find(|method| method.name == name && method.is_static == is_static)
45 }
46
47 pub fn find_static_method(&self, name: &str) -> Option<&Fn> {
48 self.find_method_internal(name, true)
49 }
50
51 pub fn find_method(&self, name: &str) -> Option<&Fn> {
52 self.find_method_internal(name, false)
53 }
54}
55
56#[derive(Clone, Debug)]
57pub struct StoredImpl {
58 pub def: StructImpl,
59 pub defining_module: String,
60}
61
62#[derive(Clone, Debug)]
63pub struct StoredTraitImpl {
64 pub def: TraitImpl,
65 pub defining_module: String,
66}
67
68#[derive(Clone, Debug)]
69pub struct StoredConst {
70 pub ident: Token,
71 pub value: Value,
72}
73
74#[derive(Debug, Clone)]
75pub enum ExportType {
76 Function(Fn),
77 Trait(TraitDef),
78 Struct(StoredStruct),
79 Const(StoredConst),
80}
81
82#[derive(Debug, Clone)]
84pub enum StoredFunction {
85 Native(NativeFunction),
86 Function {
87 function: Fn,
88 defining_module: String,
89 },
90}
91
92#[derive(Clone)]
93pub struct Module {
94 pub source: Source,
95 pub path: Option<PathBuf>,
96 pub tokens: Vec<Token>,
97 pub ast: Ast,
98 pub functions: Vec<StoredFunction>,
99 pub exports: Vec<(String, ExportType)>,
100 pub scopes: Vec<HashMap<String, Value>>,
101 pub structs: Vec<StoredStruct>,
102 pub traits: Vec<TraitDef>,
103 pub consts: Vec<StoredConst>,
104 pub id: String,
105 pub lex_comments: bool
106}
107
108impl Debug for Module {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 f.debug_struct("Module")
111 .field("path", &self.path)
112 .field("source", &self.source)
113 .field("exports", &self.exports)
117 .field("scopes", &self.scopes)
118 .field("structs", &self.structs)
119 .field("traits", &self.traits)
120 .field("consts", &self.consts)
121 .finish()
122 }
123}
124
125impl Module {
126 pub fn new(source: Source) -> Self {
134 let path = source.path().as_deref().map(Path::to_path_buf);
135
136 Self {
137 source,
138 path,
139 tokens: vec![],
140 functions: get_stored_function(),
141 exports: vec![],
142 scopes: vec![HashMap::new()],
143 ast: Ast::new(),
144 structs: vec![],
145 traits: vec![],
146 consts: vec![],
147 id: Uuid::new_v4().to_string(),
148 lex_comments: false,
149 }
150 }
151
152 pub fn set_lex_comments(&mut self, lex_comments: bool) {
153 self.lex_comments = lex_comments;
154 }
155
156 pub fn id(&self) -> String {
158 self.id.clone()
159 }
160
161 pub fn path(&self) -> Option<PathBuf> {
163 self.path.clone()
164 }
165
166 pub fn source(&self) -> &Source {
168 &self.source
169 }
170
171 pub fn tokens(&self) -> &Vec<Token> {
173 &self.tokens
174 }
175
176 pub fn parse(&mut self) -> Result<()> {
180 debug!("Parsing module from source");
181 let mut lexer = Lexer::new(self.source.clone());
182
183 let tokens = lexer.lex(self.lex_comments)?;
184 debug!("Parsed {} tokens", tokens.len());
185 self.tokens = tokens;
186
187 let mut parser = Parser::new(self.tokens.clone());
188
189 debug!("Parsing tokens into AST");
190 let ast = parser.parse()?;
191 self.ast = ast;
192
193 Ok(())
194 }
195
196 pub fn interpret(&mut self, ctx: &mut Context, vm: &mut VM) -> Result<()> {
197 for stmt in self.ast.stmts.clone() {
198 match self.interpret_stmt(stmt, ctx, vm) {
199 Ok(_) => {}
200 Err(e) => {
201 print_diagnostic(e, Some(self.source.content()));
202 std::process::exit(1);
203 }
204 }
205 }
206
207 Ok(())
208 }
209
210 pub fn enter_scope(&mut self) {
212 debug!("Entering new scope");
213 self.scopes.push(HashMap::new());
214 }
215
216 pub fn exit_scope(&mut self) {
218 debug!("Exiting current scope");
219 self.scopes.pop();
220 }
221
222 pub fn declare_variable(&mut self, name: String, val: Value) {
224 debug!("Declaring variable '{}' in current scope", name);
225 if let Some(current_scope) = self.scopes.last_mut() {
226 current_scope.insert(name, val);
227 }
228 }
229
230 pub fn set_variable(&mut self, name: &str, val: Value) -> Result<()> {
232 for scope in self.scopes.iter_mut().rev() {
233 if scope.contains_key(name) {
234 debug!("Setting variable '{}' to {:?}", name, val);
235 scope.insert(name.to_string(), val);
236 return Ok(());
237 }
238 }
239 Err(VariableNotFoundError(name.to_string(), TextSpan::default()).into())
241 }
242
243 pub fn find_variable(&self, name: &str) -> Option<&Value> {
245 for scope in self.scopes.iter().rev() {
246 if let Some(val) = scope.get(name) {
247 debug!("Found variable '{}' with value {:?}", name, val);
248 return Some(val);
249 }
250 }
251 debug!("Variable '{}' not found in any scope", name);
252 None
253 }
254
255 pub fn find_const(&self, name: &str) -> Option<&StoredConst> {
257 self.consts.iter().find(|c| c.ident.literal() == name)
258 }
259
260 pub fn name(&self) -> String {
261 self.path()
262 .unwrap()
263 .file_stem()
264 .unwrap()
265 .to_string_lossy()
266 .to_string()
267 }
268
269 pub fn extract_variable_name(expr: &Expr) -> Option<String> {
270 match expr {
271 Expr::Variable(v) => Some(v.ident.clone()),
272 Expr::Access(access) => Self::extract_variable_name(&access.base),
273 _ => None,
274 }
275 }
276
277 pub fn find_function(&self, name: &str) -> Option<&StoredFunction> {
279 debug!("Looking for function: {}", name);
280
281 self.functions.iter().find(|f| match f {
282 StoredFunction::Native(n) => n.name == name,
283 StoredFunction::Function { function, .. } => function.name == name,
284 })
285 }
286
287 pub fn update_variable(
288 &mut self,
289 name: &str,
290 val: Value,
291 func: fn(Value, Value) -> Value,
292 ) -> Result<()> {
293 let variable = self
294 .find_variable(name)
295 .ok_or_else(|| VariableNotFoundError(name.to_string(), TextSpan::default()))?;
296
297 let new_val = func(variable.clone(), val);
298 self.set_variable(name, new_val)?;
299 Ok(())
300 }
301}