Implement serde traits for Value
This commit is contained in:
parent
859d8db384
commit
ed4820a137
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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()),
|
||||
])))
|
||||
);
|
||||
}
|
||||
|
6
examples/assets/data.json
Normal file
6
examples/assets/data.json
Normal 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 }
|
||||
]
|
Loading…
Reference in New Issue
Block a user