mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Merge branch 'roc-lang:main' into builtin-dict-docs
This commit is contained in:
commit
deadd19de0
8 changed files with 40 additions and 43 deletions
4
.github/workflows/macos_x86_64.yml
vendored
4
.github/workflows/macos_x86_64.yml
vendored
|
@ -25,9 +25,5 @@ jobs:
|
|||
# swift tests are skipped because of "Could not find or use auto-linked library 'swiftCompatibilityConcurrency'" on macos-11 x86_64 CI machine
|
||||
# this issue may be caused by using older versions of XCode
|
||||
|
||||
# TODO build basic-cli for macos 11
|
||||
#- name: test examples/helloWorld.roc separately because it is ignored by default
|
||||
# run: cargo test --locked --release -p roc_cli cli_run::hello_world -- --ignored && sccache --show-stats
|
||||
|
||||
- name: test launching the editor
|
||||
run: cargo test --release --locked editor_launch_test::launch -- --ignored # `--ignored` to run this test that is ignored for "normal" runs
|
||||
|
|
6
.github/workflows/ubuntu_x86_64.yml
vendored
6
.github/workflows/ubuntu_x86_64.yml
vendored
|
@ -36,12 +36,6 @@ jobs:
|
|||
- name: regular rust tests
|
||||
run: cargo test --locked --release && sccache --show-stats
|
||||
|
||||
- name: test hellow_world separately because it is ignored by default, the use of url platforms causes issues within nix
|
||||
run: cargo test --locked --release -p roc_cli cli_run::hello_world -- --ignored && sccache --show-stats
|
||||
|
||||
- name: test parse_letter_counts separately because it is ignored by default, the use of url platforms causes issues within nix
|
||||
run: cargo test --locked --release -p roc_cli cli_run::parse_letter_counts -- --ignored && sccache --show-stats
|
||||
|
||||
- name: check that the platform`s produced dylib is loadable
|
||||
run: cd examples/platform-switching/rust-platform && LD_LIBRARY_PATH=. cargo test --release --locked
|
||||
|
||||
|
|
|
@ -474,7 +474,7 @@ mod cli_run {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Prebuilt platforms cause problems with nix and NixOS. This is run explicitly tested on CI (.github/workflows/ubuntu_x86_64.yml)"]
|
||||
#[cfg_attr(windows, ignore)]
|
||||
fn hello_world() {
|
||||
test_roc_app_slim(
|
||||
"examples",
|
||||
|
@ -805,10 +805,10 @@ mod cli_run {
|
|||
"False.roc",
|
||||
"false",
|
||||
&[],
|
||||
&[Arg::ExamplePath("examples/hello.false")],
|
||||
&[Arg::ExamplePath("examples/sqrt.false")],
|
||||
&[],
|
||||
&("Hello, World!".to_string() + LINE_ENDING),
|
||||
UseValgrind::No,
|
||||
"1414",
|
||||
UseValgrind::Yes,
|
||||
TestCliCommands::Many,
|
||||
)
|
||||
}
|
||||
|
@ -864,6 +864,7 @@ mod cli_run {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[serial(parser_package)]
|
||||
#[serial(zig_platform)]
|
||||
#[cfg_attr(windows, ignore)]
|
||||
fn parse_movies_csv() {
|
||||
|
@ -877,7 +878,8 @@ mod cli_run {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Prebuilt platforms cause problems with nix and NixOS. This is run explicitly tested on CI (.github/workflows/ubuntu_x86_64.yml)"]
|
||||
#[serial(parser_package)]
|
||||
#[cfg_attr(windows, ignore)]
|
||||
fn parse_letter_counts() {
|
||||
test_roc_app_slim(
|
||||
"examples/parser/examples",
|
||||
|
|
|
@ -125,7 +125,7 @@ pub const RocList = extern struct {
|
|||
}
|
||||
|
||||
fn refcountMachine(self: RocList) usize {
|
||||
if (self.getCapacity() == 0) {
|
||||
if (self.getCapacity() == 0 and !self.isSeamlessSlice()) {
|
||||
// the zero-capacity is Clone, copying it will not leak memory
|
||||
return utils.REFCOUNT_ONE;
|
||||
}
|
||||
|
@ -147,12 +147,15 @@ pub const RocList = extern struct {
|
|||
}
|
||||
|
||||
pub fn makeUnique(self: RocList, alignment: u32, element_width: usize) RocList {
|
||||
if (self.isEmpty()) {
|
||||
if (self.isUnique()) {
|
||||
return self;
|
||||
}
|
||||
|
||||
if (self.isUnique()) {
|
||||
return self;
|
||||
if (self.isEmpty()) {
|
||||
// Empty is not necessarily unique on it's own.
|
||||
// The list could have capacity and be shared.
|
||||
self.decref(alignment);
|
||||
return RocList.empty();
|
||||
}
|
||||
|
||||
// unfortunately, we have to clone
|
||||
|
@ -511,6 +514,7 @@ pub fn listReleaseExcessCapacity(
|
|||
|
||||
@memcpy(dest_ptr, source_ptr, old_length * element_width);
|
||||
}
|
||||
list.decref(alignment);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -602,19 +606,19 @@ pub fn listSublist(
|
|||
) callconv(.C) RocList {
|
||||
const size = list.len();
|
||||
if (len == 0 or start >= size) {
|
||||
if (list.isUnique()) {
|
||||
// Decrement the reference counts of all elements.
|
||||
if (list.bytes) |source_ptr| {
|
||||
var i: usize = 0;
|
||||
while (i < size) : (i += 1) {
|
||||
const element = source_ptr + i * element_width;
|
||||
dec(element);
|
||||
}
|
||||
var output = list;
|
||||
output.length = 0;
|
||||
return output;
|
||||
// Decrement the reference counts of all elements.
|
||||
if (list.bytes) |source_ptr| {
|
||||
var i: usize = 0;
|
||||
while (i < size) : (i += 1) {
|
||||
const element = source_ptr + i * element_width;
|
||||
dec(element);
|
||||
}
|
||||
}
|
||||
if (list.isUnique()) {
|
||||
var output = list;
|
||||
output.length = 0;
|
||||
return output;
|
||||
}
|
||||
list.decref(alignment);
|
||||
return RocList.empty();
|
||||
}
|
||||
|
@ -831,6 +835,8 @@ pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_widt
|
|||
// NOTE we always use list_a! because it is owned, we must consume it, and it may have unused capacity
|
||||
if (list_b.isEmpty()) {
|
||||
if (list_a.getCapacity() == 0) {
|
||||
// a could be a seamless slice, so we still need to decref.
|
||||
list_a.decref(alignment);
|
||||
return list_b;
|
||||
} else {
|
||||
// we must consume this list. Even though it has no elements, it could still have capacity
|
||||
|
|
|
@ -1989,6 +1989,7 @@ pub fn isValidUnicode(buf: []const u8) bool {
|
|||
|
||||
while (buf[i] >= 0b1000_0000) {
|
||||
// This forces prefetching, otherwise the loop can run at about half speed.
|
||||
if (i + 4 >= buf.len) break;
|
||||
var small_buf: [4]u8 = undefined;
|
||||
@memcpy(&small_buf, @ptrCast([*]const u8, buf) + i, 4);
|
||||
// TODO: Should we always inline these function calls below?
|
||||
|
@ -1997,7 +1998,6 @@ pub fn isValidUnicode(buf: []const u8) bool {
|
|||
return false;
|
||||
}
|
||||
i += cp_len;
|
||||
if (i + 4 >= buf.len) break;
|
||||
} else |_| {
|
||||
return false;
|
||||
}
|
||||
|
@ -2927,6 +2927,7 @@ pub fn strReleaseExcessCapacity(
|
|||
const dest_ptr = output.asU8ptrMut();
|
||||
|
||||
@memcpy(dest_ptr, source_ptr, old_length);
|
||||
string.decref();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
app "helloWorld"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
app "example"
|
||||
packages {
|
||||
cli: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br",
|
||||
cli: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br",
|
||||
parser: "../package/main.roc",
|
||||
}
|
||||
imports [
|
||||
|
|
|
@ -120,15 +120,13 @@ We'll get into more depth about modules later, but for now you can think of a mo
|
|||
|
||||
## [Building an Application](#building-an-application) {#building-an-application}
|
||||
|
||||
> **For NixOS:** URL imports don't work yet. Instead you'll have to clone [roc-lang/basic-cli](https://github.com/roc-lang/basic-cli) locally and use it like [this](https://github.com/roc-lang/roc/issues/4655#issuecomment-1336215883).
|
||||
|
||||
Let's move out of the REPL and create our first Roc application!
|
||||
|
||||
Make a file named `main.roc` and put this in it:
|
||||
|
||||
```roc
|
||||
app "hello"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
||||
|
@ -520,7 +518,7 @@ Besides being more concise, there are other advantages to using `when` here.
|
|||
1. We don't have to specify an `else` branch, so the code can be more self-documenting about exactly what all the options are.
|
||||
2. We get more compiler help. If we try deleting any of these branches, we'll get a compile-time error saying that we forgot to cover a case that could come up. For example, if we delete the `Green ->` branch, the compiler will say that we didn't handle the possibility that `stoplightColor` could be `Green`. It knows this because `Green` is one of the possibilities in our `stoplightColor = if ...` definition.
|
||||
|
||||
We can still have the equivalent of an `else` branch in our `when` if we like. Instead of writing `else`, we write `\_ ->` like so:
|
||||
We can still have the equivalent of an `else` branch in our `when` if we like. Instead of writing `else`, we write `_ ->` like so:
|
||||
|
||||
```roc
|
||||
stoplightStr =
|
||||
|
@ -628,7 +626,7 @@ This can be both more concise and more efficient (at runtime) than calling [`Lis
|
|||
|
||||
In many programming languages, `true` and `false` are special language keywords that refer to the two [boolean](https://en.wikipedia.org/wiki/Boolean_data_type) values. In Roc, booleans do not get special keywords; instead, they are exposed as the ordinary values `Bool.true` and `Bool.false`.
|
||||
|
||||
This design is partly to keep the number of special keywords in the language smaller, but mainly to suggest how booleans are intended be used in Roc: for [_boolean logic_](https://en.wikipedia.org/wiki/Boolean_algebra) (`&&`, `||`, and so on) as opposed to for data modeling. Tags are the preferred choice for data modeling, and having tag values be more concise than boolean values helps make this preference clear.
|
||||
This design is partly to keep the number of special keywords in the language smaller, but mainly to suggest how booleans are intended to be used in Roc: for [_boolean logic_](https://en.wikipedia.org/wiki/Boolean_algebra) (`&&`, `||`, and so on) as opposed to for data modeling. Tags are the preferred choice for data modeling, and having tag values be more concise than boolean values helps make this preference clear.
|
||||
|
||||
As an example of why tags are encouraged for data modeling, in many languages it would be common to write a record like `{ name: "Richard", isAdmin: Bool.true }`, but in Roc it would be preferable to write something like `{ name: "Richard", role: Admin }`. At first, the `role` field might only ever be set to `Admin` or `Normal`, but because the data has been modeled using tags instead of booleans, it's much easier to add other alternatives in the future, like `Guest` or `Moderator` - some of which might also want payloads.
|
||||
|
||||
|
@ -1370,7 +1368,7 @@ Let's take a closer look at the part of `main.roc` above the `main` def:
|
|||
|
||||
```roc
|
||||
app "hello"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout]
|
||||
provides main to pf
|
||||
```
|
||||
|
@ -1382,7 +1380,7 @@ The line `app "hello"` states that this module defines a Roc application, and th
|
|||
The remaining lines all involve the [platform](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform) this application is built on:
|
||||
|
||||
```roc
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
```
|
||||
|
@ -1468,7 +1466,7 @@ Let's start with a basic "Hello World" program.
|
|||
|
||||
```roc
|
||||
app "cli-tutorial"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
||||
|
@ -1498,7 +1496,7 @@ Let's change `main` to read a line from `stdin`, and then print it back out agai
|
|||
|
||||
```roc
|
||||
app "cli-tutorial"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout, pf.Stdin, pf.Task]
|
||||
provides [main] to pf
|
||||
|
||||
|
@ -1539,7 +1537,7 @@ This works, but we can make it a little nicer to read. Let's change it to the fo
|
|||
|
||||
```roc
|
||||
app "cli-tutorial"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
|
||||
imports [pf.Stdout, pf.Stdin, pf.Task.{ await }]
|
||||
provides [main] to pf
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue