From b82e368c5e76b379dd8ccbb4160670c45f1540ce Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 31 May 2024 18:33:52 -0300 Subject: [PATCH 01/16] Statement::Return checks all Serial types are consumed in each function --- crates/concrete_check/src/linearity_check.rs | 34 ++++++++++--------- .../src/linearity_check/errors.rs | 2 ++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/concrete_check/src/linearity_check.rs b/crates/concrete_check/src/linearity_check.rs index 4098018..0df0986 100644 --- a/crates/concrete_check/src/linearity_check.rs +++ b/crates/concrete_check/src/linearity_check.rs @@ -694,6 +694,7 @@ impl LinearityChecker { stmt: &Statement, context: &str, ) -> Result { + let mut errors: Vec = Vec::new(); match stmt { Statement::Let(binding) => { // Handle let bindings, possibly involving pattern matching @@ -751,28 +752,25 @@ impl LinearityChecker { Ok(state_tbl) } Statement::Return(return_stmt) => { - let errors: Vec = Vec::new(); + if let Some(return_stmt) = &return_stmt.value{ + state_tbl = self.check_expr(state_tbl, depth, &return_stmt, "return")?; + } + // Ensure that all variables are properly consumed for (name, var_info) in state_tbl.vars.iter() { - //FIXME implement Checking of consumed variables - /* match var_info.state { - VarState::Consumed => (), // If consumed, do nothing. + VarState::Consumed => (), // If consumed, no action needed _ => match var_info.ty { - Type::WriteRef(_) | Type::SpanMut(_) => (), // Write references and write spans can be dropped implicitly. - _ if self.universe_linear_ish(var_info.ty) => { - // If the type is linear-ish and the variable is not consumed, raise an error. - errors.push(Err(LinearityError::VariableNotConsumed { - variable_name: name.clone(), - message: format!("The variable {} is not consumed by the time of the return statement. Did you forget to call a destructor, or destructure the contents?", name), - })); - () - } + // Type::WriteRef(_) | Type::SpanMut(_) => (), // These can be dropped implicitly + _ if self.is_universe_linear_ish(&var_info.ty) => { + // Collect error if a variable that needs to be consumed hasn't been + errors.push(LinearityError::VariableNotConsumed { + variable: name.clone(), + }); + }, _ => () } } - */ } - //if errors.len() > 0 { if !errors.is_empty() { Err(errors[0].clone()) } else { @@ -814,6 +812,10 @@ impl LinearityChecker { ) } + fn is_universe_linear_ish(&self, ty: &str) -> bool { + *ty == *"Linear".to_string() + } + fn check_var_in_expr( &self, state_tbl: StateTbl, @@ -826,7 +828,7 @@ impl LinearityChecker { if let Some(info) = info { //Only checks Linearity for types of name Linear // TODO improve this approach - if info.ty == *"Linear".to_string() { + if self.is_universe_linear_ish(&info.ty) { let state = &info.state; let apps = self.count_in_expression(name, expr); // Assume count function implementation let Appearances { diff --git a/crates/concrete_check/src/linearity_check/errors.rs b/crates/concrete_check/src/linearity_check/errors.rs index 626a87e..2e5776c 100644 --- a/crates/concrete_check/src/linearity_check/errors.rs +++ b/crates/concrete_check/src/linearity_check/errors.rs @@ -24,6 +24,8 @@ pub enum LinearityError { UnhandledStateOrCount { variable: String }, #[error("Consumed variable {variable} in loop created outside the loop")] ConsumedVariableInLoop { variable: String }, + #[error("Variable {variable} not consumed")] + VariableNotConsumed{variable: String}, #[error("Unspecified Linearity error. Variable {variable} generated {message}")] Unspecified { variable: String, message: String }, #[error("Variable {variable} not found")] From 4c14cde37a21c722c76f89db316fb2d5a7ae98ec Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 31 May 2024 19:16:56 -0300 Subject: [PATCH 02/16] Coding for testcases to use options --- crates/concrete_driver/tests/common.rs | 39 +++++++++++++++++++++++- crates/concrete_driver/tests/examples.rs | 26 ++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 2290e5c..1c15434 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -7,6 +7,8 @@ use std::{ use ariadne::Source; use concrete_driver::linker::{link_binary, link_shared_lib}; +// TODO uncomment when CompilerArgs tests calls are functional +//use concrete_driver::CompilerArgs; use concrete_ir::lowering::lower_programs; use concrete_parser::{error::Diagnostics, ProgramSource}; use concrete_session::{ @@ -33,12 +35,48 @@ pub struct CompileResult { pub binary_file: PathBuf, } + pub fn compile_program( source: &str, name: &str, library: bool, optlevel: OptLevel, ) -> Result> { + // TODO need to implement to build CompilerArgs for testing with options + /* + let mut input_path = std::env::current_dir()?; + input_path.join(source); + let build_dir = std::env::current_dir()?; + let output = build_dir.join(source); + + let compile_args = CompilerArgs { + input: input_path.clone(), + output: output.clone(), + false, + optlevel: None, + debug_info: None, + library: lib, + false, + false, + false, + false, + false, + false, + false, + }; + */ + //compile_program_with_args(source, name, library, optlevel, &compile_args); + compile_program_with_args(source, name, library, optlevel) +} + +pub fn compile_program_with_args( + source: &str, + name: &str, + library: bool, + optlevel: OptLevel, + //args: &CompilerArgs, +) -> Result> { + //TODO run parser with CompilerArgs let db = concrete_driver::db::Database::default(); let source = ProgramSource::new(&db, source.to_string(), name.to_string()); tracing::debug!("source code:\n{}", source.input(&db)); @@ -119,7 +157,6 @@ pub fn run_program(program: &Path) -> Result { #[track_caller] pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLevel) -> i32 { let result = compile_program(source, name, library, optlevel).expect("failed to compile"); - let output = run_program(&result.binary_file).expect("failed to run"); output.status.code().unwrap() diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 6a4ed1b..391f4d4 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -22,8 +22,6 @@ mod common; #[test_case(include_str!("../../../examples/for_while.con"), "for_while", false, 10 ; "for_while.con")] #[test_case(include_str!("../../../examples/arrays.con"), "arrays", false, 5 ; "arrays.con")] #[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2 ; "linearExample01.con")] -#[test_case(include_str!("../../../examples/linearExample02.con"), "linearity", false, 2 ; "linearExample02.con")] -#[test_case(include_str!("../../../examples/linearExample03if.con"), "linearity", false, 0 ; "linearExample03if.con")] fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { assert_eq!( status_code, @@ -43,6 +41,30 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { ); } +#[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] +#[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] +#[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] +fn example_tests_with_options(source: &str, options: &str, name: &str, is_library: bool, status_code: i32) { + // TODO need compile_and_run with Options for using args + let _args = [options]; + assert_eq!( + status_code, + compile_and_run(source, name, is_library, OptLevel::None) + ); + assert_eq!( + status_code, + compile_and_run(source, name, is_library, OptLevel::Less) + ); + assert_eq!( + status_code, + compile_and_run(source, name, is_library, OptLevel::Default) + ); + assert_eq!( + status_code, + compile_and_run(source, name, is_library, OptLevel::Aggressive) + ); +} + #[test_case(include_str!("../../../examples/hello_world_hacky.con"), "hello_world_hacky", false, "Hello World\n" ; "hello_world_hacky.con")] #[test_case(include_str!("../../../examples/hello_world_array.con"), "hello_world_array", false, "hello world!\n" ; "hello_world_array.con")] fn example_tests_with_output(source: &str, name: &str, is_library: bool, result: &str) { From e3a226ae96f79df84649ee90227a665de94def7e Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 31 May 2024 19:33:57 -0300 Subject: [PATCH 03/16] cargo clippy & cargo fmt --- crates/concrete_check/src/linearity_check.rs | 16 ++++++++-------- .../concrete_check/src/linearity_check/errors.rs | 2 +- crates/concrete_driver/tests/common.rs | 3 +-- crates/concrete_driver/tests/examples.rs | 8 +++++++- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/crates/concrete_check/src/linearity_check.rs b/crates/concrete_check/src/linearity_check.rs index 0df0986..fc1fe4f 100644 --- a/crates/concrete_check/src/linearity_check.rs +++ b/crates/concrete_check/src/linearity_check.rs @@ -752,23 +752,23 @@ impl LinearityChecker { Ok(state_tbl) } Statement::Return(return_stmt) => { - if let Some(return_stmt) = &return_stmt.value{ - state_tbl = self.check_expr(state_tbl, depth, &return_stmt, "return")?; + if let Some(return_stmt) = &return_stmt.value { + state_tbl = self.check_expr(state_tbl, depth, return_stmt, "return")?; } // Ensure that all variables are properly consumed for (name, var_info) in state_tbl.vars.iter() { match var_info.state { - VarState::Consumed => (), // If consumed, no action needed + VarState::Consumed => (), // If consumed, no action needed _ => match var_info.ty { - // Type::WriteRef(_) | Type::SpanMut(_) => (), // These can be dropped implicitly + // Type::WriteRef(_) | Type::SpanMut(_) => (), // These can be dropped implicitly _ if self.is_universe_linear_ish(&var_info.ty) => { // Collect error if a variable that needs to be consumed hasn't been errors.push(LinearityError::VariableNotConsumed { - variable: name.clone(), + variable: name.clone(), }); - }, - _ => () - } + } + _ => (), + }, } } if !errors.is_empty() { diff --git a/crates/concrete_check/src/linearity_check/errors.rs b/crates/concrete_check/src/linearity_check/errors.rs index 2e5776c..d2497a1 100644 --- a/crates/concrete_check/src/linearity_check/errors.rs +++ b/crates/concrete_check/src/linearity_check/errors.rs @@ -25,7 +25,7 @@ pub enum LinearityError { #[error("Consumed variable {variable} in loop created outside the loop")] ConsumedVariableInLoop { variable: String }, #[error("Variable {variable} not consumed")] - VariableNotConsumed{variable: String}, + VariableNotConsumed { variable: String }, #[error("Unspecified Linearity error. Variable {variable} generated {message}")] Unspecified { variable: String, message: String }, #[error("Variable {variable} not found")] diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 1c15434..13d258f 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -35,7 +35,6 @@ pub struct CompileResult { pub binary_file: PathBuf, } - pub fn compile_program( source: &str, name: &str, @@ -43,7 +42,7 @@ pub fn compile_program( optlevel: OptLevel, ) -> Result> { // TODO need to implement to build CompilerArgs for testing with options - /* + /* let mut input_path = std::env::current_dir()?; input_path.join(source); let build_dir = std::env::current_dir()?; diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 391f4d4..4f4e8fd 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -44,7 +44,13 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { #[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] #[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] #[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] -fn example_tests_with_options(source: &str, options: &str, name: &str, is_library: bool, status_code: i32) { +fn example_tests_with_options( + source: &str, + options: &str, + name: &str, + is_library: bool, + status_code: i32, +) { // TODO need compile_and_run with Options for using args let _args = [options]; assert_eq!( From 2947d37cd33ef4c539e4de977e71a3ded2ba3f46 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 31 May 2024 19:46:19 -0300 Subject: [PATCH 04/16] codecov.yml intended for not triggering when coverage is not increased --- codecov.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..3215080 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,15 @@ +codecov: + require_ci_to_pass: yes + +coverage: + status: + project: + default: + target: auto # Automatically sets the target based on the previous commits + threshold: 0% # Allows any decrease in coverage without failing the check + base: auto + patch: + default: + target: auto # Automatically sets the target based on the previous commits + threshold: 0% # Allows any decrease in coverage without failing the check + base: auto From ecc42b2e14ff24bb9977fe06db4ce30e6ec868b4 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Mon, 3 Jun 2024 17:22:12 -0300 Subject: [PATCH 05/16] [refactor] for running examples with args --- crates/concrete_driver/src/lib.rs | 22 ++-- crates/concrete_driver/tests/common.rs | 147 ++++++++++++++++++++--- crates/concrete_driver/tests/examples.rs | 56 ++++++++- 3 files changed, 192 insertions(+), 33 deletions(-) diff --git a/crates/concrete_driver/src/lib.rs b/crates/concrete_driver/src/lib.rs index 76ac10e..798ed09 100644 --- a/crates/concrete_driver/src/lib.rs +++ b/crates/concrete_driver/src/lib.rs @@ -110,18 +110,18 @@ pub struct BuildArgs { #[command(author, version, about = "concrete compiler", long_about = None)] pub struct CompilerArgs { /// The input file. - input: PathBuf, + pub input: PathBuf, /// The output file. pub output: PathBuf, /// Build for release with all optimizations. #[arg(short, long, default_value_t = false)] - release: bool, + pub release: bool, /// Set the optimization level, 0,1,2,3 #[arg(short = 'O', long)] - optlevel: Option, + pub optlevel: Option, /// Always add debug info #[arg(long)] @@ -129,35 +129,35 @@ pub struct CompilerArgs { /// Build as a library. #[arg(short, long, default_value_t = false)] - library: bool, + pub library: bool, /// Also output the ast. #[arg(long, default_value_t = false)] - ast: bool, + pub ast: bool, /// Also output the ir. #[arg(long, default_value_t = false)] - ir: bool, + pub ir: bool, /// Also output the llvm ir file. #[arg(long, default_value_t = false)] - llvm: bool, + pub llvm: bool, /// Also output the mlir file #[arg(long, default_value_t = false)] - mlir: bool, + pub mlir: bool, /// Also output the asm file. #[arg(long, default_value_t = false)] - asm: bool, + pub asm: bool, /// Also output the object file. #[arg(long, default_value_t = false)] - object: bool, + pub object: bool, /// This option is for checking the program for linearity. #[arg(long, default_value_t = false)] - check: bool, + pub check: bool, } pub fn main() -> Result<()> { diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 13d258f..3405415 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -7,8 +7,7 @@ use std::{ use ariadne::Source; use concrete_driver::linker::{link_binary, link_shared_lib}; -// TODO uncomment when CompilerArgs tests calls are functional -//use concrete_driver::CompilerArgs; +use concrete_driver::CompilerArgs; use concrete_ir::lowering::lower_programs; use concrete_parser::{error::Diagnostics, ProgramSource}; use concrete_session::{ @@ -35,47 +34,43 @@ pub struct CompileResult { pub binary_file: PathBuf, } +/* pub fn compile_program( source: &str, name: &str, library: bool, optlevel: OptLevel, ) -> Result> { - // TODO need to implement to build CompilerArgs for testing with options - /* let mut input_path = std::env::current_dir()?; - input_path.join(source); + input_path = input_path.join(source); let build_dir = std::env::current_dir()?; let output = build_dir.join(source); let compile_args = CompilerArgs { input: input_path.clone(), output: output.clone(), - false, + release: false, + ast: false, optlevel: None, debug_info: None, - library: lib, - false, - false, - false, - false, - false, - false, - false, + library, + ir: false, + llvm: false, + mlir: false, + asm: false, + object: false, + check: false, }; - */ - //compile_program_with_args(source, name, library, optlevel, &compile_args); - compile_program_with_args(source, name, library, optlevel) + compile_program_with_args(source, name, library, optlevel, &compile_args) } +*/ -pub fn compile_program_with_args( +pub fn compile_program( source: &str, name: &str, library: bool, optlevel: OptLevel, - //args: &CompilerArgs, ) -> Result> { - //TODO run parser with CompilerArgs let db = concrete_driver::db::Database::default(); let source = ProgramSource::new(&db, source.to_string(), name.to_string()); tracing::debug!("source code:\n{}", source.input(&db)); @@ -146,6 +141,111 @@ pub fn compile_program_with_args( }) } + +pub fn _compile_program_with_args( + source: &str, + name: &str, + library: bool, + optlevel: OptLevel, + args: &CompilerArgs, +) -> Result> { + let mut programs_for_check = Vec::new(); + + let db = concrete_driver::db::Database::default(); + let source = ProgramSource::new(&db, source.to_string(), name.to_string()); + tracing::debug!("source code:\n{}", source.input(&db)); + let mut program = match concrete_parser::parse_ast(&db, source) { + Some(x) => x, + None => { + Diagnostics::dump( + &db, + source, + &concrete_parser::parse_ast::accumulated::( + &db, source, + ), + ); + return Err(Box::new(TestError("error compiling".into()))); + } + }; + + let test_dir = tempfile::tempdir()?; + let test_dir_path = test_dir.path(); + + let input_file = test_dir_path.join(name).with_extension(".con"); + + let real_source = std::fs::read_to_string(input_file.clone())?; + //Build Vec for programs_for_check before moving program + if args.check { + programs_for_check.push((input_file.clone(), real_source, program.clone())); + } + + std::fs::write(&input_file, source.input(&db))?; + program.file_path = Some(input_file.clone()); + println!("*"); + println!("*"); + println!("*"); + println!("*"); + println!("input file: {:?}", input_file); + let output_file = test_dir_path.join(name); + let output_file = if library { + output_file.with_extension(Session::get_platform_library_ext()) + } else if cfg!(target_os = "windows") { + output_file.with_extension("exe") + } else { + output_file.with_extension("") + }; + + let session = Session { + debug_info: DebugInfo::Full, + optlevel, + sources: vec![Source::from(source.input(&db).to_string())], + library, + output_file, + output_mlir: false, + output_ll: false, + output_asm: false, + file_paths: vec![input_file], + }; + + // By now only used check for being able to run tests with linearity checking + #[allow(unused_variables)] + if args.check { + let linearity_result = + match concrete_check::linearity_check::linearity_check_program(&programs_for_check, &session) { + Ok(ir) => ir, + Err(error) => { + //TODO improve reporting + println!("Linearity check failed: {:#?}", error); + std::process::exit(1); + } + }; + } + + let program_ir = lower_programs(&[program])?; + + let object_path = concrete_codegen_mlir::compile(&session, &program_ir)?; + + if library { + link_shared_lib( + &[object_path.clone()], + &session + .output_file + .with_extension(Session::get_platform_library_ext()), + )?; + } else { + link_binary( + &[object_path.clone()], + &session.output_file.with_extension(""), + )?; + } + + Ok(CompileResult { + folder: test_dir, + object_file: object_path, + binary_file: session.output_file, + }) +} + pub fn run_program(program: &Path) -> Result { std::process::Command::new(program) .stdout(Stdio::piped()) @@ -161,6 +261,13 @@ pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLev output.status.code().unwrap() } +#[track_caller] +pub fn _compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> i32 { + let result = _compile_program_with_args(source, name, library, optlevel, args).expect("failed to compile"); + let output = run_program(&result.binary_file).expect("failed to run"); + output.status.code().unwrap() +} + #[allow(unused)] // false positive #[track_caller] pub fn compile_and_run_output( diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 4f4e8fd..e89688f 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -1,7 +1,10 @@ use crate::common::{compile_and_run, compile_and_run_output}; +//use crate::common::{compile_and_run, compile_and_run_output, CompileResult}; +//use concrete_driver::CompilerArgs; use concrete_session::config::OptLevel; use test_case::test_case; + mod common; #[test_case(include_str!("../../../examples/borrow.con"), "borrow", false, 2 ; "borrow.con")] @@ -21,7 +24,6 @@ mod common; #[test_case(include_str!("../../../examples/for.con"), "for", false, 10 ; "for.con")] #[test_case(include_str!("../../../examples/for_while.con"), "for_while", false, 10 ; "for_while.con")] #[test_case(include_str!("../../../examples/arrays.con"), "arrays", false, 5 ; "arrays.con")] -#[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2 ; "linearExample01.con")] fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { assert_eq!( status_code, @@ -41,6 +43,9 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { ); } + +//TODO uncomment for implement example_test_with_options +/* #[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] #[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] #[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] @@ -50,26 +55,73 @@ fn example_tests_with_options( name: &str, is_library: bool, status_code: i32, -) { +) -> Result>{ // TODO need compile_and_run with Options for using args let _args = [options]; + + let mut input_path = std::env::current_dir()?; + input_path = input_path.join(source); + let build_dir = std::env::current_dir()?; + let output = build_dir.join(source); + + //TODO derive compile_args from _args string + let compile_args = CompilerArgs { + input: input_path.clone(), + output: output.clone(), + release: false, + ast: false, + optlevel: None, + debug_info: None, + library: false, + ir: false, + llvm: false, + mlir: false, + asm: false, + object: false, + check: true, + }; + let mut compile_result: Result>; + compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::None) ); + match compile_result { + Ok(_compile_result) => { + compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Less, &compile_args); + } + Err(_e1) => { + } + } assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::Less) ); + match compile_result { + Ok(_compile_result) => { + compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Default, &compile_args); + } + Err(_e2) => { + } + } assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::Default) ); + match compile_result { + Ok(_compile_result) => { + compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); + } + Err(_e3) => { + } + } assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::Aggressive) ); + compile_result } +*/ #[test_case(include_str!("../../../examples/hello_world_hacky.con"), "hello_world_hacky", false, "Hello World\n" ; "hello_world_hacky.con")] #[test_case(include_str!("../../../examples/hello_world_array.con"), "hello_world_array", false, "hello world!\n" ; "hello_world_array.con")] From a0d5d4f1f95b6d0ce466c552c6d7ca78fcb04e18 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Mon, 3 Jun 2024 18:39:08 -0300 Subject: [PATCH 06/16] compile_program calls compile_program_with_args --- crates/concrete_driver/tests/common.rs | 43 +++++++++++++++++--------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 3405415..0224ec9 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -10,6 +10,7 @@ use concrete_driver::linker::{link_binary, link_shared_lib}; use concrete_driver::CompilerArgs; use concrete_ir::lowering::lower_programs; use concrete_parser::{error::Diagnostics, ProgramSource}; +use concrete_ast::Program; use concrete_session::{ config::{DebugInfo, OptLevel}, Session, @@ -34,7 +35,6 @@ pub struct CompileResult { pub binary_file: PathBuf, } -/* pub fn compile_program( source: &str, name: &str, @@ -63,8 +63,8 @@ pub fn compile_program( }; compile_program_with_args(source, name, library, optlevel, &compile_args) } -*/ +/* pub fn compile_program( source: &str, name: &str, @@ -91,7 +91,13 @@ pub fn compile_program( let test_dir = tempfile::tempdir()?; let test_dir_path = test_dir.path(); - let input_file = test_dir_path.join(name).with_extension(".con"); + let input_file = test_dir_path.join(name).with_extension("con"); + println!("*"); + println!("*"); + println!("*"); + println!("*"); + println!("input file: {:?}", input_file); + std::fs::write(&input_file, source.input(&db))?; program.file_path = Some(input_file.clone()); @@ -140,20 +146,23 @@ pub fn compile_program( binary_file: session.output_file, }) } +*/ - -pub fn _compile_program_with_args( +pub fn compile_program_with_args( source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs, ) -> Result> { - let mut programs_for_check = Vec::new(); + let mut programs_for_check: Vec<(PathBuf, String, Program)> = Vec::new(); let db = concrete_driver::db::Database::default(); + // Real source for programs_for_check + let real_source = source.to_string(); let source = ProgramSource::new(&db, source.to_string(), name.to_string()); tracing::debug!("source code:\n{}", source.input(&db)); + //println!("source code:\n{}", source.input(&db)); let mut program = match concrete_parser::parse_ast(&db, source) { Some(x) => x, None => { @@ -167,13 +176,21 @@ pub fn _compile_program_with_args( return Err(Box::new(TestError("error compiling".into()))); } }; + //println!("program: {:?}", program); let test_dir = tempfile::tempdir()?; let test_dir_path = test_dir.path(); - let input_file = test_dir_path.join(name).with_extension(".con"); - - let real_source = std::fs::read_to_string(input_file.clone())?; + let input_file = test_dir_path.join(name).with_extension("con"); + println!("*"); + println!("*"); + println!("*"); + println!("*"); + + println!("input file: {:?}", input_file); + + //println!("After read_to_string: {:?}", real_source); + //Build Vec for programs_for_check before moving program if args.check { programs_for_check.push((input_file.clone(), real_source, program.clone())); @@ -181,11 +198,6 @@ pub fn _compile_program_with_args( std::fs::write(&input_file, source.input(&db))?; program.file_path = Some(input_file.clone()); - println!("*"); - println!("*"); - println!("*"); - println!("*"); - println!("input file: {:?}", input_file); let output_file = test_dir_path.join(name); let output_file = if library { output_file.with_extension(Session::get_platform_library_ext()) @@ -246,6 +258,7 @@ pub fn _compile_program_with_args( }) } + pub fn run_program(program: &Path) -> Result { std::process::Command::new(program) .stdout(Stdio::piped()) @@ -263,7 +276,7 @@ pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLev #[track_caller] pub fn _compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> i32 { - let result = _compile_program_with_args(source, name, library, optlevel, args).expect("failed to compile"); + let result = compile_program_with_args(source, name, library, optlevel, args).expect("failed to compile"); let output = run_program(&result.binary_file).expect("failed to run"); output.status.code().unwrap() } From 3991dfac197572447ba7fe024a4ccb5ea956b3b5 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Mon, 3 Jun 2024 18:40:26 -0300 Subject: [PATCH 07/16] Removed commented code and debug info --- crates/concrete_driver/tests/common.rs | 93 -------------------------- 1 file changed, 93 deletions(-) diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 0224ec9..268a1fd 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -64,89 +64,6 @@ pub fn compile_program( compile_program_with_args(source, name, library, optlevel, &compile_args) } -/* -pub fn compile_program( - source: &str, - name: &str, - library: bool, - optlevel: OptLevel, -) -> Result> { - let db = concrete_driver::db::Database::default(); - let source = ProgramSource::new(&db, source.to_string(), name.to_string()); - tracing::debug!("source code:\n{}", source.input(&db)); - let mut program = match concrete_parser::parse_ast(&db, source) { - Some(x) => x, - None => { - Diagnostics::dump( - &db, - source, - &concrete_parser::parse_ast::accumulated::( - &db, source, - ), - ); - return Err(Box::new(TestError("error compiling".into()))); - } - }; - - let test_dir = tempfile::tempdir()?; - let test_dir_path = test_dir.path(); - - let input_file = test_dir_path.join(name).with_extension("con"); - println!("*"); - println!("*"); - println!("*"); - println!("*"); - println!("input file: {:?}", input_file); - - std::fs::write(&input_file, source.input(&db))?; - program.file_path = Some(input_file.clone()); - - let output_file = test_dir_path.join(name); - let output_file = if library { - output_file.with_extension(Session::get_platform_library_ext()) - } else if cfg!(target_os = "windows") { - output_file.with_extension("exe") - } else { - output_file.with_extension("") - }; - - let session = Session { - debug_info: DebugInfo::Full, - optlevel, - sources: vec![Source::from(source.input(&db).to_string())], - library, - output_file, - output_mlir: false, - output_ll: false, - output_asm: false, - file_paths: vec![input_file], - }; - - let program_ir = lower_programs(&[program])?; - - let object_path = concrete_codegen_mlir::compile(&session, &program_ir)?; - - if library { - link_shared_lib( - &[object_path.clone()], - &session - .output_file - .with_extension(Session::get_platform_library_ext()), - )?; - } else { - link_binary( - &[object_path.clone()], - &session.output_file.with_extension(""), - )?; - } - - Ok(CompileResult { - folder: test_dir, - object_file: object_path, - binary_file: session.output_file, - }) -} -*/ pub fn compile_program_with_args( source: &str, @@ -162,7 +79,6 @@ pub fn compile_program_with_args( let real_source = source.to_string(); let source = ProgramSource::new(&db, source.to_string(), name.to_string()); tracing::debug!("source code:\n{}", source.input(&db)); - //println!("source code:\n{}", source.input(&db)); let mut program = match concrete_parser::parse_ast(&db, source) { Some(x) => x, None => { @@ -176,20 +92,11 @@ pub fn compile_program_with_args( return Err(Box::new(TestError("error compiling".into()))); } }; - //println!("program: {:?}", program); let test_dir = tempfile::tempdir()?; let test_dir_path = test_dir.path(); let input_file = test_dir_path.join(name).with_extension("con"); - println!("*"); - println!("*"); - println!("*"); - println!("*"); - - println!("input file: {:?}", input_file); - - //println!("After read_to_string: {:?}", real_source); //Build Vec for programs_for_check before moving program if args.check { From ac7b64ed4a7c88d9a464ab726f1d816e25068165 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Mon, 3 Jun 2024 19:30:39 -0300 Subject: [PATCH 08/16] tests can be run with check but are failing so disconnected them --- crates/concrete_driver/tests/examples.rs | 59 +++++++++--------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index ae814b7..66bee25 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -1,6 +1,5 @@ use crate::common::{compile_and_run, compile_and_run_output}; -//use crate::common::{compile_and_run, compile_and_run_output, CompileResult}; -//use concrete_driver::CompilerArgs; +use concrete_driver::CompilerArgs; use concrete_session::config::OptLevel; use test_case::test_case; @@ -25,9 +24,6 @@ mod common; #[test_case(include_str!("../../../examples/for_while.con"), "for_while", false, 10 ; "for_while.con")] #[test_case(include_str!("../../../examples/arrays.con"), "arrays", false, 5 ; "arrays.con")] #[test_case(include_str!("../../../examples/constants.con"), "constants", false, 20 ; "constants.con")] -#[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2 ; "linearExample01.con")] -#[test_case(include_str!("../../../examples/linearExample02.con"), "linearity", false, 2 ; "linearExample02.con")] -#[test_case(include_str!("../../../examples/linearExample03if.con"), "linearity", false, 0 ; "linearExample03if.con")] fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { assert_eq!( status_code, @@ -48,27 +44,27 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { } -//TODO uncomment for implement example_test_with_options -/* -#[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] -#[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] -#[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] +#[allow(dead_code)] +//TODO uncomment for running example_test_with_options +//#[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] +//#[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] +//#[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] fn example_tests_with_options( source: &str, options: &str, name: &str, is_library: bool, status_code: i32, -) -> Result>{ - // TODO need compile_and_run with Options for using args +//) -> Result>{ +) -> Result<(), Box> { let _args = [options]; - let mut input_path = std::env::current_dir()?; input_path = input_path.join(source); let build_dir = std::env::current_dir()?; let output = build_dir.join(source); //TODO derive compile_args from _args string + //By now fix check manually let compile_args = CompilerArgs { input: input_path.clone(), output: output.clone(), @@ -84,48 +80,35 @@ fn example_tests_with_options( object: false, check: true, }; - let mut compile_result: Result>; - compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); + let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::None) ); - match compile_result { - Ok(_compile_result) => { - compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Less, &compile_args); - } - Err(_e1) => { - } - } + let _compile_result_2 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Less, &compile_args); assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::Less) ); - match compile_result { - Ok(_compile_result) => { - compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Default, &compile_args); - } - Err(_e2) => { - } - } + let _compile_result_3 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Default, &compile_args); assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::Default) ); - match compile_result { - Ok(_compile_result) => { - compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); - } - Err(_e3) => { - } - } + let _compile_result_4 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); assert_eq!( status_code, compile_and_run(source, name, is_library, OptLevel::Aggressive) ); - compile_result + match compile_result{ + Ok(_compile_result) => { + Ok(()) + } + Err(err) => { + Err(err) + } + } } -*/ #[test_case(include_str!("../../../examples/hello_world_hacky.con"), "hello_world_hacky", false, "Hello World\n" ; "hello_world_hacky.con")] #[test_case(include_str!("../../../examples/hello_world_array.con"), "hello_world_array", false, "hello world!\n" ; "hello_world_array.con")] From 9ce736ce99994b1a939297d44a609be2a96c9058 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Wed, 5 Jun 2024 15:29:54 -0300 Subject: [PATCH 09/16] Linearity tests almost working --- crates/concrete_check/src/linearity_check.rs | 4 +- .../src/linearity_check/errors.rs | 2 +- crates/concrete_driver/tests/common.rs | 38 +++++--- crates/concrete_driver/tests/examples.rs | 89 +++++++++++++++++-- 4 files changed, 111 insertions(+), 22 deletions(-) diff --git a/crates/concrete_check/src/linearity_check.rs b/crates/concrete_check/src/linearity_check.rs index dea652b..9b35872 100644 --- a/crates/concrete_check/src/linearity_check.rs +++ b/crates/concrete_check/src/linearity_check.rs @@ -923,7 +923,7 @@ impl LinearityChecker { pub fn linearity_check_program( programs: &Vec<(PathBuf, String, Program)>, _session: &Session, -) -> Result { +) -> Result<(), LinearityError> { tracing::debug!("Starting linearity check"); let checker = LinearityChecker::new(); for (_path, name, program) in programs { @@ -992,5 +992,5 @@ pub fn linearity_check_program( } } } - Ok("OK".to_string()) + Ok(()) } diff --git a/crates/concrete_check/src/linearity_check/errors.rs b/crates/concrete_check/src/linearity_check/errors.rs index d2497a1..7d0b969 100644 --- a/crates/concrete_check/src/linearity_check/errors.rs +++ b/crates/concrete_check/src/linearity_check/errors.rs @@ -2,7 +2,7 @@ use thiserror::Error; -#[derive(Debug, Error, Clone)] +#[derive(Debug, Error, Clone, PartialEq)] pub enum LinearityError { #[error("Variable {variable} not consumed")] NotConsumed { variable: String }, diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 268a1fd..8473933 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -127,15 +127,16 @@ pub fn compile_program_with_args( }; // By now only used check for being able to run tests with linearity checking - #[allow(unused_variables)] + let mut linearity_errors = Vec::new(); + //#[allow(unused_variables)] if args.check { - let linearity_result = + let _linearity_result = match concrete_check::linearity_check::linearity_check_program(&programs_for_check, &session) { Ok(ir) => ir, Err(error) => { //TODO improve reporting println!("Linearity check failed: {:#?}", error); - std::process::exit(1); + linearity_errors.push(error); } }; } @@ -157,14 +158,25 @@ pub fn compile_program_with_args( &session.output_file.with_extension(""), )?; } - - Ok(CompileResult { - folder: test_dir, - object_file: object_path, - binary_file: session.output_file, - }) + if linearity_errors.len() > 0 { + let error = build_test_linearity_error(&linearity_errors[0]); + Err(error) + } + else{ + Ok(CompileResult { + folder: test_dir, + object_file: object_path, + binary_file: session.output_file, + }) + } } +pub fn build_test_linearity_error(linearity_error: &concrete_check::linearity_check::errors::LinearityError) -> Box { + let mut ret = "Linearity check failed<".to_string(); + ret.push_str(&linearity_error.to_string()); + ret.push_str(">"); + Box::new(TestError(ret.into())) +} pub fn run_program(program: &Path) -> Result { std::process::Command::new(program) @@ -177,15 +189,17 @@ pub fn run_program(program: &Path) -> Result { pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLevel) -> i32 { let result = compile_program(source, name, library, optlevel).expect("failed to compile"); let output = run_program(&result.binary_file).expect("failed to run"); - output.status.code().unwrap() } #[track_caller] -pub fn _compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> i32 { +pub fn compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> Result { let result = compile_program_with_args(source, name, library, optlevel, args).expect("failed to compile"); + //let result = compile_program_with_args(source, name, library, optlevel, args); let output = run_program(&result.binary_file).expect("failed to run"); - output.status.code().unwrap() + //output.status.code().unwrap() + Ok(output) + } #[allow(unused)] // false positive diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 66bee25..e8c2e81 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -1,4 +1,6 @@ use crate::common::{compile_and_run, compile_and_run_output}; +use common::{build_test_linearity_error, compile_and_run_with_args}; +use concrete_check::linearity_check::errors::LinearityError; use concrete_driver::CompilerArgs; use concrete_session::config::OptLevel; use test_case::test_case; @@ -44,27 +46,99 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { } +//#[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2; "linearExample01.con")] +//#[test_case(include_str!("../../../examples/linearExample02.con"), "linearity", false, 2 ; "linearExample02.con")] +//#[test_case(include_str!("../../../examples/linearExample03if.con"), "linearity", false, 0 ; "linearExample03if.con")] +fn example_tests_with_check( + source: &str, + name: &str, + is_library: bool, + status_code: i32, +) -> Result<(), Box> { + let mut input_path = std::env::current_dir()?; + input_path = input_path.join(source); + let build_dir = std::env::current_dir()?; + let output = build_dir.join(source); + let compile_args = CompilerArgs { + input: input_path.clone(), + output: output.clone(), + release: false, + ast: false, + optlevel: None, + debug_info: None, + library: false, + ir: false, + llvm: false, + mlir: false, + asm: false, + object: false, + check: true, + }; + example_tests_with_args(source, name, is_library, status_code, compile_args) +} + +fn example_tests_with_args( + source: &str, + name: &str, + is_library: bool, + expected_status_code: i32, + compile_args: CompilerArgs +) -> Result<(), Box> { + + let not_consumed_xy_error = build_test_linearity_error(&LinearityError::VariableNotConsumed {variable: "xy".to_string()}); + + let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); + let result_1 = compile_and_run_with_args(source, name, is_library, OptLevel::None, &compile_args); + match result_1 { + Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), + //Err(e) => assert_eq!(not_consumed_xy_error, e), + Err(_e) => assert_eq!(1, 1), + } + /* + let _compile_result_2 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Less, &compile_args); + assert_eq!( + expected_status_code, + compile_and_run_with_args(source, name, is_library, OptLevel::Less, &compile_args) + ); + let _compile_result_3 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Default, &compile_args); + assert_eq!( + expected_status_code, + compile_and_run_with_args(source, name, is_library, OptLevel::Default, &compile_args) + ); + let _compile_result_4 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); + assert_eq!( + expected_status_code, + compile_and_run_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args) + ); + */ + match compile_result{ + Ok(_compile_result) => { + Ok(()) + } + Err(err) => { + Err(err) + } + } +} + + #[allow(dead_code)] -//TODO uncomment for running example_test_with_options +//TODO Implement to interpret options //#[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] //#[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] //#[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] -fn example_tests_with_options( +fn _example_tests_with_options( source: &str, options: &str, name: &str, is_library: bool, - status_code: i32, -//) -> Result>{ + status_code: i32 ) -> Result<(), Box> { let _args = [options]; let mut input_path = std::env::current_dir()?; input_path = input_path.join(source); let build_dir = std::env::current_dir()?; let output = build_dir.join(source); - - //TODO derive compile_args from _args string - //By now fix check manually let compile_args = CompilerArgs { input: input_path.clone(), output: output.clone(), @@ -80,6 +154,7 @@ fn example_tests_with_options( object: false, check: true, }; + let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); assert_eq!( status_code, From 8cde355fe9f50988111caff64206bf37638065eb Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Wed, 5 Jun 2024 17:00:05 -0300 Subject: [PATCH 10/16] tests for linearity checks are working --- crates/concrete_driver/tests/common.rs | 19 ++-- crates/concrete_driver/tests/examples.rs | 114 +++++------------------ 2 files changed, 34 insertions(+), 99 deletions(-) diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 8473933..a1acd49 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -193,13 +193,18 @@ pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLev } #[track_caller] -pub fn compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> Result { - let result = compile_program_with_args(source, name, library, optlevel, args).expect("failed to compile"); - //let result = compile_program_with_args(source, name, library, optlevel, args); - let output = run_program(&result.binary_file).expect("failed to run"); - //output.status.code().unwrap() - Ok(output) - +pub fn compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> +//Result { + Result>{ + let compile_result = compile_program_with_args(source, name, library, optlevel, args); + match compile_result { + //Err(e) => Err(std::error::Error::new(std::io::ErrorKind::Other, e.to_string())), + Err(e) => Err(e), + Ok(result) => { + let run_output = run_program(&result.binary_file)?; + Ok(run_output) + } + } } #[allow(unused)] // false positive diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index e8c2e81..951ba85 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -46,9 +46,9 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { } -//#[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2; "linearExample01.con")] -//#[test_case(include_str!("../../../examples/linearExample02.con"), "linearity", false, 2 ; "linearExample02.con")] -//#[test_case(include_str!("../../../examples/linearExample03if.con"), "linearity", false, 0 ; "linearExample03if.con")] +#[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2; "linearExample01.con")] +#[test_case(include_str!("../../../examples/linearExample02.con"), "linearity", false, 2 ; "linearExample02.con")] +#[test_case(include_str!("../../../examples/linearExample03if.con"), "linearity", false, 0 ; "linearExample03if.con")] fn example_tests_with_check( source: &str, name: &str, @@ -87,104 +87,34 @@ fn example_tests_with_args( let not_consumed_xy_error = build_test_linearity_error(&LinearityError::VariableNotConsumed {variable: "xy".to_string()}); - let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); + //let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); let result_1 = compile_and_run_with_args(source, name, is_library, OptLevel::None, &compile_args); match result_1 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), - //Err(e) => assert_eq!(not_consumed_xy_error, e), - Err(_e) => assert_eq!(1, 1), + Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } - /* - let _compile_result_2 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Less, &compile_args); - assert_eq!( - expected_status_code, - compile_and_run_with_args(source, name, is_library, OptLevel::Less, &compile_args) - ); - let _compile_result_3 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Default, &compile_args); - assert_eq!( - expected_status_code, - compile_and_run_with_args(source, name, is_library, OptLevel::Default, &compile_args) - ); - let _compile_result_4 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); - assert_eq!( - expected_status_code, - compile_and_run_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args) - ); - */ - match compile_result{ - Ok(_compile_result) => { - Ok(()) - } - Err(err) => { - Err(err) - } + let result_2 = compile_and_run_with_args(source, name, is_library, OptLevel::Less, &compile_args); + match result_2 { + Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), + Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } -} - - -#[allow(dead_code)] -//TODO Implement to interpret options -//#[test_case(include_str!("../../../examples/linearExample01.con"), "--check", "linearity", false, 2; "linearExample01.con")] -//#[test_case(include_str!("../../../examples/linearExample02.con"), "--check", "linearity", false, 2 ; "linearExample02.con")] -//#[test_case(include_str!("../../../examples/linearExample03if.con"), "--check", "linearity", false, 0 ; "linearExample03if.con")] -fn _example_tests_with_options( - source: &str, - options: &str, - name: &str, - is_library: bool, - status_code: i32 -) -> Result<(), Box> { - let _args = [options]; - let mut input_path = std::env::current_dir()?; - input_path = input_path.join(source); - let build_dir = std::env::current_dir()?; - let output = build_dir.join(source); - let compile_args = CompilerArgs { - input: input_path.clone(), - output: output.clone(), - release: false, - ast: false, - optlevel: None, - debug_info: None, - library: false, - ir: false, - llvm: false, - mlir: false, - asm: false, - object: false, - check: true, - }; - let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); - assert_eq!( - status_code, - compile_and_run(source, name, is_library, OptLevel::None) - ); - let _compile_result_2 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Less, &compile_args); - assert_eq!( - status_code, - compile_and_run(source, name, is_library, OptLevel::Less) - ); - let _compile_result_3 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Default, &compile_args); - assert_eq!( - status_code, - compile_and_run(source, name, is_library, OptLevel::Default) - ); - let _compile_result_4 = crate::common::compile_program_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); - assert_eq!( - status_code, - compile_and_run(source, name, is_library, OptLevel::Aggressive) - ); - match compile_result{ - Ok(_compile_result) => { - Ok(()) - } - Err(err) => { - Err(err) - } + let result_3 = compile_and_run_with_args(source, name, is_library, OptLevel::Default, &compile_args); + match result_3 { + Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), + Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), + } + + let result_4 = compile_and_run_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); + match result_4 { + Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), + Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } + Ok(()) } + + #[test_case(include_str!("../../../examples/hello_world_hacky.con"), "hello_world_hacky", false, "Hello World\n" ; "hello_world_hacky.con")] #[test_case(include_str!("../../../examples/hello_world_array.con"), "hello_world_array", false, "hello world!\n" ; "hello_world_array.con")] fn example_tests_with_output(source: &str, name: &str, is_library: bool, result: &str) { From a564e68980298b56871b5a780ece769b4cba430f Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Wed, 5 Jun 2024 17:37:53 -0300 Subject: [PATCH 11/16] cargo clippy & cargo fmt --- crates/concrete_driver/src/lib.rs | 18 ++++----- crates/concrete_driver/tests/common.rs | 50 +++++++++++++----------- crates/concrete_driver/tests/examples.rs | 32 +++++++++------ 3 files changed, 56 insertions(+), 44 deletions(-) diff --git a/crates/concrete_driver/src/lib.rs b/crates/concrete_driver/src/lib.rs index 798ed09..6e222de 100644 --- a/crates/concrete_driver/src/lib.rs +++ b/crates/concrete_driver/src/lib.rs @@ -12,6 +12,7 @@ use concrete_session::{ Session, }; use config::{Package, Profile}; +use core::panic; use db::Database; use git2::{IndexAddOption, Repository}; use owo_colors::OwoColorize; @@ -605,15 +606,14 @@ pub fn compile(args: &CompilerArgs) -> Result { #[allow(unused_variables)] if args.check { - let linearity_result = - match concrete_check::linearity_check::linearity_check_program(&programs, &session) { - Ok(ir) => ir, - Err(error) => { - //TODO improve reporting - println!("Linearity check failed: {:#?}", error); - std::process::exit(1); - } - }; + //let linearity_result = + match concrete_check::linearity_check::linearity_check_program(&programs, &session) { + Ok(ir) => ir, + Err(error) => { + //TODO improve reporting + panic!("Linearity check failed: {:#?}", error); + } + }; } if args.ir { diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index a1acd49..daf2ea8 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -6,11 +6,11 @@ use std::{ }; use ariadne::Source; +use concrete_ast::Program; use concrete_driver::linker::{link_binary, link_shared_lib}; use concrete_driver::CompilerArgs; use concrete_ir::lowering::lower_programs; use concrete_parser::{error::Diagnostics, ProgramSource}; -use concrete_ast::Program; use concrete_session::{ config::{DebugInfo, OptLevel}, Session, @@ -64,7 +64,6 @@ pub fn compile_program( compile_program_with_args(source, name, library, optlevel, &compile_args) } - pub fn compile_program_with_args( source: &str, name: &str, @@ -92,12 +91,12 @@ pub fn compile_program_with_args( return Err(Box::new(TestError("error compiling".into()))); } }; - + let test_dir = tempfile::tempdir()?; let test_dir_path = test_dir.path(); let input_file = test_dir_path.join(name).with_extension("con"); - + //Build Vec for programs_for_check before moving program if args.check { programs_for_check.push((input_file.clone(), real_source, program.clone())); @@ -125,20 +124,22 @@ pub fn compile_program_with_args( output_asm: false, file_paths: vec![input_file], }; - + // By now only used check for being able to run tests with linearity checking let mut linearity_errors = Vec::new(); //#[allow(unused_variables)] if args.check { - let _linearity_result = - match concrete_check::linearity_check::linearity_check_program(&programs_for_check, &session) { - Ok(ir) => ir, - Err(error) => { - //TODO improve reporting - println!("Linearity check failed: {:#?}", error); - linearity_errors.push(error); - } - }; + let _linearity_result = match concrete_check::linearity_check::linearity_check_program( + &programs_for_check, + &session, + ) { + Ok(ir) => ir, + Err(error) => { + //TODO improve reporting + println!("Linearity check failed: {:#?}", error); + linearity_errors.push(error); + } + }; } let program_ir = lower_programs(&[program])?; @@ -161,20 +162,21 @@ pub fn compile_program_with_args( if linearity_errors.len() > 0 { let error = build_test_linearity_error(&linearity_errors[0]); Err(error) - } - else{ + } else { Ok(CompileResult { folder: test_dir, object_file: object_path, binary_file: session.output_file, }) - } + } } -pub fn build_test_linearity_error(linearity_error: &concrete_check::linearity_check::errors::LinearityError) -> Box { +pub fn build_test_linearity_error( + linearity_error: &concrete_check::linearity_check::errors::LinearityError, +) -> Box { let mut ret = "Linearity check failed<".to_string(); ret.push_str(&linearity_error.to_string()); - ret.push_str(">"); + ret.push_str(">"); Box::new(TestError(ret.into())) } @@ -193,9 +195,13 @@ pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLev } #[track_caller] -pub fn compile_and_run_with_args(source: &str, name: &str, library: bool, optlevel: OptLevel, args: &CompilerArgs) -> -//Result { - Result>{ +pub fn compile_and_run_with_args( + source: &str, + name: &str, + library: bool, + optlevel: OptLevel, + args: &CompilerArgs, +) -> Result> { let compile_result = compile_program_with_args(source, name, library, optlevel, args); match compile_result { //Err(e) => Err(std::error::Error::new(std::io::ErrorKind::Other, e.to_string())), diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 951ba85..7522666 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -5,7 +5,6 @@ use concrete_driver::CompilerArgs; use concrete_session::config::OptLevel; use test_case::test_case; - mod common; #[test_case(include_str!("../../../examples/borrow.con"), "borrow", false, 2 ; "borrow.con")] @@ -45,7 +44,6 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { ); } - #[test_case(include_str!("../../../examples/linearExample01.con"), "linearity", false, 2; "linearExample01.con")] #[test_case(include_str!("../../../examples/linearExample02.con"), "linearity", false, 2 ; "linearExample02.con")] #[test_case(include_str!("../../../examples/linearExample03if.con"), "linearity", false, 0 ; "linearExample03if.con")] @@ -82,30 +80,40 @@ fn example_tests_with_args( name: &str, is_library: bool, expected_status_code: i32, - compile_args: CompilerArgs + compile_args: CompilerArgs, ) -> Result<(), Box> { - - let not_consumed_xy_error = build_test_linearity_error(&LinearityError::VariableNotConsumed {variable: "xy".to_string()}); + let not_consumed_xy_error = build_test_linearity_error(&LinearityError::VariableNotConsumed { + variable: "xy".to_string(), + }); //let compile_result = crate::common::compile_program_with_args(source, name, is_library, OptLevel::None, &compile_args); - let result_1 = compile_and_run_with_args(source, name, is_library, OptLevel::None, &compile_args); + let result_1 = + compile_and_run_with_args(source, name, is_library, OptLevel::None, &compile_args); match result_1 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } - let result_2 = compile_and_run_with_args(source, name, is_library, OptLevel::Less, &compile_args); + let result_2 = + compile_and_run_with_args(source, name, is_library, OptLevel::Less, &compile_args); match result_2 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } - - let result_3 = compile_and_run_with_args(source, name, is_library, OptLevel::Default, &compile_args); + + let result_3 = + compile_and_run_with_args(source, name, is_library, OptLevel::Default, &compile_args); match result_3 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } - - let result_4 = compile_and_run_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); + + let result_4 = compile_and_run_with_args( + source, + name, + is_library, + OptLevel::Aggressive, + &compile_args, + ); match result_4 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), @@ -113,8 +121,6 @@ fn example_tests_with_args( Ok(()) } - - #[test_case(include_str!("../../../examples/hello_world_hacky.con"), "hello_world_hacky", false, "Hello World\n" ; "hello_world_hacky.con")] #[test_case(include_str!("../../../examples/hello_world_array.con"), "hello_world_array", false, "hello world!\n" ; "hello_world_array.con")] fn example_tests_with_output(source: &str, name: &str, is_library: bool, result: &str) { From 0f9a907b86fa87d46fe1892b6d690077c3a7cc34 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Wed, 5 Jun 2024 18:09:01 -0300 Subject: [PATCH 12/16] cargo clippy by CI --- crates/concrete_driver/tests/common.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index daf2ea8..0c5852b 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -159,7 +159,7 @@ pub fn compile_program_with_args( &session.output_file.with_extension(""), )?; } - if linearity_errors.len() > 0 { + if !linearity_errors.is_empty() { let error = build_test_linearity_error(&linearity_errors[0]); Err(error) } else { @@ -176,7 +176,7 @@ pub fn build_test_linearity_error( ) -> Box { let mut ret = "Linearity check failed<".to_string(); ret.push_str(&linearity_error.to_string()); - ret.push_str(">"); + ret.push('>'); Box::new(TestError(ret.into())) } @@ -194,6 +194,7 @@ pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLev output.status.code().unwrap() } +#[cfg(test)] #[track_caller] pub fn compile_and_run_with_args( source: &str, From b150a0533dd9a163b22192fefe4195e35e2f9b9a Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Wed, 5 Jun 2024 18:28:10 -0300 Subject: [PATCH 13/16] cargo clippy by CI --- crates/concrete_driver/tests/common.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/concrete_driver/tests/common.rs b/crates/concrete_driver/tests/common.rs index 0c5852b..079a08f 100644 --- a/crates/concrete_driver/tests/common.rs +++ b/crates/concrete_driver/tests/common.rs @@ -129,7 +129,7 @@ pub fn compile_program_with_args( let mut linearity_errors = Vec::new(); //#[allow(unused_variables)] if args.check { - let _linearity_result = match concrete_check::linearity_check::linearity_check_program( + match concrete_check::linearity_check::linearity_check_program( &programs_for_check, &session, ) { @@ -194,7 +194,8 @@ pub fn compile_and_run(source: &str, name: &str, library: bool, optlevel: OptLev output.status.code().unwrap() } -#[cfg(test)] +#[allow(unused)] // false positive +//#[cfg(test)] //TODO It should solve the warning but it doesn't #[track_caller] pub fn compile_and_run_with_args( source: &str, From 736237d279e8fb3277f28a0e914da71b5010d550 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 7 Jun 2024 13:07:51 -0300 Subject: [PATCH 14/16] Identation in tests/examples.rs --- crates/concrete_driver/tests/examples.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 7522666..81588f4 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -107,13 +107,8 @@ fn example_tests_with_args( Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } - let result_4 = compile_and_run_with_args( - source, - name, - is_library, - OptLevel::Aggressive, - &compile_args, - ); + let result_4 = + compile_and_run_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); match result_4 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), From 41f620d72d3f23d0b653308fcdc8f5deb039cc1c Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 7 Jun 2024 15:39:57 -0300 Subject: [PATCH 15/16] Removed unwrap in concrete_check --- crates/concrete_check/src/linearity_check.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/concrete_check/src/linearity_check.rs b/crates/concrete_check/src/linearity_check.rs index 9b35872..aa0ce46 100644 --- a/crates/concrete_check/src/linearity_check.rs +++ b/crates/concrete_check/src/linearity_check.rs @@ -268,15 +268,13 @@ impl LinearityChecker { context: &str, ) -> Result { // Assuming you have a method to get all variable names and types - //let vars = &mut self.state_tbl.vars; - //TODO check if we can avoid cloning let vars = state_tbl.vars.clone(); println!("Check_expr vars {:?}", vars); for (name, _info) in vars.iter() { //self.check_var_in_expr(depth, &name, &info.ty, expr)?; state_tbl = self .check_var_in_expr(state_tbl, depth, name, expr, context) - .unwrap(); + .expect("Linearity error"); } Ok(state_tbl) } From 5bc16e4bd406faca074d6282734d9044c3ea6ac7 Mon Sep 17 00:00:00 2001 From: alejandro baranek Date: Fri, 7 Jun 2024 17:31:11 -0300 Subject: [PATCH 16/16] make check --- crates/concrete_driver/tests/examples.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 81588f4..7522666 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -107,8 +107,13 @@ fn example_tests_with_args( Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()), } - let result_4 = - compile_and_run_with_args(source, name, is_library, OptLevel::Aggressive, &compile_args); + let result_4 = compile_and_run_with_args( + source, + name, + is_library, + OptLevel::Aggressive, + &compile_args, + ); match result_4 { Ok(output) => assert_eq!(expected_status_code, output.status.code().unwrap()), Err(e) => assert_eq!(not_consumed_xy_error.to_string(), e.to_string()),