Implement serde for Value; Rework comment parsing

This commit is contained in:
Jeff 2024-06-19 03:32:51 -04:00
parent d37c618ead
commit 859d8db384
6 changed files with 429 additions and 112 deletions

View File

@ -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);

View File

@ -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}"),

View File

@ -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))

View File

@ -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)]

View File

@ -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)
}
}

View File

@ -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")