Skip to content

Commit e802277

Browse files
committed
WIP Add fully qualified paths for structs in ABI
1 parent 9f769ad commit e802277

File tree

11 files changed

+88
-33
lines changed

11 files changed

+88
-33
lines changed

crates/nargo_cli/src/cli/check_cmd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ mod tests {
135135
typed_param(
136136
"d",
137137
AbiType::Struct {
138-
name: String::from("MyStruct"),
138+
path: String::from("MyStruct"),
139139
fields: vec![
140140
(String::from("d1"), AbiType::Field),
141141
(

crates/nargo_cli/src/cli/test_cmd.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use nargo::{ops::execute_circuit, package::Package, prepare_package};
66
use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection};
77
use noirc_driver::{compile_no_check, CompileOptions};
88
use noirc_frontend::{
9-
graph::CrateName,
9+
graph::{CrateId, CrateName},
1010
hir::{Context, FunctionNameMatch},
1111
node_interner::FuncId,
1212
};
@@ -94,7 +94,15 @@ fn run_tests<B: Backend>(
9494
.expect("Failed to write to stdout");
9595
writer.flush().expect("Failed to flush writer");
9696

97-
match run_test(backend, &test_name, test_function, &context, show_output, compile_options) {
97+
match run_test(
98+
backend,
99+
&crate_id,
100+
&test_name,
101+
test_function,
102+
&context,
103+
show_output,
104+
compile_options,
105+
) {
98106
Ok(_) => {
99107
writer
100108
.set_color(ColorSpec::new().set_fg(Some(Color::Green)))
@@ -122,13 +130,14 @@ fn run_tests<B: Backend>(
122130

123131
fn run_test<B: Backend>(
124132
backend: &B,
133+
crate_id: &CrateId,
125134
test_name: &str,
126135
main: FuncId,
127136
context: &Context,
128137
show_output: bool,
129138
config: &CompileOptions,
130139
) -> Result<(), CliError<B>> {
131-
let mut program = compile_no_check(context, config, main).map_err(|err| {
140+
let mut program = compile_no_check(context, crate_id, config, main).map_err(|err| {
132141
noirc_errors::reporter::report_all(&context.file_manager, &[err], config.deny_warnings);
133142
CliError::Generic(format!("Test '{test_name}' failed to compile"))
134143
})?;

crates/noirc_abi/src/input_parser/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ mod serialization_tests {
133133
AbiParameter {
134134
name: "bar".into(),
135135
typ: AbiType::Struct {
136-
name: "MyStruct".into(),
136+
path: "MyStruct".into(),
137137
fields: vec![
138138
("field1".into(), AbiType::Integer { sign: Sign::Unsigned, width: 8 }),
139139
(

crates/noirc_abi/src/lib.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use acvm::{
1212
use errors::AbiError;
1313
use input_parser::InputValue;
1414
use iter_extended::{try_btree_map, try_vecmap, vecmap};
15-
use noirc_frontend::{Signedness, Type, TypeBinding, TypeVariableKind, Visibility};
15+
use noirc_frontend::{
16+
graph::CrateId, hir::Context, Signedness, Type, TypeBinding, TypeVariableKind, Visibility,
17+
};
1618
use serde::{Deserialize, Serialize};
1719
// This is the ABI used to bridge the different TOML formats for the initial
1820
// witness, the partial witness generator and the interpreter.
@@ -53,7 +55,7 @@ pub enum AbiType {
5355
},
5456
Boolean,
5557
Struct {
56-
name: String,
58+
path: String,
5759
#[serde(
5860
serialize_with = "serialization::serialize_struct_fields",
5961
deserialize_with = "serialization::deserialize_struct_fields"
@@ -117,7 +119,7 @@ pub enum Sign {
117119

118120
impl AbiType {
119121
// TODO: Add `Context` argument for resolving fully qualified struct paths
120-
pub fn from_type(typ: &Type) -> Self {
122+
pub fn from_type(context: &Context, crate_id: &CrateId, typ: &Type) -> Self {
121123
// Note; use strict_eq instead of partial_eq when comparing field types
122124
// in this method, you most likely want to distinguish between public and private
123125
match typ {
@@ -127,7 +129,7 @@ impl AbiType {
127129
.evaluate_to_u64()
128130
.expect("Cannot have variable sized arrays as a parameter to main");
129131
let typ = typ.as_ref();
130-
Self::Array { length, typ: Box::new(Self::from_type(typ)) }
132+
Self::Array { length, typ: Box::new(Self::from_type(context, crate_id, typ)) }
131133
}
132134
Type::Integer(sign, bit_width) => {
133135
let sign = match sign {
@@ -139,8 +141,10 @@ impl AbiType {
139141
}
140142
Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => {
141143
match &*binding.borrow() {
142-
TypeBinding::Bound(typ) => Self::from_type(typ),
143-
TypeBinding::Unbound(_) => Self::from_type(&Type::default_int_type()),
144+
TypeBinding::Bound(typ) => Self::from_type(context, crate_id, typ),
145+
TypeBinding::Unbound(_) => {
146+
Self::from_type(context, crate_id, &Type::default_int_type())
147+
}
144148
}
145149
}
146150
Type::Bool => Self::Boolean,
@@ -157,8 +161,10 @@ impl AbiType {
157161
Type::Struct(def, ref args) => {
158162
let struct_type = def.borrow();
159163
let fields = struct_type.get_fields(args);
160-
let fields = vecmap(fields, |(name, typ)| (name, Self::from_type(&typ)));
161-
Self::Struct { fields, name: struct_type.name.to_string() }
164+
let fields =
165+
vecmap(fields, |(name, typ)| (name, Self::from_type(context, crate_id, &typ)));
166+
let path = context.fully_qualified_struct_name(crate_id, struct_type.id);
167+
Self::Struct { fields, path }
162168
}
163169
Type::Tuple(_) => todo!("as_abi_type not yet implemented for tuple types"),
164170
Type::TypeVariable(_, _) => unreachable!(),

crates/noirc_abi/src/serialization.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ mod tests {
8888
let deserialized_array: AbiParameter = serde_json::from_str(serialized_array).unwrap();
8989
assert_eq!(deserialized_array, expected_array);
9090

91-
let serialized_struct = "{
91+
let serialized_struct = "{
9292
\"name\":\"thing3\",
9393
\"type\": {
9494
\"kind\":\"struct\",
95-
\"name\": \"MyStruct\",
95+
\"path\": \"MyStruct\",
9696
\"fields\": [
9797
{
9898
\"name\": \"field1\",
@@ -120,7 +120,7 @@ mod tests {
120120
let expected_struct = AbiParameter {
121121
name: "thing3".to_string(),
122122
typ: AbiType::Struct {
123-
name: "MyStruct".to_string(),
123+
path: "MyStruct".to_string(),
124124
fields: vec![
125125
("field1".to_string(), AbiType::Integer { sign: Sign::Unsigned, width: 3 }),
126126
(

crates/noirc_driver/src/lib.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ pub fn compute_function_abi(
134134
let func_meta = context.def_interner.function_meta(&main_function);
135135

136136
let (parameters, return_type) = func_meta.into_function_signature();
137-
let parameters = into_abi_params(parameters, &context.def_interner);
138-
let return_type = return_type.map(|typ| AbiType::from_type(&typ));
137+
let parameters = into_abi_params(context, crate_id, parameters);
138+
let return_type = return_type.map(|typ| AbiType::from_type(context, crate_id, &typ));
139139
Some((parameters, return_type))
140140
}
141141

@@ -162,7 +162,7 @@ pub fn compile_main(
162162
}
163163
};
164164

165-
let compiled_program = compile_no_check(context, options, main)?;
165+
let compiled_program = compile_no_check(context, &crate_id, options, main)?;
166166

167167
if options.print_acir {
168168
println!("Compiled ACIR for main (unoptimized):");
@@ -186,7 +186,7 @@ pub fn compile_contracts(
186186
let mut errors = warnings;
187187

188188
for contract in contracts {
189-
match compile_contract(context, contract, options) {
189+
match compile_contract(context, &crate_id, contract, options) {
190190
Ok(contract) => compiled_contracts.push(contract),
191191
Err(mut more_errors) => errors.append(&mut more_errors),
192192
}
@@ -223,14 +223,15 @@ fn has_errors(errors: &[FileDiagnostic], deny_warnings: bool) -> bool {
223223
/// Compile all of the functions associated with a Noir contract.
224224
fn compile_contract(
225225
context: &Context,
226+
crate_id: &CrateId,
226227
contract: Contract,
227228
options: &CompileOptions,
228229
) -> Result<CompiledContract, Vec<FileDiagnostic>> {
229230
let mut functions = Vec::new();
230231
let mut errors = Vec::new();
231232
for function_id in &contract.functions {
232233
let name = context.function_name(function_id).to_owned();
233-
let function = match compile_no_check(context, options, *function_id) {
234+
let function = match compile_no_check(context, crate_id, options, *function_id) {
234235
Ok(function) => function,
235236
Err(new_error) => {
236237
errors.push(new_error);
@@ -268,13 +269,14 @@ fn compile_contract(
268269
#[allow(deprecated)]
269270
pub fn compile_no_check(
270271
context: &Context,
272+
crate_id: &CrateId,
271273
options: &CompileOptions,
272274
main_function: FuncId,
273275
) -> Result<CompiledProgram, FileDiagnostic> {
274276
let program = monomorphize(main_function, &context.def_interner);
275277

276278
let (circuit, debug, abi) =
277-
create_circuit(context, program, options.show_ssa, options.show_brillig)?;
279+
create_circuit(context, crate_id, program, options.show_ssa, options.show_brillig)?;
278280

279281
Ok(CompiledProgram { circuit, debug, abi })
280282
}

crates/noirc_evaluator/src/ssa.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use noirc_errors::debug_info::DebugInfo;
1919

2020
use noirc_abi::Abi;
2121

22-
use noirc_frontend::{hir::Context, monomorphization::ast::Program};
22+
use noirc_frontend::{graph::CrateId, hir::Context, monomorphization::ast::Program};
2323

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

@@ -82,6 +82,7 @@ pub(crate) fn optimize_into_acir(
8282
/// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation.
8383
pub fn create_circuit(
8484
context: &Context,
85+
crate_id: &CrateId,
8586
program: Program,
8687
enable_ssa_logging: bool,
8788
enable_brillig_logging: bool,
@@ -96,7 +97,7 @@ pub fn create_circuit(
9697
..
9798
} = optimize_into_acir(program, enable_ssa_logging, enable_brillig_logging)?;
9899

99-
let abi = gen_abi(&context.def_interner, func_sig, &input_witnesses, return_witnesses.clone());
100+
let abi = gen_abi(context, crate_id, func_sig, &input_witnesses, return_witnesses.clone());
100101
let public_abi = abi.clone().public_abi();
101102

102103
let public_parameters =

crates/noirc_evaluator/src/ssa/abi_gen/mod.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use acvm::acir::native_types::Witness;
44
use iter_extended::{btree_map, vecmap};
55
use noirc_abi::{Abi, AbiParameter, AbiType};
66
use noirc_frontend::{
7+
graph::CrateId,
8+
hir::Context,
79
hir_def::{
810
function::{FunctionSignature, Param},
911
stmt::HirPattern,
@@ -22,27 +24,32 @@ fn get_param_name<'a>(pattern: &HirPattern, interner: &'a NodeInterner) -> Optio
2224
}
2325
}
2426

25-
pub fn into_abi_params(params: Vec<Param>, interner: &NodeInterner) -> Vec<AbiParameter> {
27+
pub fn into_abi_params(
28+
context: &Context,
29+
crate_id: &CrateId,
30+
params: Vec<Param>,
31+
) -> Vec<AbiParameter> {
2632
vecmap(params, |(pattern, typ, vis)| {
27-
let param_name = get_param_name(&pattern, interner)
33+
let param_name = get_param_name(&pattern, &context.def_interner)
2834
.expect("Abi for tuple and struct parameters is unimplemented")
2935
.to_owned();
30-
let as_abi = AbiType::from_type(&typ);
36+
let as_abi = AbiType::from_type(context, crate_id, &typ);
3137
AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() }
3238
})
3339
}
3440

3541
/// Arranges a function signature and a generated circuit's return witnesses into a
3642
/// `noirc_abi::Abi`.
3743
pub(crate) fn gen_abi(
38-
interner: &NodeInterner,
44+
context: &Context,
45+
crate_id: &CrateId,
3946
func_sig: FunctionSignature,
4047
input_witnesses: &[Witness],
4148
return_witnesses: Vec<Witness>,
4249
) -> Abi {
4350
let (parameters, return_type) = func_sig;
44-
let parameters = into_abi_params(parameters, interner);
45-
let return_type = return_type.map(|typ| AbiType::from_type(&typ));
51+
let parameters = into_abi_params(context, crate_id, parameters);
52+
let return_type = return_type.map(|typ| AbiType::from_type(context, crate_id, &typ));
4653
let param_witnesses = param_witnesses_from_abi_param(&parameters, input_witnesses);
4754
Abi { parameters, return_type, param_witnesses, return_witnesses }
4855
}

crates/noirc_frontend/src/graph/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,12 @@ impl std::ops::Index<CrateId> for CrateGraph {
225225
&self.arena[&crate_id]
226226
}
227227
}
228+
impl std::ops::Index<&CrateId> for CrateGraph {
229+
type Output = CrateData;
230+
fn index(&self, crate_id: &CrateId) -> &CrateData {
231+
&self.arena[crate_id]
232+
}
233+
}
228234

229235
/// XXX: This is bare-bone for two reasons:
230236
// There are no display names currently

crates/noirc_frontend/src/hir/mod.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ pub mod resolution;
44
pub mod scope;
55
pub mod type_check;
66

7-
use crate::graph::{CrateGraph, CrateId};
7+
use crate::graph::{CrateGraph, CrateId, Dependency};
88
use crate::hir_def::function::FuncMeta;
9-
use crate::node_interner::{FuncId, NodeInterner};
9+
use crate::node_interner::{FuncId, NodeInterner, StructId};
1010
use def_map::{Contract, CrateDefMap};
1111
use fm::FileManager;
1212
use std::collections::HashMap;
@@ -82,6 +82,29 @@ impl Context {
8282
}
8383
}
8484

85+
// TODO: This still feels hacky, need to fix
86+
pub fn fully_qualified_struct_name(&self, crate_id: &CrateId, id: StructId) -> String {
87+
let module_id = id.0;
88+
let child_id = module_id.local_id.0;
89+
let def_map =
90+
self.def_map(&module_id.krate).expect("The local crate should be analyzed already");
91+
92+
let module = self.module(module_id);
93+
94+
let crate_name = &self.crate_graph[crate_id]
95+
.dependencies
96+
.iter()
97+
.find_map(|dep| match dep {
98+
Dependency { name, crate_id } if crate_id == &module_id.krate => Some(name),
99+
_ => None,
100+
})
101+
.unwrap();
102+
103+
let module_path = def_map.get_module_path_with_separator(child_id, module.parent, "::");
104+
105+
format!("{crate_name}::{module_path}")
106+
}
107+
85108
pub fn function_meta(&self, func_id: &FuncId) -> FuncMeta {
86109
self.def_interner.function_meta(func_id)
87110
}

crates/wasm/src/compile.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ pub fn compile(args: JsValue) -> JsValue {
105105
} else {
106106
let main = context.get_main_function(&crate_id).expect("Could not find main function!");
107107
let mut compiled_program =
108-
compile_no_check(&context, &options.compile_options, main).expect("Compilation failed");
108+
compile_no_check(&context, &crate_id, &options.compile_options, main)
109+
.expect("Compilation failed");
109110

110111
compiled_program.circuit = optimize_circuit(compiled_program.circuit);
111112

0 commit comments

Comments
 (0)