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);
|
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)
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
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(),
|
||||||
|
@ -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()),
|
||||||
])))
|
])))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
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