Update AST

This commit is contained in:
evan-schott 2024-03-26 14:48:06 -07:00
parent 4a3e89f877
commit bc7e6c3fa2
6 changed files with 194 additions and 7 deletions

View File

@ -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 <https://www.gnu.org/licenses/>.
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<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.program.hash(state);
self.span.hash(state);
}
}
impl Serialize for LocatorExpression {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
// Converts an element that implements Serialize into a string.
fn to_json_string<E: Serialize, Error: serde::ser::Error>(element: &E) -> Result<String, Error> {
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<String, String> = 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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
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<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
// 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<D, Error> {
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<String, String> = 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)
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Type>,
pub value: Box<Type>,
pub program: Symbol,
}
impl fmt::Display for MappingType {