Skip to content

Commit

Permalink
chore(experimental): Add compiler option to enable the Elaborator (#5003
Browse files Browse the repository at this point in the history
)

# Description

## Problem\*

Working towards #4594 

## Summary\*

Adds a hidden compiler option `--use-elaborator` to enable the
experimental elaborator code to be run on a codebase.

This also connects the elaborator with `dc_crate` (and thus the cli flag
above) by filling in the stub for elaborating functions. Filling in the
stub required quite a bit of code but it was as usual just copied from
name resolution and type checking.

## Additional Context

Originally I wanted to connect the elaborator to more of the frontend
(e.g. resolve globals, types, traits, etc) but this already ballooned to
a large line count. To review I'd recommend reviewing the non-elaborator
portions first then just skimming through the elaborator portions since
they are copied from `Resolver::resolve_function`,
`Resolver::extract_meta`, `Resolver::intern_function`, and
`type_check_func`.

## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] 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.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
jfecher committed May 9, 2024
1 parent e12bf9b commit c8b70ac
Show file tree
Hide file tree
Showing 25 changed files with 1,015 additions and 192 deletions.
25 changes: 20 additions & 5 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ pub struct CompileOptions {
/// Force Brillig output (for step debugging)
#[arg(long, hide = true)]
pub force_brillig: bool,

/// Enable the experimental elaborator pass
#[arg(long, hide = true)]
pub use_elaborator: bool,
}

fn parse_expression_width(input: &str) -> Result<ExpressionWidth, std::io::Error> {
Expand Down Expand Up @@ -245,12 +249,13 @@ pub fn check_crate(
crate_id: CrateId,
deny_warnings: bool,
disable_macros: bool,
use_elaborator: bool,
) -> CompilationResult<()> {
let macros: &[&dyn MacroProcessor] =
if disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] };

let mut errors = vec![];
let diagnostics = CrateDefMap::collect_defs(crate_id, context, macros);
let diagnostics = CrateDefMap::collect_defs(crate_id, context, use_elaborator, macros);
errors.extend(diagnostics.into_iter().map(|(error, file_id)| {
let diagnostic = CustomDiagnostic::from(&error);
diagnostic.in_file(file_id)
Expand Down Expand Up @@ -282,8 +287,13 @@ pub fn compile_main(
options: &CompileOptions,
cached_program: Option<CompiledProgram>,
) -> CompilationResult<CompiledProgram> {
let (_, mut warnings) =
check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?;
let (_, mut warnings) = check_crate(
context,
crate_id,
options.deny_warnings,
options.disable_macros,
options.use_elaborator,
)?;

let main = context.get_main_function(&crate_id).ok_or_else(|| {
// TODO(#2155): This error might be a better to exist in Nargo
Expand Down Expand Up @@ -318,8 +328,13 @@ pub fn compile_contract(
crate_id: CrateId,
options: &CompileOptions,
) -> CompilationResult<CompiledContract> {
let (_, warnings) =
check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?;
let (_, warnings) = check_crate(
context,
crate_id,
options.deny_warnings,
options.disable_macros,
options.use_elaborator,
)?;

// TODO: We probably want to error if contracts is empty
let contracts = context.get_all_contracts(&crate_id);
Expand Down
3 changes: 2 additions & 1 deletion compiler/noirc_driver/tests/stdlib_warnings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ fn stdlib_does_not_produce_constant_warnings() -> Result<(), ErrorsAndWarnings>
let mut context = Context::new(file_manager, parsed_files);
let root_crate_id = prepare_crate(&mut context, file_name);

let ((), warnings) = noirc_driver::check_crate(&mut context, root_crate_id, false, false)?;
let ((), warnings) =
noirc_driver::check_crate(&mut context, root_crate_id, false, false, false)?;

assert_eq!(warnings, Vec::new(), "stdlib is producing warnings");

Expand Down
9 changes: 9 additions & 0 deletions compiler/noirc_frontend/src/ast/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ pub enum FunctionKind {
Recursive,
}

impl FunctionKind {
pub fn can_ignore_return_type(self) -> bool {
match self {
FunctionKind::LowLevel | FunctionKind::Builtin | FunctionKind::Oracle => true,
FunctionKind::Normal | FunctionKind::Recursive => false,
}
}
}

impl NoirFunction {
pub fn normal(def: FunctionDefinition) -> NoirFunction {
NoirFunction { kind: FunctionKind::Normal, def }
Expand Down
6 changes: 3 additions & 3 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::{

use super::Elaborator;

impl Elaborator {
impl<'context> Elaborator<'context> {
pub(super) fn elaborate_expression(&mut self, expr: Expression) -> (ExprId, Type) {
let (hir_expr, typ) = match expr.kind {
ExpressionKind::Literal(literal) => self.elaborate_literal(literal, expr.span),
Expand Down Expand Up @@ -323,7 +323,7 @@ impl Elaborator {
&method_ref,
object_type,
location,
&mut self.interner,
self.interner,
);

let func_type = self.type_check_variable(function_name, function_id);
Expand Down Expand Up @@ -443,7 +443,7 @@ impl Elaborator {
(expr_id, typ)
}

fn intern_expr(&mut self, expr: HirExpression, span: Span) -> ExprId {
pub fn intern_expr(&mut self, expr: HirExpression, span: Span) -> ExprId {
let id = self.interner.push_expr(expr);
self.interner.push_expr_location(id, span, self.file);
id
Expand Down
Loading

0 comments on commit c8b70ac

Please sign in to comment.