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);
if let Some(item) = found_item {
Ok(Evaluation::Return(item.node.clone()))
Ok(Evaluation::Return(item.clone()))
} else {
Ok(Evaluation::None)
}

View File

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

View File

@ -38,18 +38,44 @@ impl<'de> Deserialize<'de> for Identifier {
where
D: serde::Deserializer<'de>,
{
Ok(Identifier(Arc::new(
deserializer.deserialize_string(StringVisitor)?,
)))
deserializer.deserialize_identifier(IdentifierVisitor)
}
}
struct StringVisitor;
struct IdentifierVisitor;
impl<'de> Visitor<'de> for StringVisitor {
type Value = String;
impl<'de> Visitor<'de> for IdentifierVisitor {
type Value = Identifier;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
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),
),
DustError::Runtime { error, position } => {
let error_message = match &error {
RuntimeError::Io(_) => todo!(),
let note = match &error {
RuntimeError::Io(io_error) => &io_error.to_string(),
RuntimeError::RwLockPoison(_) => todo!(),
RuntimeError::ValidationFailure(_) => todo!(),
RuntimeError::SerdeJson(serde_json_error) => serde_json_error.to_string(),
RuntimeError::ValidationFailure(_) => {
"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,
)
.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.",
)
.with_help(
"This is the interpreter's fault. Please submit a bug with this error message.",
)
.with_note(note)
.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 {

View File

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

View File

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