Merge remote-tracking branch 'origin/main' into roc-dev-inline-expects

This commit is contained in:
Folkert 2022-10-21 23:05:34 +02:00
commit ebac056814
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
67 changed files with 851 additions and 1952 deletions

View file

@ -201,9 +201,9 @@ pub fn build_zig_host_native(
if let Some(shared_lib_path) = shared_lib_path {
command.args(&[
"build-exe",
"-fPIE",
// "-fPIE", PIE seems to fail on windows
shared_lib_path.to_str().unwrap(),
&bitcode::get_builtins_host_obj_path(),
&bitcode::get_builtins_windows_obj_path(),
]);
} else {
command.args(&["build-obj", "-fPIC"]);
@ -221,6 +221,7 @@ pub fn build_zig_host_native(
// include libc
"--library",
"c",
"-dynamic",
// cross-compile?
"-target",
target,

View file

@ -745,37 +745,54 @@ pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_widt
} else if (list_a.isUnique()) {
const total_length: usize = list_a.len() + list_b.len();
if (list_a.bytes) |source| {
const new_source = if (list_a.capacity >= total_length)
source
else
utils.unsafeReallocate(
source,
alignment,
list_a.len(),
total_length,
element_width,
);
const resized_list_a = list_a.reallocate(alignment, total_length, element_width);
if (list_b.bytes) |source_b| {
@memcpy(new_source + list_a.len() * element_width, source_b, list_b.len() * element_width);
}
// These must exist, otherwise, the lists would have been empty.
const source_a = resized_list_a.bytes orelse unreachable;
const source_b = list_b.bytes orelse unreachable;
@memcpy(source_a + list_a.len() * element_width, source_b, list_b.len() * element_width);
return RocList{ .bytes = new_source, .length = total_length, .capacity = total_length };
}
// decrement list b.
utils.decref(source_b, list_b.len(), alignment);
return resized_list_a;
} else if (list_b.isUnique()) {
const total_length: usize = list_a.len() + list_b.len();
const resized_list_b = list_b.reallocate(alignment, total_length, element_width);
// These must exist, otherwise, the lists would have been empty.
const source_a = list_a.bytes orelse unreachable;
const source_b = resized_list_b.bytes orelse unreachable;
// This is a bit special, we need to first copy the elements of list_b to the end,
// then copy the elements of list_a to the beginning.
// This first call must use mem.copy because the slices might overlap.
const byte_count_a = list_a.len() * element_width;
const byte_count_b = list_b.len() * element_width;
mem.copy(u8, source_b[byte_count_a .. byte_count_a + byte_count_b], source_b[0..byte_count_b]);
@memcpy(source_b, source_a, byte_count_a);
// decrement list a.
utils.decref(source_a, list_a.len(), alignment);
return resized_list_b;
}
const total_length: usize = list_a.len() + list_b.len();
const output = RocList.allocate(alignment, total_length, element_width);
if (output.bytes) |target| {
if (list_a.bytes) |source| {
@memcpy(target, source, list_a.len() * element_width);
}
if (list_b.bytes) |source| {
@memcpy(target + list_a.len() * element_width, source, list_b.len() * element_width);
}
}
// These must exist, otherwise, the lists would have been empty.
const target = output.bytes orelse unreachable;
const source_a = list_a.bytes orelse unreachable;
const source_b = list_b.bytes orelse unreachable;
@memcpy(target, source_a, list_a.len() * element_width);
@memcpy(target + list_a.len() * element_width, source_b, list_b.len() * element_width);
// decrement list a and b.
utils.decref(source_a, list_a.len(), alignment);
utils.decref(source_b, list_b.len(), alignment);
return output;
}

View file

@ -224,11 +224,6 @@ LowLevelHasher := { originalSeed : U64, state : U64 } has [
addU32,
addU64,
addU128,
addI8,
addI16,
addI32,
addI64,
addI128,
complete,
},
]
@ -250,17 +245,6 @@ combineState = \@LowLevelHasher { originalSeed, state }, { a, b, seed, length }
complete = \@LowLevelHasher { state } -> state
addI8 = \hasher, i8 ->
addU8 hasher (Num.toU8 i8)
addI16 = \hasher, i16 ->
addU16 hasher (Num.toU16 i16)
addI32 = \hasher, i32 ->
addU32 hasher (Num.toU32 i32)
addI64 = \hasher, i64 ->
addU64 hasher (Num.toU64 i64)
addI128 = \hasher, i128 ->
addU128 hasher (Num.toU128 i128)
# These implementations hash each value individually with the seed and then mix
# the resulting hash with the state. There are other options that may be faster
# like using the output of the last hash as the seed to the current hash.

