1
0

Begin function implementation; Clean up

This commit is contained in:
Jeff 2023-10-05 14:29:13 -04:00
parent 0359fabf1a
commit 8f0bc386b1
4 changed files with 91 additions and 46 deletions

View File

@ -20,10 +20,10 @@ use crate::{language, Error, Result, Value, VariableMap};
/// # use dust_lib::*; /// # use dust_lib::*;
/// assert_eq!(eval("1 + 2 + 3"), vec![Ok(Value::from(6))]); /// assert_eq!(eval("1 + 2 + 3"), vec![Ok(Value::from(6))]);
/// ``` /// ```
pub fn eval(source: &str) -> Vec<Result<Value>> { pub fn evaluate(source: &str) -> Vec<Result<Value>> {
let mut context = VariableMap::new(); let mut context = VariableMap::new();
eval_with_context(source, &mut context) evaluate_with_context(source, &mut context)
} }
/// Evaluate the given source code with the given context. /// Evaluate the given source code with the given context.
@ -45,7 +45,7 @@ pub fn eval(source: &str) -> Vec<Result<Value>> {
/// vec![Ok(Value::Primitive(Primitive::Empty)), Ok(Value::from(10))] /// vec![Ok(Value::Primitive(Primitive::Empty)), Ok(Value::from(10))]
/// ); /// );
/// ``` /// ```
pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<Value>> { pub fn evaluate_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<Value>> {
let mut parser = Parser::new(); let mut parser = Parser::new();
parser.set_language(language()).unwrap(); parser.set_language(language()).unwrap();
@ -255,6 +255,10 @@ impl EvaluatorTree for Expression {
pub struct Identifier(String); pub struct Identifier(String);
impl Identifier { impl Identifier {
pub fn new(inner: String) -> Self {
Identifier(inner)
}
pub fn take_inner(self) -> String { pub fn take_inner(self) -> String {
self.0 self.0
} }
@ -458,45 +462,54 @@ impl EvaluatorTree for FunctionCall {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::Table; use crate::{Function, Table};
use super::*; use super::*;
#[test] #[test]
fn evaluate_empty() { fn evaluate_empty() {
assert_eq!(eval("x = 9"), vec![Ok(Value::Empty)]); assert_eq!(evaluate("x = 9"), vec![Ok(Value::Empty)]);
assert_eq!(eval("x = 'foo' + 'bar'"), vec![Ok(Value::Empty)]); assert_eq!(evaluate("x = 'foo' + 'bar'"), vec![Ok(Value::Empty)]);
} }
#[test] #[test]
fn evaluate_integer() { fn evaluate_integer() {
assert_eq!(eval("1"), vec![Ok(Value::Integer(1))]); assert_eq!(evaluate("1"), vec![Ok(Value::Integer(1))]);
assert_eq!(eval("123"), vec![Ok(Value::Integer(123))]); assert_eq!(evaluate("123"), vec![Ok(Value::Integer(123))]);
assert_eq!(eval("-666"), vec![Ok(Value::Integer(-666))]); assert_eq!(evaluate("-666"), vec![Ok(Value::Integer(-666))]);
} }
#[test] #[test]
fn evaluate_float() { fn evaluate_float() {
assert_eq!(eval("0.1"), vec![Ok(Value::Float(0.1))]); assert_eq!(evaluate("0.1"), vec![Ok(Value::Float(0.1))]);
assert_eq!(eval("12.3"), vec![Ok(Value::Float(12.3))]); assert_eq!(evaluate("12.3"), vec![Ok(Value::Float(12.3))]);
assert_eq!(eval("-6.66"), vec![Ok(Value::Float(-6.66))]); assert_eq!(evaluate("-6.66"), vec![Ok(Value::Float(-6.66))]);
} }
#[test] #[test]
fn evaluate_string() { fn evaluate_string() {
assert_eq!(eval("\"one\""), vec![Ok(Value::String("one".to_string()))]);
assert_eq!(eval("'one'"), vec![Ok(Value::String("one".to_string()))]);
assert_eq!(eval("`one`"), vec![Ok(Value::String("one".to_string()))]);
assert_eq!( assert_eq!(
eval("`'one'`"), evaluate("\"one\""),
vec![Ok(Value::String("one".to_string()))]
);
assert_eq!(
evaluate("'one'"),
vec![Ok(Value::String("one".to_string()))]
);
assert_eq!(
evaluate("`one`"),
vec![Ok(Value::String("one".to_string()))]
);
assert_eq!(
evaluate("`'one'`"),
vec![Ok(Value::String("'one'".to_string()))] vec![Ok(Value::String("'one'".to_string()))]
); );
assert_eq!( assert_eq!(
eval("'`one`'"), evaluate("'`one`'"),
vec![Ok(Value::String("`one`".to_string()))] vec![Ok(Value::String("`one`".to_string()))]
); );
assert_eq!( assert_eq!(
eval("\"'one'\""), evaluate("\"'one'\""),
vec![Ok(Value::String("'one'".to_string()))] vec![Ok(Value::String("'one'".to_string()))]
); );
} }
@ -504,7 +517,7 @@ mod tests {
#[test] #[test]
fn evaluate_list() { fn evaluate_list() {
assert_eq!( assert_eq!(
eval("[1, 2, 'foobar']"), evaluate("[1, 2, 'foobar']"),
vec![Ok(Value::List(vec![ vec![Ok(Value::List(vec![
Value::Integer(1), Value::Integer(1),
Value::Integer(2), Value::Integer(2),
@ -521,7 +534,7 @@ mod tests {
map.set_value("foo".to_string(), Value::String("bar".to_string())) map.set_value("foo".to_string(), Value::String("bar".to_string()))
.unwrap(); .unwrap();
assert_eq!(eval("{ x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]); assert_eq!(evaluate("{ x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]);
} }
#[test] #[test]
@ -539,7 +552,7 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
eval( evaluate(
" "
table <messages, numbers> { table <messages, numbers> {
['hiya', 42] ['hiya', 42]
@ -553,18 +566,21 @@ mod tests {
} }
#[test] #[test]
fn if_then() { fn evaluate_if_then() {
assert_eq!( assert_eq!(
eval("if true then 'true'"), evaluate("if true then 'true'"),
vec![Ok(Value::String("true".to_string()))] vec![Ok(Value::String("true".to_string()))]
); );
} }
#[test] #[test]
fn if_then_else() { fn evaluate_if_then_else() {
assert_eq!(eval("if false then 1 else 2"), vec![Ok(Value::Integer(2))]);
assert_eq!( assert_eq!(
eval("if true then 1.0 else 42.0"), evaluate("if false then 1 else 2"),
vec![Ok(Value::Integer(2))]
);
assert_eq!(
evaluate("if true then 1.0 else 42.0"),
vec![Ok(Value::Float(1.0))] vec![Ok(Value::Float(1.0))]
); );
} }

View File

@ -11,7 +11,7 @@ use rustyline::{
use std::{borrow::Cow, fs::read_to_string}; use std::{borrow::Cow, fs::read_to_string};
use dust::{eval, eval_with_context, Value, VariableMap}; use dust::{evaluate, evaluate_with_context, Value, VariableMap};
/// Command-line arguments to be parsed. /// Command-line arguments to be parsed.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -35,9 +35,9 @@ fn main() {
let eval_results = if let Some(path) = args.path { let eval_results = if let Some(path) = args.path {
let file_contents = read_to_string(path).unwrap(); let file_contents = read_to_string(path).unwrap();
eval(&file_contents) evaluate(&file_contents)
} else if let Some(command) = args.command { } else if let Some(command) = args.command {
eval(&command) evaluate(&command)
} else { } else {
vec![Ok(Value::Empty)] vec![Ok(Value::Empty)]
}; };
@ -143,7 +143,7 @@ fn run_cli_shell() {
rl.add_history_entry(line).unwrap(); rl.add_history_entry(line).unwrap();
let eval_results = eval_with_context(line, &mut context); let eval_results = evaluate_with_context(line, &mut context);
for result in eval_results { for result in eval_results {
match result { match result {

View File

@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{Identifier, Result, Statement, Value, VariableMap}; use crate::{EvaluatorTree, Identifier, Result, Statement, Value, VariableMap};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Function { pub struct Function {
@ -17,12 +17,19 @@ impl Function {
statements, statements,
} }
} }
pub fn run(&self) -> Result<Value> {
todo!()
} }
pub fn run_with_context(&self, _context: &mut VariableMap) -> Result<Value> { impl EvaluatorTree for Function {
fn from_syntax_node(node: tree_sitter::Node, source: &str) -> Result<Self> {
debug_assert_eq!(node.kind(), "function");
Ok(Function {
identifiers: vec![],
statements: vec![],
})
}
fn run(&self, context: &mut VariableMap) -> Result<Value> {
todo!() todo!()
} }
} }
@ -36,3 +43,25 @@ impl Display for Function {
) )
} }
} }
#[cfg(test)]
mod tests {
use crate::{evaluate, Expression};
use super::*;
#[test]
fn evaluate_function() {
let function = Function::new(
vec![Identifier::new("output".to_string())],
vec![Statement::Expression(Expression::Identifier(
Identifier::new("output".to_string()),
))],
);
assert_eq!(
evaluate("function <output> { output }"),
vec![Ok(Value::Function(function))]
);
}
}

View File

@ -10,14 +10,14 @@ use serde::{
ser::SerializeTuple, ser::SerializeTuple,
Deserialize, Serialize, Serializer, Deserialize, Serialize, Serializer,
}; };
use tree_sitter::{Node, TreeCursor}; use tree_sitter::Node;
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
convert::TryFrom, convert::TryFrom,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
marker::PhantomData, marker::PhantomData,
ops::{Add, Range, Sub}, ops::{Add, Sub},
}; };
pub mod function; pub mod function;
@ -166,23 +166,23 @@ impl Value {
for index in 0..child_count { for index in 0..child_count {
let child = child.child(index).unwrap(); let child = child.child(index).unwrap();
// if child.kind() == "identifier" { if child.kind() == "identifier" {
// let identifier = Identifier::new(source, cursor)?; let identifier = Identifier::from_syntax_node(child, source)?;
// identifiers.push(identifier) identifiers.push(identifier)
// } }
// if child.kind() == "statement" { if child.kind() == "statement" {
// let statement = Statement::new(source, cursor)?; let statement = Statement::from_syntax_node(child, source)?;
// statements.push(statement) statements.push(statement)
// } }
} }
Ok(Value::Function(Function::new(identifiers, statements))) Ok(Value::Function(Function::new(identifiers, statements)))
} }
_ => Err(Error::UnexpectedSyntax { _ => Err(Error::UnexpectedSyntax {
expected: "integer, float, boolean, string list, table, map, function or empty", expected: "string, integer, float, boolean, list, table, map, function or empty",
actual: child.kind(), actual: child.kind(),
location: child.start_position(), location: child.start_position(),
}), }),
@ -428,7 +428,7 @@ impl Add for Value {
impl Sub for Value { impl Sub for Value {
type Output = Result<Self>; type Output = Result<Self>;
fn sub(self, other: Self) -> Self::Output { fn sub(self, _other: Self) -> Self::Output {
todo!() todo!()
} }
} }