Merge branch 'trunk' into regression_testing

This commit is contained in:
Anton-4 2021-06-08 17:08:04 +02:00 committed by GitHub
commit 799cc39397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 141 additions and 114 deletions

4
.earthignore Normal file
View File

@ -0,0 +1,4 @@
AUTHORS
nix
.envrc
.gitignore

6
Cargo.lock generated
View File

@ -1612,13 +1612,13 @@ dependencies = [
name = "inkwell" name = "inkwell"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"inkwell 0.1.0 (git+https://github.com/rtfeldman/inkwell?tag=llvm10-0.release5)", "inkwell 0.1.0 (git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release2)",
] ]
[[package]] [[package]]
name = "inkwell" name = "inkwell"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/rtfeldman/inkwell?tag=llvm10-0.release5#f0a32d3a0595bda3777a7b7e08a2e46c97eba6f4" source = "git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release2#2f9bfb728cb5713b39fe527838969dcc8e184c4d"
dependencies = [ dependencies = [
"either", "either",
"inkwell_internals", "inkwell_internals",
@ -1632,7 +1632,7 @@ dependencies = [
[[package]] [[package]]
name = "inkwell_internals" name = "inkwell_internals"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/rtfeldman/inkwell?tag=llvm10-0.release5#f0a32d3a0595bda3777a7b7e08a2e46c97eba6f4" source = "git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release2#2f9bfb728cb5713b39fe527838969dcc8e184c4d"
dependencies = [ dependencies = [
"proc-macro2 1.0.27", "proc-macro2 1.0.27",
"quote 1.0.9", "quote 1.0.9",

View File

@ -99,17 +99,35 @@ check-rustfmt:
RUN cargo fmt --version RUN cargo fmt --version
RUN cargo fmt --all -- --check RUN cargo fmt --all -- --check
check-typos:
RUN cargo install typos-cli --version 1.0.4 # use latest version on resolution of issue crate-ci/typos#277
COPY --dir .github ci cli compiler docs editor examples packages roc_std www *.md LEGAL_DETAILS shell.nix ./
RUN typos
test-rust: test-rust:
FROM +copy-dirs-and-cache FROM +copy-dirs-and-cache
ENV RUST_BACKTRACE=1 ENV RUST_BACKTRACE=1
RUN --mount=type=cache,target=$SCCACHE_DIR \ RUN --mount=type=cache,target=$SCCACHE_DIR \
cargo test --release && sccache --show-stats cargo test --release && sccache --show-stats
verify-no-git-changes:
FROM +test-rust
# If running tests caused anything to be changed or added (without being
# included in a .gitignore somewhere), fail the build!
#
# How it works: the `git ls-files` command lists all the modified or
# uncommitted files in the working tree, the `| grep -E .` command returns a
# zero exit code if it listed any files and nonzero otherwise (which is the
# opposite of what we want), and the `!` at the start inverts the exit code.
RUN ! git ls-files --deleted --modified --others --exclude-standard | grep -E .
test-all: test-all:
BUILD +test-zig BUILD +test-zig
BUILD +check-rustfmt BUILD +check-rustfmt
BUILD +check-clippy BUILD +check-clippy
BUILD +check-typos
BUILD +test-rust BUILD +test-rust
BUILD +verify-no-git-changes
bench-roc: bench-roc:
FROM +copy-dirs-and-cache FROM +copy-dirs-and-cache

View File

@ -46,7 +46,7 @@ By using systems-level programming languages like C and C++, platform authors sa
Roc is designed to make the "systems-level platform, higher-level application" experience as nice as possible. Roc is designed to make the "systems-level platform, higher-level application" experience as nice as possible.
* **Application** authors code exclusively in Roc. It's a language designed for nice ergonomics. The syntax resembles Ruby or CoffeeScript, and it has a fast compiler with full type inference. * **Application** authors code exclusively in Roc. It's a language designed for nice ergonomics. The syntax resembles Ruby or CoffeeScript, and it has a fast compiler with full type inference.
* **Platform** authors code almost exclusively in a systems-level langauge like C, C++, Rust, or [Zig](https://ziglang.org/), except for the thin Roc API they expose to application authors. Roc application code compiles to machine code, and production builds of Roc apps benefit from the same [LLVM](https://llvm.org/) optimizations that C++, Rust, and Zig do. Roc application authors do not need to know this lower-level code exists; all they have to interact with is the platform's API, which is exposed as an ordinary Roc API. * **Platform** authors code almost exclusively in a systems-level language like C, C++, Rust, or [Zig](https://ziglang.org/), except for the thin Roc API they expose to application authors. Roc application code compiles to machine code, and production builds of Roc apps benefit from the same [LLVM](https://llvm.org/) optimizations that C++, Rust, and Zig do. Roc application authors do not need to know this lower-level code exists; all they have to interact with is the platform's API, which is exposed as an ordinary Roc API.
Every Roc application is built on top of exactly one Roc platform. There is no such thing as a Roc application that runs without a platform, and there is no default platform. You must choose one! Every Roc application is built on top of exactly one Roc platform. There is no such thing as a Roc application that runs without a platform, and there is no default platform. You must choose one!

View File

@ -30,7 +30,7 @@ pub const DIRECTORY_OR_FILES: &str = "DIRECTORY_OR_FILES";
pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP"; pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP";
pub fn build_app<'a>() -> App<'a> { pub fn build_app<'a>() -> App<'a> {
App::new("roc") let app = App::new("roc")
.version(crate_version!()) .version(crate_version!())
.subcommand(App::new(CMD_BUILD) .subcommand(App::new(CMD_BUILD)
.about("Build a program") .about("Build a program")
@ -81,15 +81,6 @@ pub fn build_app<'a>() -> App<'a> {
.subcommand(App::new(CMD_REPL) .subcommand(App::new(CMD_REPL)
.about("Launch the interactive Read Eval Print Loop (REPL)") .about("Launch the interactive Read Eval Print Loop (REPL)")
) )
.subcommand(App::new(CMD_EDIT)
.about("Launch the Roc editor")
.arg(Arg::with_name(DIRECTORY_OR_FILES)
.index(1)
.multiple(true)
.required(false)
.help("(optional) The directory or files to open on launch.")
)
)
.subcommand( .subcommand(
App::new(CMD_DOCS) App::new(CMD_DOCS)
.about("Generate documentation for Roc modules") .about("Generate documentation for Roc modules")
@ -100,7 +91,21 @@ pub fn build_app<'a>() -> App<'a> {
.help("The directory or files to build documentation for") .help("The directory or files to build documentation for")
) )
);
if cfg!(feature = "edit") {
app.subcommand(
App::new(CMD_EDIT).about("Launch the Roc editor").arg(
Arg::with_name(DIRECTORY_OR_FILES)
.index(1)
.multiple(true)
.required(false)
.help("(optional) The directory or files to open on launch."),
),
) )
} else {
app
}
} }
pub fn docs(files: Vec<PathBuf>) { pub fn docs(files: Vec<PathBuf>) {

View File

@ -42,7 +42,7 @@ fn list_repeat(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
``` ```
In these builtin definitions you will need to allocate for and list the arguments. For `List.repeat`, the arguments are the `elem_var` and the `len_var`. So in both the `body` and `defn` we list these arguments in a vector, with the `Symobl::ARG_1` adn` Symvol::ARG_2` designating which argument is which. In these builtin definitions you will need to allocate for and list the arguments. For `List.repeat`, the arguments are the `elem_var` and the `len_var`. So in both the `body` and `defn` we list these arguments in a vector, with the `Symobl::ARG_1` and` Symvol::ARG_2` designating which argument is which.
Since `List.repeat` is implemented entirely as low level functions, its `body` is a `RunLowLevel`, and the `op` is `LowLevel::ListRepeat`. Lets talk about `LowLevel` in the next section. Since `List.repeat` is implemented entirely as low level functions, its `body` is a `RunLowLevel`, and the `op` is `LowLevel::ListRepeat`. Lets talk about `LowLevel` in the next section.
@ -60,7 +60,7 @@ Its one thing to actually write these functions, its _another_ thing to let the
## Specifying how we pass args to the function ## Specifying how we pass args to the function
### builtins/mono/src/borrow.rs ### builtins/mono/src/borrow.rs
After we have all of this, we need to specify if the arguements we're passing are owned, borrowed or irrelvant. Towards the bottom of this file, add a new case for you builtin and specify each arg. Be sure to read the comment, as it explains this in more detail. After we have all of this, we need to specify if the arguments we're passing are owned, borrowed or irrelvant. Towards the bottom of this file, add a new case for you builtin and specify each arg. Be sure to read the comment, as it explains this in more detail.
## Specifying the uniqueness of a function ## Specifying the uniqueness of a function
### builtins/src/unique.rs ### builtins/src/unique.rs

View File

@ -3,10 +3,10 @@
## Adding a bitcode builtin ## Adding a bitcode builtin
To add a builtin: To add a builtin:
1. Add the function to the relevent module. For `Num` builtin use it in `src/num.zig`, for `Str` builtins use `src/str.zig`, and so on. **For anything you add, you must add tests for it!** Not only does to make the builtins more maintainable, it's the the easiest way to test these functions on Zig. To run the test, run: `zig build test` 1. Add the function to the relevant module. For `Num` builtin use it in `src/num.zig`, for `Str` builtins use `src/str.zig`, and so on. **For anything you add, you must add tests for it!** Not only does to make the builtins more maintainable, it's the the easiest way to test these functions on Zig. To run the test, run: `zig build test`
2. Make sure the function is public with the `pub` keyword and uses the C calling convention. This is really easy, just add `pub` and `callconv(.C)` to the function declaration like so: `pub fn atan(num: f64) callconv(.C) f64 { ... }` 2. Make sure the function is public with the `pub` keyword and uses the C calling convention. This is really easy, just add `pub` and `callconv(.C)` to the function declaration like so: `pub fn atan(num: f64) callconv(.C) f64 { ... }`
3. In `src/main.zig`, export the function. This is also organized by module. For example, for a `Num` function find the `Num` section and add: `comptime { exportNumFn(num.atan, "atan"); }`. The first arguement is the function, the second is the name of it in LLVM. 3. In `src/main.zig`, export the function. This is also organized by module. For example, for a `Num` function find the `Num` section and add: `comptime { exportNumFn(num.atan, "atan"); }`. The first argument is the function, the second is the name of it in LLVM.
4. In `compiler/builtins/src/bitcode.rs`, add a constant for the new function. This is how we use it in Rust. Once again, this is organized by module, so just find the relevent area and add your new function. 4. In `compiler/builtins/src/bitcode.rs`, add a constant for the new function. This is how we use it in Rust. Once again, this is organized by module, so just find the relevant area and add your new function.
5. You can now your function in Rust using `call_bitcode_fn` in `llvm/src/build.rs`! 5. You can now your function in Rust using `call_bitcode_fn` in `llvm/src/build.rs`!
## How it works ## How it works
@ -32,4 +32,4 @@ There will be two directories like `roc_builtins-[some random characters]`, look
## Calling bitcode functions ## Calling bitcode functions
use the `call_bitcode_fn` function defined in `llvm/src/build.rs` to call bitcode funcitons. use the `call_bitcode_fn` function defined in `llvm/src/build.rs` to call bitcode functions.

View File

@ -176,7 +176,7 @@ fn mul_and_decimalize(a: u128, b: u128) i128 {
// floor(2^315/10^18) is 66749594872528440074844428317798503581334516323645399060845050244444366430645 // floor(2^315/10^18) is 66749594872528440074844428317798503581334516323645399060845050244444366430645
// Add 1. // Add 1.
// This can't overflow because the intial numbers are only 127bit due to removing the sign bit. // This can't overflow because the initial numbers are only 127bit due to removing the sign bit.
var overflowed = @addWithOverflow(u128, lhs_lo, 1, &lhs_lo); var overflowed = @addWithOverflow(u128, lhs_lo, 1, &lhs_lo);
lhs_hi = blk: { lhs_hi = blk: {
if (overflowed) { if (overflowed) {

View File

@ -27,7 +27,7 @@ map :
# TODO: removed `'` from signature because parser does not support it yet # TODO: removed `'` from signature because parser does not support it yet
# Original signature: insert : Dict 'key val, 'key, val -> Dict 'key val # Original signature: insert : Dict 'key val, 'key, val -> Dict 'key val
## Make sure never to insert a key of *NaN* into a [Dict]! Becuase *NaN* is ## Make sure never to insert a key of *NaN* into a [Dict]! Because *NaN* is
## defined to be unequal to *NaN*, inserting a *NaN* key results in an entry ## defined to be unequal to *NaN*, inserting a *NaN* key results in an entry
## that can never be retrieved or removed from the [Dict]. ## that can never be retrieved or removed from the [Dict].
insert : Dict key val, key, val -> Dict key val insert : Dict key val, key, val -> Dict key val

View File

@ -180,7 +180,7 @@ interface List2
## we can free it immediately because there are no other refcounts. However, ## we can free it immediately because there are no other refcounts. However,
## in the case of `lists`, we have to iterate through the list and decrement ## in the case of `lists`, we have to iterate through the list and decrement
## the refcounts of each of its contained lists - because they, too, have ## the refcounts of each of its contained lists - because they, too, have
## refcounts! Importantly, beacuse the first element had its refcount incremented ## refcounts! Importantly, because the first element had its refcount incremented
## because the function returned `first`, that element will actually end up ## because the function returned `first`, that element will actually end up
## *not* getting freed at the end - but all the others will be. ## *not* getting freed at the end - but all the others will be.
## ##

View File

@ -562,7 +562,7 @@ trunc : Frac * -> Int *
## Since #Nat has a different maximum number depending on the system you're building ## Since #Nat has a different maximum number depending on the system you're building
## for, this may give a different answer on different systems. ## for, this may give a different answer on different systems.
## ##
## For example, on a 32-bit sytem, #Num.maxNat will return the same answer as ## For example, on a 32-bit system, #Num.maxNat will return the same answer as
## #Num.maxU32. This means that calling `Num.toNat 9_000_000_000` on a 32-bit ## #Num.maxU32. This means that calling `Num.toNat 9_000_000_000` on a 32-bit
## system will return #Num.maxU32 instead of 9 billion, because 9 billion is ## system will return #Num.maxU32 instead of 9 billion, because 9 billion is
## higher than #Num.maxU32 and will not fit in a #Nat on a 32-bit system. ## higher than #Num.maxU32 and will not fit in a #Nat on a 32-bit system.

View File

@ -18,7 +18,7 @@ len : Set * -> Nat
# TODO: removed `'` from signature because parser does not support it yet # TODO: removed `'` from signature because parser does not support it yet
# Original signature: `add : Set 'elem, 'elem -> Set 'elem` # Original signature: `add : Set 'elem, 'elem -> Set 'elem`
## Make sure never to add a *NaN* to a [Set]! Becuase *NaN* is defined to be ## Make sure never to add a *NaN* to a [Set]! Because *NaN* is defined to be
## unequal to *NaN*, adding a *NaN* results in an entry that can never be ## unequal to *NaN*, adding a *NaN* results in an entry that can never be
## retrieved or removed from the [Set]. ## retrieved or removed from the [Set].
add : Set elem, elem -> Set elem add : Set elem, elem -> Set elem

View File

@ -194,7 +194,7 @@ startsWith : Str, Str -> Bool
## if you want to check whether a string begins with something that's representable ## if you want to check whether a string begins with something that's representable
## in a single code point, you can use (for example) `Str.startsWithCodePoint '鹏'` ## in a single code point, you can use (for example) `Str.startsWithCodePoint '鹏'`
## instead of `Str.startsWithCodePoint "鹏"`. ('鹏' evaluates to the [U32] ## instead of `Str.startsWithCodePoint "鹏"`. ('鹏' evaluates to the [U32]
## value `40527`.) This will not work for graphemes which take up mulitple code ## value `40527`.) This will not work for graphemes which take up multiple code
## points, however; `Str.startsWithCodePoint '👩‍👩‍👦‍👦'` would be a compiler error ## points, however; `Str.startsWithCodePoint '👩‍👩‍👦‍👦'` would be a compiler error
## because 👩‍👩‍👦‍👦 takes up multiple code points and cannot be represented as a ## because 👩‍👩‍👦‍👦 takes up multiple code points and cannot be represented as a
## single [U32]. You'd need to use `Str.startsWithCodePoint "🕊"` instead. ## single [U32]. You'd need to use `Str.startsWithCodePoint "🕊"` instead.

View File

@ -603,7 +603,7 @@ pub fn canonicalize_expr<'a>(
// A "when" with no branches is a runtime error, but it will mess things up // A "when" with no branches is a runtime error, but it will mess things up
// if code gen mistakenly thinks this is a tail call just because its condition // if code gen mistakenly thinks this is a tail call just because its condition
// happend to be one. (The condition gave us our initial output value.) // happened to be one. (The condition gave us our initial output value.)
if branches.is_empty() { if branches.is_empty() {
output.tail_call = None; output.tail_call = None;
} }

View File

@ -345,7 +345,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
) )
} }
If(if_thens, final_else_branch) => { If(if_thens, final_else_branch) => {
// If does not get desugared into `when` so we can give more targetted error messages during type checking. // If does not get desugared into `when` so we can give more targeted error messages during type checking.
let desugared_final_else = &*arena.alloc(desugar_expr(arena, &final_else_branch)); let desugared_final_else = &*arena.alloc(desugar_expr(arena, &final_else_branch));
let mut desugared_if_thens = Vec::with_capacity_in(if_thens.len(), arena); let mut desugared_if_thens = Vec::with_capacity_in(if_thens.len(), arena);

View File

@ -13,7 +13,7 @@ use roc_types::types::Type::{self, *};
#[inline(always)] #[inline(always)]
pub fn int_literal( pub fn int_literal(
num_var: Variable, num_var: Variable,
percision_var: Variable, precision_var: Variable,
expected: Expected<Type>, expected: Expected<Type>,
region: Region, region: Region,
) -> Constraint { ) -> Constraint {
@ -25,7 +25,7 @@ pub fn int_literal(
And(vec![ And(vec![
Eq( Eq(
num_type.clone(), num_type.clone(),
ForReason(reason, num_int(Type::Variable(percision_var)), region), ForReason(reason, num_int(Type::Variable(precision_var)), region),
Category::Int, Category::Int,
region, region,
), ),

View File

@ -96,7 +96,7 @@ pub fn constrain_expr(
expected: Expected<Type>, expected: Expected<Type>,
) -> Constraint { ) -> Constraint {
match expr { match expr {
Int(var, percision, _) => int_literal(*var, *percision, expected, region), Int(var, precision, _) => int_literal(*var, *precision, expected, region),
Num(var, _) => exists( Num(var, _) => exists(
vec![*var], vec![*var],
Eq( Eq(
@ -106,7 +106,7 @@ pub fn constrain_expr(
region, region,
), ),
), ),
Float(var, percision, _) => float_literal(*var, *percision, expected, region), Float(var, precision, _) => float_literal(*var, *precision, expected, region),
EmptyRecord => constrain_empty_record(region, expected), EmptyRecord => constrain_empty_record(region, expected),
Expr::Record { record_var, fields } => { Expr::Record { record_var, fields } => {
if fields.is_empty() { if fields.is_empty() {

View File

@ -146,7 +146,7 @@ pub fn pre_constrain_imports(
// Translate referenced symbols into constraints. We do this on the main // Translate referenced symbols into constraints. We do this on the main
// thread because we need exclusive access to the exposed_types map, in order // thread because we need exclusive access to the exposed_types map, in order
// to get the necessary constraint info for any aliases we imported. We also // to get the necessary constraint info for any aliases we imported. We also
// resolve builtin types now, so we can use a refernce to stdlib instead of // resolve builtin types now, so we can use a reference to stdlib instead of
// having to either clone it or recreate it from scratch on the other thread. // having to either clone it or recreate it from scratch on the other thread.
for &symbol in references.iter() { for &symbol in references.iter() {
let module_id = symbol.module_id(); let module_id = symbol.module_id();

View File

@ -116,7 +116,7 @@ mod test_fmt {
} }
#[test] #[test]
fn force_space_at_begining_of_comment() { fn force_space_at_beginning_of_comment() {
expr_formats_to( expr_formats_to(
indoc!( indoc!(
r#" r#"

View File

@ -5,7 +5,7 @@ It goes from Roc's [mono ir](https://github.com/rtfeldman/roc/blob/trunk/compile
## General Process ## General Process
The backend is essentially defined as two recursive match statment over the mono ir. The backend is essentially defined as two recursive match statement over the mono ir.
The first pass is used to do simple linear scan lifetime analysis. The first pass is used to do simple linear scan lifetime analysis.
In the future it may be expanded to add a few other quick optimizations. In the future it may be expanded to add a few other quick optimizations.
The second pass is the actual meat of the backend that generates the byte buffer of output binary. The second pass is the actual meat of the backend that generates the byte buffer of output binary.
@ -62,7 +62,7 @@ Here are example implementations for [arm](https://github.com/rtfeldman/roc/blob
Adding a new builtin to the dev backend can be pretty simple. Adding a new builtin to the dev backend can be pretty simple.
Here is [an example](https://github.com/rtfeldman/roc/pull/893/files) of adding `Num.Sub`. Here is [an example](https://github.com/rtfeldman/roc/pull/893/files) of adding `Num.Sub`.
This is the general procede I follow with some helpful links: This is the general procedure I follow with some helpful links:
1. Find a feature that is just n+1. 1. Find a feature that is just n+1.
For example, since we already have integers, adding a builtin that functions on them should be n+1. For example, since we already have integers, adding a builtin that functions on them should be n+1.

View File

@ -205,7 +205,7 @@ pub struct Backend64Bit<
float_used_callee_saved_regs: MutSet<FloatReg>, float_used_callee_saved_regs: MutSet<FloatReg>,
stack_size: u32, stack_size: u32,
// The ammount of stack space needed to pass args for function calling. // The amount of stack space needed to pass args for function calling.
fn_call_stack_size: u32, fn_call_stack_size: u32,
} }
@ -409,7 +409,7 @@ impl<
Ok(()) Ok(())
} }
x => Err(format!( x => Err(format!(
"recieving return type, {:?}, is not yet implemented", "receiving return type, {:?}, is not yet implemented",
x x
)), )),
} }

View File

@ -236,7 +236,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64SystemV {
Layout::Builtin(Builtin::Float64) => {} Layout::Builtin(Builtin::Float64) => {}
x => { x => {
return Err(format!( return Err(format!(
"recieving return type, {:?}, is not yet implemented", "receiving return type, {:?}, is not yet implemented",
x x
)); ));
} }
@ -530,7 +530,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg> for X86_64WindowsFastcall {
Layout::Builtin(Builtin::Float64) => {} Layout::Builtin(Builtin::Float64) => {}
x => { x => {
return Err(format!( return Err(format!(
"recieving return type, {:?}, is not yet implemented", "receiving return type, {:?}, is not yet implemented",
x x
)); ));
} }

View File

@ -145,7 +145,7 @@ where
) -> Result<(), String>; ) -> Result<(), String>;
/// build_expr builds the expressions for the specified symbol. /// build_expr builds the expressions for the specified symbol.
/// The builder must keep track of the symbol because it may be refered to later. /// The builder must keep track of the symbol because it may be referred to later.
fn build_expr( fn build_expr(
&mut self, &mut self,
sym: &Symbol, sym: &Symbol,
@ -230,7 +230,7 @@ where
} }
/// build_run_low_level builds the low level opertation and outputs to the specified symbol. /// build_run_low_level builds the low level opertation and outputs to the specified symbol.
/// The builder must keep track of the symbol because it may be refered to later. /// The builder must keep track of the symbol because it may be referred to later.
fn build_run_low_level( fn build_run_low_level(
&mut self, &mut self,
sym: &Symbol, sym: &Symbol,

View File

@ -1460,7 +1460,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
let builder = env.builder; let builder = env.builder;
// Determine types, assumes the descriminant is in the field layouts // Determine types, assumes the discriminant is in the field layouts
let num_fields = field_layouts.len(); let num_fields = field_layouts.len();
let mut field_types = Vec::with_capacity_in(num_fields, env.arena); let mut field_types = Vec::with_capacity_in(num_fields, env.arena);
@ -5135,7 +5135,7 @@ fn build_int_binop<'a, 'ctx, 'env>(
// rem == 0 // rem == 0
// } // }
// //
// NOTE we'd like the branches to be swapped for better branch prediciton, // NOTE we'd like the branches to be swapped for better branch prediction,
// but llvm normalizes to the above ordering in -O3 // but llvm normalizes to the above ordering in -O3
let zero = rhs.get_type().const_zero(); let zero = rhs.get_type().const_zero();
let neg_1 = rhs.get_type().const_int(-1i64 as u64, false); let neg_1 = rhs.get_type().const_int(-1i64 as u64, false);
@ -5482,7 +5482,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
int_abs_raise_on_overflow(env, arg, arg_layout) int_abs_raise_on_overflow(env, arg, arg_layout)
} }
NumToFloat => { NumToFloat => {
// TODO: Handle differnt sized numbers // TODO: Handle different sized numbers
// This is an Int, so we need to convert it. // This is an Int, so we need to convert it.
bd.build_cast( bd.build_cast(
InstructionOpcode::SIToFP, InstructionOpcode::SIToFP,
@ -5606,7 +5606,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
let bd = env.builder; let bd = env.builder;
// TODO: Handle differnt sized floats // TODO: Handle different sized floats
match op { match op {
NumNeg => bd.build_float_neg(arg, "negate_float").into(), NumNeg => bd.build_float_neg(arg, "negate_float").into(),
NumAbs => env.call_intrinsic(LLVM_FABS_F64, &[arg.into()]), NumAbs => env.call_intrinsic(LLVM_FABS_F64, &[arg.into()]),
@ -5747,7 +5747,7 @@ fn throw_exception<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, message: &str) {
let builder = env.builder; let builder = env.builder;
let info = { let info = {
// we represend both void and char pointers with `u8*` // we represented both void and char pointers with `u8*`
let u8_ptr = context.i8_type().ptr_type(AddressSpace::Generic); let u8_ptr = context.i8_type().ptr_type(AddressSpace::Generic);
// allocate an exception (that can hold a pointer to a string) // allocate an exception (that can hold a pointer to a string)

View File

@ -1,4 +1,4 @@
use crate::docs::DocEntry::DetatchedDoc; use crate::docs::DocEntry::DetachedDoc;
use crate::docs::TypeAnnotation::{ use crate::docs::TypeAnnotation::{
Apply, BoundVariable, Function, NoTypeAnn, ObscuredRecord, ObscuredTagUnion, Record, TagUnion, Apply, BoundVariable, Function, NoTypeAnn, ObscuredRecord, ObscuredTagUnion, Record, TagUnion,
}; };
@ -32,7 +32,7 @@ pub struct ModuleDocumentation {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum DocEntry { pub enum DocEntry {
DocDef(DocDef), DocDef(DocDef),
DetatchedDoc(String), DetachedDoc(String),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -108,10 +108,10 @@ pub fn generate_module_docs<'a>(
} }
} }
fn detatched_docs_from_comments_and_new_lines<'a>( fn detached_docs_from_comments_and_new_lines<'a>(
comments_or_new_lines: &'a [roc_parse::ast::CommentOrNewline<'a>], comments_or_new_lines: &'a [roc_parse::ast::CommentOrNewline<'a>],
) -> Vec<String> { ) -> Vec<String> {
let mut detatched_docs: Vec<String> = Vec::new(); let mut detached_docs: Vec<String> = Vec::new();
let mut docs = String::new(); let mut docs = String::new();
@ -123,13 +123,13 @@ fn detatched_docs_from_comments_and_new_lines<'a>(
} }
CommentOrNewline::LineComment(_) | CommentOrNewline::Newline => { CommentOrNewline::LineComment(_) | CommentOrNewline::Newline => {
detatched_docs.push(docs.clone()); detached_docs.push(docs.clone());
docs = String::new(); docs = String::new();
} }
} }
} }
detatched_docs detached_docs
} }
fn generate_entry_doc<'a>( fn generate_entry_doc<'a>(
@ -147,8 +147,8 @@ fn generate_entry_doc<'a>(
Def::SpaceBefore(sub_def, comments_or_new_lines) => { Def::SpaceBefore(sub_def, comments_or_new_lines) => {
// Comments before a definition are attached to the current defition // Comments before a definition are attached to the current defition
for detatched_doc in detatched_docs_from_comments_and_new_lines(comments_or_new_lines) { for detached_doc in detached_docs_from_comments_and_new_lines(comments_or_new_lines) {
acc.push(DetatchedDoc(detatched_doc)); acc.push(DetachedDoc(detached_doc));
} }
generate_entry_doc(ident_ids, acc, Some(comments_or_new_lines), sub_def) generate_entry_doc(ident_ids, acc, Some(comments_or_new_lines), sub_def)

View File

@ -40,7 +40,7 @@ pub fn infer_borrow<'a>(
// This is a fixed-point analysis // This is a fixed-point analysis
// //
// all functions initiall own all their paramters // all functions initiall own all their parameters
// through a series of checks and heuristics, some arguments are set to borrowed // through a series of checks and heuristics, some arguments are set to borrowed
// when that doesn't lead to conflicts the change is kept, otherwise it may be reverted // when that doesn't lead to conflicts the change is kept, otherwise it may be reverted
// //
@ -348,7 +348,7 @@ impl<'a> BorrowInfState<'a> {
/// let z = e in ... /// let z = e in ...
/// ///
/// and determines whether z and which of the symbols used in e /// and determines whether z and which of the symbols used in e
/// must be taken as owned paramters /// must be taken as owned parameters
fn collect_call(&mut self, z: Symbol, e: &crate::ir::Call<'a>) { fn collect_call(&mut self, z: Symbol, e: &crate::ir::Call<'a>) {
use crate::ir::CallType::*; use crate::ir::CallType::*;

View File

@ -7,16 +7,16 @@ use roc_collections::all::{MutMap, MutSet};
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
pub fn free_variables(stmt: &Stmt<'_>) -> MutSet<Symbol> { pub fn free_variables(stmt: &Stmt<'_>) -> MutSet<Symbol> {
let (mut occuring, bound) = occuring_variables(stmt); let (mut occurring, bound) = occurring_variables(stmt);
for ref s in bound { for ref s in bound {
occuring.remove(s); occurring.remove(s);
} }
occuring occurring
} }
pub fn occuring_variables(stmt: &Stmt<'_>) -> (MutSet<Symbol>, MutSet<Symbol>) { pub fn occurring_variables(stmt: &Stmt<'_>) -> (MutSet<Symbol>, MutSet<Symbol>) {
let mut stack = std::vec![stmt]; let mut stack = std::vec![stmt];
let mut result = MutSet::default(); let mut result = MutSet::default();
let mut bound_variables = MutSet::default(); let mut bound_variables = MutSet::default();
@ -26,7 +26,7 @@ pub fn occuring_variables(stmt: &Stmt<'_>) -> (MutSet<Symbol>, MutSet<Symbol>) {
match stmt { match stmt {
Let(symbol, expr, _, cont) => { Let(symbol, expr, _, cont) => {
occuring_variables_expr(expr, &mut result); occurring_variables_expr(expr, &mut result);
result.insert(*symbol); result.insert(*symbol);
bound_variables.insert(*symbol); bound_variables.insert(*symbol);
stack.push(cont); stack.push(cont);
@ -39,7 +39,7 @@ pub fn occuring_variables(stmt: &Stmt<'_>) -> (MutSet<Symbol>, MutSet<Symbol>) {
fail, fail,
.. ..
} => { } => {
occuring_variables_call(call, &mut result); occurring_variables_call(call, &mut result);
result.insert(*symbol); result.insert(*symbol);
bound_variables.insert(*symbol); bound_variables.insert(*symbol);
stack.push(pass); stack.push(pass);
@ -93,13 +93,13 @@ pub fn occuring_variables(stmt: &Stmt<'_>) -> (MutSet<Symbol>, MutSet<Symbol>) {
(result, bound_variables) (result, bound_variables)
} }
fn occuring_variables_call(call: &crate::ir::Call<'_>, result: &mut MutSet<Symbol>) { fn occurring_variables_call(call: &crate::ir::Call<'_>, result: &mut MutSet<Symbol>) {
// NOTE though the function name does occur, it is a static constant in the program // NOTE though the function name does occur, it is a static constant in the program
// for liveness, it should not be included here. // for liveness, it should not be included here.
result.extend(call.arguments.iter().copied()); result.extend(call.arguments.iter().copied());
} }
pub fn occuring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) { pub fn occurring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
use Expr::*; use Expr::*;
match expr { match expr {
@ -109,7 +109,7 @@ pub fn occuring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
result.insert(*symbol); result.insert(*symbol);
} }
Call(call) => occuring_variables_call(call, result), Call(call) => occurring_variables_call(call, result),
Tag { arguments, .. } Tag { arguments, .. }
| Struct(arguments) | Struct(arguments)
@ -160,13 +160,13 @@ struct Context<'a> {
fn update_live_vars<'a>(expr: &Expr<'a>, v: &LiveVarSet) -> LiveVarSet { fn update_live_vars<'a>(expr: &Expr<'a>, v: &LiveVarSet) -> LiveVarSet {
let mut v = v.clone(); let mut v = v.clone();
occuring_variables_expr(expr, &mut v); occurring_variables_expr(expr, &mut v);
v v
} }
/// `isFirstOcc xs x i = true` if `xs[i]` is the first occurrence of `xs[i]` in `xs` /// `isFirstOcc xs x i = true` if `xs[i]` is the first occurrence of `xs[i]` in `xs`
fn is_first_occurence(xs: &[Symbol], i: usize) -> bool { fn is_first_occurrence(xs: &[Symbol], i: usize) -> bool {
match xs.get(i) { match xs.get(i) {
None => unreachable!(), None => unreachable!(),
Some(s) => i == xs.iter().position(|v| s == v).unwrap(), Some(s) => i == xs.iter().position(|v| s == v).unwrap(),
@ -319,7 +319,7 @@ impl<'a> Context<'a> {
{ {
for (i, x) in xs.iter().enumerate() { for (i, x) in xs.iter().enumerate() {
let info = self.get_var_info(*x); let info = self.get_var_info(*x);
if !info.reference || !is_first_occurence(xs, i) { if !info.reference || !is_first_occurrence(xs, i) {
// do nothing // do nothing
} else { } else {
let num_consumptions = get_num_consumptions(*x, xs, consume_param_pred.clone()); // number of times the argument is used let num_consumptions = get_num_consumptions(*x, xs, consume_param_pred.clone()); // number of times the argument is used
@ -393,7 +393,7 @@ impl<'a> Context<'a> {
// Remark: `x` may occur multiple times in the application (e.g., `f x y x`). // Remark: `x` may occur multiple times in the application (e.g., `f x y x`).
// This is why we check whether it is the first occurrence. // This is why we check whether it is the first occurrence.
if self.must_consume(*x) if self.must_consume(*x)
&& is_first_occurence(xs, i) && is_first_occurrence(xs, i)
&& is_borrow_param(*x, xs, ps) && is_borrow_param(*x, xs, ps)
&& !b_live_vars.contains(x) && !b_live_vars.contains(x)
{ {
@ -418,7 +418,7 @@ impl<'a> Context<'a> {
This is why we check whether it is the first occurrence. */ This is why we check whether it is the first occurrence. */
if self.must_consume(*x) if self.must_consume(*x)
&& is_first_occurence(xs, i) && is_first_occurrence(xs, i)
&& *is_borrow && *is_borrow
&& !b_live_vars.contains(x) && !b_live_vars.contains(x)
{ {
@ -1096,7 +1096,7 @@ pub fn collect_stmt(
vars = collect_stmt(cont, jp_live_vars, vars); vars = collect_stmt(cont, jp_live_vars, vars);
vars.remove(symbol); vars.remove(symbol);
let mut result = MutSet::default(); let mut result = MutSet::default();
occuring_variables_expr(expr, &mut result); occurring_variables_expr(expr, &mut result);
vars.extend(result); vars.extend(result);
vars vars
@ -1114,7 +1114,7 @@ pub fn collect_stmt(
vars.remove(symbol); vars.remove(symbol);
let mut result = MutSet::default(); let mut result = MutSet::default();
occuring_variables_call(call, &mut result); occurring_variables_call(call, &mut result);
vars.extend(result); vars.extend(result);

View File

@ -7669,7 +7669,7 @@ pub fn num_argument_to_int_or_float(
4 => IntOrFloat::UnsignedIntType(IntPrecision::I32), 4 => IntOrFloat::UnsignedIntType(IntPrecision::I32),
8 => IntOrFloat::UnsignedIntType(IntPrecision::I64), 8 => IntOrFloat::UnsignedIntType(IntPrecision::I64),
_ => panic!( _ => panic!(
"Invalid target for Num type arguement: Roc does't support compiling to {}-bit systems.", "Invalid target for Num type argument: Roc does't support compiling to {}-bit systems.",
ptr_bytes * 8 ptr_bytes * 8
), ),
} }

View File

@ -418,7 +418,7 @@ impl<'a> ExprState<'a> {
F: Fn(Region, Row, Col) -> EExpr<'a>, F: Fn(Region, Row, Col) -> EExpr<'a>,
{ {
if !self.operators.is_empty() { if !self.operators.is_empty() {
// this `=` or `<-` likely occured inline; treat it as an invalid operator // this `=` or `<-` likely occurred inline; treat it as an invalid operator
let opchar = match loc_op.value { let opchar = match loc_op.value {
BinOp::Assignment => arena.alloc([b'=']) as &[_], BinOp::Assignment => arena.alloc([b'=']) as &[_],
BinOp::Backpassing => arena.alloc([b'<', b'-']) as &[_], BinOp::Backpassing => arena.alloc([b'<', b'-']) as &[_],
@ -451,7 +451,7 @@ impl<'a> ExprState<'a> {
debug_assert_eq!(loc_op.value, BinOp::HasType); debug_assert_eq!(loc_op.value, BinOp::HasType);
if !self.operators.is_empty() { if !self.operators.is_empty() {
// this `:` likely occured inline; treat it as an invalid operator // this `:` likely occurred inline; treat it as an invalid operator
let opchar = arena.alloc([b':']) as &[_]; let opchar = arena.alloc([b':']) as &[_];
let fail = let fail =
@ -1000,7 +1000,7 @@ fn parse_expr_operator<'a>(
(&*arena.alloc(Located::at(alias_region, alias)), state) (&*arena.alloc(Located::at(alias_region, alias)), state)
} }
Err(_) => { Err(_) => {
// this `=` likely occured inline; treat it as an invalid operator // this `=` likely occurred inline; treat it as an invalid operator
let fail = EExpr::BadOperator( let fail = EExpr::BadOperator(
arena.alloc([b'=']), arena.alloc([b'=']),
loc_op.region.start_line, loc_op.region.start_line,
@ -1044,7 +1044,7 @@ fn parse_expr_operator<'a>(
(Located::at(expr_region, good), ann_type, state) (Located::at(expr_region, good), ann_type, state)
} }
Err(_) => { Err(_) => {
// this `=` likely occured inline; treat it as an invalid operator // this `=` likely occurred inline; treat it as an invalid operator
let fail = EExpr::BadOperator( let fail = EExpr::BadOperator(
arena.alloc([b'=']), arena.alloc([b'=']),
loc_op.region.start_line, loc_op.region.start_line,
@ -1153,7 +1153,7 @@ fn parse_expr_operator<'a>(
} }
} }
Err(_) => { Err(_) => {
// this `:` likely occured inline; treat it as an invalid operator // this `:` likely occurred inline; treat it as an invalid operator
let fail = EExpr::BadOperator( let fail = EExpr::BadOperator(
arena.alloc([b':']), arena.alloc([b':']),
loc_op.region.start_line, loc_op.region.start_line,

View File

@ -3385,7 +3385,7 @@ mod test_parse {
// Reproducing this bug requires a bizarre set of things to all be true: // Reproducing this bug requires a bizarre set of things to all be true:
// //
// * Must be parsing a *module* def (nested expr defs don't repro this) // * Must be parsing a *module* def (nested expr defs don't repro this)
// * That top-level module def conatins a def inside it // * That top-level module def contains a def inside it
// * That inner def is defining a function // * That inner def is defining a function
// * The name of the inner def begins with a keyword (`if`, `then`, `else`, `when`, `is`) // * The name of the inner def begins with a keyword (`if`, `then`, `else`, `when`, `is`)
// //

View File

@ -1973,7 +1973,7 @@ fn to_type_report<'a>(
let region = Region::from_row_col(*row, *col); let region = Region::from_row_col(*row, *col);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just started parsing a function argument type, but I encounterd two commas in a row:"), alloc.reflow(r"I just started parsing a function argument type, but I encountered two commas in a row:"),
alloc.region_with_subregion(surroundings, region), alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![alloc.reflow("Try removing one of them.")]), alloc.concat(vec![alloc.reflow("Try removing one of them.")]),
]); ]);

View File

@ -1046,7 +1046,7 @@ fn to_pattern_report<'b>(
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.text("This pattern is being used in an unexpected way:"), alloc.text("This pattern is being used in an unexpected way:"),
alloc.region(expr_region), alloc.region(expr_region),
pattern_type_comparision( pattern_type_comparison(
alloc, alloc,
found, found,
expected_type, expected_type,
@ -1078,7 +1078,7 @@ fn to_pattern_report<'b>(
.append(name.clone()) .append(name.clone())
.append(alloc.text(" is weird:")), .append(alloc.text(" is weird:")),
alloc.region(region), alloc.region(region),
pattern_type_comparision( pattern_type_comparison(
alloc, alloc,
found, found,
expected_type, expected_type,
@ -1112,7 +1112,7 @@ fn to_pattern_report<'b>(
.append(alloc.keyword("when")) .append(alloc.keyword("when"))
.append(alloc.text(" is causing a mismatch:")), .append(alloc.text(" is causing a mismatch:")),
alloc.region(region), alloc.region(region),
pattern_type_comparision( pattern_type_comparison(
alloc, alloc,
found, found,
expected_type, expected_type,
@ -1144,7 +1144,7 @@ fn to_pattern_report<'b>(
.append(alloc.keyword("when")) .append(alloc.keyword("when"))
.append(alloc.text(" does not match the previous ones:")), .append(alloc.text(" does not match the previous ones:")),
alloc.region(region), alloc.region(region),
pattern_type_comparision( pattern_type_comparison(
alloc, alloc,
found, found,
expected_type, expected_type,
@ -1175,7 +1175,7 @@ fn to_pattern_report<'b>(
} }
} }
fn pattern_type_comparision<'b>( fn pattern_type_comparison<'b>(
alloc: &'b RocDocAllocator<'b>, alloc: &'b RocDocAllocator<'b>,
actual: ErrorType, actual: ErrorType,
expected: ErrorType, expected: ErrorType,

View File

@ -450,11 +450,11 @@ impl<'a> RocDocAllocator<'a> {
} else { } else {
ERROR_UNDERLINE.repeat((sub_region2.end_col - sub_region2.start_col) as usize) ERROR_UNDERLINE.repeat((sub_region2.end_col - sub_region2.start_col) as usize)
}; };
let inbetween = " " let in_between = " "
.repeat((sub_region2.start_col.saturating_sub(sub_region1.end_col)) as usize); .repeat((sub_region2.start_col.saturating_sub(sub_region1.end_col)) as usize);
self.text(highlight1) self.text(highlight1)
.append(self.text(inbetween)) .append(self.text(in_between))
.append(self.text(highlight2)) .append(self.text(highlight2))
}; };

View File

@ -4774,7 +4774,7 @@ mod test_reporting {
r#" r#"
DOUBLE COMMA DOUBLE COMMA
I just started parsing a function argument type, but I encounterd two I just started parsing a function argument type, but I encountered two
commas in a row: commas in a row:
1 f : I64,,I64 -> I64 1 f : I64,,I64 -> I64

View File

@ -793,7 +793,7 @@ fn type_to_variable(
Alias(symbol, args, alias_type) => { Alias(symbol, args, alias_type) => {
// TODO cache in uniqueness inference gives problems! all Int's get the same uniqueness var! // TODO cache in uniqueness inference gives problems! all Int's get the same uniqueness var!
// Cache aliases without type arguments. Commonly used aliases like `Int` would otherwise get O(n) // Cache aliases without type arguments. Commonly used aliases like `Int` would otherwise get O(n)
// different variables (once for each occurence). The recursion restriction is required // different variables (once for each occurrence). The recursion restriction is required
// for uniqueness types only: recursive aliases "introduce" an unbound uniqueness // for uniqueness types only: recursive aliases "introduce" an unbound uniqueness
// attribute in the body, when // attribute in the body, when
// //

View File

@ -82,7 +82,7 @@ When calling `List.append list1 list2` on a unique `list1`, first we'll check to
If there is not enough capacity to fit both lists, then we can try to call [`realloc`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/realloc?view=vs-2019) to hopefully extend the size of our allocated memory. If `realloc` succeeds (meaning there happened to be enough free memory right after our current allocation), then we update `capacity` to reflect the new amount of space, and move on. If there is not enough capacity to fit both lists, then we can try to call [`realloc`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/realloc?view=vs-2019) to hopefully extend the size of our allocated memory. If `realloc` succeeds (meaning there happened to be enough free memory right after our current allocation), then we update `capacity` to reflect the new amount of space, and move on.
> **Note:** The reason we store capacity right after the last element in the list is becasue of how memory cache lines work. Whenever we need to access `capacity`, it's because we're about to increase the length of the list, which means that we will most certainly be writing to the memory location right after its last element. That in turn means that we'll need to have that memory location in cache, which in turn means that looking up the `capacity` there is guaranteed not to cause a cache miss. (It's possible that writing the new capacity value to a later address could cause a cache miss, but this strategy minimizes the chance of that happening.) An alternate design would be where we store the capacity right before the first element in the list. In that design we wouldn't have to re-write the capacity value at the end of the list every time we grew it, but we'd be much more likely to incur more cache misses that way - because we're working at the end of the list, not at the beginning. Cache misses are many times more expensive than an extra write to a memory address that's in cache already, not to mention the potential extra load instruction to add the length to the memory address of the first element (instead of subtracting 1 from that address), so we optimize for minimizing the highly expensive cache misses by always paying a tiny additional cost when increasing the length of the list, as well as a potential even tinier cost (zero, if the length already happens to be in a register) when looking up its capacity or refcount. > **Note:** The reason we store capacity right after the last element in the list is because of how memory cache lines work. Whenever we need to access `capacity`, it's because we're about to increase the length of the list, which means that we will most certainly be writing to the memory location right after its last element. That in turn means that we'll need to have that memory location in cache, which in turn means that looking up the `capacity` there is guaranteed not to cause a cache miss. (It's possible that writing the new capacity value to a later address could cause a cache miss, but this strategy minimizes the chance of that happening.) An alternate design would be where we store the capacity right before the first element in the list. In that design we wouldn't have to re-write the capacity value at the end of the list every time we grew it, but we'd be much more likely to incur more cache misses that way - because we're working at the end of the list, not at the beginning. Cache misses are many times more expensive than an extra write to a memory address that's in cache already, not to mention the potential extra load instruction to add the length to the memory address of the first element (instead of subtracting 1 from that address), so we optimize for minimizing the highly expensive cache misses by always paying a tiny additional cost when increasing the length of the list, as well as a potential even tinier cost (zero, if the length already happens to be in a register) when looking up its capacity or refcount.
If `realloc` fails, then we have to fall back on the same "allocate new memory and copy everything" strategy that we do with shared lists. If `realloc` fails, then we have to fall back on the same "allocate new memory and copy everything" strategy that we do with shared lists.
@ -107,7 +107,7 @@ Since each bool value is a byte, it's okay for them to be packed side-by-side ev
Note that unlike in the `List Str` example before, there wouldn't be any unused memory between the refcount (or capacity, depending on whether the list was shared or unique) and the first element in the list. That will always be the case when the size of the refcount is no bigger than the alignment of the list's elements. Note that unlike in the `List Str` example before, there wouldn't be any unused memory between the refcount (or capacity, depending on whether the list was shared or unique) and the first element in the list. That will always be the case when the size of the refcount is no bigger than the alignment of the list's elements.
## Distinguishing bewteen refcount and capacity in the host ## Distinguishing between refcount and capacity in the host
If I'm a platform author, and I receive a `List` from the application, it's important that I be able to tell whether I'm dealing with a refcount or a capacity. (The uniqueness type information will have been erased by this time, because some applications will return a Unique list while others return a Shared list, so I need to be able to tell using runtime information only which is which.) This way, I can know to either increment the refcount, or to feel free to mutate it in-place using the capacity value. If I'm a platform author, and I receive a `List` from the application, it's important that I be able to tell whether I'm dealing with a refcount or a capacity. (The uniqueness type information will have been erased by this time, because some applications will return a Unique list while others return a Shared list, so I need to be able to tell using runtime information only which is which.) This way, I can know to either increment the refcount, or to feel free to mutate it in-place using the capacity value.

View File

@ -383,7 +383,7 @@ fn list_walk_with_str() {
} }
#[test] #[test]
fn list_walk_substraction() { fn list_walk_subtraction() {
assert_evals_to!(r#"List.walk [ 1, 2 ] Num.sub 1"#, 2, i64); assert_evals_to!(r#"List.walk [ 1, 2 ] Num.sub 1"#, 2, i64);
} }

View File

@ -143,7 +143,7 @@ fn render_main_content(interns: &Interns, module: &mut ModuleDocumentation) -> S
); );
} }
} }
DocEntry::DetatchedDoc(docs) => { DocEntry::DetachedDoc(docs) => {
buf.push_str( buf.push_str(
markdown_to_html(&mut module.scope, interns, docs.to_string()).as_str(), markdown_to_html(&mut module.scope, interns, docs.to_string()).as_str(),
); );

View File

@ -104,7 +104,7 @@ e.g. you have a test `calculate_sum_test` that only uses the function `add`, whe
* When refactoring; * When refactoring;
- Cutting and pasting code to a new file should automatically add imports to the new file and delete them from the old file. - Cutting and pasting code to a new file should automatically add imports to the new file and delete them from the old file.
- Ability to link e.g. variable name in comments to actual variable name. Comment is automatically updated when variable name is changed. - Ability to link e.g. variable name in comments to actual variable name. Comment is automatically updated when variable name is changed.
- When updating dependencies with breaking changes; show similar diffs from github projects that have succesfully updated that dependency. - When updating dependencies with breaking changes; show similar diffs from github projects that have successfully updated that dependency.
- AST backed renaming, changing variable/function/type name should change it all over the codebase. - AST backed renaming, changing variable/function/type name should change it all over the codebase.
* Automatically create all "arms" when pattern matching after entering `when var is` based on the type. * Automatically create all "arms" when pattern matching after entering `when var is` based on the type.
- All `when ... is` should be updated if the type is changed, e.g. adding Indigo to the Color type should add an arm everywhere where `when color is` is used. - All `when ... is` should be updated if the type is changed, e.g. adding Indigo to the Color type should add an arm everywhere where `when color is` is used.
@ -135,7 +135,7 @@ e.g. you have a test `calculate_sum_test` that only uses the function `add`, whe
- Webcam based eye tracking for quick selection. - Webcam based eye tracking for quick selection.
- Machine Learning: - Machine Learning:
* GPT-3 can generate correct python functions based on a comment describing the functionality, video [here](https://www.youtube.com/watch?v=utuz7wBGjKM). It's possible that training a model using ast's may lead to better results than text based models. * GPT-3 can generate correct python functions based on a comment describing the functionality, video [here](https://www.youtube.com/watch?v=utuz7wBGjKM). It's possible that training a model using ast's may lead to better results than text based models.
- Current autocomplete lacks flow, moving through suggestions with arrows is slow. Being able to code by weaving together autocomplete suggestions layed out in rows using eye tracking, that could flow. - Current autocomplete lacks flow, moving through suggestions with arrows is slow. Being able to code by weaving together autocomplete suggestions laid out in rows using eye tracking, that could flow.
#### Productivity Inspiration #### Productivity Inspiration
@ -207,9 +207,9 @@ Thoughts and ideas possibly taken from above inspirations or separate.
Or Total blindness where we need to trough sound to communicate to the user Or Total blindness where we need to trough sound to communicate to the user
Screen readers read trees of labeled elements. Each platform has different apis, but I think they are horrible. Just close your eyes and imagine listening to screen reader all day while you are using this majectic machines called computers. Screen readers read trees of labeled elements. Each platform has different apis, but I think they are horrible. Just close your eyes and imagine listening to screen reader all day while you are using this majectic machines called computers.
But blind people walk with a tool and they can react much better to sound/space relations than full on visal majority does. They are acute to sound as a spatial hint. And a hand for most of them is a very sensitive tool that can make sounds in space. But blind people walk with a tool and they can react much better to sound/space relations than full on visal majority does. They are acute to sound as a spatial hint. And a hand for most of them is a very sensitive tool that can make sounds in space.
Imagine if everytime for the user doesnt want to rely on shining rendered pixels on the screen for a feedback from machine, we make a accoustic room simulation, where with moving the "stick", either with mouse or with key arrows, we bump into one of the objects and that produces certain contextually appropriate sound (clean)*ding* Imagine if everytime for the user doesnt want to rely on shining rendered pixels on the screen for a feedback from machine, we make a acoustic room simulation, where with moving the "stick", either with mouse or with key arrows, we bump into one of the objects and that produces certain contextually appropriate sound (clean)*ding*
On the each level of abstraction they can make sounds more deeper, so then when you type letters you feel like you are playing with the sand (soft)*shh*. We would need help from some sound engeneer about it, but imagine moving down, which can be voice trigered command for motion impaired, you hear (soft)*pup* and the name of the module, and then you have options and commands appropriate for the module, they could map to those basic 4 buttons that we trained user on, and he would shortcut all the soft talk with click of a button. Think of the satisfaction when you can skip the dialog of the game and get straight into action. (X) Open functions! each function would make a sound and say its name, unless you press search and start searching for a specific function inside module, if you want one you select or move to next. On the each level of abstraction they can make sounds more deeper, so then when you type letters you feel like you are playing with the sand (soft)*shh*. We would need help from some sound engineer about it, but imagine moving down, which can be voice trigered command for motion impaired, you hear (soft)*pup* and the name of the module, and then you have options and commands appropriate for the module, they could map to those basic 4 buttons that we trained user on, and he would shortcut all the soft talk with click of a button. Think of the satisfaction when you can skip the dialog of the game and get straight into action. (X) Open functions! each function would make a sound and say its name, unless you press search and start searching for a specific function inside module, if you want one you select or move to next.
* Motor impariments * Motor impariments
[rant]BACKS OF CODERS ARE NOT HEALTHY! We need to change that![/neverstop] [rant]BACKS OF CODERS ARE NOT HEALTHY! We need to change that![/neverstop]

View File

@ -105,7 +105,7 @@ impl GridNodeMap {
} }
} }
// get position of first occurence of node_id if get_first_pos, else get the last occurence // get position of first occurrence of node_id if get_first_pos, else get the last occurrence
pub fn get_node_position(&self, node_id: MarkNodeId, get_first_pos: bool) -> EdResult<TextPos> { pub fn get_node_position(&self, node_id: MarkNodeId, get_first_pos: bool) -> EdResult<TextPos> {
let mut last_pos_opt = None; let mut last_pos_opt = None;

View File

@ -81,7 +81,7 @@ pub fn set_clipboard_txt(clipboard_opt: &mut Option<Clipboard>, txt: &str) -> Ed
clipboard.set_content(txt.to_owned())?; clipboard.set_content(txt.to_owned())?;
} else { } else {
return Err(ClipboardWriteFailed { return Err(ClipboardWriteFailed {
err_msg: "Clipboard was never initialized succesfully.".to_owned(), err_msg: "Clipboard was never initialized successfully.".to_owned(),
}); });
} }
@ -93,7 +93,7 @@ pub fn get_clipboard_txt(clipboard_opt: &mut Option<Clipboard>) -> EdResult<Stri
clipboard.get_content() clipboard.get_content()
} else { } else {
Err(ClipboardReadFailed { Err(ClipboardReadFailed {
err_msg: "Clipboard was never initialized succesfully.".to_owned(), err_msg: "Clipboard was never initialized successfully.".to_owned(),
}) })
} }
} }

View File

@ -32,7 +32,7 @@ pub fn index_of<T: ::std::fmt::Debug + std::cmp::Eq>(elt: T, slice: &[T]) -> EdR
Ok(index) Ok(index)
} }
// returns the index of the first occurence of element and index of the last occurence // returns the index of the first occurrence of element and index of the last occurrence
pub fn first_last_index_of<T: ::std::fmt::Debug + std::cmp::Eq>( pub fn first_last_index_of<T: ::std::fmt::Debug + std::cmp::Eq>(
elt: T, elt: T,
slice: &[T], slice: &[T],

View File

@ -5,7 +5,7 @@ use wgpu::{
ShaderStage, ShaderStage,
}; };
// orthographic projection is used to transfrom pixel coords to the coordinate system used by wgpu // orthographic projection is used to transform pixel coords to the coordinate system used by wgpu
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]

View File

@ -630,7 +630,7 @@ pub fn constrain_expr<'a>(
} }
} }
} }
_ => todo!("implement constaints for {:?}", expr), _ => todo!("implement constraints for {:?}", expr),
} }
} }

View File

@ -555,7 +555,7 @@ pub fn to_expr2<'a>(
// A "when" with no branches is a runtime error, but it will mess things up // A "when" with no branches is a runtime error, but it will mess things up
// if code gen mistakenly thinks this is a tail call just because its condition // if code gen mistakenly thinks this is a tail call just because its condition
// happend to be one. (The condition gave us our initial output value.) // happened to be one. (The condition gave us our initial output value.)
if branches.is_empty() { if branches.is_empty() {
output.tail_call = None; output.tail_call = None;
} }

View File

@ -776,7 +776,7 @@ fn type_to_variable<'a>(
Alias(symbol, args, alias_type_id) => { Alias(symbol, args, alias_type_id) => {
// TODO cache in uniqueness inference gives problems! all Int's get the same uniqueness var! // TODO cache in uniqueness inference gives problems! all Int's get the same uniqueness var!
// Cache aliases without type arguments. Commonly used aliases like `Int` would otherwise get O(n) // Cache aliases without type arguments. Commonly used aliases like `Int` would otherwise get O(n)
// different variables (once for each occurence). The recursion restriction is required // different variables (once for each occurrence). The recursion restriction is required
// for uniqueness types only: recursive aliases "introduce" an unbound uniqueness // for uniqueness types only: recursive aliases "introduce" an unbound uniqueness
// attribute in the body, when // attribute in the body, when
// //

View File

@ -26,7 +26,7 @@ toStr = \@Scalar u32
Ok str -> str Ok str -> str
Err _ -> Err _ ->
# This will quickly crash if it ever runs, but we're confident # This will quickly crash if it ever runs, but we're confident
# this Err branch will never run. That's becasue it only runs # this Err branch will never run. That's because it only runs
# if Str.fromScalar receives an invalid scalar value, and we've # if Str.fromScalar receives an invalid scalar value, and we've
# already validated this! # already validated this!
toStr (@Scalar (scalar * 256)) toStr (@Scalar (scalar * 256))

View File

@ -23,7 +23,7 @@ edition = "2018"
# commit of TheDan64/inkwell, push a new tag which points to the latest commit, # commit of TheDan64/inkwell, push a new tag which points to the latest commit,
# change the tag value in this Cargo.toml to point to that tag, and `cargo update`. # change the tag value in this Cargo.toml to point to that tag, and `cargo update`.
# This way, GitHub Actions works and nobody's builds get broken. # This way, GitHub Actions works and nobody's builds get broken.
inkwell = { git = "https://github.com/rtfeldman/inkwell", tag = "llvm10-0.release5", features = [ "llvm10-0" ] } inkwell = { git = "https://github.com/rtfeldman/inkwell", tag = "llvm12-0.release2", features = [ "llvm10-0" ] }
[features] [features]
target-arm = [] target-arm = []

View File

@ -185,9 +185,9 @@ macro_rules! impl_doc {
/// Mark this document as a group. /// Mark this document as a group.
/// ///
/// Groups are layed out on a single line if possible. Within a group, all basic documents with /// Groups are laid out on a single line if possible. Within a group, all basic documents with
/// several possible layouts are assigned the same layout, that is, they are all layed out /// several possible layouts are assigned the same layout, that is, they are all laid out
/// horizontally and combined into a one single line, or they are each layed out on their own /// horizontally and combined into a one single line, or they are each laid out on their own
/// line. /// line.
#[inline] #[inline]
pub fn group(self) -> Self { pub fn group(self) -> Self {
@ -714,9 +714,9 @@ where
/// Mark this document as a group. /// Mark this document as a group.
/// ///
/// Groups are layed out on a single line if possible. Within a group, all basic documents with /// Groups are laid out on a single line if possible. Within a group, all basic documents with
/// several possible layouts are assigned the same layout, that is, they are all layed out /// several possible layouts are assigned the same layout, that is, they are all laid out
/// horizontally and combined into a one single line, or they are each layed out on their own /// horizontally and combined into a one single line, or they are each laid out on their own
/// line. /// line.
#[inline] #[inline]
pub fn group(self) -> DocBuilder<'a, D, A> { pub fn group(self) -> DocBuilder<'a, D, A> {