View file

@ -9,11 +9,11 @@ interface Hash
addU32,
addU64,
addU128,
addI8,
addI16,
addI32,
addI64,
addI128,
hashI8,
hashI16,
hashI32,
hashI64,
hashI128,
complete,
hashStrBytes,
hashList,
@ -55,21 +55,6 @@ Hasher has
## Adds a single U128 to the hasher.
addU128 : a, U128 -> a | a has Hasher
## Adds a single I8 to the hasher.
addI8 : a, I8 -> a | a has Hasher
## Adds a single I16 to the hasher.
addI16 : a, I16 -> a | a has Hasher
## Adds a single I32 to the hasher.
addI32 : a, I32 -> a | a has Hasher
## Adds a single I64 to the hasher.
addI64 : a, I64 -> a | a has Hasher
## Adds a single I128 to the hasher.
addI128 : a, I128 -> a | a has Hasher
## Completes the hasher, extracting a hash value from its
## accumulated hash state.
complete : a -> U64 | a has Hasher
@ -83,6 +68,26 @@ hashList = \hasher, lst ->
List.walk lst hasher \accumHasher, elem ->
hash accumHasher elem
## Adds a single I8 to a hasher.
hashI8 : a, I8 -> a | a has Hasher
hashI8 = \hasher, n -> addU8 hasher (Num.toU8 n)
## Adds a single I16 to a hasher.
hashI16 : a, I16 -> a | a has Hasher
hashI16 = \hasher, n -> addU16 hasher (Num.toU16 n)
## Adds a single I32 to a hasher.
hashI32 : a, I32 -> a | a has Hasher
hashI32 = \hasher, n -> addU32 hasher (Num.toU32 n)
## Adds a single I64 to a hasher.
hashI64 : a, I64 -> a | a has Hasher
hashI64 = \hasher, n -> addU64 hasher (Num.toU64 n)
## Adds a single I128 to a hasher.
hashI128 : a, I128 -> a | a has Hasher
hashI128 = \hasher, n -> addU128 hasher (Num.toU128 n)
## Adds a container of [Hash]able elements to a [Hasher] by hashing each element.
## The container is iterated using the walk method passed in.
## The order of the elements does not affect the final hash.

View file

@ -29,6 +29,8 @@ interface List
map3,
product,
walkUntil,
walkFrom,
walkFromUntil,
range,
sortWith,
drop,
@ -443,6 +445,22 @@ walkBackwardsUntil = \list, initial, func ->
Continue new -> new
Break new -> new
## Walks to the end of the list from a specified starting index
walkFrom : List elem, Nat, state, (state, elem -> state) -> state
walkFrom = \list, index, state, func ->
walkHelp : _, _ -> [Continue _, Break []]
walkHelp = \currentState, element -> Continue (func currentState element)
when List.iterHelp list state walkHelp index (List.len list) is
Continue new -> new
## A combination of [List.walkFrom] and [List.walkUntil]
walkFromUntil : List elem, Nat, state, (state, elem -> [Continue state, Break state]) -> state
walkFromUntil = \list, index, state, func ->
when List.iterHelp list state func index (List.len list) is
Continue new -> new
Break new -> new
sum : List (Num a) -> Num a
sum = \list ->
List.walk list 0 Num.add

View file

@ -314,7 +314,10 @@ fn to_encoder_record(
record_var,
ext_var: env.subs.fresh_unnamed_flex_var(),
field_var,
loc_expr: Box::new(Loc::at_zero(Var(rcd_sym, record_var))),
loc_expr: Box::new(Loc::at_zero(Var(
rcd_sym,
env.subs.fresh_unnamed_flex_var(),
))),
field: field_name,
};

View file

@ -99,7 +99,10 @@ fn hash_record(env: &mut Env<'_>, fn_name: Symbol, fields: Vec<Lowercase>) -> (V
record_var,
field_var,
ext_var: env.subs.fresh_unnamed_flex_var(),
loc_expr: Box::new(Loc::at_zero(Expr::Var(rcd_sym, record_var))),
loc_expr: Box::new(Loc::at_zero(Expr::Var(
rcd_sym,
env.subs.fresh_unnamed_flex_var(),
))),
field: field_name,
};

