Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: turbofish operator on path segments #5603

Merged
merged 11 commits into from
Jul 25, 2024
7 changes: 4 additions & 3 deletions aztec_macros/src/transforms/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use crate::{
ast_utils::{
assignment, assignment_with_type, call, cast, expression, ident, ident_path,
index_array, make_eq, make_statement, make_type, method_call, mutable_assignment,
mutable_reference, path, return_type, variable, variable_ident, variable_path,
mutable_reference, path, path_segment, return_type, variable, variable_ident,
variable_path,
},
errors::AztecMacroError,
},
Expand Down Expand Up @@ -722,8 +723,8 @@ fn add_struct_to_hasher(identifier: &Ident, hasher_name: &str) -> Statement {
fn str_to_bytes(identifier: &Ident) -> (Statement, Ident) {
// let identifier_as_bytes = identifier.as_bytes();
let var = variable_ident(identifier.clone());
let contents = if let ExpressionKind::Variable(p, _) = &var.kind {
p.segments.first().cloned().unwrap_or_else(|| panic!("No segments")).0.contents
let contents = if let ExpressionKind::Variable(p) = &var.kind {
p.first_segment().0.contents
} else {
panic!("Unexpected identifier type")
};
Expand Down
1 change: 1 addition & 0 deletions aztec_macros/src/transforms/note_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
utils::{
ast_utils::{
check_trait_method_implemented, ident, ident_path, is_custom_attribute, make_type,
path_segment,
},
errors::AztecMacroError,
hir_utils::{fetch_notes, get_contract_module_data, inject_global},
Expand Down
10 changes: 5 additions & 5 deletions aztec_macros/src/transforms/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
utils::{
ast_utils::{
call, expression, ident, ident_path, is_custom_attribute, lambda, make_statement,
make_type, pattern, return_type, variable, variable_path,
make_type, path_segment, pattern, return_type, variable, variable_path,
},
errors::AztecMacroError,
hir_utils::{
Expand Down Expand Up @@ -59,7 +59,7 @@
vec![],
false,
)));
match path.segments.last().unwrap().0.contents.as_str() {
match path.last_segment().0.contents.as_str() {
"Map" => inject_context_in_storage_field(&mut generics[1]),
_ => Ok(()),
}
Expand Down Expand Up @@ -107,7 +107,7 @@
) -> bool {
module.impls.iter().any(|r#impl| match &r#impl.object_type.typ {
UnresolvedTypeData::Named(path, _, _) => {
path.segments.last().is_some_and(|segment| segment.0.contents == *storage_struct_name)
path.last_segment().0.contents == *storage_struct_name
}
_ => false,
})
Expand All @@ -123,8 +123,8 @@
match typ {
UnresolvedTypeData::Named(path, generics, _) => {
let mut new_path = path.clone().to_owned();
new_path.segments.push(ident("new"));
match path.segments.last().unwrap().0.contents.as_str() {
new_path.segments.push(path_segment("new"));
match path.last_segment().0.contents.as_str() {
"Map" => Ok(call(
variable_path(new_path),
vec![
Expand Down Expand Up @@ -173,7 +173,7 @@
///
/// To:
///
/// impl<Context> Storage<Contex> {

Check warning on line 176 in aztec_macros/src/transforms/storage.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Contex)
/// fn init(context: Context) -> Self {
/// Storage {
/// a_map: Map::new(context, 0, |context, slot| {
Expand Down
18 changes: 11 additions & 7 deletions aztec_macros/src/utils/ast_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use noirc_errors::{Span, Spanned};
use noirc_frontend::ast::{
BinaryOpKind, CallExpression, CastExpression, Expression, ExpressionKind, FunctionReturnType,
Ident, IndexExpression, InfixExpression, Lambda, LetStatement, MemberAccessExpression,
MethodCallExpression, NoirTraitImpl, Path, Pattern, PrefixExpression, Statement, StatementKind,
TraitImplItem, UnaryOp, UnresolvedType, UnresolvedTypeData,
MethodCallExpression, NoirTraitImpl, Path, PathSegment, Pattern, PrefixExpression, Statement,
StatementKind, TraitImplItem, UnaryOp, UnresolvedType, UnresolvedTypeData,
};
use noirc_frontend::token::SecondaryAttribute;

Expand All @@ -18,6 +18,10 @@ pub fn ident_path(name: &str) -> Path {
Path::from_ident(ident(name))
}

pub fn path_segment(name: &str) -> PathSegment {
PathSegment::from(ident(name))
}

pub fn path(ident: Ident) -> Path {
Path::from_ident(ident)
}
Expand All @@ -27,15 +31,15 @@ pub fn expression(kind: ExpressionKind) -> Expression {
}

pub fn variable(name: &str) -> Expression {
expression(ExpressionKind::Variable(ident_path(name), None))
expression(ExpressionKind::Variable(ident_path(name)))
}

pub fn variable_ident(identifier: Ident) -> Expression {
expression(ExpressionKind::Variable(path(identifier), None))
expression(ExpressionKind::Variable(path(identifier)))
}

pub fn variable_path(path: Path) -> Expression {
expression(ExpressionKind::Variable(path, None))
expression(ExpressionKind::Variable(path))
}

pub fn method_call(
Expand Down Expand Up @@ -149,7 +153,7 @@ macro_rules! chained_path {
{
let mut base_path = ident_path($base);
$(
base_path.segments.push(ident($tail));
base_path.segments.push(path_segment($tail));
)*
base_path
}
Expand All @@ -163,7 +167,7 @@ macro_rules! chained_dep {
let mut base_path = ident_path($base);
base_path.kind = PathKind::Plain;
$(
base_path.segments.push(ident($tail));
base_path.segments.push(path_segment($tail));
)*
base_path
}
Expand Down
15 changes: 3 additions & 12 deletions compiler/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ pub enum ExpressionKind {
Cast(Box<CastExpression>),
Infix(Box<InfixExpression>),
If(Box<IfExpression>),
// The optional vec here is the optional list of generics
// provided by the turbofish operator, if used
Variable(Path, Option<Vec<UnresolvedType>>),
Variable(Path),
Tuple(Vec<Expression>),
Lambda(Box<Lambda>),
Parenthesized(Box<Expression>),
Expand Down Expand Up @@ -118,7 +116,7 @@ impl From<Ident> for UnresolvedGeneric {
impl ExpressionKind {
pub fn into_path(self) -> Option<Path> {
match self {
ExpressionKind::Variable(path, _) => Some(path),
ExpressionKind::Variable(path) => Some(path),
_ => None,
}
}
Expand Down Expand Up @@ -583,14 +581,7 @@ impl Display for ExpressionKind {
Cast(cast) => cast.fmt(f),
Infix(infix) => infix.fmt(f),
If(if_expr) => if_expr.fmt(f),
Variable(path, generics) => {
if let Some(generics) = generics {
let generics = vecmap(generics, ToString::to_string);
write!(f, "{path}::<{}>", generics.join(", "))
} else {
path.fmt(f)
}
}
Variable(path) => path.fmt(f),
Constructor(constructor) => constructor.fmt(f),
MemberAccess(access) => access.fmt(f),
Tuple(elements) => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
/*env:*/ Box<UnresolvedType>,
),

// The type of quoted code for metaprogramming

Check warning on line 120 in compiler/noirc_frontend/src/ast/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (metaprogramming)
Quoted(crate::QuotedType),

/// An already resolved type. These can only be parsed if they were present in the token stream
Expand Down Expand Up @@ -324,7 +324,7 @@
Some(int) => Ok(UnresolvedTypeExpression::Constant(int, expr.span)),
None => Err(expr),
},
ExpressionKind::Variable(path, _) => Ok(UnresolvedTypeExpression::Variable(path)),
ExpressionKind::Variable(path) => Ok(UnresolvedTypeExpression::Variable(path)),
ExpressionKind::Prefix(prefix) if prefix.operator == UnaryOp::Minus => {
let lhs = Box::new(UnresolvedTypeExpression::Constant(0, expr.span));
let rhs = Box::new(UnresolvedTypeExpression::from_expr_helper(prefix.rhs)?);
Expand Down
81 changes: 57 additions & 24 deletions compiler/noirc_frontend/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,11 @@ impl From<Ident> for Expression {
fn from(i: Ident) -> Expression {
Expression {
span: i.0.span(),
kind: ExpressionKind::Variable(
Path { span: i.span(), segments: vec![i], kind: PathKind::Plain },
None,
),
kind: ExpressionKind::Variable(Path {
span: i.span(),
segments: vec![PathSegment::from(i)],
kind: PathKind::Plain,
}),
}
}
}
Expand Down Expand Up @@ -362,18 +363,18 @@ impl UseTree {
// it would most likely cause further errors during name resolution
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct Path {
pub segments: Vec<Ident>,
pub segments: Vec<PathSegment>,
pub kind: PathKind,
pub span: Span,
}

impl Path {
pub fn pop(&mut self) -> Ident {
self.segments.pop().unwrap()
self.segments.pop().unwrap().ident
}

fn join(mut self, ident: Ident) -> Path {
self.segments.push(ident);
self.segments.push(PathSegment::from(ident));
self
}

Expand All @@ -384,16 +385,21 @@ impl Path {
}

pub fn from_ident(name: Ident) -> Path {
Path { span: name.span(), segments: vec![name], kind: PathKind::Plain }
Path { span: name.span(), segments: vec![PathSegment::from(name)], kind: PathKind::Plain }
}

pub fn span(&self) -> Span {
self.span
}

pub fn first_segment(&self) -> Ident {
assert!(!self.segments.is_empty());
self.segments.first().unwrap().ident.clone()
}

pub fn last_segment(&self) -> Ident {
assert!(!self.segments.is_empty());
self.segments.last().unwrap().clone()
self.segments.last().unwrap().ident.clone()
}

pub fn is_ident(&self) -> bool {
Expand All @@ -404,14 +410,14 @@ impl Path {
if !self.is_ident() {
return None;
}
self.segments.first()
self.segments.first().map(|segment| &segment.ident)
}

pub fn to_ident(&self) -> Option<Ident> {
if !self.is_ident() {
return None;
}
self.segments.first().cloned()
self.segments.first().cloned().map(|segment| segment.ident)
}

pub fn as_string(&self) -> String {
Expand All @@ -421,19 +427,44 @@ impl Path {
match segments.next() {
None => panic!("empty segment"),
Some(seg) => {
string.push_str(&seg.0.contents);
string.push_str(&seg.ident.0.contents);
}
}

for segment in segments {
string.push_str("::");
string.push_str(&segment.0.contents);
string.push_str(&segment.ident.0.contents);
}

string
}
}

#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct PathSegment {
pub ident: Ident,
pub generics: Option<Vec<UnresolvedType>>,
}

impl From<Ident> for PathSegment {
fn from(ident: Ident) -> PathSegment {
PathSegment { ident, generics: None }
}
}

impl Display for PathSegment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.ident.fmt(f)?;

if let Some(generics) = &self.generics {
let generics = vecmap(generics, ToString::to_string);
write!(f, "::<{}>", generics.join(", "))?;
}

Ok(())
}
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct LetStatement {
pub pattern: Pattern,
Expand Down Expand Up @@ -517,7 +548,7 @@ impl Recoverable for Pattern {
impl LValue {
fn as_expression(&self) -> Expression {
let kind = match self {
LValue::Ident(ident) => ExpressionKind::Variable(Path::from_ident(ident.clone()), None),
LValue::Ident(ident) => ExpressionKind::Variable(Path::from_ident(ident.clone())),
LValue::MemberAccess { object, field_name, span: _ } => {
ExpressionKind::MemberAccess(Box::new(MemberAccessExpression {
lhs: object.as_expression(),
Expand Down Expand Up @@ -606,11 +637,12 @@ impl ForRange {
};

// array.len()
let segments = vec![array_ident];
let array_ident = ExpressionKind::Variable(
Path { segments, kind: PathKind::Plain, span: array_span },
None,
);
let segments = vec![PathSegment::from(array_ident)];
let array_ident = ExpressionKind::Variable(Path {
segments,
kind: PathKind::Plain,
span: array_span,
});

let end_range = ExpressionKind::MethodCall(Box::new(MethodCallExpression {
object: Expression::new(array_ident.clone(), array_span),
Expand All @@ -626,11 +658,12 @@ impl ForRange {
let fresh_identifier = Ident::new(index_name.clone(), array_span);

// array[i]
let segments = vec![Ident::new(index_name, array_span)];
let index_ident = ExpressionKind::Variable(
Path { segments, kind: PathKind::Plain, span: array_span },
None,
);
let segments = vec![PathSegment::from(Ident::new(index_name, array_span))];
let index_ident = ExpressionKind::Variable(Path {
segments,
kind: PathKind::Plain,
span: array_span,
});

let loop_element = ExpressionKind::Index(Box::new(IndexExpression {
collection: Expression::new(array_ident, array_span),
Expand Down
Loading
Loading