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: Remove noirc_abi::FunctionSignature and define in terms of HIR #2372

Merged
merged 2 commits into from
Aug 21, 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
4 changes: 2 additions & 2 deletions crates/nargo_cli/src/cli/check_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use iter_extended::btree_map;
use nargo::{package::Package, prepare_package};
use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection};
use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME};
use noirc_driver::{check_crate, compute_function_signature, CompileOptions};
use noirc_driver::{check_crate, compute_function_abi, CompileOptions};
use noirc_frontend::{
graph::{CrateId, CrateName},
hir::Context,
Expand Down Expand Up @@ -56,7 +56,7 @@ fn check_package(package: &Package, compile_options: &CompileOptions) -> Result<
Ok(())
} else {
// XXX: We can have a --overwrite flag to determine if you want to overwrite the Prover/Verifier.toml files
if let Some((parameters, return_type)) = compute_function_signature(&context, &crate_id) {
if let Some((parameters, return_type)) = compute_function_abi(&context, &crate_id) {
let path_to_prover_input = package.prover_input_path();
let path_to_verifier_input = package.verifier_input_path();

Expand Down
3 changes: 0 additions & 3 deletions crates/noirc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ mod serialization;
/// A map from the fields in an TOML/JSON file which correspond to some ABI to their values
pub type InputMap = BTreeMap<String, InputValue>;

/// A tuple of the arguments to a function along with its return value.
pub type FunctionSignature = (Vec<AbiParameter>, Option<AbiType>);

pub const MAIN_RETURN_NAME: &str = "return";

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand Down
16 changes: 10 additions & 6 deletions crates/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

use clap::Args;
use fm::FileId;
use noirc_abi::FunctionSignature;
use noirc_abi::{AbiParameter, AbiType};
use noirc_errors::{CustomDiagnostic, FileDiagnostic};
use noirc_evaluator::create_circuit;
use noirc_evaluator::{create_circuit, into_abi_params};
use noirc_frontend::graph::{CrateId, CrateName};
use noirc_frontend::hir::def_map::{Contract, CrateDefMap};
use noirc_frontend::hir::Context;
Expand Down Expand Up @@ -125,15 +125,18 @@ pub fn check_crate(
}
}

pub fn compute_function_signature(
pub fn compute_function_abi(
context: &Context,
crate_id: &CrateId,
) -> Option<FunctionSignature> {
) -> Option<(Vec<AbiParameter>, Option<AbiType>)> {
let main_function = context.get_main_function(crate_id)?;

let func_meta = context.def_interner.function_meta(&main_function);

Some(func_meta.into_function_signature(&context.def_interner))
let (parameters, return_type) = func_meta.into_function_signature();
let parameters = into_abi_params(parameters, &context.def_interner);
let return_type = return_type.map(|typ| typ.as_abi_type());
Some((parameters, return_type))
}

/// Run the frontend to check the crate for errors then compile the main function if there were none
Expand Down Expand Up @@ -270,7 +273,8 @@ pub fn compile_no_check(
) -> Result<CompiledProgram, FileDiagnostic> {
let program = monomorphize(main_function, &context.def_interner);

let (circuit, debug, abi) = create_circuit(program, options.show_ssa, options.show_brillig)?;
let (circuit, debug, abi) =
create_circuit(context, program, options.show_ssa, options.show_brillig)?;

Ok(CompiledProgram { circuit, debug, abi })
}
1 change: 1 addition & 0 deletions crates/noirc_evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ pub mod ssa;

pub mod brillig;

pub use ssa::abi_gen::into_abi_params;
pub use ssa::create_circuit;
7 changes: 4 additions & 3 deletions crates/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ use noirc_errors::debug_info::DebugInfo;

use noirc_abi::Abi;

use noirc_frontend::monomorphization::ast::Program;
use noirc_frontend::{hir::Context, monomorphization::ast::Program};

use self::{abi_gen::gen_abi, acir_gen::GeneratedAcir, ir::function::RuntimeType, ssa_gen::Ssa};

mod abi_gen;
pub mod abi_gen;
mod acir_gen;
pub mod ir;
mod opt;
Expand Down Expand Up @@ -81,6 +81,7 @@ pub(crate) fn optimize_into_acir(
///
/// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation.
pub fn create_circuit(
context: &Context,
program: Program,
enable_ssa_logging: bool,
enable_brillig_logging: bool,
Expand All @@ -95,7 +96,7 @@ pub fn create_circuit(
..
} = optimize_into_acir(program, enable_ssa_logging, enable_brillig_logging)?;

let abi = gen_abi(func_sig, &input_witnesses, return_witnesses.clone());
let abi = gen_abi(&context.def_interner, func_sig, &input_witnesses, return_witnesses.clone());
let public_abi = abi.clone().public_abi();

let public_parameters =
Expand Down
35 changes: 33 additions & 2 deletions crates/noirc_evaluator/src/ssa/abi_gen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
use std::collections::BTreeMap;

use acvm::acir::native_types::Witness;
use iter_extended::btree_map;
use noirc_abi::{Abi, AbiParameter, FunctionSignature};
use iter_extended::{btree_map, vecmap};
use noirc_abi::{Abi, AbiParameter};
use noirc_frontend::{
hir_def::{
function::{FunctionSignature, Param},
stmt::HirPattern,
},
node_interner::NodeInterner,
};

/// Attempts to retrieve the name of this parameter. Returns None
/// if this parameter is a tuple or struct pattern.
fn get_param_name<'a>(pattern: &HirPattern, interner: &'a NodeInterner) -> Option<&'a str> {
match pattern {
HirPattern::Identifier(ident) => Some(interner.definition_name(ident.id)),
HirPattern::Mutable(pattern, _) => get_param_name(pattern, interner),
HirPattern::Tuple(_, _) => None,
HirPattern::Struct(_, _, _) => None,
}
}

pub fn into_abi_params(params: Vec<Param>, interner: &NodeInterner) -> Vec<AbiParameter> {
vecmap(params, |(pattern, typ, vis)| {
let param_name = get_param_name(&pattern, interner)
.expect("Abi for tuple and struct parameters is unimplemented")
.to_owned();
let as_abi = typ.as_abi_type();
AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() }
})
}

/// Arranges a function signature and a generated circuit's return witnesses into a
/// `noirc_abi::Abi`.
pub(crate) fn gen_abi(
interner: &NodeInterner,
func_sig: FunctionSignature,
input_witnesses: &[Witness],
return_witnesses: Vec<Witness>,
) -> Abi {
let (parameters, return_type) = func_sig;
let parameters = into_abi_params(parameters, interner);
let return_type = return_type.map(|typ| typ.as_abi_type());
let param_witnesses = param_witnesses_from_abi_param(&parameters, input_witnesses);
Abi { parameters, return_type, param_witnesses, return_witnesses }
}
Expand Down
4 changes: 2 additions & 2 deletions crates/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use crate::hir::scope::{
Scope as GenericScope, ScopeForest as GenericScopeForest, ScopeTree as GenericScopeTree,
};
use crate::hir_def::{
function::{FuncMeta, HirFunction, Param},
function::{FuncMeta, HirFunction},
stmt::{HirConstrainStatement, HirLetStatement, HirStatement},
};

Expand Down Expand Up @@ -671,7 +671,7 @@ impl<'a> Resolver<'a> {
let pattern = self.resolve_pattern(pattern, DefinitionKind::Local(None));
let typ = self.resolve_type_inner(typ, &mut generics);

parameters.push(Param(pattern, typ.clone(), visibility));
parameters.push((pattern, typ.clone(), visibility));
parameter_types.push(typ);
}

Expand Down
6 changes: 3 additions & 3 deletions crates/noirc_frontend/src/hir/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ mod test {
use crate::hir_def::types::Type;
use crate::hir_def::{
expr::{HirBinaryOp, HirBlockExpression, HirExpression, HirInfixExpression},
function::{FuncMeta, HirFunction, Param},
function::{FuncMeta, HirFunction},
stmt::HirStatement,
};
use crate::node_interner::{DefinitionKind, FuncId, NodeInterner};
Expand Down Expand Up @@ -268,8 +268,8 @@ mod test {
Box::new(Type::Unit),
),
parameters: vec![
Param(Identifier(x), Type::FieldElement, Visibility::Private),
Param(Identifier(y), Type::FieldElement, Visibility::Private),
(Identifier(x), Type::FieldElement, Visibility::Private),
(Identifier(y), Type::FieldElement, Visibility::Private),
]
.into(),
return_visibility: Visibility::Private,
Expand Down
49 changes: 16 additions & 33 deletions crates/noirc_frontend/src/hir_def/function.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use iter_extended::vecmap;
use noirc_abi::{AbiParameter, AbiType};
use noirc_errors::{Location, Span};

use super::expr::{HirBlockExpression, HirExpression, HirIdent};
Expand Down Expand Up @@ -36,34 +35,12 @@ impl HirFunction {
}

/// An interned function parameter from a function definition
#[derive(Debug, Clone)]
pub struct Param(pub HirPattern, pub Type, pub Visibility);

/// Attempts to retrieve the name of this parameter. Returns None
/// if this parameter is a tuple or struct pattern.
fn get_param_name<'a>(pattern: &HirPattern, interner: &'a NodeInterner) -> Option<&'a str> {
match pattern {
HirPattern::Identifier(ident) => Some(interner.definition_name(ident.id)),
HirPattern::Mutable(pattern, _) => get_param_name(pattern, interner),
HirPattern::Tuple(_, _) => None,
HirPattern::Struct(_, _, _) => None,
}
}
pub type Param = (HirPattern, Type, Visibility);

#[derive(Debug, Clone)]
pub struct Parameters(pub Vec<Param>);

impl Parameters {
fn into_abi_params(self, interner: &NodeInterner) -> Vec<AbiParameter> {
vecmap(self.0, |param| {
let param_name = get_param_name(&param.0, interner)
.expect("Abi for tuple and struct parameters is unimplemented")
.to_owned();
let as_abi = param.1.as_abi_type();
AbiParameter { name: param_name, typ: as_abi, visibility: param.2.into() }
})
}

pub fn span(&self) -> Span {
assert!(!self.is_empty());
let mut spans = vecmap(&self.0, |param| match &param.0 {
Expand Down Expand Up @@ -108,6 +85,8 @@ impl From<Vec<Param>> for Parameters {
}
}

pub type FunctionSignature = (Vec<Param>, Option<Type>);

/// A FuncMeta contains the signature of the function and any associated meta data like
/// the function's Location, FunctionKind, and attributes. If the function's body is
/// needed, it can be retrieved separately via `NodeInterner::function(&self, &FuncId)`.
Expand Down Expand Up @@ -165,18 +144,22 @@ impl FuncMeta {
}
}

pub fn into_function_signature(
self,
interner: &NodeInterner,
) -> (Vec<AbiParameter>, Option<AbiType>) {
let return_type = match self.return_type() {
pub fn into_function_signature(self) -> FunctionSignature {
// Doesn't use `self.return_type()` so we aren't working with references and don't need a `clone()`
let return_type = match self.typ {
Type::Function(_, ret, _env) => *ret,
Type::Forall(_, typ) => match *typ {
Type::Function(_, ret, _env) => *ret,
_ => unreachable!(),
},
_ => unreachable!(),
};
let return_type = match return_type {
Type::Unit => None,
typ => Some(typ.as_abi_type()),
typ => Some(typ),
};

let params = self.parameters.into_abi_params(interner);

(params, return_type)
(self.parameters.0, return_type)
}

/// Gives the (uninstantiated) return type of this function.
Expand Down
3 changes: 1 addition & 2 deletions crates/noirc_frontend/src/monomorphization/ast.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use acvm::FieldElement;
use iter_extended::vecmap;
use noirc_abi::FunctionSignature;
use noirc_errors::Location;

use crate::{BinaryOpKind, Distinctness, Signedness};
use crate::{hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, Signedness};

/// The monomorphized AST is expression-based, all statements are also
/// folded into this expression enum. Compared to the HIR, the monomorphized
Expand Down
15 changes: 6 additions & 9 deletions crates/noirc_frontend/src/monomorphization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
//! function, will monomorphize the entire reachable program.
use acvm::FieldElement;
use iter_extended::{btree_map, vecmap};
use noirc_abi::FunctionSignature;
use std::collections::{BTreeMap, HashMap, VecDeque};

use crate::{
hir_def::{
expr::*,
function::{FuncMeta, Param, Parameters},
function::{FuncMeta, FunctionSignature, Parameters},
stmt::{HirAssignStatement, HirLValue, HirLetStatement, HirPattern, HirStatement},
types,
},
Expand Down Expand Up @@ -190,7 +189,7 @@ impl<'interner> Monomorphizer<'interner> {
self.function(main_id, new_main_id);

let main_meta = self.interner.function_meta(&main_id);
main_meta.into_function_signature(self.interner)
main_meta.into_function_signature()
}

fn function(&mut self, f: node_interner::FuncId, id: FuncId) {
Expand Down Expand Up @@ -1025,9 +1024,8 @@ impl<'interner> Monomorphizer<'interner> {
let parameter_types = vecmap(&lambda.parameters, |(_, typ)| Self::convert_type(typ));

// Manually convert to Parameters type so we can reuse the self.parameters method
let parameters = Parameters(vecmap(lambda.parameters, |(pattern, typ)| {
Param(pattern, typ, Visibility::Private)
}));
let parameters =
vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into();

let parameters = self.parameters(parameters);
let body = self.expr(lambda.body);
Expand Down Expand Up @@ -1077,9 +1075,8 @@ impl<'interner> Monomorphizer<'interner> {
let parameter_types = vecmap(&lambda.parameters, |(_, typ)| Self::convert_type(typ));

// Manually convert to Parameters type so we can reuse the self.parameters method
let parameters = Parameters(vecmap(lambda.parameters, |(pattern, typ)| {
Param(pattern, typ, Visibility::Private)
}));
let parameters =
vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into();

let mut converted_parameters = self.parameters(parameters);

Expand Down