Implement serde for Value; Rework comment parsing
This commit is contained in:
parent
d37c618ead
commit
859d8db384
@ -65,11 +65,7 @@ impl AbstractNode for Assignment {
|
||||
..
|
||||
} = function_type
|
||||
{
|
||||
if let Type::Generic {
|
||||
identifier,
|
||||
concrete_type,
|
||||
} = *return_type
|
||||
{
|
||||
if let Type::Generic { identifier, .. } = *return_type {
|
||||
let returned_parameter = type_parameters
|
||||
.into_iter()
|
||||
.find(|parameter| parameter == &identifier);
|
||||
|
@ -24,7 +24,7 @@ impl<'src> Display for Token<'src> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Token::Boolean(boolean) => write!(f, "{boolean}"),
|
||||
Token::Comment(comment) => write!(f, "# {comment}"),
|
||||
Token::Comment(comment) => write!(f, "// {comment}"),
|
||||
Token::Integer(integer) => write!(f, "{integer}"),
|
||||
Token::Float(float) => write!(f, "{float}"),
|
||||
Token::String(string) => write!(f, "{string}"),
|
||||
|
@ -204,96 +204,109 @@ impl InterpreterError {
|
||||
|
||||
for error in self.errors {
|
||||
let (mut builder, validation_error) = match error {
|
||||
DustError::Lex {
|
||||
expected,
|
||||
span,
|
||||
reason,
|
||||
} => {
|
||||
let description = if expected.is_empty() {
|
||||
"Invalid character.".to_string()
|
||||
} else {
|
||||
format!("Expected {expected}.")
|
||||
};
|
||||
DustError::Lex {
|
||||
expected,
|
||||
span,
|
||||
reason,
|
||||
} => {
|
||||
let description = if expected.is_empty() {
|
||||
"Invalid character.".to_string()
|
||||
} else {
|
||||
format!("Expected {expected}.")
|
||||
};
|
||||
|
||||
(
|
||||
Report::build(
|
||||
ReportKind::Custom("Lexing Error", Color::Yellow),
|
||||
self.source_id.clone(),
|
||||
span.1,
|
||||
(
|
||||
Report::build(
|
||||
ReportKind::Custom("Lexing Error", Color::Yellow),
|
||||
self.source_id.clone(),
|
||||
span.1,
|
||||
)
|
||||
.with_message(description)
|
||||
.with_label(
|
||||
Label::new((self.source_id.clone(), span.0..span.1))
|
||||
.with_message(reason)
|
||||
.with_color(Color::Red),
|
||||
),
|
||||
None,
|
||||
)
|
||||
.with_message(description)
|
||||
.with_label(
|
||||
Label::new((self.source_id.clone(), span.0..span.1))
|
||||
.with_message(reason)
|
||||
.with_color(Color::Red),
|
||||
),
|
||||
None,
|
||||
)
|
||||
}
|
||||
DustError::Parse {
|
||||
expected,
|
||||
span,
|
||||
found,
|
||||
} => {
|
||||
let description = if expected.is_empty() {
|
||||
"Invalid token.".to_string()
|
||||
} else {
|
||||
format!("Expected {expected}.")
|
||||
};
|
||||
let found = found.unwrap_or_else(|| "End of input".to_string()).fg(token_color);
|
||||
}
|
||||
DustError::Parse {
|
||||
expected,
|
||||
span,
|
||||
found,
|
||||
} => {
|
||||
let description = if expected.is_empty() {
|
||||
"Invalid token.".to_string()
|
||||
} else {
|
||||
format!("Expected {expected}.")
|
||||
};
|
||||
let found = found
|
||||
.unwrap_or_else(|| "End of input".to_string())
|
||||
.fg(token_color);
|
||||
|
||||
(
|
||||
Report::build(
|
||||
ReportKind::Custom("Parsing Error", Color::Yellow),
|
||||
self.source_id.clone(),
|
||||
span.1,
|
||||
(
|
||||
Report::build(
|
||||
ReportKind::Custom("Parsing Error", Color::Yellow),
|
||||
self.source_id.clone(),
|
||||
span.1,
|
||||
)
|
||||
.with_message(description)
|
||||
.with_label(
|
||||
Label::new((self.source_id.clone(), span.0..span.1))
|
||||
.with_message(format!("{found} is not valid in this position."))
|
||||
.with_color(Color::Red),
|
||||
),
|
||||
None,
|
||||
)
|
||||
.with_message(description)
|
||||
.with_label(
|
||||
Label::new((self.source_id.clone(), span.0..span.1))
|
||||
.with_message(format!("{found} is not valid in this position."))
|
||||
.with_color(Color::Red),
|
||||
}
|
||||
DustError::Validation { error, position } => (
|
||||
Report::build(
|
||||
ReportKind::Custom("Validation Error", Color::Magenta),
|
||||
self.source_id.clone(),
|
||||
position.1,
|
||||
)
|
||||
.with_message("The syntax is valid but this code would cause an error.")
|
||||
.with_note(
|
||||
"This error was detected by the interpreter before running the code.",
|
||||
),
|
||||
None,
|
||||
)
|
||||
}
|
||||
DustError::Validation { error, position } => (
|
||||
Report::build(
|
||||
ReportKind::Custom("Validation Error", Color::Magenta),
|
||||
self.source_id.clone(),
|
||||
position.1,
|
||||
)
|
||||
.with_message("The syntax is valid but this code would cause an error.")
|
||||
.with_note("This error was detected by the interpreter before running the code."),
|
||||
Some(error),
|
||||
),
|
||||
DustError::Runtime { error, position } => (
|
||||
Report::build(
|
||||
ReportKind::Custom("Runtime Error", Color::Red),
|
||||
self.source_id.clone(),
|
||||
position.1,
|
||||
)
|
||||
.with_message("An error occured that forced the program to exit.")
|
||||
.with_note(
|
||||
"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_label(
|
||||
Label::new((self.source_id.clone(), position.0..position.1)).with_message("Runtime error occured here.")
|
||||
Some(error),
|
||||
),
|
||||
if let RuntimeError::ValidationFailure(validation_error) = error {
|
||||
Some(validation_error)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
),
|
||||
};
|
||||
DustError::Runtime { error, position } => {
|
||||
let error_message = match &error {
|
||||
RuntimeError::Io(_) => todo!(),
|
||||
RuntimeError::RwLockPoison(_) => todo!(),
|
||||
RuntimeError::ValidationFailure(_) => todo!(),
|
||||
RuntimeError::SerdeJson(serde_json_error) => serde_json_error.to_string(),
|
||||
};
|
||||
|
||||
(
|
||||
Report::build(
|
||||
ReportKind::Custom("Runtime Error", Color::Red),
|
||||
self.source_id.clone(),
|
||||
position.1,
|
||||
)
|
||||
.with_message("An error occured that forced the program to exit.")
|
||||
.with_note(
|
||||
"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_label(
|
||||
Label::new((self.source_id.clone(), position.0..position.1)).with_message(error_message)
|
||||
),
|
||||
|
||||
if let RuntimeError::ValidationFailure(validation_error) = error {
|
||||
Some(validation_error)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(validation_error) = validation_error {
|
||||
match validation_error {
|
||||
|
||||
ValidationError::CannotAssignToNone(postion) => {
|
||||
builder.add_label(
|
||||
Label::new((self.source_id.clone(), postion.0..postion.1))
|
||||
|
@ -33,6 +33,9 @@ pub fn parse<'src>(
|
||||
pub fn parser<'src>(
|
||||
allow_built_ins: bool,
|
||||
) -> impl Parser<'src, ParserInput<'src>, Vec<Statement>, ParserExtra<'src>> {
|
||||
let comment = select_ref! {
|
||||
Token::Comment(_) => {}
|
||||
};
|
||||
let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new());
|
||||
let identifier = select! {
|
||||
Token::Identifier(text) => {
|
||||
@ -527,6 +530,7 @@ pub fn parser<'src>(
|
||||
basic_value,
|
||||
identifier_expression,
|
||||
))
|
||||
// .delimited_by(comment.clone().or_not(), comment.or_not())
|
||||
});
|
||||
|
||||
let expression_statement = expression
|
||||
@ -621,27 +625,24 @@ pub fn parser<'src>(
|
||||
)
|
||||
});
|
||||
|
||||
choice((
|
||||
async_block,
|
||||
if_else,
|
||||
assignment,
|
||||
expression_statement,
|
||||
r#break,
|
||||
block_statement,
|
||||
r#loop,
|
||||
r#while,
|
||||
type_assignment,
|
||||
))
|
||||
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
||||
comment
|
||||
.repeated()
|
||||
.or_not()
|
||||
.ignore_then(choice((
|
||||
async_block,
|
||||
if_else,
|
||||
assignment,
|
||||
expression_statement,
|
||||
r#break,
|
||||
block_statement,
|
||||
r#loop,
|
||||
r#while,
|
||||
type_assignment,
|
||||
)))
|
||||
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
||||
});
|
||||
|
||||
select_ref! {
|
||||
Token::Comment(_) => {}
|
||||
}
|
||||
.or_not()
|
||||
.ignore_then(statement)
|
||||
.repeated()
|
||||
.collect()
|
||||
statement.repeated().collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -6,7 +6,11 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{
|
||||
de::Visitor,
|
||||
ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple},
|
||||
Deserialize, Deserializer, Serialize,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
||||
@ -184,20 +188,312 @@ impl Ord for Value {
|
||||
}
|
||||
|
||||
impl Serialize for Value {
|
||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match self.0.as_ref() {
|
||||
ValueInner::Boolean(boolean) => serializer.serialize_bool(*boolean),
|
||||
ValueInner::Float(float) => serializer.serialize_f64(*float),
|
||||
ValueInner::Function(Function {
|
||||
type_parameters,
|
||||
value_parameters,
|
||||
return_type,
|
||||
body,
|
||||
}) => {
|
||||
let mut struct_ser = serializer.serialize_struct("Function", 4)?;
|
||||
|
||||
struct_ser.serialize_field("type_parameters", type_parameters)?;
|
||||
struct_ser.serialize_field("value_parameters", value_parameters)?;
|
||||
struct_ser.serialize_field("return_type", return_type)?;
|
||||
struct_ser.serialize_field("body", body)?;
|
||||
|
||||
struct_ser.end()
|
||||
}
|
||||
ValueInner::Integer(integer) => serializer.serialize_i64(*integer),
|
||||
ValueInner::List(list) => {
|
||||
let mut list_ser = serializer.serialize_seq(Some(list.len()))?;
|
||||
|
||||
for item in list {
|
||||
list_ser.serialize_element(&item.node)?;
|
||||
}
|
||||
|
||||
list_ser.end()
|
||||
}
|
||||
ValueInner::Map(map) => {
|
||||
let mut map_ser = serializer.serialize_map(Some(map.len()))?;
|
||||
|
||||
for (identifier, value) in map {
|
||||
map_ser.serialize_entry(identifier, value)?;
|
||||
}
|
||||
|
||||
map_ser.end()
|
||||
}
|
||||
ValueInner::Range(range) => {
|
||||
let mut tuple_ser = serializer.serialize_tuple(2)?;
|
||||
|
||||
tuple_ser.serialize_element(&range.start)?;
|
||||
tuple_ser.serialize_element(&range.end)?;
|
||||
|
||||
tuple_ser.end()
|
||||
}
|
||||
ValueInner::String(string) => serializer.serialize_str(string),
|
||||
ValueInner::Structure { name, fields } => {
|
||||
let mut struct_ser = serializer.serialize_struct("Structure", 2)?;
|
||||
|
||||
struct_ser.serialize_field("name", name)?;
|
||||
struct_ser.serialize_field("fields", fields)?;
|
||||
|
||||
struct_ser.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ValueVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ValueVisitor {
|
||||
type Value = Value;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
.write_str("a boolean, float, function, integer, list, map, range, string or structure")
|
||||
}
|
||||
|
||||
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Bool(v),
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_i64(v as i64)
|
||||
}
|
||||
|
||||
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_i64(v as i64)
|
||||
}
|
||||
|
||||
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_i64(v as i64)
|
||||
}
|
||||
|
||||
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Ok(Value::integer(v))
|
||||
}
|
||||
|
||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_u64(v as u64)
|
||||
}
|
||||
|
||||
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_u64(v as u64)
|
||||
}
|
||||
|
||||
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_u64(v as u64)
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Ok(Value::integer(v as i64))
|
||||
}
|
||||
|
||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_f64(v as f64)
|
||||
}
|
||||
|
||||
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Float(v),
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
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,
|
||||
{
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Str(v),
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Bytes(v),
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_bytes(v)
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_bytes(&v)
|
||||
}
|
||||
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Option,
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let _ = deserializer;
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Option,
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Unit,
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let _ = deserializer;
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::NewtypeStruct,
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, 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,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, 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,
|
||||
))
|
||||
}
|
||||
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: serde::de::EnumAccess<'de>,
|
||||
{
|
||||
let _ = data;
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Enum,
|
||||
&self,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Value {
|
||||
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
todo!()
|
||||
deserializer.deserialize_any(ValueVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,16 @@
|
||||
// This function returns its argument.
|
||||
foo = fn |T| (x: T) -> T { x }
|
||||
bar: str = foo::(str)::("hi")
|
||||
|
||||
// Use turbofish to supply type information.
|
||||
bar = foo::(str)::("hi")
|
||||
|
||||
// Use type annotation
|
||||
baz: str = foo("hi")
|
||||
|
||||
// The `json.parse` function takes a string and returns the specified type
|
||||
|
||||
// Use turbofish
|
||||
x = json.parse::(int)::("1")
|
||||
|
||||
// Use type annotation
|
||||
x: int = json.parse("1")
|
||||
|
Loading…
Reference in New Issue
Block a user