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 {