Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Add stdlib to every crate as it is added to graph #2392

Merged
merged 2 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
50 changes: 18 additions & 32 deletions crates/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ mod program;
pub use contract::{CompiledContract, ContractFunction, ContractFunctionType};
pub use program::CompiledProgram;

const STD_CRATE_NAME: &str = "std";

#[derive(Args, Clone, Debug, Default, Serialize, Deserialize)]
pub struct CompileOptions {
/// Emit debug information for the intermediate SSA IR
Expand Down Expand Up @@ -58,16 +60,30 @@ pub fn compile_file(

/// Adds the file from the file system at `Path` to the crate graph as a root file
pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId {
let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr");
let std_file_id = context.file_manager.add_file(&path_to_std_lib_file).unwrap();
let std_crate_id = context.crate_graph.add_stdlib(std_file_id);

let root_file_id = context.file_manager.add_file(file_name).unwrap();

context.crate_graph.add_crate_root(root_file_id)
let root_crate_id = context.crate_graph.add_crate_root(root_file_id);

add_dep(context, root_crate_id, std_crate_id, STD_CRATE_NAME.parse().unwrap());

root_crate_id
}

// Adds the file from the file system at `Path` to the crate graph
pub fn prepare_dependency(context: &mut Context, file_name: &Path) -> CrateId {
let root_file_id = context.file_manager.add_file(file_name).unwrap();

context.crate_graph.add_crate(root_file_id)
let crate_id = context.crate_graph.add_crate(root_file_id);

// Every dependency has access to stdlib
let std_crate_id = context.stdlib_crate_id();
add_dep(context, crate_id, *std_crate_id, STD_CRATE_NAME.parse().unwrap());

crate_id
}

/// Adds a edge in the crate graph for two crates
Expand All @@ -83,23 +99,6 @@ pub fn add_dep(
.expect("cyclic dependency triggered");
}

/// Propagates a given dependency to every other crate.
pub fn propagate_dep(
context: &mut Context,
dep_to_propagate: CrateId,
dep_to_propagate_name: &CrateName,
) {
let crate_ids: Vec<_> =
context.crate_graph.iter_keys().filter(|crate_id| *crate_id != dep_to_propagate).collect();

for crate_id in crate_ids {
context
.crate_graph
.add_dep(crate_id, dep_to_propagate_name.clone(), dep_to_propagate)
.expect("ice: cyclic error triggered with std library");
}
}

/// Run the lexing, parsing, name resolution, and type checking passes.
///
/// This returns a (possibly empty) vector of any warnings found on success.
Expand All @@ -109,19 +108,6 @@ pub fn check_crate(
crate_id: CrateId,
deny_warnings: bool,
) -> Result<Warnings, ErrorsAndWarnings> {
// Add the stdlib before we check the crate
// TODO: This should actually be done when constructing the driver and then propagated to each dependency when added;
// however, the `create_non_local_crate` panics if you add the stdlib as the first crate in the graph and other
// parts of the code expect the `0` FileID to be the crate root. See also #1681
let std_crate_name = "std";
let path_to_std_lib_file = Path::new(std_crate_name).join("lib.nr");
let root_file_id = context.file_manager.add_file(&path_to_std_lib_file).unwrap();

// You can add any crate type to the crate graph
// but you cannot depend on Binaries
let std_crate = context.crate_graph.add_stdlib(root_file_id);
propagate_dep(context, std_crate, &std_crate_name.parse().unwrap());

let mut errors = vec![];
CrateDefMap::collect_defs(crate_id, context, &mut errors);

Expand Down
7 changes: 7 additions & 0 deletions crates/noirc_frontend/src/graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ impl CrateGraph {
.expect("ICE: A root crate should exist in the CrateGraph")
}

pub fn stdlib_crate_id(&self) -> &CrateId {
self.arena
.keys()
.find(|crate_id| crate_id.is_stdlib())
.expect("ICE: The stdlib should exist in the CrateGraph")
}

pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
for (crate_id, crate_data) in self.arena.iter() {
if crate_id.is_root() {
Expand Down
4 changes: 4 additions & 0 deletions crates/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ impl Context {
self.crate_graph.root_crate_id()
}

pub fn stdlib_crate_id(&self) -> &CrateId {
self.crate_graph.stdlib_crate_id()
}

// TODO: Decide if we actually need `function_name` and `fully_qualified_function_name`
pub fn function_name(&self, id: &FuncId) -> &str {
self.def_interner.function_name(id)
Expand Down
35 changes: 28 additions & 7 deletions crates/wasm/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use fm::FileManager;
use gloo_utils::format::JsValueSerdeExt;
use log::debug;
use noirc_driver::{
check_crate, compile_contracts, compile_no_check, prepare_crate, prepare_dependency,
propagate_dep, CompileOptions, CompiledContract,
add_dep, check_crate, compile_contracts, compile_no_check, prepare_crate, prepare_dependency,
CompileOptions, CompiledContract,
};
use noirc_frontend::{graph::CrateGraph, hir::Context};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -58,11 +58,32 @@ impl Default for WASMCompileOptions {
}
}

fn add_noir_lib(context: &mut Context, crate_name: &str) {
let path_to_lib = Path::new(&crate_name).join("lib.nr");
let library_crate = prepare_dependency(context, &path_to_lib);

propagate_dep(context, library_crate, &crate_name.parse().unwrap());
fn add_noir_lib(context: &mut Context, library_name: &str) {
let path_to_lib = Path::new(&library_name).join("lib.nr");
let library_crate_id = prepare_dependency(context, &path_to_lib);

add_dep(context, *context.root_crate_id(), library_crate_id, library_name.parse().unwrap());

// TODO: Remove this code that attaches every crate to every other crate as a dependency
let root_crate_id = context.root_crate_id();
let stdlib_crate_id = context.stdlib_crate_id();
let other_crate_ids: Vec<_> = context
.crate_graph
.iter_keys()
.filter(|crate_id| {
// We don't want to attach this crate to itself or stdlib, nor re-attach it to the root crate
crate_id != &library_crate_id
&& crate_id != root_crate_id
&& crate_id != stdlib_crate_id
})
.collect();

for crate_id in other_crate_ids {
context
.crate_graph
.add_dep(crate_id, library_name.parse().unwrap(), library_crate_id)
.expect(&format!("ICE: Cyclic error triggered by {} library", library_name));
}
phated marked this conversation as resolved.
Show resolved Hide resolved
}

#[wasm_bindgen]
Expand Down