mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Merge branch 'trunk' into ir-cleanup
This commit is contained in:
commit
5f36da98ee
33 changed files with 1200 additions and 1001 deletions
|
@ -784,6 +784,10 @@ enum Msg<'a> {
|
|||
},
|
||||
|
||||
FailedToParse(ParseProblem<'a, SyntaxError<'a>>),
|
||||
FailedToReadFile {
|
||||
filename: PathBuf,
|
||||
error: io::ErrorKind,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -996,18 +1000,16 @@ pub enum LoadingProblem<'a> {
|
|||
FileProblem {
|
||||
filename: PathBuf,
|
||||
error: io::ErrorKind,
|
||||
msg: &'static str,
|
||||
},
|
||||
ParsingFailed(ParseProblem<'a, SyntaxError<'a>>),
|
||||
UnexpectedHeader(String),
|
||||
/// there is no platform (likely running an Interface module)
|
||||
NoPlatform(String),
|
||||
|
||||
MsgChannelDied,
|
||||
ErrJoiningWorkerThreads,
|
||||
TriedToImportAppModule,
|
||||
/// a formatted report of parsing failure
|
||||
ParsingFailedReport(String),
|
||||
|
||||
/// a formatted report
|
||||
FormattedReport(String),
|
||||
}
|
||||
|
||||
pub enum Phases {
|
||||
|
@ -1399,6 +1401,14 @@ where
|
|||
Err(LoadingProblem::ParsingFailed(problem)) => {
|
||||
msg_tx.send(Msg::FailedToParse(problem)).unwrap();
|
||||
}
|
||||
Err(LoadingProblem::FileProblem {
|
||||
filename,
|
||||
error,
|
||||
}) => {
|
||||
msg_tx
|
||||
.send(Msg::FailedToReadFile { filename, error })
|
||||
.unwrap();
|
||||
}
|
||||
Err(other) => {
|
||||
return Err(other);
|
||||
}
|
||||
|
@ -1457,6 +1467,16 @@ where
|
|||
let worker_listeners = worker_listeners.into_bump_slice();
|
||||
let msg_tx = msg_tx.clone();
|
||||
|
||||
macro_rules! shut_down_worker_threads {
|
||||
() => {
|
||||
for listener in worker_listeners {
|
||||
listener
|
||||
.send(WorkerMsg::Shutdown)
|
||||
.map_err(|_| LoadingProblem::MsgChannelDied)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// The root module will have already queued up messages to process,
|
||||
// and processing those messages will in turn queue up more messages.
|
||||
for msg in msg_rx.iter() {
|
||||
|
@ -1490,12 +1510,7 @@ where
|
|||
// We're done! There should be no more messages pending.
|
||||
debug_assert!(msg_rx.is_empty());
|
||||
|
||||
// Shut down all the worker threads.
|
||||
for listener in worker_listeners {
|
||||
listener
|
||||
.send(WorkerMsg::Shutdown)
|
||||
.map_err(|_| LoadingProblem::MsgChannelDied)?;
|
||||
}
|
||||
shut_down_worker_threads!();
|
||||
|
||||
return Ok(LoadResult::Monomorphized(finish_specialization(
|
||||
state,
|
||||
|
@ -1503,50 +1518,29 @@ where
|
|||
exposed_to_host,
|
||||
)?));
|
||||
}
|
||||
Msg::FailedToReadFile { filename, error } => {
|
||||
shut_down_worker_threads!();
|
||||
|
||||
let buf = to_file_problem_report(&filename, error);
|
||||
return Err(LoadingProblem::FormattedReport(buf));
|
||||
}
|
||||
|
||||
Msg::FailedToParse(problem) => {
|
||||
// Shut down all the worker threads.
|
||||
for listener in worker_listeners {
|
||||
listener
|
||||
.send(WorkerMsg::Shutdown)
|
||||
.map_err(|_| LoadingProblem::MsgChannelDied)?;
|
||||
}
|
||||
shut_down_worker_threads!();
|
||||
|
||||
use roc_reporting::report::{
|
||||
parse_problem, RocDocAllocator, DEFAULT_PALETTE,
|
||||
};
|
||||
|
||||
// TODO this is not in fact safe
|
||||
let src = unsafe { from_utf8_unchecked(problem.bytes) };
|
||||
let src_lines: Vec<&str> = src.split('\n').collect();
|
||||
|
||||
let palette = DEFAULT_PALETTE;
|
||||
|
||||
let mut module_ids = Arc::try_unwrap(state.arc_modules)
|
||||
let module_ids = Arc::try_unwrap(state.arc_modules)
|
||||
.unwrap_or_else(|_| {
|
||||
panic!("There were still outstanding Arc references to module_ids")
|
||||
})
|
||||
.into_inner()
|
||||
.into_module_ids();
|
||||
|
||||
let module_id =
|
||||
module_ids.get_or_insert(&"find module name somehow?".into());
|
||||
|
||||
let interns = Interns {
|
||||
let buf = to_parse_problem_report(
|
||||
problem,
|
||||
module_ids,
|
||||
all_ident_ids: state.constrained_ident_ids,
|
||||
};
|
||||
|
||||
// Report parsing and canonicalization problems
|
||||
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
||||
|
||||
let starting_line = 0;
|
||||
let report =
|
||||
parse_problem(&alloc, problem.filename.clone(), starting_line, problem);
|
||||
let mut buf = String::new();
|
||||
|
||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||
|
||||
return Err(LoadingProblem::ParsingFailedReport(buf));
|
||||
state.constrained_ident_ids,
|
||||
);
|
||||
return Err(LoadingProblem::FormattedReport(buf));
|
||||
}
|
||||
msg => {
|
||||
// This is where most of the main thread's work gets done.
|
||||
|
@ -2086,6 +2080,9 @@ fn update<'a>(
|
|||
Msg::FailedToParse(_) => {
|
||||
unreachable!();
|
||||
}
|
||||
Msg::FailedToReadFile { .. } => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2142,72 +2139,8 @@ fn finish_specialization(
|
|||
}
|
||||
Valid(To::NewPackage(p_or_p)) => p_or_p,
|
||||
other => {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
let module_id = state.root_id;
|
||||
|
||||
let palette = DEFAULT_PALETTE;
|
||||
|
||||
// Report parsing and canonicalization problems
|
||||
let alloc = RocDocAllocator::new(&[], module_id, &interns);
|
||||
|
||||
let report = {
|
||||
match other {
|
||||
Valid(_) => unreachable!(),
|
||||
NotSpecified => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow("I could not find a platform based on your input file."),
|
||||
alloc.reflow(r"Does the module header contain an entry that looks like this:"),
|
||||
alloc
|
||||
.parser_suggestion(" packages { base: \"platform\" }")
|
||||
.indent(4),
|
||||
alloc.reflow("See also TODO."),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "NO PLATFORM".to_string(),
|
||||
}
|
||||
}
|
||||
RootIsInterface => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"The input file is a interface file, but only app modules can be ran."),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies,"),
|
||||
alloc.reflow(r"but won't output any executable."),
|
||||
])
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "NO PLATFORM".to_string(),
|
||||
}
|
||||
}
|
||||
RootIsPkgConfig => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"The input file is a package config file, but only app modules can be ran."),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies,"),
|
||||
alloc.reflow(r"but won't output any executable."),
|
||||
])
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "NO PLATFORM".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut buf = String::new();
|
||||
|
||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||
|
||||
return Err(LoadingProblem::NoPlatform(buf));
|
||||
let buf = to_missing_platform_report(state.root_id, other);
|
||||
return Err(LoadingProblem::FormattedReport(buf));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2365,7 +2298,7 @@ fn load_pkg_config<'a>(
|
|||
Ok(Msg::Many(vec![effects_module_msg, pkg_config_module_msg]))
|
||||
}
|
||||
Err(fail) => Err(LoadingProblem::ParsingFailed(
|
||||
SyntaxError::Header(fail).into_parse_problem(filename, bytes),
|
||||
SyntaxError::Header(fail).into_parse_problem(filename, "", bytes),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -2373,7 +2306,6 @@ fn load_pkg_config<'a>(
|
|||
Err(err) => Err(LoadingProblem::FileProblem {
|
||||
filename,
|
||||
error: err.kind(),
|
||||
msg: "while reading a Pkg-Config.roc file",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -2638,7 +2570,7 @@ fn parse_header<'a>(
|
|||
module_timing,
|
||||
)),
|
||||
Err(fail) => Err(LoadingProblem::ParsingFailed(
|
||||
SyntaxError::Header(fail).into_parse_problem(filename, src_bytes),
|
||||
SyntaxError::Header(fail).into_parse_problem(filename, "", src_bytes),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -2675,7 +2607,6 @@ fn load_filename<'a>(
|
|||
Err(err) => Err(LoadingProblem::FileProblem {
|
||||
filename,
|
||||
error: err.kind(),
|
||||
msg: "in `load_filename`",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -3712,9 +3643,11 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result<Msg<'a>, Loadi
|
|||
let parsed_defs = match module_defs().parse(&arena, parse_state) {
|
||||
Ok((_, success, _state)) => success,
|
||||
Err((_, fail, _)) => {
|
||||
return Err(LoadingProblem::ParsingFailed(
|
||||
fail.into_parse_problem(header.module_path, source),
|
||||
));
|
||||
return Err(LoadingProblem::ParsingFailed(fail.into_parse_problem(
|
||||
header.module_path,
|
||||
header.header_src,
|
||||
source,
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4209,3 +4142,179 @@ where
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_file_problem_report(filename: &PathBuf, error: io::ErrorKind) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
let src_lines: Vec<&str> = Vec::new();
|
||||
|
||||
let mut module_ids = ModuleIds::default();
|
||||
|
||||
let module_id = module_ids.get_or_insert(&"find module name somehow?".into());
|
||||
|
||||
let interns = Interns::default();
|
||||
|
||||
// Report parsing and canonicalization problems
|
||||
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
||||
|
||||
let report = match error {
|
||||
io::ErrorKind::NotFound => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I am looking for this file, but it's not there:"),
|
||||
alloc
|
||||
.parser_suggestion(filename.to_str().unwrap())
|
||||
.indent(4),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"Is the file supposed to be there? "),
|
||||
alloc.reflow("Maybe there is a typo in the file name?"),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "FILE NOT FOUND".to_string(),
|
||||
}
|
||||
}
|
||||
io::ErrorKind::PermissionDenied => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I don't have the required permissions to read this file:"),
|
||||
alloc
|
||||
.parser_suggestion(filename.to_str().unwrap())
|
||||
.indent(4),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"Is it the right file? Maybe change its permissions?")
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "PERMISSION DENIED".to_string(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let error = std::io::Error::from(error);
|
||||
let formatted = format!("{}", error);
|
||||
let doc = alloc.concat(vec![
|
||||
alloc.reflow(r"I tried to read this file, but ran into a "),
|
||||
alloc.text(formatted),
|
||||
alloc.reflow(r" problem."),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "FILE PROBLEM".to_string(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
let palette = DEFAULT_PALETTE;
|
||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
fn to_parse_problem_report<'a>(
|
||||
problem: ParseProblem<'a, SyntaxError<'a>>,
|
||||
mut module_ids: ModuleIds,
|
||||
all_ident_ids: MutMap<ModuleId, IdentIds>,
|
||||
) -> String {
|
||||
use roc_reporting::report::{parse_problem, RocDocAllocator, DEFAULT_PALETTE};
|
||||
|
||||
// TODO this is not in fact safe
|
||||
let src = unsafe { from_utf8_unchecked(problem.bytes) };
|
||||
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 {
|
||||
module_ids,
|
||||
all_ident_ids,
|
||||
};
|
||||
|
||||
// Report parsing and canonicalization problems
|
||||
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
||||
|
||||
let starting_line = 0;
|
||||
let report = parse_problem(&alloc, problem.filename.clone(), starting_line, problem);
|
||||
|
||||
let mut buf = String::new();
|
||||
let palette = DEFAULT_PALETTE;
|
||||
|
||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
use PlatformPath::*;
|
||||
|
||||
// Report parsing and canonicalization problems
|
||||
let interns = Interns::default();
|
||||
let alloc = RocDocAllocator::new(&[], module_id, &interns);
|
||||
|
||||
let report = {
|
||||
match other {
|
||||
Valid(_) => unreachable!(),
|
||||
NotSpecified => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow("I could not find a platform based on your input file."),
|
||||
alloc.reflow(r"Does the module header contain an entry that looks like this:"),
|
||||
alloc
|
||||
.parser_suggestion(" packages { base: \"platform\" }")
|
||||
.indent(4),
|
||||
alloc.reflow("See also TODO."),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "NO PLATFORM".to_string(),
|
||||
}
|
||||
}
|
||||
RootIsInterface => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"The input file is a interface file, but only app modules can be ran."),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies,"),
|
||||
alloc.reflow(r"but won't output any executable."),
|
||||
])
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "NO PLATFORM".to_string(),
|
||||
}
|
||||
}
|
||||
RootIsPkgConfig => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"The input file is a package config file, but only app modules can be ran."),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies,"),
|
||||
alloc.reflow(r"but won't output any executable."),
|
||||
])
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename: "UNKNOWN.roc".into(),
|
||||
doc,
|
||||
title: "NO PLATFORM".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let palette = DEFAULT_PALETTE;
|
||||
let mut buf = String::new();
|
||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||
|
||||
buf
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue