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::*;
|
/// # 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))]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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> {
|
impl EvaluatorTree for Function {
|
||||||
todo!()
|
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!()
|
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,
|
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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user