mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Merge branch 'main' of https://github.com/roc-lang/roc into list-splitting
This commit is contained in:
commit
35f221d9de
28 changed files with 295 additions and 370 deletions
37
.github/workflows/docker.yml
vendored
37
.github/workflows/docker.yml
vendored
|
@ -1,7 +1,6 @@
|
|||
on:
|
||||
workflow_dispatch:
|
||||
#pull_request:
|
||||
# TODO remove pull_request trigger
|
||||
|
||||
name: Docker images tests
|
||||
|
||||
|
@ -19,8 +18,10 @@ jobs:
|
|||
- name: Build image
|
||||
run: docker compose -f docker/nightly-ubuntu-latest/docker-compose.yml build
|
||||
|
||||
- name: Run hello world test
|
||||
run: docker compose -f docker/nightly-ubuntu-latest/docker-compose.yml run roc examples/helloWorld.roc
|
||||
- name: Test with hello world
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/roc-lang/examples/refs/heads/main/examples/HelloWorld/main.roc
|
||||
docker compose -f docker/nightly-ubuntu-latest/docker-compose.yml run roc main.roc
|
||||
|
||||
|
||||
nightly-ubuntu-2204:
|
||||
|
@ -36,8 +37,10 @@ jobs:
|
|||
- name: Build image
|
||||
run: docker compose -f docker/nightly-ubuntu-2204/docker-compose.yml build
|
||||
|
||||
- name: Run hello world test
|
||||
run: docker compose -f docker/nightly-ubuntu-2204/docker-compose.yml run roc examples/helloWorld.roc
|
||||
- name: Test with hello world
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/roc-lang/examples/refs/heads/main/examples/HelloWorld/main.roc
|
||||
docker compose -f docker/nightly-ubuntu-2204/docker-compose.yml run roc main.roc
|
||||
|
||||
nightly-ubuntu-2004:
|
||||
name: nightly-ubuntu-2004
|
||||
|
@ -52,8 +55,10 @@ jobs:
|
|||
- name: Build image
|
||||
run: docker compose -f docker/nightly-ubuntu-2004/docker-compose.yml build
|
||||
|
||||
- name: Run hello world test
|
||||
run: docker compose -f docker/nightly-ubuntu-2004/docker-compose.yml run roc examples/helloWorld.roc
|
||||
- name: Test with hello world
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/roc-lang/examples/refs/heads/main/examples/HelloWorld/main.roc
|
||||
docker compose -f docker/nightly-ubuntu-2004/docker-compose.yml run roc main.roc
|
||||
|
||||
nightly-debian-latest:
|
||||
name: nightly-debian-latest
|
||||
|
@ -68,8 +73,10 @@ jobs:
|
|||
- name: Build image
|
||||
run: docker compose -f docker/nightly-debian-latest/docker-compose.yml build
|
||||
|
||||
- name: Run hello world test
|
||||
run: docker compose -f docker/nightly-debian-latest/docker-compose.yml run roc examples/helloWorld.roc
|
||||
- name: Test with hello world
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/roc-lang/examples/refs/heads/main/examples/HelloWorld/main.roc
|
||||
docker compose -f docker/nightly-debian-latest/docker-compose.yml run roc main.roc
|
||||
|
||||
nightly-debian-bookworm:
|
||||
name: nightly-debian-bookworm
|
||||
|
@ -84,8 +91,10 @@ jobs:
|
|||
- name: Build image
|
||||
run: docker compose -f docker/nightly-debian-bookworm/docker-compose.yml build
|
||||
|
||||
- name: Run hello world test
|
||||
run: docker compose -f docker/nightly-debian-bookworm/docker-compose.yml run roc examples/helloWorld.roc
|
||||
- name: Test with hello world
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/roc-lang/examples/refs/heads/main/examples/HelloWorld/main.roc
|
||||
docker compose -f docker/nightly-debian-bookworm/docker-compose.yml run roc main.roc
|
||||
|
||||
nightly-debian-buster:
|
||||
name: nightly-debian-buster
|
||||
|
@ -100,5 +109,7 @@ jobs:
|
|||
- name: Build image
|
||||
run: docker compose -f docker/nightly-debian-buster/docker-compose.yml build
|
||||
|
||||
- name: Run hello world test
|
||||
run: docker compose -f docker/nightly-debian-buster/docker-compose.yml run roc examples/helloWorld.roc
|
||||
- name: Test with hello world
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/roc-lang/examples/refs/heads/main/examples/HelloWorld/main.roc
|
||||
docker compose -f docker/nightly-debian-buster/docker-compose.yml run roc main.roc
|
||||
|
|
|
@ -58,7 +58,7 @@ jobs:
|
|||
|
||||
- name: test with zig platform
|
||||
run: |
|
||||
cd ${{ env.RELEASE_FOLDER_NAME }} && ./roc --build-host --suppress-build-host-warning crates/cli/tests/test-projects/test-platform-simple-zig/app.roc
|
||||
cd ${{ env.RELEASE_FOLDER_NAME }} && ./roc --build-host --suppress-build-host-warning examples/platform-switching/rocLovesZig.roc
|
||||
|
||||
- name: print short commit SHA
|
||||
run: git rev-parse --short "$GITHUB_SHA"
|
||||
|
|
|
@ -26,14 +26,11 @@ jobs:
|
|||
- name: rename nightly folder
|
||||
run: mv roc_nightly* roc_nightly
|
||||
|
||||
- name: test roc hello world
|
||||
run: cd roc_nightly && ./roc examples/helloWorld.roc
|
||||
|
||||
- name: test platform switching zig
|
||||
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesZig.roc
|
||||
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesZig.roc --build-host --suppress-build-host-warning
|
||||
|
||||
- name: test platform switching c
|
||||
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesC.roc
|
||||
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesC.roc --build-host --suppress-build-host-warning
|
||||
|
||||
- name: test repl
|
||||
run: |
|
||||
|
|
|
@ -28,9 +28,6 @@ mv roc_nightly* roc_nightly
|
|||
|
||||
cd roc_nightly
|
||||
|
||||
# test roc hello world
|
||||
./roc examples/helloWorld.roc
|
||||
|
||||
# test rust platform (first prebuild the host)
|
||||
examples/platform-switching/rust-platform/build.sh
|
||||
./roc examples/platform-switching/rocLovesRust.roc
|
||||
|
|
|
@ -54,6 +54,6 @@ fi
|
|||
./jump-start.sh
|
||||
|
||||
# build the basic cli platform
|
||||
roc build.roc --prebuilt-platform
|
||||
roc build.roc
|
||||
|
||||
cd ..
|
||||
|
|
|
@ -47,6 +47,6 @@ cd ..
|
|||
|
||||
cd basic-webserver
|
||||
|
||||
roc build.roc --prebuilt-platform
|
||||
roc build.roc
|
||||
|
||||
cd ..
|
||||
|
|
|
@ -12,7 +12,7 @@ mkdir -p $1 $1/examples $1/crates/compiler/builtins/bitcode
|
|||
mv target/release-with-lto/{roc,roc_language_server,lib} $1
|
||||
mv LICENSE LEGAL_DETAILS $1
|
||||
|
||||
mv examples/{helloWorld.roc,platform-switching,cli} $1/examples
|
||||
mv examples/{platform-switching,cli} $1/examples
|
||||
|
||||
mv crates/roc_std $1/crates
|
||||
mv crates/compiler/builtins/bitcode/src $1/crates/compiler/builtins/bitcode
|
||||
|
|
|
@ -274,6 +274,7 @@ pub fn build_app() -> Command {
|
|||
Arg::new(ROC_FILE)
|
||||
.help("The .roc file to test")
|
||||
.value_parser(value_parser!(PathBuf))
|
||||
.num_args(0..)
|
||||
.required(false)
|
||||
.default_value(DEFAULT_ROC_FILENAME)
|
||||
)
|
||||
|
@ -516,8 +517,11 @@ pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
|
|||
Some(n) => Threading::AtMost(*n),
|
||||
};
|
||||
|
||||
let path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
|
||||
let paths: Vec<_> = matches.get_many::<PathBuf>(ROC_FILE).unwrap().collect();
|
||||
|
||||
let paths: Vec<_> = {
|
||||
let mut flatten_paths: Vec<_> = vec![];
|
||||
for path in paths.into_iter() {
|
||||
// Spawn the root task
|
||||
if !path.exists() {
|
||||
let current_dir = env::current_dir().unwrap();
|
||||
|
@ -535,10 +539,20 @@ pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
|
|||
}
|
||||
_ => eprintln!("\nThis file was not found: {expected_file_path_string}\n\nYou can run `roc help` for more information on how to provide a .roc file.\n"),
|
||||
}
|
||||
|
||||
process::exit(1);
|
||||
} else if path.is_dir() {
|
||||
find_all_roc_files(path, &mut flatten_paths);
|
||||
} else {
|
||||
flatten_paths.push(path.clone());
|
||||
}
|
||||
}
|
||||
flatten_paths
|
||||
};
|
||||
|
||||
let mut all_files_total_failed_count = 0;
|
||||
let mut all_files_total_passed_count = 0;
|
||||
|
||||
for path in paths.iter() {
|
||||
let arena = &arena;
|
||||
let function_kind = FunctionKind::from_env();
|
||||
|
||||
|
@ -643,8 +657,23 @@ pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
|
|||
}
|
||||
|
||||
let total_duration = start_time.elapsed();
|
||||
|
||||
all_files_total_failed_count += total_failed_count;
|
||||
all_files_total_passed_count += total_passed_count;
|
||||
if total_failed_count == 0 && total_passed_count == 0 {
|
||||
// Only report no expectations found once.
|
||||
continue;
|
||||
} else if matches.get_flag(FLAG_VERBOSE) {
|
||||
println!("Compiled in {} ms.", compilation_duration.as_millis());
|
||||
for module_test_results in results_by_module {
|
||||
print_test_results(module_test_results, &sources);
|
||||
}
|
||||
} else {
|
||||
let test_summary_str =
|
||||
test_summary(total_failed_count, total_passed_count, total_duration);
|
||||
println!("{test_summary_str}");
|
||||
}
|
||||
}
|
||||
if all_files_total_failed_count == 0 && all_files_total_passed_count == 0 {
|
||||
// TODO print this in a more nicely formatted way!
|
||||
println!("No expectations were found.");
|
||||
|
||||
|
@ -655,18 +684,32 @@ pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
|
|||
// running tests altogether!
|
||||
Ok(2)
|
||||
} else {
|
||||
if matches.get_flag(FLAG_VERBOSE) {
|
||||
println!("Compiled in {} ms.", compilation_duration.as_millis());
|
||||
for module_test_results in results_by_module {
|
||||
print_test_results(module_test_results, &sources);
|
||||
Ok((all_files_total_failed_count > 0) as i32)
|
||||
}
|
||||
} else {
|
||||
let test_summary_str =
|
||||
test_summary(total_failed_count, total_passed_count, total_duration);
|
||||
println!("{test_summary_str}");
|
||||
}
|
||||
|
||||
Ok((total_failed_count > 0) as i32)
|
||||
fn find_all_roc_files(path: &PathBuf, flatten_paths: &mut Vec<PathBuf>) {
|
||||
if path.is_dir() {
|
||||
if let Ok(entries) = std::fs::read_dir(path) {
|
||||
entries.for_each(|entry| {
|
||||
if let Ok(entry) = entry {
|
||||
let entry_path = entry.path();
|
||||
find_all_roc_files(&entry_path, flatten_paths);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
eprintln!(
|
||||
"\nSomething went wrong opening the directory {}\n",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
} else if path.is_file() {
|
||||
match path.extension() {
|
||||
Some(extension) if extension == "roc" => {
|
||||
flatten_paths.push(path.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ fn gen_from_mono_module_dev_wasm32<'a>(
|
|||
|
||||
let host_bytes = std::fs::read(built_host_path).unwrap_or_else(|_| {
|
||||
internal_error!(
|
||||
"Failed to read host object file {}! Try omitting --prebuilt-platform",
|
||||
"Failed to read host object file {}!",
|
||||
built_host_path.display()
|
||||
)
|
||||
});
|
||||
|
|
|
@ -482,7 +482,6 @@ pub fn find_type_def_symbols(
|
|||
AssignedField::LabelOnly(_) => {}
|
||||
AssignedField::SpaceBefore(inner, _)
|
||||
| AssignedField::SpaceAfter(inner, _) => inner_stack.push(inner),
|
||||
AssignedField::Malformed(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,7 +506,6 @@ pub fn find_type_def_symbols(
|
|||
Tag::SpaceBefore(inner, _) | Tag::SpaceAfter(inner, _) => {
|
||||
inner_stack.push(inner)
|
||||
}
|
||||
Tag::Malformed(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1355,7 +1353,7 @@ fn can_assigned_fields<'a>(
|
|||
// field names we've seen so far in this record
|
||||
let mut seen = std::collections::HashMap::with_capacity(fields.len());
|
||||
|
||||
'outer: for loc_field in fields.iter() {
|
||||
for loc_field in fields.iter() {
|
||||
let mut field = &loc_field.value;
|
||||
|
||||
// use this inner loop to unwrap the SpaceAfter/SpaceBefore
|
||||
|
@ -1430,12 +1428,6 @@ fn can_assigned_fields<'a>(
|
|||
field = nested;
|
||||
continue 'inner;
|
||||
}
|
||||
Malformed(string) => {
|
||||
malformed(env, region, string);
|
||||
|
||||
// completely skip this element, advance to the next tag
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1522,7 +1514,7 @@ fn can_tags<'a>(
|
|||
// tag names we've seen so far in this tag union
|
||||
let mut seen = std::collections::HashMap::with_capacity(tags.len());
|
||||
|
||||
'outer: for loc_tag in tags.iter() {
|
||||
for loc_tag in tags.iter() {
|
||||
let mut tag = &loc_tag.value;
|
||||
|
||||
// use this inner loop to unwrap the SpaceAfter/SpaceBefore
|
||||
|
@ -1561,12 +1553,6 @@ fn can_tags<'a>(
|
|||
tag = nested;
|
||||
continue 'inner;
|
||||
}
|
||||
Tag::Malformed(string) => {
|
||||
malformed(env, region, string);
|
||||
|
||||
// completely skip this element, advance to the next tag
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -715,10 +715,6 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||
});
|
||||
Err(())
|
||||
}
|
||||
AssignedField::Malformed(_) => {
|
||||
// An error will already have been reported
|
||||
Err(())
|
||||
}
|
||||
AssignedField::SpaceBefore(_, _)
|
||||
| AssignedField::SpaceAfter(_, _)
|
||||
| AssignedField::IgnoredValue(_, _, _) => {
|
||||
|
|
|
@ -407,7 +407,6 @@ pub fn desugar_expr<'a>(
|
|||
| AccessorFunction(_)
|
||||
| Underscore { .. }
|
||||
| MalformedIdent(_, _)
|
||||
| MalformedClosure
|
||||
| MalformedSuffixed(..)
|
||||
| PrecedenceConflict { .. }
|
||||
| EmptyRecordBuilder(_)
|
||||
|
@ -712,7 +711,6 @@ pub fn desugar_expr<'a>(
|
|||
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => {
|
||||
unreachable!("Should have been desugared in `desugar_field`")
|
||||
}
|
||||
AssignedField::Malformed(_name) => continue,
|
||||
};
|
||||
|
||||
field_data.push(FieldData {
|
||||
|
@ -1316,8 +1314,6 @@ fn desugar_field<'a>(
|
|||
}
|
||||
SpaceBefore(field, _spaces) => desugar_field(env, scope, field),
|
||||
SpaceAfter(field, _spaces) => desugar_field(env, scope, field),
|
||||
|
||||
Malformed(string) => Malformed(string),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1391,10 +1391,6 @@ pub fn canonicalize_expr<'a>(
|
|||
Output::default(),
|
||||
)
|
||||
}
|
||||
ast::Expr::MalformedClosure => {
|
||||
use roc_problem::can::RuntimeError::*;
|
||||
(RuntimeError(MalformedClosure(region)), Output::default())
|
||||
}
|
||||
ast::Expr::MalformedIdent(name, bad_ident) => {
|
||||
use roc_problem::can::RuntimeError::*;
|
||||
|
||||
|
@ -1976,10 +1972,6 @@ fn canonicalize_field<'a>(
|
|||
SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
|
||||
canonicalize_field(env, var_store, scope, sub_field)
|
||||
}
|
||||
|
||||
Malformed(_string) => {
|
||||
internal_error!("TODO canonicalize malformed record field");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2568,8 +2560,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::Expr::Underscore(_)
|
||||
| ast::Expr::MalformedIdent(_, _)
|
||||
| ast::Expr::Tag(_)
|
||||
| ast::Expr::OpaqueRef(_)
|
||||
| ast::Expr::MalformedClosure => true,
|
||||
| ast::Expr::OpaqueRef(_) => true,
|
||||
// Newlines are disallowed inside interpolation, and these all require newlines
|
||||
ast::Expr::DbgStmt(_, _)
|
||||
| ast::Expr::LowLevelDbg(_, _, _)
|
||||
|
@ -2604,7 +2595,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::SpaceBefore(_, _) | ast::AssignedField::SpaceAfter(_, _) => false,
|
||||
}),
|
||||
ast::Expr::Tuple(fields) => fields
|
||||
|
@ -2655,7 +2646,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::SpaceBefore(_, _)
|
||||
| ast::AssignedField::SpaceAfter(_, _) => false,
|
||||
})
|
||||
|
@ -2668,7 +2659,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::SpaceBefore(_, _)
|
||||
| ast::AssignedField::SpaceAfter(_, _) => false,
|
||||
})
|
||||
|
|
|
@ -438,7 +438,6 @@ fn is_multiline_assigned_field_help<T: Formattable>(afield: &AssignedField<'_, T
|
|||
| IgnoredValue(_, spaces, ann) => !spaces.is_empty() || ann.value.is_multiline(),
|
||||
LabelOnly(_) => false,
|
||||
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => true,
|
||||
Malformed(text) => text.chars().any(|c| c == '\n'),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,9 +521,6 @@ fn format_assigned_field_help<T>(
|
|||
format_assigned_field_help(sub_field, buf, indent, separator_spaces, is_multiline);
|
||||
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
|
||||
}
|
||||
Malformed(raw) => {
|
||||
buf.push_str(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,7 +531,6 @@ impl<'a> Formattable for Tag<'a> {
|
|||
match self {
|
||||
Apply { args, .. } => args.iter().any(|arg| arg.value.is_multiline()),
|
||||
Tag::SpaceBefore(_, _) | Tag::SpaceAfter(_, _) => true,
|
||||
Malformed(text) => text.chars().any(|c| c == '\n'),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,10 +567,6 @@ impl<'a> Formattable for Tag<'a> {
|
|||
}
|
||||
}
|
||||
Tag::SpaceBefore(_, _) | Tag::SpaceAfter(_, _) => unreachable!(),
|
||||
Tag::Malformed(raw) => {
|
||||
buf.indent(indent);
|
||||
buf.push_str(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ impl<'a> Formattable for Expr<'a> {
|
|||
| Var { .. }
|
||||
| Underscore { .. }
|
||||
| MalformedIdent(_, _)
|
||||
| MalformedClosure
|
||||
| Tag(_)
|
||||
| OpaqueRef(_)
|
||||
| Crash
|
||||
|
@ -557,7 +556,6 @@ impl<'a> Formattable for Expr<'a> {
|
|||
buf.indent(indent);
|
||||
loc_expr.format_with_options(buf, parens, newlines, indent);
|
||||
}
|
||||
MalformedClosure => {}
|
||||
PrecedenceConflict { .. } => {}
|
||||
EmptyRecordBuilder { .. } => {}
|
||||
SingleFieldRecordBuilder { .. } => {}
|
||||
|
@ -1646,9 +1644,6 @@ fn format_assigned_field_multiline<T>(
|
|||
format_assigned_field_multiline(buf, sub_field, indent, separator_prefix);
|
||||
fmt_comments_only(buf, spaces.iter(), NewlineAt::Top, indent);
|
||||
}
|
||||
Malformed(raw) => {
|
||||
buf.push_str(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -476,7 +476,7 @@ fn contains_unexposed_type(
|
|||
return true;
|
||||
}
|
||||
}
|
||||
AssignedField::Malformed(_) | AssignedField::LabelOnly(_) => {
|
||||
AssignedField::LabelOnly(_) => {
|
||||
// contains no unexposed types, so continue
|
||||
}
|
||||
AssignedField::SpaceBefore(field, _) | AssignedField::SpaceAfter(field, _) => {
|
||||
|
@ -524,9 +524,6 @@ fn contains_unexposed_type(
|
|||
}
|
||||
}
|
||||
}
|
||||
Tag::Malformed(_) => {
|
||||
// contains no unexposed types, so continue
|
||||
}
|
||||
Tag::SpaceBefore(tag, _) | Tag::SpaceAfter(tag, _) => {
|
||||
tags_to_process.push(*tag);
|
||||
}
|
||||
|
@ -728,7 +725,7 @@ fn record_field_to_doc(
|
|||
AssignedField::LabelOnly(label) => Some(RecordField::LabelOnly {
|
||||
name: label.value.to_string(),
|
||||
}),
|
||||
AssignedField::Malformed(_) | AssignedField::IgnoredValue(_, _, _) => None,
|
||||
AssignedField::IgnoredValue(_, _, _) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -749,7 +746,6 @@ fn tag_to_doc(in_func_ann: bool, tag: ast::Tag) -> Option<Tag> {
|
|||
}),
|
||||
ast::Tag::SpaceBefore(&sub_tag, _) => tag_to_doc(in_func_ann, sub_tag),
|
||||
ast::Tag::SpaceAfter(&sub_tag, _) => tag_to_doc(in_func_ann, sub_tag),
|
||||
ast::Tag::Malformed(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ use roc_solve_problem::TypeError;
|
|||
use roc_target::Target;
|
||||
use roc_types::subs::{CopiedImport, ExposedTypesStorageSubs, Subs, VarStore, Variable};
|
||||
use roc_types::types::{Alias, Types};
|
||||
use roc_worker::{ChannelProblem, WorkerMsg};
|
||||
use roc_worker::ChannelProblem;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
|
@ -1035,14 +1035,14 @@ type MsgSender<'a> = Sender<Msg<'a>>;
|
|||
/// Add a task to the queue, and notify all the listeners.
|
||||
fn enqueue_task<'a>(
|
||||
injector: &Injector<BuildTask<'a>>,
|
||||
listeners: &[Sender<WorkerMsg>],
|
||||
listeners: &[Sender<()>],
|
||||
task: BuildTask<'a>,
|
||||
) -> Result<(), LoadingProblem<'a>> {
|
||||
injector.push(task);
|
||||
|
||||
for listener in listeners {
|
||||
listener
|
||||
.send(WorkerMsg::TaskAdded)
|
||||
.send(())
|
||||
.map_err(|_| LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask))?;
|
||||
}
|
||||
|
||||
|
@ -1569,9 +1569,9 @@ pub fn load_single_threaded<'a>(
|
|||
// We'll add tasks to this, and then worker threads will take tasks from it.
|
||||
let injector = Injector::new();
|
||||
|
||||
let (worker_msg_tx, worker_msg_rx) = bounded(1024);
|
||||
let worker_listener = worker_msg_tx;
|
||||
let worker_listeners = arena.alloc([worker_listener]);
|
||||
let (worker_wakup_tx, worker_wakup_rx) = bounded(1024);
|
||||
let worker_waker = worker_wakup_tx;
|
||||
let worker_wakers = [worker_waker];
|
||||
|
||||
let worker = Worker::new_fifo();
|
||||
let stealer = worker.stealer();
|
||||
|
@ -1579,7 +1579,7 @@ pub fn load_single_threaded<'a>(
|
|||
|
||||
// now we just manually interleave stepping the state "thread" and the worker "thread"
|
||||
loop {
|
||||
match state_thread_step(arena, state, worker_listeners, &injector, &msg_tx, &msg_rx) {
|
||||
match state_thread_step(arena, state, &worker_wakers, &injector, &msg_tx, &msg_rx) {
|
||||
Ok(ControlFlow::Break(done)) => return Ok(done),
|
||||
Ok(ControlFlow::Continue(new_state)) => {
|
||||
state = new_state;
|
||||
|
@ -1589,7 +1589,7 @@ pub fn load_single_threaded<'a>(
|
|||
|
||||
// then check if the worker can step
|
||||
let control_flow =
|
||||
roc_worker::worker_task_step(&worker, &injector, stealers, &worker_msg_rx, |task| {
|
||||
roc_worker::worker_task_step(&worker, &injector, stealers, &worker_wakup_rx, |task| {
|
||||
run_task(task, arena, &src_dir, msg_tx.clone(), roc_cache_dir, target)
|
||||
});
|
||||
|
||||
|
@ -1606,7 +1606,7 @@ pub fn load_single_threaded<'a>(
|
|||
fn state_thread_step<'a>(
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
worker_listeners: &'a [Sender<WorkerMsg>],
|
||||
worker_wakers: &[Sender<()>],
|
||||
injector: &Injector<BuildTask<'a>>,
|
||||
msg_tx: &crossbeam::channel::Sender<Msg<'a>>,
|
||||
msg_rx: &crossbeam::channel::Receiver<Msg<'a>>,
|
||||
|
@ -1712,14 +1712,8 @@ fn state_thread_step<'a>(
|
|||
let render = state.render;
|
||||
let palette = state.palette;
|
||||
|
||||
let res_state = update(
|
||||
state,
|
||||
msg,
|
||||
msg_tx.clone(),
|
||||
injector,
|
||||
worker_listeners,
|
||||
arena,
|
||||
);
|
||||
let res_state =
|
||||
update(state, msg, msg_tx.clone(), injector, worker_wakers, arena);
|
||||
|
||||
match res_state {
|
||||
Ok(new_state) => Ok(ControlFlow::Continue(new_state)),
|
||||
|
@ -1993,15 +1987,21 @@ fn load_multi_threaded<'a>(
|
|||
|
||||
{
|
||||
let thread_result = thread::scope(|thread_scope| {
|
||||
let mut worker_listeners =
|
||||
bumpalo::collections::Vec::with_capacity_in(num_workers, arena);
|
||||
// Careful! It's important that worker listeners aren't allocated in the arena,
|
||||
// since they need to be correctly dropped if we have a panic in this thread::scope code.
|
||||
// Making sure they're owned means they'll be dropped correctly on either normal exit
|
||||
// of this thread::scope block or on panicking. When they're dropped, the worker threads
|
||||
// will correctly exit their message processing loops.
|
||||
// If these were allocated in the arena, we might panic without shutting down the worker threads,
|
||||
// causing the thread::scope block to hang while it waits for the worker threads to exit.
|
||||
let mut worker_wakers = Vec::with_capacity(num_workers);
|
||||
|
||||
for worker_arena in it {
|
||||
let msg_tx = msg_tx.clone();
|
||||
let worker = worker_queues.pop().unwrap();
|
||||
|
||||
let (worker_msg_tx, worker_msg_rx) = bounded(1024);
|
||||
worker_listeners.push(worker_msg_tx);
|
||||
let (worker_wakup_tx, worker_wakup_rx) = bounded(1024);
|
||||
worker_wakers.push(worker_wakup_tx);
|
||||
|
||||
// We only want to move a *reference* to the main task queue's
|
||||
// injector in the thread, not the injector itself
|
||||
|
@ -2015,7 +2015,12 @@ fn load_multi_threaded<'a>(
|
|||
.stack_size(EXPANDED_STACK_SIZE)
|
||||
.spawn(move |_| {
|
||||
// will process messages until we run out
|
||||
roc_worker::worker_task(worker, injector, stealers, worker_msg_rx, |task| {
|
||||
roc_worker::worker_task(
|
||||
worker,
|
||||
injector,
|
||||
stealers,
|
||||
worker_wakup_rx,
|
||||
|task| {
|
||||
run_task(
|
||||
task,
|
||||
worker_arena,
|
||||
|
@ -2024,7 +2029,8 @@ fn load_multi_threaded<'a>(
|
|||
roc_cache_dir,
|
||||
target,
|
||||
)
|
||||
})
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
res_join_handle.unwrap_or_else(|_| {
|
||||
|
@ -2039,31 +2045,13 @@ fn load_multi_threaded<'a>(
|
|||
|
||||
// Grab a reference to these Senders outside the loop, so we can share
|
||||
// it across each iteration of the loop.
|
||||
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 {
|
||||
// We intentionally don't propagate this Result, because even if
|
||||
// shutting down a worker failed (which can happen if a a panic
|
||||
// occurred on that thread), we want to continue shutting down
|
||||
// the others regardless.
|
||||
if listener.send(WorkerMsg::Shutdown).is_err() {
|
||||
log!("There was an error trying to shutdown a worker thread. One reason this can happen is if the thread panicked.");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// The root module will have already queued up messages to process,
|
||||
// and processing those messages will in turn queue up more messages.
|
||||
loop {
|
||||
match state_thread_step(arena, state, worker_listeners, &injector, &msg_tx, &msg_rx)
|
||||
{
|
||||
match state_thread_step(arena, state, &worker_wakers, &injector, &msg_tx, &msg_rx) {
|
||||
Ok(ControlFlow::Break(load_result)) => {
|
||||
shut_down_worker_threads!();
|
||||
|
||||
return Ok(load_result);
|
||||
}
|
||||
Ok(ControlFlow::Continue(new_state)) => {
|
||||
|
@ -2071,8 +2059,6 @@ fn load_multi_threaded<'a>(
|
|||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
shut_down_worker_threads!();
|
||||
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
|
@ -2111,13 +2097,13 @@ fn start_tasks<'a>(
|
|||
state: &mut State<'a>,
|
||||
work: MutSet<(ModuleId, Phase)>,
|
||||
injector: &Injector<BuildTask<'a>>,
|
||||
worker_listeners: &'a [Sender<WorkerMsg>],
|
||||
worker_wakers: &[Sender<()>],
|
||||
) -> Result<(), LoadingProblem<'a>> {
|
||||
for (module_id, phase) in work {
|
||||
let tasks = start_phase(module_id, phase, arena, state);
|
||||
|
||||
for task in tasks {
|
||||
enqueue_task(injector, worker_listeners, task)?
|
||||
enqueue_task(injector, worker_wakers, task)?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2179,7 +2165,7 @@ fn update<'a>(
|
|||
msg: Msg<'a>,
|
||||
msg_tx: MsgSender<'a>,
|
||||
injector: &Injector<BuildTask<'a>>,
|
||||
worker_listeners: &'a [Sender<WorkerMsg>],
|
||||
worker_wakers: &[Sender<()>],
|
||||
arena: &'a Bump,
|
||||
) -> Result<State<'a>, LoadingProblem<'a>> {
|
||||
use self::Msg::*;
|
||||
|
@ -2305,7 +2291,7 @@ fn update<'a>(
|
|||
work.extend(state.dependencies.notify(home, Phase::LoadHeader));
|
||||
work.insert((home, Phase::Parse));
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
@ -2382,7 +2368,7 @@ fn update<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
state
|
||||
.module_cache
|
||||
|
@ -2393,7 +2379,7 @@ fn update<'a>(
|
|||
|
||||
let work = state.dependencies.notify(module_id, Phase::Parse);
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
@ -2445,7 +2431,7 @@ fn update<'a>(
|
|||
.dependencies
|
||||
.notify(module_id, Phase::CanonicalizeAndConstrain);
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
@ -2652,7 +2638,7 @@ fn update<'a>(
|
|||
work
|
||||
};
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
}
|
||||
|
||||
Ok(state)
|
||||
|
@ -2700,7 +2686,7 @@ fn update<'a>(
|
|||
.dependencies
|
||||
.notify(module_id, Phase::FindSpecializations);
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
@ -2990,13 +2976,13 @@ fn update<'a>(
|
|||
|
||||
let work = state.dependencies.reload_make_specialization_pass();
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
NextStep::MakingInPhase => {
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
|
|
@ -539,7 +539,6 @@ pub enum Expr<'a> {
|
|||
|
||||
// Problems
|
||||
MalformedIdent(&'a str, crate::ident::BadIdent),
|
||||
MalformedClosure,
|
||||
MalformedSuffixed(&'a Loc<Expr<'a>>),
|
||||
// Both operators were non-associative, e.g. (True == False == False).
|
||||
// We should tell the author to disambiguate by grouping them with parens.
|
||||
|
@ -687,7 +686,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
Expr::SpaceBefore(a, _) => is_expr_suffixed(a),
|
||||
Expr::SpaceAfter(a, _) => is_expr_suffixed(a),
|
||||
Expr::MalformedIdent(_, _) => false,
|
||||
Expr::MalformedClosure => false,
|
||||
Expr::MalformedSuffixed(_) => false,
|
||||
Expr::PrecedenceConflict(_) => false,
|
||||
Expr::EmptyRecordBuilder(_) => false,
|
||||
|
@ -713,7 +711,6 @@ fn is_assigned_value_suffixed<'a>(value: &AssignedField<'a, Expr<'a>>) -> bool {
|
|||
AssignedField::SpaceBefore(a, _) | AssignedField::SpaceAfter(a, _) => {
|
||||
is_assigned_value_suffixed(a)
|
||||
}
|
||||
AssignedField::Malformed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -889,7 +886,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
| OptionalValue(_, _, loc_val)
|
||||
| IgnoredValue(_, _, loc_val) => break expr_stack.push(&loc_val.value),
|
||||
SpaceBefore(next, _) | SpaceAfter(next, _) => current = *next,
|
||||
LabelOnly(_) | Malformed(_) => break,
|
||||
LabelOnly(_) => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1038,7 +1035,6 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
| Tag(_)
|
||||
| OpaqueRef(_)
|
||||
| MalformedIdent(_, _)
|
||||
| MalformedClosure
|
||||
| PrecedenceConflict(_)
|
||||
| MalformedSuffixed(_) => { /* terminal */ }
|
||||
}
|
||||
|
@ -1614,9 +1610,6 @@ pub enum Tag<'a> {
|
|||
// We preserve this for the formatter; canonicalization ignores it.
|
||||
SpaceBefore(&'a Tag<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a Tag<'a>, &'a [CommentOrNewline<'a>]),
|
||||
|
||||
/// A malformed tag, which will code gen to a runtime error
|
||||
Malformed(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
@ -1639,9 +1632,6 @@ pub enum AssignedField<'a, Val> {
|
|||
// We preserve this for the formatter; canonicalization ignores it.
|
||||
SpaceBefore(&'a AssignedField<'a, Val>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a AssignedField<'a, Val>, &'a [CommentOrNewline<'a>]),
|
||||
|
||||
/// A malformed assigned field, which will code gen to a runtime error
|
||||
Malformed(&'a str),
|
||||
}
|
||||
|
||||
impl<'a, Val> AssignedField<'a, Val> {
|
||||
|
@ -1653,7 +1643,7 @@ impl<'a, Val> AssignedField<'a, Val> {
|
|||
Self::RequiredValue(_, _, val)
|
||||
| Self::OptionalValue(_, _, val)
|
||||
| Self::IgnoredValue(_, _, val) => break Some(val),
|
||||
Self::LabelOnly(_) | Self::Malformed(_) => break None,
|
||||
Self::LabelOnly(_) => break None,
|
||||
Self::SpaceBefore(next, _) | Self::SpaceAfter(next, _) => current = *next,
|
||||
}
|
||||
}
|
||||
|
@ -2518,7 +2508,6 @@ impl<'a> Malformed for Expr<'a> {
|
|||
ParensAround(expr) => expr.is_malformed(),
|
||||
|
||||
MalformedIdent(_, _) |
|
||||
MalformedClosure |
|
||||
MalformedSuffixed(..) |
|
||||
PrecedenceConflict(_) |
|
||||
EmptyRecordBuilder(_) |
|
||||
|
@ -2593,7 +2582,6 @@ impl<'a, T: Malformed> Malformed for AssignedField<'a, T> {
|
|||
AssignedField::SpaceBefore(field, _) | AssignedField::SpaceAfter(field, _) => {
|
||||
field.is_malformed()
|
||||
}
|
||||
AssignedField::Malformed(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2815,7 +2803,6 @@ impl<'a> Malformed for Tag<'a> {
|
|||
match self {
|
||||
Tag::Apply { name: _, args } => args.iter().any(|arg| arg.is_malformed()),
|
||||
Tag::SpaceBefore(tag, _) | Tag::SpaceAfter(tag, _) => tag.is_malformed(),
|
||||
Tag::Malformed(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2180,7 +2180,6 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
| Expr::DbgStmt(_, _)
|
||||
| Expr::LowLevelDbg(_, _, _)
|
||||
| Expr::Return(_, _)
|
||||
| Expr::MalformedClosure
|
||||
| Expr::MalformedSuffixed(..)
|
||||
| Expr::PrecedenceConflict { .. }
|
||||
| Expr::EmptyRecordBuilder(_)
|
||||
|
@ -2254,7 +2253,6 @@ fn assigned_expr_field_to_pattern_help<'a>(
|
|||
arena.alloc(assigned_expr_field_to_pattern_help(arena, nested)?),
|
||||
spaces,
|
||||
),
|
||||
AssignedField::Malformed(string) => Pattern::Malformed(string),
|
||||
AssignedField::IgnoredValue(_, _, _) => return Err(()),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -556,7 +556,6 @@ impl<'a, T: Normalize<'a> + Copy + std::fmt::Debug> Normalize<'a> for AssignedFi
|
|||
arena.alloc(c.normalize(arena)),
|
||||
),
|
||||
AssignedField::LabelOnly(a) => AssignedField::LabelOnly(a.normalize(arena)),
|
||||
AssignedField::Malformed(a) => AssignedField::Malformed(a),
|
||||
AssignedField::SpaceBefore(a, _) => a.normalize(arena),
|
||||
AssignedField::SpaceAfter(a, _) => a.normalize(arena),
|
||||
}
|
||||
|
@ -784,7 +783,6 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
a.normalize(arena)
|
||||
}
|
||||
Expr::MalformedIdent(a, b) => Expr::MalformedIdent(a, remove_spaces_bad_ident(b)),
|
||||
Expr::MalformedClosure => Expr::MalformedClosure,
|
||||
Expr::MalformedSuffixed(a) => Expr::MalformedSuffixed(a),
|
||||
Expr::PrecedenceConflict(a) => Expr::PrecedenceConflict(a),
|
||||
Expr::SpaceBefore(a, _) => a.normalize(arena),
|
||||
|
@ -938,7 +936,6 @@ impl<'a> Normalize<'a> for Tag<'a> {
|
|||
name: name.normalize(arena),
|
||||
args: args.normalize(arena),
|
||||
},
|
||||
Tag::Malformed(a) => Tag::Malformed(a),
|
||||
Tag::SpaceBefore(a, _) => a.normalize(arena),
|
||||
Tag::SpaceAfter(a, _) => a.normalize(arena),
|
||||
}
|
||||
|
|
|
@ -435,7 +435,6 @@ impl Problem {
|
|||
| Problem::RuntimeError(RuntimeError::InvalidPrecedence(_, region))
|
||||
| Problem::RuntimeError(RuntimeError::MalformedIdentifier(_, _, region))
|
||||
| Problem::RuntimeError(RuntimeError::MalformedTypeName(_, region))
|
||||
| Problem::RuntimeError(RuntimeError::MalformedClosure(region))
|
||||
| Problem::RuntimeError(RuntimeError::MalformedSuffixed(region))
|
||||
| Problem::RuntimeError(RuntimeError::InvalidRecordUpdate { region })
|
||||
| Problem::RuntimeError(RuntimeError::InvalidFloat(_, region, _))
|
||||
|
@ -678,7 +677,6 @@ pub enum RuntimeError {
|
|||
InvalidPrecedence(PrecedenceProblem, Region),
|
||||
MalformedIdentifier(Box<str>, roc_parse::ident::BadIdent, Region),
|
||||
MalformedTypeName(Box<str>, Region),
|
||||
MalformedClosure(Region),
|
||||
InvalidRecordUpdate {
|
||||
region: Region,
|
||||
},
|
||||
|
@ -750,7 +748,6 @@ impl RuntimeError {
|
|||
| RuntimeError::InvalidPrecedence(_, region)
|
||||
| RuntimeError::MalformedIdentifier(_, _, region)
|
||||
| RuntimeError::MalformedTypeName(_, region)
|
||||
| RuntimeError::MalformedClosure(region)
|
||||
| RuntimeError::MalformedSuffixed(region)
|
||||
| RuntimeError::InvalidRecordUpdate { region }
|
||||
| RuntimeError::InvalidFloat(_, region, _)
|
||||
|
|
|
@ -7,12 +7,6 @@ use roc_module::symbol::ModuleId;
|
|||
use roc_work::Phase;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WorkerMsg {
|
||||
Shutdown,
|
||||
TaskAdded,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ChannelProblem {
|
||||
FailedToSendRootMsg,
|
||||
|
@ -29,20 +23,11 @@ pub fn worker_task_step<Task>(
|
|||
worker: &Worker<Task>,
|
||||
injector: &Injector<Task>,
|
||||
stealers: &[Stealer<Task>],
|
||||
worker_msg_rx: &Receiver<WorkerMsg>,
|
||||
worker_wakeup_rx: &Receiver<()>,
|
||||
run_task: impl Fn(Task) -> Result<(), ChannelProblem>,
|
||||
) -> Result<ControlFlow<(), ()>, ChannelProblem> {
|
||||
match worker_msg_rx.try_recv() {
|
||||
Ok(msg) => {
|
||||
match msg {
|
||||
WorkerMsg::Shutdown => {
|
||||
// We've finished all our work. It's time to
|
||||
// shut down the thread, so when the main thread
|
||||
// blocks on joining with all the worker threads,
|
||||
// it can finally exit too!
|
||||
Ok(ControlFlow::Break(()))
|
||||
}
|
||||
WorkerMsg::TaskAdded => {
|
||||
match worker_wakeup_rx.try_recv() {
|
||||
Ok(()) => {
|
||||
// Find a task - either from this thread's queue,
|
||||
// or from the main queue, or from another worker's
|
||||
// queue - and run it.
|
||||
|
@ -58,12 +43,11 @@ pub fn worker_task_step<Task>(
|
|||
|
||||
Ok(ControlFlow::Continue(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => match err {
|
||||
crossbeam::channel::TryRecvError::Empty => Ok(ControlFlow::Continue(())),
|
||||
crossbeam::channel::TryRecvError::Disconnected => {
|
||||
Err(ChannelProblem::ChannelDisconnected)
|
||||
// The channel sender has been dropped, which means we want to shut down
|
||||
Ok(ControlFlow::Break(()))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -73,20 +57,11 @@ pub fn worker_task<Task>(
|
|||
worker: Worker<Task>,
|
||||
injector: &Injector<Task>,
|
||||
stealers: &[Stealer<Task>],
|
||||
worker_msg_rx: crossbeam::channel::Receiver<WorkerMsg>,
|
||||
worker_wakeup_rx: crossbeam::channel::Receiver<()>,
|
||||
run_task: impl Fn(Task) -> Result<(), ChannelProblem>,
|
||||
) -> Result<(), ChannelProblem> {
|
||||
// Keep listening until we receive a Shutdown msg
|
||||
for msg in worker_msg_rx.iter() {
|
||||
match msg {
|
||||
WorkerMsg::Shutdown => {
|
||||
// We've finished all our work. It's time to
|
||||
// shut down the thread, so when the main thread
|
||||
// blocks on joining with all the worker threads,
|
||||
// it can finally exit too!
|
||||
return Ok(());
|
||||
}
|
||||
WorkerMsg::TaskAdded => {
|
||||
for () in worker_wakeup_rx.iter() {
|
||||
// Find a task - either from this thread's queue,
|
||||
// or from the main queue, or from another worker's
|
||||
// queue - and run it.
|
||||
|
@ -100,8 +75,6 @@ pub fn worker_task<Task>(
|
|||
run_task(task)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -110,17 +83,17 @@ pub fn start_tasks<State, Task, Tasks: IntoIterator<Item = Task>>(
|
|||
state: &mut State,
|
||||
work: MutSet<(ModuleId, Phase)>,
|
||||
injector: &Injector<Task>,
|
||||
worker_listeners: &[Sender<WorkerMsg>],
|
||||
worker_wakers: &[Sender<()>],
|
||||
mut start_phase: impl FnMut(ModuleId, Phase, &mut State) -> Tasks,
|
||||
) -> Result<(), SendError<WorkerMsg>> {
|
||||
) -> Result<(), SendError<()>> {
|
||||
for (module_id, phase) in work {
|
||||
let tasks = start_phase(module_id, phase, state);
|
||||
|
||||
for task in tasks {
|
||||
injector.push(task);
|
||||
|
||||
for listener in worker_listeners {
|
||||
listener.send(WorkerMsg::TaskAdded)?;
|
||||
for listener in worker_wakers {
|
||||
listener.send(())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -481,7 +481,7 @@ pre>samp {
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
#module-search-form:focus-within #search-type-ahead {
|
||||
#search-type-ahead {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-direction: column;
|
||||
|
@ -489,11 +489,7 @@ pre>samp {
|
|||
top: calc(var(--module-search-padding-height) + var(--module-search-height));
|
||||
left: var(--module-search-form-padding-width);
|
||||
width: calc(100% - 2 * var(--module-search-form-padding-width));
|
||||
}
|
||||
|
||||
#search-type-ahead {
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
z-index: 100;
|
||||
background-color: var(--body-bg-color);
|
||||
border-width: 1px;
|
||||
|
|
|
@ -443,7 +443,6 @@ where
|
|||
AssignedField::SpaceBefore(af, _) | AssignedField::SpaceAfter(af, _) => {
|
||||
af.iter_tokens(arena)
|
||||
}
|
||||
AssignedField::Malformed(_) => bumpvec![in arena;],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -461,7 +460,6 @@ impl IterTokens for Tag<'_> {
|
|||
.chain(args.iter_tokens(arena))
|
||||
.collect_in(arena),
|
||||
Tag::SpaceBefore(t, _) | Tag::SpaceAfter(t, _) => t.iter_tokens(arena),
|
||||
Tag::Malformed(_) => bumpvec![in arena;],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -735,7 +733,6 @@ impl IterTokens for Loc<Expr<'_>> {
|
|||
Expr::SingleFieldRecordBuilder(e) => e.iter_tokens(arena),
|
||||
Expr::OptionalFieldInRecordBuilder(_name, e) => e.iter_tokens(arena),
|
||||
Expr::MalformedIdent(_, _)
|
||||
| Expr::MalformedClosure
|
||||
| Expr::PrecedenceConflict(_)
|
||||
| Expr::MalformedSuffixed(_) => {
|
||||
bumpvec![in arena;]
|
||||
|
|
|
@ -55,7 +55,6 @@ fn nixos_error_if_dynamic(url: &str, dest_dir: &Path) {
|
|||
You can:\n\n\t\
|
||||
- Download the source of the platform and build it locally, like in this example:\n\t \
|
||||
https://github.com/roc-lang/roc/blob/main/examples/platform-switching/rocLovesRust.roc.\n\t \
|
||||
When building your roc application, you can use the flag `--prebuilt-platform` to prevent the platform from being rebuilt every time.\n\t \
|
||||
For some graphical platforms you may need to use https://github.com/guibou/nixGL.\n\n\t\
|
||||
- Contact the author of the platform to ask them to statically link their platform.\n\t \
|
||||
musl can be used to prevent a dynamic dependency on the systems' libc.\n\t \
|
||||
|
|
|
@ -22,7 +22,7 @@ pub struct ReplOutput {
|
|||
|
||||
pub fn format_answer<'a>(arena: &'a Bump, answer: Expr<'_>) -> &'a str {
|
||||
match answer {
|
||||
Expr::Closure(_, _) | Expr::MalformedClosure => "<function>",
|
||||
Expr::Closure(_, _) => "<function>",
|
||||
_ => {
|
||||
let mut expr = roc_fmt::Buf::new_in(arena);
|
||||
|
||||
|
|
|
@ -2194,9 +2194,6 @@ fn pretty_runtime_error<'b>(
|
|||
|
||||
title = SYNTAX_PROBLEM;
|
||||
}
|
||||
RuntimeError::MalformedClosure(_) => {
|
||||
todo!("");
|
||||
}
|
||||
RuntimeError::MalformedSuffixed(_) => {
|
||||
todo!("error for malformed suffix");
|
||||
}
|
||||
|
|
|
@ -29,15 +29,14 @@ If you have a specific question, the [FAQ](/faq) might have an answer, although
|
|||
|
||||
## Running Examples
|
||||
|
||||
You can run examples as follows:
|
||||
You can run [examples](https://github.com/roc-lang/examples) as follows:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/roc-lang/examples.git
|
||||
cd examples
|
||||
roc dev helloWorld.roc
|
||||
roc ./HelloWorld/main.roc
|
||||
```
|
||||
|
||||
[crates/cli/tests/benchmarks](https://github.com/roc-lang/roc/tree/main/crates/cli/tests/benchmarks) contains more examples.
|
||||
|
||||
## Getting Involved
|
||||
|
||||
The number of people involved in Roc's development has been steadily increasing
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue