Merge branch 'roc-lang:main' into builtin-dict-docs

This commit is contained in:
Seth Workman 2023-03-17 11:02:57 -05:00 committed by GitHub
commit deadd19de0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 43 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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