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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Abstract, executable representations of corresponding items found in Dust
//! source code. The types that implement [AbstractTree] are inteded to be
//! created by an [Evaluator].
//!
//! When adding new lanugage features, first extend the grammar to recognize new
//! syntax nodes. Then add a new AbstractTree type using the existing types as
//! examples.

pub mod assignment;
pub mod block;
pub mod built_in_value;
pub mod expression;
pub mod r#for;
pub mod function_call;
pub mod function_expression;
pub mod identifier;
pub mod if_else;
pub mod index;
pub mod index_assignment;
pub mod index_expression;
pub mod logic;
pub mod r#match;
pub mod math;
pub mod statement;
pub mod type_definition;
pub mod value_node;
pub mod r#while;
pub mod r#yield;

pub use {
    assignment::*, block::*, built_in_value::*, expression::*, function_call::*,
    function_expression::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment,
    index_expression::*, logic::*, math::*, r#for::*, r#match::*, r#while::*, r#yield::*,
    statement::*, type_definition::*, value_node::*,
};

use tree_sitter::Node;

use crate::{Error, Map, Result, Value};

pub struct Root {
    statements: Vec<Statement>,
}

impl AbstractTree for Root {
    fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
        Error::expect_syntax_node(source, "root", node)?;

        let statement_count = node.child_count();
        let mut statements = Vec::with_capacity(statement_count);

        for index in 0..statement_count {
            let statement_node = node.child(index).unwrap();
            let statement = Statement::from_syntax_node(source, statement_node, context)?;

            statements.push(statement);
        }

        Ok(Root { statements })
    }

    fn run(&self, source: &str, context: &Map) -> Result<Value> {
        let mut value = Value::none();

        for statement in &self.statements {
            if let Statement::Return(inner_statement) = statement {
                return inner_statement.run(source, context);
            } else {
                value = statement.run(source, context)?;
            }
        }

        Ok(value)
    }

    fn expected_type(&self, context: &Map) -> Result<Type> {
        self.statements.last().unwrap().expected_type(context)
    }
}

/// This trait is implemented by the Evaluator's internal types to form an
/// executable tree that resolves to a single value.
pub trait AbstractTree: Sized {
    /// Interpret the syntax tree at the given node and return the abstraction.
    ///
    /// This function is used to convert nodes in the Tree Sitter concrete
    /// syntax tree into executable nodes in an abstract tree. This function is
    /// where the tree should be traversed by accessing sibling and child nodes.
    /// Each node in the CST should be traversed only once.
    ///
    /// If necessary, the source code can be accessed directly by getting the
    /// node's byte range.
    fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self>;

    /// Execute dust code by traversing the tree.
    fn run(&self, source: &str, context: &Map) -> Result<Value>;

    fn expected_type(&self, context: &Map) -> Result<Type>;
}