Implement serde traits for Value

This commit is contained in:
Jeff 2024-06-19 04:56:56 -04:00
parent 859d8db384
commit ed4820a137
7 changed files with 84 additions and 59 deletions

View File

@ -82,7 +82,7 @@ impl AbstractNode for ListIndex {
let found_item = list.get(index as usize); let found_item = list.get(index as usize);
if let Some(item) = found_item { if let Some(item) = found_item {
Ok(Evaluation::Return(item.node.clone())) Ok(Evaluation::Return(item.clone()))
} else { } else {
Ok(Evaluation::None) Ok(Evaluation::None)
} }

View File

@ -149,12 +149,9 @@ impl AbstractNode for ValueNode {
for expression in expression_list { for expression in expression_list {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.evaluate(context, _manage_memory)?; let evaluation = expression.evaluate(context, _manage_memory)?;
let value = if let Evaluation::Return(value) = action { let value = if let Evaluation::Return(value) = evaluation {
WithPosition { value
node: value,
position: expression_position,
}
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression_position), ValidationError::InterpreterExpectedReturn(expression_position),

View File

@ -38,18 +38,44 @@ impl<'de> Deserialize<'de> for Identifier {
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
Ok(Identifier(Arc::new( deserializer.deserialize_identifier(IdentifierVisitor)
deserializer.deserialize_string(StringVisitor)?,
)))
} }
} }
struct StringVisitor; struct IdentifierVisitor;
impl<'de> Visitor<'de> for StringVisitor { impl<'de> Visitor<'de> for IdentifierVisitor {
type Value = String; type Value = Identifier;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a UTF-8 string") formatter.write_str("a UTF-8 string")
} }
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Identifier::new(v))
}
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.visit_str(v)
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.visit_str(&v)
}
} }

View File

