roan_engine/interpreter/
functions.rs1use crate::{
2 context::Context,
3 module::{Module, StoredFunction},
4 value::Value,
5 vm::{native_fn::NativeFunction, VM},
6};
7use anyhow::Result;
8use roan_ast::{CallExpr, GetSpan};
9use roan_error::{
10 error::RoanError::{MissingParameter, TypeMismatch, UndefinedFunctionError},
11 frame::Frame,
12 print_diagnostic, TextSpan,
13};
14use tracing::debug;
15
16impl Module {
17 pub fn execute_native_function(
19 &mut self,
20 mut native: NativeFunction,
21 args: Vec<Value>,
22 vm: &mut VM,
23 ) -> Result<()> {
24 let result = native.call(args)?;
25 vm.push(result);
26
27 Ok(())
28 }
29
30 pub fn execute_user_defined_function(
32 &mut self,
33 function: roan_ast::Fn,
34 def_module: &mut Module,
35 args: Vec<Value>,
36 ctx: &mut Context,
37 vm: &mut VM,
38 call: &CallExpr,
39 ) -> Result<()> {
40 debug!("Executing user-defined function: {}", function.name);
41
42 self.enter_scope();
43
44 {
45 let exprs = call
46 .args
47 .iter()
48 .map(|arg| arg.span())
49 .collect::<Vec<TextSpan>>();
50
51 let mut offset = 0;
52 for (i, (param, arg)) in function
53 .params
54 .iter()
55 .zip(args.iter().chain(std::iter::repeat(&Value::Null)))
56 .enumerate()
57 {
58 let ident = param.ident.literal();
59 if ident == "self" {
61 offset += 1;
62
63 def_module.declare_variable(ident, arg.clone());
64 continue;
65 }
66
67 let expr = exprs.get(i - offset);
68 if param.is_rest {
69 let rest: Vec<Value> = args
70 .iter()
71 .skip(function.params.len() - 1)
72 .cloned()
73 .collect();
74
75 if expr.is_none() {
76 def_module.declare_variable(ident, Value::Vec(rest));
77 } else {
78 if let Some(_type) = param.type_annotation.as_ref() {
79 for arg in &rest {
80 if _type.is_any() {
81 continue;
82 };
83
84 arg.check_type(&_type.type_name.literal(), expr.unwrap().clone())?;
85 }
86 }
87
88 def_module.declare_variable(ident, Value::Vec(rest));
89 }
90 } else {
91 if let Some(_type) = param.type_annotation.as_ref() {
92 if arg.is_null() && _type.is_nullable {
93 def_module.declare_variable(ident, Value::Null);
94 continue;
95 }
96
97 if expr.is_none() {
98 return Err(MissingParameter(ident.clone(), call.span()).into());
99 }
100
101 if arg.is_null() && !_type.is_nullable {
102 return Err(TypeMismatch(
103 format!("Expected type {} but got null", _type.type_name.literal()),
104 expr.unwrap().clone(),
105 )
106 .into());
107 }
108
109 if _type.is_array {
110 match arg {
111 Value::Vec(vec) => {
112 for arg in vec {
113 if _type.is_any() {
114 continue;
115 };
116
117 arg.check_type(
118 &_type.type_name.literal(),
119 expr.unwrap().clone(),
120 )?;
121 }
122 def_module.declare_variable(ident.clone(), arg.clone());
123 }
124 _ => {
125 return Err(TypeMismatch(
126 format!(
127 "Expected array type {} but got {}",
128 _type.type_name.literal(),
129 arg.type_name()
130 ),
131 expr.unwrap().clone(),
132 )
133 .into());
134 }
135 }
136 } else {
137 if arg.is_null() && !_type.is_nullable && !_type.is_any() {
138 arg.check_type(&_type.type_name.literal(), expr.unwrap().clone())?;
139 }
140 def_module.declare_variable(ident, arg.clone());
141 }
142 } else {
143 def_module.declare_variable(ident, arg.clone());
144 }
145 }
146 }
147 }
148
149 let frame = Frame::new(
150 function.name.clone(),
151 function.fn_token.span.clone(),
152 Frame::path_or_unknown(def_module.path()),
153 );
154 vm.push_frame(frame);
155
156 for stmt in function.body.stmts {
157 def_module.interpret_stmt(stmt, ctx, vm)?;
158 }
159
160 vm.pop_frame();
161 self.exit_scope();
162
163 Ok(())
164 }
165
166 pub fn interpret_call(
175 &mut self,
176 call: &CallExpr,
177 ctx: &mut Context,
178 vm: &mut VM,
179 ) -> Result<Value> {
180 log::debug!("Interpreting call");
181
182 let args = self.interpret_possible_spread(call.args.clone(), ctx, vm)?;
183
184 let stored_function = self
185 .find_function(&call.callee)
186 .ok_or_else(|| UndefinedFunctionError(call.callee.clone(), call.token.span.clone()))?
187 .clone();
188
189 match stored_function {
190 StoredFunction::Native(n) => {
191 self.execute_native_function(n, args, vm)?;
192
193 Ok(vm.pop().unwrap())
194 }
195 StoredFunction::Function {
196 function,
197 defining_module,
198 } => {
199 let mut def_module = ctx.query_module(&defining_module).unwrap();
200
201 match self.execute_user_defined_function(
202 function,
203 &mut def_module,
204 args,
205 ctx,
206 vm,
207 call,
208 ) {
209 Ok(_) => Ok(vm.pop().unwrap_or(Value::Void)),
210 Err(e) => {
211 print_diagnostic(e, Some(def_module.source.content()));
212 std::process::exit(1);
213 }
214 }
215 }
216 }
217 }
218}