Skip to content

Commit

Permalink
feat: add FunctionDefinition::module and StructDefinition::module (
Browse files Browse the repository at this point in the history
…#5956)

# Description

## Problem

Resolves #5953

## Summary

## Additional Context

## Documentation

Check one:
- [ ] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
asterite authored Sep 6, 2024
1 parent f57ce85 commit f19344c
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 8 deletions.
44 changes: 40 additions & 4 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ use crate::{
FunctionReturnType, IntegerBitSize, LValue, Literal, Statement, StatementKind, UnaryOp,
UnresolvedType, UnresolvedTypeData, Visibility,
},
hir::comptime::{
errors::IResult,
value::{ExprValue, TypedExpr},
InterpreterError, Value,
hir::{
comptime::{
errors::IResult,
value::{ExprValue, TypedExpr},
InterpreterError, Value,
},
def_map::ModuleId,
},
hir_def::function::FunctionBody,
lexer::Lexer,
Expand Down Expand Up @@ -102,6 +105,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"function_def_has_named_attribute" => {
function_def_has_named_attribute(interner, arguments, location)
}
"function_def_module" => function_def_module(interner, arguments, location),
"function_def_name" => function_def_name(interner, arguments, location),
"function_def_parameters" => function_def_parameters(interner, arguments, location),
"function_def_return_type" => function_def_return_type(interner, arguments, location),
Expand Down Expand Up @@ -142,6 +146,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"struct_def_has_named_attribute" => {
struct_def_has_named_attribute(interner, arguments, location)
}
"struct_def_module" => struct_def_module(self, arguments, location),
"struct_def_set_fields" => struct_def_set_fields(interner, arguments, location),
"to_le_radix" => to_le_radix(arguments, return_type, location),
"trait_constraint_eq" => trait_constraint_eq(interner, arguments, location),
Expand Down Expand Up @@ -399,6 +404,25 @@ fn struct_def_fields(
Ok(Value::Slice(fields, typ))
}

// fn module(self) -> Module
fn struct_def_module(
interpreter: &Interpreter,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let self_argument = check_one_argument(arguments, location)?;
let struct_id = get_struct(self_argument)?;
let struct_module_id = struct_id.module_id();

// A struct's module is its own module. To get the module where its defined we need
// to look for its parent.
let module_data = interpreter.elaborator.get_module(struct_module_id);
let parent_local_id = module_data.parent.expect("Expected struct module parent to exist");
let parent = ModuleId { krate: struct_module_id.krate, local_id: parent_local_id };

Ok(Value::ModuleDefinition(parent))
}

/// fn set_fields(self, new_fields: [(Quoted, Type)]) {}
/// Returns (name, type) pairs of each field of this StructDefinition
fn struct_def_set_fields(
Expand Down Expand Up @@ -1827,6 +1851,18 @@ fn function_def_has_named_attribute(
Ok(Value::Bool(has_named_attribute(&name, attributes, location)))
}

// fn module(self) -> Module
fn function_def_module(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let self_argument = check_one_argument(arguments, location)?;
let func_id = get_function_def(self_argument)?;
let module = interner.function_module(func_id);
Ok(Value::ModuleDefinition(module))
}

// fn name(self) -> Quoted
fn function_def_name(
interner: &NodeInterner,
Expand Down
8 changes: 7 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,13 @@ impl<'value, 'interner> Display for ValuePrinter<'value, 'interner> {
Value::FunctionDefinition(function_id) => {
write!(f, "{}", self.interner.function_name(function_id))
}
Value::ModuleDefinition(_) => write!(f, "(module)"),
Value::ModuleDefinition(module_id) => {
if let Some(attributes) = self.interner.try_module_attributes(module_id) {
write!(f, "{}", &attributes.name)
} else {
write!(f, "(crate root)")
}
}
Value::Zeroed(typ) => write!(f, "(zeroed {typ})"),
Value::Type(typ) => write!(f, "{:?}", typ),
Value::Expr(ExprValue::Expression(expr)) => {
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/noir/standard_library/meta/function_def.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ This means any functions called at compile-time are invalid targets for this met

Returns true if this function has a custom attribute with the given name.

### module

#include_code module noir_stdlib/src/meta/function_def.nr rust

Returns the module where the function is defined.

### name

#include_code name noir_stdlib/src/meta/function_def.nr rust
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/noir/standard_library/meta/struct_def.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ Returns each field of this struct as a pair of (field name, field type).

Returns true if this struct has a custom attribute with the given name.

### module

#include_code module noir_stdlib/src/meta/struct_def.nr rust

Returns the module where the struct is defined.

### set_fields

#include_code set_fields noir_stdlib/src/meta/struct_def.nr rust
Expand Down
5 changes: 5 additions & 0 deletions noir_stdlib/src/meta/function_def.nr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ impl FunctionDefinition {
fn has_named_attribute(self, name: Quoted) -> bool {}
// docs:end:has_named_attribute

#[builtin(function_def_module)]
// docs:start:module
fn module(self) -> Module {}
// docs:end:module

#[builtin(function_def_name)]
// docs:start:name
fn name(self) -> Quoted {}
Expand Down
5 changes: 5 additions & 0 deletions noir_stdlib/src/meta/struct_def.nr
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ impl StructDefinition {
fn fields(self) -> [(Quoted, Type)] {}
// docs:end:fields

#[builtin(struct_def_module)]
// docs:start:module
fn module(self) -> Module {}
// docs:end:module

/// Sets the fields of this struct to the given fields list.
/// All existing fields of the struct will be overridden with the given fields.
/// Each element of the fields list corresponds to the name and type of a field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,12 @@ contract some_contract {
fn set_pub_return(f: FunctionDefinition) {
f.set_return_public(true);
}

mod foo {
#[attr]
pub fn some() {}

fn attr(f: FunctionDefinition) {
assert_eq(f.module().name(), quote { foo });
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "comptime_type_definition"
name = "comptime_struct_definition"
type = "bin"
authors = [""]
compiler_version = ">=0.31.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
fn main() {}

#[my_comptime_fn]
struct MyType<A, B, C> {
field1: [A; 10],
Expand All @@ -24,3 +22,15 @@ comptime fn mutate_struct_fields(s: StructDefinition) {
];
s.set_fields(fields);
}

mod foo {
#[attr]
struct Foo {}

fn attr(s: StructDefinition) {
assert_eq(s.module().name(), quote { foo });
}
}

fn main() {}

0 comments on commit f19344c

Please sign in to comment.