Improve internal API
This commit is contained in:
parent
41483f6b84
commit
a4660cbafb
64
src/error.rs
64
src/error.rs
@ -3,7 +3,7 @@
|
|||||||
//! To deal with errors from dependencies, either create a new error variant
|
//! To deal with errors from dependencies, either create a new error variant
|
||||||
//! or use the MacroFailure variant if the error can only occur inside a macro.
|
//! or use the MacroFailure variant if the error can only occur inside a macro.
|
||||||
|
|
||||||
use crate::{value::value_type::ValueType, value::Value, ToolInfo};
|
use crate::{value::value_type::ValueType, value::Value, Primitive};
|
||||||
|
|
||||||
use std::{fmt, io, time::SystemTimeError};
|
use std::{fmt, io, time::SystemTimeError};
|
||||||
|
|
||||||
@ -24,12 +24,6 @@ pub enum Error {
|
|||||||
empty_node_sexp: String,
|
empty_node_sexp: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Dust's internal type checking failed to identify a type mismatch. This should never happen, /// the error prompts the user to report the bug.
|
|
||||||
TypeCheckFailure {
|
|
||||||
tool_info: ToolInfo<'static>,
|
|
||||||
argument: Value,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// The 'assert' macro did not resolve successfully.
|
/// The 'assert' macro did not resolve successfully.
|
||||||
AssertEqualFailed {
|
AssertEqualFailed {
|
||||||
expected: Value,
|
expected: Value,
|
||||||
@ -142,14 +136,6 @@ pub enum Error {
|
|||||||
actual: Value,
|
actual: Value,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A macro or function was called with the wrong type of input.
|
|
||||||
MacroArgumentType {
|
|
||||||
/// The macro that was called.
|
|
||||||
macro_info: ToolInfo<'static>,
|
|
||||||
/// The actual value.
|
|
||||||
actual: Value,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// An operator is used with a wrong combination of types.
|
/// An operator is used with a wrong combination of types.
|
||||||
WrongTypeCombination {
|
WrongTypeCombination {
|
||||||
/// The operator that whose evaluation caused the error.
|
/// The operator that whose evaluation caused the error.
|
||||||
@ -396,19 +382,13 @@ impl Error {
|
|||||||
/// Returns `Ok(())` if the given value is a string or a numeric.
|
/// Returns `Ok(())` if the given value is a string or a numeric.
|
||||||
pub fn expect_number_or_string(actual: &Value) -> Result<()> {
|
pub fn expect_number_or_string(actual: &Value) -> Result<()> {
|
||||||
match actual {
|
match actual {
|
||||||
Value::String(_) | Value::Float(_) | Value::Integer(_) => Ok(()),
|
Value::Primitive(Primitive::String(_))
|
||||||
|
| Value::Primitive(Primitive::Float(_))
|
||||||
|
| Value::Primitive(Primitive::Integer(_)) => Ok(()),
|
||||||
_ => Err(Error::expected_number_or_string(actual.clone())),
|
_ => Err(Error::expected_number_or_string(actual.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Ok(())` if the given value is a String, List, Map or Table.
|
|
||||||
pub fn _expect_collection(actual: &Value) -> Result<()> {
|
|
||||||
match actual {
|
|
||||||
Value::String(_) | Value::List(_) | Value::Map(_) | Value::Table(_) => Ok(()),
|
|
||||||
_ => Err(Error::expected_collection(actual.clone())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -416,9 +396,14 @@ impl fmt::Display for Error {
|
|||||||
use Error::*;
|
use Error::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
TypeCheckFailure { tool_info, argument } => write!(f, "Type check failure. This is a bug with the tool or with Dust's internal type checking. Please report this bug and include this error message.\nToolInfo = {tool_info:?}\nargument = {argument}"),
|
AssertEqualFailed { expected, actual } => write!(
|
||||||
AssertEqualFailed {expected, actual } => write!(f, "Equality assertion failed. {expected} does not equal {actual}."),
|
f,
|
||||||
AssertFailed => write!(f, "Assertion failed. A false value was passed to \"assert\"."),
|
"Equality assertion failed. {expected} does not equal {actual}."
|
||||||
|
),
|
||||||
|
AssertFailed => write!(
|
||||||
|
f,
|
||||||
|
"Assertion failed. A false value was passed to \"assert\"."
|
||||||
|
),
|
||||||
ExpectedOperatorArgumentAmount { expected, actual } => write!(
|
ExpectedOperatorArgumentAmount { expected, actual } => write!(
|
||||||
f,
|
f,
|
||||||
"An operator expected {} arguments, but got {}.",
|
"An operator expected {} arguments, but got {}.",
|
||||||
@ -543,20 +528,25 @@ impl fmt::Display for Error {
|
|||||||
f,
|
f,
|
||||||
"Wrong number of columns for this table. Expected {expected}, found {actual}."
|
"Wrong number of columns for this table. Expected {expected}, found {actual}."
|
||||||
),
|
),
|
||||||
MacroArgumentType {
|
UnexpectedSyntax {
|
||||||
macro_info,
|
expected,
|
||||||
actual,
|
actual,
|
||||||
|
location,
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"Wrong argument of type {:?} was passed to {}. Expected one of the following types: {:?}.",
|
"Unexpected syntax at {location}. Expected {expected}, but found {actual}."
|
||||||
actual.value_type(),
|
|
||||||
macro_info.identifier,
|
|
||||||
macro_info.inputs
|
|
||||||
),
|
),
|
||||||
UnexpectedSyntax { expected, actual, location } => write!(f, "Unexpected syntax at {location}. Expected {expected}, but found {actual}."),
|
ExpectedFieldName => write!(
|
||||||
ExpectedFieldName => write!(f, "Expected a field name for this node, but none was found."),
|
f,
|
||||||
WrongTypeCombination { expected, actual } => write!(f, "Wrong type combination. Expected {expected}, found {actual}."),
|
"Expected a field name for this node, but none was found."
|
||||||
ExpectedChildNode { empty_node_sexp } => write!(f, "Expected this node to have a child, {empty_node_sexp}."),
|
),
|
||||||
|
WrongTypeCombination { expected, actual } => write!(
|
||||||
|
f,
|
||||||
|
"Wrong type combination. Expected {expected}, found {actual}."
|
||||||
|
),
|
||||||
|
ExpectedChildNode { empty_node_sexp } => {
|
||||||
|
write!(f, "Expected this node to have a child, {empty_node_sexp}.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
107
src/interface.rs
107
src/interface.rs
@ -7,7 +7,7 @@ use std::fmt::{self, Debug, Formatter};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
||||||
|
|
||||||
use crate::{language, Error, Result, Value, VariableMap};
|
use crate::{language, Error, Primitive, Result, Value, VariableMap};
|
||||||
|
|
||||||
/// Evaluate the given source code.
|
/// Evaluate the given source code.
|
||||||
///
|
///
|
||||||
@ -42,7 +42,7 @@ pub fn eval(source: &str) -> Vec<Result<Value>> {
|
|||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// eval_with_context(dust_code, &mut context),
|
/// eval_with_context(dust_code, &mut context),
|
||||||
/// vec![Ok(Value::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 eval_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<Value>> {
|
||||||
@ -165,7 +165,7 @@ impl EvaluatorTree for Item {
|
|||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
Item::Comment(text) => Ok(Value::String(text.clone())),
|
Item::Comment(text) => Ok(Value::Primitive(Primitive::String(text.clone()))),
|
||||||
Item::Statement(statement) => statement.run(context),
|
Item::Statement(statement) => statement.run(context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ impl EvaluatorTree for Expression {
|
|||||||
|
|
||||||
let expression = match child.kind() {
|
let expression = match child.kind() {
|
||||||
"identifier" => Self::Identifier(Identifier::new(source, cursor)?),
|
"identifier" => Self::Identifier(Identifier::new(source, cursor)?),
|
||||||
"value" => Expression::Value(Value::new(source, cursor)?),
|
"value" => Expression::Value(Value::from_source(source, cursor)?),
|
||||||
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)),
|
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)),
|
||||||
"assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)),
|
"assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)),
|
||||||
"math" => Expression::Math(Box::new(Math::new(source, cursor)?)),
|
"math" => Expression::Math(Box::new(Math::new(source, cursor)?)),
|
||||||
@ -330,7 +330,7 @@ impl EvaluatorTree for ControlFlow {
|
|||||||
} else if let Some(statement) = &self.else_statement {
|
} else if let Some(statement) = &self.else_statement {
|
||||||
statement.run(context)
|
statement.run(context)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Empty)
|
Ok(Value::Primitive(Primitive::Empty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,7 +367,7 @@ impl EvaluatorTree for Assignment {
|
|||||||
|
|
||||||
context.set_value(key, value)?;
|
context.set_value(key, value)?;
|
||||||
|
|
||||||
Ok(Value::Empty)
|
Ok(Value::Primitive(Primitive::Empty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ impl EvaluatorTree for Math {
|
|||||||
MathOperator::Modulo => left_value % right_value,
|
MathOperator::Modulo => left_value % right_value,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::Float(outcome))
|
Ok(Value::Primitive(Primitive::Float(outcome)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,40 +488,67 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_empty() {
|
fn evaluate_empty() {
|
||||||
assert_eq!(eval("x = 9"), vec![Ok(Value::Empty)]);
|
assert_eq!(eval("x = 9"), vec![Ok(Value::Primitive(Primitive::Empty))]);
|
||||||
assert_eq!(eval("x = 'foo' + 'bar'"), vec![Ok(Value::Empty)]);
|
assert_eq!(
|
||||||
|
eval("x = 'foo' + 'bar'"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::Empty))]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_integer() {
|
fn evaluate_integer() {
|
||||||
assert_eq!(eval("1"), vec![Ok(Value::Integer(1))]);
|
assert_eq!(eval("1"), vec![Ok(Value::Primitive(Primitive::Integer(1)))]);
|
||||||
assert_eq!(eval("123"), vec![Ok(Value::Integer(123))]);
|
assert_eq!(
|
||||||
assert_eq!(eval("-666"), vec![Ok(Value::Integer(-666))]);
|
eval("123"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::Integer(123)))]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("-666"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::Integer(-666)))]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_float() {
|
fn evaluate_float() {
|
||||||
assert_eq!(eval("0.1"), vec![Ok(Value::Float(0.1))]);
|
assert_eq!(
|
||||||
assert_eq!(eval("12.3"), vec![Ok(Value::Float(12.3))]);
|
eval("0.1"),
|
||||||
assert_eq!(eval("-6.66"), vec![Ok(Value::Float(-6.66))]);
|
vec![Ok(Value::Primitive(Primitive::Float(0.1)))]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("12.3"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::Float(12.3)))]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("-6.66"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::Float(-6.66)))]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_string() {
|
fn evaluate_string() {
|
||||||
assert_eq!(eval("\"one\""), vec![Ok(Value::String("one".to_string()))]);
|
assert_eq!(
|
||||||
assert_eq!(eval("'one'"), vec![Ok(Value::String("one".to_string()))]);
|
eval("\"one\""),
|
||||||
assert_eq!(eval("`one`"), vec![Ok(Value::String("one".to_string()))]);
|
vec![Ok(Value::Primitive(Primitive::String("one".to_string())))]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("'one'"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::String("one".to_string())))]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
eval("`one`"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::String("one".to_string())))]
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval("`'one'`"),
|
eval("`'one'`"),
|
||||||
vec![Ok(Value::String("'one'".to_string()))]
|
vec![Ok(Value::Primitive(Primitive::String("'one'".to_string())))]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval("'`one`'"),
|
eval("'`one`'"),
|
||||||
vec![Ok(Value::String("`one`".to_string()))]
|
vec![Ok(Value::Primitive(Primitive::String("`one`".to_string())))]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval("\"'one'\""),
|
eval("\"'one'\""),
|
||||||
vec![Ok(Value::String("'one'".to_string()))]
|
vec![Ok(Value::Primitive(Primitive::String("'one'".to_string())))]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,9 +557,9 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval("[1, 2, 'foobar']"),
|
eval("[1, 2, 'foobar']"),
|
||||||
vec![Ok(Value::List(vec![
|
vec![Ok(Value::List(vec![
|
||||||
Value::Integer(1),
|
Value::Primitive(Primitive::Integer(1)),
|
||||||
Value::Integer(2),
|
Value::Primitive(Primitive::Integer(2)),
|
||||||
Value::String("foobar".to_string()),
|
Value::Primitive(Primitive::String("foobar".to_string())),
|
||||||
]))]
|
]))]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -541,8 +568,12 @@ mod tests {
|
|||||||
fn evaluate_map() {
|
fn evaluate_map() {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
map.set_value("x".to_string(), Value::Integer(1)).unwrap();
|
map.set_value("x".to_string(), Value::Primitive(Primitive::Integer(1)))
|
||||||
map.set_value("foo".to_string(), Value::String("bar".to_string()))
|
.unwrap();
|
||||||
|
map.set_value(
|
||||||
|
"foo".to_string(),
|
||||||
|
Value::Primitive(Primitive::String("bar".to_string())),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(eval("map { x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]);
|
assert_eq!(eval("map { x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]);
|
||||||
@ -553,13 +584,22 @@ mod tests {
|
|||||||
let mut table = Table::new(vec!["messages".to_string(), "numbers".to_string()]);
|
let mut table = Table::new(vec!["messages".to_string(), "numbers".to_string()]);
|
||||||
|
|
||||||
table
|
table
|
||||||
.insert(vec![Value::String("hiya".to_string()), Value::Integer(42)])
|
.insert(vec![
|
||||||
|
Value::Primitive(Primitive::String("hiya".to_string())),
|
||||||
|
Value::Primitive(Primitive::Integer(42)),
|
||||||
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
table
|
table
|
||||||
.insert(vec![Value::String("foo".to_string()), Value::Integer(57)])
|
.insert(vec![
|
||||||
|
Value::Primitive(Primitive::String("foo".to_string())),
|
||||||
|
Value::Primitive(Primitive::Integer(57)),
|
||||||
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
table
|
table
|
||||||
.insert(vec![Value::String("bar".to_string()), Value::Float(99.99)])
|
.insert(vec![
|
||||||
|
Value::Primitive(Primitive::String("bar".to_string())),
|
||||||
|
Value::Primitive(Primitive::Float(99.99)),
|
||||||
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -580,16 +620,19 @@ mod tests {
|
|||||||
fn if_then() {
|
fn if_then() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval("if true then 'true'"),
|
eval("if true then 'true'"),
|
||||||
vec![Ok(Value::String("true".to_string()))]
|
vec![Ok(Value::Primitive(Primitive::String("true".to_string())))]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_then_else() {
|
fn if_then_else() {
|
||||||
assert_eq!(eval("if false then 1 else 2"), vec![Ok(Value::Integer(2))]);
|
assert_eq!(
|
||||||
|
eval("if false then 1 else 2"),
|
||||||
|
vec![Ok(Value::Primitive(Primitive::Integer(2)))]
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval("if true then 1.0 else 42.0"),
|
eval("if true then 1.0 else 42.0"),
|
||||||
vec![Ok(Value::Float(1.0))]
|
vec![Ok(Value::Primitive(Primitive::Float(1.0)))]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,12 @@
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
error::*,
|
error::*,
|
||||||
interface::*,
|
interface::*,
|
||||||
tools::{Tool, ToolInfo, TOOL_LIST},
|
|
||||||
value::{
|
value::{
|
||||||
function::Function, table::Table, time::Time, value_type::ValueType,
|
function::Function, table::Table, time::Time, value_type::ValueType,
|
||||||
variable_map::VariableMap, Value,
|
variable_map::VariableMap, Primitive, Value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod tools;
|
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod interface;
|
mod interface;
|
||||||
mod value;
|
mod value;
|
||||||
|
12
src/main.rs
12
src/main.rs
@ -11,7 +11,7 @@ use rustyline::{
|
|||||||
|
|
||||||
use std::{borrow::Cow, fs::read_to_string};
|
use std::{borrow::Cow, fs::read_to_string};
|
||||||
|
|
||||||
use dust_lib::{eval, eval_with_context, Value, VariableMap, TOOL_LIST};
|
use dust_lib::{eval, eval_with_context, Primitive, Value, VariableMap};
|
||||||
|
|
||||||
/// Command-line arguments to be parsed.
|
/// Command-line arguments to be parsed.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@ -39,7 +39,7 @@ fn main() {
|
|||||||
} else if let Some(command) = args.command {
|
} else if let Some(command) = args.command {
|
||||||
eval(&command)
|
eval(&command)
|
||||||
} else {
|
} else {
|
||||||
vec![Ok(Value::Empty)]
|
vec![Ok(Value::Primitive(Primitive::Empty))]
|
||||||
};
|
};
|
||||||
|
|
||||||
for result in eval_results {
|
for result in eval_results {
|
||||||
@ -66,13 +66,7 @@ impl DustReadline {
|
|||||||
Self {
|
Self {
|
||||||
completer: FilenameCompleter::new(),
|
completer: FilenameCompleter::new(),
|
||||||
_hinter: HistoryHinter {},
|
_hinter: HistoryHinter {},
|
||||||
tool_hints: TOOL_LIST
|
tool_hints: Vec::new(),
|
||||||
.iter()
|
|
||||||
.map(|tool| ToolHint {
|
|
||||||
display: tool.info().identifier.to_string() + "()",
|
|
||||||
complete_to: tool.info().identifier.len(),
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
320
src/value/mod.rs
320
src/value/mod.rs
@ -27,28 +27,54 @@ pub mod time;
|
|||||||
pub mod value_type;
|
pub mod value_type;
|
||||||
pub mod variable_map;
|
pub mod variable_map;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||||
|
pub enum Primitive {
|
||||||
|
String(String),
|
||||||
|
Float(f64),
|
||||||
|
Integer(i64),
|
||||||
|
Boolean(bool),
|
||||||
|
#[default]
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Primitive {}
|
||||||
|
|
||||||
|
impl Ord for Primitive {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Primitive::String(left), Primitive::String(right)) => left.cmp(right),
|
||||||
|
(Primitive::Float(left), Primitive::Float(right)) => {
|
||||||
|
left.to_le_bytes().cmp(&right.to_le_bytes())
|
||||||
|
}
|
||||||
|
(Primitive::Integer(left), Primitive::Integer(right)) => left.cmp(right),
|
||||||
|
(Primitive::Boolean(left), Primitive::Boolean(right)) => left.cmp(right),
|
||||||
|
(Primitive::Empty, Primitive::Empty) => Ordering::Equal,
|
||||||
|
(Primitive::String(_), _) => Ordering::Greater,
|
||||||
|
(Primitive::Float(_), _) => Ordering::Greater,
|
||||||
|
(Primitive::Integer(_), _) => Ordering::Greater,
|
||||||
|
(Primitive::Boolean(_), _) => Ordering::Greater,
|
||||||
|
(Primitive::Empty, _) => Ordering::Less,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whale value representation.
|
/// Whale value representation.
|
||||||
///
|
///
|
||||||
/// Every whale variable has a key and a Value. Variables are represented by
|
/// Every whale variable has a key and a Value. Variables are represented by
|
||||||
/// storing them in a VariableMap. This means the map of variables is itself a
|
/// storing them in a VariableMap. This means the map of variables is itself a
|
||||||
/// value that can be treated as any other.
|
/// value that can be treated as any other.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
String(String),
|
Primitive(Primitive),
|
||||||
Float(f64),
|
|
||||||
Integer(i64),
|
|
||||||
Boolean(bool),
|
|
||||||
List(Vec<Value>),
|
List(Vec<Value>),
|
||||||
Map(VariableMap),
|
Map(VariableMap),
|
||||||
Table(Table),
|
Table(Table),
|
||||||
Time(Time),
|
Time(Time),
|
||||||
Function(Function),
|
Function(Function),
|
||||||
#[default]
|
|
||||||
Empty,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn new(source: &str, mut cursor: &mut TreeCursor) -> Result<Self> {
|
pub fn from_source(source: &str, mut cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
let node = cursor.node();
|
let node = cursor.node();
|
||||||
cursor.goto_first_child();
|
cursor.goto_first_child();
|
||||||
let child = cursor.node();
|
let child = cursor.node();
|
||||||
@ -57,7 +83,7 @@ impl Value {
|
|||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
"integer" | "float" | "boolean" | "string" | "empty" => {
|
"integer" | "float" | "boolean" | "string" | "empty" => {
|
||||||
Value::from_syntax_node(child, source)
|
Value::simple_from_syntax_node(node, source)
|
||||||
}
|
}
|
||||||
"list" => {
|
"list" => {
|
||||||
let list_length = child.named_child_count();
|
let list_length = child.named_child_count();
|
||||||
@ -66,7 +92,7 @@ impl Value {
|
|||||||
cursor.goto_first_child();
|
cursor.goto_first_child();
|
||||||
|
|
||||||
for value_node in child.children_by_field_name("item", &mut cursor) {
|
for value_node in child.children_by_field_name("item", &mut cursor) {
|
||||||
let value = Value::from_syntax_node(value_node.child(0).unwrap(), source)?;
|
let value = Value::simple_from_syntax_node(value_node, source)?;
|
||||||
|
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
@ -81,25 +107,19 @@ impl Value {
|
|||||||
Ok(Value::Table(table))
|
Ok(Value::Table(table))
|
||||||
}
|
}
|
||||||
"map" => {
|
"map" => {
|
||||||
let grandchild_count = child.child_count();
|
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
let mut previous_grandchild = child.child(0).unwrap();
|
let mut current_key = String::new();
|
||||||
let mut key = String::new();
|
|
||||||
|
|
||||||
for _ in 0..grandchild_count {
|
for key_value_node in child.children_by_field_name("key_value_pair", &mut cursor) {
|
||||||
if let Some(current_node) = previous_grandchild.next_sibling() {
|
if key_value_node.kind() == "identifier" {
|
||||||
if current_node.kind() == "identifier" {
|
let identifier_text = &source[key_value_node.byte_range()];
|
||||||
key = Identifier::new(source, cursor)?.take_inner();
|
current_key = identifier_text.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
if current_node.kind() == "value" {
|
if key_value_node.kind() == "value" {
|
||||||
let value = Value::new(source, cursor)?;
|
let value = Value::simple_from_syntax_node(key_value_node, source)?;
|
||||||
|
map.set_value(current_key.to_string(), value)?;
|
||||||
map.set_value(key.clone(), value)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
previous_grandchild = current_node
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,17 +156,23 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
/// Creates a simple value from the given source code and a node in the
|
||||||
match node.kind() {
|
/// syntax tree.
|
||||||
"integer" => Value::integer_from_source(source, node.byte_range()),
|
///
|
||||||
"float" => Value::integer_from_source(source, node.byte_range()),
|
///
|
||||||
"boolean" => Value::integer_from_source(source, node.byte_range()),
|
pub fn simple_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
"string" => Value::integer_from_source(source, node.byte_range()),
|
let child = node.child(0).unwrap();
|
||||||
"empty" => Ok(Value::Empty),
|
|
||||||
|
match child.kind() {
|
||||||
|
"integer" => Value::integer_from_source(source, child.byte_range()),
|
||||||
|
"float" => Value::float_from_source(source, child.byte_range()),
|
||||||
|
"boolean" => Value::boolean_from_source(source, child.byte_range()),
|
||||||
|
"string" => Value::string_from_source(source, child.byte_range()),
|
||||||
|
"empty" => Ok(Value::Primitive(Primitive::Empty)),
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
expected: "integer, float, boolean, string or empty",
|
expected: "integer, float, boolean, string or empty",
|
||||||
actual: node.kind(),
|
actual: child.kind(),
|
||||||
location: node.start_position(),
|
location: child.start_position(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,29 +181,30 @@ impl Value {
|
|||||||
let value_snippet = &source[byte_range];
|
let value_snippet = &source[byte_range];
|
||||||
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::Integer(raw))
|
Ok(Value::Primitive(Primitive::Integer(raw)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
let value_snippet = &source[byte_range];
|
||||||
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::Float(raw))
|
Ok(Value::Primitive(Primitive::Float(raw)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
let value_snippet = &source[byte_range];
|
||||||
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::Boolean(raw))
|
Ok(Value::Primitive(Primitive::Boolean(raw)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
let value_snippet = &source[byte_range];
|
||||||
let quote_str = &value_snippet.chars().nth(0).unwrap();
|
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||||
let without_quotes = value_snippet.trim_matches(*quote_str);
|
|
||||||
|
|
||||||
Ok(Value::String(without_quotes.to_string()))
|
Ok(Value::Primitive(Primitive::String(
|
||||||
|
without_quotes.to_string(),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
pub fn value_type(&self) -> ValueType {
|
||||||
@ -189,23 +216,26 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_string(&self) -> bool {
|
pub fn is_string(&self) -> bool {
|
||||||
matches!(self, Value::String(_))
|
matches!(self, Value::Primitive(Primitive::String(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_integer(&self) -> bool {
|
pub fn is_integer(&self) -> bool {
|
||||||
matches!(self, Value::Integer(_))
|
matches!(self, Value::Primitive(Primitive::Integer(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_float(&self) -> bool {
|
pub fn is_float(&self) -> bool {
|
||||||
matches!(self, Value::Float(_))
|
matches!(self, Value::Primitive(Primitive::Float(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_number(&self) -> bool {
|
pub fn is_number(&self) -> bool {
|
||||||
matches!(self, Value::Integer(_) | Value::Float(_))
|
matches!(
|
||||||
|
self,
|
||||||
|
Value::Primitive(Primitive::Integer(_)) | Value::Primitive(Primitive::Float(_))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_boolean(&self) -> bool {
|
pub fn is_boolean(&self) -> bool {
|
||||||
matches!(self, Value::Boolean(_))
|
matches!(self, Value::Primitive(Primitive::Boolean(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_list(&self) -> bool {
|
pub fn is_list(&self) -> bool {
|
||||||
@ -213,7 +243,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
matches!(self, Value::Empty)
|
matches!(self, Value::Primitive(Primitive::Empty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_map(&self) -> bool {
|
pub fn is_map(&self) -> bool {
|
||||||
@ -224,10 +254,10 @@ impl Value {
|
|||||||
matches!(self, Value::Map(_))
|
matches!(self, Value::Map(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::String`.
|
/// Borrows the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::Primitive(Primitive::String`.
|
||||||
pub fn as_string(&self) -> Result<&String> {
|
pub fn as_string(&self) -> Result<&String> {
|
||||||
match self {
|
match self {
|
||||||
Value::String(string) => Ok(string),
|
Value::Primitive(Primitive::String(string)) => Ok(string),
|
||||||
value => Err(Error::expected_string(value.clone())),
|
value => Err(Error::expected_string(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,33 +265,33 @@ impl Value {
|
|||||||
/// Copies the value stored in `self` as `i64`, or returns `Err` if `self` is not a `Value::Int`.
|
/// Copies the value stored in `self` as `i64`, or returns `Err` if `self` is not a `Value::Int`.
|
||||||
pub fn as_int(&self) -> Result<i64> {
|
pub fn as_int(&self) -> Result<i64> {
|
||||||
match self {
|
match self {
|
||||||
Value::Integer(i) => Ok(*i),
|
Value::Primitive(Primitive::Integer(i)) => Ok(*i),
|
||||||
value => Err(Error::expected_int(value.clone())),
|
value => Err(Error::expected_int(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies the value stored in `self` as `f64`, or returns `Err` if `self` is not a `Value::Float`.
|
/// Copies the value stored in `self` as `f64`, or returns `Err` if `self` is not a `Primitive::Float`.
|
||||||
pub fn as_float(&self) -> Result<f64> {
|
pub fn as_float(&self) -> Result<f64> {
|
||||||
match self {
|
match self {
|
||||||
Value::Float(f) => Ok(*f),
|
Value::Primitive(Primitive::Float(f)) => Ok(*f),
|
||||||
value => Err(Error::expected_float(value.clone())),
|
value => Err(Error::expected_float(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies the value stored in `self` as `f64`, or returns `Err` if `self` is not a `Value::Float` or `Value::Int`.
|
/// Copies the value stored in `self` as `f64`, or returns `Err` if `self` is not a `Primitive::Float` or `Value::Int`.
|
||||||
/// Note that this method silently converts `i64` to `f64`, if `self` is a `Value::Int`.
|
/// Note that this method silently converts `i64` to `f64`, if `self` is a `Value::Int`.
|
||||||
pub fn as_number(&self) -> Result<f64> {
|
pub fn as_number(&self) -> Result<f64> {
|
||||||
match self {
|
match self {
|
||||||
Value::Float(f) => Ok(*f),
|
Value::Primitive(Primitive::Float(f)) => Ok(*f),
|
||||||
Value::Integer(i) => Ok(*i as f64),
|
Value::Primitive(Primitive::Integer(i)) => Ok(*i as f64),
|
||||||
value => Err(Error::expected_number(value.clone())),
|
value => Err(Error::expected_number(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies the value stored in `self` as `bool`, or returns `Err` if `self` is not a `Value::Boolean`.
|
/// Copies the value stored in `self` as `bool`, or returns `Err` if `self` is not a `Primitive::Boolean`.
|
||||||
pub fn as_boolean(&self) -> Result<bool> {
|
pub fn as_boolean(&self) -> Result<bool> {
|
||||||
match self {
|
match self {
|
||||||
Value::Boolean(boolean) => Ok(*boolean),
|
Value::Primitive(Primitive::Boolean(boolean)) => Ok(*boolean),
|
||||||
value => Err(Error::expected_boolean(value.clone())),
|
value => Err(Error::expected_boolean(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,7 +363,7 @@ impl Value {
|
|||||||
/// Returns `()`, or returns`Err` if `self` is not a `Value::Tuple`.
|
/// Returns `()`, or returns`Err` if `self` is not a `Value::Tuple`.
|
||||||
pub fn as_empty(&self) -> Result<()> {
|
pub fn as_empty(&self) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Value::Empty => Ok(()),
|
Value::Primitive(Primitive::Empty) => Ok(()),
|
||||||
value => Err(Error::expected_empty(value.clone())),
|
value => Err(Error::expected_empty(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,33 +379,54 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Value {
|
||||||
|
fn default() -> Self {
|
||||||
|
Value::Primitive(Primitive::Empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Add for Value {
|
impl Add for Value {
|
||||||
type Output = Result<Value>;
|
type Output = Result<Value>;
|
||||||
|
|
||||||
fn add(self, other: Self) -> Self::Output {
|
fn add(self, other: Self) -> Self::Output {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::String(left), Value::String(right)) => {
|
(
|
||||||
|
Value::Primitive(Primitive::String(left)),
|
||||||
|
Value::Primitive(Primitive::String(right)),
|
||||||
|
) => {
|
||||||
let concatenated = left + &right;
|
let concatenated = left + &right;
|
||||||
|
|
||||||
Ok(Value::String(concatenated))
|
Ok(Value::Primitive(Primitive::String(concatenated)))
|
||||||
}
|
}
|
||||||
(Value::String(_), other) | (other, Value::String(_)) => {
|
(Value::Primitive(Primitive::String(_)), other)
|
||||||
|
| (other, Value::Primitive(Primitive::String(_))) => {
|
||||||
Err(Error::ExpectedString { actual: other })
|
Err(Error::ExpectedString { actual: other })
|
||||||
}
|
}
|
||||||
(Value::Float(left), Value::Float(right)) => {
|
(
|
||||||
|
Value::Primitive(Primitive::Float(left)),
|
||||||
|
Value::Primitive(Primitive::Float(right)),
|
||||||
|
) => {
|
||||||
let addition = left + right;
|
let addition = left + right;
|
||||||
|
|
||||||
Ok(Value::Float(addition))
|
Ok(Value::Primitive(Primitive::Float(addition)))
|
||||||
}
|
}
|
||||||
(Value::Float(_), other) | (other, Value::Float(_)) => {
|
(Value::Primitive(Primitive::Float(_)), other)
|
||||||
|
| (other, Value::Primitive(Primitive::Float(_))) => {
|
||||||
Err(Error::ExpectedFloat { actual: other })
|
Err(Error::ExpectedFloat { actual: other })
|
||||||
}
|
}
|
||||||
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)),
|
(
|
||||||
(Value::Integer(_), other) | (other, Value::Integer(_)) => {
|
Value::Primitive(Primitive::Integer(left)),
|
||||||
|
Value::Primitive(Primitive::Integer(right)),
|
||||||
|
) => Ok(Value::Primitive(Primitive::Integer(left + right))),
|
||||||
|
(Value::Primitive(Primitive::Integer(_)), other)
|
||||||
|
| (other, Value::Primitive(Primitive::Integer(_))) => {
|
||||||
Err(Error::ExpectedInt { actual: other })
|
Err(Error::ExpectedInt { actual: other })
|
||||||
}
|
}
|
||||||
(Value::Boolean(_), Value::Boolean(_)) => todo!(),
|
(Value::Primitive(Primitive::Boolean(_)), Value::Primitive(Primitive::Boolean(_))) => {
|
||||||
(Value::Boolean(_), other) | (other, Value::Boolean(_)) => {
|
todo!()
|
||||||
|
}
|
||||||
|
(Value::Primitive(Primitive::Boolean(_)), other)
|
||||||
|
| (other, Value::Primitive(Primitive::Boolean(_))) => {
|
||||||
Err(Error::ExpectedBoolean { actual: other })
|
Err(Error::ExpectedBoolean { actual: other })
|
||||||
}
|
}
|
||||||
(Value::List(_), Value::List(_)) => todo!(),
|
(Value::List(_), Value::List(_)) => todo!(),
|
||||||
@ -386,7 +437,9 @@ impl Add for Value {
|
|||||||
(Value::Map(_), other) | (other, Value::Map(_)) => {
|
(Value::Map(_), other) | (other, Value::Map(_)) => {
|
||||||
Err(Error::ExpectedMap { actual: other })
|
Err(Error::ExpectedMap { actual: other })
|
||||||
}
|
}
|
||||||
(Value::Empty, Value::Empty) => Ok(Value::Empty),
|
(Value::Primitive(Primitive::Empty), Value::Primitive(Primitive::Empty)) => {
|
||||||
|
Ok(Value::Primitive(Primitive::Empty))
|
||||||
|
}
|
||||||
_ => Err(Error::CustomMessage(
|
_ => Err(Error::CustomMessage(
|
||||||
"Cannot add the given types.".to_string(),
|
"Cannot add the given types.".to_string(),
|
||||||
)),
|
)),
|
||||||
@ -398,44 +451,7 @@ 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 {
|
||||||
match (&self, &other) {
|
todo!()
|
||||||
(Value::String(_), Value::String(_)) => Err(Error::ExpectedNumber {
|
|
||||||
actual: self.clone(),
|
|
||||||
}),
|
|
||||||
(Value::String(_), other) | (other, Value::String(_)) => Err(Error::ExpectedNumber {
|
|
||||||
actual: other.clone(),
|
|
||||||
}),
|
|
||||||
(Value::Float(left), Value::Float(right)) => {
|
|
||||||
let addition = left - right;
|
|
||||||
|
|
||||||
Ok(Value::Float(addition))
|
|
||||||
}
|
|
||||||
(Value::Float(_), other) | (other, Value::Float(_)) => Err(Error::ExpectedNumber {
|
|
||||||
actual: other.clone(),
|
|
||||||
}),
|
|
||||||
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left - right)),
|
|
||||||
(Value::Integer(_), other) | (other, Value::Integer(_)) => Err(Error::ExpectedInt {
|
|
||||||
actual: other.clone(),
|
|
||||||
}),
|
|
||||||
(Value::Boolean(_), Value::Boolean(_)) => todo!(),
|
|
||||||
(Value::Boolean(_), other) | (other, Value::Boolean(_)) => {
|
|
||||||
Err(Error::ExpectedBoolean {
|
|
||||||
actual: other.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(Value::List(_), Value::List(_)) => todo!(),
|
|
||||||
(Value::List(_), other) | (other, Value::List(_)) => Err(Error::ExpectedList {
|
|
||||||
actual: other.clone(),
|
|
||||||
}),
|
|
||||||
(Value::Map(_), Value::Map(_)) => todo!(),
|
|
||||||
(Value::Map(_), other) | (other, Value::Map(_)) => Err(Error::ExpectedMap {
|
|
||||||
actual: other.clone(),
|
|
||||||
}),
|
|
||||||
(Value::Empty, Value::Empty) => Ok(Value::Empty),
|
|
||||||
_ => Err(Error::CustomMessage(
|
|
||||||
"Cannot add the given types.".to_string(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,18 +460,12 @@ impl Eq for Value {}
|
|||||||
impl PartialEq for Value {
|
impl PartialEq for Value {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::String(left), Value::String(right)) => left == right,
|
|
||||||
(Value::Float(left), Value::Float(right)) => left == right,
|
|
||||||
(Value::Integer(left), Value::Integer(right)) => left == right,
|
|
||||||
(Value::Float(float), Value::Integer(integer))
|
|
||||||
| (Value::Integer(integer), Value::Float(float)) => *float == *integer as f64,
|
|
||||||
(Value::Boolean(left), Value::Boolean(right)) => left == right,
|
|
||||||
(Value::List(left), Value::List(right)) => left == right,
|
(Value::List(left), Value::List(right)) => left == right,
|
||||||
(Value::Map(left), Value::Map(right)) => left == right,
|
(Value::Map(left), Value::Map(right)) => left == right,
|
||||||
(Value::Table(left), Value::Table(right)) => left == right,
|
(Value::Table(left), Value::Table(right)) => left == right,
|
||||||
(Value::Time(left), Value::Time(right)) => left == right,
|
(Value::Time(left), Value::Time(right)) => left == right,
|
||||||
(Value::Function(left), Value::Function(right)) => left == right,
|
(Value::Function(left), Value::Function(right)) => left == right,
|
||||||
(Value::Empty, Value::Empty) => true,
|
(Value::Primitive(left), Value::Primitive(right)) => left == right,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,14 +480,6 @@ impl PartialOrd for Value {
|
|||||||
impl Ord for Value {
|
impl Ord for Value {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::String(left), Value::String(right)) => left.cmp(right),
|
|
||||||
(Value::String(_), _) => Ordering::Greater,
|
|
||||||
(Value::Integer(left), Value::Integer(right)) => left.cmp(right),
|
|
||||||
(Value::Integer(_), _) => Ordering::Greater,
|
|
||||||
(Value::Boolean(left), Value::Boolean(right)) => left.cmp(right),
|
|
||||||
(Value::Boolean(_), _) => Ordering::Greater,
|
|
||||||
(Value::Float(left), Value::Float(right)) => left.total_cmp(right),
|
|
||||||
(Value::Float(_), _) => Ordering::Greater,
|
|
||||||
(Value::List(left), Value::List(right)) => left.cmp(right),
|
(Value::List(left), Value::List(right)) => left.cmp(right),
|
||||||
(Value::List(_), _) => Ordering::Greater,
|
(Value::List(_), _) => Ordering::Greater,
|
||||||
(Value::Map(left), Value::Map(right)) => left.cmp(right),
|
(Value::Map(left), Value::Map(right)) => left.cmp(right),
|
||||||
@ -488,8 +490,8 @@ impl Ord for Value {
|
|||||||
(Value::Function(_), _) => Ordering::Greater,
|
(Value::Function(_), _) => Ordering::Greater,
|
||||||
(Value::Time(left), Value::Time(right)) => left.cmp(right),
|
(Value::Time(left), Value::Time(right)) => left.cmp(right),
|
||||||
(Value::Time(_), _) => Ordering::Greater,
|
(Value::Time(_), _) => Ordering::Greater,
|
||||||
(Value::Empty, Value::Empty) => Ordering::Equal,
|
(Value::Primitive(left), Value::Primitive(right)) => left.cmp(right),
|
||||||
(Value::Empty, _) => Ordering::Less,
|
(Value::Primitive(_), _) => Ordering::Less,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -500,10 +502,10 @@ impl Serialize for Value {
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Value::String(inner) => serializer.serialize_str(inner),
|
Value::Primitive(Primitive::String(inner)) => serializer.serialize_str(inner),
|
||||||
Value::Float(inner) => serializer.serialize_f64(*inner),
|
Value::Primitive(Primitive::Float(inner)) => serializer.serialize_f64(*inner),
|
||||||
Value::Integer(inner) => serializer.serialize_i64(*inner),
|
Value::Primitive(Primitive::Integer(inner)) => serializer.serialize_i64(*inner),
|
||||||
Value::Boolean(inner) => serializer.serialize_bool(*inner),
|
Value::Primitive(Primitive::Boolean(inner)) => serializer.serialize_bool(*inner),
|
||||||
Value::List(inner) => {
|
Value::List(inner) => {
|
||||||
let mut tuple = serializer.serialize_tuple(inner.len())?;
|
let mut tuple = serializer.serialize_tuple(inner.len())?;
|
||||||
|
|
||||||
@ -513,7 +515,7 @@ impl Serialize for Value {
|
|||||||
|
|
||||||
tuple.end()
|
tuple.end()
|
||||||
}
|
}
|
||||||
Value::Empty => todo!(),
|
Value::Primitive(Primitive::Empty) => todo!(),
|
||||||
Value::Map(inner) => inner.serialize(serializer),
|
Value::Map(inner) => inner.serialize(serializer),
|
||||||
Value::Table(inner) => inner.serialize(serializer),
|
Value::Table(inner) => inner.serialize(serializer),
|
||||||
Value::Function(inner) => inner.serialize(serializer),
|
Value::Function(inner) => inner.serialize(serializer),
|
||||||
@ -525,11 +527,11 @@ impl Serialize for Value {
|
|||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::String(string) => write!(f, "{string}"),
|
Value::Primitive(Primitive::String(string)) => write!(f, "{string}"),
|
||||||
Value::Float(float) => write!(f, "{}", float),
|
Value::Primitive(Primitive::Float(float)) => write!(f, "{}", float),
|
||||||
Value::Integer(int) => write!(f, "{}", int),
|
Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int),
|
||||||
Value::Boolean(boolean) => write!(f, "{}", boolean),
|
Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean),
|
||||||
Value::Empty => write!(f, "()"),
|
Value::Primitive(Primitive::Empty) => write!(f, "()"),
|
||||||
Value::List(list) => Table::from(list).fmt(f),
|
Value::List(list) => Table::from(list).fmt(f),
|
||||||
Value::Map(map) => write!(f, "{map}"),
|
Value::Map(map) => write!(f, "{map}"),
|
||||||
Value::Table(table) => write!(f, "{table}"),
|
Value::Table(table) => write!(f, "{table}"),
|
||||||
@ -541,31 +543,31 @@ impl Display for Value {
|
|||||||
|
|
||||||
impl From<String> for Value {
|
impl From<String> for Value {
|
||||||
fn from(string: String) -> Self {
|
fn from(string: String) -> Self {
|
||||||
Value::String(string)
|
Value::Primitive(Primitive::String(string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Value {
|
impl From<&str> for Value {
|
||||||
fn from(string: &str) -> Self {
|
fn from(string: &str) -> Self {
|
||||||
Value::String(string.to_string())
|
Value::Primitive(Primitive::String(string.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<f64> for Value {
|
impl From<f64> for Value {
|
||||||
fn from(float: f64) -> Self {
|
fn from(float: f64) -> Self {
|
||||||
Value::Float(float)
|
Value::Primitive(Primitive::Float(float))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i64> for Value {
|
impl From<i64> for Value {
|
||||||
fn from(int: i64) -> Self {
|
fn from(int: i64) -> Self {
|
||||||
Value::Integer(int)
|
Value::Primitive(Primitive::Integer(int))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<bool> for Value {
|
impl From<bool> for Value {
|
||||||
fn from(boolean: bool) -> Self {
|
fn from(boolean: bool) -> Self {
|
||||||
Value::Boolean(boolean)
|
Value::Primitive(Primitive::Boolean(boolean))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +585,7 @@ impl From<Value> for Result<Value> {
|
|||||||
|
|
||||||
impl From<()> for Value {
|
impl From<()> for Value {
|
||||||
fn from(_: ()) -> Self {
|
fn from(_: ()) -> Self {
|
||||||
Value::Empty
|
Value::Primitive(Primitive::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,11 +596,11 @@ impl TryFrom<JsonValue> for Value {
|
|||||||
use JsonValue::*;
|
use JsonValue::*;
|
||||||
|
|
||||||
match json_value {
|
match json_value {
|
||||||
Null => Ok(Value::Empty),
|
Null => Ok(Value::Primitive(Primitive::Empty)),
|
||||||
Short(short) => Ok(Value::String(short.to_string())),
|
Short(short) => Ok(Value::Primitive(Primitive::String(short.to_string()))),
|
||||||
String(string) => Ok(Value::String(string)),
|
String(string) => Ok(Value::Primitive(Primitive::String(string))),
|
||||||
Number(number) => Ok(Value::Float(f64::from(number))),
|
Number(number) => Ok(Value::Primitive(Primitive::Float(f64::from(number)))),
|
||||||
Boolean(boolean) => Ok(Value::Boolean(boolean)),
|
Boolean(boolean) => Ok(Value::Primitive(Primitive::Boolean(boolean))),
|
||||||
Object(object) => {
|
Object(object) => {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
@ -632,11 +634,11 @@ impl TryFrom<&JsonValue> for Value {
|
|||||||
use JsonValue::*;
|
use JsonValue::*;
|
||||||
|
|
||||||
match json_value {
|
match json_value {
|
||||||
Null => Ok(Value::Empty),
|
Null => Ok(Value::Primitive(Primitive::Empty)),
|
||||||
Short(short) => Ok(Value::String(short.to_string())),
|
Short(short) => Ok(Value::Primitive(Primitive::String(short.to_string()))),
|
||||||
String(string) => Ok(Value::String(string.clone())),
|
String(string) => Ok(Value::Primitive(Primitive::String(string.clone()))),
|
||||||
Number(number) => Ok(Value::Float(f64::from(*number))),
|
Number(number) => Ok(Value::Primitive(Primitive::Float(f64::from(*number)))),
|
||||||
Boolean(boolean) => Ok(Value::Boolean(*boolean)),
|
Boolean(boolean) => Ok(Value::Primitive(Primitive::Boolean(*boolean))),
|
||||||
Object(object) => {
|
Object(object) => {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
@ -667,7 +669,7 @@ impl TryFrom<Value> for String {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
||||||
if let Value::String(value) = value {
|
if let Value::Primitive(Primitive::String(value)) = value {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ExpectedString { actual: value })
|
Err(Error::ExpectedString { actual: value })
|
||||||
@ -679,7 +681,7 @@ impl TryFrom<Value> for f64 {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
||||||
if let Value::Float(value) = value {
|
if let Value::Primitive(Primitive::Float(value)) = value {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ExpectedFloat { actual: value })
|
Err(Error::ExpectedFloat { actual: value })
|
||||||
@ -691,7 +693,7 @@ impl TryFrom<Value> for i64 {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
||||||
if let Value::Integer(value) = value {
|
if let Value::Primitive(Primitive::Integer(value)) = value {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ExpectedInt { actual: value })
|
Err(Error::ExpectedInt { actual: value })
|
||||||
@ -703,7 +705,7 @@ impl TryFrom<Value> for bool {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
||||||
if let Value::Boolean(value) = value {
|
if let Value::Primitive(Primitive::Boolean(value)) = value {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ExpectedBoolean { actual: value })
|
Err(Error::ExpectedBoolean { actual: value })
|
||||||
@ -734,7 +736,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::Boolean(v))
|
Ok(Value::Primitive(Primitive::Boolean(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_i8<E>(self, v: i8) -> std::result::Result<Self::Value, E>
|
fn visit_i8<E>(self, v: i8) -> std::result::Result<Self::Value, E>
|
||||||
@ -762,7 +764,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::Integer(v))
|
Ok(Value::Primitive(Primitive::Integer(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_i128<E>(self, v: i128) -> std::result::Result<Self::Value, E>
|
fn visit_i128<E>(self, v: i128) -> std::result::Result<Self::Value, E>
|
||||||
@ -770,9 +772,9 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
if v > i64::MAX as i128 {
|
if v > i64::MAX as i128 {
|
||||||
Ok(Value::Integer(i64::MAX))
|
Ok(Value::Primitive(Primitive::Integer(i64::MAX)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Integer(v as i64))
|
Ok(Value::Primitive(Primitive::Integer(v as i64)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,7 +824,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::Float(v))
|
Ok(Value::Primitive(Primitive::Float(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_char<E>(self, v: char) -> std::result::Result<Self::Value, E>
|
fn visit_char<E>(self, v: char) -> std::result::Result<Self::Value, E>
|
||||||
@ -836,7 +838,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::String(v.to_string()))
|
Ok(Value::Primitive(Primitive::String(v.to_string())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_borrowed_str<E>(self, v: &'de str) -> std::result::Result<Self::Value, E>
|
fn visit_borrowed_str<E>(self, v: &'de str) -> std::result::Result<Self::Value, E>
|
||||||
@ -850,7 +852,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::String(v))
|
Ok(Value::Primitive(Primitive::String(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bytes<E>(self, v: &[u8]) -> std::result::Result<Self::Value, E>
|
fn visit_bytes<E>(self, v: &[u8]) -> std::result::Result<Self::Value, E>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Error, Result, Value, VariableMap};
|
use crate::{Error, Primitive, Result, Value, VariableMap};
|
||||||
use comfy_table::{Cell, Color, ContentArrangement, Table as ComfyTable};
|
use comfy_table::{Cell, Color, ContentArrangement, Table as ComfyTable};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
@ -98,7 +98,7 @@ impl Table {
|
|||||||
|
|
||||||
if let Some(index) = new_table_column_index {
|
if let Some(index) = new_table_column_index {
|
||||||
while new_row.len() < index + 1 {
|
while new_row.len() < index + 1 {
|
||||||
new_row.push(Value::Empty);
|
new_row.push(Value::Primitive(Primitive::Empty));
|
||||||
}
|
}
|
||||||
new_row[index] = value.clone();
|
new_row[index] = value.clone();
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ impl Display for Table {
|
|||||||
Value::Map(map) => format!("Map ({} items)", map.len()),
|
Value::Map(map) => format!("Map ({} items)", map.len()),
|
||||||
Value::Table(table) => format!("Table ({} items)", table.len()),
|
Value::Table(table) => format!("Table ({} items)", table.len()),
|
||||||
Value::Function(_) => "Function".to_string(),
|
Value::Function(_) => "Function".to_string(),
|
||||||
Value::Empty => "Empty".to_string(),
|
Value::Primitive(Primitive::Empty) => "Empty".to_string(),
|
||||||
value => value.to_string(),
|
value => value.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -220,38 +220,46 @@ impl Display for Table {
|
|||||||
impl From<&Value> for Table {
|
impl From<&Value> for Table {
|
||||||
fn from(value: &Value) -> Self {
|
fn from(value: &Value) -> Self {
|
||||||
match value {
|
match value {
|
||||||
Value::String(string) => {
|
Value::Primitive(Primitive::String(string)) => {
|
||||||
let mut table = Table::new(vec!["string".to_string()]);
|
let mut table = Table::new(vec!["string".to_string()]);
|
||||||
|
|
||||||
table
|
table
|
||||||
.insert(vec![Value::String(string.to_string())])
|
.insert(vec![Value::Primitive(Primitive::String(
|
||||||
|
string.to_string(),
|
||||||
|
))])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
Value::Float(float) => {
|
Value::Primitive(Primitive::Float(float)) => {
|
||||||
let mut table = Table::new(vec!["float".to_string()]);
|
let mut table = Table::new(vec!["float".to_string()]);
|
||||||
|
|
||||||
table.insert(vec![Value::Float(*float)]).unwrap();
|
table
|
||||||
|
.insert(vec![Value::Primitive(Primitive::Float(*float))])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
Value::Integer(integer) => {
|
Value::Primitive(Primitive::Integer(integer)) => {
|
||||||
let mut table = Table::new(vec!["integer".to_string()]);
|
let mut table = Table::new(vec!["integer".to_string()]);
|
||||||
|
|
||||||
table.insert(vec![Value::Integer(*integer)]).unwrap();
|
table
|
||||||
|
.insert(vec![Value::Primitive(Primitive::Integer(*integer))])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
Value::Boolean(boolean) => {
|
Value::Primitive(Primitive::Boolean(boolean)) => {
|
||||||
let mut table = Table::new(vec!["boolean".to_string()]);
|
let mut table = Table::new(vec!["boolean".to_string()]);
|
||||||
|
|
||||||
table.insert(vec![Value::Boolean(*boolean)]).unwrap();
|
table
|
||||||
|
.insert(vec![Value::Primitive(Primitive::Boolean(*boolean))])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
Value::List(list) => Self::from(list),
|
Value::List(list) => Self::from(list),
|
||||||
Value::Empty => Table::new(Vec::with_capacity(0)),
|
Value::Primitive(Primitive::Empty) => Table::new(Vec::with_capacity(0)),
|
||||||
Value::Map(map) => Self::from(map),
|
Value::Map(map) => Self::from(map),
|
||||||
Value::Table(table) => table.clone(),
|
Value::Table(table) => table.clone(),
|
||||||
Value::Function(function) => {
|
Value::Function(function) => {
|
||||||
@ -274,7 +282,10 @@ impl From<&Vec<Value>> for Table {
|
|||||||
|
|
||||||
for (i, value) in list.iter().enumerate() {
|
for (i, value) in list.iter().enumerate() {
|
||||||
table
|
table
|
||||||
.insert(vec![Value::Integer(i as i64), value.clone()])
|
.insert(vec![
|
||||||
|
Value::Primitive(Primitive::Integer(i as i64)),
|
||||||
|
value.clone(),
|
||||||
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +302,10 @@ impl From<&mut Vec<Value>> for Table {
|
|||||||
table.insert(list.clone()).unwrap();
|
table.insert(list.clone()).unwrap();
|
||||||
} else {
|
} else {
|
||||||
table
|
table
|
||||||
.insert(vec![Value::Integer(i as i64), value.clone()])
|
.insert(vec![
|
||||||
|
Value::Primitive(Primitive::Integer(i as i64)),
|
||||||
|
value.clone(),
|
||||||
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
|
|
||||||
use crate::Value;
|
use crate::{Primitive, Value};
|
||||||
|
|
||||||
/// The type of a `Value`.
|
/// The type of a `Value`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -94,16 +94,16 @@ impl Debug for ValueType {
|
|||||||
impl From<&Value> for ValueType {
|
impl From<&Value> for ValueType {
|
||||||
fn from(value: &Value) -> Self {
|
fn from(value: &Value) -> Self {
|
||||||
match value {
|
match value {
|
||||||
Value::String(_) => ValueType::String,
|
Value::Primitive(Primitive::String(_)) => ValueType::String,
|
||||||
Value::Float(_) => ValueType::Float,
|
Value::Primitive(Primitive::Float(_)) => ValueType::Float,
|
||||||
Value::Integer(_) => ValueType::Integer,
|
Value::Primitive(Primitive::Integer(_)) => ValueType::Integer,
|
||||||
Value::Boolean(_) => ValueType::Boolean,
|
Value::Primitive(Primitive::Boolean(_)) => ValueType::Boolean,
|
||||||
|
Value::Primitive(Primitive::Empty) => ValueType::Empty,
|
||||||
Value::List(list) => {
|
Value::List(list) => {
|
||||||
let values = list.iter().map(|value| value.value_type()).collect();
|
let values = list.iter().map(|value| value.value_type()).collect();
|
||||||
|
|
||||||
ValueType::ListExact(values)
|
ValueType::ListExact(values)
|
||||||
}
|
}
|
||||||
Value::Empty => ValueType::Empty,
|
|
||||||
Value::Map(_) => ValueType::Map,
|
Value::Map(_) => ValueType::Map,
|
||||||
Value::Table { .. } => ValueType::Table,
|
Value::Table { .. } => ValueType::Table,
|
||||||
Value::Function(_) => ValueType::Function,
|
Value::Function(_) => ValueType::Function,
|
||||||
|
@ -4,7 +4,7 @@ use std::{
|
|||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{value::Value, Error, Result, Table, TOOL_LIST};
|
use crate::{value::Value, Error, Primitive, Result, Table};
|
||||||
|
|
||||||
/// A collection dust variables comprised of key-value pairs.
|
/// A collection dust variables comprised of key-value pairs.
|
||||||
///
|
///
|
||||||
@ -27,34 +27,34 @@ impl VariableMap {
|
|||||||
/// argument. Returns an error a tool is called with the wrong inputs or if the identifier does
|
/// argument. Returns an error a tool is called with the wrong inputs or if the identifier does
|
||||||
/// not match any tools or functions.
|
/// not match any tools or functions.
|
||||||
pub fn call_function(&self, identifier: &str, argument: &Value) -> Result<Value> {
|
pub fn call_function(&self, identifier: &str, argument: &Value) -> Result<Value> {
|
||||||
for macro_item in TOOL_LIST {
|
// for macro_item in TOOL_LIST {
|
||||||
let valid_input_types = macro_item.info().inputs;
|
// let valid_input_types = macro_item.info().inputs;
|
||||||
|
|
||||||
if identifier == macro_item.info().identifier {
|
// if identifier == macro_item.info().identifier {
|
||||||
let input_type = argument.value_type();
|
// let input_type = argument.value_type();
|
||||||
|
|
||||||
if valid_input_types.contains(&input_type) {
|
// if valid_input_types.contains(&input_type) {
|
||||||
return macro_item.run(argument);
|
// return macro_item.run(argument);
|
||||||
} else {
|
// } else {
|
||||||
return Err(Error::MacroArgumentType {
|
// return Err(Error::MacroArgumentType {
|
||||||
macro_info: macro_item.info(),
|
// macro_info: macro_item.info(),
|
||||||
actual: argument.clone(),
|
// actual: argument.clone(),
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
for (key, value) in &self.variables {
|
// for (key, value) in &self.variables {
|
||||||
if identifier == key {
|
// if identifier == key {
|
||||||
if let Ok(function) = value.as_function() {
|
// if let Ok(function) = value.as_function() {
|
||||||
let mut context = self.clone();
|
// let mut context = self.clone();
|
||||||
|
|
||||||
context.set_value("input".to_string(), argument.clone())?;
|
// context.set_value("input".to_string(), argument.clone())?;
|
||||||
|
|
||||||
return function.run_with_context(&mut context);
|
// return function.run_with_context(&mut context);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Err(Error::FunctionIdentifierNotFound(identifier.to_string()))
|
Err(Error::FunctionIdentifierNotFound(identifier.to_string()))
|
||||||
}
|
}
|
||||||
@ -77,9 +77,9 @@ impl VariableMap {
|
|||||||
let index = if let Ok(index) = next_identifier.parse::<usize>() {
|
let index = if let Ok(index) = next_identifier.parse::<usize>() {
|
||||||
index
|
index
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::expected_int(Value::String(
|
return Err(Error::expected_int(Value::Primitive(Primitive::String(
|
||||||
next_identifier.to_string(),
|
next_identifier.to_string(),
|
||||||
)));
|
))));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(list.get(index).cloned())
|
Ok(list.get(index).cloned())
|
||||||
@ -106,9 +106,9 @@ impl VariableMap {
|
|||||||
let index = if let Ok(index) = next_identifier.parse::<usize>() {
|
let index = if let Ok(index) = next_identifier.parse::<usize>() {
|
||||||
index
|
index
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::expected_int(Value::String(
|
return Err(Error::expected_int(Value::Primitive(Primitive::String(
|
||||||
next_identifier.to_string(),
|
next_identifier.to_string(),
|
||||||
)));
|
))));
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut missing_elements = index.saturating_sub(list.len()) + 1;
|
let mut missing_elements = index.saturating_sub(list.len()) + 1;
|
||||||
@ -193,9 +193,13 @@ mod tests {
|
|||||||
fn get_and_set_simple_value() {
|
fn get_and_set_simple_value() {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
map.set_value("x".to_string(), Value::Integer(1)).unwrap();
|
map.set_value("x".to_string(), Value::Primitive(Primitive::Integer(1)))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(Value::Integer(1), map.get_value("x").unwrap().unwrap());
|
assert_eq!(
|
||||||
|
Value::Primitive(Primitive::Integer(1)),
|
||||||
|
map.get_value("x").unwrap().unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user