mirror of
https://github.com/AleoHQ/leo.git
synced 2024-09-11 15:05:33 +03:00
Add support for multi-file compile tests
This commit is contained in:
parent
8456096ac8
commit
f4af8a77d2
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1459,6 +1459,7 @@ dependencies = [
|
|||||||
name = "leo-compiler"
|
name = "leo-compiler"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"disassembler",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"leo-ast",
|
"leo-ast",
|
||||||
|
@ -45,6 +45,9 @@ version = "0.10"
|
|||||||
version = "1.9"
|
version = "1.9"
|
||||||
features = []
|
features = []
|
||||||
|
|
||||||
|
[dev-dependencies.disassembler]
|
||||||
|
path = "../../utils/disassembler"
|
||||||
|
|
||||||
[dev-dependencies.leo-test-framework]
|
[dev-dependencies.leo-test-framework]
|
||||||
path = "../../tests/test-framework"
|
path = "../../tests/test-framework"
|
||||||
|
|
||||||
@ -76,4 +79,4 @@ version = "3.10"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ ]
|
default = [ ]
|
||||||
ci_skip = [ "leo-ast/ci_skip" ]
|
ci_skip = [ "leo-ast/ci_skip" ]
|
||||||
|
@ -27,16 +27,20 @@ use utilities::{
|
|||||||
BufferEmitter,
|
BufferEmitter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use disassembler::disassemble_from_str;
|
||||||
use leo_compiler::{CompilerOptions, OutputOptions};
|
use leo_compiler::{CompilerOptions, OutputOptions};
|
||||||
use leo_errors::{emitter::Handler, LeoError};
|
use leo_errors::{emitter::Handler, LeoError};
|
||||||
use leo_span::symbol::create_session_if_not_set_then;
|
use leo_span::symbol::create_session_if_not_set_then;
|
||||||
use leo_test_framework::{
|
use leo_test_framework::{
|
||||||
runner::{Namespace, ParseType, Runner},
|
runner::{Namespace, ParseType, Runner},
|
||||||
Test,
|
Test,
|
||||||
|
PROGRAM_DELIMITER,
|
||||||
};
|
};
|
||||||
|
|
||||||
use snarkvm::console::prelude::*;
|
use snarkvm::console::prelude::*;
|
||||||
|
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use leo_span::Symbol;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
use std::{fs, path::Path, rc::Rc};
|
use std::{fs, path::Path, rc::Rc};
|
||||||
@ -101,48 +105,68 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse the program.
|
// Split the test content into individual program strings based on the program delimiter.
|
||||||
let mut parsed =
|
let program_strings = test.content.split(PROGRAM_DELIMITER).collect::<Vec<&str>>();
|
||||||
handler.extend_if_error(parse_program(handler, &test.content, cwd.clone(), Some(compiler_options)))?;
|
|
||||||
|
|
||||||
// Compile the program to bytecode.
|
// Initialize storage for the stubs.
|
||||||
let program_name = format!("{}.{}", parsed.program_name, parsed.network);
|
let mut import_stubs = IndexMap::new();
|
||||||
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
|
|
||||||
|
|
||||||
// Set up the build directory.
|
// Compile each program string separately.
|
||||||
// Note that this function checks that the bytecode is well-formed.
|
for program_string in program_strings {
|
||||||
let package = setup_build_directory(&program_name, &bytecode, handler)?;
|
// Parse the program.
|
||||||
|
let mut parsed = handler.extend_if_error(parse_program(
|
||||||
|
handler,
|
||||||
|
program_string,
|
||||||
|
cwd.clone(),
|
||||||
|
Some(compiler_options.clone()),
|
||||||
|
import_stubs.clone(),
|
||||||
|
))?;
|
||||||
|
|
||||||
// Get the program process and check all instructions.
|
// Compile the program to bytecode.
|
||||||
handler.extend_if_error(package.get_process().map_err(LeoError::Anyhow))?;
|
let program_name = parsed.program_name.to_string();
|
||||||
|
let full_program_name = format!("{program_name}.{}", parsed.network);
|
||||||
|
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
|
||||||
|
|
||||||
// Hash the ast files.
|
// Add the bytecode to the import stubs.
|
||||||
let (initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast) = hash_asts();
|
let stub = handler.extend_if_error(disassemble_from_str(&bytecode).map_err(|err| err.into()))?;
|
||||||
|
import_stubs.insert(Symbol::intern(&program_name), stub);
|
||||||
|
|
||||||
// Hash the symbol tables.
|
// Set up the build directory.
|
||||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) = hash_symbol_tables();
|
// Note that this function checks that the bytecode is well-formed.
|
||||||
|
let package = setup_build_directory(&full_program_name, &bytecode, handler)?;
|
||||||
|
|
||||||
// Clean up the output directory.
|
// Get the program process and check all instructions.
|
||||||
if fs::read_dir("/tmp/output").is_ok() {
|
handler.extend_if_error(package.get_process().map_err(LeoError::Anyhow))?;
|
||||||
fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir.");
|
|
||||||
|
// Hash the ast files.
|
||||||
|
let (initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast) =
|
||||||
|
hash_asts();
|
||||||
|
|
||||||
|
// Hash the symbol tables.
|
||||||
|
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) = hash_symbol_tables();
|
||||||
|
|
||||||
|
// Clean up the output directory.
|
||||||
|
if fs::read_dir("/tmp/output").is_ok() {
|
||||||
|
fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let final_output = CompileOutput {
|
||||||
|
initial_symbol_table,
|
||||||
|
type_checked_symbol_table,
|
||||||
|
unrolled_symbol_table,
|
||||||
|
initial_ast,
|
||||||
|
unrolled_ast,
|
||||||
|
ssa_ast,
|
||||||
|
flattened_ast,
|
||||||
|
destructured_ast,
|
||||||
|
inlined_ast,
|
||||||
|
dce_ast,
|
||||||
|
bytecode: hash_content(&bytecode),
|
||||||
|
warnings: buf.1.take().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs.push(final_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
let final_output = CompileOutput {
|
|
||||||
initial_symbol_table,
|
|
||||||
type_checked_symbol_table,
|
|
||||||
unrolled_symbol_table,
|
|
||||||
initial_ast,
|
|
||||||
unrolled_ast,
|
|
||||||
ssa_ast,
|
|
||||||
flattened_ast,
|
|
||||||
destructured_ast,
|
|
||||||
inlined_ast,
|
|
||||||
dce_ast,
|
|
||||||
bytecode: hash_content(&bytecode),
|
|
||||||
warnings: buf.1.take().to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs.push(final_output);
|
|
||||||
}
|
}
|
||||||
Ok(serde_yaml::to_value(outputs).expect("serialization failed"))
|
Ok(serde_yaml::to_value(outputs).expect("serialization failed"))
|
||||||
}
|
}
|
||||||
|
@ -116,8 +116,13 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Va
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parse the program.
|
// Parse the program.
|
||||||
let mut parsed =
|
let mut parsed = handler.extend_if_error(parse_program(
|
||||||
handler.extend_if_error(parse_program(handler, &test.content, cwd.clone(), Some(compiler_options)))?;
|
handler,
|
||||||
|
&test.content,
|
||||||
|
cwd.clone(),
|
||||||
|
Some(compiler_options),
|
||||||
|
Default::default(),
|
||||||
|
))?;
|
||||||
|
|
||||||
// Compile the program to bytecode.
|
// Compile the program to bytecode.
|
||||||
let program_name = format!("{}.{}", parsed.program_name, parsed.network);
|
let program_name = format!("{}.{}", parsed.program_name, parsed.network);
|
||||||
|
@ -30,7 +30,8 @@ use leo_test_framework::{test::TestConfig, Test};
|
|||||||
use snarkvm::prelude::*;
|
use snarkvm::prelude::*;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use leo_ast::ProgramVisitor;
|
use leo_ast::{ProgramVisitor, Stub};
|
||||||
|
use leo_span::Symbol;
|
||||||
use snarkvm::{file::Manifest, package::Package};
|
use snarkvm::{file::Manifest, package::Package};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
@ -139,6 +140,7 @@ pub fn new_compiler(
|
|||||||
handler: &Handler,
|
handler: &Handler,
|
||||||
main_file_path: PathBuf,
|
main_file_path: PathBuf,
|
||||||
compiler_options: Option<CompilerOptions>,
|
compiler_options: Option<CompilerOptions>,
|
||||||
|
import_stubs: IndexMap<Symbol, Stub>,
|
||||||
) -> Compiler<'_> {
|
) -> Compiler<'_> {
|
||||||
let output_dir = PathBuf::from("/tmp/output/");
|
let output_dir = PathBuf::from("/tmp/output/");
|
||||||
fs::create_dir_all(output_dir.clone()).unwrap();
|
fs::create_dir_all(output_dir.clone()).unwrap();
|
||||||
@ -150,7 +152,7 @@ pub fn new_compiler(
|
|||||||
main_file_path,
|
main_file_path,
|
||||||
output_dir,
|
output_dir,
|
||||||
compiler_options,
|
compiler_options,
|
||||||
IndexMap::new(),
|
import_stubs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +161,10 @@ pub fn parse_program<'a>(
|
|||||||
program_string: &str,
|
program_string: &str,
|
||||||
cwd: Option<PathBuf>,
|
cwd: Option<PathBuf>,
|
||||||
compiler_options: Option<CompilerOptions>,
|
compiler_options: Option<CompilerOptions>,
|
||||||
|
import_stubs: IndexMap<Symbol, Stub>,
|
||||||
) -> Result<Compiler<'a>, LeoError> {
|
) -> Result<Compiler<'a>, LeoError> {
|
||||||
let mut compiler = new_compiler(handler, cwd.clone().unwrap_or_else(|| "compiler-test".into()), compiler_options);
|
let mut compiler =
|
||||||
|
new_compiler(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);
|
let name = cwd.map_or_else(|| FileName::Custom("compiler-test".into()), FileName::Real);
|
||||||
compiler.parse_program_from_string(program_string, name)?;
|
compiler.parse_program_from_string(program_string, name)?;
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ version = "1.10"
|
|||||||
[dev-dependencies.leo-compiler]
|
[dev-dependencies.leo-compiler]
|
||||||
path = "../../compiler/compiler"
|
path = "../../compiler/compiler"
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies.leo-span]
|
[dev-dependencies.leo-span]
|
||||||
path = "../../compiler/span"
|
path = "../../compiler/span"
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ use std::{
|
|||||||
|
|
||||||
use crate::{error::*, fetch::find_tests, output::TestExpectation, test::*};
|
use crate::{error::*, fetch::find_tests, output::TestExpectation, test::*};
|
||||||
|
|
||||||
|
pub const PROGRAM_DELIMITER: &str = "// --- Next Program --- //";
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum ParseType {
|
pub enum ParseType {
|
||||||
Line,
|
Line,
|
||||||
|
@ -71,8 +71,8 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble_from_str(program: String) -> Result<Stub, UtilError> {
|
pub fn disassemble_from_str(program: &str) -> Result<Stub, UtilError> {
|
||||||
match Program::<CurrentNetwork>::from_str(&program) {
|
match Program::<CurrentNetwork>::from_str(program) {
|
||||||
Ok(p) => Ok(disassemble(p)),
|
Ok(p) => Ok(disassemble(p)),
|
||||||
Err(_) => Err(UtilError::snarkvm_parsing_error(Default::default())),
|
Err(_) => Err(UtilError::snarkvm_parsing_error(Default::default())),
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ mod tests {
|
|||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(|_| {
|
||||||
let program_from_file =
|
let program_from_file =
|
||||||
fs::read_to_string("../tmp/.aleo/registry/testnet3/zk_bitwise_stack_v0_0_2.aleo").unwrap();
|
fs::read_to_string("../tmp/.aleo/registry/testnet3/zk_bitwise_stack_v0_0_2.aleo").unwrap();
|
||||||
let _program = disassemble_from_str(program_from_file).unwrap();
|
let _program = disassemble_from_str(&program_from_file).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ impl Retriever {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Cache the disassembled stub
|
// Cache the disassembled stub
|
||||||
let stub: Stub = disassemble_from_str(content)?;
|
let stub: Stub = disassemble_from_str(&content)?;
|
||||||
if cur_context.add_stub(stub.clone()) {
|
if cur_context.add_stub(stub.clone()) {
|
||||||
Err(UtilError::duplicate_dependency_name_error(stub.stub_id.name.name, Default::default()))?;
|
Err(UtilError::duplicate_dependency_name_error(stub.stub_id.name.name, Default::default()))?;
|
||||||
}
|
}
|
||||||
@ -484,7 +484,7 @@ fn retrieve_from_network(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Disassemble into Stub
|
// Disassemble into Stub
|
||||||
let stub: Stub = disassemble_from_str(file_str)?;
|
let stub: Stub = disassemble_from_str(&file_str)?;
|
||||||
|
|
||||||
// Create entry for leo.lock
|
// Create entry for leo.lock
|
||||||
Ok((
|
Ok((
|
||||||
|
Loading…
Reference in New Issue
Block a user