From 99338dedc5de09f1c637f576a775e3d2d4b43ddd Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 10 Dec 2023 13:47:05 -0500 Subject: [PATCH] Fix map deserialization; Clean up; Improve errors --- src/abstract_tree/function_call.rs | 4 +- src/error.rs | 83 ++++++++++++++++-------------- src/evaluate.rs | 6 +-- src/value/map.rs | 11 +++- src/value/mod.rs | 5 +- 5 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 17e68c3..d19629e 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -92,7 +92,9 @@ impl AbstractTree for FunctionCall { if let Some((value, _)) = variables.get(key) { value.clone() } else { - return Err(Error::FunctionIdentifierNotFound(identifier.clone())); + return Err(Error::FunctionIdentifierNotFound( + identifier.inner().clone(), + )); } } Expression::Index(index) => index.run(source, context)?, diff --git a/src/error.rs b/src/error.rs index 26f07f8..a611fbe 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,9 +5,16 @@ use tree_sitter::{Node, Point}; -use crate::{value::Value, BuiltInFunction, Identifier, Type}; +use crate::{value::Value, BuiltInFunction, Type}; -use std::{fmt, io, num::ParseFloatError, string::FromUtf8Error, sync::PoisonError, time}; +use std::{ + fmt::{self, Formatter}, + io, + num::ParseFloatError, + string::FromUtf8Error, + sync::PoisonError, + time, +}; pub type Result = std::result::Result; @@ -131,10 +138,10 @@ pub enum Error { VariableIdentifierNotFound(String), /// A `FunctionIdentifier` operation did not find its value in the context. - FunctionIdentifierNotFound(Identifier), + FunctionIdentifierNotFound(String), /// The function failed due to an external error. - ToolFailure(String), + External(String), /// A custom error explained by its message. CustomMessage(String), @@ -144,6 +151,8 @@ pub enum Error { source: String, location: Point, }, + + SerdeJson(String), } impl Error { @@ -208,55 +217,55 @@ impl Error { impl From> for Error { fn from(value: PoisonError) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: FromUtf8Error) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: ParseFloatError) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: csv::Error) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: std::io::Error) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: reqwest::Error) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: serde_json::Error) -> Self { - Error::ToolFailure(value.to_string()) + Error::SerdeJson(value.to_string()) } } impl From for Error { fn from(value: time::SystemTimeError) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } impl From for Error { fn from(value: toml::de::Error) -> Self { - Error::ToolFailure(value.to_string()) + Error::External(value.to_string()) } } @@ -269,15 +278,15 @@ impl fmt::Debug for Error { } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { use Error::*; match self { AssertEqualFailed { expected, actual } => { - write!(f, "Equality assertion failed")?; - write!(f, " {expected} ")?; - write!(f, "does not equal")?; - write!(f, " {actual}.") + write!( + f, + "Equality assertion failed. {expected} does not equal {actual}." + ) } AssertFailed => write!( f, @@ -305,20 +314,20 @@ impl fmt::Display for Error { "{function_name} expected a minimum of {minimum} arguments, but got {actual}.", ), ExpectedString { actual } => { - write!(f, "Expected a string but got {:?}.", actual) + write!(f, "Expected a string but got {actual}.") } - ExpectedInteger { actual } => write!(f, "Expected an integer, but got {:?}.", actual), - ExpectedFloat { actual } => write!(f, "Expected a float, but got {:?}.", actual), + ExpectedInteger { actual } => write!(f, "Expected an integer, but got {actual}."), + ExpectedFloat { actual } => write!(f, "Expected a float, but got {actual}."), ExpectedNumber { actual } => { - write!(f, "Expected a float or integer but got {:?}.", actual) + write!(f, "Expected a float or integer but got {actual}.",) } ExpectedNumberOrString { actual } => { - write!(f, "Expected a number or string, but got {:?}.", actual) + write!(f, "Expected a number or string, but got {actual}.") } ExpectedBoolean { actual } => { - write!(f, "Expected a boolean, but got {:?}.", actual) + write!(f, "Expected a boolean, but got {actual}.") } - ExpectedList { actual } => write!(f, "Expected a list, but got {:?}.", actual), + ExpectedList { actual } => write!(f, "Expected a list, but got {actual}."), ExpectedMinLengthList { minimum_len, actual_len, @@ -334,28 +343,25 @@ impl fmt::Display for Error { "Expected a list of len {}, but got {:?}.", expected_len, actual ), - ExpectedEmpty { actual } => write!(f, "Expected an empty value, but got {:?}.", actual), - ExpectedMap { actual } => write!(f, "Expected a map, but got {:?}.", actual), - ExpectedTable { actual } => write!(f, "Expected a table, but got {:?}.", actual), + ExpectedEmpty { actual } => write!(f, "Expected an empty value, but got {actual}."), + ExpectedMap { actual } => write!(f, "Expected a map, but got {actual}."), + ExpectedTable { actual } => write!(f, "Expected a table, but got {actual}."), ExpectedFunction { actual } => { - write!(f, "Expected function, but got {:?}.", actual) + write!(f, "Expected function, but got {actual}.") } ExpectedCollection { actual } => { write!( f, - "Expected a string, list, map or table, but got {:?}.", - actual + "Expected a string, list, map or table, but got {actual}.", ) } - VariableIdentifierNotFound(identifier) => write!( + VariableIdentifierNotFound(key) => write!( f, - "Variable identifier is not bound to anything by context: {}.", - identifier + "Variable identifier is not bound to anything by context: {key}.", ), - FunctionIdentifierNotFound(identifier) => write!( + FunctionIdentifierNotFound(key) => write!( f, - "Function identifier is not bound to anything by context: {}.", - identifier.inner() + "Function identifier is not bound to anything by context: {key}." ), UnexpectedSyntaxNode { expected, @@ -370,7 +376,7 @@ impl fmt::Display for Error { f, "Wrong column amount. Expected {expected} but got {actual}." ), - ToolFailure(message) => write!(f, "{message}"), + External(message) => write!(f, "External error: {message}"), CustomMessage(message) => write!(f, "{message}"), Syntax { source, location } => { write!(f, "Syntax error at {location}, this is not valid: {source}") @@ -384,6 +390,7 @@ impl fmt::Display for Error { location, source, } => write!(f, "{error} Occured at {location}: \"{source}\""), + SerdeJson(message) => write!(f, "JSON processing error: {message}"), } } } diff --git a/src/evaluate.rs b/src/evaluate.rs index 1af462f..d3280e6 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -34,9 +34,9 @@ pub fn evaluate(source: &str) -> Result { /// { /// let mut variables = context.variables_mut().unwrap(); /// -/// variables.insert("one".into(), 1.into()); -/// variables.insert("two".into(), 2.into()); -/// variables.insert("three".into(), 3.into()); +/// variables.insert("one".into(), (1.into(), Type::Integer)); +/// variables.insert("two".into(), (2.into(), Type::Integer)); +/// variables.insert("three".into(), (3.into(), Type::Integer)); /// } /// /// let dust_code = "four = 4 one + two + three + four"; diff --git a/src/value/map.rs b/src/value/map.rs index 1efe1d3..f949f6a 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -1,4 +1,4 @@ -use serde::Serialize; +use serde::{ser::SerializeMap, Deserialize, Serialize}; use std::{ cmp::Ordering, collections::BTreeMap, @@ -118,6 +118,13 @@ impl Serialize for Map { where S: serde::Serializer, { - self.variables.serialize(serializer) + let variables = self.variables.read().unwrap(); + let mut map = serializer.serialize_map(Some(variables.len()))?; + + for (key, (value, _type)) in variables.iter() { + map.serialize_entry(key, value)?; + } + + map.end() } } diff --git a/src/value/mod.rs b/src/value/mod.rs index cea810e..f37c747 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -783,8 +783,9 @@ impl<'de> Visitor<'de> for ValueVisitor { { let mut variables = map.variables_mut().unwrap(); - while let Some((key, value)) = access.next_entry()? { - variables.insert(key, value); + while let Some((key, value)) = access.next_entry::()? { + let r#type = value.r#type(); + variables.insert(key, (value, r#type)); } }