diff --git a/cli/src/repl.rs b/cli/src/repl.rs index cfd4811e5a..87f672704a 100644 --- a/cli/src/repl.rs +++ b/cli/src/repl.rs @@ -29,7 +29,7 @@ use roc_types::subs::{Content, Subs, VarStore, Variable}; use roc_types::types::Type; use std::hash::Hash; use std::io::{self, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::str::from_utf8_unchecked; use target_lexicon::Triple; @@ -158,33 +158,64 @@ pub fn repl_home() -> ModuleId { ModuleIds::default().get_or_insert(&"REPL".into()) } +fn promote_expr_to_module(src: &str) -> String { + let mut buffer = String::from("app Repl provides [ replOutput ] imports []\n\nreplOutput =\n"); + + for line in src.lines() { + // indent the body! + buffer.push_str(" "); + buffer.push_str(line); + buffer.push('\n'); + } + + buffer +} + fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result { use roc_reporting::report::{can_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE}; - // Look up the types and expressions of the `provided` values - let ptr_bytes = target.pointer_width().unwrap().bytes() as u32; let arena = Bump::new(); - let CanExprOut { - loc_expr, - var_store, - var, - constraint, - home, + + // SAFETY: we've already verified that this is valid UTF-8 during parsing. + let src_str: &str = unsafe { from_utf8_unchecked(src) }; + + let stdlib = roc_builtins::std::standard_stdlib(); + let stdlib_mode = stdlib.mode; + let filename = PathBuf::from("REPL.roc"); + let src_dir = Path::new("fake/test/path"); + + let module_src = promote_expr_to_module(src_str); + + 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 loaded = loaded.expect("failed to load module"); + + use roc_load::file::MonomorphizedModule; + let MonomorphizedModule { + can_problems, + type_problems, + mono_problems, + mut procedures, interns, - problems: can_problems, + exposed_to_host, + mut subs, + module_id: home, .. - } = can_expr(src)?; // IMPORTANT: we must bail out here if there were UTF-8 errors! + } = loaded; - let subs = Subs::new(var_store.into()); - let mut type_problems = Vec::new(); - let (content, mut subs) = infer_expr(subs, &mut type_problems, &constraint, var); + let error_count = can_problems.len() + type_problems.len() + mono_problems.len(); - let total_problems = can_problems.len() + type_problems.len(); - - if total_problems > 0 { + if error_count > 0 { // There were problems; report them and return. - // SAFETY: we've already verified that this is valid UTF-8 during parsing. - let src_lines: Vec<&str> = unsafe { from_utf8_unchecked(src).split('\n').collect() }; + let src_lines: Vec<&str> = src_str.split('\n').collect(); // Used for reporting where an error came from. // @@ -197,7 +228,7 @@ fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result Result Result map.len(), - None => 0, - }; - - Vec::with_capacity(num_headers) - }; - let procs = roc_mono::ir::specialize_all(&mut mono_env, procs, &mut layout_cache); - - assert_eq!( - procs.runtime_errors, - roc_collections::all::MutMap::default() - ); - - let (mut procs, param_map) = procs.get_specialized_procs_help(mono_env.arena); - let main_body = roc_mono::inc_dec::visit_declaration( - mono_env.arena, - param_map, - mono_env.arena.alloc(main_body), - ); - - // Put this module's ident_ids back in the interns, so we can use them in env. - // This must happen *after* building the headers, because otherwise there's - // a conflicting mutable borrow on ident_ids. - env.interns.all_ident_ids.insert(home, ident_ids); + let mut layout_ids = roc_gen::layout_id::LayoutIds::default(); + let mut headers = Vec::with_capacity(procedures.len()); // Add all the Proc headers to the module. // We have to do this in a separate pass first, // because their bodies may reference each other. let mut scope = roc_gen::llvm::build::Scope::default(); - for ((symbol, layout), proc) in procs.drain() { + for ((symbol, layout), proc) in procedures.drain() { let fn_val = build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc); if proc.args.is_empty() { @@ -325,34 +321,45 @@ fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result "OPTIMIZED", + Mode::Standard => "NON-OPTIMIZED", + }; + eprintln!( - "\n\nFunction {:?} failed LLVM verification in build. Its content was:\n", - fn_val.get_name().to_str().unwrap() + "\n\nFunction {:?} failed LLVM verification in {} build. Its content was:\n", + fn_val.get_name().to_str().unwrap(), + mode, ); fn_val.print_to_stderr(); panic!( - "The preceding code was from {:?}, which failed LLVM verification in build.", - fn_val.get_name().to_str().unwrap() + "The preceding code was from {:?}, which failed LLVM verification in {} build.", + fn_val.get_name().to_str().unwrap(), + mode, ); } } - - let (main_fn_name, main_fn) = roc_gen::llvm::build::make_main_function( + let (main_fn_name, main_fn) = roc_gen::llvm::build::promote_to_main_function( &env, &mut layout_ids, - &main_ret_layout, - &main_body, + main_fn_symbol, + &main_fn_layout, ); // Uncomment this to see the module's un-optimized LLVM instruction output: @@ -379,7 +386,7 @@ fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result( // important! we don't want any procedures to get the C calling convention exposed_to_host: MutSet::default(), }; - let mut layout_ids = roc_gen::layout_id::LayoutIds::default(); + let mut layout_ids = roc_gen::layout_id::LayoutIds::default(); let mut headers = Vec::with_capacity(procedures.len()); // Add all the Proc headers to the module. diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 43b889e235..e7bc87225f 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -439,7 +439,7 @@ pub struct MonomorphizedModule<'a> { pub type_problems: Vec, pub mono_problems: Vec, pub procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>, - pub exposed_to_host: MutSet, + pub exposed_to_host: MutMap, pub src: Box, pub timings: MutMap, } @@ -498,7 +498,7 @@ enum Msg<'a> { FinishedAllSpecialization { subs: Subs, problems: Vec, - exposed_to_host: MutSet, + exposed_to_host: MutMap, src: &'a str, }, } @@ -525,7 +525,7 @@ struct State<'a> { pub module_cache: ModuleCache<'a>, pub dependencies: Dependencies, pub procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>, - pub exposed_to_host: MutSet, + pub exposed_to_host: MutMap, /// This is the "final" list of IdentIds, after canonicalization and constraint gen /// have completed for a given module. @@ -667,7 +667,7 @@ enum BuildTask<'a> { ident_ids: IdentIds, decls: Vec, finished_info: FinishedInfo<'a>, - exposed_to_host: MutSet, + exposed_to_host: MutMap, }, MakeSpecializations { module_id: ModuleId, @@ -1060,7 +1060,7 @@ where module_cache: ModuleCache::default(), dependencies: Dependencies::default(), procedures: MutMap::default(), - exposed_to_host: MutSet::default(), + exposed_to_host: MutMap::default(), exposed_types, headers_parsed, loading_started, @@ -1283,7 +1283,7 @@ fn update<'a>( if module_id == state.root_id { state .exposed_to_host - .extend(solved_module.exposed_vars_by_symbol.iter().map(|x| x.0)); + .extend(solved_module.exposed_vars_by_symbol.iter().copied()); } if module_id == state.root_id && state.goal_phase == Phase::SolveTypes { @@ -1480,7 +1480,7 @@ fn finish_specialization<'a>( mut state: State<'a>, subs: Subs, problems: Vec, - exposed_to_host: MutSet, + exposed_to_host: MutMap, src: &'a str, ) -> MonomorphizedModule<'a> { state.mono_problems.extend(problems); @@ -2148,7 +2148,7 @@ fn build_pending_specializations<'a>( _module_timing: ModuleTiming, mut layout_cache: LayoutCache<'a>, // TODO remove - exposed_to_host: MutSet, + exposed_to_host: MutMap, finished_info: FinishedInfo<'a>, ) -> Msg<'a> { let mut procs = Procs::default(); @@ -2212,7 +2212,7 @@ fn add_def_to_module<'a>( procs: &mut Procs<'a>, mono_env: &mut roc_mono::ir::Env<'a, '_>, def: roc_can::def::Def, - exposed_to_host: &MutSet, + exposed_to_host: &MutMap, is_recursive: bool, ) { use roc_can::expr::Expr::*; @@ -2220,7 +2220,7 @@ fn add_def_to_module<'a>( match def.loc_pattern.value { Identifier(symbol) => { - let is_exposed = exposed_to_host.contains(&symbol); + let is_exposed = exposed_to_host.contains_key(&symbol); match def.loc_expr.value { Closure {