Skip to content

Commit

Permalink
feat: Allow comptime attributes on traits & functions (noir-lang/noir…
Browse files Browse the repository at this point in the history
…#5496)

feat: skip reading values immediately after it being written into an array (noir-lang/noir#5449)
fix: Don't type error when calling certain trait impls in the interpreter (noir-lang/noir#5471)
feat: LSP hover (noir-lang/noir#5491)
chore: update typo PR script (noir-lang/noir#5488)
feat: Handle ACIR calls in the debugger (noir-lang/noir#5051)
feat: Add unquote function (noir-lang/noir#5497)
feat: Allow arguments to attribute functions (noir-lang/noir#5494)
  • Loading branch information
AztecBot committed Jul 13, 2024
2 parents 067efe6 + 81778a2 commit 56ba2cd
Show file tree
Hide file tree
Showing 18 changed files with 497 additions and 248 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
010c835e4ebfdf49ea4e9326abafcdeb587153b6
b59a29e5b246121a4d81e4894a4b10f5df4dd5cf
12 changes: 12 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,18 @@ impl Instruction {
}
}
Instruction::ArrayGet { array, index } => {
if let Value::Instruction { instruction, .. } = &dfg[*array] {
if let Instruction::ArraySet { index: write_index, value, .. } =
dfg[*instruction]
{
// If we're reading from an index of the array which we just wrote to, we can return
// the value which we wrote without performing the read.
if dfg.resolve(write_index) == dfg.resolve(*index) {
return SimplifiedTo(value);
}
}
}

let array = dfg.get_array_constant(*array);
let index = dfg.get_numeric_constant(*index);
if let (Some((array, _)), Some(index)) = (array, index) {
Expand Down
2 changes: 2 additions & 0 deletions noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::ast::{
BlockExpression, Expression, FunctionReturnType, Ident, NoirFunction, Path, UnresolvedGenerics,
UnresolvedType,
};
use crate::macros_api::SecondaryAttribute;
use crate::node_interner::TraitId;

/// AST node for trait definitions:
Expand All @@ -18,6 +19,7 @@ pub struct NoirTrait {
pub where_clause: Vec<UnresolvedTraitConstraint>,
pub span: Span,
pub items: Vec<TraitItem>,
pub attributes: Vec<SecondaryAttribute>,
}

/// Any declaration inside the body of a trait that a user is required to
Expand Down
50 changes: 37 additions & 13 deletions noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,11 @@ impl<'context> Elaborator<'context> {
}

// Must resolve structs before we resolve globals.
let generated_items = self.collect_struct_definitions(items.types);
let mut generated_items = self.collect_struct_definitions(items.types);

self.define_function_metas(&mut items.functions, &mut items.impls, &mut items.trait_impls);

self.collect_traits(items.traits);
self.collect_traits(items.traits, &mut generated_items);

// Before we resolve any function symbols we must go through our impls and
// re-collect the methods within into their proper module. This cannot be
Expand All @@ -278,6 +278,10 @@ impl<'context> Elaborator<'context> {
self.elaborate_global(global);
}

// We have to run any comptime attributes on functions before the function is elaborated
// since the generated items are checked beforehand as well.
self.run_attributes_on_functions(&items.functions, &mut generated_items);

// After everything is collected, we can elaborate our generated items.
// It may be better to inline these within `items` entirely since elaborating them
// all here means any globals will not see these. Inlining them completely within `items`
Expand Down Expand Up @@ -1242,7 +1246,8 @@ impl<'context> Elaborator<'context> {
.add_definition_location(ReferenceId::StructMember(type_id, field_index), None);
}

self.run_comptime_attributes_on_struct(attributes, type_id, span, &mut generated_items);
let item = Value::StructDefinition(type_id);
self.run_comptime_attributes_on_item(&attributes, item, span, &mut generated_items);
}

// Check whether the struct fields have nested slices
Expand All @@ -1268,34 +1273,34 @@ impl<'context> Elaborator<'context> {
generated_items
}

fn run_comptime_attributes_on_struct(
fn run_comptime_attributes_on_item(
&mut self,
attributes: Vec<SecondaryAttribute>,
struct_id: StructId,
attributes: &[SecondaryAttribute],
item: Value,
span: Span,
generated_items: &mut CollectedItems,
) {
for attribute in attributes {
if let SecondaryAttribute::Custom(name) = attribute {
if let Err(error) =
self.run_comptime_attribute_on_struct(name, struct_id, span, generated_items)
self.run_comptime_attribute_on_item(name, item.clone(), span, generated_items)
{
self.errors.push(error);
}
}
}
}

fn run_comptime_attribute_on_struct(
fn run_comptime_attribute_on_item(
&mut self,
attribute: String,
struct_id: StructId,
attribute: &str,
item: Value,
span: Span,
generated_items: &mut CollectedItems,
) -> Result<(), (CompilationError, FileId)> {
let location = Location::new(span, self.file);
let (function_name, mut arguments) =
Self::parse_attribute(&attribute, location).unwrap_or((attribute, Vec::new()));
let (function_name, mut arguments) = Self::parse_attribute(attribute, location)
.unwrap_or_else(|| (attribute.to_string(), Vec::new()));

let id = self
.lookup_global(Path::from_single(function_name, span))
Expand All @@ -1307,7 +1312,7 @@ impl<'context> Elaborator<'context> {
};

self.handle_varargs_attribute(function, &mut arguments, location);
arguments.insert(0, (Value::StructDefinition(struct_id), location));
arguments.insert(0, (item, location));

let mut interpreter_errors = vec![];
let mut interpreter = self.setup_interpreter(&mut interpreter_errors);
Expand Down Expand Up @@ -1741,4 +1746,23 @@ impl<'context> Elaborator<'context> {
));
}
}

fn run_attributes_on_functions(
&mut self,
function_sets: &[UnresolvedFunctions],
generated_items: &mut CollectedItems,
) {
for function_set in function_sets {
self.file = function_set.file_id;
self.self_type = function_set.self_type.clone();

for (local_module, function_id, function) in &function_set.functions {
self.local_module = *local_module;
let attributes = function.secondary_attributes();
let item = Value::FunctionDefinition(*function_id);
let span = function.span();
self.run_comptime_attributes_on_item(attributes, item, span, generated_items);
}
}
}
}
13 changes: 11 additions & 2 deletions noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
ast::{
FunctionKind, TraitItem, UnresolvedGeneric, UnresolvedGenerics, UnresolvedTraitConstraint,
},
hir::def_collector::dc_crate::UnresolvedTrait,
hir::def_collector::dc_crate::{CollectedItems, UnresolvedTrait},
hir_def::traits::{TraitConstant, TraitFunction, TraitType},
macros_api::{
BlockExpression, FunctionDefinition, FunctionReturnType, Ident, ItemVisibility,
Expand All @@ -21,7 +21,11 @@ use crate::{
use super::Elaborator;

impl<'context> Elaborator<'context> {
pub fn collect_traits(&mut self, traits: BTreeMap<TraitId, UnresolvedTrait>) {
pub fn collect_traits(
&mut self,
traits: BTreeMap<TraitId, UnresolvedTrait>,
generated_items: &mut CollectedItems,
) {
for (trait_id, unresolved_trait) in traits {
self.recover_generics(|this| {
let resolved_generics = this.interner.get_trait(trait_id).generics.clone();
Expand All @@ -41,6 +45,11 @@ impl<'context> Elaborator<'context> {
this.interner.update_trait(trait_id, |trait_def| {
trait_def.set_methods(methods);
});

let attributes = &unresolved_trait.trait_def.attributes;
let item = crate::hir::comptime::Value::TraitDefinition(trait_id);
let span = unresolved_trait.trait_def.span;
this.run_comptime_attributes_on_item(attributes, item, span, generated_items);
});

// This check needs to be after the trait's methods are set since
Expand Down
24 changes: 21 additions & 3 deletions noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ use noirc_errors::Location;

use crate::{
ast::{ArrayLiteral, ConstructorExpression, Ident, IntegerBitSize, Signedness},
hir::def_map::ModuleId,
hir_def::expr::{HirArrayLiteral, HirConstructorExpression, HirIdent, HirLambda, ImplKind},
macros_api::{
Expression, ExpressionKind, HirExpression, HirLiteral, Literal, NodeInterner, Path,
StructId,
},
node_interner::{ExprId, FuncId},
node_interner::{ExprId, FuncId, TraitId},
parser::{self, NoirParser, TopLevelStatement},
token::{SpannedToken, Token, Tokens},
QuotedType, Shared, Type, TypeBindings,
Expand Down Expand Up @@ -45,6 +46,9 @@ pub enum Value {
Slice(Vector<Value>, Type),
Code(Rc<Tokens>),
StructDefinition(StructId),
TraitDefinition(TraitId),
FunctionDefinition(FuncId),
ModuleDefinition(ModuleId),
}

impl Value {
Expand Down Expand Up @@ -79,6 +83,9 @@ impl Value {
let element = element.borrow().get_type().into_owned();
Type::MutableReference(Box::new(element))
}
Value::TraitDefinition(_) => Type::Quoted(QuotedType::TraitDefinition),
Value::FunctionDefinition(_) => Type::Quoted(QuotedType::FunctionDefinition),
Value::ModuleDefinition(_) => Type::Quoted(QuotedType::Module),
})
}

Expand Down Expand Up @@ -192,7 +199,11 @@ impl Value {
}
};
}
Value::Pointer(_) | Value::StructDefinition(_) => {
Value::Pointer(_)
| Value::StructDefinition(_)
| Value::TraitDefinition(_)
| Value::FunctionDefinition(_)
| Value::ModuleDefinition(_) => {
return Err(InterpreterError::CannotInlineMacro { value: self, location })
}
};
Expand Down Expand Up @@ -298,7 +309,11 @@ impl Value {
HirExpression::Literal(HirLiteral::Slice(HirArrayLiteral::Standard(elements)))
}
Value::Code(block) => HirExpression::Unquote(unwrap_rc(block)),
Value::Pointer(_) | Value::StructDefinition(_) => {
Value::Pointer(_)
| Value::StructDefinition(_)
| Value::TraitDefinition(_)
| Value::FunctionDefinition(_)
| Value::ModuleDefinition(_) => {
return Err(InterpreterError::CannotInlineMacro { value: self, location })
}
};
Expand Down Expand Up @@ -402,6 +417,9 @@ impl Display for Value {
write!(f, " }}")
}
Value::StructDefinition(_) => write!(f, "(struct definition)"),
Value::TraitDefinition(_) => write!(f, "(trait definition)"),
Value::FunctionDefinition(_) => write!(f, "(function definition)"),
Value::ModuleDefinition(_) => write!(f, "(module)"),
}
}
}
Loading

0 comments on commit 56ba2cd

Please sign in to comment.