Merge branch 'main' into list-walk-with-index-until

This commit is contained in:
Bryce Miller 2023-12-18 17:25:06 +01:00 committed by GitHub
commit a710dd18ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 341 additions and 106 deletions

View file

@ -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

View file

@ -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

View file

@ -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 }}

View file

@ -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

View file

@ -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

View file

@ -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!

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
} }
} }

View file

@ -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());

View file

@ -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,

View file

@ -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
"#
));
} }
} }

View file

@ -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;
} }

View file

@ -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,

View file

@ -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";
};
};
}); });
} }

View file

@ -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
View 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
];
};
};
}
);
}
```

View file

@ -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;
};
} }

View file

@ -0,0 +1,7 @@
{ ... }: rec {
default = simple;
simple = {
description = "Basic flake with roc cli + lsp";
path = ./simple;
};
}

View 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
'';
};
};
});
}

View file

@ -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)

View file

@ -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)>).
Thats why the logo is a bird. Its 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. Its 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.

View file

@ -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)

View file

@ -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>