Begin function implementation; Clean up
This commit is contained in:
parent
0359fabf1a
commit
8f0bc386b1
@ -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))]
|
||||
);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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))]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user