From 14368fafb89c36b5b47ad5bbdd6ae84f7f53a3cb Mon Sep 17 00:00:00 2001 From: rvcas Date: Tue, 24 Nov 2020 21:47:25 -0500 Subject: [PATCH 01/12] quick commit --- compiler/module/src/symbol.rs | 6 +++++ examples/effect/Main.roc | 36 +++++-------------------- examples/effect/platform/Pkg-Config.roc | 2 +- examples/effect/platform/Task.roc | 9 +++++++ 4 files changed, 23 insertions(+), 30 deletions(-) create mode 100644 examples/effect/platform/Task.roc diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 351edbee69..468996317a 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -312,6 +312,12 @@ impl fmt::Debug for ModuleId { /// Stores a mapping between ModuleId and InlinableString. /// +/// base.Task +/// 1. build mapping from short name to package +/// 2. when adding new modules from package we need to register them in some other map (this module id goes with short name) (shortname, module-name) -> moduleId +/// 3. pass this around to other modules getting headers parsed. when parsing interfaces we need to use this map to reference shortnames +/// 4. throw away short names. stash the module id in the can env under the resolved module name +/// 5. test: /// Each module name is stored twice, for faster lookups. /// Since these are interned strings, this shouldn't result in many total allocations in practice. #[derive(Debug, Clone)] diff --git a/examples/effect/Main.roc b/examples/effect/Main.roc index c13c2afb63..1fda6417ab 100644 --- a/examples/effect/Main.roc +++ b/examples/effect/Main.roc @@ -1,31 +1,9 @@ -app "effect-example" provides [ main ] imports [ Effect, RBTree ] +app "effect-example" + packages { base: "./platform" } + imports [ base.Task.{ Task, after } ] + provides [ main ] to base -toAndFro : Int -toAndFro = - empty : RBTree.Dict Int {} - empty = RBTree.empty - - empty - |> (\d -> RBTree.insert 1 {} d) - |> RBTree.toList - |> List.len - - - - -main : Effect.Effect {} as Fx +main : Task {} main = - # if RBTree.isEmpty empty then - if toAndFro == 2 then - Effect.putLine "Yay" - |> Effect.after (\{} -> Effect.getLine) - |> Effect.after (\line -> Effect.putLine line) - else - Effect.putLine "Nay" - - -# Effect.always "Write a thing" -# |> Effect.map (\line -> Str.concat line "!") -# |> Effect.after (\line -> Effect.putLine line) -# |> Effect.after (\{} -> Effect.getLine) -# |> Effect.after (\line -> Effect.putLine line) + Task.putLine "Hello world" + \ No newline at end of file diff --git a/examples/effect/platform/Pkg-Config.roc b/examples/effect/platform/Pkg-Config.roc index ec2c67ca43..78afc1799e 100644 --- a/examples/effect/platform/Pkg-Config.roc +++ b/examples/effect/platform/Pkg-Config.roc @@ -1,6 +1,6 @@ platform folkertdev/foo requires { main : Effect {} } - exposes [] + exposes [ Task ] packages {} imports [] provides [ mainForHost ] diff --git a/examples/effect/platform/Task.roc b/examples/effect/platform/Task.roc new file mode 100644 index 0000000000..10722f5905 --- /dev/null +++ b/examples/effect/platform/Task.roc @@ -0,0 +1,9 @@ +interface Task + exposes [ Task, putLine, after ] + imports [ Effect ] + +Task a : Effect.Effect a + +putLine = Effect.putLine + +after = Effect.after From f72a63edbb6d84243614b97b7effb558b656ccaf Mon Sep 17 00:00:00 2001 From: rvcas Date: Sat, 28 Nov 2020 15:42:29 -0500 Subject: [PATCH 02/12] feat: build a map of package qualified module names --- compiler/load/src/file.rs | 89 +++++++++++++++++++++++++++++------ compiler/module/src/ident.rs | 5 ++ compiler/module/src/symbol.rs | 73 +++++++++++++++++++++++++++- 3 files changed, 150 insertions(+), 17 deletions(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 0175e0bb77..ddc3cb3dc7 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -13,8 +13,8 @@ use roc_constrain::module::{ constrain_imports, pre_constrain_imports, ConstrainableImports, Import, }; use roc_constrain::module::{constrain_module, ExposedModuleTypes, SubsByModule}; -use roc_module::ident::{Ident, Lowercase, ModuleName, TagName}; -use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, Symbol}; +use roc_module::ident::{Ident, Lowercase, ModuleName, QualifiedModuleName, TagName}; +use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol}; use roc_mono::ir::{ CapturedSymbols, ExternalSpecializations, PartialProc, PendingSpecialization, Proc, Procs, }; @@ -346,6 +346,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> // Provide mutexes of ModuleIds and IdentIds by module, // so other modules can populate them as they load. module_ids: Arc::clone(&state.arc_modules), + package_module_ids: Arc::clone(&state.arc_package_modules), ident_ids_by_module: Arc::clone(&state.ident_ids_by_module), mode: state.stdlib.mode, } @@ -690,6 +691,7 @@ struct State<'a> { /// From now on, these will be used by multiple threads; time to make an Arc>! pub arc_modules: Arc>, + pub arc_package_modules: Arc>>, pub ident_ids_by_module: Arc>>, @@ -819,6 +821,7 @@ enum BuildTask<'a> { LoadModule { module_name: ModuleName, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, mode: Mode, }, @@ -989,6 +992,7 @@ pub fn load_and_monomorphize_from_str<'a>( struct LoadStart<'a> { pub arc_modules: Arc>, + pub arc_package_modules: Arc>>, pub ident_ids_by_module: Arc>>, pub root_id: ModuleId, pub root_msg: Msg<'a>, @@ -1001,6 +1005,7 @@ impl<'a> LoadStart<'a> { mode: Mode, ) -> Result { let arc_modules = Arc::new(Mutex::new(ModuleIds::default())); + let arc_package_modules = Arc::new(Mutex::new(PackageModuleIds::default())); let root_exposed_ident_ids = IdentIds::exposed_builtins(0); let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids)); @@ -1012,6 +1017,7 @@ impl<'a> LoadStart<'a> { arena, filename, Arc::clone(&arc_modules), + Arc::clone(&arc_package_modules), Arc::clone(&ident_ids_by_module), root_start_time, mode, @@ -1020,6 +1026,7 @@ impl<'a> LoadStart<'a> { Ok(LoadStart { arc_modules, + arc_package_modules, ident_ids_by_module, root_id, root_msg, @@ -1033,6 +1040,7 @@ impl<'a> LoadStart<'a> { mode: Mode, ) -> Result { let arc_modules = Arc::new(Mutex::new(ModuleIds::default())); + let arc_package_modules = Arc::new(Mutex::new(PackageModuleIds::default())); let root_exposed_ident_ids = IdentIds::exposed_builtins(0); let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids)); @@ -1045,6 +1053,7 @@ impl<'a> LoadStart<'a> { filename, src, Arc::clone(&arc_modules), + Arc::clone(&arc_package_modules), Arc::clone(&ident_ids_by_module), root_start_time, mode, @@ -1053,6 +1062,7 @@ impl<'a> LoadStart<'a> { Ok(LoadStart { arc_modules, + arc_package_modules, ident_ids_by_module, root_id, root_msg, @@ -1121,6 +1131,7 @@ where { let LoadStart { arc_modules, + arc_package_modules, ident_ids_by_module, root_id, root_msg, @@ -1256,6 +1267,7 @@ where headers_parsed, loading_started, arc_modules, + arc_package_modules, constrained_ident_ids: IdentIds::exposed_builtins(0), ident_ids_by_module, declarations_by_id: MutMap::default(), @@ -1913,6 +1925,7 @@ fn load_module<'a>( src_dir: &Path, module_name: ModuleName, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, mode: Mode, ) -> Result<(ModuleId, Msg<'a>), LoadingProblem> { @@ -1933,6 +1946,7 @@ fn load_module<'a>( arena, filename, module_ids, + package_module_ids, ident_ids_by_module, module_start_time, mode, @@ -1971,6 +1985,7 @@ fn parse_header<'a>( read_file_duration: Duration, filename: PathBuf, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, mode: Mode, src_bytes: &'a [u8], @@ -1998,6 +2013,7 @@ fn parse_header<'a>( header.imports.into_bump_slice(), parse_state, module_ids, + package_module_ids, ident_ids_by_module, module_timing, )), @@ -2015,6 +2031,7 @@ fn parse_header<'a>( header.imports.into_bump_slice(), parse_state, module_ids.clone(), + package_module_ids, ident_ids_by_module.clone(), module_timing, ); @@ -2059,6 +2076,7 @@ fn load_filename<'a>( arena: &'a Bump, filename: PathBuf, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, module_start_time: SystemTime, mode: Mode, @@ -2073,6 +2091,7 @@ fn load_filename<'a>( file_io_duration, filename, module_ids, + package_module_ids, ident_ids_by_module, mode, arena.alloc(bytes), @@ -2092,6 +2111,7 @@ fn load_from_str<'a>( filename: PathBuf, src: &'a str, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, module_start_time: SystemTime, mode: Mode, @@ -2104,6 +2124,7 @@ fn load_from_str<'a>( file_io_duration, filename, module_ids, + package_module_ids, ident_ids_by_module, mode, src.as_bytes(), @@ -2126,6 +2147,7 @@ fn send_header<'a>( imports: &'a [Located>], parse_state: parser::State<'a>, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, module_timing: ModuleTiming, ) -> (ModuleId, Msg<'a>) { @@ -2141,16 +2163,18 @@ fn send_header<'a>( } }; - let mut imported: Vec<(ModuleName, Vec, Region)> = Vec::with_capacity(imports.len()); + let mut imported: Vec<(QualifiedModuleName, Vec, Region)> = + Vec::with_capacity(imports.len()); let mut imported_modules: MutSet = MutSet::default(); + let mut imported_package_modules: MutSet = MutSet::default(); let mut scope_size = 0; for loc_entry in imports { - let (module_name, exposed) = exposed_from_import(&loc_entry.value); + let (qualified_module_name, exposed) = exposed_from_import(&loc_entry.value); scope_size += exposed.len(); - imported.push((module_name, exposed, loc_entry.region)); + imported.push((qualified_module_name, exposed, loc_entry.region)); } let num_exposes = exposes.len(); @@ -2167,6 +2191,7 @@ fn send_header<'a>( let ident_ids = { // Lock just long enough to perform the minimal operations necessary. let mut module_ids = (*module_ids).lock(); + let mut package_module_ids = (*package_module_ids).lock(); let mut ident_ids_by_module = (*ident_ids_by_module).lock(); home = module_ids.get_or_insert(&declared_name.as_inline_str()); @@ -2178,16 +2203,30 @@ fn send_header<'a>( // For each of our imports, add an entry to deps_by_name // - // e.g. for `imports [ Foo.{ bar } ]`, add `Foo` to deps_by_name + // e.g. for `imports [ base.Foo.{ bar } ]`, add `Foo` to deps_by_name // // Also build a list of imported_values_to_expose (like `bar` above.) - for (module_name, exposed_idents, region) in imported.into_iter() { - let cloned_module_name = module_name.clone(); - let module_id = module_ids.get_or_insert(&module_name.into()); + for (qualified_module_name, exposed_idents, region) in imported.into_iter() { + let cloned_module_name = qualified_module_name.module.clone(); + let module_id = match qualified_module_name.opt_package { + None => { + let id = module_ids.get_or_insert(&qualified_module_name.module.into()); - deps_by_name.insert(cloned_module_name, module_id); + imported_modules.insert(id); - imported_modules.insert(module_id); + deps_by_name.insert(cloned_module_name, id); + + id + } + Some(package) => { + let id = + package_module_ids.get_or_insert(&(package, cloned_module_name.into())); + + imported_package_modules.insert(id); + + id + } + }; // Add the new exposed idents to the dep module's IdentIds, so // once that module later gets loaded, its lookups will resolve @@ -2236,6 +2275,8 @@ fn send_header<'a>( ident_ids.clone() }; + dbg!(package_module_ids); + // Send the deps to the coordinator thread for processing, // then continue on to parsing and canonicalizing defs. // @@ -2782,7 +2823,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi Ok(Msg::Parsed(parsed)) } -fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec) { +fn exposed_from_import<'a>(entry: &ImportsEntry<'a>) -> (QualifiedModuleName<'a>, Vec) { use roc_parse::header::ImportsEntry::*; match entry { @@ -2793,11 +2834,27 @@ fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec) { exposed.push(ident_from_exposed(&loc_entry.value)); } - (module_name.as_str().into(), exposed) + let qualified_module_name = QualifiedModuleName { + opt_package: None, + module: module_name.as_str().into(), + }; + + (qualified_module_name, exposed) } - Package(_package_name, _module_name, _exposes) => { - todo!("TODO support exposing package-qualified module names."); + Package(package_name, module_name, exposes) => { + let mut exposed = Vec::with_capacity(exposes.len()); + + for loc_entry in exposes { + exposed.push(ident_from_exposed(&loc_entry.value)); + } + + let qualified_module_name = QualifiedModuleName { + opt_package: Some(package_name), + module: module_name.as_str().into(), + }; + + (qualified_module_name, exposed) } SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => { @@ -3074,6 +3131,7 @@ fn run_task<'a>( LoadModule { module_name, module_ids, + package_module_ids, ident_ids_by_module, mode, } => load_module( @@ -3081,6 +3139,7 @@ fn run_task<'a>( src_dir, module_name, module_ids, + package_module_ids, ident_ids_by_module, mode, ) diff --git a/compiler/module/src/ident.rs b/compiler/module/src/ident.rs index f3bcb53561..438fa88060 100644 --- a/compiler/module/src/ident.rs +++ b/compiler/module/src/ident.rs @@ -12,6 +12,11 @@ impl Ident { } } +pub struct QualifiedModuleName<'a> { + pub opt_package: Option<&'a str>, + pub module: ModuleName, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ModuleName(InlinableString); diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 44fd48637f..c8c9b3cd67 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -310,14 +310,71 @@ impl fmt::Debug for ModuleId { } } -/// Stores a mapping between ModuleId and InlinableString. -/// /// base.Task /// 1. build mapping from short name to package /// 2. when adding new modules from package we need to register them in some other map (this module id goes with short name) (shortname, module-name) -> moduleId /// 3. pass this around to other modules getting headers parsed. when parsing interfaces we need to use this map to reference shortnames /// 4. throw away short names. stash the module id in the can env under the resolved module name /// 5. test: + +type PackageModule<'a> = (&'a str, InlinableString); + +#[derive(Debug, Clone)] +pub struct PackageModuleIds<'a> { + by_name: MutMap, ModuleId>, + by_id: Vec>, +} + +impl<'a> PackageModuleIds<'a> { + pub fn get_or_insert(&mut self, module_name: &PackageModule<'a>) -> ModuleId { + match self.by_name.get(module_name) { + Some(id) => *id, + None => { + let by_id = &mut self.by_id; + let module_id = ModuleId(by_id.len() as u32); + + by_id.push(module_name.clone()); + + self.by_name.insert(module_name.clone(), module_id); + + if cfg!(debug_assertions) { + Self::insert_debug_name(module_id, &module_name); + } + + module_id + } + } + } + + #[cfg(debug_assertions)] + fn insert_debug_name(module_id: ModuleId, module_name: &PackageModule) { + let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked."); + + let (_package, module) = module_name; + + names.insert(module_id.0, module.to_string().into()); + } + + #[cfg(not(debug_assertions))] + fn insert_debug_name(_module_id: ModuleId, _module_name: &PackageModule) { + // By design, this is a no-op in release builds! + } + + pub fn get_id(&self, module_name: &PackageModule<'a>) -> Option<&ModuleId> { + self.by_name.get(module_name) + } + + pub fn get_name(&self, id: ModuleId) -> Option<&PackageModule> { + self.by_id.get(id.0 as usize) + } + + pub fn available_modules(&self) -> impl Iterator { + self.by_id.iter() + } +} + +/// Stores a mapping between ModuleId and InlinableString. +/// /// Each module name is stored twice, for faster lookups. /// Since these are interned strings, this shouldn't result in many total allocations in practice. #[derive(Debug, Clone)] @@ -557,6 +614,18 @@ macro_rules! define_builtins { } } + impl<'a> Default for PackageModuleIds<'a> { + fn default() -> Self { + // +1 because the user will be compiling at least 1 non-builtin module! + let capacity = $total + 1; + + let by_name = HashMap::with_capacity_and_hasher(capacity, default_hasher()); + let by_id = Vec::with_capacity(capacity); + + PackageModuleIds { by_name, by_id } + } + } + impl Symbol { $( $( From 4f19eedce442258f73560ebcb2a88026515597e3 Mon Sep 17 00:00:00 2001 From: rvcas Date: Tue, 1 Dec 2020 23:02:25 -0500 Subject: [PATCH 03/12] chore: comment out unused stuff to reduce noise --- compiler/gen_dev/tests/gen_num.rs | 6 +- compiler/gen_dev/tests/helpers/eval.rs | 381 ++++++++++++------------- 2 files changed, 193 insertions(+), 194 deletions(-) diff --git a/compiler/gen_dev/tests/gen_num.rs b/compiler/gen_dev/tests/gen_num.rs index c2550052bc..e820b017b7 100644 --- a/compiler/gen_dev/tests/gen_num.rs +++ b/compiler/gen_dev/tests/gen_num.rs @@ -1,7 +1,7 @@ -#[macro_use] +// #[macro_use] extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +// #[macro_use] +// extern crate indoc; extern crate bumpalo; extern crate libc; diff --git a/compiler/gen_dev/tests/helpers/eval.rs b/compiler/gen_dev/tests/helpers/eval.rs index 0108211709..18a0508ce5 100644 --- a/compiler/gen_dev/tests/helpers/eval.rs +++ b/compiler/gen_dev/tests/helpers/eval.rs @@ -1,233 +1,232 @@ -use libloading::Library; -use roc_build::link::{link, LinkType}; -use roc_collections::all::MutMap; -use tempfile::tempdir; +// use libloading::Library; +// use roc_build::link::{link, LinkType}; +// use roc_collections::all::MutMap; +// use tempfile::tempdir; -fn promote_expr_to_module(src: &str) -> String { - let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); +// fn promote_expr_to_module(src: &str) -> String { +// let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); - for line in src.lines() { - // indent the body! - buffer.push_str(" "); - buffer.push_str(line); - buffer.push('\n'); - } +// for line in src.lines() { +// // indent the body! +// buffer.push_str(" "); +// buffer.push_str(line); +// buffer.push('\n'); +// } - buffer -} +// buffer +// } -pub fn helper<'a>( - arena: &'a bumpalo::Bump, - src: &str, - stdlib: roc_builtins::std::StdLib, - _leak: bool, - lazy_literals: bool, -) -> (String, Vec, Library) { - use std::path::{Path, PathBuf}; +// pub fn helper<'a>( +// arena: &'a bumpalo::Bump, +// src: &str, +// stdlib: roc_builtins::std::StdLib, +// _leak: bool, +// lazy_literals: bool, +// ) -> (String, Vec, Library) { +// use std::path::{Path, PathBuf}; - //let stdlib_mode = stdlib.mode; - let dir = tempdir().unwrap(); - let filename = PathBuf::from("Test.roc"); - let src_dir = Path::new("fake/test/path"); - let app_o_file = dir.path().join("app.o"); +// //let stdlib_mode = stdlib.mode; +// let dir = tempdir().unwrap(); +// let filename = PathBuf::from("Test.roc"); +// let src_dir = Path::new("fake/test/path"); +// let app_o_file = dir.path().join("app.o"); - let module_src; - let temp; - if src.starts_with("app") { - // this is already a module - module_src = src; - } else { - // this is an expression, promote it to a module - temp = promote_expr_to_module(src); - module_src = &temp; - } +// let module_src; +// let temp; +// if src.starts_with("app") { +// // this is already a module +// module_src = src; +// } else { +// // this is an expression, promote it to a module +// temp = promote_expr_to_module(src); +// module_src = &temp; +// } - let exposed_types = MutMap::default(); - let loaded = roc_load::file::load_and_monomorphize_from_str( - arena, - filename, - &module_src, - stdlib, - src_dir, - exposed_types, - ); +// let exposed_types = MutMap::default(); +// let loaded = roc_load::file::load_and_monomorphize_from_str( +// arena, +// filename, +// &module_src, +// stdlib, +// src_dir, +// exposed_types, +// ); - let mut loaded = loaded.expect("failed to load module"); +// let mut loaded = loaded.expect("failed to load module"); - use roc_load::file::MonomorphizedModule; - let MonomorphizedModule { - procedures, - interns, - exposed_to_host, - .. - } = loaded; +// use roc_load::file::MonomorphizedModule; +// let MonomorphizedModule { +// procedures, +// interns, +// exposed_to_host, +// .. +// } = loaded; - /* - println!("=========== Procedures =========="); - println!("{:?}", procedures); - println!("=================================\n"); +// /* +// println!("=========== Procedures =========="); +// println!("{:?}", procedures); +// println!("=================================\n"); - println!("=========== Interns =========="); - println!("{:?}", interns); - println!("=================================\n"); +// println!("=========== Interns =========="); +// println!("{:?}", interns); +// println!("=================================\n"); - println!("=========== Exposed =========="); - println!("{:?}", exposed_to_host); - println!("=================================\n"); - */ +// println!("=========== Exposed =========="); +// println!("{:?}", exposed_to_host); +// println!("=================================\n"); +// */ +// debug_assert_eq!(exposed_to_host.len(), 1); +// let main_fn_symbol = exposed_to_host.keys().copied().nth(0).unwrap(); - debug_assert_eq!(exposed_to_host.len(), 1); - let main_fn_symbol = exposed_to_host.keys().copied().nth(0).unwrap(); +// let (_, main_fn_layout) = procedures +// .keys() +// .find(|(s, _)| *s == main_fn_symbol) +// .unwrap() +// .clone(); +// let mut layout_ids = roc_mono::layout::LayoutIds::default(); +// let main_fn_name = layout_ids +// .get(main_fn_symbol, &main_fn_layout) +// .to_symbol_string(main_fn_symbol, &interns); - let (_, main_fn_layout) = procedures - .keys() - .find(|(s, _)| *s == main_fn_symbol) - .unwrap() - .clone(); - let mut layout_ids = roc_mono::layout::LayoutIds::default(); - let main_fn_name = layout_ids - .get(main_fn_symbol, &main_fn_layout) - .to_symbol_string(main_fn_symbol, &interns); +// let mut lines = Vec::new(); +// // errors whose reporting we delay (so we can see that code gen generates runtime errors) +// let mut delayed_errors = Vec::new(); - let mut lines = Vec::new(); - // errors whose reporting we delay (so we can see that code gen generates runtime errors) - let mut delayed_errors = Vec::new(); +// for (home, (module_path, src)) in loaded.sources { +// use roc_reporting::report::{ +// can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE, +// }; - for (home, (module_path, src)) in loaded.sources { - use roc_reporting::report::{ - can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE, - }; +// let can_problems = loaded.can_problems.remove(&home).unwrap_or_default(); +// let type_problems = loaded.type_problems.remove(&home).unwrap_or_default(); +// let mono_problems = loaded.mono_problems.remove(&home).unwrap_or_default(); - let can_problems = loaded.can_problems.remove(&home).unwrap_or_default(); - let type_problems = loaded.type_problems.remove(&home).unwrap_or_default(); - let mono_problems = loaded.mono_problems.remove(&home).unwrap_or_default(); +// let error_count = can_problems.len() + type_problems.len() + mono_problems.len(); - let error_count = can_problems.len() + type_problems.len() + mono_problems.len(); +// if error_count == 0 { +// continue; +// } - if error_count == 0 { - continue; - } +// let src_lines: Vec<&str> = src.split('\n').collect(); +// let palette = DEFAULT_PALETTE; - let src_lines: Vec<&str> = src.split('\n').collect(); - let palette = DEFAULT_PALETTE; +// // Report parsing and canonicalization problems +// let alloc = RocDocAllocator::new(&src_lines, home, &interns); - // Report parsing and canonicalization problems - let alloc = RocDocAllocator::new(&src_lines, home, &interns); +// use roc_problem::can::Problem::*; +// for problem in can_problems.into_iter() { +// // Ignore "unused" problems +// match problem { +// UnusedDef(_, _) | UnusedArgument(_, _, _) | UnusedImport(_, _) => { +// delayed_errors.push(problem); +// continue; +// } +// _ => { +// let report = can_problem(&alloc, module_path.clone(), problem); +// let mut buf = String::new(); - use roc_problem::can::Problem::*; - for problem in can_problems.into_iter() { - // Ignore "unused" problems - match problem { - UnusedDef(_, _) | UnusedArgument(_, _, _) | UnusedImport(_, _) => { - delayed_errors.push(problem); - continue; - } - _ => { - let report = can_problem(&alloc, module_path.clone(), problem); - let mut buf = String::new(); +// report.render_color_terminal(&mut buf, &alloc, &palette); - report.render_color_terminal(&mut buf, &alloc, &palette); +// lines.push(buf); +// } +// } +// } - lines.push(buf); - } - } - } +// for problem in type_problems { +// let report = type_problem(&alloc, module_path.clone(), problem); +// let mut buf = String::new(); - for problem in type_problems { - let report = type_problem(&alloc, module_path.clone(), problem); - let mut buf = String::new(); +// report.render_color_terminal(&mut buf, &alloc, &palette); - report.render_color_terminal(&mut buf, &alloc, &palette); +// lines.push(buf); +// } - lines.push(buf); - } +// for problem in mono_problems { +// let report = mono_problem(&alloc, module_path.clone(), problem); +// let mut buf = String::new(); - for problem in mono_problems { - let report = mono_problem(&alloc, module_path.clone(), problem); - let mut buf = String::new(); +// report.render_color_terminal(&mut buf, &alloc, &palette); - report.render_color_terminal(&mut buf, &alloc, &palette); +// lines.push(buf); +// } +// } - lines.push(buf); - } - } +// if !lines.is_empty() { +// println!("{}", lines.join("\n")); +// assert_eq!(0, 1, "Mistakes were made"); +// } - if !lines.is_empty() { - println!("{}", lines.join("\n")); - assert_eq!(0, 1, "Mistakes were made"); - } +// let env = roc_gen_dev::Env { +// arena, +// interns, +// exposed_to_host: exposed_to_host.keys().copied().collect(), +// lazy_literals, +// }; - let env = roc_gen_dev::Env { - arena, - interns, - exposed_to_host: exposed_to_host.keys().copied().collect(), - lazy_literals, - }; +// let target = target_lexicon::Triple::host(); +// let module_object = +// roc_gen_dev::build_module(&env, &target, procedures).expect("failed to compile module"); - let target = target_lexicon::Triple::host(); - let module_object = - roc_gen_dev::build_module(&env, &target, procedures).expect("failed to compile module"); +// let module_out = module_object +// .write() +// .expect("failed to build output object"); +// std::fs::write(&app_o_file, module_out).expect("failed to write object to file"); - let module_out = module_object - .write() - .expect("failed to build output object"); - std::fs::write(&app_o_file, module_out).expect("failed to write object to file"); +// let (mut child, dylib_path) = link( +// &target, +// app_o_file.clone(), +// &[app_o_file.to_str().unwrap()], +// LinkType::Dylib, +// ) +// .expect("failed to link dynamic library"); - let (mut child, dylib_path) = link( - &target, - app_o_file.clone(), - &[app_o_file.to_str().unwrap()], - LinkType::Dylib, - ) - .expect("failed to link dynamic library"); +// child.wait().unwrap(); - child.wait().unwrap(); +// // Load the dylib +// let path = dylib_path.as_path().to_str().unwrap(); - // Load the dylib - let path = dylib_path.as_path().to_str().unwrap(); +// // std::fs::copy(&app_o_file, "/tmp/app.o").unwrap(); +// // std::fs::copy(&path, "/tmp/libapp.so").unwrap(); - // std::fs::copy(&app_o_file, "/tmp/app.o").unwrap(); - // std::fs::copy(&path, "/tmp/libapp.so").unwrap(); +// let lib = Library::new(path).expect("failed to load shared library"); - let lib = Library::new(path).expect("failed to load shared library"); +// (main_fn_name, delayed_errors, lib) +// } - (main_fn_name, delayed_errors, lib) -} +// #[macro_export] +// macro_rules! assert_evals_to { +// ($src:expr, $expected:expr, $ty:ty) => {{ +// assert_evals_to!($src, $expected, $ty, (|val| val)); +// }}; +// ($src:expr, $expected:expr, $ty:ty, $transform:expr) => { +// // Same as above, except with an additional transformation argument. +// { +// assert_evals_to!($src, $expected, $ty, $transform, true); +// } +// }; +// ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr) => { +// // Run both with and without lazy literal optimization. +// { +// assert_evals_to!($src, $expected, $ty, $transform, $leak, false); +// } +// { +// assert_evals_to!($src, $expected, $ty, $transform, $leak, true); +// } +// }; +// ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr, $lazy_literals:expr) => { +// use bumpalo::Bump; +// use roc_gen_dev::run_jit_function_raw; +// let stdlib = roc_builtins::std::standard_stdlib(); -#[macro_export] -macro_rules! assert_evals_to { - ($src:expr, $expected:expr, $ty:ty) => {{ - assert_evals_to!($src, $expected, $ty, (|val| val)); - }}; - ($src:expr, $expected:expr, $ty:ty, $transform:expr) => { - // Same as above, except with an additional transformation argument. - { - assert_evals_to!($src, $expected, $ty, $transform, true); - } - }; - ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr) => { - // Run both with and without lazy literal optimization. - { - assert_evals_to!($src, $expected, $ty, $transform, $leak, false); - } - { - assert_evals_to!($src, $expected, $ty, $transform, $leak, true); - } - }; - ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr, $lazy_literals:expr) => { - use bumpalo::Bump; - use roc_gen_dev::run_jit_function_raw; - let stdlib = roc_builtins::std::standard_stdlib(); +// let arena = Bump::new(); +// let (main_fn_name, errors, lib) = +// $crate::helpers::eval::helper(&arena, $src, stdlib, $leak, $lazy_literals); - let arena = Bump::new(); - let (main_fn_name, errors, lib) = - $crate::helpers::eval::helper(&arena, $src, stdlib, $leak, $lazy_literals); - - let transform = |success| { - let expected = $expected; - let given = $transform(success); - assert_eq!(&given, &expected); - }; - run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors) - }; -} +// let transform = |success| { +// let expected = $expected; +// let given = $transform(success); +// assert_eq!(&given, &expected); +// }; +// run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors) +// }; +// } From bddc69896c76b5914a2a4c80dec64d5e499fbefe Mon Sep 17 00:00:00 2001 From: rvcas Date: Tue, 1 Dec 2020 23:03:31 -0500 Subject: [PATCH 04/12] feat: do not hardcode the platform path --- compiler/load/src/file.rs | 74 ++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index ddc3cb3dc7..594344faf6 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -20,7 +20,9 @@ use roc_mono::ir::{ }; use roc_mono::layout::{Layout, LayoutCache}; use roc_parse::ast::{self, Attempting, StrLiteral, TypeAnnotation}; -use roc_parse::header::{ExposesEntry, ImportsEntry, PlatformHeader, TypedIdent}; +use roc_parse::header::{ + ExposesEntry, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, TypedIdent, +}; use roc_parse::module::module_defs; use roc_parse::parser::{self, Fail, Parser}; use roc_region::all::{Located, Region}; @@ -542,6 +544,7 @@ struct ModuleHeader<'a> { exposed_ident_ids: IdentIds, deps_by_name: MutMap, imported_modules: MutSet, + imported_package_modules: MutSet, exposes: Vec, exposed_imports: MutMap, src: &'a [u8], @@ -2036,27 +2039,57 @@ fn parse_header<'a>( module_timing, ); - // check whether we can find a Pkg-Config.roc file - let mut pkg_config_roc = pkg_config_dir.clone(); - pkg_config_roc.push("platform"); - pkg_config_roc.push(PKG_CONFIG_FILE_NAME); - pkg_config_roc.set_extension(ROC_FILE_EXTENSION); + let opt_base_package = header.packages.iter().find(|loc_package_entry| { + let Located { value, .. } = loc_package_entry; - if pkg_config_roc.as_path().exists() { - let load_pkg_config_msg = load_pkg_config( - arena, - &pkg_config_dir, - module_ids, - ident_ids_by_module, - mode, - )?; + match value { + PackageEntry::Entry { shorthand, .. } => shorthand == &"base", + _ => false, + } + }); - Ok(( - module_id, - Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]), - )) - } else { - Ok((module_id, app_module_header_msg)) + match opt_base_package { + Some(Located { + value: + PackageEntry::Entry { + package_or_path: + Located { + value: package_or_path, + .. + }, + .. + }, + .. + }) => { + match package_or_path { + PackageOrPath::Path(StrLiteral::PlainLine(package)) => { + // check whether we can find a Pkg-Config.roc file + let mut pkg_config_roc = pkg_config_dir.clone(); + pkg_config_roc.push(package); + pkg_config_roc.push(PKG_CONFIG_FILE_NAME); + pkg_config_roc.set_extension(ROC_FILE_EXTENSION); + + if pkg_config_roc.as_path().exists() { + let load_pkg_config_msg = load_pkg_config( + arena, + &pkg_config_dir, + module_ids, + ident_ids_by_module, + mode, + )?; + + Ok(( + module_id, + Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]), + )) + } else { + Ok((module_id, app_module_header_msg)) + } + } + _ => panic!("TODO not yet implement none path platform imports"), + } + } + _ => panic!("could not find base"), } } Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module( @@ -2291,6 +2324,7 @@ fn send_header<'a>( exposed_ident_ids: ident_ids, module_name: loc_name.value, imported_modules, + imported_package_modules, deps_by_name, exposes: exposed, src: parse_state.bytes, From 4808611fc3f6ba70c708154ce3323aaeb5a0fd3b Mon Sep 17 00:00:00 2001 From: rvcas Date: Wed, 2 Dec 2020 21:53:15 -0500 Subject: [PATCH 05/12] fix: don't hard code base --- compiler/load/src/file.rs | 101 +++++++++++------- examples/effect/Main.roc | 2 +- .../platform-dir}/Cargo.lock | 0 .../platform-dir}/Cargo.toml | 0 .../platform-dir}/Pkg-Config.roc | 0 .../{platform => thing/platform-dir}/Task.roc | 0 .../{platform => thing/platform-dir}/host.c | 0 .../platform-dir}/src/lib.rs | 0 8 files changed, 61 insertions(+), 42 deletions(-) rename examples/effect/{platform => thing/platform-dir}/Cargo.lock (100%) rename examples/effect/{platform => thing/platform-dir}/Cargo.toml (100%) rename examples/effect/{platform => thing/platform-dir}/Pkg-Config.roc (100%) rename examples/effect/{platform => thing/platform-dir}/Task.roc (100%) rename examples/effect/{platform => thing/platform-dir}/host.c (100%) rename examples/effect/{platform => thing/platform-dir}/src/lib.rs (100%) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 594344faf6..01a743cc47 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -21,7 +21,7 @@ use roc_mono::ir::{ use roc_mono::layout::{Layout, LayoutCache}; use roc_parse::ast::{self, Attempting, StrLiteral, TypeAnnotation}; use roc_parse::header::{ - ExposesEntry, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, TypedIdent, + ExposesEntry, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, To, TypedIdent, }; use roc_parse::module::module_defs; use roc_parse::parser::{self, Fail, Parser}; @@ -2039,57 +2039,76 @@ fn parse_header<'a>( module_timing, ); - let opt_base_package = header.packages.iter().find(|loc_package_entry| { - let Located { value, .. } = loc_package_entry; + match header.to.value { + To::ExistingPackage(existing_package) => { + let opt_base_package = header.packages.iter().find(|loc_package_entry| { + let Located { value, .. } = loc_package_entry; - match value { - PackageEntry::Entry { shorthand, .. } => shorthand == &"base", - _ => false, - } - }); + match value { + PackageEntry::Entry { shorthand, .. } => shorthand == &existing_package, + _ => false, + } + }); - match opt_base_package { - Some(Located { - value: - PackageEntry::Entry { - package_or_path: - Located { - value: package_or_path, + match opt_base_package { + Some(Located { + value: + PackageEntry::Entry { + package_or_path: + Located { + value: package_or_path, + .. + }, .. }, .. - }, - .. - }) => { - match package_or_path { - PackageOrPath::Path(StrLiteral::PlainLine(package)) => { - // check whether we can find a Pkg-Config.roc file - let mut pkg_config_roc = pkg_config_dir.clone(); - pkg_config_roc.push(package); - pkg_config_roc.push(PKG_CONFIG_FILE_NAME); - pkg_config_roc.set_extension(ROC_FILE_EXTENSION); + }) => { + match package_or_path { + PackageOrPath::Path(StrLiteral::PlainLine(package)) => { + // check whether we can find a Pkg-Config.roc file + let mut pkg_config_roc = pkg_config_dir.clone(); + pkg_config_roc.push(package); + pkg_config_roc.push(PKG_CONFIG_FILE_NAME); + pkg_config_roc.set_extension(ROC_FILE_EXTENSION); - if pkg_config_roc.as_path().exists() { - let load_pkg_config_msg = load_pkg_config( - arena, - &pkg_config_dir, - module_ids, - ident_ids_by_module, - mode, - )?; + if pkg_config_roc.as_path().exists() { + let load_pkg_config_msg = load_pkg_config( + arena, + &pkg_config_dir, + module_ids, + ident_ids_by_module, + mode, + )?; - Ok(( - module_id, - Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]), - )) - } else { - Ok((module_id, app_module_header_msg)) + Ok(( + module_id, + Msg::Many(vec![ + app_module_header_msg, + load_pkg_config_msg, + ]), + )) + } else { + Ok((module_id, app_module_header_msg)) + } + } + _ => unreachable!(), } } - _ => panic!("TODO not yet implement none path platform imports"), + _ => panic!("could not find base"), } } - _ => panic!("could not find base"), + To::NewPackage(package_or_path) => match package_or_path { + PackageOrPath::Package(_, _) => panic!("TODO implement packages"), + PackageOrPath::Path(StrLiteral::PlainLine(_package)) => { + panic!("TODO implement plain line package path") + } + PackageOrPath::Path(StrLiteral::Block(_)) => { + panic!("TODO implement block package path") + } + PackageOrPath::Path(StrLiteral::Line(_)) => { + panic!("TODO implement line package path") + } + }, } } Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module( diff --git a/examples/effect/Main.roc b/examples/effect/Main.roc index d200fad75a..59aaeedf94 100644 --- a/examples/effect/Main.roc +++ b/examples/effect/Main.roc @@ -1,5 +1,5 @@ app "effect-example" - packages { base: "./platform" } + packages { base: "./thing/platform-dir" } imports [ base.Task.{ Task, after } ] provides [ main ] to base diff --git a/examples/effect/platform/Cargo.lock b/examples/effect/thing/platform-dir/Cargo.lock similarity index 100% rename from examples/effect/platform/Cargo.lock rename to examples/effect/thing/platform-dir/Cargo.lock diff --git a/examples/effect/platform/Cargo.toml b/examples/effect/thing/platform-dir/Cargo.toml similarity index 100% rename from examples/effect/platform/Cargo.toml rename to examples/effect/thing/platform-dir/Cargo.toml diff --git a/examples/effect/platform/Pkg-Config.roc b/examples/effect/thing/platform-dir/Pkg-Config.roc similarity index 100% rename from examples/effect/platform/Pkg-Config.roc rename to examples/effect/thing/platform-dir/Pkg-Config.roc diff --git a/examples/effect/platform/Task.roc b/examples/effect/thing/platform-dir/Task.roc similarity index 100% rename from examples/effect/platform/Task.roc rename to examples/effect/thing/platform-dir/Task.roc diff --git a/examples/effect/platform/host.c b/examples/effect/thing/platform-dir/host.c similarity index 100% rename from examples/effect/platform/host.c rename to examples/effect/thing/platform-dir/host.c diff --git a/examples/effect/platform/src/lib.rs b/examples/effect/thing/platform-dir/src/lib.rs similarity index 100% rename from examples/effect/platform/src/lib.rs rename to examples/effect/thing/platform-dir/src/lib.rs From 6d4ecc8023dd4e33a90bbef510a75af62a6d7825 Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 3 Dec 2020 19:10:10 -0500 Subject: [PATCH 06/12] feat: handle plain line package --- compiler/load/src/file.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 01a743cc47..19b0acba38 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -2099,8 +2099,29 @@ fn parse_header<'a>( } To::NewPackage(package_or_path) => match package_or_path { PackageOrPath::Package(_, _) => panic!("TODO implement packages"), - PackageOrPath::Path(StrLiteral::PlainLine(_package)) => { - panic!("TODO implement plain line package path") + PackageOrPath::Path(StrLiteral::PlainLine(package)) => { + // check whether we can find a Pkg-Config.roc file + let mut pkg_config_roc = pkg_config_dir.clone(); + pkg_config_roc.push(package); + pkg_config_roc.push(PKG_CONFIG_FILE_NAME); + pkg_config_roc.set_extension(ROC_FILE_EXTENSION); + + if pkg_config_roc.as_path().exists() { + let load_pkg_config_msg = load_pkg_config( + arena, + &pkg_config_dir, + module_ids, + ident_ids_by_module, + mode, + )?; + + Ok(( + module_id, + Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]), + )) + } else { + Ok((module_id, app_module_header_msg)) + } } PackageOrPath::Path(StrLiteral::Block(_)) => { panic!("TODO implement block package path") From 654a01810660bdea97e8da4cb190f6a7dc558bc8 Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 3 Dec 2020 20:06:25 -0500 Subject: [PATCH 07/12] chore: remove load pkg config from plain line --- compiler/load/src/file.rs | 41 +++++++++++++++------------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 19b0acba38..b1f4fc09d5 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -830,6 +830,7 @@ enum BuildTask<'a> { }, LoadPkgConfig { module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, mode: Mode, }, @@ -1859,6 +1860,7 @@ fn load_pkg_config<'a>( arena: &'a Bump, src_dir: &Path, module_ids: Arc>, + package_module_ids: Arc>, ident_ids_by_module: Arc>>, mode: Mode, ) -> Result, LoadingProblem> { @@ -2034,7 +2036,7 @@ fn parse_header<'a>( header.imports.into_bump_slice(), parse_state, module_ids.clone(), - package_module_ids, + package_module_ids.clone(), ident_ids_by_module.clone(), module_timing, ); @@ -2054,6 +2056,7 @@ fn parse_header<'a>( Some(Located { value: PackageEntry::Entry { + shorthand, package_or_path: Located { value: package_or_path, @@ -2076,6 +2079,7 @@ fn parse_header<'a>( arena, &pkg_config_dir, module_ids, + package_module_ids, ident_ids_by_module, mode, )?; @@ -2099,29 +2103,8 @@ fn parse_header<'a>( } To::NewPackage(package_or_path) => match package_or_path { PackageOrPath::Package(_, _) => panic!("TODO implement packages"), - PackageOrPath::Path(StrLiteral::PlainLine(package)) => { - // check whether we can find a Pkg-Config.roc file - let mut pkg_config_roc = pkg_config_dir.clone(); - pkg_config_roc.push(package); - pkg_config_roc.push(PKG_CONFIG_FILE_NAME); - pkg_config_roc.set_extension(ROC_FILE_EXTENSION); - - if pkg_config_roc.as_path().exists() { - let load_pkg_config_msg = load_pkg_config( - arena, - &pkg_config_dir, - module_ids, - ident_ids_by_module, - mode, - )?; - - Ok(( - module_id, - Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]), - )) - } else { - Ok((module_id, app_module_header_msg)) - } + PackageOrPath::Path(StrLiteral::PlainLine(_package)) => { + Ok((module_id, app_module_header_msg)) } PackageOrPath::Path(StrLiteral::Block(_)) => { panic!("TODO implement block package path") @@ -3220,9 +3203,17 @@ fn run_task<'a>( .map(|(_, msg)| msg), LoadPkgConfig { module_ids, + package_module_ids, ident_ids_by_module, mode, - } => load_pkg_config(arena, src_dir, module_ids, ident_ids_by_module, mode), + } => load_pkg_config( + arena, + src_dir, + module_ids, + package_module_ids, + ident_ids_by_module, + mode, + ), Parse { header } => parse(arena, header), CanonicalizeAndConstrain { parsed, From f527afe9fd6753998bb66980cb35d83e7582510f Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 3 Dec 2020 20:30:19 -0500 Subject: [PATCH 08/12] feat: put all exposes from platform in package module ids --- compiler/load/src/file.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index b1f4fc09d5..fe69d787e0 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -829,6 +829,7 @@ enum BuildTask<'a> { mode: Mode, }, LoadPkgConfig { + shorthand: &'a str, module_ids: Arc>, package_module_ids: Arc>>, ident_ids_by_module: Arc>>, @@ -1859,8 +1860,9 @@ fn finish<'a>( fn load_pkg_config<'a>( arena: &'a Bump, src_dir: &Path, + shorthand: &'a str, module_ids: Arc>, - package_module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, mode: Mode, ) -> Result, LoadingProblem> { @@ -1906,7 +1908,9 @@ fn load_pkg_config<'a>( } Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module( arena, + shorthand, module_ids, + package_module_ids, ident_ids_by_module, mode, header, @@ -2078,6 +2082,7 @@ fn parse_header<'a>( let load_pkg_config_msg = load_pkg_config( arena, &pkg_config_dir, + shorthand, module_ids, package_module_ids, ident_ids_by_module, @@ -2117,7 +2122,9 @@ fn parse_header<'a>( } Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module( arena, + &"", module_ids, + package_module_ids, ident_ids_by_module, mode, header, @@ -2470,7 +2477,9 @@ fn run_solve<'a>( fn fabricate_effects_module<'a>( arena: &'a Bump, + shorthand: &'a str, module_ids: Arc>, + package_module_ids: Arc>>, ident_ids_by_module: Arc>>, mode: Mode, header: PlatformHeader<'a>, @@ -2496,6 +2505,17 @@ fn fabricate_effects_module<'a>( functions }; + let mut package_module_ids = (*package_module_ids).lock(); + + for exposed in header.exposes { + match exposed.value { + ExposesEntry::Exposed(module_name) => { + package_module_ids.get_or_insert(&(shorthand, module_name.into())); + } + _ => {} + } + } + let exposed_ident_ids = { // Lock just long enough to perform the minimal operations necessary. let mut module_ids = (*module_ids).lock(); @@ -3202,6 +3222,7 @@ fn run_task<'a>( ) .map(|(_, msg)| msg), LoadPkgConfig { + shorthand, module_ids, package_module_ids, ident_ids_by_module, @@ -3209,6 +3230,7 @@ fn run_task<'a>( } => load_pkg_config( arena, src_dir, + shorthand, module_ids, package_module_ids, ident_ids_by_module, From b130f86fdf0c560659bb3258e2a06a3a9d2273aa Mon Sep 17 00:00:00 2001 From: rvcas Date: Sun, 6 Dec 2020 14:13:24 -0500 Subject: [PATCH 09/12] fix: last hardcoded "platform" in file.rs --- compiler/load/src/file.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index fe69d787e0..3091e5a66c 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -1868,13 +1868,7 @@ fn load_pkg_config<'a>( ) -> Result, LoadingProblem> { let module_start_time = SystemTime::now(); - let mut filename = PathBuf::from(src_dir); - - filename.push("platform"); - filename.push(PKG_CONFIG_FILE_NAME); - - // End with .roc - filename.set_extension(ROC_FILE_EXTENSION); + let filename = PathBuf::from(src_dir); let file_io_start = SystemTime::now(); let file = fs::read(&filename); @@ -2081,7 +2075,7 @@ fn parse_header<'a>( if pkg_config_roc.as_path().exists() { let load_pkg_config_msg = load_pkg_config( arena, - &pkg_config_dir, + &pkg_config_roc, shorthand, module_ids, package_module_ids, From 1471cd0db4a7be3cffa52c29dcbbf666b67d91f1 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 6 Dec 2020 21:19:52 +0100 Subject: [PATCH 10/12] error message investigation --- compiler/can/src/module.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/can/src/module.rs b/compiler/can/src/module.rs index 134b00d781..1c3277fff0 100644 --- a/compiler/can/src/module.rs +++ b/compiler/can/src/module.rs @@ -97,6 +97,7 @@ pub fn canonicalize_module_defs<'a>( let first_char = ident.as_inline_str().chars().next().unwrap(); if first_char.is_lowercase() { + // this is a value definition let expr_var = var_store.fresh(); match scope.import(ident, symbol, region) { @@ -116,6 +117,15 @@ pub fn canonicalize_module_defs<'a>( } } } else { + // This is a type alias + + // the same scheme as with identifiers won't work here, e.g. + // + // Task : Effect + // + // really is not the same as + // + // Task a : Effect a panic!("TODO add type aliases to type alias dictionary, based on exposed types"); } } From 0873792488c34094e24d70d23225f0b768497399 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 6 Dec 2020 21:51:08 +0100 Subject: [PATCH 11/12] special-case effect modules so they are not parsed --- compiler/load/src/file.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 3091e5a66c..1a53f129f3 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -103,6 +103,7 @@ impl Dependencies { pub fn add_module( &mut self, module_id: ModuleId, + opt_effect_module: Option, dependencies: &MutSet, goal_phase: Phase, ) -> MutSet<(ModuleId, Phase)> { @@ -145,7 +146,8 @@ impl Dependencies { // all the dependencies can be loaded for dep in dependencies { // TODO figure out how to "load" (because it doesn't exist on the file system) the Effect module - if !format!("{:?}", dep).contains("Effect") { + + if Some(*dep) != opt_effect_module { output.insert((*dep, LoadHeader)); } } @@ -680,6 +682,7 @@ struct State<'a> { pub stdlib: StdLib, pub exposed_types: SubsByModule, pub output_path: Option<&'a str>, + pub opt_effect_module: Option, pub headers_parsed: MutSet, @@ -1264,6 +1267,7 @@ where goal_phase, stdlib, output_path: None, + opt_effect_module: None, module_cache: ModuleCache::default(), dependencies: Dependencies::default(), procedures: MutMap::default(), @@ -1429,6 +1433,7 @@ fn update<'a>( let work = state.dependencies.add_module( header.module_id, + state.opt_effect_module, &header.imported_modules, state.goal_phase, ); @@ -1516,6 +1521,9 @@ fn update<'a>( module_docs, } => { let module_id = constrained_module.module.module_id; + + state.opt_effect_module = Some(module_id); + log!("made effect module for {:?}", module_id); state .module_cache From 7919b2eef37d50d60d0b9a721454a3008e313475 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 6 Dec 2020 22:16:53 +0100 Subject: [PATCH 12/12] clippy --- compiler/gen_dev/tests/gen_num.rs | 7 +- compiler/gen_dev/tests/helpers/eval.rs | 380 ++++++++++++------------- compiler/load/src/file.rs | 13 +- 3 files changed, 199 insertions(+), 201 deletions(-) diff --git a/compiler/gen_dev/tests/gen_num.rs b/compiler/gen_dev/tests/gen_num.rs index 32a83b3fc2..24be18721f 100644 --- a/compiler/gen_dev/tests/gen_num.rs +++ b/compiler/gen_dev/tests/gen_num.rs @@ -1,7 +1,8 @@ -// #[macro_use] +#[macro_use] extern crate pretty_assertions; -// #[macro_use] -// extern crate indoc; + +#[macro_use] +extern crate indoc; extern crate bumpalo; extern crate libc; diff --git a/compiler/gen_dev/tests/helpers/eval.rs b/compiler/gen_dev/tests/helpers/eval.rs index 18a0508ce5..7f6f8ea55c 100644 --- a/compiler/gen_dev/tests/helpers/eval.rs +++ b/compiler/gen_dev/tests/helpers/eval.rs @@ -1,232 +1,232 @@ -// use libloading::Library; -// use roc_build::link::{link, LinkType}; -// use roc_collections::all::MutMap; -// use tempfile::tempdir; +use libloading::Library; +use roc_build::link::{link, LinkType}; +use roc_collections::all::MutMap; +use tempfile::tempdir; -// fn promote_expr_to_module(src: &str) -> String { -// let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); +fn promote_expr_to_module(src: &str) -> String { + let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); -// for line in src.lines() { -// // indent the body! -// buffer.push_str(" "); -// buffer.push_str(line); -// buffer.push('\n'); -// } + for line in src.lines() { + // indent the body! + buffer.push_str(" "); + buffer.push_str(line); + buffer.push('\n'); + } -// buffer -// } + buffer +} -// pub fn helper<'a>( -// arena: &'a bumpalo::Bump, -// src: &str, -// stdlib: roc_builtins::std::StdLib, -// _leak: bool, -// lazy_literals: bool, -// ) -> (String, Vec, Library) { -// use std::path::{Path, PathBuf}; +pub fn helper<'a>( + arena: &'a bumpalo::Bump, + src: &str, + stdlib: roc_builtins::std::StdLib, + _leak: bool, + lazy_literals: bool, +) -> (String, Vec, Library) { + use std::path::{Path, PathBuf}; -// //let stdlib_mode = stdlib.mode; -// let dir = tempdir().unwrap(); -// let filename = PathBuf::from("Test.roc"); -// let src_dir = Path::new("fake/test/path"); -// let app_o_file = dir.path().join("app.o"); + //let stdlib_mode = stdlib.mode; + let dir = tempdir().unwrap(); + let filename = PathBuf::from("Test.roc"); + let src_dir = Path::new("fake/test/path"); + let app_o_file = dir.path().join("app.o"); -// let module_src; -// let temp; -// if src.starts_with("app") { -// // this is already a module -// module_src = src; -// } else { -// // this is an expression, promote it to a module -// temp = promote_expr_to_module(src); -// module_src = &temp; -// } + let module_src; + let temp; + if src.starts_with("app") { + // this is already a module + module_src = src; + } else { + // this is an expression, promote it to a module + temp = promote_expr_to_module(src); + module_src = &temp; + } -// let exposed_types = MutMap::default(); -// let loaded = roc_load::file::load_and_monomorphize_from_str( -// arena, -// filename, -// &module_src, -// stdlib, -// src_dir, -// exposed_types, -// ); + let exposed_types = MutMap::default(); + let loaded = roc_load::file::load_and_monomorphize_from_str( + arena, + filename, + &module_src, + stdlib, + src_dir, + exposed_types, + ); -// let mut loaded = loaded.expect("failed to load module"); + let mut loaded = loaded.expect("failed to load module"); -// use roc_load::file::MonomorphizedModule; -// let MonomorphizedModule { -// procedures, -// interns, -// exposed_to_host, -// .. -// } = loaded; + use roc_load::file::MonomorphizedModule; + let MonomorphizedModule { + procedures, + interns, + exposed_to_host, + .. + } = loaded; -// /* -// println!("=========== Procedures =========="); -// println!("{:?}", procedures); -// println!("=================================\n"); + /* + println!("=========== Procedures =========="); + println!("{:?}", procedures); + println!("=================================\n"); -// println!("=========== Interns =========="); -// println!("{:?}", interns); -// println!("=================================\n"); + println!("=========== Interns =========="); + println!("{:?}", interns); + println!("=================================\n"); -// println!("=========== Exposed =========="); -// println!("{:?}", exposed_to_host); -// println!("=================================\n"); -// */ -// debug_assert_eq!(exposed_to_host.len(), 1); -// let main_fn_symbol = exposed_to_host.keys().copied().nth(0).unwrap(); + println!("=========== Exposed =========="); + println!("{:?}", exposed_to_host); + println!("=================================\n"); + */ + debug_assert_eq!(exposed_to_host.len(), 1); + let main_fn_symbol = exposed_to_host.keys().copied().nth(0).unwrap(); -// let (_, main_fn_layout) = procedures -// .keys() -// .find(|(s, _)| *s == main_fn_symbol) -// .unwrap() -// .clone(); -// let mut layout_ids = roc_mono::layout::LayoutIds::default(); -// let main_fn_name = layout_ids -// .get(main_fn_symbol, &main_fn_layout) -// .to_symbol_string(main_fn_symbol, &interns); + let (_, main_fn_layout) = procedures + .keys() + .find(|(s, _)| *s == main_fn_symbol) + .unwrap() + .clone(); + let mut layout_ids = roc_mono::layout::LayoutIds::default(); + let main_fn_name = layout_ids + .get(main_fn_symbol, &main_fn_layout) + .to_symbol_string(main_fn_symbol, &interns); -// let mut lines = Vec::new(); -// // errors whose reporting we delay (so we can see that code gen generates runtime errors) -// let mut delayed_errors = Vec::new(); + let mut lines = Vec::new(); + // errors whose reporting we delay (so we can see that code gen generates runtime errors) + let mut delayed_errors = Vec::new(); -// for (home, (module_path, src)) in loaded.sources { -// use roc_reporting::report::{ -// can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE, -// }; + for (home, (module_path, src)) in loaded.sources { + use roc_reporting::report::{ + can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE, + }; -// let can_problems = loaded.can_problems.remove(&home).unwrap_or_default(); -// let type_problems = loaded.type_problems.remove(&home).unwrap_or_default(); -// let mono_problems = loaded.mono_problems.remove(&home).unwrap_or_default(); + let can_problems = loaded.can_problems.remove(&home).unwrap_or_default(); + let type_problems = loaded.type_problems.remove(&home).unwrap_or_default(); + let mono_problems = loaded.mono_problems.remove(&home).unwrap_or_default(); -// let error_count = can_problems.len() + type_problems.len() + mono_problems.len(); + let error_count = can_problems.len() + type_problems.len() + mono_problems.len(); -// if error_count == 0 { -// continue; -// } + if error_count == 0 { + continue; + } -// let src_lines: Vec<&str> = src.split('\n').collect(); -// let palette = DEFAULT_PALETTE; + let src_lines: Vec<&str> = src.split('\n').collect(); + let palette = DEFAULT_PALETTE; -// // Report parsing and canonicalization problems -// let alloc = RocDocAllocator::new(&src_lines, home, &interns); + // Report parsing and canonicalization problems + let alloc = RocDocAllocator::new(&src_lines, home, &interns); -// use roc_problem::can::Problem::*; -// for problem in can_problems.into_iter() { -// // Ignore "unused" problems -// match problem { -// UnusedDef(_, _) | UnusedArgument(_, _, _) | UnusedImport(_, _) => { -// delayed_errors.push(problem); -// continue; -// } -// _ => { -// let report = can_problem(&alloc, module_path.clone(), problem); -// let mut buf = String::new(); + use roc_problem::can::Problem::*; + for problem in can_problems.into_iter() { + // Ignore "unused" problems + match problem { + UnusedDef(_, _) | UnusedArgument(_, _, _) | UnusedImport(_, _) => { + delayed_errors.push(problem); + continue; + } + _ => { + let report = can_problem(&alloc, module_path.clone(), problem); + let mut buf = String::new(); -// report.render_color_terminal(&mut buf, &alloc, &palette); + report.render_color_terminal(&mut buf, &alloc, &palette); -// lines.push(buf); -// } -// } -// } + lines.push(buf); + } + } + } -// for problem in type_problems { -// let report = type_problem(&alloc, module_path.clone(), problem); -// let mut buf = String::new(); + for problem in type_problems { + let report = type_problem(&alloc, module_path.clone(), problem); + let mut buf = String::new(); -// report.render_color_terminal(&mut buf, &alloc, &palette); + report.render_color_terminal(&mut buf, &alloc, &palette); -// lines.push(buf); -// } + lines.push(buf); + } -// for problem in mono_problems { -// let report = mono_problem(&alloc, module_path.clone(), problem); -// let mut buf = String::new(); + for problem in mono_problems { + let report = mono_problem(&alloc, module_path.clone(), problem); + let mut buf = String::new(); -// report.render_color_terminal(&mut buf, &alloc, &palette); + report.render_color_terminal(&mut buf, &alloc, &palette); -// lines.push(buf); -// } -// } + lines.push(buf); + } + } -// if !lines.is_empty() { -// println!("{}", lines.join("\n")); -// assert_eq!(0, 1, "Mistakes were made"); -// } + if !lines.is_empty() { + println!("{}", lines.join("\n")); + assert_eq!(0, 1, "Mistakes were made"); + } -// let env = roc_gen_dev::Env { -// arena, -// interns, -// exposed_to_host: exposed_to_host.keys().copied().collect(), -// lazy_literals, -// }; + let env = roc_gen_dev::Env { + arena, + interns, + exposed_to_host: exposed_to_host.keys().copied().collect(), + lazy_literals, + }; -// let target = target_lexicon::Triple::host(); -// let module_object = -// roc_gen_dev::build_module(&env, &target, procedures).expect("failed to compile module"); + let target = target_lexicon::Triple::host(); + let module_object = + roc_gen_dev::build_module(&env, &target, procedures).expect("failed to compile module"); -// let module_out = module_object -// .write() -// .expect("failed to build output object"); -// std::fs::write(&app_o_file, module_out).expect("failed to write object to file"); + let module_out = module_object + .write() + .expect("failed to build output object"); + std::fs::write(&app_o_file, module_out).expect("failed to write object to file"); -// let (mut child, dylib_path) = link( -// &target, -// app_o_file.clone(), -// &[app_o_file.to_str().unwrap()], -// LinkType::Dylib, -// ) -// .expect("failed to link dynamic library"); + let (mut child, dylib_path) = link( + &target, + app_o_file.clone(), + &[app_o_file.to_str().unwrap()], + LinkType::Dylib, + ) + .expect("failed to link dynamic library"); -// child.wait().unwrap(); + child.wait().unwrap(); -// // Load the dylib -// let path = dylib_path.as_path().to_str().unwrap(); + // Load the dylib + let path = dylib_path.as_path().to_str().unwrap(); -// // std::fs::copy(&app_o_file, "/tmp/app.o").unwrap(); -// // std::fs::copy(&path, "/tmp/libapp.so").unwrap(); + // std::fs::copy(&app_o_file, "/tmp/app.o").unwrap(); + // std::fs::copy(&path, "/tmp/libapp.so").unwrap(); -// let lib = Library::new(path).expect("failed to load shared library"); + let lib = Library::new(path).expect("failed to load shared library"); -// (main_fn_name, delayed_errors, lib) -// } + (main_fn_name, delayed_errors, lib) +} -// #[macro_export] -// macro_rules! assert_evals_to { -// ($src:expr, $expected:expr, $ty:ty) => {{ -// assert_evals_to!($src, $expected, $ty, (|val| val)); -// }}; -// ($src:expr, $expected:expr, $ty:ty, $transform:expr) => { -// // Same as above, except with an additional transformation argument. -// { -// assert_evals_to!($src, $expected, $ty, $transform, true); -// } -// }; -// ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr) => { -// // Run both with and without lazy literal optimization. -// { -// assert_evals_to!($src, $expected, $ty, $transform, $leak, false); -// } -// { -// assert_evals_to!($src, $expected, $ty, $transform, $leak, true); -// } -// }; -// ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr, $lazy_literals:expr) => { -// use bumpalo::Bump; -// use roc_gen_dev::run_jit_function_raw; -// let stdlib = roc_builtins::std::standard_stdlib(); +#[macro_export] +macro_rules! assert_evals_to { + ($src:expr, $expected:expr, $ty:ty) => {{ + assert_evals_to!($src, $expected, $ty, (|val| val)); + }}; + ($src:expr, $expected:expr, $ty:ty, $transform:expr) => { + // Same as above, except with an additional transformation argument. + { + assert_evals_to!($src, $expected, $ty, $transform, true); + } + }; + ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr) => { + // Run both with and without lazy literal optimization. + { + assert_evals_to!($src, $expected, $ty, $transform, $leak, false); + } + { + assert_evals_to!($src, $expected, $ty, $transform, $leak, true); + } + }; + ($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr, $lazy_literals:expr) => { + use bumpalo::Bump; + use roc_gen_dev::run_jit_function_raw; + let stdlib = roc_builtins::std::standard_stdlib(); -// let arena = Bump::new(); -// let (main_fn_name, errors, lib) = -// $crate::helpers::eval::helper(&arena, $src, stdlib, $leak, $lazy_literals); + let arena = Bump::new(); + let (main_fn_name, errors, lib) = + $crate::helpers::eval::helper(&arena, $src, stdlib, $leak, $lazy_literals); -// let transform = |success| { -// let expected = $expected; -// let given = $transform(success); -// assert_eq!(&given, &expected); -// }; -// run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors) -// }; -// } + let transform = |success| { + let expected = $expected; + let given = $transform(success); + assert_eq!(&given, &expected); + }; + run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors) + }; +} diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 1a53f129f3..b46279c9c2 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -2075,7 +2075,7 @@ fn parse_header<'a>( match package_or_path { PackageOrPath::Path(StrLiteral::PlainLine(package)) => { // check whether we can find a Pkg-Config.roc file - let mut pkg_config_roc = pkg_config_dir.clone(); + let mut pkg_config_roc = pkg_config_dir; pkg_config_roc.push(package); pkg_config_roc.push(PKG_CONFIG_FILE_NAME); pkg_config_roc.set_extension(ROC_FILE_EXTENSION); @@ -2171,6 +2171,7 @@ fn load_filename<'a>( /// Load a module from a str /// the `filename` is never read, but used for the module name +#[allow(clippy::too_many_arguments)] fn load_from_str<'a>( arena: &'a Bump, filename: PathBuf, @@ -2340,8 +2341,6 @@ fn send_header<'a>( ident_ids.clone() }; - dbg!(package_module_ids); - // Send the deps to the coordinator thread for processing, // then continue on to parsing and canonicalizing defs. // @@ -2477,6 +2476,7 @@ fn run_solve<'a>( } } +#[allow(clippy::too_many_arguments)] fn fabricate_effects_module<'a>( arena: &'a Bump, shorthand: &'a str, @@ -2510,11 +2510,8 @@ fn fabricate_effects_module<'a>( let mut package_module_ids = (*package_module_ids).lock(); for exposed in header.exposes { - match exposed.value { - ExposesEntry::Exposed(module_name) => { - package_module_ids.get_or_insert(&(shorthand, module_name.into())); - } - _ => {} + if let ExposesEntry::Exposed(module_name) = exposed.value { + package_module_ids.get_or_insert(&(shorthand, module_name.into())); } }