From bc7e6c3fa225c5d59f90365629fe0947deb83d87 Mon Sep 17 00:00:00 2001 From: evan-schott <53463459+evan-schott@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:48:06 -0700 Subject: [PATCH] Update AST --- compiler/ast/src/expressions/locator.rs | 159 +++++++++++++++++++++++ compiler/ast/src/expressions/mod.rs | 24 +++- compiler/ast/src/passes/consumer.rs | 3 + compiler/ast/src/passes/reconstructor.rs | 8 ++ compiler/ast/src/passes/visitor.rs | 5 + compiler/ast/src/types/mapping.rs | 2 + 6 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 compiler/ast/src/expressions/locator.rs diff --git a/compiler/ast/src/expressions/locator.rs b/compiler/ast/src/expressions/locator.rs new file mode 100644 index 0000000000..89a5c88b90 --- /dev/null +++ b/compiler/ast/src/expressions/locator.rs @@ -0,0 +1,159 @@ +// Copyright (C) 2019-2023 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 leo_errors::Result; +use leo_span::{Span, Symbol}; + +use crate::{simple_node_impl, Node, NodeID}; +use serde::{ + de::{ + Visitor, + {self}, + }, + Deserialize, + Deserializer, + Serialize, + Serializer, +}; +use std::{ + collections::BTreeMap, + fmt, + hash::{Hash, Hasher}, +}; + +/// A locator that references an external resource. +#[derive(Clone, Copy)] +pub struct LocatorExpression { + /// The program that the resource is in. + pub program: Symbol, + /// The name of the resource. + pub name: Symbol, + /// A span indicating where the locator occurred in the source. + pub span: Span, + /// The ID of the node. + pub id: NodeID, +} + +simple_node_impl!(LocatorExpression); + +impl LocatorExpression { + /// Constructs a new Locator with `name`, `program` and `id` and a default span. + pub fn new(program: Symbol, name: Symbol, id: NodeID) -> Self { + Self { program, name, span: Span::default(), id } + } + + /// Check if the Locator name and program matches the other name and program. + pub fn matches(&self, other: &Self) -> bool { + self.name == other.name && self.program == other.program + } +} + +impl fmt::Display for LocatorExpression { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}.aleo/{}", self.program, self.name) + } +} +impl fmt::Debug for LocatorExpression { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}.aleo/{}", self.program, self.name) + } +} + +impl PartialEq for LocatorExpression { + fn eq(&self, other: &Self) -> bool { + self.name == other.name && self.program == other.program && self.span == other.span + } +} + +impl Eq for LocatorExpression {} + +impl Hash for LocatorExpression { + fn hash(&self, state: &mut H) { + self.name.hash(state); + self.program.hash(state); + self.span.hash(state); + } +} + +impl Serialize for LocatorExpression { + fn serialize(&self, serializer: S) -> Result { + // Converts an element that implements Serialize into a string. + fn to_json_string(element: &E) -> Result { + serde_json::to_string(&element).map_err(|e| Error::custom(e.to_string())) + } + + // Load the struct elements into a BTreeMap (to preserve serialized ordering of keys). + let mut key: BTreeMap = BTreeMap::new(); + key.insert("name".to_string(), self.name.to_string()); + key.insert("program".to_string(), self.program.to_string()); + key.insert("span".to_string(), to_json_string(&self.span)?); + key.insert("id".to_string(), to_json_string(&self.id)?); + + // Convert the serialized object into a string for use as a key. + serializer.serialize_str(&to_json_string(&key)?) + } +} + +impl<'de> Deserialize<'de> for LocatorExpression { + fn deserialize>(deserializer: D) -> Result { + struct LocatorVisitor; + + impl Visitor<'_> for LocatorVisitor { + type Value = LocatorExpression; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string encoding the ast Identifier struct") + } + + /// Implementation for recovering a string that serializes Locator. + fn visit_str(self, value: &str) -> Result { + // Converts a serialized string into an element that implements Deserialize. + fn to_json_string<'a, D: Deserialize<'a>, Error: serde::de::Error>( + serialized: &'a str, + ) -> Result { + serde_json::from_str::<'a>(serialized).map_err(|e| Error::custom(e.to_string())) + } + + // Convert the serialized string into a BTreeMap to recover Locator. + let key: BTreeMap = to_json_string(value)?; + + let name = match key.get("name") { + Some(name) => Symbol::intern(name), + None => return Err(E::custom("missing 'name' in serialized Identifier struct")), + }; + + let program = match key.get("program") { + Some(program) => Symbol::intern(program), + None => return Err(E::custom("missing 'program' in serialized Identifier struct")), + }; + + let span: Span = match key.get("span") { + Some(span) => to_json_string(span)?, + None => return Err(E::custom("missing 'span' in serialized Identifier struct")), + }; + + let id: NodeID = match key.get("id") { + Some(id) => to_json_string(id)?, + None => return Err(E::custom("missing 'id' in serialized Identifier struct")), + }; + + Ok(LocatorExpression { program, name, span, id }) + } + } + + deserializer.deserialize_str(LocatorVisitor) + } +} diff --git a/compiler/ast/src/expressions/mod.rs b/compiler/ast/src/expressions/mod.rs index 1d4cb40880..c590740bad 100644 --- a/compiler/ast/src/expressions/mod.rs +++ b/compiler/ast/src/expressions/mod.rs @@ -56,6 +56,9 @@ pub use unit::*; mod literal; pub use literal::*; +pub mod locator; +pub use locator::*; + /// Expression that evaluates to a value. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum Expression { @@ -69,8 +72,6 @@ pub enum Expression { Call(CallExpression), /// A cast expression, e.g., `42u32 as u8`. Cast(CastExpression), - /// An expression constructing a struct like `Foo { bar: 42, baz }`. - Struct(StructExpression), /// An expression of type "error". /// Will result in a compile error eventually. Err(ErrExpression), @@ -78,6 +79,10 @@ pub enum Expression { Identifier(Identifier), /// A literal expression. Literal(Literal), + /// A locator expression, e.g., `hello.aleo/foo`. + Locator(LocatorExpression), + /// An expression constructing a struct like `Foo { bar: 42, baz }`. + Struct(StructExpression), /// A ternary conditional expression `cond ? if_expr : else_expr`. Ternary(TernaryExpression), /// A tuple expression e.g., `(foo, 42, true)`. @@ -97,10 +102,11 @@ impl Node for Expression { Binary(n) => n.span(), Call(n) => n.span(), Cast(n) => n.span(), - Struct(n) => n.span(), Err(n) => n.span(), Identifier(n) => n.span(), Literal(n) => n.span(), + Locator(n) => n.span(), + Struct(n) => n.span(), Ternary(n) => n.span(), Tuple(n) => n.span(), Unary(n) => n.span(), @@ -116,10 +122,11 @@ impl Node for Expression { Binary(n) => n.set_span(span), Call(n) => n.set_span(span), Cast(n) => n.set_span(span), - Struct(n) => n.set_span(span), Identifier(n) => n.set_span(span), Literal(n) => n.set_span(span), + Locator(n) => n.set_span(span), Err(n) => n.set_span(span), + Struct(n) => n.set_span(span), Ternary(n) => n.set_span(span), Tuple(n) => n.set_span(span), Unary(n) => n.set_span(span), @@ -135,10 +142,11 @@ impl Node for Expression { Binary(n) => n.id(), Call(n) => n.id(), Cast(n) => n.id(), - Struct(n) => n.id(), Identifier(n) => n.id(), Literal(n) => n.id(), + Locator(n) => n.id(), Err(n) => n.id(), + Struct(n) => n.id(), Ternary(n) => n.id(), Tuple(n) => n.id(), Unary(n) => n.id(), @@ -154,10 +162,11 @@ impl Node for Expression { Binary(n) => n.set_id(id), Call(n) => n.set_id(id), Cast(n) => n.set_id(id), - Struct(n) => n.set_id(id), Identifier(n) => n.set_id(id), Literal(n) => n.set_id(id), + Locator(n) => n.set_id(id), Err(n) => n.set_id(id), + Struct(n) => n.set_id(id), Ternary(n) => n.set_id(id), Tuple(n) => n.set_id(id), Unary(n) => n.set_id(id), @@ -175,10 +184,11 @@ impl fmt::Display for Expression { Binary(n) => n.fmt(f), Call(n) => n.fmt(f), Cast(n) => n.fmt(f), - Struct(n) => n.fmt(f), Err(n) => n.fmt(f), Identifier(n) => n.fmt(f), Literal(n) => n.fmt(f), + Locator(n) => n.fmt(f), + Struct(n) => n.fmt(f), Ternary(n) => n.fmt(f), Tuple(n) => n.fmt(f), Unary(n) => n.fmt(f), diff --git a/compiler/ast/src/passes/consumer.rs b/compiler/ast/src/passes/consumer.rs index e44813a626..8987545894 100644 --- a/compiler/ast/src/passes/consumer.rs +++ b/compiler/ast/src/passes/consumer.rs @@ -34,6 +34,7 @@ pub trait ExpressionConsumer { Expression::Err(err) => self.consume_err(err), Expression::Identifier(identifier) => self.consume_identifier(identifier), Expression::Literal(value) => self.consume_literal(value), + Expression::Locator(locator) => self.consume_locator(locator), Expression::Ternary(ternary) => self.consume_ternary(ternary), Expression::Tuple(tuple) => self.consume_tuple(tuple), Expression::Unary(unary) => self.consume_unary(unary), @@ -60,6 +61,8 @@ pub trait ExpressionConsumer { fn consume_identifier(&mut self, _input: Identifier) -> Self::Output; fn consume_literal(&mut self, _input: Literal) -> Self::Output; + + fn consume_locator(&mut self, _input: LocatorExpression) -> Self::Output; fn consume_ternary(&mut self, _input: TernaryExpression) -> Self::Output; diff --git a/compiler/ast/src/passes/reconstructor.rs b/compiler/ast/src/passes/reconstructor.rs index 12aa3631d4..23b4de9528 100644 --- a/compiler/ast/src/passes/reconstructor.rs +++ b/compiler/ast/src/passes/reconstructor.rs @@ -35,6 +35,7 @@ pub trait ExpressionReconstructor { Expression::Err(err) => self.reconstruct_err(err), Expression::Identifier(identifier) => self.reconstruct_identifier(identifier), Expression::Literal(value) => self.reconstruct_literal(value), + Expression::Locator(locator) => self.reconstruct_locator(locator), Expression::Ternary(ternary) => self.reconstruct_ternary(ternary), Expression::Tuple(tuple) => self.reconstruct_tuple(tuple), Expression::Unary(unary) => self.reconstruct_unary(unary), @@ -197,6 +198,13 @@ pub trait ExpressionReconstructor { fn reconstruct_literal(&mut self, input: Literal) -> (Expression, Self::AdditionalOutput) { (Expression::Literal(input), Default::default()) } + + fn reconstruct_locator(&mut self, input: LocatorExpression) -> (Expression, Self::AdditionalOutput) { + ( + Expression::Locator(input), + Default::default(), + ) + } fn reconstruct_ternary(&mut self, input: TernaryExpression) -> (Expression, Self::AdditionalOutput) { ( diff --git a/compiler/ast/src/passes/visitor.rs b/compiler/ast/src/passes/visitor.rs index f7fba70ece..dc27dc943c 100644 --- a/compiler/ast/src/passes/visitor.rs +++ b/compiler/ast/src/passes/visitor.rs @@ -36,6 +36,7 @@ pub trait ExpressionVisitor<'a> { Expression::Err(err) => self.visit_err(err, additional), Expression::Identifier(identifier) => self.visit_identifier(identifier, additional), Expression::Literal(literal) => self.visit_literal(literal, additional), + Expression::Locator(locator) => self.visit_locator(locator, additional), Expression::Ternary(ternary) => self.visit_ternary(ternary, additional), Expression::Tuple(tuple) => self.visit_tuple(tuple, additional), Expression::Unary(unary) => self.visit_unary(unary, additional), @@ -106,6 +107,10 @@ pub trait ExpressionVisitor<'a> { fn visit_literal(&mut self, _input: &'a Literal, _additional: &Self::AdditionalInput) -> Self::Output { Default::default() } + + fn visit_locator(&mut self, input: &'a LocatorExpression, additional: &Self::AdditionalInput) -> Self::Output { + Default::default() + } fn visit_ternary(&mut self, input: &'a TernaryExpression, additional: &Self::AdditionalInput) -> Self::Output { self.visit_expression(&input.condition, additional); diff --git a/compiler/ast/src/types/mapping.rs b/compiler/ast/src/types/mapping.rs index 46270a5df5..06439f89fd 100644 --- a/compiler/ast/src/types/mapping.rs +++ b/compiler/ast/src/types/mapping.rs @@ -18,12 +18,14 @@ use crate::Type; use serde::{Deserialize, Serialize}; use std::fmt; +use leo_span::Symbol; /// A mapping type of a key and value type. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct MappingType { pub key: Box, pub value: Box, + pub program: Symbol, } impl fmt::Display for MappingType {