@ -272,11 +272,13 @@ impl InterpreterError {
Some(error), Some(error),
), ),
DustError::Runtime { error, position } => { DustError::Runtime { error, position } => {
let error_message = match &error { let note = match &error {
RuntimeError::Io(_) => todo!(), RuntimeError::Io(io_error) => &io_error.to_string(),
RuntimeError::RwLockPoison(_) => todo!(), RuntimeError::RwLockPoison(_) => todo!(),
RuntimeError::ValidationFailure(_) => todo!(), RuntimeError::ValidationFailure(_) => {
RuntimeError::SerdeJson(serde_json_error) => serde_json_error.to_string(), "This is the interpreter's fault. Please submit a bug with this error message."
}
RuntimeError::SerdeJson(serde_json_error) => &serde_json_error.to_string(),
}; };
( (
@ -286,14 +288,12 @@ impl InterpreterError {
position.1, position.1,
) )
.with_message("An error occured that forced the program to exit.") .with_message("An error occured that forced the program to exit.")
.with_note( .with_help(
"There may be unexpected side-effects because the program could not finish.", "There may be unexpected side-effects because the program could not finish.",
) )
.with_help( .with_note(note)
"This is the interpreter's fault. Please submit a bug with this error message.",
)
.with_label( .with_label(
Label::new((self.source_id.clone(), position.0..position.1)).with_message(error_message) Label::new((self.source_id.clone(), position.0..position.1)).with_message("Error occured here.")
), ),
if let RuntimeError::ValidationFailure(validation_error) = error { if let RuntimeError::ValidationFailure(validation_error) = error {

View File

@ -6,6 +6,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
use chumsky::container::Container;
use serde::{ use serde::{
de::Visitor, de::Visitor,
ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple}, ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple},
@ -39,7 +40,7 @@ impl Value {
Value(Arc::new(ValueInner::Integer(integer))) Value(Arc::new(ValueInner::Integer(integer)))
} }
pub fn list(list: Vec<WithPosition<Value>>) -> Self { pub fn list(list: Vec<Value>) -> Self {
Value(Arc::new(ValueInner::List(list))) Value(Arc::new(ValueInner::List(list)))
} }
@ -85,7 +86,7 @@ impl Value {
} }
} }
pub fn as_list(&self) -> Option<&Vec<WithPosition<Value>>> { pub fn as_list(&self) -> Option<&Vec<Value>> {
if let ValueInner::List(list) = self.inner().as_ref() { if let ValueInner::List(list) = self.inner().as_ref() {
Some(list) Some(list)
} else { } else {
@ -113,9 +114,9 @@ impl Display for Value {
for (index, value) in list.into_iter().enumerate() { for (index, value) in list.into_iter().enumerate() {
if index == list.len() - 1 { if index == list.len() - 1 {
write!(f, "{}", value.node)?; write!(f, "{}", value)?;
} else { } else {
write!(f, "{}, ", value.node)?; write!(f, "{}, ", value)?;
} }
} }
@ -215,7 +216,7 @@ impl Serialize for Value {
let mut list_ser = serializer.serialize_seq(Some(list.len()))?; let mut list_ser = serializer.serialize_seq(Some(list.len()))?;
for item in list { for item in list {
list_ser.serialize_element(&item.node)?; list_ser.serialize_element(&item)?;
} }
list_ser.end() list_ser.end()
@ -264,10 +265,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
where where
E: serde::de::Error, E: serde::de::Error,
{ {
Err(serde::de::Error::invalid_type( Ok(Value::boolean(v))
serde::de::Unexpected::Bool(v),
&self,
))
} }
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E> fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
@ -298,7 +296,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
Ok(Value::integer(v)) Ok(Value::integer(v))
} }
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> fn visit_i128<E>(self, _: i128) -> Result<Self::Value, E>
where where
E: serde::de::Error, E: serde::de::Error,
{ {
@ -333,7 +331,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
Ok(Value::integer(v as i64)) Ok(Value::integer(v as i64))
} }
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> fn visit_u128<E>(self, _: u128) -> Result<Self::Value, E>
where where
E: serde::de::Error, E: serde::de::Error,
{ {
@ -351,10 +349,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
where where
E: serde::de::Error, E: serde::de::Error,
{ {
Err(serde::de::Error::invalid_type( Ok(Value::float(v))
serde::de::Unexpected::Float(v),
&self,
))
} }
fn visit_char<E>(self, v: char) -> Result<Self::Value, E> fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
@ -368,10 +363,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
where where
E: serde::de::Error, E: serde::de::Error,
{ {
Err(serde::de::Error::invalid_type( Ok(Value::string(v))
serde::de::Unexpected::Str(v),
&self,
))
} }
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
@ -454,26 +446,30 @@ impl<'de> Visitor<'de> for ValueVisitor {
)) ))
} }
fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: serde::de::SeqAccess<'de>, A: serde::de::SeqAccess<'de>,
{ {
let _ = seq; let mut list = Vec::with_capacity(seq.size_hint().unwrap_or(10));
Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Seq, while let Some(element) = seq.next_element()? {
&self, list.push(element);
)) }
Ok(Value::list(list))
} }
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: serde::de::MapAccess<'de>, A: serde::de::MapAccess<'de>,
{ {
let _ = map; let mut btree = BTreeMap::with_capacity(map.size_hint().unwrap_or(10));
Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Map, while let Some((key, value)) = map.next_entry()? {
&self, btree.insert(key, value);
)) }
Ok(Value::map(btree))
} }
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
@ -503,7 +499,7 @@ pub enum ValueInner {
Float(f64), Float(f64),
Function(Function), Function(Function),
Integer(i64), Integer(i64),
List(Vec<WithPosition<Value>>), List(Vec<Value>),
Map(BTreeMap<Identifier, Value>), Map(BTreeMap<Identifier, Value>),
Range(Range<i64>), Range(Range<i64>),
String(String), String(String),
@ -520,7 +516,7 @@ impl ValueInner {
ValueInner::Float(_) => Type::Float, ValueInner::Float(_) => Type::Float,
ValueInner::Integer(_) => Type::Integer, ValueInner::Integer(_) => Type::Integer,
ValueInner::List(values) => { ValueInner::List(values) => {
let item_type = values.first().unwrap().node.r#type(context)?; let item_type = values.first().unwrap().r#type(context)?;
Type::List { Type::List {
length: values.len(), length: values.len(),

View File

@ -1,7 +1,7 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use dust_lang::{ use dust_lang::{
abstract_tree::{Type, WithPos}, abstract_tree::Type,
error::{DustError, TypeConflict, ValidationError}, error::{DustError, TypeConflict, ValidationError},
identifier::Identifier, identifier::Identifier,
*, *,
@ -89,9 +89,9 @@ fn list() {
assert_eq!( assert_eq!(
interpret("test", "[1, 2, 'foobar']"), interpret("test", "[1, 2, 'foobar']"),
Ok(Some(Value::list(vec![ Ok(Some(Value::list(vec![
Value::integer(1).with_position((1, 2)), Value::integer(1),
Value::integer(2).with_position((4, 5)), Value::integer(2),
Value::string("foobar".to_string()).with_position((7, 15)), Value::string("foobar".to_string()),
]))) ])))
); );
} }

View File

@ -0,0 +1,6 @@
[
{ "name": "Sammy", "type": "shark", "clams": 5 },
{ "name": "Bubbles", "type": "orca", "clams": 3 },
{ "name": "Splish", "type": "dolphin", "clams": 2 },
{ "name": "Splash", "type": "dolphin", "clams": 2 }
]