Fix map deserialization; Clean up; Improve errors
This commit is contained in:
parent
744290f0d4
commit
99338dedc5
@ -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)?,
|
||||||
|
83
src/error.rs
83
src/error.rs
@ -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}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user