Fix map deserialization; Clean up; Improve errors

This commit is contained in:
Jeff 2023-12-10 13:47:05 -05:00
parent 744290f0d4
commit 99338dedc5
5 changed files with 63 additions and 46 deletions

View File

@ -92,7 +92,9 @@ impl AbstractTree for FunctionCall {
if let Some((value, _)) = variables.get(key) { if let Some((value, _)) = variables.get(key) {
value.clone() value.clone()
} else { } else {
return Err(Error::FunctionIdentifierNotFound(identifier.clone())); return Err(Error::FunctionIdentifierNotFound(
identifier.inner().clone(),
));
} }
} }
Expression::Index(index) => index.run(source, context)?, Expression::Index(index) => index.run(source, context)?,

View File

@ -5,9 +5,16 @@
use tree_sitter::{Node, Point}; 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<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
@ -131,10 +138,10 @@ pub enum Error {
VariableIdentifierNotFound(String), VariableIdentifierNotFound(String),
/// A `FunctionIdentifier` operation did not find its value in the context. /// A `FunctionIdentifier` operation did not find its value in the context.
FunctionIdentifierNotFound(Identifier), FunctionIdentifierNotFound(String),
/// The function failed due to an external error. /// The function failed due to an external error.
ToolFailure(String), External(String),
/// A custom error explained by its message. /// A custom error explained by its message.
CustomMessage(String), CustomMessage(String),
@ -144,6 +151,8 @@ pub enum Error {
source: String, source: String,
location: Point, location: Point,
}, },
SerdeJson(String),
} }
impl Error { impl Error {
@ -208,55 +217,55 @@ impl Error {
impl<T> From<PoisonError<T>> for Error { impl<T> From<PoisonError<T>> for Error {
fn from(value: PoisonError<T>) -> Self { fn from(value: PoisonError<T>) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<FromUtf8Error> for Error { impl From<FromUtf8Error> for Error {
fn from(value: FromUtf8Error) -> Self { fn from(value: FromUtf8Error) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<ParseFloatError> for Error { impl From<ParseFloatError> for Error {
fn from(value: ParseFloatError) -> Self { fn from(value: ParseFloatError) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<csv::Error> for Error { impl From<csv::Error> for Error {
fn from(value: csv::Error) -> Self { fn from(value: csv::Error) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<io::Error> for Error { impl From<io::Error> for Error {
fn from(value: std::io::Error) -> Self { fn from(value: std::io::Error) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<reqwest::Error> for Error { impl From<reqwest::Error> for Error {
fn from(value: reqwest::Error) -> Self { fn from(value: reqwest::Error) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<serde_json::Error> for Error { impl From<serde_json::Error> for Error {
fn from(value: serde_json::Error) -> Self { fn from(value: serde_json::Error) -> Self {
Error::ToolFailure(value.to_string()) Error::SerdeJson(value.to_string())
} }
} }
impl From<time::SystemTimeError> for Error { impl From<time::SystemTimeError> for Error {
fn from(value: time::SystemTimeError) -> Self { fn from(value: time::SystemTimeError) -> Self {
Error::ToolFailure(value.to_string()) Error::External(value.to_string())
} }
} }
impl From<toml::de::Error> for Error { impl From<toml::de::Error> for Error {
fn from(value: toml::de::Error) -> Self { 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 { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use Error::*; use Error::*;
match self { match self {
AssertEqualFailed { expected, actual } => { AssertEqualFailed { expected, actual } => {
write!(f, "Equality assertion failed")?; write!(
write!(f, " {expected} ")?; f,
write!(f, "does not equal")?; "Equality assertion failed. {expected} does not equal {actual}."
write!(f, " {actual}.") )
} }
AssertFailed => write!( AssertFailed => write!(
f, f,
@ -305,20 +314,20 @@ impl fmt::Display for Error {
"{function_name} expected a minimum of {minimum} arguments, but got {actual}.", "{function_name} expected a minimum of {minimum} arguments, but got {actual}.",
), ),
ExpectedString { 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), ExpectedInteger { actual } => write!(f, "Expected an integer, but got {actual}."),
ExpectedFloat { actual } => write!(f, "Expected a float, but got {:?}.", actual), ExpectedFloat { actual } => write!(f, "Expected a float, but got {actual}."),
ExpectedNumber { 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 } => { ExpectedNumberOrString { actual } => {
write!(f, "Expected a number or string, but got {:?}.", actual) write!(f, "Expected a number or string, but got {actual}.")
} }
ExpectedBoolean { 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 { ExpectedMinLengthList {
minimum_len, minimum_len,
actual_len, actual_len,
@ -334,28 +343,25 @@ impl fmt::Display for Error {
"Expected a list of len {}, but got {:?}.", "Expected a list of len {}, but got {:?}.",
expected_len, actual expected_len, actual
), ),
ExpectedEmpty { actual } => write!(f, "Expected an empty value, but got {:?}.", actual), ExpectedEmpty { actual } => write!(f, "Expected an empty value, but got {actual}."),
ExpectedMap { actual } => write!(f, "Expected a map, but got {:?}.", actual), ExpectedMap { actual } => write!(f, "Expected a map, but got {actual}."),
ExpectedTable { actual } => write!(f, "Expected a table, but got {:?}.", actual), ExpectedTable { actual } => write!(f, "Expected a table, but got {actual}."),
ExpectedFunction { actual } => { ExpectedFunction { actual } => {
write!(f, "Expected function, but got {:?}.", actual) write!(f, "Expected function, but got {actual}.")
} }
ExpectedCollection { actual } => { ExpectedCollection { actual } => {
write!( write!(
f, f,
"Expected a string, list, map or table, but got {:?}.", "Expected a string, list, map or table, but got {actual}.",
actual
) )
} }
VariableIdentifierNotFound(identifier) => write!( VariableIdentifierNotFound(key) => write!(
f, f,
"Variable identifier is not bound to anything by context: {}.", "Variable identifier is not bound to anything by context: {key}.",
identifier
), ),
FunctionIdentifierNotFound(identifier) => write!( FunctionIdentifierNotFound(key) => write!(
f, f,
"Function identifier is not bound to anything by context: {}.", "Function identifier is not bound to anything by context: {key}."
identifier.inner()
), ),
UnexpectedSyntaxNode { UnexpectedSyntaxNode {
expected, expected,
@ -370,7 +376,7 @@ impl fmt::Display for Error {
f, f,
"Wrong column amount. Expected {expected} but got {actual}." "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}"), CustomMessage(message) => write!(f, "{message}"),
Syntax { source, location } => { Syntax { source, location } => {
write!(f, "Syntax error at {location}, this is not valid: {source}") write!(f, "Syntax error at {location}, this is not valid: {source}")
@ -384,6 +390,7 @@ impl fmt::Display for Error {
location, location,
source, source,
} => write!(f, "{error} Occured at {location}: \"{source}\""), } => write!(f, "{error} Occured at {location}: \"{source}\""),
SerdeJson(message) => write!(f, "JSON processing error: {message}"),
} }
} }
} }

View File

@ -34,9 +34,9 @@ pub fn evaluate(source: &str) -> Result<Value> {
/// { /// {
/// let mut variables = context.variables_mut().unwrap(); /// let mut variables = context.variables_mut().unwrap();
/// ///
/// variables.insert("one".into(), 1.into()); /// variables.insert("one".into(), (1.into(), Type::Integer));
/// variables.insert("two".into(), 2.into()); /// variables.insert("two".into(), (2.into(), Type::Integer));
/// variables.insert("three".into(), 3.into()); /// variables.insert("three".into(), (3.into(), Type::Integer));
/// } /// }
/// ///
/// let dust_code = "four = 4 one + two + three + four"; /// let dust_code = "four = 4 one + two + three + four";

View File

@ -1,4 +1,4 @@
use serde::Serialize; use serde::{ser::SerializeMap, Deserialize, Serialize};
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::BTreeMap, collections::BTreeMap,
@ -118,6 +118,13 @@ impl Serialize for Map {
where where
S: serde::Serializer, 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()
} }
} }

View File

@ -783,8 +783,9 @@ impl<'de> Visitor<'de> for ValueVisitor {
{ {
let mut variables = map.variables_mut().unwrap(); let mut variables = map.variables_mut().unwrap();
while let Some((key, value)) = access.next_entry()? { while let Some((key, value)) = access.next_entry::<String, Value>()? {
variables.insert(key, value); let r#type = value.r#type();
variables.insert(key, (value, r#type));
} }
} }