mirror of
https://github.com/AleoHQ/leo.git
synced 2024-09-21 03:57:39 +03:00
Add complex finalization multi-program example; regen expectations
This commit is contained in:
parent
4c750bc963
commit
058d3bf79a
@ -336,7 +336,7 @@ impl<'a> Compiler<'a> {
|
||||
}
|
||||
|
||||
/// Merges the dependencies defined in `program.json` with the dependencies imported in `.leo` file
|
||||
fn add_import_stubs(&mut self) -> Result<()> {
|
||||
pub fn add_import_stubs(&mut self) -> Result<()> {
|
||||
// Create a list of both the explicit dependencies specified in the `.leo` file, as well as the implicit ones derived from those dependencies.
|
||||
let (mut unexplored, mut explored): (IndexSet<Symbol>, IndexSet<Symbol>) =
|
||||
(self.ast.ast.imports.keys().cloned().collect(), IndexSet::new());
|
||||
|
@ -42,6 +42,7 @@ use snarkvm::console::prelude::*;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use leo_span::Symbol;
|
||||
use regex::Regex;
|
||||
use serde_yaml::Value;
|
||||
use snarkvm::{prelude::Process, synthesizer::program::ProgramCore};
|
||||
use std::{fs, path::Path, rc::Rc};
|
||||
@ -112,8 +113,12 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
|
||||
// Compile each program string separately.
|
||||
for program_string in program_strings {
|
||||
// Parse the program name from the program string.
|
||||
let re = Regex::new(r"program\s+([^\s.]+)\.aleo").unwrap();
|
||||
let program_name = re.captures(program_string).unwrap().get(1).unwrap().as_str();
|
||||
// Parse the program.
|
||||
let mut parsed = handler.extend_if_error(parse_program(
|
||||
program_name.to_string(),
|
||||
handler,
|
||||
program_string,
|
||||
cwd.clone(),
|
||||
@ -139,10 +144,11 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
|
||||
// Hash the ast files.
|
||||
let (initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast) =
|
||||
hash_asts();
|
||||
hash_asts(&program_name);
|
||||
|
||||
// Hash the symbol tables.
|
||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) = hash_symbol_tables();
|
||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) =
|
||||
hash_symbol_tables(&program_name);
|
||||
|
||||
// Clean up the output directory.
|
||||
if fs::read_dir("/tmp/output").is_ok() {
|
||||
|
@ -47,6 +47,7 @@ use disassembler::disassemble_from_str;
|
||||
use indexmap::IndexMap;
|
||||
use leo_errors::LeoError;
|
||||
use leo_span::Symbol;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_yaml::Value;
|
||||
use snarkvm::{
|
||||
@ -143,8 +144,13 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
|
||||
// Compile each program string separately.
|
||||
for program_string in program_strings {
|
||||
// Parse the program name from the program string.
|
||||
let re = Regex::new(r"program\s+([^\s.]+)\.aleo").unwrap();
|
||||
let program_name = re.captures(program_string).unwrap().get(1).unwrap().as_str();
|
||||
|
||||
// Parse the program.
|
||||
let mut parsed = handler.extend_if_error(parse_program(
|
||||
program_name.to_string(),
|
||||
handler,
|
||||
program_string,
|
||||
cwd.clone(),
|
||||
@ -178,10 +184,11 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
|
||||
// Hash the ast files.
|
||||
let (initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast) =
|
||||
hash_asts();
|
||||
hash_asts(&program_name);
|
||||
|
||||
// Hash the symbol tables.
|
||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) = hash_symbol_tables();
|
||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) =
|
||||
hash_symbol_tables(&program_name);
|
||||
|
||||
// Clean up the output directory.
|
||||
if fs::read_dir("/tmp/output").is_ok() {
|
||||
@ -243,7 +250,7 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
// Initialize the statuses of execution.
|
||||
let mut execution = None;
|
||||
let mut verified = false;
|
||||
let mut status = "None";
|
||||
let mut status = "none";
|
||||
|
||||
// Execute the program, construct a block and add it to the ledger.
|
||||
let result = std::panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
@ -264,10 +271,10 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
})
|
||||
.and_then(|block| {
|
||||
status = match block.aborted_transaction_ids().is_empty() {
|
||||
false => "Aborted",
|
||||
false => "aborted",
|
||||
true => match block.transactions().num_accepted() == 1 {
|
||||
true => "Accepted",
|
||||
false => "Rejected",
|
||||
true => "accepted",
|
||||
false => "rejected",
|
||||
},
|
||||
};
|
||||
ledger.advance_to_next_block(&block)
|
||||
|
@ -49,22 +49,23 @@ pub type CurrentNetwork = Testnet3;
|
||||
#[allow(unused)]
|
||||
pub type CurrentAleo = snarkvm::circuit::AleoV0;
|
||||
|
||||
pub fn hash_asts() -> (String, String, String, String, String, String, String) {
|
||||
let initial_ast = hash_file("/tmp/output/test.initial_ast.json");
|
||||
let unrolled_ast = hash_file("/tmp/output/test.unrolled_ast.json");
|
||||
let ssa_ast = hash_file("/tmp/output/test.ssa_ast.json");
|
||||
let flattened_ast = hash_file("/tmp/output/test.flattened_ast.json");
|
||||
let destructured_ast = hash_file("/tmp/output/test.destructured_ast.json");
|
||||
let inlined_ast = hash_file("/tmp/output/test.inlined_ast.json");
|
||||
let dce_ast = hash_file("/tmp/output/test.dce_ast.json");
|
||||
pub fn hash_asts(program_name: &str) -> (String, String, String, String, String, String, String) {
|
||||
let initial_ast = hash_file(&format!("/tmp/output/{program_name}.initial_ast.json"));
|
||||
let unrolled_ast = hash_file(&format!("/tmp/output/{program_name}.unrolled_ast.json"));
|
||||
let ssa_ast = hash_file(&format!("/tmp/output/{program_name}.ssa_ast.json"));
|
||||
let flattened_ast = hash_file(&format!("/tmp/output/{program_name}.flattened_ast.json"));
|
||||
let destructured_ast = hash_file(&format!("/tmp/output/{program_name}.destructured_ast.json"));
|
||||
let inlined_ast = hash_file(&format!("/tmp/output/{program_name}.inlined_ast.json"));
|
||||
let dce_ast = hash_file(&format!("/tmp/output/{program_name}.dce_ast.json"));
|
||||
|
||||
(initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast)
|
||||
}
|
||||
|
||||
pub fn hash_symbol_tables() -> (String, String, String) {
|
||||
let initial_symbol_table = hash_file("/tmp/output/test.initial_symbol_table.json");
|
||||
let type_checked_symbol_table = hash_file("/tmp/output/test.type_checked_symbol_table.json");
|
||||
let unrolled_symbol_table = hash_file("/tmp/output/test.unrolled_symbol_table.json");
|
||||
pub fn hash_symbol_tables(program_name: &str) -> (String, String, String) {
|
||||
let initial_symbol_table = hash_file(&format!("/tmp/output/{program_name}.initial_symbol_table.json"));
|
||||
let type_checked_symbol_table = hash_file(&format!("/tmp/output/{program_name}.type_checked_symbol_table.json"));
|
||||
let unrolled_symbol_table = hash_file(&format!("/tmp/output/{program_name}.unrolled_symbol_table.json"));
|
||||
|
||||
(initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table)
|
||||
}
|
||||
|
||||
@ -144,6 +145,7 @@ pub fn setup_build_directory(
|
||||
}
|
||||
|
||||
pub fn new_compiler(
|
||||
program_name: String,
|
||||
handler: &Handler,
|
||||
main_file_path: PathBuf,
|
||||
compiler_options: Option<CompilerOptions>,
|
||||
@ -153,7 +155,7 @@ pub fn new_compiler(
|
||||
fs::create_dir_all(output_dir.clone()).unwrap();
|
||||
|
||||
Compiler::new(
|
||||
String::from("test"),
|
||||
program_name,
|
||||
String::from("aleo"),
|
||||
handler,
|
||||
main_file_path,
|
||||
@ -164,14 +166,20 @@ pub fn new_compiler(
|
||||
}
|
||||
|
||||
pub fn parse_program<'a>(
|
||||
program_name: String,
|
||||
handler: &'a Handler,
|
||||
program_string: &str,
|
||||
cwd: Option<PathBuf>,
|
||||
compiler_options: Option<CompilerOptions>,
|
||||
import_stubs: IndexMap<Symbol, Stub>,
|
||||
) -> Result<Compiler<'a>, LeoError> {
|
||||
let mut compiler =
|
||||
new_compiler(handler, cwd.clone().unwrap_or_else(|| "compiler-test".into()), compiler_options, import_stubs);
|
||||
let mut compiler = new_compiler(
|
||||
program_name,
|
||||
handler,
|
||||
cwd.clone().unwrap_or_else(|| "compiler-test".into()),
|
||||
compiler_options,
|
||||
import_stubs,
|
||||
);
|
||||
let name = cwd.map_or_else(|| FileName::Custom("compiler-test".into()), FileName::Real);
|
||||
compiler.parse_program_from_string(program_string, name)?;
|
||||
|
||||
@ -242,6 +250,8 @@ pub fn temp_dir() -> PathBuf {
|
||||
}
|
||||
|
||||
pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>) -> Result<String, LeoError> {
|
||||
parsed.add_import_stubs()?;
|
||||
|
||||
let st = parsed.symbol_table_pass()?;
|
||||
|
||||
CheckUniqueNodeIds::new().visit_program(&parsed.ast.ast);
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
76
tests/expectations/execution/complex_finalization.out
Normal file
76
tests/expectations/execution/complex_finalization.out
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
130
tests/tests/execution/complex_finalization.leo
Normal file
130
tests/tests/execution/complex_finalization.leo
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
namespace: Execute
|
||||
expectation: Pass
|
||||
cases:
|
||||
- program: four_program.aleo
|
||||
function: a
|
||||
input: []
|
||||
*/
|
||||
|
||||
// This test checks that the finalization order is correct.
|
||||
// The functions are invoked in the following order:
|
||||
// "four::a"
|
||||
// --> "two::b"
|
||||
// --> "zero::c"
|
||||
// --> "one::d"
|
||||
// --> "three::e"
|
||||
// --> "two::b"
|
||||
// --> "zero::c"
|
||||
// --> "one::d"
|
||||
// --> "one::d"
|
||||
// --> "zero::c"
|
||||
// The future (call graph) produced by the top-level finalize should reflect this structure.
|
||||
|
||||
program zero_program.aleo {
|
||||
|
||||
mapping counts: address => u64;
|
||||
|
||||
transition c() {
|
||||
return then finalize(self.signer);
|
||||
}
|
||||
|
||||
finalize c(addr: address) {
|
||||
let count: u64 = counts.get_or_use(addr, 0u64);
|
||||
counts.set(addr, count + 1u64);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
|
||||
program one_program.aleo {
|
||||
|
||||
mapping counts: address => u64;
|
||||
|
||||
transition d() {
|
||||
return then finalize(self.signer);
|
||||
}
|
||||
|
||||
finalize d(addr: address) {
|
||||
let count: u64 = counts.get_or_use(addr, 0u64);
|
||||
counts.set(addr, count + 1u64);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
|
||||
import zero_program.aleo;
|
||||
import one_program.aleo;
|
||||
|
||||
program two_program.aleo {
|
||||
|
||||
mapping counts: address => u64;
|
||||
|
||||
transition b() {
|
||||
zero_program.aleo/c();
|
||||
one_program.aleo/d();
|
||||
return then finalize(self.signer);
|
||||
}
|
||||
|
||||
finalize b(addr: address) {
|
||||
let count: u64 = counts.get_or_use(addr, 0u64);
|
||||
counts.set(addr, count + 1u64);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
|
||||
import zero_program.aleo;
|
||||
import one_program.aleo;
|
||||
import two_program.aleo;
|
||||
|
||||
program three_program.aleo {
|
||||
|
||||
mapping counts: address => u64;
|
||||
|
||||
transition e() {
|
||||
two_program.aleo/b();
|
||||
one_program.aleo/d();
|
||||
zero_program.aleo/c();
|
||||
return then finalize(self.signer);
|
||||
}
|
||||
|
||||
finalize e(addr: address) {
|
||||
let count: u64 = counts.get_or_use(addr, 0u64);
|
||||
counts.set(addr, count + 1u64);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
|
||||
import two_program.aleo;
|
||||
import three_program.aleo;
|
||||
|
||||
program four_program.aleo {
|
||||
|
||||
mapping counts: address => u64;
|
||||
|
||||
transition a() {
|
||||
two_program.aleo/b();
|
||||
three_program.aleo/e();
|
||||
return then finalize(self.signer);
|
||||
}
|
||||
|
||||
finalize a(addr: address) {
|
||||
let count: u64 = counts.get_or_use(addr, 0u64);
|
||||
counts.set(addr, count + 1u64);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user