View file

@ -123,19 +123,19 @@ impl FlatHash {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_U128))
}
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_I8))
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I8))
}
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_I16))
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I16))
}
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_I32))
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I32))
}
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_I64))
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I64))
}
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_I128))
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I128))
}
// NB: I believe it is okay to unwrap opaques here because derivers are only used
// by the backend, and the backend treats opaques like structural aliases.

View file

@ -3492,6 +3492,65 @@ mod test_fmt {
));
}
#[test]
fn def_when() {
expr_formats_same(indoc!(
r#"
myLongFunctionName = \x ->
when b is
1 | 2 ->
when c is
6 | 7 ->
8
3 | 4 ->
5
123
"#
));
}
#[test]
#[ignore] // TODO: reformat when-in-function-body with extra newline
fn def_when_with_python_indentation() {
expr_formats_to(
// vvv Currently this input formats to _itself_ :( vvv
// Instead, if the body of the `when` is multiline (the overwhelmingly common case)
// we want to make sure the `when` is at the beginning of the line, inserting
// a newline if necessary.
indoc!(
r#"
myLongFunctionName = \x -> when b is
1 | 2 ->
when c is
6 | 7 ->
8
3 | 4 ->
5
123
"#
),
indoc!(
r#"
myLongFunctionName = \x ->
when b is
1 | 2 ->
when c is
6 | 7 ->
8
3 | 4 ->
5
123
"#
),
);
}
#[test]
fn when_with_alternatives_1() {
expr_formats_same(indoc!(

View file

@ -1398,6 +1398,8 @@ define_builtins! {
75 LIST_WALK_TRY: "walkTry"
76 LIST_WALK_BACKWARDS_UNTIL: "walkBackwardsUntil"
77 LIST_COUNT_IF: "countIf"
78 LIST_WALK_FROM: "walkFrom"
79 LIST_WALK_FROM_UNTIL: "walkFromUntil"
}
7 RESULT: "Result" => {
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
@ -1526,11 +1528,11 @@ define_builtins! {
6 HASH_ADD_U32: "addU32"
7 HASH_ADD_U64: "addU64"
8 HASH_ADD_U128: "addU128"
9 HASH_ADD_I8: "addI8"
10 HASH_ADD_I16: "addI16"
11 HASH_ADD_I32: "addI32"
12 HASH_ADD_I64: "addI64"
13 HASH_ADD_I128: "addI128"
9 HASH_HASH_I8: "hashI8"
10 HASH_HASH_I16: "hashI16"
11 HASH_HASH_I32: "hashI32"
12 HASH_HASH_I64: "hashI64"
13 HASH_HASH_I128: "hashI128"
14 HASH_COMPLETE: "complete"
15 HASH_HASH_STR_BYTES: "hashStrBytes"
16 HASH_HASH_LIST: "hashList"

View file

@ -2080,7 +2080,7 @@ mod when {
/// Parsing when with indentation.
fn when_with_indent<'a>() -> impl Parser<'a, u32, EWhen<'a>> {
move |arena, state: State<'a>| {
let min_indent = state.column();
let min_indent = state.line_indent() + 1;
parser::keyword_e(keyword::WHEN, EWhen::When)
.parse(arena, state)
.map(|(progress, (), state)| (progress, min_indent, state))

View file

@ -0,0 +1,64 @@
Defs(
Defs {
tags: [
Index(2147483648),
],
regions: [
@0-33,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [],
value_defs: [
Body(
@0-4 Identifier(
"func",
),
@7-33 Closure(
[
@8-9 Identifier(
"x",
),
],
@13-33 When(
@18-19 Var {
module_name: "",
ident: "n",
},
[
WhenBranch {
patterns: [
@27-28 SpaceBefore(
NumLiteral(
"0",
),
[
Newline,
],
),
],
value: @32-33 Num(
"0",
),
guard: None,
},
],
),
),
),
],
},
@34-36 SpaceBefore(
Num(
"42",
),
[
Newline,
],
),
)

View file

@ -0,0 +1,3 @@
func = \x -> when n is
0 -> 0
42

View file

@ -284,6 +284,7 @@ mod test_parse {
pass/when_if_guard.expr,
pass/when_in_assignment.expr,
pass/when_in_function.expr,
pass/when_in_function_python_style_indent.expr,
pass/when_in_parens_indented.expr,
pass/when_in_parens.expr,
pass/when_with_alternative_patterns.expr,

View file

@ -66,11 +66,11 @@ fn immediates() {
check_single_lset_immediate(Hash, v!(U32), Symbol::HASH_ADD_U32);
check_single_lset_immediate(Hash, v!(U64), Symbol::HASH_ADD_U64);
check_single_lset_immediate(Hash, v!(U128), Symbol::HASH_ADD_U128);
check_single_lset_immediate(Hash, v!(I8), Symbol::HASH_ADD_I8);
check_single_lset_immediate(Hash, v!(I16), Symbol::HASH_ADD_I16);
check_single_lset_immediate(Hash, v!(I32), Symbol::HASH_ADD_I32);
check_single_lset_immediate(Hash, v!(I64), Symbol::HASH_ADD_I64);
check_single_lset_immediate(Hash, v!(I128), Symbol::HASH_ADD_I128);
check_single_lset_immediate(Hash, v!(I8), Symbol::HASH_HASH_I8);
check_single_lset_immediate(Hash, v!(I16), Symbol::HASH_HASH_I16);
check_single_lset_immediate(Hash, v!(I32), Symbol::HASH_HASH_I32);
check_single_lset_immediate(Hash, v!(I64), Symbol::HASH_HASH_I64);
check_single_lset_immediate(Hash, v!(I128), Symbol::HASH_HASH_I128);
check_single_lset_immediate(Hash, v!(STR), Symbol::HASH_HASH_STR_BYTES);
check_single_lset_immediate(Hash, v!(Symbol::LIST_LIST v!(U8)), Symbol::HASH_HASH_LIST);
check_single_lset_immediate(Hash, v!(Symbol::LIST_LIST v!(STR)), Symbol::HASH_HASH_LIST);

View file

@ -1122,11 +1122,6 @@ mod hash {
addU32: tAddU32,
addU64: tAddU64,
addU128: tAddU128,
addI8: tAddI8,
addI16: tAddI16,
addI32: tAddI32,
addI64: tAddI64,
addI128: tAddI128,
complete: tComplete,
}]
@ -1165,11 +1160,6 @@ mod hash {
tAddU32 = \@THasher total, n -> @THasher (do32 total n)
tAddU64 = \@THasher total, n -> @THasher (do64 total n)
tAddU128 = \@THasher total, n -> @THasher (do128 total n)
tAddI8 = \@THasher total, n -> @THasher (do8 total (Num.toU8 n))
tAddI16 = \@THasher total, n -> @THasher (do16 total (Num.toU16 n))
tAddI32 = \@THasher total, n -> @THasher (do32 total (Num.toU32 n))
tAddI64 = \@THasher total, n -> @THasher (do64 total (Num.toU64 n))
tAddI128 = \@THasher total, n -> @THasher (do128 total (Num.toU128 n))
tComplete = \@THasher _ -> Num.maxU64
tRead = \@THasher bytes -> bytes

View file

@ -956,6 +956,12 @@ fn list_walk_until_even_prefix_sum() {
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_from_sum() {
assert_evals_to!(r#"List.walkFrom [1, 2, 3] 1 0 Num.add"#, 5, i64);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_keep_if_empty_list_of_int() {
@ -3482,16 +3488,6 @@ fn list_let_generalization() {
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_until_sum() {
assert_evals_to!(
r#"List.walkBackwardsUntil [1, 2] 0 \a,b -> Continue (a + b)"#,
3,
i64
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_implements_position() {
@ -3520,6 +3516,16 @@ fn list_walk_backwards_implements_position() {
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_until_sum() {
assert_evals_to!(
r#"List.walkBackwardsUntil [1, 2] 0 \a,b -> Continue (a + b)"#,
3,
i64
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_until_even_prefix_sum() {
@ -3537,3 +3543,31 @@ fn list_walk_backwards_until_even_prefix_sum() {
i64
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_from_until_sum() {
assert_evals_to!(
r#"List.walkFromUntil [1, 2, 3, 4] 2 0 \a,b -> Continue (a + b)"#,
7,
i64
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_from_even_prefix_sum() {
assert_evals_to!(
r#"
helper = \a, b ->
if Num.isEven b then
Continue (a + b)
else
Break a
List.walkFromUntil [2, 4, 8, 9] 1 0 helper"#,
4 + 8,
i64
);
}