diff --git a/src/abstract_tree/tool.rs b/src/abstract_tree/tool.rs index d1acf75..4119b9e 100644 --- a/src/abstract_tree/tool.rs +++ b/src/abstract_tree/tool.rs @@ -515,6 +515,26 @@ impl AbstractTree for Tool { Ok(Value::String(String::from_utf8(output)?)) } Tool::Random(expressions) => { + if expressions.len() == 1 { + let value = expressions[0].run(source, context)?; + let list = value.as_list()?; + + if list.len() < 2 { + return Err(Error::ExpectedMinLengthList { + minimum_len: 2, + actual_len: list.len(), + }); + } + + let range = 0..list.len(); + let random_index = thread_rng().gen_range(range); + let random_value = list.get(random_index).ok_or(Error::ExpectedList { + actual: value.clone(), + })?; + + return Ok(random_value.clone()); + } + let range = 0..expressions.len(); let random_index = thread_rng().gen_range(range); let random_expression = expressions.get(random_index).unwrap(); diff --git a/src/abstract_tree/use.rs b/src/abstract_tree/use.rs new file mode 100644 index 0000000..0b2709f --- /dev/null +++ b/src/abstract_tree/use.rs @@ -0,0 +1,34 @@ +use std::fs::read_to_string; + +use serde::{Deserialize, Serialize}; +use tree_sitter::Node; + +use crate::{evaluate_with_context, AbstractTree, Result, Value, ValueNode, VariableMap}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct Use { + path: ValueNode, +} + +impl AbstractTree for Use { + fn from_syntax_node(source: &str, node: Node) -> Result { + let path_node = node.child(1).unwrap(); + let value_node = ValueNode::from_syntax_node(source, path_node)?; + + Ok(Use { path: value_node }) + } + + fn run(&self, source: &str, context: &mut VariableMap) -> Result { + let run_node = self.path.run(source, context)?; + let path = run_node.as_string()?; + let file_contents = read_to_string(path)?; + let mut temp_context = VariableMap::new(); + let eval_result = evaluate_with_context(&file_contents, &mut temp_context)?; + + while let Some((key, value)) = temp_context.inner_mut().pop_first() { + context.set_value(key, value)?; + } + + Ok(eval_result) + } +} diff --git a/src/error.rs b/src/error.rs index c709319..5facdcc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -83,6 +83,11 @@ pub enum Error { actual: Value, }, + ExpectedMinLengthList { + minimum_len: usize, + actual_len: usize, + }, + ExpectedFixedLenList { expected_len: usize, actual: Value, @@ -261,13 +266,20 @@ impl fmt::Display for Error { ExpectedBoolean { actual } => { write!(f, "Expected a Value::Boolean, but got {:?}.", actual) } - ExpectedList { actual } => write!(f, "Expected a Value::Tuple, but got {:?}.", actual), + ExpectedList { actual } => write!(f, "Expected a Value::List, but got {:?}.", actual), + ExpectedMinLengthList { + minimum_len, + actual_len, + } => write!( + f, + "Expected a list of at least {minimum_len} values, but got one with {actual_len}.", + ), ExpectedFixedLenList { expected_len, actual, } => write!( f, - "Expected a Value::Tuple of len {}, but got {:?}.", + "Expected a Value::List of len {}, but got {:?}.", expected_len, actual ), ExpectedEmpty { actual } => write!(f, "Expected a Value::Empty, but got {:?}.", actual),