From 73ff1d85e0406d2d2588ee69531607ad169c321b Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu Date: Tue, 21 Sep 2021 18:28:50 -0700 Subject: [PATCH] Added custom serialization for spans in tuple-like enum variants; changed expected output in serialization test --- ast/src/expression/value.rs | 24 ++++++-- ast/src/groups/group_coordinate.rs | 5 +- ast/src/groups/group_value.rs | 5 +- ast/src/statements/assign/assignee.rs | 2 +- errors/src/common/mod.rs | 5 ++ errors/src/common/span_json.rs | 55 +++++++++++++++++++ .../tests/serialization/expected_leo_ast.json | 28 ++++++---- 7 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 errors/src/common/span_json.rs diff --git a/ast/src/expression/value.rs b/ast/src/expression/value.rs index f9201de574..dab9623d65 100644 --- a/ast/src/expression/value.rs +++ b/ast/src/expression/value.rs @@ -22,18 +22,30 @@ use crate::{Char, CharValue}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ValueExpression { // todo: deserialize values here - Address(#[serde(with = "leo_errors::common::tendril_json")] StrTendril, Span), - Boolean(#[serde(with = "leo_errors::common::tendril_json")] StrTendril, Span), + Address( + #[serde(with = "leo_errors::common::tendril_json")] StrTendril, + #[serde(with = "leo_errors::common::span_json")] Span, + ), + Boolean( + #[serde(with = "leo_errors::common::tendril_json")] StrTendril, + #[serde(with = "leo_errors::common::span_json")] Span, + ), Char(CharValue), - Field(#[serde(with = "leo_errors::common::tendril_json")] StrTendril, Span), + Field( + #[serde(with = "leo_errors::common::tendril_json")] StrTendril, + #[serde(with = "leo_errors::common::span_json")] Span, + ), Group(Box), - Implicit(#[serde(with = "leo_errors::common::tendril_json")] StrTendril, Span), + Implicit( + #[serde(with = "leo_errors::common::tendril_json")] StrTendril, + #[serde(with = "leo_errors::common::span_json")] Span, + ), Integer( IntegerType, #[serde(with = "leo_errors::common::tendril_json")] StrTendril, - Span, + #[serde(with = "leo_errors::common::span_json")] Span, ), - String(Vec, Span), + String(Vec, #[serde(with = "leo_errors::common::span_json")] Span), } impl fmt::Display for ValueExpression { diff --git a/ast/src/groups/group_coordinate.rs b/ast/src/groups/group_coordinate.rs index d13c7b9d19..a9073662e4 100644 --- a/ast/src/groups/group_coordinate.rs +++ b/ast/src/groups/group_coordinate.rs @@ -26,7 +26,10 @@ use tendril::StrTendril; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum GroupCoordinate { - Number(#[serde(with = "leo_errors::common::tendril_json")] StrTendril, Span), + Number( + #[serde(with = "leo_errors::common::tendril_json")] StrTendril, + #[serde(with = "leo_errors::common::span_json")] Span, + ), SignHigh, SignLow, Inferred, diff --git a/ast/src/groups/group_value.rs b/ast/src/groups/group_value.rs index 489422774e..a7f1408d24 100644 --- a/ast/src/groups/group_value.rs +++ b/ast/src/groups/group_value.rs @@ -26,7 +26,10 @@ use tendril::StrTendril; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum GroupValue { - Single(#[serde(with = "leo_errors::common::tendril_json")] StrTendril, Span), + Single( + #[serde(with = "leo_errors::common::tendril_json")] StrTendril, + #[serde(with = "leo_errors::common::span_json")] Span, + ), Tuple(GroupTuple), } diff --git a/ast/src/statements/assign/assignee.rs b/ast/src/statements/assign/assignee.rs index 4816cb20b4..e63dfae4d8 100644 --- a/ast/src/statements/assign/assignee.rs +++ b/ast/src/statements/assign/assignee.rs @@ -24,7 +24,7 @@ use std::fmt; pub enum AssigneeAccess { ArrayRange(Option, Option), ArrayIndex(Expression), - Tuple(PositiveNumber, Span), + Tuple(PositiveNumber, #[serde(with = "leo_errors::common::span_json")] Span), Member(Identifier), } diff --git a/errors/src/common/mod.rs b/errors/src/common/mod.rs index 9ec9731a6b..a8a9bc4c77 100644 --- a/errors/src/common/mod.rs +++ b/errors/src/common/mod.rs @@ -31,6 +31,11 @@ pub use self::macros::*; pub mod span; pub use self::span::Span; +/// This module contains a custome serialize/deserialize +/// implementation for Span. +pub mod span_json; +pub use self::span_json::*; + /// This module contains information on how to serialize and /// deserialze StrTendril type. pub mod tendril_json; diff --git a/errors/src/common/span_json.rs b/errors/src/common/span_json.rs new file mode 100644 index 0000000000..6627ead7e1 --- /dev/null +++ b/errors/src/common/span_json.rs @@ -0,0 +1,55 @@ +// Copyright (C) 2019-2021 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . +use crate::Span; + +use std::fmt; + +use serde::de::{MapAccess, Visitor}; +use serde::ser::SerializeMap; +use serde::{Deserializer, Serializer}; + +/// The AST contains a few tuple-like enum variants the contain spans +/// #[derive(Serialize, Deserialize)] outputs these fields as anonmyous +/// mappings, which makes them difficult to remove from the JSON AST. +/// This function provides a custom serialization that maps the keyword +/// `span` to the span information. +pub fn serialize(span: &Span, serializer: S) -> Result { + let mut map = serializer.serialize_map(Some(1))?; + map.serialize_entry("span", span)?; + map.end() +} + +/// Custom deserialization to enable removing spans from enums. +pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + deserializer.deserialize_map(SpanMapVisitor) +} + +/// This visitor is used by the deserializer to unwrap mappings +/// and extract span information. +struct SpanMapVisitor; + +impl<'de> Visitor<'de> for SpanMapVisitor { + type Value = Span; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Mapping from `span` keyword to span information") + } + + fn visit_map>(self, mut access: M) -> Result { + let (_, value): (String, Span) = access.next_entry()?.unwrap(); + Ok(value) + } +} diff --git a/parser/tests/serialization/expected_leo_ast.json b/parser/tests/serialization/expected_leo_ast.json index 1c54611b6c..5865517126 100644 --- a/parser/tests/serialization/expected_leo_ast.json +++ b/parser/tests/serialization/expected_leo_ast.json @@ -26,12 +26,14 @@ "U8", "1", { - "line_start": 2, - "line_stop": 2, - "col_start": 12, - "col_stop": 15, - "path": "", - "content": " return 1u8 + 1u8;" + "span" : { + "line_start": 2, + "line_stop": 2, + "col_start": 12, + "col_stop": 15, + "path": "", + "content": " return 1u8 + 1u8;" + } } ] } @@ -42,12 +44,14 @@ "U8", "1", { - "line_start": 2, - "line_stop": 2, - "col_start": 18, - "col_stop": 21, - "path": "", - "content": " return 1u8 + 1u8;" + "span": { + "line_start": 2, + "line_stop": 2, + "col_start": 18, + "col_stop": 21, + "path": "", + "content": " return 1u8 + 1u8;" + } } ] }