mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Merge remote-tracking branch 'origin/trunk' into dict
This commit is contained in:
commit
0ed87828e5
76 changed files with 4113 additions and 8034 deletions
|
@ -27,7 +27,7 @@ use roc_parse::header::{
|
|||
ExposesEntry, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, To, TypedIdent,
|
||||
};
|
||||
use roc_parse::module::module_defs;
|
||||
use roc_parse::parser::{self, Fail, Parser};
|
||||
use roc_parse::parser::{self, ParseProblem, Parser, SyntaxError};
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_solve::module::SolvedModule;
|
||||
use roc_solve::solve;
|
||||
|
@ -762,6 +762,8 @@ enum Msg<'a> {
|
|||
subs: Subs,
|
||||
exposed_to_host: MutMap<Symbol, Variable>,
|
||||
},
|
||||
|
||||
FailedToParse(ParseProblem<'a, SyntaxError<'a>>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -968,20 +970,20 @@ enum WorkerMsg {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoadingProblem {
|
||||
pub enum LoadingProblem<'a> {
|
||||
FileProblem {
|
||||
filename: PathBuf,
|
||||
error: io::ErrorKind,
|
||||
msg: &'static str,
|
||||
},
|
||||
ParsingFailed {
|
||||
filename: PathBuf,
|
||||
fail: Fail,
|
||||
},
|
||||
ParsingFailed(ParseProblem<'a, SyntaxError<'a>>),
|
||||
UnexpectedHeader(String),
|
||||
|
||||
MsgChannelDied,
|
||||
ErrJoiningWorkerThreads,
|
||||
TriedToImportAppModule,
|
||||
/// a formatted report of parsing failure
|
||||
ParsingFailedReport(String),
|
||||
}
|
||||
|
||||
pub enum Phases {
|
||||
|
@ -998,7 +1000,7 @@ fn enqueue_task<'a>(
|
|||
injector: &Injector<BuildTask<'a>>,
|
||||
listeners: &[Sender<WorkerMsg>],
|
||||
task: BuildTask<'a>,
|
||||
) -> Result<(), LoadingProblem> {
|
||||
) -> Result<(), LoadingProblem<'a>> {
|
||||
injector.push(task);
|
||||
|
||||
for listener in listeners {
|
||||
|
@ -1010,15 +1012,15 @@ fn enqueue_task<'a>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_and_typecheck<F>(
|
||||
arena: &Bump,
|
||||
pub fn load_and_typecheck<'a, F>(
|
||||
arena: &'a Bump,
|
||||
filename: PathBuf,
|
||||
stdlib: &StdLib,
|
||||
stdlib: &'a StdLib,
|
||||
src_dir: &Path,
|
||||
exposed_types: SubsByModule,
|
||||
ptr_bytes: u32,
|
||||
look_up_builtin: F,
|
||||
) -> Result<LoadedModule, LoadingProblem>
|
||||
) -> Result<LoadedModule, LoadingProblem<'a>>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
|
@ -1049,7 +1051,7 @@ pub fn load_and_monomorphize<'a, F>(
|
|||
exposed_types: SubsByModule,
|
||||
ptr_bytes: u32,
|
||||
look_up_builtin: F,
|
||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem>
|
||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem<'a>>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
|
@ -1082,7 +1084,7 @@ pub fn load_and_monomorphize_from_str<'a, F>(
|
|||
exposed_types: SubsByModule,
|
||||
ptr_bytes: u32,
|
||||
look_up_builtin: F,
|
||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem>
|
||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem<'a>>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
|
@ -1117,7 +1119,7 @@ impl<'a> LoadStart<'a> {
|
|||
arena: &'a Bump,
|
||||
filename: PathBuf,
|
||||
mode: Mode,
|
||||
) -> Result<Self, LoadingProblem> {
|
||||
) -> Result<Self, LoadingProblem<'a>> {
|
||||
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));
|
||||
|
@ -1150,7 +1152,7 @@ impl<'a> LoadStart<'a> {
|
|||
filename: PathBuf,
|
||||
src: &'a str,
|
||||
mode: Mode,
|
||||
) -> Result<Self, LoadingProblem> {
|
||||
) -> Result<Self, LoadingProblem<'a>> {
|
||||
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));
|
||||
|
@ -1238,7 +1240,7 @@ fn load<'a, F>(
|
|||
goal_phase: Phase,
|
||||
ptr_bytes: u32,
|
||||
look_up_builtins: F,
|
||||
) -> Result<LoadResult<'a>, LoadingProblem>
|
||||
) -> Result<LoadResult<'a>, LoadingProblem<'a>>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
|
@ -1329,7 +1331,7 @@ where
|
|||
let injector = &injector;
|
||||
|
||||
// Record this thread's handle so the main thread can join it later.
|
||||
thread_scope
|
||||
let res_join_handle = thread_scope
|
||||
.builder()
|
||||
.stack_size(EXPANDED_STACK_SIZE)
|
||||
.spawn(move |_| {
|
||||
|
@ -1342,7 +1344,7 @@ where
|
|||
// shut down the thread, so when the main thread
|
||||
// blocks on joining with all the worker threads,
|
||||
// it can finally exit too!
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
WorkerMsg::TaskAdded => {
|
||||
// Find a task - either from this thread's queue,
|
||||
|
@ -1355,15 +1357,27 @@ where
|
|||
// added. In that case, do nothing, and keep waiting
|
||||
// until we receive a Shutdown message.
|
||||
if let Some(task) = find_task(&worker, injector, stealers) {
|
||||
run_task(
|
||||
let result = run_task(
|
||||
task,
|
||||
worker_arena,
|
||||
src_dir,
|
||||
msg_tx.clone(),
|
||||
ptr_bytes,
|
||||
look_up_builtins,
|
||||
)
|
||||
.expect("Msg channel closed unexpectedly.");
|
||||
);
|
||||
|
||||
match result {
|
||||
Ok(()) => {}
|
||||
Err(LoadingProblem::MsgChannelDied) => {
|
||||
panic!("Msg channel closed unexpectedly.")
|
||||
}
|
||||
Err(LoadingProblem::ParsingFailed(problem)) => {
|
||||
msg_tx.send(Msg::FailedToParse(problem)).unwrap();
|
||||
}
|
||||
Err(other) => {
|
||||
return Err(other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1372,8 +1386,11 @@ where
|
|||
// Needed to prevent a borrow checker error about this closure
|
||||
// outliving its enclosing function.
|
||||
drop(worker_msg_rx);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
res_join_handle.unwrap();
|
||||
}
|
||||
|
||||
let mut state = State {
|
||||
|
@ -1461,6 +1478,51 @@ where
|
|||
exposed_to_host,
|
||||
)));
|
||||
}
|
||||
Msg::FailedToParse(problem) => {
|
||||
// Shut down all the worker threads.
|
||||
for listener in worker_listeners {
|
||||
listener
|
||||
.send(WorkerMsg::Shutdown)
|
||||
.map_err(|_| LoadingProblem::MsgChannelDied)?;
|
||||
}
|
||||
|
||||
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)
|
||||
.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 {
|
||||
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));
|
||||
}
|
||||
msg => {
|
||||
// This is where most of the main thread's work gets done.
|
||||
// Everything up to this point has been setting up the threading
|
||||
|
@ -1489,7 +1551,7 @@ fn start_tasks<'a>(
|
|||
state: &mut State<'a>,
|
||||
injector: &Injector<BuildTask<'a>>,
|
||||
worker_listeners: &'a [Sender<WorkerMsg>],
|
||||
) -> Result<(), LoadingProblem> {
|
||||
) -> Result<(), LoadingProblem<'a>> {
|
||||
for (module_id, phase) in work {
|
||||
for task in start_phase(module_id, phase, state) {
|
||||
enqueue_task(&injector, worker_listeners, task)?
|
||||
|
@ -1506,7 +1568,7 @@ fn update<'a>(
|
|||
injector: &Injector<BuildTask<'a>>,
|
||||
worker_listeners: &'a [Sender<WorkerMsg>],
|
||||
arena: &'a Bump,
|
||||
) -> Result<State<'a>, LoadingProblem> {
|
||||
) -> Result<State<'a>, LoadingProblem<'a>> {
|
||||
use self::Msg::*;
|
||||
|
||||
match msg {
|
||||
|
@ -1963,6 +2025,9 @@ fn update<'a>(
|
|||
Msg::FinishedAllSpecialization { .. } => {
|
||||
unreachable!();
|
||||
}
|
||||
Msg::FailedToParse(_) => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2085,7 +2150,7 @@ fn load_pkg_config<'a>(
|
|||
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
) -> Result<Msg<'a>, LoadingProblem> {
|
||||
) -> Result<Msg<'a>, LoadingProblem<'a>> {
|
||||
let module_start_time = SystemTime::now();
|
||||
|
||||
let filename = PathBuf::from(src_dir);
|
||||
|
@ -2095,9 +2160,10 @@ fn load_pkg_config<'a>(
|
|||
let file_io_duration = file_io_start.elapsed().unwrap();
|
||||
|
||||
match file {
|
||||
Ok(bytes) => {
|
||||
Ok(bytes_vec) => {
|
||||
let parse_start = SystemTime::now();
|
||||
let parse_state = parser::State::new(arena.alloc(bytes), Attempting::Module);
|
||||
let bytes = arena.alloc(bytes_vec);
|
||||
let parse_state = parser::State::new_in(arena, bytes, Attempting::Module);
|
||||
let parsed = roc_parse::module::header().parse(&arena, parse_state);
|
||||
let parse_header_duration = parse_start.elapsed().unwrap();
|
||||
|
||||
|
@ -2112,19 +2178,19 @@ fn load_pkg_config<'a>(
|
|||
effect_module_timing.parse_header = parse_header_duration;
|
||||
|
||||
match parsed {
|
||||
Ok((ast::Module::Interface { header }, _parse_state)) => {
|
||||
Ok((_, ast::Module::Interface { header }, _parse_state)) => {
|
||||
Err(LoadingProblem::UnexpectedHeader(format!(
|
||||
"expected platform/package module, got Interface with header\n{:?}",
|
||||
header
|
||||
)))
|
||||
}
|
||||
Ok((ast::Module::App { header }, _parse_state)) => {
|
||||
Ok((_, ast::Module::App { header }, _parse_state)) => {
|
||||
Err(LoadingProblem::UnexpectedHeader(format!(
|
||||
"expected platform/package module, got App with header\n{:?}",
|
||||
header
|
||||
)))
|
||||
}
|
||||
Ok((ast::Module::Platform { header }, parser_state)) => {
|
||||
Ok((_, ast::Module::Platform { header }, parser_state)) => {
|
||||
// make a Pkg-Config module that ultimately exposes `main` to the host
|
||||
let pkg_config_module_msg = fabricate_pkg_config_module(
|
||||
arena,
|
||||
|
@ -2152,7 +2218,9 @@ fn load_pkg_config<'a>(
|
|||
|
||||
Ok(Msg::Many(vec![effects_module_msg, pkg_config_module_msg]))
|
||||
}
|
||||
Err((fail, _)) => Err(LoadingProblem::ParsingFailed { filename, fail }),
|
||||
Err((_, fail, _)) => Err(LoadingProblem::ParsingFailed(
|
||||
fail.into_parse_problem(filename, bytes),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2173,7 +2241,7 @@ fn load_module<'a>(
|
|||
arc_shorthands: Arc<Mutex<MutMap<&'a str, PackageOrPath<'a>>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
let module_start_time = SystemTime::now();
|
||||
let mut filename = PathBuf::new();
|
||||
|
||||
|
@ -2261,9 +2329,9 @@ fn parse_header<'a>(
|
|||
mode: Mode,
|
||||
src_bytes: &'a [u8],
|
||||
start_time: SystemTime,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
let parse_start = SystemTime::now();
|
||||
let parse_state = parser::State::new(src_bytes, Attempting::Module);
|
||||
let parse_state = parser::State::new_in(arena, src_bytes, Attempting::Module);
|
||||
let parsed = roc_parse::module::header().parse(&arena, parse_state);
|
||||
let parse_header_duration = parse_start.elapsed().unwrap();
|
||||
|
||||
|
@ -2274,7 +2342,7 @@ fn parse_header<'a>(
|
|||
module_timing.parse_header = parse_header_duration;
|
||||
|
||||
match parsed {
|
||||
Ok((ast::Module::Interface { header }, parse_state)) => Ok(send_header(
|
||||
Ok((_, ast::Module::Interface { header }, parse_state)) => Ok(send_header(
|
||||
Located {
|
||||
region: header.name.region,
|
||||
value: ModuleNameEnum::Interface(header.name.value),
|
||||
|
@ -2290,7 +2358,7 @@ fn parse_header<'a>(
|
|||
ident_ids_by_module,
|
||||
module_timing,
|
||||
)),
|
||||
Ok((ast::Module::App { header }, parse_state)) => {
|
||||
Ok((_, ast::Module::App { header }, parse_state)) => {
|
||||
let mut pkg_config_dir = filename.clone();
|
||||
pkg_config_dir.pop();
|
||||
|
||||
|
@ -2388,7 +2456,7 @@ fn parse_header<'a>(
|
|||
},
|
||||
}
|
||||
}
|
||||
Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module(
|
||||
Ok((_, ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module(
|
||||
arena,
|
||||
&"",
|
||||
module_ids,
|
||||
|
@ -2397,7 +2465,9 @@ fn parse_header<'a>(
|
|||
header,
|
||||
module_timing,
|
||||
),
|
||||
Err((fail, _)) => Err(LoadingProblem::ParsingFailed { filename, fail }),
|
||||
Err((_, fail, _)) => Err(LoadingProblem::ParsingFailed(
|
||||
fail.into_parse_problem(filename, src_bytes),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2410,7 +2480,7 @@ fn load_filename<'a>(
|
|||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
module_start_time: SystemTime,
|
||||
mode: Mode,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
let file_io_start = SystemTime::now();
|
||||
let file = fs::read(&filename);
|
||||
let file_io_duration = file_io_start.elapsed().unwrap();
|
||||
|
@ -2446,7 +2516,7 @@ fn load_from_str<'a>(
|
|||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
module_start_time: SystemTime,
|
||||
mode: Mode,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
let file_io_start = SystemTime::now();
|
||||
let file_io_duration = file_io_start.elapsed().unwrap();
|
||||
|
||||
|
@ -3014,7 +3084,7 @@ fn fabricate_pkg_config_module<'a>(
|
|||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
header: &PlatformHeader<'a>,
|
||||
module_timing: ModuleTiming,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
let provides: &'a [Located<ExposesEntry<'a, &'a str>>] =
|
||||
header.provides.clone().into_bump_slice();
|
||||
|
||||
|
@ -3043,7 +3113,7 @@ fn fabricate_effects_module<'a>(
|
|||
mode: Mode,
|
||||
header: PlatformHeader<'a>,
|
||||
module_timing: ModuleTiming,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
let num_exposes = header.provides.len() + 1;
|
||||
let mut exposed: Vec<Symbol> = Vec::with_capacity(num_exposes);
|
||||
|
||||
|
@ -3323,7 +3393,7 @@ fn canonicalize_and_constrain<'a, F>(
|
|||
mode: Mode,
|
||||
parsed: ParsedModule<'a>,
|
||||
look_up_builtins: F,
|
||||
) -> Result<Msg<'a>, LoadingProblem>
|
||||
) -> Result<Msg<'a>, LoadingProblem<'a>>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
|
@ -3408,13 +3478,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result<Msg<'a>, LoadingProblem> {
|
||||
fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result<Msg<'a>, LoadingProblem<'a>> {
|
||||
let mut module_timing = header.module_timing;
|
||||
let parse_start = SystemTime::now();
|
||||
let parse_state = parser::State::new(&header.src, Attempting::Module);
|
||||
let (parsed_defs, _) = module_defs()
|
||||
.parse(&arena, parse_state)
|
||||
.expect("TODO gracefully handle parse error on module defs. IMPORTANT: Bail out entirely if there are any BadUtf8 problems! That means the whole source file is not valid UTF-8 and any other errors we report may get mis-reported. We rely on this for safety in an `unsafe` block later on in this function.");
|
||||
let parse_state = parser::State::new_in(arena, &header.src, Attempting::Module);
|
||||
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, header.src),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let parsed_defs = parsed_defs.into_bump_slice();
|
||||
|
||||
|
@ -3795,7 +3870,7 @@ fn run_task<'a, F>(
|
|||
msg_tx: MsgSender<'a>,
|
||||
ptr_bytes: u32,
|
||||
look_up_builtins: F,
|
||||
) -> Result<(), LoadingProblem>
|
||||
) -> Result<(), LoadingProblem<'a>>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue