bean_script/
evaluator.rs

1use std::{borrow::Borrow, cell::RefCell, rc::Rc};
2
3use crate::{
4	data::Data,
5	error::{BeanResult, Error, ErrorSource},
6	parser::{Node, PosNode},
7	scope::{block_scope::BlockScope, function::Function, ScopeRef},
8};
9
10pub fn evaluate_verbose(
11	pos_node: &PosNode,
12	scope_ref: ScopeRef,
13	return_scope: bool,
14	access_scope_ref: Option<ScopeRef>,
15) -> Result<Data, Error> {
16	match &pos_node.node {
17		Node::FnCall {
18			name,
19			parameters,
20			body_fn,
21		} => {
22			let scope = RefCell::borrow(&scope_ref);
23			let function = scope.get_function(&name).ok_or_else(|| {
24				Error::new(
25					&format!("Unknown value or function {}.", name),
26					ErrorSource::Line(pos_node.ln),
27				)
28			})?;
29			drop(scope);
30
31			let mut args: Vec<Data> = Vec::new();
32			for n in parameters {
33				args.push(evaluate(
34					n,
35					Rc::clone(access_scope_ref.as_ref().unwrap_or(&scope_ref)),
36				)?);
37			}
38
39			let return_value = function
40				.call_from(
41					args,
42					if let Some(body) = body_fn {
43						Some(Function::Custom {
44							body: Rc::new(*body.clone()),
45							scope_ref: Rc::clone(
46								access_scope_ref.as_ref().unwrap_or(&scope_ref),
47							),
48						})
49					} else {
50						None
51					},
52					Rc::clone(&scope_ref),
53					access_scope_ref,
54				)
55				.trace(ErrorSource::Line(pos_node.ln));
56
57			return return_value;
58		}
59		Node::Scope { body } => {
60			let scope = BlockScope::new(Some(Rc::clone(&scope_ref)));
61			let scope_ref = Rc::new(RefCell::new(scope));
62
63			for n in body {
64				evaluate(n, Rc::clone(&scope_ref) as ScopeRef)?;
65				if RefCell::borrow(&scope_ref).did_break() {
66					break;
67				}
68			}
69
70			let scope: &RefCell<BlockScope> = scope_ref.borrow();
71			let return_value = scope.borrow().return_value.clone();
72			return if return_scope {
73				Ok(Data::Scope(scope_ref))
74			} else {
75				Ok(return_value)
76			};
77		}
78		Node::ParameterBlock { body } => {
79			let mut return_value: Data = Data::None;
80			for n in body {
81				return_value = evaluate(n, Rc::clone(&scope_ref))?;
82			}
83
84			return Ok(return_value);
85		}
86		Node::Program { body } => {
87			for n in body {
88				evaluate(n, Rc::clone(&scope_ref))?;
89			}
90			return Ok(Data::None);
91		}
92		Node::FnAccess { target, call } => {
93			let target = evaluate(target, Rc::clone(&scope_ref))?;
94
95			if let Data::Scope(target_scope) = target {
96				evaluate_verbose(
97					&call,
98					Rc::clone(&target_scope),
99					false,
100					Some(Rc::clone(access_scope_ref.as_ref().unwrap_or(&scope_ref))),
101				)
102			} else {
103				return Err(Error::new(
104					&format!(
105						"Expected scope for dot operator, but got {}.",
106						target.get_type().to_string()
107					),
108					ErrorSource::Line(pos_node.ln),
109				));
110			}
111		}
112		Node::Boolean(v) => Ok(Data::Boolean(*v)),
113		Node::Number(v) => Ok(Data::Number(*v)),
114		Node::String(v) => Ok(Data::String(v.clone())),
115		Node::Name(name) => Ok(Data::Name {
116			scope: Rc::clone(&scope_ref),
117			name: name.clone(),
118		}),
119		Node::None => Ok(Data::None),
120	}
121}
122
123pub fn evaluate(node: &PosNode, scope_ref: ScopeRef) -> Result<Data, Error> {
124	evaluate_verbose(node, scope_ref, false, None)
125}