1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//! The top level of Dust's API with functions in interpret Dust code.

use crate::{token, tree, Result, Value, VariableMap};

/// Evaluate the given expression string.
///
/// # Examples
///
/// ```rust
/// # use dust_lib::*;
/// assert_eq!(eval("1 + 2 + 3"), Ok(Value::from(6)));
/// ```
///
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
pub fn eval(string: &str) -> Result<Value> {
    let mut context = VariableMap::new();
    eval_with_context(string, &mut context)
}

/// Evaluate the given expression string with the given context.
///
/// # Examples
///
/// ```rust
/// # use dust_lib::*;
/// let mut context = VariableMap::new();
/// context.set_value("one".into(), 1.into()).unwrap(); // Do proper error handling here
/// context.set_value("two".into(), 2.into()).unwrap(); // Do proper error handling here
/// context.set_value("three".into(), 3.into()).unwrap(); // Do proper error handling here
/// assert_eq!(eval_with_context("one + two + three", &mut context), Ok(Value::from(6)));
/// ```
pub fn eval_with_context(input: &str, context: &mut VariableMap) -> Result<Value> {
    let without_comments = input
        .lines()
        .map(|line| {
            let split = line.split_once('#');

            if let Some((code, _comment)) = split {
                code
            } else {
                line
            }
        })
        .collect::<String>();

    let split = without_comments.split_once("->");

    if let Some((left, right)) = split {
        let left_result = tree::tokens_to_operator_tree(token::tokenize(left)?)?
            .eval_with_context_mut(context)?;

        context.set_value("input", left_result)?;

        let right_result = eval_with_context(right, context)?;

        Ok(right_result)
    } else {
        tree::tokens_to_operator_tree(token::tokenize(&without_comments)?)?
            .eval_with_context_mut(context)
    }
}