diff --git a/crates/compiler/load/src/lib.rs b/crates/compiler/load/src/lib.rs index 56804d34da..402eb9c344 100644 --- a/crates/compiler/load/src/lib.rs +++ b/crates/compiler/load/src/lib.rs @@ -1,7 +1,7 @@ use bumpalo::Bump; use roc_can::module::{ExposedByModule, TypeState}; use roc_collections::all::MutMap; -use roc_module::symbol::ModuleId; +use roc_module::symbol::{Interns, ModuleId}; use roc_reporting::report::RenderTarget; use roc_target::TargetInfo; use std::path::PathBuf; @@ -25,7 +25,7 @@ fn load<'a>( load_start: LoadStart<'a>, exposed_types: ExposedByModule, load_config: LoadConfig, -) -> Result, LoadingProblem<'a>> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { let cached_types = read_cached_types(); roc_load_internal::file::load(arena, load_start, exposed_types, cached_types, load_config) @@ -39,7 +39,7 @@ pub fn load_single_threaded<'a>( target_info: TargetInfo, render: RenderTarget, exec_mode: ExecutionMode, -) -> Result, LoadingProblem<'a>> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { let cached_subs = read_cached_types(); roc_load_internal::file::load_single_threaded( @@ -84,7 +84,7 @@ pub fn load_and_monomorphize_from_str<'a>( src_dir: PathBuf, exposed_types: ExposedByModule, load_config: LoadConfig, -) -> Result, LoadingProblem<'a>> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { use LoadResult::*; let load_start = LoadStart::from_str(arena, filename, src, src_dir)?; diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 24b9d62281..a4b6949105 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1193,7 +1193,7 @@ pub fn load_and_typecheck_str<'a>( target_info: TargetInfo, render: RenderTarget, threading: Threading, -) -> Result> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { use LoadResult::*; let load_start = LoadStart::from_str(arena, filename, source, src_dir)?; @@ -1255,7 +1255,7 @@ impl<'a> LoadStart<'a> { root_start_time, ); - match res_loaded { + match dbg!(res_loaded) { Ok((module_id, msg)) => { if let Msg::Header(ModuleHeader { module_id: header_id, @@ -1282,25 +1282,6 @@ impl<'a> LoadStart<'a> { (module_id, msg) } - - Err(LoadingProblem::ParsingFailed(problem)) => { - let module_ids = Arc::try_unwrap(arc_modules) - .unwrap_or_else(|_| { - panic!("There were still outstanding Arc references to module_ids") - }) - .into_inner() - .into_module_ids(); - - // if parsing failed, this module did not add any identifiers - let root_exposed_ident_ids = IdentIds::exposed_builtins(0); - let buf = to_parse_problem_report( - problem, - module_ids, - root_exposed_ident_ids, - render, - ); - return Err(LoadingProblem::FormattedReport(buf)); - } Err(LoadingProblem::FileProblem { filename, error }) => { let buf = to_file_problem_report(&filename, error); return Err(LoadingProblem::FormattedReport(buf)); @@ -1363,7 +1344,7 @@ impl<'a> LoadStart<'a> { filename: PathBuf, src: &'a str, src_dir: PathBuf, - ) -> Result> { + ) -> Result, ModuleId, Interns)> { let arc_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)); @@ -1461,7 +1442,7 @@ pub fn load<'a>( exposed_types: ExposedByModule, cached_types: MutMap, load_config: LoadConfig, -) -> Result, LoadingProblem<'a>> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { enum Threads { Single, Many(usize), @@ -1519,7 +1500,7 @@ pub fn load_single_threaded<'a>( cached_types: MutMap, render: RenderTarget, exec_mode: ExecutionMode, -) -> Result, LoadingProblem<'a>> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { let LoadStart { arc_modules, ident_ids_by_module, @@ -1651,17 +1632,7 @@ fn state_thread_step<'a>( let buf = to_file_problem_report(&filename, error); Err(LoadingProblem::FormattedReport(buf)) } - - Msg::FailedToParse(problem) => { - let module_ids = (*state.arc_modules).lock().clone().into_module_ids(); - let buf = to_parse_problem_report( - problem, - module_ids, - state.constrained_ident_ids, - state.render, - ); - Err(LoadingProblem::FormattedReport(buf)) - } + Msg::FailedToParse(problem) => Err(LoadingProblem::ParsingFailed(problem)), Msg::IncorrectModuleName(FileError { problem: SourceError { problem, bytes }, filename, @@ -1768,7 +1739,7 @@ fn load_multi_threaded<'a>( render: RenderTarget, available_threads: usize, exec_mode: ExecutionMode, -) -> Result, LoadingProblem<'a>> { +) -> Result, (LoadingProblem<'a>, ModuleId, Interns)> { let LoadStart { arc_modules, ident_ids_by_module, @@ -3424,7 +3395,7 @@ fn parse_header<'a>( ident_ids_by_module: SharedIdentIdsByModule, src_bytes: &'a [u8], start_time: Instant, -) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { +) -> Result<(ModuleId, Msg<'a>), (LoadingProblem<'a>, ModuleId, Interns)> { let parse_start = Instant::now(); let parse_state = roc_parse::state::State::new(src_bytes); let parsed = roc_parse::module::parse_header(arena, parse_state.clone()); @@ -3436,7 +3407,7 @@ fn parse_header<'a>( module_timing.read_roc_file = read_file_duration; module_timing.parse_header = parse_header_duration; - match parsed { + match dbg!(parsed) { Ok((ast::Module::Interface { header }, parse_state)) => { verify_interface_matches_file_path(header.name, &filename, &parse_state)?; @@ -3639,7 +3610,7 @@ fn load_filename<'a>( module_ids: Arc>>, ident_ids_by_module: SharedIdentIdsByModule, module_start_time: Instant, -) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { +) -> Result<(ModuleId, Msg<'a>), (LoadingProblem<'a>, ModuleId, Interns)> { let file_io_start = Instant::now(); let file = fs::read(&filename); let file_io_duration = file_io_start.elapsed(); @@ -3674,7 +3645,7 @@ fn load_from_str<'a>( module_ids: Arc>>, ident_ids_by_module: SharedIdentIdsByModule, module_start_time: Instant, -) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { +) -> Result<(ModuleId, Msg<'a>), (LoadingProblem<'a>, ModuleId, Interns)> { let file_io_start = Instant::now(); let file_io_duration = file_io_start.elapsed(); @@ -5862,12 +5833,8 @@ fn to_parse_problem_report<'a>( ) -> String { use roc_reporting::report::{parse_problem, RocDocAllocator, DEFAULT_PALETTE}; - // TODO this is not in fact safe - let src = unsafe { from_utf8_unchecked(problem.problem.bytes) }; + let src = std::str::from_utf8(problem.problem.bytes).unwrap(); let src_lines = src.lines().collect::>(); - // let mut src_lines: Vec<&str> = problem.prefix.lines().collect(); - // src_lines.extend(src.lines().skip(1)); - let module_id = module_ids.get_or_insert(&"find module name somehow?".into()); let interns = Interns { @@ -5877,9 +5844,7 @@ fn to_parse_problem_report<'a>( // Report parsing and canonicalization problems let alloc = RocDocAllocator::new(&src_lines, module_id, &interns); - let starting_line = 0; - let lines = LineInfo::new(src); let report = parse_problem( diff --git a/crates/repl_eval/src/gen.rs b/crates/repl_eval/src/gen.rs index a21d086491..3e22498527 100644 --- a/crates/repl_eval/src/gen.rs +++ b/crates/repl_eval/src/gen.rs @@ -1,6 +1,6 @@ use bumpalo::Bump; use roc_load::{ExecutionMode, LoadConfig, Threading}; -use roc_reporting::report::{Palette, Severity}; +use roc_reporting::report::{parse_problem, Palette, RenderTarget, Severity, DEFAULT_PALETTE}; use std::path::PathBuf; use roc_fmt::annotation::Formattable; @@ -51,7 +51,7 @@ pub fn compile_to_mono<'a>( let filename = PathBuf::from(""); let src_dir = PathBuf::from("fake/test/path"); - let module_src = arena.alloc(promote_expr_to_module(src)); + let module_src = arena.alloc(dbg!(promote_expr_to_module(src))); let exposed_types = Default::default(); let loaded = roc_load::load_and_monomorphize_from_str( @@ -68,7 +68,7 @@ pub fn compile_to_mono<'a>( }, ); - let mut loaded = match loaded { + let mut loaded = match dbg!(loaded) { Ok(v) => v, Err(LoadingProblem::FormattedReport(report)) => { return ( @@ -79,6 +79,27 @@ pub fn compile_to_mono<'a>( }, ); } + Err(LoadingProblem::ParsingFailed(problem)) => { + let lines = LineInfo::new(src); + let alloc = RocDocAllocator::new(&src_lines, module_id, &interns); + let starting_line = 0; + let report = parse_problem( + &alloc, + &lines, + problem.filename.clone(), + starting_line, + problem, + ); + + let mut buf = String::new(); + let palette = DEFAULT_PALETTE; + + // Seems safe to assume that the REPL is in an actual terminal (e.g. as opposed to CI). + // If we want to be extra careful, we could try to detect whether colors are supported. + report.render(RenderTarget::ColorTerminal, &mut buf, &alloc, &palette); + + buf + } Err(e) => { todo!("error while loading module: {:?}", e) } @@ -97,24 +118,25 @@ pub fn compile_to_mono<'a>( let errors = &mut problems.errors; let warnings = &mut problems.warnings; - for (home, (module_path, src)) in sources.iter() { + for (home, (module_path, src)) in dbg!(sources).iter() { let can_probs = can_problems.remove(home).unwrap_or_default(); let type_probs = type_problems.remove(home).unwrap_or_default(); - let error_count = can_probs.len() + type_probs.len(); if error_count == 0 { continue; } - let line_info = LineInfo::new(module_src); + // Skip over the repl app module wrapper lines, so that line 1 becomes the first + // line of the expr you entered. + let line_info = LineInfo::new(dbg!(&module_src)); let src_lines: Vec<&str> = src.split('\n').collect(); // Report parsing and canonicalization problems let alloc = RocDocAllocator::new(&src_lines, *home, interns); for problem in can_probs.into_iter() { - let report = can_problem(&alloc, &line_info, module_path.clone(), problem); + let report = can_problem(&alloc, &line_info, module_path.clone(), dbg!(problem)); let severity = report.severity; let mut buf = String::new(); @@ -149,12 +171,24 @@ pub fn compile_to_mono<'a>( } } - (Some(loaded), problems) + (Some(loaded), dbg!(problems)) +} + +const REPL_APP_MODULE_WRAPPER: &str = + "app \"app\" provides [replOutput] to \"./platform\"\n\nreplOutput =\n"; + +const REPL_APP_MODULE_WRAPPER_LINES: usize = 3; + +#[test] +fn repl_app_module_wrapper_lines() { + assert_eq!( + REPL_APP_MODULE_WRAPPER_LINES, + REPL_APP_MODULE_WRAPPER.lines().count() + ); } fn promote_expr_to_module(src: &str) -> String { - let mut buffer = - String::from("app \"app\" provides [replOutput] to \"./platform\"\n\nreplOutput =\n"); + let mut buffer = String::from(REPL_APP_MODULE_WRAPPER); for line in src.lines() { // indent the body!