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}