Skip to content

Commit

Permalink
Track global value resolution in GlobalInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Dec 18, 2024
1 parent 4053db3 commit 2d6c5a0
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 38 deletions.
6 changes: 3 additions & 3 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::{
};

use crate::{
ast::ItemVisibility, hir_def::traits::ResolvedTraitBound, usage_tracker::UsageTracker,
StructField, StructType, TypeBindings,
ast::ItemVisibility, hir_def::traits::ResolvedTraitBound, node_interner::GlobalValue,
usage_tracker::UsageTracker, StructField, StructType, TypeBindings,
};
use crate::{
ast::{
Expand Down Expand Up @@ -1689,7 +1689,7 @@ impl<'context> Elaborator<'context> {

self.debug_comptime(location, |interner| value.display(interner).to_string());

self.interner.get_global_mut(global_id).value = Some(value);
self.interner.get_global_mut(global_id).value = GlobalValue::Resolved(value);
}
}

Expand Down
7 changes: 4 additions & 3 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use crate::{
traits::{NamedType, ResolvedTraitBound, Trait, TraitConstraint},
},
node_interner::{
DependencyId, ExprId, ImplSearchErrorKind, NodeInterner, TraitId, TraitImplKind,
TraitMethodId,
DependencyId, ExprId, GlobalValue, ImplSearchErrorKind, NodeInterner, TraitId,
TraitImplKind, TraitMethodId,
},
token::SecondaryAttribute,
Generics, Kind, ResolvedGeneric, Type, TypeBinding, TypeBindings, UnificationError,
Expand Down Expand Up @@ -426,7 +426,8 @@ impl<'context> Elaborator<'context> {
let rhs = stmt.expression;
let span = self.interner.expr_span(&rhs);

let Some(global_value) = &self.interner.get_global(id).value else {
let GlobalValue::Resolved(global_value) = &self.interner.get_global(id).value
else {
self.push_err(ResolverError::UnevaluatedGlobalType { span });
return None;
};
Expand Down
55 changes: 27 additions & 28 deletions compiler/noirc_frontend/src/hir/comptime/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::{HashSet, VecDeque};
use std::collections::VecDeque;
use std::{collections::hash_map::Entry, rc::Rc};

use acvm::blackbox_solver::BigIntSolverWithId;
Expand All @@ -20,7 +20,7 @@ use crate::monomorphization::{
perform_impl_bindings, perform_instantiation_bindings, resolve_trait_method,
undo_instantiation_bindings,
};
use crate::node_interner::GlobalId;
use crate::node_interner::GlobalValue;
use crate::token::{FmtStrFragment, Tokens};
use crate::TypeVariable;
use crate::{
Expand Down Expand Up @@ -67,12 +67,6 @@ pub struct Interpreter<'local, 'interner> {

/// Stateful bigint calculator.
bigint_solver: BigIntSolverWithId,

/// Globals currently being interpreted, to detect recursive cycles.
/// Note that recursive cycles are also detected by NodeInterner,
/// it's just that the error message there happens after we evaluate globals:
/// if we don't detect cycles here too the program will stack overflow.
globals_being_interpreted: HashSet<GlobalId>,
}

#[allow(unused)]
Expand All @@ -89,7 +83,6 @@ impl<'local, 'interner> Interpreter<'local, 'interner> {
bound_generics: Vec::new(),
in_loop: false,
bigint_solver: BigIntSolverWithId::default(),
globals_being_interpreted: HashSet::new(),
}
}

Expand Down Expand Up @@ -578,29 +571,35 @@ impl<'local, 'interner> Interpreter<'local, 'interner> {
// Avoid resetting the value if it is already known
let global_id = *global_id;
let global_info = self.elaborator.interner.get_global(global_id);
if let Some(value) = &global_info.value {
Ok(value.clone())
} else if self.globals_being_interpreted.contains(&global_id) {
let location = self.elaborator.interner.expr_location(&id);
Err(InterpreterError::GlobalsDependencyCycle { location })
} else {
let let_ =
self.elaborator.interner.get_global_let_statement(global_id).ok_or_else(
|| {
let global_crate_id = global_info.crate_id;
match &global_info.value {
GlobalValue::Resolved(value) => Ok(value.clone()),
GlobalValue::Resolving => {
let location = self.elaborator.interner.expr_location(&id);
Err(InterpreterError::GlobalsDependencyCycle { location })
}
GlobalValue::Unresolved => {
let let_ = self
.elaborator
.interner
.get_global_let_statement(global_id)
.ok_or_else(|| {
let location = self.elaborator.interner.expr_location(&id);
InterpreterError::VariableNotInScope { location }
},
)?;
})?;

if let_.runs_comptime() || global_info.crate_id != self.crate_id {
self.globals_being_interpreted.insert(global_id);
self.evaluate_let(let_.clone())?;
self.globals_being_interpreted.remove(&global_id);
}
self.elaborator.interner.get_global_mut(global_id).value =
GlobalValue::Resolving;

let value = self.lookup(&ident)?;
self.elaborator.interner.get_global_mut(global_id).value = Some(value.clone());
Ok(value)
if let_.runs_comptime() || global_crate_id != self.crate_id {
self.evaluate_let(let_.clone())?;
}

let value = self.lookup(&ident)?;
self.elaborator.interner.get_global_mut(global_id).value =
GlobalValue::Resolved(value.clone());
Ok(value)
}
}
}
DefinitionKind::NumericGeneric(type_variable, numeric_typ) => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/monomorphization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use crate::ast::{FunctionKind, IntegerBitSize, Signedness, UnaryOp, Visibility};
use crate::hir::comptime::InterpreterError;
use crate::hir::type_check::{NoMatchingImplFoundError, TypeCheckError};
use crate::node_interner::{ExprId, ImplSearchErrorKind};
use crate::node_interner::{ExprId, GlobalValue, ImplSearchErrorKind};
use crate::token::FmtStrFragment;
use crate::{
debug::DebugInstrumenter,
Expand Down Expand Up @@ -895,7 +895,7 @@ impl<'interner> Monomorphizer<'interner> {
DefinitionKind::Global(global_id) => {
let global = self.interner.get_global(*global_id);

let expr = if let Some(value) = global.value.clone() {
let expr = if let GlobalValue::Resolved(value) = global.value.clone() {
value
.into_hir_expression(self.interner, global.location)
.map_err(MonomorphizationError::InterpreterError)?
Expand Down
11 changes: 9 additions & 2 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,14 @@ pub struct GlobalInfo {
pub crate_id: CrateId,
pub location: Location,
pub let_statement: StmtId,
pub value: Option<comptime::Value>,
pub value: GlobalValue,
}

#[derive(Debug, Clone)]
pub enum GlobalValue {
Unresolved,
Resolving,
Resolved(comptime::Value),
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -861,7 +868,7 @@ impl NodeInterner {
crate_id,
let_statement,
location,
value: None,
value: GlobalValue::Unresolved,
});
self.global_attributes.insert(id, attributes);
id
Expand Down

0 comments on commit 2d6c5a0

Please sign in to comment.