From 327a2d044b4416ffe27d70c6c3485e6dea2b573c Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 30 Sep 2023 17:52:37 -0400 Subject: [PATCH] Implement function value --- src/interface.rs | 31 ++++++++++--------------------- src/value/function.rs | 22 ++++++++++++++++------ src/value/mod.rs | 27 ++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index efd1bb5..a8c458e 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,5 +1,6 @@ //! The top level of Dust's API with functions to interpret Dust code. +use serde::{Deserialize, Serialize}; use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor}; use crate::{language, Error, Result, Value, VariableMap}; @@ -170,7 +171,7 @@ impl Item { /// Items are either comments, which do nothing, or statements, which can be run /// to produce a single value or interact with a context by creating or /// referencing variables. -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub enum Statement { Open(Expression), } @@ -205,7 +206,7 @@ impl Statement { } } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub enum Expression { Identifier(String), Value(Value), @@ -267,7 +268,7 @@ impl Expression { } } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Operation { left: Expression, operator: String, @@ -298,7 +299,8 @@ impl Operation { ) -> Result { let left = self.left.run(context, &mut cursor, source)?; let right = self.right.run(context, &mut cursor, source)?; - let result = match self.operator.as_str() { + + match self.operator.as_str() { "+" => left + right, "-" => left - right, "=" => { @@ -309,10 +311,8 @@ impl Operation { Ok(Value::Empty) } "==" => Ok(Value::Boolean(left == right)), - _ => return Err(Error::CustomMessage("Operator not supported.".to_string())), - }; - - Ok(result?) + _ => Err(Error::CustomMessage("Operator not supported.".to_string())), + } } } @@ -320,7 +320,7 @@ impl Operation { /// /// A ControlFlow instance represents work to be done when the "run" method is /// called. -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct ControlFlow { if_expression: Expression, then_statement: Statement, @@ -369,7 +369,7 @@ impl ControlFlow { #[cfg(test)] mod tests { - use crate::{Function, Table}; + use crate::Table; use super::*; @@ -416,17 +416,6 @@ mod tests { ); } - #[test] - fn evaluate_function() { - let function_str = "function { - output message - output number - }"; - - todo!(); - // assert_eq!("", vec![Ok(Value::Function(Function::new(function_str)))]); - } - #[test] fn evaluate_map() { let mut map = VariableMap::new(); diff --git a/src/value/function.rs b/src/value/function.rs index 0f8a15e..a00df81 100644 --- a/src/value/function.rs +++ b/src/value/function.rs @@ -2,14 +2,20 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; -use crate::{eval, eval_with_context, Result, Value, VariableMap}; +use crate::{Result, Statement, Value, VariableMap}; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct Function(String); +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct Function { + identifiers: Vec, + statements: Vec, +} impl Function { - pub fn new(body: &str) -> Self { - Function(body.to_string()) + pub fn new(identifiers: Vec, statements: Vec) -> Self { + Function { + identifiers, + statements, + } } pub fn run(&self) -> Result { @@ -23,6 +29,10 @@ impl Function { impl Display for Function { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) + write!( + f, + "function < {:?} > {{ {:?} }}", + self.identifiers, self.statements + ) } } diff --git a/src/value/mod.rs b/src/value/mod.rs index a64a406..35f2a6c 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,7 +1,7 @@ //! Types that represent runtime values. use crate::{ error::{Error, Result}, - Expression, Function, Table, Time, ValueType, VariableMap, + Expression, Function, Statement, Table, Time, ValueType, VariableMap, }; use json::JsonValue; @@ -134,6 +134,31 @@ impl Value { Ok(Value::Table(table)) } "map" => todo!(), + "function" => { + let child_count = node.child_count(); + let mut identifiers = Vec::new(); + let mut statements = Vec::new(); + + for index in 0..child_count { + let child = node.child(index).unwrap(); + + if child.kind() == "identifier" { + let child_identifier = Expression::new(child, source)?; + + if let Expression::Identifier(identifier) = child_identifier { + identifiers.push(identifier) + } + } + + if child.kind() == "statement" { + let statement = Statement::new(child, source)?; + + statements.push(statement) + } + } + + Ok(Value::Function(Function::new(identifiers, statements))) + } "empty" => Ok(Value::Empty), _ => Err(Error::UnexpectedSourceNode { expected: "integer, string, boolean, float, list or empty",