1use bigdecimal::ToPrimitive;
2
3use super::{builtins::Builtins, environment::Environment};
4use crate::{
5 ast::*,
6 errors::{Error as OYError, ErrorKind, Result as OYResult, SpanError},
7 utils,
8};
9
10#[derive(Debug, Default)]
12pub struct Interpreter {
13 environment: Environment,
15}
16
17impl Interpreter {
18 pub fn new() -> Self {
20 Self {
21 environment: Environment::new(),
22 }
23 }
24
25 pub fn interpret(mut self, program: Program, argc: usize, argv: Vec<String>) -> OYResult<u8> {
27 let mut exit_code = 0;
28 for function in program.0 {
30 match function {
31 Statement::Function(function) => {
32 self.environment.add_global_function(function)?;
33 }
34 _ => unreachable!("The program only contains functions"),
35 }
36 }
37
38 if let Some(main_function) = self.environment.get_global_function("main") {
40 let args = vec![
41 Arg {
42 expr: ExpressionStatement::Value(ValueExpression::Object(
43 ObjectExpression::Int(argc.to_string().parse().unwrap(), Span::new(0, 0)),
44 )),
45 is_unpack: false,
46 span: Span::new(0, 0),
47 },
48 Arg {
49 expr: ExpressionStatement::Value(ValueExpression::Object(
50 ObjectExpression::Array(
51 argv.into_iter()
52 .map(|v| {
53 ExpressionStatement::Value(ValueExpression::Object(
54 ObjectExpression::String(v, Span::new(0, 0)),
55 ))
56 })
57 .collect(),
58 Span::new(0, 0),
59 ),
60 )),
61 is_unpack: false,
62 span: Span::new(0, 0),
63 },
64 ];
65 exit_code = match self.execute_function(main_function, args)? {
66 ObjectExpression::Int(int, span) => int
67 .to_u8()
68 .ok_or_else(|| OYError::new(ErrorKind::InvalidExitCode(int), span))?,
69 _ => exit_code,
70 };
71 Ok(exit_code)
72 } else {
73 Err(OYError::new(ErrorKind::MissingMainFunction, (0, 0)))
74 }
75 }
76
77 pub fn execute_function(
82 &mut self,
83 function: FunctionStatement,
84 args: Vec<Arg>,
85 ) -> OYResult<ObjectExpression> {
86 self.environment.new_for_function(function.params, args)?;
87 let mut result = ObjectExpression::Nil(function.span);
88 if let Some(block) = function.block {
89 for statement in block.statements {
90 if let Some(return_value) = self.execute_statement(statement)? {
91 result = return_value;
92 break;
93 }
94 }
95 } else {
96 unreachable!("The builtin function should call in the call expression")
97 }
98 self.environment.exit_frame();
99 Ok(result)
100 }
101
102 pub fn execute_statement(
105 &mut self,
106 statement: Statement,
107 ) -> OYResult<Option<ObjectExpression>> {
108 match statement {
109 Statement::Function(function) => {
110 self.environment.add_local_function(function).map(|_| None)
111 }
112 Statement::Assignment(assign) => self.execute_assign(assign).map(|_| None),
113 Statement::Return(return_stmt) => {
114 let return_value = self.execute_expression(return_stmt.value)?;
115 Ok(Some(return_value))
116 }
117 Statement::Expression(expr) => {
118 self.execute_expression(expr)?;
119 Ok(None)
120 }
121 }
122 }
123
124 pub fn execute_assign(&mut self, assign: AssignmentStatement) -> OYResult<()> {
127 let object = self.execute_expression(assign.expression)?;
128 let assign = AssignmentStatement {
129 ident: assign.ident,
130 expression: ExpressionStatement::Value(ValueExpression::Object(object)),
131 span: assign.span,
132 };
133 self.environment.add_variable(assign)?;
134 Ok(())
135 }
136
137 pub fn execute_expression(&mut self, expr: ExpressionStatement) -> OYResult<ObjectExpression> {
140 match expr {
141 ExpressionStatement::FunctionCall(func_call) => self.execute_function_call(func_call),
142 ExpressionStatement::Value(value) => self.execute_value(value),
143 }
144 }
145
146 pub fn execute_function_call(
149 &mut self,
150 func_call: FunctionCallExpression,
151 ) -> OYResult<ObjectExpression> {
152 let function = match func_call.callable {
153 ValueExpression::Ident(ident) => {
154 let function = self.environment.take(&ident.ident, func_call.span)?;
155 match function {
156 Statement::Assignment(assign) => match assign.expression {
157 ExpressionStatement::Value(ValueExpression::Object(
158 ObjectExpression::Function(function),
159 )) => function,
160 _ => {
161 return Err(OYError::new(
162 ErrorKind::NotCallable(func_call.span.span()),
163 assign.span,
164 ));
165 }
166 },
167 Statement::Function(function) => function,
168 _ => {
169 return Err(OYError::new(
170 ErrorKind::NotCallable(func_call.span.span()),
171 function.span(),
172 ));
173 }
174 }
175 }
176 ValueExpression::Object(ObjectExpression::Function(anonymous_function)) => {
177 anonymous_function
178 }
179 _ => unreachable!(
180 "The function call can only be an anonymous function or a function identifier"
181 ),
182 };
183
184 let args = if func_call.args.iter().any(|arg| arg.is_unpack) {
185 utils::unpack_args(self, func_call.args)?
186 } else {
187 func_call.args
188 };
189 let args = if args.len() >= function.params.len()
190 && function.params.last().map(|p| p.is_pack).unwrap_or(false)
191 {
192 utils::pack_args(self, &function, args)?
193 } else {
194 args
195 };
196 if function.params.len() != args.len() {
197 return Err(OYError::new(
198 ErrorKind::UncorrectArguments(
199 args.len(),
200 function
201 .ident
202 .clone()
203 .map_or_else(|| function.span.span(), |ident| ident.span.span()),
204 function.params,
205 function
206 .ident
207 .map_or_else(|| "Anonymous function".to_owned(), |ident| ident.ident),
208 ),
209 func_call.span,
210 ));
211 }
212 if function.block.is_none() {
213 Builtins::execute_builtin_funtion(
214 &function.ident.unwrap().ident,
215 func_call.span,
216 args.into_iter()
217 .map(|arg| {
218 let arg_span = arg.span;
219 let mut expr = self.execute_expression(arg.expr)?;
220 *expr.span_mut() = arg_span;
221 Ok(expr)
222 })
223 .collect::<OYResult<Vec<ObjectExpression>>>()?,
224 )
225 } else {
226 self.execute_function(function, args)
227 }
228 }
229
230 pub fn execute_value(&mut self, value: ValueExpression) -> OYResult<ObjectExpression> {
233 match value {
234 ValueExpression::Object(ObjectExpression::Array(arr, _)) => {
235 let mut result = Vec::new();
236 for expr in arr {
237 result.push(ExpressionStatement::Value(ValueExpression::Object(
238 self.execute_expression(expr)?,
239 )));
240 }
241 Ok(ObjectExpression::Array(result, Span::new(0, 0)))
242 }
243 ValueExpression::Object(obj) => Ok(obj),
244 ValueExpression::Ident(ident) => {
245 match self.environment.take(&ident.ident, ident.span)? {
246 Statement::Assignment(assign) => self.execute_expression(assign.expression),
247 Statement::Function(function) => Ok(ObjectExpression::Function(function)),
248 _ => unreachable!(),
249 }
250 }
251 }
252 }
253}