Skip to content

Commit 8c583bf

Browse files
authored
Merge d8c1d38 into 114903d
2 parents 114903d + d8c1d38 commit 8c583bf

File tree

11 files changed

+98
-68
lines changed

11 files changed

+98
-68
lines changed

compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ fn struct_def_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResu
441441
eq_item(arguments, location, get_struct)
442442
}
443443

444-
// fn has_named_attribute(self, name: Quoted) -> bool
444+
// fn has_named_attribute<let N: u32>(self, name: str<N>) -> bool {}
445445
fn struct_def_has_named_attribute(
446446
interner: &NodeInterner,
447447
arguments: Vec<(Value, Location)>,
@@ -450,14 +450,9 @@ fn struct_def_has_named_attribute(
450450
let (self_argument, name) = check_two_arguments(arguments, location)?;
451451
let struct_id = get_struct(self_argument)?;
452452

453-
let name = get_quoted(name)?;
454-
let name = name.iter().map(|token| token.to_string()).collect::<Vec<_>>().join("");
453+
let name = get_str(interner, name)?;
455454

456-
let attributes = interner.struct_attributes(&struct_id);
457-
let attributes = attributes.iter().filter_map(|attribute| attribute.as_custom());
458-
let attributes = attributes.map(|attribute| &attribute.contents);
459-
460-
Ok(Value::Bool(has_named_attribute(&name, attributes, location)))
455+
Ok(Value::Bool(has_named_attribute(&name, interner.struct_attributes(&struct_id))))
461456
}
462457

463458
/// fn fields(self) -> [(Quoted, Type)]
@@ -1957,23 +1952,25 @@ fn function_def_body(
19571952
}
19581953
}
19591954

1960-
// fn has_named_attribute(self, name: Quoted) -> bool
1955+
// fn has_named_attribute<let N: u32>(self, name: str<N>) -> bool {}
19611956
fn function_def_has_named_attribute(
19621957
interner: &NodeInterner,
19631958
arguments: Vec<(Value, Location)>,
19641959
location: Location,
19651960
) -> IResult<Value> {
19661961
let (self_argument, name) = check_two_arguments(arguments, location)?;
19671962
let func_id = get_function_def(self_argument)?;
1968-
let func_meta = interner.function_meta(&func_id);
19691963

1970-
let name = get_quoted(name)?;
1971-
let name = name.iter().map(|token| token.to_string()).collect::<Vec<_>>().join("");
1964+
let name = &*get_str(interner, name)?;
19721965

1973-
let attributes = &func_meta.custom_attributes;
1974-
let attributes = attributes.iter().map(|attribute| &attribute.contents);
1966+
let modifiers = interner.function_modifiers(&func_id);
1967+
if let Some(attribute) = &modifiers.attributes.function {
1968+
if name == attribute.name() {
1969+
return Ok(Value::Bool(true));
1970+
}
1971+
}
19751972

1976-
Ok(Value::Bool(has_named_attribute(&name, attributes, location)))
1973+
Ok(Value::Bool(has_named_attribute(name, &modifiers.attributes.secondary)))
19771974
}
19781975

19791976
fn function_def_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
@@ -2306,7 +2303,7 @@ fn module_structs(
23062303
Ok(Value::Slice(struct_ids, slice_type))
23072304
}
23082305

