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

View File

@ -11,7 +11,7 @@ use rustyline::{
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.
#[derive(Parser, Debug)]
@ -35,9 +35,9 @@ fn main() {
let eval_results = if let Some(path) = args.path {
let file_contents = read_to_string(path).unwrap();
eval(&file_contents)
evaluate(&file_contents)
} else if let Some(command) = args.command {
eval(&command)
evaluate(&command)
} else {
vec![Ok(Value::Empty)]
};
@ -143,7 +143,7 @@ fn run_cli_shell() {
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 {
match result {

View File

@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
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)]
pub struct Function {
@ -17,12 +17,19 @@ impl Function {
statements,
}
}
}
pub fn run(&self) -> Result<Value> {
todo!()
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![],
})
}
pub fn run_with_context(&self, _context: &mut VariableMap) -> Result<Value> {
fn run(&self, context: &mut VariableMap) -> Result<Value> {
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,
Deserialize, Serialize, Serializer,
};
use tree_sitter::{Node, TreeCursor};
use tree_sitter::Node;
use std::{
cmp::Ordering,
convert::TryFrom,
fmt::{self, Display, Formatter},
marker::PhantomData,
ops::{Add, Range, Sub},
ops::{Add, Sub},
};
pub mod function;
@ -166,23 +166,23 @@ impl Value {
for index in 0..child_count {
let child = child.child(index).unwrap();
// if child.kind() == "identifier" {
// let identifier = Identifier::new(source, cursor)?;
if child.kind() == "identifier" {
let identifier = Identifier::from_syntax_node(child, source)?;
// identifiers.push(identifier)
// }
identifiers.push(identifier)
}
// if child.kind() == "statement" {
// let statement = Statement::new(source, cursor)?;
if child.kind() == "statement" {
let statement = Statement::from_syntax_node(child, source)?;
// statements.push(statement)
// }
statements.push(statement)
}
}
Ok(Value::Function(Function::new(identifiers, statements)))
}
_ => 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(),
location: child.start_position(),
}),
@ -428,7 +428,7 @@ impl Add for Value {
impl Sub for Value {
type Output = Result<Self>;
fn sub(self, other: Self) -> Self::Output {
fn sub(self, _other: Self) -> Self::Output {
todo!()
}
}