mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge branch 'main' into list-walk-with-index-until
This commit is contained in:
commit
a710dd18ac
25 changed files with 341 additions and 106 deletions
2
.github/workflows/nightly_linux_arm64.yml
vendored
2
.github/workflows/nightly_linux_arm64.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
||||||
run: ./ci/write_version.sh
|
run: ./ci/write_version.sh
|
||||||
|
|
||||||
- name: build release with lto
|
- name: build release with lto
|
||||||
run: cargo build --profile=release-with-lto --locked --bin roc
|
run: cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls
|
||||||
|
|
||||||
- name: get commit SHA
|
- name: get commit SHA
|
||||||
run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV
|
run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV
|
||||||
|
|
2
.github/workflows/nightly_linux_x86_64.yml
vendored
2
.github/workflows/nightly_linux_x86_64.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
||||||
run: ./ci/write_version.sh
|
run: ./ci/write_version.sh
|
||||||
|
|
||||||
- name: build release with lto
|
- name: build release with lto
|
||||||
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc
|
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls
|
||||||
# target-cpu=x86-64 -> For maximal compatibility for all CPU's. This was also faster in our tests: https://roc.zulipchat.com/#narrow/stream/231635-compiler-development/topic/.2Ecargo.2Fconfig.2Etoml/near/325726299
|
# target-cpu=x86-64 -> For maximal compatibility for all CPU's. This was also faster in our tests: https://roc.zulipchat.com/#narrow/stream/231635-compiler-development/topic/.2Ecargo.2Fconfig.2Etoml/near/325726299
|
||||||
|
|
||||||
- name: get commit SHA
|
- name: get commit SHA
|
||||||
|
|
|
@ -42,11 +42,7 @@ jobs:
|
||||||
run: ./ci/write_version.sh
|
run: ./ci/write_version.sh
|
||||||
|
|
||||||
- name: build nightly release
|
- name: build nightly release
|
||||||
run: cargo build --locked --profile=release-with-lto --bin roc
|
run: cargo build --locked --profile=release-with-lto --bin roc --bin roc_ls
|
||||||
|
|
||||||
# this makes the roc binary a lot smaller
|
|
||||||
- name: strip debug info
|
|
||||||
run: strip ./target/release-with-lto/roc
|
|
||||||
|
|
||||||
- name: package release
|
- name: package release
|
||||||
run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }}
|
run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }}
|
||||||
|
|
2
.github/workflows/nightly_macos_x86_64.yml
vendored
2
.github/workflows/nightly_macos_x86_64.yml
vendored
|
@ -32,7 +32,7 @@ jobs:
|
||||||
# this issue may be caused by using older versions of XCode
|
# this issue may be caused by using older versions of XCode
|
||||||
|
|
||||||
- name: build release
|
- name: build release
|
||||||
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc
|
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls
|
||||||
# target-cpu=x86-64 -> For maximal compatibility for all CPU's.
|
# target-cpu=x86-64 -> For maximal compatibility for all CPU's.
|
||||||
|
|
||||||
- name: get commit SHA
|
- name: get commit SHA
|
||||||
|
|
|
@ -53,9 +53,7 @@ build-nightly-release:
|
||||||
COPY --dir .git LICENSE LEGAL_DETAILS ci ./
|
COPY --dir .git LICENSE LEGAL_DETAILS ci ./
|
||||||
# version.txt is used by the CLI: roc --version
|
# version.txt is used by the CLI: roc --version
|
||||||
RUN ./ci/write_version.sh
|
RUN ./ci/write_version.sh
|
||||||
RUN RUSTFLAGS=$RUSTFLAGS cargo build --profile=release-with-lto --locked --bin roc
|
RUN RUSTFLAGS=$RUSTFLAGS cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls
|
||||||
# strip debug info
|
|
||||||
RUN strip ./target/release-with-lto/roc
|
|
||||||
RUN ./ci/package_release.sh $RELEASE_FOLDER_NAME
|
RUN ./ci/package_release.sh $RELEASE_FOLDER_NAME
|
||||||
RUN ls
|
RUN ls
|
||||||
SAVE ARTIFACT ./$RELEASE_FOLDER_NAME.tar.gz AS LOCAL $RELEASE_FOLDER_NAME.tar.gz
|
SAVE ARTIFACT ./$RELEASE_FOLDER_NAME.tar.gz AS LOCAL $RELEASE_FOLDER_NAME.tar.gz
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
- [**tutorial**](https://roc-lang.org/tutorial)
|
- [**tutorial**](https://roc-lang.org/tutorial)
|
||||||
- [**docs** for the standard library](https://www.roc-lang.org/builtins)
|
- [**docs** for the standard library](https://www.roc-lang.org/builtins)
|
||||||
- [**examples**](https://github.com/roc-lang/examples/tree/main/examples)
|
- [**examples**](https://github.com/roc-lang/examples/tree/main/examples)
|
||||||
- [**faq**: frequently asked questions](https://github.com/roc-lang/roc/blob/main/FAQ.md)
|
- [**faq**: frequently asked questions](https://github.com/roc-lang/roc/blob/main/www/content/faq.md)
|
||||||
- [**group chat**](https://roc.zulipchat.com) for help, questions and discussions
|
- [**group chat**](https://roc.zulipchat.com) for help, questions and discussions
|
||||||
|
|
||||||
If you'd like to contribute, check out [good first issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). Don't hesitate to ask for help on our [group chat](https://roc.zulipchat.com), we're friendly!
|
If you'd like to contribute, check out [good first issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). Don't hesitate to ask for help on our [group chat](https://roc.zulipchat.com), we're friendly!
|
||||||
|
|
|
@ -3,15 +3,21 @@
|
||||||
# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
|
# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
cp target/release-with-lto/roc ./roc # to be able to delete "target" later
|
# this makes the binaries a lot smaller
|
||||||
|
strip ./target/release-with-lto/roc
|
||||||
|
strip ./target/release-with-lto/roc_ls
|
||||||
|
|
||||||
|
# to be able to delete "target" later
|
||||||
|
cp target/release-with-lto/roc ./roc
|
||||||
|
cp target/release-with-lto/roc_ls ./roc_lang_server
|
||||||
|
|
||||||
# delete unnecessary files and folders
|
# delete unnecessary files and folders
|
||||||
git clean -fdx --exclude roc
|
git clean -fdx --exclude roc --exclude roc_lang_server
|
||||||
|
|
||||||
mkdir $1
|
mkdir $1
|
||||||
|
|
||||||
|
|
||||||
mv roc LICENSE LEGAL_DETAILS $1
|
mv roc roc_lang_server LICENSE LEGAL_DETAILS $1
|
||||||
|
|
||||||
mkdir $1/examples
|
mkdir $1/examples
|
||||||
mv examples/helloWorld.roc examples/platform-switching examples/cli $1/examples
|
mv examples/helloWorld.roc examples/platform-switching examples/cli $1/examples
|
||||||
|
|
|
@ -560,8 +560,6 @@ tau = 2 * pi
|
||||||
# ------- Functions
|
# ------- Functions
|
||||||
## Convert a number to a [Str].
|
## Convert a number to a [Str].
|
||||||
##
|
##
|
||||||
## This is the same as calling `Num.format {}` - so for more details on
|
|
||||||
## exact formatting, see `Num.format`.
|
|
||||||
## ```
|
## ```
|
||||||
## Num.toStr 42
|
## Num.toStr 42
|
||||||
## ```
|
## ```
|
||||||
|
@ -573,7 +571,6 @@ tau = 2 * pi
|
||||||
## When this function is given a non-[finite](Num.isFinite)
|
## When this function is given a non-[finite](Num.isFinite)
|
||||||
## [F64] or [F32] value, the returned string will be `"NaN"`, `"∞"`, or `"-∞"`.
|
## [F64] or [F32] value, the returned string will be `"NaN"`, `"∞"`, or `"-∞"`.
|
||||||
##
|
##
|
||||||
## To get strings in hexadecimal, octal, or binary format, use `Num.format`.
|
|
||||||
toStr : Num * -> Str
|
toStr : Num * -> Str
|
||||||
intCast : Int a -> Int b
|
intCast : Int a -> Int b
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,25 @@ pub fn call_bitcode_fn<'ctx>(
|
||||||
args: &[BasicValueEnum<'ctx>],
|
args: &[BasicValueEnum<'ctx>],
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
call_bitcode_fn_help(env, args, fn_name)
|
let ret = call_bitcode_fn_help(env, args, fn_name)
|
||||||
.try_as_basic_value()
|
.try_as_basic_value()
|
||||||
.left()
|
.left()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}")
|
panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}")
|
||||||
})
|
});
|
||||||
|
|
||||||
|
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||||
|
// On windows zig uses a vector type <2xi64> instead of a i128 value
|
||||||
|
let vec_type = env.context.i64_type().vec_type(2);
|
||||||
|
if ret.get_type() == vec_type.into() {
|
||||||
|
return env
|
||||||
|
.builder
|
||||||
|
.build_bitcast(ret, env.context.i128_type(), "return_i128")
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_void_bitcode_fn<'ctx>(
|
pub fn call_void_bitcode_fn<'ctx>(
|
||||||
|
@ -54,7 +67,35 @@ fn call_bitcode_fn_help<'ctx>(
|
||||||
args: &[BasicValueEnum<'ctx>],
|
args: &[BasicValueEnum<'ctx>],
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
) -> CallSiteValue<'ctx> {
|
) -> CallSiteValue<'ctx> {
|
||||||
let it = args.iter().map(|x| (*x).into());
|
let it = args
|
||||||
|
.iter()
|
||||||
|
.map(|x| {
|
||||||
|
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||||
|
if x.get_type() == env.context.i128_type().into() {
|
||||||
|
let parent = env
|
||||||
|
.builder
|
||||||
|
.get_insert_block()
|
||||||
|
.and_then(|b| b.get_parent())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let alloca = create_entry_block_alloca(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
x.get_type(),
|
||||||
|
"pass_u128_by_reference",
|
||||||
|
);
|
||||||
|
|
||||||
|
env.builder.build_store(alloca, *x).unwrap();
|
||||||
|
|
||||||
|
alloca.into()
|
||||||
|
} else {
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|x| (x).into());
|
||||||
let arguments = bumpalo::collections::Vec::from_iter_in(it, env.arena);
|
let arguments = bumpalo::collections::Vec::from_iter_in(it, env.arena);
|
||||||
|
|
||||||
let fn_val = env
|
let fn_val = env
|
||||||
|
|
|
@ -1067,11 +1067,42 @@ pub fn module_from_builtins<'ctx>(
|
||||||
|
|
||||||
// Also, must_keep is the functions we depend on that would normally be provide by libc.
|
// Also, must_keep is the functions we depend on that would normally be provide by libc.
|
||||||
// They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd.
|
// They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd.
|
||||||
let must_keep = ["_fltused", "floorf", "memcpy", "memset"];
|
let must_keep = [
|
||||||
|
"_fltused",
|
||||||
|
"floorf",
|
||||||
|
"memcpy",
|
||||||
|
"memset",
|
||||||
|
// I have no idea why this function is special.
|
||||||
|
// Without it, some tests hang on M1 mac outside of nix.
|
||||||
|
"__muloti4",
|
||||||
|
// fixes `Undefined Symbol in relocation`
|
||||||
|
"__udivti3",
|
||||||
|
// Roc special functions
|
||||||
|
"__roc_force_longjmp",
|
||||||
|
"__roc_force_setjmp",
|
||||||
|
"set_shared_buffer",
|
||||||
|
];
|
||||||
for func in module.get_functions() {
|
for func in module.get_functions() {
|
||||||
let has_definition = func.count_basic_blocks() > 0;
|
let has_definition = func.count_basic_blocks() > 0;
|
||||||
let name = func.get_name().to_string_lossy();
|
let name = func.get_name().to_string_lossy();
|
||||||
if has_definition && !must_keep.contains(&name.as_ref()) {
|
if has_definition
|
||||||
|
&& !name.starts_with("roc_builtins.")
|
||||||
|
&& !must_keep.contains(&name.as_ref())
|
||||||
|
{
|
||||||
|
func.set_linkage(Linkage::Private);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, running DCE here is faster then waiting until full app DCE.
|
||||||
|
let mpm = PassManager::create(());
|
||||||
|
mpm.add_global_dce_pass();
|
||||||
|
mpm.run_on(&module);
|
||||||
|
|
||||||
|
// Now that the unused compiler-rt functions have been removed,
|
||||||
|
// mark that the builtin functions are allowed to be DCE'd if they aren't used.
|
||||||
|
for func in module.get_functions() {
|
||||||
|
let name = func.get_name().to_string_lossy();
|
||||||
|
if name.starts_with("roc_builtins.") {
|
||||||
func.set_linkage(Linkage::Private);
|
func.set_linkage(Linkage::Private);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1100,13 +1100,22 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
NumBytesToU128 => {
|
NumBytesToU128 => {
|
||||||
arguments!(list, position);
|
arguments!(list, position);
|
||||||
|
|
||||||
call_list_bitcode_fn(
|
let ret = call_list_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[list.into_struct_value()],
|
&[list.into_struct_value()],
|
||||||
&[position],
|
&[position],
|
||||||
BitcodeReturns::Basic,
|
BitcodeReturns::Basic,
|
||||||
bitcode::NUM_BYTES_TO_U128,
|
bitcode::NUM_BYTES_TO_U128,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||||
|
// On windows the return type is not a i128, likely due to alignment
|
||||||
|
env.builder
|
||||||
|
.build_bitcast(ret, env.context.i128_type(), "empty_string")
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NumCompare => {
|
NumCompare => {
|
||||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||||
|
@ -2596,7 +2605,16 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PtrWidth::Bytes8 => {
|
PtrWidth::Bytes8 => {
|
||||||
if target_int_width.stack_size() as usize > env.target_info.ptr_size() {
|
let return_by_pointer = {
|
||||||
|
if env.target_info.operating_system
|
||||||
|
== roc_target::OperatingSystem::Windows
|
||||||
|
{
|
||||||
|
target_int_width.stack_size() as usize >= env.target_info.ptr_size()
|
||||||
|
} else {
|
||||||
|
target_int_width.stack_size() as usize > env.target_info.ptr_size()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if return_by_pointer {
|
||||||
let bitcode_return_type =
|
let bitcode_return_type =
|
||||||
zig_to_int_checked_result_type(env, target_int_width.type_name());
|
zig_to_int_checked_result_type(env, target_int_width.type_name());
|
||||||
|
|
||||||
|
|
|
@ -684,6 +684,7 @@ impl MakeSpecializationsPass {
|
||||||
struct State<'a> {
|
struct State<'a> {
|
||||||
pub root_id: ModuleId,
|
pub root_id: ModuleId,
|
||||||
pub root_subs: Option<Subs>,
|
pub root_subs: Option<Subs>,
|
||||||
|
pub root_path: PathBuf,
|
||||||
pub cache_dir: PathBuf,
|
pub cache_dir: PathBuf,
|
||||||
/// If the root is an app module, the shorthand specified in its header's `to` field
|
/// If the root is an app module, the shorthand specified in its header's `to` field
|
||||||
pub opt_platform_shorthand: Option<&'a str>,
|
pub opt_platform_shorthand: Option<&'a str>,
|
||||||
|
@ -752,6 +753,7 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
root_id: ModuleId,
|
root_id: ModuleId,
|
||||||
|
root_path: PathBuf,
|
||||||
opt_platform_shorthand: Option<&'a str>,
|
opt_platform_shorthand: Option<&'a str>,
|
||||||
target_info: TargetInfo,
|
target_info: TargetInfo,
|
||||||
function_kind: FunctionKind,
|
function_kind: FunctionKind,
|
||||||
|
@ -770,6 +772,7 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
root_id,
|
root_id,
|
||||||
|
root_path,
|
||||||
root_subs: None,
|
root_subs: None,
|
||||||
opt_platform_shorthand,
|
opt_platform_shorthand,
|
||||||
cache_dir,
|
cache_dir,
|
||||||
|
@ -1077,8 +1080,9 @@ pub struct LoadStart<'a> {
|
||||||
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
|
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||||
ident_ids_by_module: SharedIdentIdsByModule,
|
ident_ids_by_module: SharedIdentIdsByModule,
|
||||||
root_id: ModuleId,
|
root_id: ModuleId,
|
||||||
opt_platform_shorthand: Option<&'a str>,
|
root_path: PathBuf,
|
||||||
root_msg: Msg<'a>,
|
root_msg: Msg<'a>,
|
||||||
|
opt_platform_shorthand: Option<&'a str>,
|
||||||
src_dir: PathBuf,
|
src_dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,7 +1105,7 @@ impl<'a> LoadStart<'a> {
|
||||||
|
|
||||||
let res_loaded = load_filename(
|
let res_loaded = load_filename(
|
||||||
arena,
|
arena,
|
||||||
filename,
|
filename.clone(),
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
@ -1136,6 +1140,7 @@ impl<'a> LoadStart<'a> {
|
||||||
ident_ids_by_module,
|
ident_ids_by_module,
|
||||||
src_dir,
|
src_dir,
|
||||||
root_id: header_output.module_id,
|
root_id: header_output.module_id,
|
||||||
|
root_path: filename,
|
||||||
root_msg: header_output.msg,
|
root_msg: header_output.msg,
|
||||||
opt_platform_shorthand: header_output.opt_platform_shorthand,
|
opt_platform_shorthand: header_output.opt_platform_shorthand,
|
||||||
})
|
})
|
||||||
|
@ -1162,7 +1167,7 @@ impl<'a> LoadStart<'a> {
|
||||||
|
|
||||||
let header_output = load_from_str(
|
let header_output = load_from_str(
|
||||||
arena,
|
arena,
|
||||||
filename,
|
filename.clone(),
|
||||||
src,
|
src,
|
||||||
Arc::clone(&arc_modules),
|
Arc::clone(&arc_modules),
|
||||||
Arc::clone(&ident_ids_by_module),
|
Arc::clone(&ident_ids_by_module),
|
||||||
|
@ -1178,6 +1183,7 @@ impl<'a> LoadStart<'a> {
|
||||||
src_dir,
|
src_dir,
|
||||||
ident_ids_by_module,
|
ident_ids_by_module,
|
||||||
root_id,
|
root_id,
|
||||||
|
root_path: filename,
|
||||||
root_msg,
|
root_msg,
|
||||||
opt_platform_shorthand: opt_platform_id,
|
opt_platform_shorthand: opt_platform_id,
|
||||||
})
|
})
|
||||||
|
@ -1352,6 +1358,7 @@ pub fn load_single_threaded<'a>(
|
||||||
arc_modules,
|
arc_modules,
|
||||||
ident_ids_by_module,
|
ident_ids_by_module,
|
||||||
root_id,
|
root_id,
|
||||||
|
root_path,
|
||||||
root_msg,
|
root_msg,
|
||||||
src_dir,
|
src_dir,
|
||||||
opt_platform_shorthand,
|
opt_platform_shorthand,
|
||||||
|
@ -1367,6 +1374,7 @@ pub fn load_single_threaded<'a>(
|
||||||
let number_of_workers = 1;
|
let number_of_workers = 1;
|
||||||
let mut state = State::new(
|
let mut state = State::new(
|
||||||
root_id,
|
root_id,
|
||||||
|
root_path,
|
||||||
opt_platform_shorthand,
|
opt_platform_shorthand,
|
||||||
target_info,
|
target_info,
|
||||||
function_kind,
|
function_kind,
|
||||||
|
@ -1503,7 +1511,7 @@ fn state_thread_step<'a>(
|
||||||
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
|
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
|
||||||
}
|
}
|
||||||
Msg::FailedToReadFile { filename, error } => {
|
Msg::FailedToReadFile { filename, error } => {
|
||||||
let buf = to_file_problem_report_string(&filename, error);
|
let buf = to_file_problem_report_string(filename, error);
|
||||||
Err(LoadingProblem::FormattedReport(buf))
|
Err(LoadingProblem::FormattedReport(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1654,7 +1662,7 @@ pub fn report_loading_problem(
|
||||||
}
|
}
|
||||||
LoadingProblem::FormattedReport(report) => report,
|
LoadingProblem::FormattedReport(report) => report,
|
||||||
LoadingProblem::FileProblem { filename, error } => {
|
LoadingProblem::FileProblem { filename, error } => {
|
||||||
to_file_problem_report_string(&filename, error)
|
to_file_problem_report_string(filename, error)
|
||||||
}
|
}
|
||||||
err => todo!("Loading error: {:?}", err),
|
err => todo!("Loading error: {:?}", err),
|
||||||
}
|
}
|
||||||
|
@ -1677,6 +1685,7 @@ fn load_multi_threaded<'a>(
|
||||||
arc_modules,
|
arc_modules,
|
||||||
ident_ids_by_module,
|
ident_ids_by_module,
|
||||||
root_id,
|
root_id,
|
||||||
|
root_path,
|
||||||
root_msg,
|
root_msg,
|
||||||
src_dir,
|
src_dir,
|
||||||
opt_platform_shorthand,
|
opt_platform_shorthand,
|
||||||
|
@ -1707,6 +1716,7 @@ fn load_multi_threaded<'a>(
|
||||||
|
|
||||||
let mut state = State::new(
|
let mut state = State::new(
|
||||||
root_id,
|
root_id,
|
||||||
|
root_path,
|
||||||
opt_platform_shorthand,
|
opt_platform_shorthand,
|
||||||
target_info,
|
target_info,
|
||||||
function_kind,
|
function_kind,
|
||||||
|
@ -2238,6 +2248,7 @@ fn update<'a>(
|
||||||
let buf = to_https_problem_report_string(
|
let buf = to_https_problem_report_string(
|
||||||
url,
|
url,
|
||||||
Problem::InvalidUrl(url_err),
|
Problem::InvalidUrl(url_err),
|
||||||
|
header.module_path,
|
||||||
);
|
);
|
||||||
return Err(LoadingProblem::FormattedReport(buf));
|
return Err(LoadingProblem::FormattedReport(buf));
|
||||||
}
|
}
|
||||||
|
@ -3159,7 +3170,7 @@ fn finish_specialization<'a>(
|
||||||
}
|
}
|
||||||
Valid(To::NewPackage(p_or_p)) => PathBuf::from(p_or_p.as_str()),
|
Valid(To::NewPackage(p_or_p)) => PathBuf::from(p_or_p.as_str()),
|
||||||
other => {
|
other => {
|
||||||
let buf = to_missing_platform_report(state.root_id, other);
|
let buf = report_cannot_run(state.root_id, state.root_path, other);
|
||||||
return Err(LoadingProblem::FormattedReport(buf));
|
return Err(LoadingProblem::FormattedReport(buf));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3513,9 +3524,7 @@ fn load_builtin_module_help<'a>(
|
||||||
) -> (HeaderInfo<'a>, roc_parse::state::State<'a>) {
|
) -> (HeaderInfo<'a>, roc_parse::state::State<'a>) {
|
||||||
let is_root_module = false;
|
let is_root_module = false;
|
||||||
let opt_shorthand = None;
|
let opt_shorthand = None;
|
||||||
|
|
||||||
let filename = PathBuf::from(filename);
|
let filename = PathBuf::from(filename);
|
||||||
|
|
||||||
let parse_state = roc_parse::state::State::new(src_bytes.as_bytes());
|
let parse_state = roc_parse::state::State::new(src_bytes.as_bytes());
|
||||||
let parsed = roc_parse::module::parse_header(arena, parse_state.clone());
|
let parsed = roc_parse::module::parse_header(arena, parse_state.clone());
|
||||||
|
|
||||||
|
@ -3968,6 +3977,7 @@ fn parse_header<'a>(
|
||||||
module_timing,
|
module_timing,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let filename = resolved_header.module_path.clone();
|
||||||
let mut messages = Vec::with_capacity(packages.len() + 1);
|
let mut messages = Vec::with_capacity(packages.len() + 1);
|
||||||
|
|
||||||
// It's important that the app header is first in the list!
|
// It's important that the app header is first in the list!
|
||||||
|
@ -3982,6 +3992,7 @@ fn parse_header<'a>(
|
||||||
module_id,
|
module_id,
|
||||||
module_ids,
|
module_ids,
|
||||||
ident_ids_by_module,
|
ident_ids_by_module,
|
||||||
|
filename,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Look at the app module's `to` keyword to determine which package was the platform.
|
// Look at the app module's `to` keyword to determine which package was the platform.
|
||||||
|
@ -4084,6 +4095,7 @@ fn load_packages<'a>(
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||||
ident_ids_by_module: SharedIdentIdsByModule,
|
ident_ids_by_module: SharedIdentIdsByModule,
|
||||||
|
filename: PathBuf,
|
||||||
) {
|
) {
|
||||||
// Load all the packages
|
// Load all the packages
|
||||||
for Loc { value: entry, .. } in packages.iter() {
|
for Loc { value: entry, .. } in packages.iter() {
|
||||||
|
@ -4121,7 +4133,7 @@ fn load_packages<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(problem) => {
|
Err(problem) => {
|
||||||
let buf = to_https_problem_report_string(src, problem);
|
let buf = to_https_problem_report_string(src, problem, filename);
|
||||||
|
|
||||||
load_messages.push(Msg::FailedToLoad(LoadingProblem::FormattedReport(buf)));
|
load_messages.push(Msg::FailedToLoad(LoadingProblem::FormattedReport(buf)));
|
||||||
return;
|
return;
|
||||||
|
@ -6581,7 +6593,11 @@ fn to_parse_problem_report<'a>(
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> String {
|
fn report_cannot_run(
|
||||||
|
module_id: ModuleId,
|
||||||
|
filename: PathBuf,
|
||||||
|
platform_path: &PlatformPath,
|
||||||
|
) -> String {
|
||||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||||
use ven_pretty::DocAllocator;
|
use ven_pretty::DocAllocator;
|
||||||
use PlatformPath::*;
|
use PlatformPath::*;
|
||||||
|
@ -6591,20 +6607,20 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
|
||||||
let alloc = RocDocAllocator::new(&[], module_id, &interns);
|
let alloc = RocDocAllocator::new(&[], module_id, &interns);
|
||||||
|
|
||||||
let report = {
|
let report = {
|
||||||
match other {
|
match platform_path {
|
||||||
Valid(_) => unreachable!(),
|
Valid(_) => unreachable!(),
|
||||||
NotSpecified => {
|
NotSpecified => {
|
||||||
let doc = alloc.stack([
|
let doc = alloc.stack([
|
||||||
alloc.reflow("I could not find a platform based on your input file."),
|
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.reflow(r"Does the module header have an entry that looks like this?"),
|
||||||
alloc
|
alloc
|
||||||
.parser_suggestion(" packages { pf: \"platform\" }")
|
.parser_suggestion("packages { blah: \"…path or URL to platform…\" }")
|
||||||
.indent(4),
|
.indent(4),
|
||||||
alloc.reflow("See also TODO."),
|
alloc.reflow("Tip: The following part of the tutorial has an example of specifying a platform:\n\n<https://www.roc-lang.org/tutorial#building-an-application>"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "NO PLATFORM".to_string(),
|
title: "NO PLATFORM".to_string(),
|
||||||
severity: Severity::RuntimeError,
|
severity: Severity::RuntimeError,
|
||||||
|
@ -6619,7 +6635,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "NO PLATFORM".to_string(),
|
title: "NO PLATFORM".to_string(),
|
||||||
severity: Severity::RuntimeError,
|
severity: Severity::RuntimeError,
|
||||||
|
@ -6634,7 +6650,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "NO PLATFORM".to_string(),
|
title: "NO PLATFORM".to_string(),
|
||||||
severity: Severity::RuntimeError,
|
severity: Severity::RuntimeError,
|
||||||
|
@ -6649,7 +6665,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "NO PLATFORM".to_string(),
|
title: "NO PLATFORM".to_string(),
|
||||||
severity: Severity::RuntimeError,
|
severity: Severity::RuntimeError,
|
||||||
|
|
|
@ -234,7 +234,19 @@ fn verify_procedures<'a>(
|
||||||
|
|
||||||
if !has_changes.stdout.is_empty() {
|
if !has_changes.stdout.is_empty() {
|
||||||
println!("{}", std::str::from_utf8(&has_changes.stdout).unwrap());
|
println!("{}", std::str::from_utf8(&has_changes.stdout).unwrap());
|
||||||
panic!("Output changed: resolve conflicts and `git add` the file.");
|
panic!(indoc!(
|
||||||
|
r#"
|
||||||
|
|
||||||
|
Mono output has changed! This is normal when making changes to the builtins.
|
||||||
|
To fix it; run these commands locally:
|
||||||
|
|
||||||
|
cargo test -p test_mono -p uitest --no-fail-fast
|
||||||
|
git add -u
|
||||||
|
git commit -S -m "update mono tests"
|
||||||
|
git push origin YOUR_BRANCH_NAME
|
||||||
|
|
||||||
|
"#
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1090,7 +1090,7 @@ pub fn can_problem<'b>(
|
||||||
title = "OVERAPPLIED CRASH".to_string();
|
title = "OVERAPPLIED CRASH".to_string();
|
||||||
}
|
}
|
||||||
Problem::FileProblem { filename, error } => {
|
Problem::FileProblem { filename, error } => {
|
||||||
let report = to_file_problem_report(alloc, &filename, error);
|
let report = to_file_problem_report(alloc, filename, error);
|
||||||
doc = report.doc;
|
doc = report.doc;
|
||||||
title = report.title;
|
title = report.title;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1101,7 +1101,11 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
pub fn to_https_problem_report_string(url: &str, https_problem: Problem) -> String {
|
pub fn to_https_problem_report_string(
|
||||||
|
url: &str,
|
||||||
|
https_problem: Problem,
|
||||||
|
filename: PathBuf,
|
||||||
|
) -> String {
|
||||||
let src_lines: Vec<&str> = Vec::new();
|
let src_lines: Vec<&str> = Vec::new();
|
||||||
|
|
||||||
let mut module_ids = ModuleIds::default();
|
let mut module_ids = ModuleIds::default();
|
||||||
|
@ -1115,7 +1119,7 @@ pub fn to_https_problem_report_string(url: &str, https_problem: Problem) -> Stri
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let palette = DEFAULT_PALETTE;
|
let palette = DEFAULT_PALETTE;
|
||||||
let report = to_https_problem_report(&alloc, url, https_problem);
|
let report = to_https_problem_report(&alloc, url, https_problem, filename);
|
||||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||||
|
|
||||||
buf
|
buf
|
||||||
|
@ -1126,6 +1130,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
alloc: &'b RocDocAllocator<'b>,
|
alloc: &'b RocDocAllocator<'b>,
|
||||||
url: &'b str,
|
url: &'b str,
|
||||||
https_problem: Problem,
|
https_problem: Problem,
|
||||||
|
filename: PathBuf,
|
||||||
) -> Report<'b> {
|
) -> Report<'b> {
|
||||||
match https_problem {
|
match https_problem {
|
||||||
Problem::UnsupportedEncoding(not_supported_encoding) => {
|
Problem::UnsupportedEncoding(not_supported_encoding) => {
|
||||||
|
@ -1154,7 +1159,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "UNSUPPORTED ENCODING".to_string(),
|
title: "UNSUPPORTED ENCODING".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1189,7 +1194,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "MULTIPLE ENCODINGS".to_string(),
|
title: "MULTIPLE ENCODINGS".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1224,7 +1229,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "INVALID CONTENT HASH".to_string(),
|
title: "INVALID CONTENT HASH".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1241,7 +1246,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
alloc.concat([alloc.tip(), alloc.reflow(r"Is the URL correct?")]),
|
alloc.concat([alloc.tip(), alloc.reflow(r"Is the URL correct?")]),
|
||||||
]);
|
]);
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "NOTFOUND".to_string(),
|
title: "NOTFOUND".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1268,7 +1273,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "IO ERROR".to_string(),
|
title: "IO ERROR".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1295,7 +1300,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "IO ERROR".to_string(),
|
title: "IO ERROR".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1324,7 +1329,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "HTTP ERROR".to_string(),
|
title: "HTTP ERROR".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1365,7 +1370,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "INVALID EXTENSION SUFFIX".to_string(),
|
title: "INVALID EXTENSION SUFFIX".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1398,7 +1403,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "INVALID EXTENSION".to_string(),
|
title: "INVALID EXTENSION".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1436,7 +1441,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "INVALID FRAGMENT".to_string(),
|
title: "INVALID FRAGMENT".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1474,7 +1479,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "MISSING PACKAGE HASH".to_string(),
|
title: "MISSING PACKAGE HASH".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1500,7 +1505,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "HTTPS MANDATORY".to_string(),
|
title: "HTTPS MANDATORY".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1543,7 +1548,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "MISLEADING CHARACTERS".to_string(),
|
title: "MISLEADING CHARACTERS".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1573,7 +1578,7 @@ pub fn to_https_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "FILE TOO LARGE".to_string(),
|
title: "FILE TOO LARGE".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1582,13 +1587,10 @@ pub fn to_https_problem_report<'b>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_file_problem_report_string(filename: &Path, error: io::ErrorKind) -> String {
|
pub fn to_file_problem_report_string(filename: PathBuf, error: io::ErrorKind) -> String {
|
||||||
let src_lines: Vec<&str> = Vec::new();
|
let src_lines: Vec<&str> = Vec::new();
|
||||||
|
|
||||||
let mut module_ids = ModuleIds::default();
|
let mut module_ids = ModuleIds::default();
|
||||||
|
|
||||||
let module_id = module_ids.get_or_insert(&"find module name somehow?".into());
|
let module_id = module_ids.get_or_insert(&"find module name somehow?".into());
|
||||||
|
|
||||||
let interns = Interns::default();
|
let interns = Interns::default();
|
||||||
|
|
||||||
// Report parsing and canonicalization problems
|
// Report parsing and canonicalization problems
|
||||||
|
@ -1604,16 +1606,16 @@ pub fn to_file_problem_report_string(filename: &Path, error: io::ErrorKind) -> S
|
||||||
|
|
||||||
pub fn to_file_problem_report<'b>(
|
pub fn to_file_problem_report<'b>(
|
||||||
alloc: &'b RocDocAllocator<'b>,
|
alloc: &'b RocDocAllocator<'b>,
|
||||||
filename: &Path,
|
filename: PathBuf,
|
||||||
error: io::ErrorKind,
|
error: io::ErrorKind,
|
||||||
) -> Report<'b> {
|
) -> Report<'b> {
|
||||||
let filename: String = filename.to_str().unwrap().to_string();
|
let filename_str: String = filename.to_str().unwrap().to_string();
|
||||||
match error {
|
match error {
|
||||||
io::ErrorKind::NotFound => {
|
io::ErrorKind::NotFound => {
|
||||||
let doc = alloc.stack([
|
let doc = alloc.stack([
|
||||||
alloc.reflow(r"I am looking for this file, but it's not there:"),
|
alloc.reflow(r"I am looking for this file, but it's not there:"),
|
||||||
alloc
|
alloc
|
||||||
.string(filename)
|
.string(filename_str)
|
||||||
.annotate(Annotation::ParserSuggestion)
|
.annotate(Annotation::ParserSuggestion)
|
||||||
.indent(4),
|
.indent(4),
|
||||||
alloc.concat([
|
alloc.concat([
|
||||||
|
@ -1623,7 +1625,7 @@ pub fn to_file_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "FILE NOT FOUND".to_string(),
|
title: "FILE NOT FOUND".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1633,7 +1635,7 @@ pub fn to_file_problem_report<'b>(
|
||||||
let doc = alloc.stack([
|
let doc = alloc.stack([
|
||||||
alloc.reflow(r"I don't have the required permissions to read this file:"),
|
alloc.reflow(r"I don't have the required permissions to read this file:"),
|
||||||
alloc
|
alloc
|
||||||
.string(filename)
|
.string(filename_str)
|
||||||
.annotate(Annotation::ParserSuggestion)
|
.annotate(Annotation::ParserSuggestion)
|
||||||
.indent(4),
|
.indent(4),
|
||||||
alloc
|
alloc
|
||||||
|
@ -1641,7 +1643,7 @@ pub fn to_file_problem_report<'b>(
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "FILE PERMISSION DENIED".to_string(),
|
title: "FILE PERMISSION DENIED".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
@ -1652,13 +1654,16 @@ pub fn to_file_problem_report<'b>(
|
||||||
let formatted = format!("{error}");
|
let formatted = format!("{error}");
|
||||||
let doc = alloc.stack([
|
let doc = alloc.stack([
|
||||||
alloc.reflow(r"I tried to read this file:"),
|
alloc.reflow(r"I tried to read this file:"),
|
||||||
alloc.string(filename).annotate(Annotation::Error).indent(4),
|
alloc
|
||||||
|
.string(filename_str)
|
||||||
|
.annotate(Annotation::Error)
|
||||||
|
.indent(4),
|
||||||
alloc.reflow(r"But ran into:"),
|
alloc.reflow(r"But ran into:"),
|
||||||
alloc.text(formatted).annotate(Annotation::Error).indent(4),
|
alloc.text(formatted).annotate(Annotation::Error).indent(4),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
filename: "UNKNOWN.roc".into(),
|
filename,
|
||||||
doc,
|
doc,
|
||||||
title: "FILE PROBLEM".to_string(),
|
title: "FILE PROBLEM".to_string(),
|
||||||
severity: Severity::Fatal,
|
severity: Severity::Fatal,
|
||||||
|
|
22
flake.nix
22
flake.nix
|
@ -27,11 +27,16 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, rust-overlay, flake-utils, nixgl, ... }@inputs:
|
outputs = { self, nixpkgs, rust-overlay, flake-utils, nixgl, ... }@inputs:
|
||||||
let supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" ];
|
let
|
||||||
in flake-utils.lib.eachSystem supportedSystems (system:
|
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" ];
|
||||||
|
|
||||||
|
templates = import ./nix/templates { };
|
||||||
|
in
|
||||||
|
{ inherit templates; } //
|
||||||
|
flake-utils.lib.eachSystem supportedSystems (system:
|
||||||
let
|
let
|
||||||
overlays = [ (import rust-overlay) ]
|
overlays = [ (import rust-overlay) ]
|
||||||
++ (if system == "x86_64-linux" then [ nixgl.overlay ] else [ ]);
|
++ (if system == "x86_64-linux" then [ nixgl.overlay ] else [ ]);
|
||||||
pkgs = import nixpkgs { inherit system overlays; };
|
pkgs = import nixpkgs { inherit system overlays; };
|
||||||
|
|
||||||
rocBuild = import ./nix { inherit pkgs; };
|
rocBuild = import ./nix { inherit pkgs; };
|
||||||
|
@ -105,7 +110,7 @@
|
||||||
|
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
buildInputs = sharedInputs ++ sharedDevInputs ++ darwinInputs ++ darwinDevInputs ++ linuxDevInputs
|
buildInputs = sharedInputs ++ sharedDevInputs ++ darwinInputs ++ darwinDevInputs ++ linuxDevInputs
|
||||||
++ (if system == "x86_64-linux" then
|
++ (if system == "x86_64-linux" then
|
||||||
[ pkgs.nixgl.nixVulkanIntel ]
|
[ pkgs.nixgl.nixVulkanIntel ]
|
||||||
else
|
else
|
||||||
[ ]);
|
[ ]);
|
||||||
|
@ -121,7 +126,7 @@
|
||||||
LD_LIBRARY_PATH = with pkgs;
|
LD_LIBRARY_PATH = with pkgs;
|
||||||
lib.makeLibraryPath
|
lib.makeLibraryPath
|
||||||
([ pkg-config stdenv.cc.cc.lib libffi ncurses zlib ]
|
([ pkg-config stdenv.cc.cc.lib libffi ncurses zlib ]
|
||||||
++ linuxDevInputs);
|
++ linuxDevInputs);
|
||||||
NIXPKGS_ALLOW_UNFREE =
|
NIXPKGS_ALLOW_UNFREE =
|
||||||
1; # to run the GUI examples with NVIDIA's closed source drivers
|
1; # to run the GUI examples with NVIDIA's closed source drivers
|
||||||
|
|
||||||
|
@ -143,5 +148,12 @@
|
||||||
cli = rocBuild.roc-cli;
|
cli = rocBuild.roc-cli;
|
||||||
lang-server = rocBuild.roc-lang-server;
|
lang-server = rocBuild.roc-lang-server;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
apps = {
|
||||||
|
default = {
|
||||||
|
type = "app";
|
||||||
|
program = "${rocBuild.roc-cli}/bin/roc";
|
||||||
|
};
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,12 @@ play around with as long as you have a tolerance for missing features and compil
|
||||||
|
|
||||||
The [tutorial](https://roc-lang.org/tutorial) is the best place to learn about how to use the language - it assumes no prior knowledge of Roc or similar languages. (If you already know [Elm](https://elm-lang.org/), then [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) may be of interest.)
|
The [tutorial](https://roc-lang.org/tutorial) is the best place to learn about how to use the language - it assumes no prior knowledge of Roc or similar languages. (If you already know [Elm](https://elm-lang.org/), then [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) may be of interest.)
|
||||||
|
|
||||||
If you have a specific question, the [FAQ](../FAQ.md) might have an answer, although [Roc Zulip chat](https://roc.zulipchat.com) is overall the best place to ask questions and get help! It's also where we discuss [ideas](https://roc.zulipchat.com/#narrow/stream/304641-ideas) for the language. If you want to get involved in contributing to the language, Zulip is also a great place to ask about good first projects.
|
If you have a specific question, the [FAQ](../www/content/faq.md) might have an answer, although [Roc Zulip chat](https://roc.zulipchat.com) is overall the best place to ask questions and get help! It's also where we discuss [ideas](https://roc.zulipchat.com/#narrow/stream/304641-ideas) for the language. If you want to get involved in contributing to the language, Zulip is also a great place to ask about good first projects.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
- [🐧 Linux x86_64](linux_x86_64.md)
|
- [🐧 Linux x86_64](linux_x86_64.md)
|
||||||
|
- [❄️ Nix Linux/MacOS](nix.md)
|
||||||
- [🍏 MacOS Apple Silicon](macos_apple_silicon.md)
|
- [🍏 MacOS Apple Silicon](macos_apple_silicon.md)
|
||||||
- [🍏 MacOS x86_64](macos_x86_64.md)
|
- [🍏 MacOS x86_64](macos_x86_64.md)
|
||||||
- [🟦 Windows](windows.md)
|
- [🟦 Windows](windows.md)
|
||||||
|
|
48
getting_started/nix.md
Normal file
48
getting_started/nix.md
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
## Try out
|
||||||
|
|
||||||
|
To quickly try out roc without installing, use `nix run`:
|
||||||
|
```shell
|
||||||
|
nix run roc-lang/roc -- <roc args>
|
||||||
|
# examples:
|
||||||
|
# - nix run roc-lang/roc -- repl
|
||||||
|
# - nix run roc-lang/roc -- dev main.roc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use with Flakes
|
||||||
|
|
||||||
|
|
||||||
|
### Start your project with our template
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# use the template in the current directory
|
||||||
|
nix flake init --template github:roc-lang/roc#simple --refresh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add roc to existing flake
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
roc.url = "github:roc-lang/roc";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {nixpkgs, roc, flake-utils, ...}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
rocPkgs = roc.packages.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells = {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs;
|
||||||
|
[
|
||||||
|
rocPkgs.cli
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
|
@ -3,6 +3,8 @@ let
|
||||||
inherit (compile-deps) zigPkg llvmPkgs llvmVersion llvmMajorMinorStr glibcPath libGccSPath;
|
inherit (compile-deps) zigPkg llvmPkgs llvmVersion llvmMajorMinorStr glibcPath libGccSPath;
|
||||||
|
|
||||||
subPackagePath = if subPackage != null then "crates/${subPackage}" else null;
|
subPackagePath = if subPackage != null then "crates/${subPackage}" else null;
|
||||||
|
|
||||||
|
mainBin = if subPackage == "lang_srv" then "roc_ls" else "roc";
|
||||||
in
|
in
|
||||||
rustPlatform.buildRustPackage {
|
rustPlatform.buildRustPackage {
|
||||||
pname = "roc" + lib.optionalString (subPackage != null) "_${subPackage}";
|
pname = "roc" + lib.optionalString (subPackage != null) "_${subPackage}";
|
||||||
|
@ -84,4 +86,11 @@ rustPlatform.buildRustPackage {
|
||||||
${wrapRoc}
|
${wrapRoc}
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# https://ryantm.github.io/nixpkgs/stdenv/meta/
|
||||||
|
meta = {
|
||||||
|
homepage = "https://www.roc-lang.org/";
|
||||||
|
license = lib.licenses.upl;
|
||||||
|
mainProgram = mainBin;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
7
nix/templates/default.nix
Normal file
7
nix/templates/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{ ... }: rec {
|
||||||
|
default = simple;
|
||||||
|
simple = {
|
||||||
|
description = "Basic flake with roc cli + lsp";
|
||||||
|
path = ./simple;
|
||||||
|
};
|
||||||
|
}
|
38
nix/templates/simple/flake.nix
Normal file
38
nix/templates/simple/flake.nix
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
description = "Roc flake template";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
roc.url = "github:roc-lang/roc";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils, roc, ... }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
|
||||||
|
# see "packages =" in https://github.com/roc-lang/roc/blob/main/flake.nix
|
||||||
|
rocPkgs = roc.packages.${system};
|
||||||
|
|
||||||
|
rocFull = rocPkgs.full;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
formatter = pkgs.nixpkgs-fmt;
|
||||||
|
|
||||||
|
devShells = {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs;
|
||||||
|
[
|
||||||
|
rocFull # includes CLI
|
||||||
|
];
|
||||||
|
|
||||||
|
# For vscode plugin https://github.com/ivan-demchenko/roc-vscode-unofficial
|
||||||
|
shellHook = ''
|
||||||
|
export ROC_LSP_PATH=${rocFull}/bin/roc_ls
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
- [builtins](/builtins) - docs for modules built into the language—`Str`, `Num`, etc.
|
- [builtins](/builtins) - docs for modules built into the language—`Str`, `Num`, etc.
|
||||||
|
@ -10,7 +9,7 @@ In the future, a language reference will be on this page too.
|
||||||
|
|
||||||
## [Guides](#guides) {#guides}
|
## [Guides](#guides) {#guides}
|
||||||
|
|
||||||
- [Frequently Asked Questions](https://github.com/roc-lang/roc/blob/main/FAQ.md)
|
- [Frequently Asked Questions](https://www.roc-lang.org/faq.html)
|
||||||
- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md)
|
- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md)
|
||||||
- [Tutorial](/tutorial)
|
- [Tutorial](/tutorial)
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
Click the ☰ button in the top left to see and search the table of contents.
|
|
||||||
|
|
||||||
# Frequently Asked Questions
|
# Frequently Asked Questions
|
||||||
|
|
||||||
## Where did the name Roc come from?
|
## Where did the name Roc come from?
|
||||||
|
|
||||||
<img width="128" alt="The Roc logo, an origami bird" src="https://user-images.githubusercontent.com/1094080/92188927-e61ebd00-ee2b-11ea-97ef-2fc88e0094b0.png">
|
|
||||||
|
|
||||||
The Roc programming language is named after [a mythical bird](<https://en.wikipedia.org/wiki/Roc_(mythology)>).
|
The Roc programming language is named after [a mythical bird](<https://en.wikipedia.org/wiki/Roc_(mythology)>).
|
||||||
|
|
||||||
That’s why the logo is a bird. It’s specifically an [_origami_ bird](https://youtu.be/9gni1t1k1uY) as an homage
|
<svg viewBox="0 0 52 53" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Make this icon look nicer in dark mode. (Only Firefox supports this; others ignore it.) -->
|
||||||
|
<style>@media (prefers-color-scheme: dark){polygon{fill:#9c7bea}}</style>
|
||||||
|
<polygon fill="#7d59dd" points="0,0 23.8834,3.21052 37.2438,19.0101 45.9665,16.6324 50.5,22 45,22 44.0315,26.3689 26.4673,39.3424 27.4527,45.2132 17.655,53 23.6751,22.7086"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
That's why the logo is a bird. It’s specifically an [_origami_ bird](https://youtu.be/9gni1t1k1uY) as an homage
|
||||||
to [Elm](https://elm-lang.org/)’s tangram logo.
|
to [Elm](https://elm-lang.org/)’s tangram logo.
|
||||||
|
|
||||||
Roc is a direct descendant of Elm. The languages are similar, but not the same.
|
Roc is a direct descendant of Elm. The languages are similar, but not the same.
|
||||||
|
@ -55,8 +57,10 @@ Both of these would make revising code riskier across the entire language, which
|
||||||
Another option would be to define that function equality always returns `false`. So both of these would evaluate
|
Another option would be to define that function equality always returns `false`. So both of these would evaluate
|
||||||
to `false`:
|
to `false`:
|
||||||
|
|
||||||
- `(\x -> x + 1) == (\x -> 1 + x)`
|
```roc
|
||||||
- `(\x -> x + 1) == (\x -> x + 1)`
|
(\x -> x + 1) == (\x -> 1 + x) #false
|
||||||
|
(\x -> x + 1) == (\x -> x + 1) #false
|
||||||
|
```
|
||||||
|
|
||||||
This makes function equality effectively useless, while still technically allowing it. It has some other downsides:
|
This makes function equality effectively useless, while still technically allowing it. It has some other downsides:
|
||||||
|
|
||||||
|
@ -252,11 +256,11 @@ the downsides.
|
||||||
|
|
||||||
In Roc, both of these expressions evaluate to `"Hello, World!"`
|
In Roc, both of these expressions evaluate to `"Hello, World!"`
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
Str.concat "Hello, " "World!"
|
Str.concat "Hello, " "World!"
|
||||||
```
|
```
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
"Hello, "
|
"Hello, "
|
||||||
|> Str.concat "World!"
|
|> Str.concat "World!"
|
||||||
```
|
```
|
||||||
|
@ -273,12 +277,12 @@ In Roc, both expressions evaluate to the same thing because Roc's `|>` operator
|
||||||
|
|
||||||
This comes up in other situations besides string concatenation. For example, consider subtraction and division:
|
This comes up in other situations besides string concatenation. For example, consider subtraction and division:
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
someNumber
|
someNumber
|
||||||
|> Num.div 2
|
|> Num.div 2
|
||||||
```
|
```
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
someNumber
|
someNumber
|
||||||
|> Num.sub 1
|
|> Num.sub 1
|
||||||
```
|
```
|
||||||
|
@ -292,7 +296,7 @@ experienced users.
|
||||||
|
|
||||||
The way `|>` works in Roc has a second benefit when it comes to higher-order functions. Consider these two examples:
|
The way `|>` works in Roc has a second benefit when it comes to higher-order functions. Consider these two examples:
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
answer = List.map numbers \num ->
|
answer = List.map numbers \num ->
|
||||||
someFunction
|
someFunction
|
||||||
"some argument"
|
"some argument"
|
||||||
|
@ -300,7 +304,7 @@ answer = List.map numbers \num ->
|
||||||
anotherArg
|
anotherArg
|
||||||
```
|
```
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
numbers
|
numbers
|
||||||
|> List.map Num.abs
|
|> List.map Num.abs
|
||||||
```
|
```
|
||||||
|
@ -311,7 +315,7 @@ In a curried language, these two examples couldn't both be valid. In order for `
|
||||||
|
|
||||||
This means the first example would have to change from this...
|
This means the first example would have to change from this...
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
answer = List.map numbers \num ->
|
answer = List.map numbers \num ->
|
||||||
someFunction
|
someFunction
|
||||||
"some argument"
|
"some argument"
|
||||||
|
@ -321,7 +325,7 @@ answer = List.map numbers \num ->
|
||||||
|
|
||||||
...to this:
|
...to this:
|
||||||
|
|
||||||
```elixir
|
```roc
|
||||||
answer =
|
answer =
|
||||||
List.map
|
List.map
|
||||||
(\num ->
|
(\num ->
|
||||||
|
@ -370,7 +374,7 @@ And however easy Roc would be to learn if it had currying, the language is certa
|
||||||
a new function by composing together two existing functions without naming intermediate arguments.
|
a new function by composing together two existing functions without naming intermediate arguments.
|
||||||
Here's an example:
|
Here's an example:
|
||||||
|
|
||||||
```elm
|
```roc
|
||||||
reverseSort : List elem -> List elem
|
reverseSort : List elem -> List elem
|
||||||
reverseSort = compose List.reverse List.sort
|
reverseSort = compose List.reverse List.sort
|
||||||
|
|
||||||
|
@ -380,7 +384,7 @@ compose = \f, g, x -> f (g x)
|
||||||
|
|
||||||
Here's a way to write it without pointfree function composition:
|
Here's a way to write it without pointfree function composition:
|
||||||
|
|
||||||
```elm
|
```roc
|
||||||
reverseSort : List elem -> List elem
|
reverseSort : List elem -> List elem
|
||||||
reverseSort = \list -> List.reverse (List.sort list)
|
reverseSort = \list -> List.reverse (List.sort list)
|
||||||
```
|
```
|
||||||
|
@ -443,7 +447,3 @@ There were a few reasons for this rewrite.
|
||||||
4. Zig has more tools for working in a memory-unsafe environment, such as reporting memory leaks in tests. These have been helpful in finding bugs that are out of scope for safe Rust.
|
4. Zig has more tools for working in a memory-unsafe environment, such as reporting memory leaks in tests. These have been helpful in finding bugs that are out of scope for safe Rust.
|
||||||
|
|
||||||
The split of Rust for the compiler and Zig for the standard library has worked well so far, and there are no plans to change it.
|
The split of Rust for the compiler and Zig for the standard library has worked well so far, and there are no plans to change it.
|
||||||
|
|
||||||
## Why is the website so basic?
|
|
||||||
|
|
||||||
We have a very basic website on purpose, it helps set expectations that roc is a work in progress and not ready yet for a first release.
|
|
|
@ -5,7 +5,7 @@ Roc is a very young language with many incomplete features and known bugs. It do
|
||||||
There are currently a few known OS-specific issues:
|
There are currently a few known OS-specific issues:
|
||||||
* **macOS:** There are no known compatibility issues, but the compiler doesn't run as fast as it does on Linux or Windows, because we don't (yet) do our own linking like we do on those targets. (Linking works similarly on Linux and Windows, but the way macOS does it is both different and significantly more complicated.)
|
* **macOS:** There are no known compatibility issues, but the compiler doesn't run as fast as it does on Linux or Windows, because we don't (yet) do our own linking like we do on those targets. (Linking works similarly on Linux and Windows, but the way macOS does it is both different and significantly more complicated.)
|
||||||
* **Windows:** There are some known Windows-specific compiler bugs, and probably some other unknown ones because more people have tried out Roc on Mac and Linux than on Windows.
|
* **Windows:** There are some known Windows-specific compiler bugs, and probably some other unknown ones because more people have tried out Roc on Mac and Linux than on Windows.
|
||||||
* **Linux:** The nightlies are built with glibc, so they aren't usable on distros that don't use (dynamically linked) glibc, like Alpine or NixOS. In the future we plan to build Linux releases with [musl libc](https://wiki.musl-libc.org/) to address this, but this requires [building LLVM from source with musl](https://wiki.musl-libc.org/building-llvm.html).
|
* **Linux:** The nightlies are built with glibc, so they aren't usable on distros that don't use glibc, like Alpine. In the future we plan to build Linux releases with [musl libc](https://wiki.musl-libc.org/) to address this, but this requires [building LLVM from source with musl](https://wiki.musl-libc.org/building-llvm.html).
|
||||||
* **Other operating systems:** Roc has not been built on any other operating systems. [Building from source](https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md) on another OS might work, but you might very well be the first person ever to try it!
|
* **Other operating systems:** Roc has not been built on any other operating systems. [Building from source](https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md) on another OS might work, but you might very well be the first person ever to try it!
|
||||||
|
|
||||||
### [Getting Started](#getting-started) {#getting-started}
|
### [Getting Started](#getting-started) {#getting-started}
|
||||||
|
@ -14,6 +14,7 @@ Here are some Getting Started guides for different operating systems:
|
||||||
<!-- TODO detect current OS with browser and only show link for that, provide other button for others -->
|
<!-- TODO detect current OS with browser and only show link for that, provide other button for others -->
|
||||||
|
|
||||||
- [Linux x86-64](https://github.com/roc-lang/roc/blob/main/getting_started/linux_x86_64.md)
|
- [Linux x86-64](https://github.com/roc-lang/roc/blob/main/getting_started/linux_x86_64.md)
|
||||||
|
- [Nix Linux/MacOS](https://github.com/roc-lang/roc/blob/main/getting_started/nix.md)
|
||||||
- [MacOS Apple Silicon](https://github.com/roc-lang/roc/blob/main/getting_started/macos_apple_silicon.md)
|
- [MacOS Apple Silicon](https://github.com/roc-lang/roc/blob/main/getting_started/macos_apple_silicon.md)
|
||||||
- [MacOS x86-64](https://github.com/roc-lang/roc/blob/main/getting_started/macos_x86_64.md)
|
- [MacOS x86-64](https://github.com/roc-lang/roc/blob/main/getting_started/macos_x86_64.md)
|
||||||
- [Windows](https://github.com/roc-lang/roc/blob/main/getting_started/windows.md)
|
- [Windows](https://github.com/roc-lang/roc/blob/main/getting_started/windows.md)
|
||||||
|
|
|
@ -2076,8 +2076,8 @@ Here are various Roc expressions involving operators, and what they desugar to.
|
||||||
| `a && b` | `Bool.and a b` |
|
| `a && b` | `Bool.and a b` |
|
||||||
| <code>a \|\| b</code> | `Bool.or a b` |
|
| <code>a \|\| b</code> | `Bool.or a b` |
|
||||||
| `!a` | `Bool.not a` |
|
| `!a` | `Bool.not a` |
|
||||||
| <code>a \|> b</code> | `b a` |
|
| <code>a \|> f</code> | `f a` |
|
||||||
| <code>a b c \|> f x y</code> | `f (a b c) x y` |
|
| <code>f a b \|> g x y</code> | `g (f a b) x y` |
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue