diff --git a/Cargo.toml b/Cargo.toml index 2da5efc..3374c2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ name = "bonsai" doc = false [dependencies] -oak = "^0.5.3" +oak = "^0.5.4" oak_runtime = "^0.5.5" partial = "0.2.3" clap = "^2" diff --git a/src/back/compiler/expression.rs b/src/back/compiler/expression.rs index 93bf6d7..143ae9d 100644 --- a/src/back/compiler/expression.rs +++ b/src/back/compiler/expression.rs @@ -13,29 +13,32 @@ // limitations under the License. use context::*; +use session::*; use back::code_formatter::*; use std::collections::HashMap; /// Useful to compile expression without using the environment (for example when initializing a field). /// Precondition: All the free variables occuring in `expr` are supposed to be in scope. -pub fn compile_expression(context: &Context, fmt: &mut CodeFormatter, expr: Expr) { - ExpressionCompiler::new(context, fmt).compile(expr) +pub fn compile_expression(session: &Session, context: &Context, fmt: &mut CodeFormatter, expr: Expr) { + ExpressionCompiler::new(session, context, fmt).compile(expr) } /// Wrap the expression inside a closure `(env) -> [[expr]]` to be executed later with the environment. -pub fn compile_closure(context: &Context, fmt: &mut CodeFormatter, expr: Expr, return_expr: bool) { - ExpressionCompiler::new(context, fmt).closure(expr, return_expr) +pub fn compile_closure(session: &Session, context: &Context, fmt: &mut CodeFormatter, expr: Expr, return_expr: bool) { + ExpressionCompiler::new(session, context, fmt).closure(expr, return_expr) } struct ExpressionCompiler<'a> { + session: &'a Session, context: &'a Context, fmt: &'a mut CodeFormatter } impl<'a> ExpressionCompiler<'a> { - fn new(context: &'a Context, fmt: &'a mut CodeFormatter) -> Self { + fn new(session: &'a Session, context: &'a Context, fmt: &'a mut CodeFormatter) -> Self { ExpressionCompiler { + session: session, context: context, fmt: fmt } diff --git a/src/back/compiler/module.rs b/src/back/compiler/module.rs index 021a5f6..63c721e 100644 --- a/src/back/compiler/module.rs +++ b/src/back/compiler/module.rs @@ -13,23 +13,29 @@ // limitations under the License. use context::*; +use session::*; use back::code_formatter::*; use back::compiler::expression::*; use back::compiler::statement::*; -pub fn compile_module(context: &Context, module: JModule) -> Partial { - ModuleCompiler::new(context).compile(module) +pub fn compile_module(env: Env, module: JModule) -> Env<(Context, String)> { + env.and_next(|session, context| { + let code = ModuleCompiler::new(&session, &context).compile(module); + Env::new(session, code.map(|code| (context, code))) + }) } struct ModuleCompiler<'a> { + session: &'a Session, context: &'a Context, fmt: CodeFormatter } impl<'a> ModuleCompiler<'a> { - fn new(context: &'a Context) -> Self { + fn new(session: &'a Session, context: &'a Context) -> Self { ModuleCompiler { + session: session, context: context, fmt: CodeFormatter::new() } @@ -70,9 +76,9 @@ impl<'a> ModuleCompiler<'a> } fn runtime_boilerplate(&mut self, module: &JModule) { - self.runtime_object_uid(&module); - self.runtime_init_method(&module); - self.runtime_destroy_method(&module); + self.runtime_object_uid(module); + self.runtime_init_method(module); + self.runtime_destroy_method(module); } fn class_decl(&mut self, jclass: &JClass) { @@ -95,11 +101,11 @@ impl<'a> ModuleCompiler<'a> } fn main_method(&mut self, class_name: Ident) { - if let Some(main) = self.context.config().main_method.clone() { + if let Some(main) = self.session.config().main_method.clone() { if main.class == *class_name { self.fmt.push_line("public static void main(String[] args)"); self.fmt.open_block(); - let machine_method = if self.context.config().debug { "createDebug" } else { "create" }; + let machine_method = if self.session.config().debug { "createDebug" } else { "create" }; self.fmt.push_block(format!("\ {} current = new {}();\n\ Program program = current.{}();\n\ @@ -160,7 +166,7 @@ impl<'a> ModuleCompiler<'a> self.fmt.push(&format!("new {}()", field.binding.ty.name)); } else { - compile_expression(&self.context, &mut self.fmt, expr); + compile_expression(self.session, self.context, &mut self.fmt, expr); } } self.fmt.terminate_line(";"); @@ -246,7 +252,7 @@ impl<'a> ModuleCompiler<'a> self.proc_uid(&process, proc_instance); self.fmt.push_line("return"); self.fmt.indent(); - compile_statement(self.context, &mut self.fmt, process.body); + compile_statement(self.session, self.context, &mut self.fmt, process.body); self.fmt.unindent(); self.fmt.terminate_line(";"); self.fmt.close_block(); diff --git a/src/driver/config.rs b/src/driver/config.rs index 281ee68..7573696 100644 --- a/src/driver/config.rs +++ b/src/driver/config.rs @@ -96,7 +96,7 @@ impl Config output: file_to_test, libs: libs, main_method: None, - debug: true, + debug: false, testing_mode: true } } diff --git a/src/driver/mod.rs b/src/driver/mod.rs index f4e9c1a..6977e5b 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -22,7 +22,7 @@ use self::module_file::*; use session::*; use front; use middle; -// use back; +use back; use context::Context; use ast::{JModule, JCrate, TestAnnotation}; @@ -67,19 +67,18 @@ fn run_middle<'a>(env: Env) -> Env { middle::analyse_bonsai(env) } -fn run_back(session: Session, context: Context) -> Env { +pub fn run_back(session: Session, context: Context) -> Env { assert_eq!(session.has_errors(), false); - Env::value(session, context) - // context.ast.modules.clone() - // .into_iter() - // .filter(|module| module.file.is_lib()) - // .fold(Env::value(session, context), |env, module| { - // let file = module.file.clone(); - // back::compile_module(env, module) - // .map(|(context, output)| { - // file.write_output(output); - // context - // }) - // .ensure(ABORT_MSG) - // }) + context.ast.modules.clone() + .into_iter() + .filter(|module| module.file.is_lib()) + .fold(Env::value(session, context), |env, module| { + let file = module.file.clone(); + back::compile_module(env, module) + .map(|(context, output)| { + file.write_output(output); + context + }) + .ensure(ABORT_MSG) + }) } diff --git a/src/lib.rs b/src/lib.rs index d69e739..6fbf301 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,4 +30,4 @@ pub mod context; pub mod driver; pub mod front; pub mod middle; -// pub mod back; +pub mod back; diff --git a/src/main.rs b/src/main.rs index f977a87..819b182 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ mod context; mod driver; mod front; mod middle; -// mod back; +mod back; fn main() { driver::run(); diff --git a/tests/test/unit.rs b/tests/test/compile_test.rs similarity index 82% rename from tests/test/unit.rs rename to tests/test/compile_test.rs index c56af9f..e24786c 100644 --- a/tests/test/unit.rs +++ b/tests/test/compile_test.rs @@ -19,14 +19,12 @@ use test::*; use libbonsai::ast::*; use libbonsai::context::*; -use partial::*; - use std::path::{PathBuf}; use ExpectedResult::*; use ExpectedResult; -pub struct Unit<'a> +pub struct CompileTest<'a> { display: &'a mut Display, result: Partial, @@ -36,7 +34,7 @@ pub struct Unit<'a> test_path: PathBuf } -impl<'a> Unit<'a> +impl<'a> CompileTest<'a> { pub fn new(display: &'a mut Display, result: Partial, expect: ExpectedResult, @@ -44,7 +42,7 @@ impl<'a> Unit<'a> obtained_diagnostics: Vec, test_path: PathBuf) -> Self { - Unit { + CompileTest { display: display, result: result, expect: expect, @@ -54,10 +52,21 @@ impl<'a> Unit<'a> } } - pub fn diagnostic(mut self) { + /// Returns the context if the compilation succeeded as expected. + pub fn diagnostic(mut self) -> Option { let file_name = self.file_name(); if self.compilation_status(file_name.clone()) { - self.compare_diagnostics(file_name); + self.compare_diagnostics(file_name) + } + else { + None + } + } + + pub fn context_to_option(self) -> Option { + match self.result { + Partial::Value(x) => Some(x), + _ => None } } @@ -76,15 +85,17 @@ impl<'a> Unit<'a> } } - fn compare_diagnostics(self, file_name: String) { + fn compare_diagnostics(self, file_name: String) -> Option { if &self.obtained_diagnostics != &self.expected_diagnostics { self.display.diagnostics_failure(self.test_path, file_name, &self.obtained_diagnostics, &self.expected_diagnostics, ); + None } else { self.display.success(file_name); + self.context_to_option() } } diff --git a/tests/test/engine.rs b/tests/test/engine.rs index 0510e87..945f6c3 100644 --- a/tests/test/engine.rs +++ b/tests/test/engine.rs @@ -14,6 +14,7 @@ use libbonsai::session::*; use libbonsai::driver::*; +use libbonsai::context::*; use syntex_syntax::codemap::{CodeMap}; use std::rc::Rc; @@ -21,7 +22,6 @@ use std::cell::RefCell; use std::path::{PathBuf, Path}; use std::fs::read_dir; -use partial::*; use test::*; use test::ExpectedResult::*; @@ -63,14 +63,14 @@ impl Engine } fn test_directory(&mut self, start_msg: String, directory: PathBuf, - expect: ExpectedResult, run: bool) + expect: ExpectedResult, execute: bool) { self.display.info(start_msg); match read_dir(&directory) { Ok(dir_entries) => { for entry in dir_entries.map(Result::unwrap).map(|entry| entry.path()) { if entry.is_file() { - self.compile_and_run(entry, expect, run); + self.compile_and_run(entry, expect, execute); } else { self.display.warn(format!("Entry ignored because it's not a file.")); self.display.path(entry); @@ -83,7 +83,7 @@ impl Engine } } - fn compile_and_run(&mut self, filepath: PathBuf, expect: ExpectedResult, run: bool) { + fn compile_and_run(&mut self, filepath: PathBuf, expect: ExpectedResult, execute: bool) { let obtained_diagnostics = Rc::new(RefCell::new(vec![])); let codemap = Rc::new(CodeMap::new()); let emitter = Box::new(TestEmitter::new(obtained_diagnostics.clone(), codemap.clone())); @@ -93,11 +93,19 @@ impl Engine let session = session.reset_diagnostic(); let obtained_diagnostics = Rc::try_unwrap(obtained_diagnostics) .expect("Could not extract `obtained_diagnostics`.").into_inner(); - let unit = Unit::new(&mut self.display, context, expect, session.compiler_tests, - obtained_diagnostics, filepath); - unit.diagnostic(); + let context = { + let compile_test = CompileTest::new(&mut self.display, context, expect, session.compiler_tests.clone(), + obtained_diagnostics, filepath); + compile_test.diagnostic() + }; + if let Some(context) = context { + if execute { + self.run_file(session, context); + } + } } - fn run_file(&mut self, filepath: PathBuf) { + fn run_file(&mut self, session: Session, context: Context) { + run_back(session, context).expect("[Test] Could not generate the Bonsai code."); } } diff --git a/tests/test/mod.rs b/tests/test/mod.rs index 4bae516..2d83967 100644 --- a/tests/test/mod.rs +++ b/tests/test/mod.rs @@ -13,13 +13,13 @@ // limitations under the License. pub mod display; -pub mod unit; +pub mod compile_test; pub mod expected_result; pub mod test_emitter; pub mod engine; pub use self::display::*; -pub use self::unit::*; +pub use self::compile_test::*; pub use self::expected_result::*; pub use self::test_emitter::*; pub use self::engine::*;