2309-
// fn has_named_attribute(self, name: Quoted) -> bool
2306+
// fn has_named_attribute<let N: u32>(self, name: str<N>) -> bool {}
23102307
fn module_has_named_attribute(
23112308
interpreter: &Interpreter,
23122309
arguments: Vec<(Value, Location)>,
@@ -2316,12 +2313,9 @@ fn module_has_named_attribute(
23162313
let module_id = get_module(self_argument)?;
23172314
let module_data = interpreter.elaborator.get_module(module_id);
23182315

2319-
let name = get_quoted(name)?;
2320-
let name = name.iter().map(|token| token.to_string()).collect::<Vec<_>>().join("");
2321-
2322-
let attributes = module_data.outer_attributes.iter().chain(&module_data.inner_attributes);
2316+
let name = get_str(interpreter.elaborator.interner, name)?;
23232317

2324-
Ok(Value::Bool(has_named_attribute(&name, attributes, location)))
2318+
Ok(Value::Bool(has_named_attribute(&name, &module_data.attributes)))
23252319
}
23262320

23272321
// fn is_contract(self) -> bool

compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs

+6-18
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::{
99
BlockExpression, ExpressionKind, IntegerBitSize, LValue, Pattern, Signedness,
1010
StatementKind, UnresolvedTypeData,
1111
},
12-
elaborator::Elaborator,
1312
hir::{
1413
comptime::{
1514
errors::IResult,
@@ -26,7 +25,7 @@ use crate::{
2625
macros_api::{NodeInterner, StructId},
2726
node_interner::{FuncId, TraitId, TraitImplId},
2827
parser::NoirParser,
29-
token::{Token, Tokens},
28+
token::{SecondaryAttribute, Token, Tokens},
3029
QuotedType, Type,
3130
};
3231

@@ -450,23 +449,12 @@ pub(super) fn block_expression_to_value(block_expr: BlockExpression) -> Value {
450449
Value::Slice(statements, typ)
451450
}
452451

453-
pub(super) fn has_named_attribute<'a>(
454-
name: &'a str,
455-
attributes: impl Iterator<Item = &'a String>,
456-
location: Location,
457-
) -> bool {
452+
pub(super) fn has_named_attribute(name: &str, attributes: &[SecondaryAttribute]) -> bool {
458453
for attribute in attributes {
459-
let parse_result = Elaborator::parse_attribute(attribute, location);
460-
let Ok(Some((function, _arguments))) = parse_result else {
461-
continue;
462-
};
463-
464-
let ExpressionKind::Variable(path) = function.kind else {
465-
continue;
466-
};
467-
468-
if path.last_name() == name {
469-
return true;
454+
if let Some(attribute_name) = attribute.name() {
455+
if name == attribute_name {
456+
return true;
457+
}
470458
}
471459
}
472460

compiler/noirc_frontend/src/hir/def_map/module_data.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ pub struct ModuleData {
2626
/// True if this module is a `contract Foo { ... }` module containing contract functions
2727
pub is_contract: bool,
2828

29-
pub outer_attributes: Vec<String>,
30-
pub inner_attributes: Vec<String>,
29+
pub attributes: Vec<SecondaryAttribute>,
3130
}
3231

3332
impl ModuleData {
@@ -38,11 +37,8 @@ impl ModuleData {
3837
inner_attributes: Vec<SecondaryAttribute>,
3938
is_contract: bool,
4039
) -> ModuleData {
41-
let outer_attributes = outer_attributes.iter().filter_map(|attr| attr.as_custom());
42-
let outer_attributes = outer_attributes.map(|attr| attr.contents.to_string()).collect();
43-
44-
let inner_attributes = inner_attributes.iter().filter_map(|attr| attr.as_custom());
45-
let inner_attributes = inner_attributes.map(|attr| attr.contents.to_string()).collect();
40+
let mut attributes = outer_attributes;
41+
attributes.extend(inner_attributes);
4642

4743
ModuleData {
4844
parent,
@@ -51,8 +47,7 @@ impl ModuleData {
5147
definitions: ItemScope::default(),
5248
location,
5349
is_contract,
54-
outer_attributes,
55-
inner_attributes,
50+
attributes,
5651
}
5752
}
5853

compiler/noirc_frontend/src/lexer/token.rs

+49-9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use crate::{
1010
},
1111
};
1212

13+
use super::Lexer;
14+
1315
/// Represents a token in noir's grammar - a word, number,
1416
/// or symbol that can be used in noir's syntax. This is the
1517
/// smallest unit of grammar. A parser may (will) decide to parse
@@ -868,6 +870,18 @@ impl FunctionAttribute {
868870
pub fn is_no_predicates(&self) -> bool {
869871
matches!(self, FunctionAttribute::NoPredicates)
870872
}
873+
874+
pub fn name(&self) -> &'static str {
875+
match self {
876+
FunctionAttribute::Foreign(_) => "foreign",
877+
FunctionAttribute::Builtin(_) => "builtin",
878+
FunctionAttribute::Oracle(_) => "oracle",
879+
FunctionAttribute::Test(_) => "test",
880+
FunctionAttribute::Recursive => "recursive",
881+
FunctionAttribute::Fold => "fold",
882+
FunctionAttribute::NoPredicates => "no_predicates",
883+
}
884+
}
871885
}
872886

873887
impl fmt::Display for FunctionAttribute {
@@ -903,15 +917,6 @@ pub enum SecondaryAttribute {
903917
Varargs,
904918
}
905919

906-
#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)]
907-
pub struct CustomAtrribute {
908-
pub contents: String,
909-
// The span of the entire attribute, including leading `#[` and trailing `]`
910-
pub span: Span,
911-
// The span for the attribute contents (what's inside `#[...]`)
912-
pub contents_span: Span,
913-
}
914-
915920
impl SecondaryAttribute {
916921
pub(crate) fn as_custom(&self) -> Option<&CustomAtrribute> {
917922
if let Self::Custom(attribute) = self {
@@ -920,6 +925,20 @@ impl SecondaryAttribute {
920925
None
921926
}
922927
}
928+
929+
pub(crate) fn name(&self) -> Option<String> {
930+
match self {
931+
SecondaryAttribute::Deprecated(_) => Some("deprecated".to_string()),
932+
SecondaryAttribute::ContractLibraryMethod => {
933+
Some("contract_library_method".to_string())
934+
}
935+
SecondaryAttribute::Export => Some("export".to_string()),
936+
SecondaryAttribute::Field(_) => Some("field".to_string()),
937+
SecondaryAttribute::Custom(custom) => custom.name(),
938+
SecondaryAttribute::Abi(_) => Some("abi".to_string()),
939+
SecondaryAttribute::Varargs => Some("varargs".to_string()),
940+
}
941+
}
923942
}
924943

925944
impl fmt::Display for SecondaryAttribute {
@@ -939,6 +958,27 @@ impl fmt::Display for SecondaryAttribute {
939958
}
940959
}
941960

961+
#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)]
962+
pub struct CustomAtrribute {
963+
pub contents: String,
964+
// The span of the entire attribute, including leading `#[` and trailing `]`
965+
pub span: Span,
966+
// The span for the attribute contents (what's inside `#[...]`)
967+
pub contents_span: Span,
968+
}
969+
970+
impl CustomAtrribute {
971+
fn name(&self) -> Option<String> {
972+
let mut lexer = Lexer::new(&self.contents);
973+
let token = lexer.next()?.ok()?;
974+
if let Token::Ident(ident) = token.into_token() {
975+
Some(ident)
976+
} else {
977+
None
978+
}
979+
}
980+
}
981+
942982
impl AsRef<str> for FunctionAttribute {
943983
fn as_ref(&self) -> &str {
944984
match self {

noir_stdlib/src/meta/function_def.nr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl FunctionDefinition {
1111

1212
#[builtin(function_def_has_named_attribute)]
1313
// docs:start:has_named_attribute
14-
comptime fn has_named_attribute(self, name: Quoted) -> bool {}
14+
comptime fn has_named_attribute<let N: u32>(self, name: str<N>) -> bool {}
1515
// docs:end:has_named_attribute
1616

1717
#[builtin(function_def_is_unconstrained)]

noir_stdlib/src/meta/module.nr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ impl Module {
66

77
#[builtin(module_has_named_attribute)]
88
// docs:start:has_named_attribute
9-
comptime fn has_named_attribute(self, name: Quoted) -> bool {}
9+
comptime fn has_named_attribute<let N: u32>(self, name: str<N>) -> bool {}
1010
// docs:end:has_named_attribute
1111

1212
#[builtin(module_is_contract)]

noir_stdlib/src/meta/struct_def.nr

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl StructDefinition {
1818

1919
#[builtin(struct_def_has_named_attribute)]
2020
// docs:start:has_named_attribute
21-
comptime fn has_named_attribute(self, name: Quoted) -> bool {}
21+
comptime fn has_named_attribute<let N: u32>(self, name: str<N>) -> bool {}
2222
// docs:end:has_named_attribute
2323

2424
/// Return each generic on this struct.

test_programs/compile_success_empty/attributes_struct/src/main.nr

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ fn main() {}
99

1010
// Check that add_attribute and has_named_attribute work well
1111

12+
#[abi(something)]
1213
#[add_attribute]
1314
struct Foo {
1415

1516
}
1617

1718
comptime fn add_attribute(s: StructDefinition) {
18-
assert(!s.has_named_attribute(quote { foo }));
19+
assert(!s.has_named_attribute("foo"));
1920
s.add_attribute("foo");
20-
assert(s.has_named_attribute(quote { foo }));
21+
assert(s.has_named_attribute("foo"));
22+
23+
assert(s.has_named_attribute("abi"));
2124
}

test_programs/compile_success_empty/comptime_function_definition/src/main.nr

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ pub fn foo(w: i32, y: Field, Foo { x, field: some_field }: Foo, mut a: bool, (b,
88
1
99
}
1010

11+
#[test]
12+
#[deprecated]
13+
#[check_named_attribute]
14+
fn some_test() {}
15+
1116
comptime fn function_attr(f: FunctionDefinition) {
1217
// Check FunctionDefinition::parameters
1318
let parameters = f.parameters();
@@ -33,7 +38,12 @@ comptime fn function_attr(f: FunctionDefinition) {
3338
// Check FunctionDefinition::name
3439
assert_eq(f.name(), quote { foo });
3540

36-
assert(f.has_named_attribute(quote { function_attr }));
41+
assert(f.has_named_attribute("function_attr"));
42+
}
43+
44+
comptime fn check_named_attribute(f: FunctionDefinition) {
45+
assert(f.has_named_attribute("test"));
46+
assert(f.has_named_attribute("deprecated"));
3747
}
3848

3949
#[mutate_add_one]

test_programs/compile_success_empty/comptime_module/src/main.nr

+4-4
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ fn main() {
8585
assert_eq(bar.name(), quote { bar });
8686

8787
// Check Module::has_named_attribute
88-
assert(foo.has_named_attribute(quote { some_attribute }));
89-
assert(foo.has_named_attribute(quote { outer_attribute }));
90-
assert(!bar.has_named_attribute(quote { some_attribute }));
91-
assert(another_module.has_named_attribute(quote { some_attribute }));
88+
assert(foo.has_named_attribute("some_attribute"));
89+
assert(foo.has_named_attribute("outer_attribute"));
90+
assert(!bar.has_named_attribute("some_attribute"));
91+
assert(another_module.has_named_attribute("some_attribute"));
9292
}
9393

9494
assert_eq(counter, 4);

test_programs/compile_success_empty/inject_context_attribute/src/main.nr

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ comptime fn mapping_function(expr: Expr, f: FunctionDefinition) -> Option<Expr>
4545
let (name, arguments) = func_call;
4646
name.resolve(Option::some(f)).as_function_definition().and_then(
4747
|function_definition: FunctionDefinition| {
48-
if function_definition.has_named_attribute(quote { inject_context }) {
48+
if function_definition.has_named_attribute("inject_context") {
4949
let arguments = arguments.push_front(quote { _context }.as_expr().unwrap());
5050
let arguments = arguments.map(|arg: Expr| arg.quoted()).join(quote { , });
5151
Option::some(quote { $name($arguments) }.as_expr().unwrap())

0 commit comments

Comments
 (0)