mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Merge remote-tracking branch 'origin/gen-equality' into dict-insert
This commit is contained in:
commit
e7efcb74e6
6 changed files with 1495 additions and 149 deletions
|
@ -11,8 +11,7 @@ use crate::llvm::build_str::{
|
|||
str_concat, str_count_graphemes, str_ends_with, str_from_int, str_join_with,
|
||||
str_number_of_bytes, str_split, str_starts_with, CHAR_LAYOUT,
|
||||
};
|
||||
|
||||
use crate::llvm::compare::{build_eq, build_neq};
|
||||
use crate::llvm::compare::{generic_eq, generic_neq};
|
||||
use crate::llvm::convert::{
|
||||
basic_type_from_builtin, basic_type_from_layout, block_of_memory, block_of_memory_slices,
|
||||
collection, get_fn_type, get_ptr_type, ptr_int,
|
||||
|
@ -3860,7 +3859,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let (rhs_arg, rhs_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
build_eq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
generic_eq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
}
|
||||
NotEq => {
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
@ -3868,7 +3867,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let (rhs_arg, rhs_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
build_neq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
generic_neq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
}
|
||||
And => {
|
||||
// The (&&) operator
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::llvm::build::{
|
||||
allocate_with_refcount_help, build_num_binop, cast_basic_basic, Env, InPlace,
|
||||
};
|
||||
use crate::llvm::compare::build_eq;
|
||||
use crate::llvm::compare::generic_eq;
|
||||
use crate::llvm::convert::{basic_type_from_layout, collection, get_ptr_type};
|
||||
use crate::llvm::refcounting::{
|
||||
decrement_refcount_layout, increment_refcount_layout, refcount_is_one_comparison,
|
||||
|
@ -1114,7 +1114,7 @@ pub fn list_contains_help<'a, 'ctx, 'env>(
|
|||
|
||||
let current_elem = builder.build_load(current_elem_ptr, "load_elem");
|
||||
|
||||
let has_found = build_eq(
|
||||
let has_found = generic_eq(
|
||||
env,
|
||||
layout_ids,
|
||||
current_elem,
|
||||
|
|
File diff suppressed because it is too large
Load diff
419
compiler/gen/tests/gen_compare.rs
Normal file
419
compiler/gen/tests/gen_compare.rs
Normal file
|
@ -0,0 +1,419 @@
|
|||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
#[macro_use]
|
||||
extern crate indoc;
|
||||
|
||||
extern crate bumpalo;
|
||||
extern crate inkwell;
|
||||
extern crate libc;
|
||||
extern crate roc_gen;
|
||||
|
||||
#[macro_use]
|
||||
mod helpers;
|
||||
|
||||
#[cfg(test)]
|
||||
mod gen_num {
|
||||
|
||||
#[test]
|
||||
fn eq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : I64
|
||||
i = 1
|
||||
|
||||
i == i
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : I64
|
||||
i = 1
|
||||
|
||||
i != i
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : U64
|
||||
i = 1
|
||||
|
||||
i == i
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : U64
|
||||
i = 1
|
||||
|
||||
i != i
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : F64
|
||||
i = 1
|
||||
|
||||
i == i
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : F64
|
||||
i = 1
|
||||
|
||||
i != i
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
true == True
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
true == False
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_record() {
|
||||
assert_evals_to!("{} == {}", true, bool);
|
||||
assert_evals_to!("{} != {}", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit() {
|
||||
assert_evals_to!("Unit == Unit", true, bool);
|
||||
assert_evals_to!("Unit != Unit", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype() {
|
||||
assert_evals_to!("Identity 42 == Identity 42", true, bool);
|
||||
assert_evals_to!("Identity 42 != Identity 42", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn small_str() {
|
||||
assert_evals_to!("\"aaa\" == \"aaa\"", true, bool);
|
||||
assert_evals_to!("\"aaa\" == \"bbb\"", false, bool);
|
||||
assert_evals_to!("\"aaa\" != \"aaa\"", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn large_str() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x = "Unicode can represent text values which span multiple languages"
|
||||
y = "Unicode can represent text values which span multiple languages"
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x = "Unicode can represent text values which span multiple languages"
|
||||
y = "Here are some valid Roc strings"
|
||||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_result_tag_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Result I64 I64
|
||||
x = Ok 1
|
||||
|
||||
y : Result I64 I64
|
||||
y = Ok 1
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_result_tag_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Result I64 I64
|
||||
x = Ok 1
|
||||
|
||||
y : Result I64 I64
|
||||
y = Err 1
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Var I64 ]
|
||||
|
||||
x : Expr
|
||||
x = Val 0
|
||||
|
||||
y : Expr
|
||||
y = Val 0
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_linked_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
x = Nil
|
||||
|
||||
y : LinkedList I64
|
||||
y = Nil
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
x = Cons 1 Nil
|
||||
|
||||
y : LinkedList I64
|
||||
y = Cons 1 Nil
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
x = Cons 1 (Cons 2 Nil)
|
||||
|
||||
y : LinkedList I64
|
||||
y = Cons 1 (Cons 2 Nil)
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_linked_list_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
x = Cons 1 Nil
|
||||
|
||||
y : LinkedList I64
|
||||
y = Cons 1 (Cons 2 Nil)
|
||||
|
||||
y == x
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_nullable_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Empty ]
|
||||
|
||||
x : Expr
|
||||
x = Val 0
|
||||
|
||||
y : Expr
|
||||
y = Add x x
|
||||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_rosetree() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Rose a : [ Rose (List (Rose a)) ]
|
||||
|
||||
x : Rose I64
|
||||
x = Rose []
|
||||
|
||||
y : Rose I64
|
||||
y = Rose []
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Rose a : [ Rose (List (Rose a)) ]
|
||||
|
||||
x : Rose I64
|
||||
x = Rose []
|
||||
|
||||
y : Rose I64
|
||||
y = Rose []
|
||||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn rosetree_with_tag() {
|
||||
// currently stack overflows in type checking
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Rose a : [ Rose (Result (List (Rose a)) I64) ]
|
||||
|
||||
x : Rose I64
|
||||
x = (Rose (Ok []))
|
||||
|
||||
y : Rose I64
|
||||
y = (Rose (Ok []))
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
}
|
|
@ -741,10 +741,14 @@ define_builtins! {
|
|||
11 DEC: "#dec" // internal function that increments the refcount
|
||||
12 ARG_CLOSURE: "#arg_closure" // symbol used to store the closure record
|
||||
13 LIST_EQ: "#list_eq" // internal function that checks list equality
|
||||
|
||||
14 GENERIC_HASH: "#generic_hash" // hash of arbitrary layouts
|
||||
15 GENERIC_HASH_REF: "#generic_hash_by_ref" // hash of arbitrary layouts, passed as an opaque pointer
|
||||
|
||||
16 GENERIC_EQ_REF: "#generic_eq_by_ref" // equality of arbitrary layouts, passed as an opaque pointer
|
||||
17 GENERIC_RC_REF: "#generic_rc_by_ref" // refcount of arbitrary layouts, passed as an opaque pointer
|
||||
|
||||
18 GENERIC_EQ: "#generic_eq" // internal function that checks generic equality
|
||||
}
|
||||
1 NUM: "Num" => {
|
||||
0 NUM_NUM: "Num" imported // the Num.Num type alias
|
||||
|
|
|
@ -19,6 +19,28 @@ use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder};
|
|||
|
||||
pub const PRETTY_PRINT_IR_SYMBOLS: bool = false;
|
||||
|
||||
macro_rules! return_on_layout_error {
|
||||
($env:expr, $layout_result:expr) => {
|
||||
match $layout_result {
|
||||
Ok(cached) => cached,
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
return Stmt::RuntimeError($env.arena.alloc(format!(
|
||||
"UnresolvedTypeVar {} line {}",
|
||||
file!(),
|
||||
line!()
|
||||
)));
|
||||
}
|
||||
Err(LayoutProblem::Erroneous) => {
|
||||
return Stmt::RuntimeError($env.arena.alloc(format!(
|
||||
"Erroneous {} line {}",
|
||||
file!(),
|
||||
line!()
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum MonoProblem {
|
||||
PatternProblem(crate::exhaustive::Error),
|
||||
|
@ -3790,11 +3812,10 @@ pub fn with_hole<'a>(
|
|||
)
|
||||
.into_bump_slice();
|
||||
|
||||
let full_layout = layout_cache
|
||||
.from_var(env.arena, fn_var, env.subs)
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("TODO turn fn_var into a RuntimeError {:?}", err)
|
||||
});
|
||||
let full_layout = return_on_layout_error!(
|
||||
env,
|
||||
layout_cache.from_var(env.arena, fn_var, env.subs)
|
||||
);
|
||||
|
||||
let arg_layouts = match full_layout {
|
||||
Layout::FunctionPointer(args, _) => args,
|
||||
|
@ -3802,11 +3823,10 @@ pub fn with_hole<'a>(
|
|||
_ => unreachable!("function has layout that is not function pointer"),
|
||||
};
|
||||
|
||||
let ret_layout = layout_cache
|
||||
.from_var(env.arena, ret_var, env.subs)
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("TODO turn fn_var into a RuntimeError {:?}", err)
|
||||
});
|
||||
let ret_layout = return_on_layout_error!(
|
||||
env,
|
||||
layout_cache.from_var(env.arena, ret_var, env.subs)
|
||||
);
|
||||
|
||||
// if the function expression (loc_expr) is already a symbol,
|
||||
// re-use that symbol, and don't define its value again
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue