Skip to content

Commit

Permalink
feat: add mvp nargo export command
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Dec 19, 2023
1 parent 698d5fd commit 4705b35
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 2 deletions.
23 changes: 23 additions & 0 deletions compiler/noirc_frontend/src/hir/def_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,29 @@ impl CrateDefMap {
})
})
}

/// Go through all modules in this crate, and find all functions in
/// each module with the #[export] attribute
pub fn get_all_exported_functions<'a>(
&'a self,
interner: &'a NodeInterner,
) -> impl Iterator<Item = FuncId> + 'a {
self.modules.iter().flat_map(|(_, module)| {
module.value_definitions().filter_map(|id| {
if let Some(func_id) = id.as_function() {
let attributes = interner.function_attributes(&func_id);
if attributes.secondary.contains(&SecondaryAttribute::Export) {
Some(func_id)
} else {
None
}
} else {
None
}
})
})
}

/// Go through all modules in this crate, find all `contract ... { ... }` declarations,
/// and collect them all into a Vec.
pub fn get_all_contracts(&self, interner: &NodeInterner) -> Vec<Contract> {
Expand Down
13 changes: 13 additions & 0 deletions compiler/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,19 @@ impl Context {
.collect()
}

pub fn get_all_exported_functions_in_crate(&self, crate_id: &CrateId) -> Vec<(String, FuncId)> {
let interner = &self.def_interner;
let def_map = self.def_map(crate_id).expect("The local crate should be analyzed already");

def_map
.get_all_exported_functions(interner)
.map(|function_id| {
let function_name = self.function_name(&function_id).to_owned();
(function_name, function_id)
})
.collect()
}

/// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId].
/// Returns [None] when definition is not found.
pub fn get_definition_location_from(&self, location: Location) -> Option<Location> {
Expand Down
5 changes: 4 additions & 1 deletion compiler/noirc_frontend/src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ impl Attribute {
Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod)
}
["event"] => Attribute::Secondary(SecondaryAttribute::Event),
["export"] => Attribute::Secondary(SecondaryAttribute::Export),
["deprecated", name] => {
if !name.starts_with('"') && !name.ends_with('"') {
return Err(LexerErrorKind::MalformedFuncAttribute {
Expand Down Expand Up @@ -588,6 +589,7 @@ pub enum SecondaryAttribute {
// the entry point.
ContractLibraryMethod,
Event,
Export,
Field(String),
Custom(String),
}
Expand All @@ -602,6 +604,7 @@ impl fmt::Display for SecondaryAttribute {
SecondaryAttribute::Custom(ref k) => write!(f, "#[{k}]"),
SecondaryAttribute::ContractLibraryMethod => write!(f, "#[contract_library_method]"),
SecondaryAttribute::Event => write!(f, "#[event]"),
SecondaryAttribute::Export => write!(f, "#[export]"),
SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"),
}
}
Expand All @@ -625,7 +628,7 @@ impl AsRef<str> for SecondaryAttribute {
SecondaryAttribute::Deprecated(None) => "",
SecondaryAttribute::Custom(string) | SecondaryAttribute::Field(string) => string,
SecondaryAttribute::ContractLibraryMethod => "",
SecondaryAttribute::Event => "",
SecondaryAttribute::Event | SecondaryAttribute::Export => "",
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tooling/nargo_cli/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ fn compile_contract(
(context.file_manager, Ok((optimized_contract, warnings)))
}

fn save_program(
pub(super) fn save_program(
program: CompiledProgram,
package: &Package,
circuit_dir: &Path,
Expand Down
98 changes: 98 additions & 0 deletions tooling/nargo_cli/src/cli/export_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use iter_extended::vecmap;
use nargo::artifacts::program::PreprocessedProgram;
use nargo::package::Package;
use nargo::prepare_package;
use nargo::workspace::Workspace;
use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection};
use noirc_driver::compile_no_check;
use noirc_driver::CompileOptions;
use noirc_driver::CompiledProgram;
use noirc_driver::NOIR_ARTIFACT_VERSION_STRING;
use noirc_frontend::graph::CrateName;

use clap::Args;

use crate::backends::Backend;
use crate::errors::CliError;

use super::check_cmd::check_crate_and_report_errors;

use super::fs::program::save_program_to_file;
use super::NargoConfig;

/// Compile the program and its secret execution trace into ACIR format
#[derive(Debug, Clone, Args)]
pub(crate) struct ExportCommand {
/// The name of the package to compile
#[clap(long, conflicts_with = "workspace")]
package: Option<CrateName>,

/// Compile all packages in the workspace
#[clap(long, conflicts_with = "package")]
workspace: bool,

#[clap(flatten)]
compile_options: CompileOptions,
}

pub(crate) fn run(
_backend: &Backend,
args: ExportCommand,
config: NargoConfig,
) -> Result<(), CliError> {
let toml_path = get_package_manifest(&config.program_dir)?;
let default_selection =
if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll };
let selection = args.package.map_or(default_selection, PackageSelection::Selected);

let workspace = resolve_workspace_from_toml(
&toml_path,
selection,
Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()),
)?;

let library_packages: Vec<_> =
workspace.into_iter().filter(|package| package.is_library()).collect();

compile_program(&workspace, library_packages[0], &args.compile_options)?;

Ok(())
}

fn compile_program(
workspace: &Workspace,
package: &Package,
compile_options: &CompileOptions,
) -> Result<(), CliError> {
let (mut context, crate_id) = prepare_package(package);
check_crate_and_report_errors(
&mut context,
crate_id,
compile_options.deny_warnings,
compile_options.disable_macros,
compile_options.silence_warnings,
)?;

let exported_functions = context.get_all_exported_functions_in_crate(&crate_id);

let exported_programs =
vecmap(exported_functions, |(function_name, function_id)| -> (String, CompiledProgram) {
let program = compile_no_check(&context, compile_options, function_id, None, false)
.expect("heyooo");

Check warning on line 81 in tooling/nargo_cli/src/cli/export_cmd.rs

View workflow job for this annotation

GitHub Actions / Spellcheck / Spellcheck

Unknown word (heyooo)

(function_name, program)
});

let export_dir = workspace.target_directory_path().parent().unwrap().join("export");
for (function_name, program) in exported_programs {
let preprocessed_program = PreprocessedProgram {
hash: program.hash,
abi: program.abi,
noir_version: program.noir_version,
bytecode: program.circuit,
};

save_program_to_file(&preprocessed_program, &function_name.parse().unwrap(), &export_dir);
}
Ok(())
}
4 changes: 4 additions & 0 deletions tooling/nargo_cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod codegen_verifier_cmd;
mod compile_cmd;
mod debug_cmd;
mod execute_cmd;
mod export_cmd;
mod fmt_cmd;
mod info_cmd;
mod init_cmd;
Expand Down Expand Up @@ -68,6 +69,8 @@ enum NargoCommand {
Init(init_cmd::InitCommand),
Execute(execute_cmd::ExecuteCommand),
#[command(hide = true)] // Hidden while the feature is being built out
Export(export_cmd::ExportCommand),
#[command(hide = true)] // Hidden while the feature is being built out
Debug(debug_cmd::DebugCommand),
Prove(prove_cmd::ProveCommand),
Verify(verify_cmd::VerifyCommand),
Expand Down Expand Up @@ -105,6 +108,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> {
NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config),
NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config),
NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config),
NargoCommand::Export(args) => export_cmd::run(&backend, args, config),
NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config),
NargoCommand::Verify(args) => verify_cmd::run(&backend, args, config),
NargoCommand::Test(args) => test_cmd::run(&backend, args, config),
Expand Down

0 comments on commit 4705b35

Please sign in to comment.