Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
5 changes: 3 additions & 2 deletions compiler/noirc_frontend/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ impl ForRange {
identifier: Ident,
block: Expression,
for_loop_span: Span,
) -> StatementKind {
) -> Statement {
/// Counter used to generate unique names when desugaring
/// code in the parser requires the creation of fresh variables.
/// The parser is stateless so this is a static global instead.
Expand Down Expand Up @@ -662,7 +662,8 @@ impl ForRange {
let block = ExpressionKind::Block(BlockExpression {
statements: vec![let_array, for_loop],
});
StatementKind::Expression(Expression::new(block, for_loop_span))
let kind = StatementKind::Expression(Expression::new(block, for_loop_span));
Statement { kind, span: for_loop_span }
}
}
}
Expand Down
604 changes: 604 additions & 0 deletions compiler/noirc_frontend/src/elaborator/expressions.rs

Large diffs are not rendered by default.

162 changes: 162 additions & 0 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#![allow(unused)]
use std::{
collections::{BTreeMap, BTreeSet},
rc::Rc,
};

use crate::graph::CrateId;
use crate::hir::def_map::CrateDefMap;
use crate::{
ast::{
ArrayLiteral, ConstructorExpression, FunctionKind, IfExpression, InfixExpression, Lambda,
UnresolvedTraitConstraint, UnresolvedTypeExpression,
},
hir::{
def_collector::dc_crate::CompilationError,
resolution::{errors::ResolverError, path_resolver::PathResolver, resolver::LambdaContext},
scope::ScopeForest as GenericScopeForest,
type_check::TypeCheckError,
},
hir_def::{
expr::{
HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression,
HirConstructorExpression, HirIdent, HirIfExpression, HirIndexExpression,
HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression,
HirMethodReference, HirPrefixExpression,
},
traits::TraitConstraint,
},
macros_api::{
BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, HirExpression,
HirLiteral, HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression,
MethodCallExpression, NodeInterner, NoirFunction, PrefixExpression, Statement,
StatementKind, StructId,
},
node_interner::{DefinitionKind, DependencyId, ExprId, FuncId, StmtId, TraitId},
Shared, StructType, Type, TypeVariable,
};

mod expressions;
mod patterns;
mod scope;
mod statements;
mod types;

use fm::FileId;
use iter_extended::vecmap;
use noirc_errors::{Location, Span};
use regex::Regex;
use rustc_hash::FxHashSet as HashSet;
use scope::Scope;

/// ResolverMetas are tagged onto each definition to track how many times they are used
#[derive(Debug, PartialEq, Eq)]
struct ResolverMeta {
num_times_used: usize,
ident: HirIdent,
warn_if_unused: bool,
}

type ScopeForest = GenericScopeForest<String, ResolverMeta>;

struct Elaborator {
scopes: ScopeForest,
globals: Scope,
local_scopes: Vec<Scope>,

errors: Vec<CompilationError>,

interner: NodeInterner,
file: FileId,

in_unconstrained_fn: bool,
nested_loops: usize,

/// True if the current module is a contract.
/// This is usually determined by self.path_resolver.module_id(), but it can
/// be overridden for impls. Impls are an odd case since the methods within resolve
/// as if they're in the parent module, but should be placed in a child module.
/// Since they should be within a child module, in_contract is manually set to false
/// for these so we can still resolve them in the parent module without them being in a contract.
in_contract: bool,

/// Contains a mapping of the current struct or functions's generics to
/// unique type variables if we're resolving a struct. Empty otherwise.
/// This is a Vec rather than a map to preserve the order a functions generics
/// were declared in.
generics: Vec<(Rc<String>, TypeVariable, Span)>,

/// When resolving lambda expressions, we need to keep track of the variables
/// that are captured. We do this in order to create the hidden environment
/// parameter for the lambda function.
lambda_stack: Vec<LambdaContext>,

/// Set to the current type if we're resolving an impl
self_type: Option<Type>,

/// The current dependency item we're resolving.
/// Used to link items to their dependencies in the dependency graph
current_item: Option<DependencyId>,

trait_id: Option<TraitId>,

path_resolver: Rc<dyn PathResolver>,
def_maps: BTreeMap<CrateId, CrateDefMap>,

/// In-resolution names
///
/// This needs to be a set because we can have multiple in-resolution
/// names when resolving structs that are declared in reverse order of their
/// dependencies, such as in the following case:
///
/// ```
/// struct Wrapper {
/// value: Wrapped
/// }
/// struct Wrapped {
/// }
/// ```
resolving_ids: BTreeSet<StructId>,

trait_bounds: Vec<UnresolvedTraitConstraint>,

current_function: Option<FuncId>,

/// All type variables created in the current function.
/// This map is used to default any integer type variables at the end of
/// a function (before checking trait constraints) if a type wasn't already chosen.
type_variables: Vec<Type>,

/// Trait constraints are collected during type checking until they are
/// verified at the end of a function. This is because constraints arise
/// on each variable, but it is only until function calls when the types
/// needed for the trait constraint may become known.
trait_constraints: Vec<(TraitConstraint, ExprId)>,
}

impl Elaborator {
fn elaborate_function(&mut self, function: NoirFunction, _id: FuncId) {
// This is a stub until the elaborator is connected to dc_crate
match function.kind {
FunctionKind::LowLevel => todo!(),
FunctionKind::Builtin => todo!(),
FunctionKind::Oracle => todo!(),
FunctionKind::Recursive => todo!(),
FunctionKind::Normal => {
let _body = self.elaborate_block(function.def.body);
}
}
}

fn push_scope(&mut self) {
self.local_scopes.push(Scope::default());
}

fn pop_scope(&mut self) {
self.local_scopes.pop();
}

fn push_err(&mut self, error: impl Into<CompilationError>) {
self.errors.push(error.into());
}
}
Loading