Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion aztec_macros/src/utils/parse_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,17 @@ fn empty_noir_function(noir_function: &mut NoirFunction) {

fn empty_trait_item(trait_item: &mut TraitItem) {
match trait_item {
TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => {
TraitItem::Function {
name,
generics,
parameters,
return_type,
where_clause,
body,
is_unconstrained: _,
visibility: _,
is_comptime: _,
} => {
empty_ident(name);
empty_unresolved_generics(generics);
for (name, typ) in parameters.iter_mut() {
Expand Down
27 changes: 24 additions & 3 deletions compiler/noirc_frontend/src/ast/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::ast::{
use crate::macros_api::SecondaryAttribute;
use crate::node_interner::TraitId;

use super::{Documented, GenericTypeArgs};
use super::{Documented, GenericTypeArgs, ItemVisibility};

/// AST node for trait definitions:
/// `trait name<generics> { ... items ... }`
Expand All @@ -29,6 +29,9 @@ pub struct NoirTrait {
#[derive(Clone, Debug)]
pub enum TraitItem {
Function {
is_unconstrained: bool,
visibility: ItemVisibility,
is_comptime: bool,
name: Ident,
generics: UnresolvedGenerics,
parameters: Vec<(Ident, UnresolvedType)>,
Expand Down Expand Up @@ -146,7 +149,17 @@ impl Display for NoirTrait {
impl Display for TraitItem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => {
TraitItem::Function {
name,
generics,
parameters,
return_type,
where_clause,
body,
is_unconstrained,
visibility,
is_comptime,
} => {
let generics = vecmap(generics, |generic| generic.to_string());
let parameters = vecmap(parameters, |(name, typ)| format!("{name}: {typ}"));
let where_clause = vecmap(where_clause, ToString::to_string);
Expand All @@ -155,9 +168,17 @@ impl Display for TraitItem {
let parameters = parameters.join(", ");
let where_clause = where_clause.join(", ");

let unconstrained = if *is_unconstrained { "unconstrained " } else { "" };
let visibility = if *visibility == ItemVisibility::Private {
"".to_string()
} else {
visibility.to_string()
};
let is_comptime = if *is_comptime { "comptime " } else { "" };

write!(
f,
"fn {name}<{generics}>({parameters}) -> {return_type} where {where_clause}"
"{unconstrained}{visibility}{is_comptime}fn {name}<{generics}>({parameters}) -> {return_type} where {where_clause}"
)?;

if let Some(body) = body {
Expand Down
12 changes: 11 additions & 1 deletion compiler/noirc_frontend/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,17 @@ impl TraitItem {

pub fn accept_children(&self, visitor: &mut impl Visitor) {
match self {
TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => {
TraitItem::Function {
name,
generics,
parameters,
return_type,
where_clause,
body,
is_unconstrained: _,
visibility: _,
is_comptime: _,
} => {
if visitor.visit_trait_item_function(
name,
generics,
Expand Down
12 changes: 9 additions & 3 deletions compiler/noirc_frontend/src/elaborator/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ impl<'context> Elaborator<'context> {
return_type,
where_clause,
body: _,
is_unconstrained,
visibility: _,
is_comptime: _,
} = &item.item
{
self.recover_generics(|this| {
Expand Down Expand Up @@ -134,9 +137,12 @@ impl<'context> Elaborator<'context> {
};

let no_environment = Box::new(Type::Unit);
// TODO: unconstrained
let function_type =
Type::Function(arguments, Box::new(return_type), no_environment, false);
let function_type = Type::Function(
arguments,
Box::new(return_type),
no_environment,
*is_unconstrained,
);

functions.push(TraitFunction {
name: name.clone(),
Expand Down
36 changes: 35 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use crate::{
Kind, QuotedType, ResolvedGeneric, Shared, Type, TypeVariable,
};

use self::builtin_helpers::{eq_item, get_array, get_str, get_u8, hash_item};
use self::builtin_helpers::{eq_item, get_array, get_ctstring, get_str, get_u8, hash_item};
use super::Interpreter;

pub(crate) mod builtin_helpers;
Expand All @@ -60,6 +60,8 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"array_len" => array_len(interner, arguments, location),
"assert_constant" => Ok(Value::Bool(true)),
"as_slice" => as_slice(interner, arguments, location),
"ctstring_eq" => ctstring_eq(arguments, location),
"ctstring_hash" => ctstring_hash(arguments, location),
"expr_as_array" => expr_as_array(interner, arguments, return_type, location),
"expr_as_assert" => expr_as_assert(interner, arguments, return_type, location),
"expr_as_assert_eq" => expr_as_assert_eq(interner, arguments, return_type, location),
Expand Down Expand Up @@ -97,6 +99,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"expr_is_continue" => expr_is_continue(interner, arguments, location),
"expr_resolve" => expr_resolve(self, arguments, location),
"is_unconstrained" => Ok(Value::Bool(true)),
"fmtstr_as_ctstring" => fmtstr_as_ctstring(interner, arguments, location),
"fmtstr_quoted_contents" => fmtstr_quoted_contents(interner, arguments, location),
"fresh_type_variable" => fresh_type_variable(interner),
"function_def_add_attribute" => function_def_add_attribute(self, arguments, location),
Expand Down Expand Up @@ -151,6 +154,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"slice_push_front" => slice_push_front(interner, arguments, location),
"slice_remove" => slice_remove(interner, arguments, location, call_stack),
"str_as_bytes" => str_as_bytes(interner, arguments, location),
"str_as_ctstring" => str_as_ctstring(interner, arguments, location),
"struct_def_add_attribute" => struct_def_add_attribute(interner, arguments, location),
"struct_def_add_generic" => struct_def_add_generic(interner, arguments, location),
"struct_def_as_type" => struct_def_as_type(interner, arguments, location),
Expand Down Expand Up @@ -297,6 +301,17 @@ fn str_as_bytes(
Ok(Value::Array(bytes, byte_array_type))
}

// fn str_as_ctstring(self) -> CtString
fn str_as_ctstring(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let self_argument = check_one_argument(arguments, location)?;
let string = get_str(interner, self_argument)?;
Ok(Value::CtString(string))
}

// fn add_attribute<let N: u32>(self, attribute: str<N>)
fn struct_def_add_attribute(
interner: &mut NodeInterner,
Expand Down Expand Up @@ -1868,6 +1883,17 @@ fn unwrap_expr_value(interner: &NodeInterner, mut expr_value: ExprValue) -> Expr
expr_value
}

// fn fmtstr_as_ctstring(self) -> CtString
fn fmtstr_as_ctstring(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let self_argument = check_one_argument(arguments, location)?;
let (string, _) = get_format_string(interner, self_argument)?;
Ok(Value::CtString(string))
}

// fn quoted_contents(self) -> Quoted
fn fmtstr_quoted_contents(
interner: &NodeInterner,
Expand Down Expand Up @@ -2441,3 +2467,11 @@ pub(crate) fn extract_option_generic_type(typ: Type) -> Type {

generics.pop().expect("Expected Option to have a T generic type")
}

fn ctstring_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
eq_item(arguments, location, get_ctstring)
}

fn ctstring_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
hash_item(arguments, location, get_ctstring)
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ pub(crate) fn get_str(
}
}

pub(crate) fn get_ctstring((value, location): (Value, Location)) -> IResult<Rc<String>> {
match value {
Value::CtString(string) => Ok(string),
value => type_mismatch(value, Type::Quoted(QuotedType::CtString), location),
}
}

pub(crate) fn get_tuple(
interner: &NodeInterner,
(value, location): (Value, Location),
Expand Down
11 changes: 9 additions & 2 deletions compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub enum Value {
U64(u64),
String(Rc<String>),
FormatString(Rc<String>, Type),
CtString(Rc<String>),
Function(FuncId, Type, Rc<TypeBindings>),
Closure(HirLambda, Vec<Value>, Type),
Tuple(Vec<Value>),
Expand Down Expand Up @@ -151,6 +152,7 @@ impl Value {
Value::Expr(_) => Type::Quoted(QuotedType::Expr),
Value::TypedExpr(_) => Type::Quoted(QuotedType::TypedExpr),
Value::UnresolvedType(_) => Type::Quoted(QuotedType::UnresolvedType),
Value::CtString(_) => Type::Quoted(QuotedType::CtString),
})
}

Expand Down Expand Up @@ -202,7 +204,9 @@ impl Value {
Value::U64(value) => {
ExpressionKind::Literal(Literal::Integer((value as u128).into(), false))
}
Value::String(value) => ExpressionKind::Literal(Literal::Str(unwrap_rc(value))),
Value::String(value) | Value::CtString(value) => {
ExpressionKind::Literal(Literal::Str(unwrap_rc(value)))
}
// Format strings are lowered as normal strings since they are already interpolated.
Value::FormatString(value, _) => {
ExpressionKind::Literal(Literal::Str(unwrap_rc(value)))
Expand Down Expand Up @@ -349,7 +353,9 @@ impl Value {
Value::U64(value) => {
HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false))
}
Value::String(value) => HirExpression::Literal(HirLiteral::Str(unwrap_rc(value))),
Value::String(value) | Value::CtString(value) => {
HirExpression::Literal(HirLiteral::Str(unwrap_rc(value)))
}
// Format strings are lowered as normal strings since they are already interpolated.
Value::FormatString(value, _) => {
HirExpression::Literal(HirLiteral::Str(unwrap_rc(value)))
Expand Down Expand Up @@ -589,6 +595,7 @@ impl<'value, 'interner> Display for ValuePrinter<'value, 'interner> {
Value::U32(value) => write!(f, "{value}"),
Value::U64(value) => write!(f, "{value}"),
Value::String(value) => write!(f, "{value}"),
Value::CtString(value) => write!(f, "{value}"),
Value::FormatString(value, _) => write!(f, "{value}"),
Value::Function(..) => write!(f, "(function)"),
Value::Closure(_, _, _) => write!(f, "(closure)"),
Expand Down
7 changes: 5 additions & 2 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,9 @@ impl<'a> ModCollector<'a> {
return_type,
where_clause,
body,
is_unconstrained,
visibility: _,
is_comptime,
} => {
let func_id = context.def_interner.push_empty_fn();
method_ids.insert(name.to_string(), func_id);
Expand All @@ -434,9 +437,9 @@ impl<'a> ModCollector<'a> {
visibility: ItemVisibility::Public,
// TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629
attributes: crate::token::Attributes::empty(),
is_unconstrained: false,
is_unconstrained: *is_unconstrained,
generic_count: generics.len(),
is_comptime: false,
is_comptime: *is_comptime,
name_location: location,
};

Expand Down
2 changes: 2 additions & 0 deletions compiler/noirc_frontend/src/hir_def/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ pub enum QuotedType {
UnresolvedType,
FunctionDefinition,
Module,
CtString,
}

/// A list of TypeVariableIds to bind to a type. Storing the
Expand Down Expand Up @@ -759,6 +760,7 @@ impl std::fmt::Display for QuotedType {
QuotedType::UnresolvedType => write!(f, "UnresolvedType"),
QuotedType::FunctionDefinition => write!(f, "FunctionDefinition"),
QuotedType::Module => write!(f, "Module"),
QuotedType::CtString => write!(f, "CtString"),
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/noirc_frontend/src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ pub enum Keyword {
Continue,
Contract,
Crate,
CtString,
Dep,
Else,
Expr,
Expand Down Expand Up @@ -1039,6 +1040,7 @@ impl fmt::Display for Keyword {
Keyword::Continue => write!(f, "continue"),
Keyword::Contract => write!(f, "contract"),
Keyword::Crate => write!(f, "crate"),
Keyword::CtString => write!(f, "CtString"),
Keyword::Dep => write!(f, "dep"),
Keyword::Else => write!(f, "else"),
Keyword::Expr => write!(f, "Expr"),
Expand Down Expand Up @@ -1098,6 +1100,7 @@ impl Keyword {
"continue" => Keyword::Continue,
"contract" => Keyword::Contract,
"crate" => Keyword::Crate,
"CtString" => Keyword::CtString,
"dep" => Keyword::Dep,
"else" => Keyword::Else,
"Expr" => Keyword::Expr,
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/parser/parser/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser<NoirFunct
/// function_modifiers: 'unconstrained'? (visibility)?
///
/// returns (is_unconstrained, visibility) for whether each keyword was present
fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility, bool)> {
pub(super) fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility, bool)> {
keyword(Keyword::Unconstrained).or_not().then(item_visibility()).then(maybe_comp_time()).map(
|((unconstrained, visibility), comptime)| (unconstrained.is_some(), visibility, comptime),
)
Expand Down
25 changes: 19 additions & 6 deletions compiler/noirc_frontend/src/parser/parser/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use chumsky::prelude::*;

use super::attributes::{attributes, validate_secondary_attributes};
use super::doc_comments::outer_doc_comments;
use super::function::function_return_type;
use super::function::{function_modifiers, function_return_type};
use super::path::path_no_turbofish;
use super::{
block, expression, fresh_statement, function, function_declaration_parameters, let_statement,
Expand Down Expand Up @@ -101,16 +101,29 @@ fn trait_function_declaration() -> impl NoirParser<TraitItem> {
}
});

keyword(Keyword::Fn)
.ignore_then(ident())
function_modifiers()
.then_ignore(keyword(Keyword::Fn))
.then(ident())
.then(function::generics())
.then(parenthesized(function_declaration_parameters()))
.then(function_return_type().map(|(_, typ)| typ))
.then(where_clause())
.then(trait_function_body_or_semicolon_or_error)
.map(|(((((name, generics), parameters), return_type), where_clause), body)| {
TraitItem::Function { name, generics, parameters, return_type, where_clause, body }
})
.map(
|((((((modifiers, name), generics), parameters), return_type), where_clause), body)| {
TraitItem::Function {
name,
generics,
parameters,
return_type,
where_clause,
body,
is_unconstrained: modifiers.0,
visibility: modifiers.1,
is_comptime: modifiers.2,
}
},
)
}

/// trait_type_declaration: 'type' ident generics
Expand Down
7 changes: 7 additions & 0 deletions compiler/noirc_frontend/src/parser/parser/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub(super) fn comptime_type() -> impl NoirParser<UnresolvedType> {
top_level_item_type(),
quoted_type(),
typed_expr_type(),
comptime_string_type(),
))
}

Expand Down Expand Up @@ -166,6 +167,12 @@ fn typed_expr_type() -> impl NoirParser<UnresolvedType> {
.map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::TypedExpr).with_span(span))
}

/// This is the `CtString` type for dynamically-sized compile-time strings
fn comptime_string_type() -> impl NoirParser<UnresolvedType> {
keyword(Keyword::CtString)
.map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::CtString).with_span(span))
}

/// This is the type of an already resolved type.
/// The only way this can appear in the token input is if an already resolved `Type` object
/// was spliced into a macro's token stream via the `$` operator.
Expand Down
Loading