1use std::cell::RefCell;
51use std::ops::ControlFlow;
52use std::ops::ControlFlow::{Break, Continue};
53use std::rc::Rc;
54
55use ast::expression::{Binary, Expression, FunctionCall, Identifier, Selection, Unary};
56use ast::literal::Literal;
57use ast::statement::{
58 Display, FunctionDeclaration, RepeatForever, RepeatNTimes, RepeatUntil, Return, Set, Statement,
59};
60use ast::Program;
61use lexer::token::TokenKind;
62use shared::error::{Error, ErrorKind};
63use shared::{err, stdoutln};
64
65use crate::runtime::{EnvRef, Environment};
66use crate::value::{Function, Value};
67
68pub const VERSION: Option<&str> = std::option_env!("CARGO_PKG_VERSION");
70
71#[cfg(test)]
72mod test;
73
74pub mod runtime;
75pub mod value;
76
77pub enum TraversalInterrupt {
89 ReturnValue(Rc<Value>),
90 Error(Error),
91}
92
93type EvaluationOutcome = ControlFlow<TraversalInterrupt, Rc<Value>>;
99
100macro_rules! traversal_error {
111 ($kind:expr, $($arg:tt)*) => {
112 Break(TraversalInterrupt::Error(Error::new(&format!($($arg)*), $kind)))
113 };
114 ($err:ident) => {
115 Break(TraversalInterrupt::Error($err))
116 }
117}
118
119pub fn create_env() -> EnvRef {
121 return Rc::new(RefCell::new(Environment::new()));
122}
123
124pub fn eval_program(env: &EnvRef, ast: Program) -> Result<(EnvRef, Rc<Value>), Error> {
139 match eval_statements(env, &ast.statements) {
140 Break(TraversalInterrupt::ReturnValue(_)) => {
141 err!(ErrorKind::TypeError, "'return' used outside of function")
142 }
143 Break(TraversalInterrupt::Error(error)) => Err(error),
144 Continue(value) => Ok((env.clone(), value)),
145 }
146}
147
148fn eval_statements(env: &EnvRef, statements: &Vec<Statement>) -> EvaluationOutcome {
150 let mut value = Rc::new(Value::Null);
151 for statement in statements {
152 value = eval_statement(env, &statement)?;
153 }
154 return Continue(value);
155}
156
157fn eval_statement(env: &EnvRef, statement: &Statement) -> EvaluationOutcome {
159 match statement {
160 Statement::Expression(expression) => eval_expression(env, expression),
161 Statement::Return(ret) => eval_return_statement(env, ret),
162 Statement::Set(set_stmt) => eval_set_statement(env, set_stmt),
163 Statement::FunctionDeclaration(func) => eval_func_decl_statement(env, func),
164 Statement::RepeatNTimes(repeat) => eval_repeat_n_times_statement(env, repeat),
165 Statement::RepeatUntil(repeat) => eval_repeat_until_statement(env, repeat),
166 Statement::RepeatForever(repeat) => eval_repeat_forever_statement(env, repeat),
167 Statement::Display(display) => eval_display_statement(env, display),
168 }
169}
170
171fn eval_set_statement(env: &EnvRef, let_stmt: &Set) -> EvaluationOutcome {
174 let value = eval_expression(env, &let_stmt.expr)?;
175 let name = let_stmt.ident.name.clone();
176 env.borrow_mut().store(name, value);
177 return Continue(Rc::new(Value::Null));
178}
179
180fn eval_return_statement(env: &EnvRef, ret: &Return) -> EvaluationOutcome {
183 let value = eval_expression(env, &ret.value)?;
184 return Break(TraversalInterrupt::ReturnValue(value));
185}
186
187fn eval_func_decl_statement(env: &EnvRef, func: &FunctionDeclaration) -> EvaluationOutcome {
190 let parameters = func
191 .parameters
192 .iter()
193 .map(|ident| ident.name.clone())
194 .collect();
195
196 let name = func.name.name.clone();
197 let value = Rc::new(Value::Function(Function {
198 parameters,
199 body: func.body.statements.clone(),
200 env: env.clone(),
201 }));
202
203 env.borrow_mut().store(name, value);
204 return Continue(Rc::new(Value::Null));
205}
206
207fn eval_display_statement(env: &EnvRef, display: &Display) -> EvaluationOutcome {
210 let mut values = Vec::new();
213 for expression in &display.expressions {
214 match eval_expression(env, expression)?.cast_to_string() {
215 Value::String(s) => values.push(s),
216 _ => unreachable!(),
217 };
218 }
219 stdoutln!("{}", values.join(" "));
220 return Continue(Rc::new(Value::Null));
221}
222
223fn eval_repeat_forever_statement(env: &EnvRef, repeat: &RepeatForever) -> EvaluationOutcome {
225 loop {
226 eval_statements(env, &repeat.body.statements)?;
227 }
228}
229
230fn eval_repeat_n_times_statement(env: &EnvRef, repeat: &RepeatNTimes) -> EvaluationOutcome {
232 let n_rc = eval_expression(env, &repeat.n)?;
234 let n = match n_rc.as_ref() {
235 Value::Integer(n) => {
236 if *n < 0 {
237 return traversal_error!(
238 ErrorKind::TypeError,
239 "repeat _ times expected non-negative integer, got '{}'",
240 n
241 );
242 }
243 *n as usize
244 }
245 _ => {
246 return traversal_error!(
247 ErrorKind::TypeError,
248 "repeat _ times expected non-negative integer, got type {}",
249 n_rc.variant_name()
250 )
251 }
252 };
253
254 for _ in 0..n {
256 eval_statements(env, &repeat.body.statements)?;
257 }
258
259 return Continue(Rc::new(Value::Null));
261}
262
263fn eval_repeat_until_statement(env: &EnvRef, repeat: &RepeatUntil) -> EvaluationOutcome {
266 loop {
267 let condition = eval_expression(env, &repeat.condition)?.cast_to_boolean();
269 let condition_value = match condition {
270 Ok(value) => value,
271 Err(e) => return traversal_error!(e),
272 };
273 if let Value::Boolean(true) = condition_value {
274 break;
275 }
276 eval_statements(env, &repeat.body.statements)?;
278 }
279
280 return Continue(Rc::new(Value::Null));
282}
283
284fn eval_expression(env: &EnvRef, expression: &Expression) -> EvaluationOutcome {
286 match expression {
287 Expression::Literal(literal) => eval_literal(literal),
288 Expression::Unary(unary) => eval_unary_expression(env, unary),
289 Expression::Binary(binary) => eval_binary_expression(env, binary),
290 Expression::Selection(selection) => eval_selection_expression(env, selection),
291 Expression::Identifier(ident) => eval_identifier_expression(env, ident),
292 Expression::FunctionCall(func_call) => eval_func_call_expression(env, func_call),
293 _ => traversal_error!(
296 ErrorKind::NotImplemented,
297 "expression type '{}' has not been implemented by the interpreter",
298 expression
299 ),
300 }
301}
302
303fn eval_literal(literal: &Literal) -> EvaluationOutcome {
305 let result = match literal {
306 Literal::Integer { value, .. } => Ok(Value::Integer(*value)),
307 Literal::Float { value, .. } => Ok(Value::Float(*value)),
308 Literal::Boolean { value, .. } => Ok(Value::Boolean(*value)),
309 Literal::String { value, .. } => Ok(Value::String(value.to_owned())),
310 };
311 match result {
312 Ok(value) => Continue(Rc::new(value)),
313 Err(e) => traversal_error!(e),
314 }
315}
316
317fn eval_unary_expression(env: &EnvRef, unary: &Unary) -> EvaluationOutcome {
319 let left_rc = eval_expression(env, &unary.operand)?;
321 let left = left_rc.as_ref();
322
323 let result = match unary.operator {
325 TokenKind::Not => left.not(),
326 TokenKind::Minus => left.neg(),
327 _ => {
328 return traversal_error!(
329 ErrorKind::TypeError,
330 "invalid operation '{}' for type {}",
331 unary.operator,
332 left.variant_name(),
333 )
334 }
335 };
336 match result {
337 Ok(value) => Continue(Rc::new(value)),
338 Err(e) => traversal_error!(e),
339 }
340}
341
342fn eval_binary_expression(env: &EnvRef, binary: &Binary) -> EvaluationOutcome {
344 let left_rc = eval_expression(env, &binary.left)?;
346 let right_rc = eval_expression(env, &binary.right)?;
347
348 let left = left_rc.as_ref();
350 let right = right_rc.as_ref();
351
352 let result = match binary.operator {
354 TokenKind::Plus => left.add(right),
355 TokenKind::Minus => left.sub(right),
356 TokenKind::Mult => left.mul(right),
357 TokenKind::Div => left.div(right),
358 TokenKind::Eq => left.eq(right),
359 TokenKind::NotEq => left.ne(right),
360 TokenKind::Lt => left.lt(right),
361 TokenKind::LtEq => left.le(right),
362 TokenKind::Gt => left.gt(right),
363 TokenKind::GtEq => left.ge(right),
364 TokenKind::And => left.and(right),
365 TokenKind::Or => left.or(right),
366 TokenKind::Mod => left.rem(right),
367 _ => {
368 return traversal_error!(
369 ErrorKind::TypeError,
370 "invalid operation '{}' between {} and {}",
371 binary.operator,
372 left.variant_name(),
373 right.variant_name(),
374 )
375 }
376 };
377 match result {
378 Ok(value) => Continue(Rc::new(value)),
379 Err(e) => traversal_error!(e),
380 }
381}
382
383fn eval_selection_expression(env: &EnvRef, selection: &Selection) -> EvaluationOutcome {
385 let result = eval_expression(env, &selection.condition)?.cast_to_boolean();
387 let condition_value = match result {
388 Ok(value) => value,
389 Err(e) => return traversal_error!(e),
390 };
391
392 match condition_value {
395 Value::Boolean(b) => {
396 if b {
397 eval_statements(env, &selection.conditional.statements)
398 } else if let Some(else_conditional) = &selection.else_conditional {
399 eval_statements(env, &else_conditional.statements)
400 } else {
401 Continue(Rc::new(Value::Null))
402 }
403 }
404 _ => unreachable!(),
407 }
408}
409
410fn eval_identifier_expression(env: &EnvRef, ident: &Identifier) -> EvaluationOutcome {
412 return lookup_variable_name(env, &ident.name);
413}
414
415fn eval_func_call_expression(env: &EnvRef, func_call: &FunctionCall) -> EvaluationOutcome {
417 let callee = eval_expression(env, &func_call.callee)?;
419
420 let mut arguments = Vec::new();
422 for expression in &func_call.arguments {
423 let value = eval_expression(env, expression)?;
424 arguments.push(value);
425 }
426
427 return apply_function(&callee, &arguments);
428}
429
430fn apply_function(callee: &Rc<Value>, arguments: &Vec<Rc<Value>>) -> EvaluationOutcome {
435 match &**callee {
436 Value::Function(function) => {
437 let mut env = Environment::new_enclosed_environment(&function.env);
439
440 for (param_name, arg_value) in function.parameters.iter().zip(arguments.iter()) {
442 env.store(param_name.clone(), arg_value.clone())
443 }
444
445 match eval_statements(&Rc::new(RefCell::new(env)), &function.body) {
447 Break(TraversalInterrupt::ReturnValue(value)) => Continue(value),
448 Break(TraversalInterrupt::Error(err)) => traversal_error!(err),
449 _ => Continue(Rc::new(Value::Null)),
450 }
451 }
452 _ => traversal_error!(
453 ErrorKind::TypeError,
454 "'{}' is not callable",
455 callee.variant_name(),
456 ),
457 }
458}
459
460fn lookup_variable_name(env: &EnvRef, name: &str) -> EvaluationOutcome {
463 if let Some(value) = env.borrow().lookup(name) {
464 Continue(value)
465 } else {
466 traversal_error!(ErrorKind::NameError, "variable '{}' does not exist", name)
467 }
468}