mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Merge branch 'trunk' into list-eq
This commit is contained in:
commit
ba9448619a
49 changed files with 1440 additions and 4168 deletions
|
@ -29,6 +29,7 @@ pub fn build_file(
|
||||||
) -> Result<PathBuf, LoadingProblem> {
|
) -> Result<PathBuf, LoadingProblem> {
|
||||||
let compilation_start = SystemTime::now();
|
let compilation_start = SystemTime::now();
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
|
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
|
||||||
|
|
||||||
// Step 1: compile the app and generate the .o file
|
// Step 1: compile the app and generate the .o file
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
|
@ -36,7 +37,7 @@ pub fn build_file(
|
||||||
// Release builds use uniqueness optimizations
|
// Release builds use uniqueness optimizations
|
||||||
let stdlib = match opt_level {
|
let stdlib = match opt_level {
|
||||||
OptLevel::Normal => roc_builtins::std::standard_stdlib(),
|
OptLevel::Normal => roc_builtins::std::standard_stdlib(),
|
||||||
OptLevel::Optimize => roc_builtins::unique::uniq_stdlib(),
|
OptLevel::Optimize => roc_builtins::std::standard_stdlib(),
|
||||||
};
|
};
|
||||||
let loaded = roc_load::file::load_and_monomorphize(
|
let loaded = roc_load::file::load_and_monomorphize(
|
||||||
&arena,
|
&arena,
|
||||||
|
@ -44,6 +45,7 @@ pub fn build_file(
|
||||||
stdlib,
|
stdlib,
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
|
ptr_bytes,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let path_to_platform = loaded.platform_path.clone();
|
let path_to_platform = loaded.platform_path.clone();
|
||||||
|
|
|
@ -35,6 +35,8 @@ pub fn gen_and_eval(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<R
|
||||||
|
|
||||||
let module_src = promote_expr_to_module(src_str);
|
let module_src = promote_expr_to_module(src_str);
|
||||||
|
|
||||||
|
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
|
||||||
|
|
||||||
let exposed_types = MutMap::default();
|
let exposed_types = MutMap::default();
|
||||||
let loaded = roc_load::file::load_and_monomorphize_from_str(
|
let loaded = roc_load::file::load_and_monomorphize_from_str(
|
||||||
&arena,
|
&arena,
|
||||||
|
@ -43,6 +45,7 @@ pub fn gen_and_eval(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<R
|
||||||
stdlib,
|
stdlib,
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
|
ptr_bytes,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = loaded.expect("failed to load module");
|
let mut loaded = loaded.expect("failed to load module");
|
||||||
|
|
|
@ -54,22 +54,22 @@ mod repl_eval {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_0x0() {
|
fn literal_0x0() {
|
||||||
expect_success("0x0", "0 : I64");
|
expect_success("0x0", "0 : Int *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_0x42() {
|
fn literal_0x42() {
|
||||||
expect_success("0x42", "66 : I64");
|
expect_success("0x42", "66 : Int *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_0point0() {
|
fn literal_0point0() {
|
||||||
expect_success("0.0", "0 : F64");
|
expect_success("0.0", "0 : Float *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_4point2() {
|
fn literal_4point2() {
|
||||||
expect_success("4.2", "4.2 : F64");
|
expect_success("4.2", "4.2 : Float *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -89,7 +89,7 @@ mod repl_eval {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn num_rem() {
|
fn num_rem() {
|
||||||
expect_success("299 % 10", "Ok 9 : Result I64 [ DivByZero ]*");
|
expect_success("299 % 10", "Ok 9 : Result (Int *) [ DivByZero ]*");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -153,7 +153,7 @@ mod repl_eval {
|
||||||
#[test]
|
#[test]
|
||||||
fn single_element_tag_union() {
|
fn single_element_tag_union() {
|
||||||
expect_success("True 1", "True 1 : [ True (Num *) ]*");
|
expect_success("True 1", "True 1 : [ True (Num *) ]*");
|
||||||
expect_success("Foo 1 3.14", "Foo 1 3.14 : [ Foo (Num *) F64 ]*");
|
expect_success("Foo 1 3.14", "Foo 1 3.14 : [ Foo (Num *) (Float *) ]*");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -162,7 +162,7 @@ mod repl_eval {
|
||||||
|
|
||||||
expect_success(
|
expect_success(
|
||||||
"if 1 == 1 then True 3 else False 3.14",
|
"if 1 == 1 then True 3 else False 3.14",
|
||||||
"True 3 : [ False F64, True (Num *) ]*",
|
"True 3 : [ False (Float *), True (Num *) ]*",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ mod repl_eval {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn str_count_graphemes() {
|
fn str_count_graphemes() {
|
||||||
expect_success("Str.countGraphemes \"å🤔\"", "2 : I64");
|
expect_success("Str.countGraphemes \"å🤔\"", "2 : Int *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -206,12 +206,12 @@ mod repl_eval {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_int_list() {
|
fn literal_int_list() {
|
||||||
expect_success("[ 0x1, 0x2, 0x3 ]", "[ 1, 2, 3 ] : List I64");
|
expect_success("[ 0x1, 0x2, 0x3 ]", "[ 1, 2, 3 ] : List (Int *)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_float_list() {
|
fn literal_float_list() {
|
||||||
expect_success("[ 1.1, 2.2, 3.3 ]", "[ 1.1, 2.2, 3.3 ] : List F64");
|
expect_success("[ 1.1, 2.2, 3.3 ]", "[ 1.1, 2.2, 3.3 ] : List (Float *)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -253,26 +253,26 @@ mod repl_eval {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn num_bitwise_and() {
|
fn num_bitwise_and() {
|
||||||
expect_success("Num.bitwiseAnd 20 20", "20 : I64");
|
expect_success("Num.bitwiseAnd 20 20", "20 : Int *");
|
||||||
|
|
||||||
expect_success("Num.bitwiseAnd 25 10", "8 : I64");
|
expect_success("Num.bitwiseAnd 25 10", "8 : Int *");
|
||||||
|
|
||||||
expect_success("Num.bitwiseAnd 200 0", "0 : I64")
|
expect_success("Num.bitwiseAnd 200 0", "0 : Int *")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn num_add_wrap() {
|
fn num_add_wrap() {
|
||||||
expect_success("Num.addWrap Num.maxInt 1", "-9223372036854775808 : I64");
|
expect_success("Num.addWrap Num.maxInt 1", "-9223372036854775808 : Int *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn num_sub_wrap() {
|
fn num_sub_wrap() {
|
||||||
expect_success("Num.subWrap Num.minInt 1", "9223372036854775807 : I64");
|
expect_success("Num.subWrap Num.minInt 1", "9223372036854775807 : Int *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn num_mul_wrap() {
|
fn num_mul_wrap() {
|
||||||
expect_success("Num.mulWrap Num.maxInt 2", "-2 : I64");
|
expect_success("Num.mulWrap Num.maxInt 2", "-2 : Int *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -309,7 +309,7 @@ mod repl_eval {
|
||||||
fn list_concat() {
|
fn list_concat() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"List.concat [ 1.1, 2.2 ] [ 3.3, 4.4, 5.5 ]",
|
"List.concat [ 1.1, 2.2 ] [ 3.3, 4.4, 5.5 ]",
|
||||||
"[ 1.1, 2.2, 3.3, 4.4, 5.5 ] : List F64",
|
"[ 1.1, 2.2, 3.3, 4.4, 5.5 ] : List (Float *)",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ mod repl_eval {
|
||||||
fn basic_1_field_f64_record() {
|
fn basic_1_field_f64_record() {
|
||||||
// Even though this gets unwrapped at runtime, the repl should still
|
// Even though this gets unwrapped at runtime, the repl should still
|
||||||
// report it as a record
|
// report it as a record
|
||||||
expect_success("{ foo: 4.2 }", "{ foo: 4.2 } : { foo : F64 }");
|
expect_success("{ foo: 4.2 }", "{ foo: 4.2 } : { foo : Float * }");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -387,7 +387,7 @@ mod repl_eval {
|
||||||
// report it as a record
|
// report it as a record
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ foo: { bar: { baz: 4.2 } } }",
|
"{ foo: { bar: { baz: 4.2 } } }",
|
||||||
"{ foo: { bar: { baz: 4.2 } } } : { foo : { bar : { baz : F64 } } }",
|
"{ foo: { bar: { baz: 4.2 } } } : { foo : { bar : { baz : Float * } } }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ mod repl_eval {
|
||||||
fn basic_2_field_i64_record() {
|
fn basic_2_field_i64_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ foo: 0x4, bar: 0x2 }",
|
"{ foo: 0x4, bar: 0x2 }",
|
||||||
"{ bar: 2, foo: 4 } : { bar : I64, foo : I64 }",
|
"{ bar: 2, foo: 4 } : { bar : Int *, foo : Int * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ mod repl_eval {
|
||||||
fn basic_2_field_f64_record() {
|
fn basic_2_field_f64_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ foo: 4.1, bar: 2.3 }",
|
"{ foo: 4.1, bar: 2.3 }",
|
||||||
"{ bar: 2.3, foo: 4.1 } : { bar : F64, foo : F64 }",
|
"{ bar: 2.3, foo: 4.1 } : { bar : Float *, foo : Float * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ mod repl_eval {
|
||||||
fn basic_2_field_mixed_record() {
|
fn basic_2_field_mixed_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ foo: 4.1, bar: 2 }",
|
"{ foo: 4.1, bar: 2 }",
|
||||||
"{ bar: 2, foo: 4.1 } : { bar : Num *, foo : F64 }",
|
"{ bar: 2, foo: 4.1 } : { bar : Num *, foo : Float * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ mod repl_eval {
|
||||||
fn basic_3_field_record() {
|
fn basic_3_field_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ foo: 4.1, bar: 2, baz: 0x5 }",
|
"{ foo: 4.1, bar: 2, baz: 0x5 }",
|
||||||
"{ bar: 2, baz: 5, foo: 4.1 } : { bar : Num *, baz : I64, foo : F64 }",
|
"{ bar: 2, baz: 5, foo: 4.1 } : { bar : Num *, baz : Int *, foo : Float * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +434,7 @@ mod repl_eval {
|
||||||
fn list_of_2_field_records() {
|
fn list_of_2_field_records() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"[ { foo: 4.1, bar: 2 } ]",
|
"[ { foo: 4.1, bar: 2 } ]",
|
||||||
"[ { bar: 2, foo: 4.1 } ] : List { bar : Num *, foo : F64 }",
|
"[ { bar: 2, foo: 4.1 } ] : List { bar : Num *, foo : Float * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +466,7 @@ mod repl_eval {
|
||||||
fn list_of_3_field_records() {
|
fn list_of_3_field_records() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"[ { foo: 4.1, bar: 2, baz: 0x3 } ]",
|
"[ { foo: 4.1, bar: 2, baz: 0x3 } ]",
|
||||||
"[ { bar: 2, baz: 3, foo: 4.1 } ] : List { bar : Num *, baz : I64, foo : F64 }",
|
"[ { bar: 2, baz: 3, foo: 4.1 } ] : List { bar : Num *, baz : Int *, foo : Float * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// addWrap : Int, Int -> Int
|
// addWrap : Int range, Int range -> Int range
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_ADD_WRAP,
|
Symbol::NUM_ADD_WRAP,
|
||||||
top_level_function(vec![int_type(), int_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// sub or (-) : Num a, Num a -> Num a
|
// sub or (-) : Num a, Num a -> Num a
|
||||||
|
@ -106,10 +109,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// subWrap : Int, Int -> Int
|
// subWrap : Int range, Int range -> Int range
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_SUB_WRAP,
|
Symbol::NUM_SUB_WRAP,
|
||||||
top_level_function(vec![int_type(), int_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// subChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
|
// subChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
|
||||||
|
@ -130,10 +136,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// mulWrap : Int, Int -> Int
|
// mulWrap : Int range, Int range -> Int range
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_MUL_WRAP,
|
Symbol::NUM_MUL_WRAP,
|
||||||
top_level_function(vec![int_type(), int_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
|
// mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
|
||||||
|
@ -214,10 +223,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// toFloat : Num a -> Float
|
// toFloat : Num * -> Float *
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_TO_FLOAT,
|
Symbol::NUM_TO_FLOAT,
|
||||||
top_level_function(vec![num_type(flex(TVAR1))], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![num_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR2))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// isNegative : Num a -> Bool
|
// isNegative : Num a -> Bool
|
||||||
|
@ -250,11 +262,11 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
top_level_function(vec![num_type(flex(TVAR1))], Box::new(bool_type())),
|
top_level_function(vec![num_type(flex(TVAR1))], Box::new(bool_type())),
|
||||||
);
|
);
|
||||||
|
|
||||||
// maxInt : Int
|
// maxInt : Int range
|
||||||
add_type(Symbol::NUM_MAX_INT, int_type());
|
add_type(Symbol::NUM_MAX_INT, int_type(flex(TVAR1)));
|
||||||
|
|
||||||
// minInt : Int
|
// minInt : Int range
|
||||||
add_type(Symbol::NUM_MIN_INT, int_type());
|
add_type(Symbol::NUM_MIN_INT, int_type(flex(TVAR1)));
|
||||||
|
|
||||||
// div : Int, Int -> Result Int [ DivByZero ]*
|
// div : Int, Int -> Result Int [ DivByZero ]*
|
||||||
let div_by_zero = SolvedType::TagUnion(
|
let div_by_zero = SolvedType::TagUnion(
|
||||||
|
@ -265,56 +277,59 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_DIV_INT,
|
Symbol::NUM_DIV_INT,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![int_type(), int_type()],
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
Box::new(result_type(int_type(), div_by_zero.clone())),
|
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// bitwiseAnd : Int, Int -> Int
|
// bitwiseAnd : Int a, Int a -> Int a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_BITWISE_AND,
|
Symbol::NUM_BITWISE_AND,
|
||||||
top_level_function(vec![int_type(), int_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// rem : Int, Int -> Result Int [ DivByZero ]*
|
// rem : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_REM,
|
Symbol::NUM_REM,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![int_type(), int_type()],
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
Box::new(result_type(int_type(), div_by_zero.clone())),
|
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// mod : Int, Int -> Result Int [ DivByZero ]*
|
// mod : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_MOD_INT,
|
Symbol::NUM_MOD_INT,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![int_type(), int_type()],
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
Box::new(result_type(int_type(), div_by_zero.clone())),
|
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Float module
|
// Float module
|
||||||
|
|
||||||
// div : Float, Float -> Float
|
// div : Float a, Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_DIV_FLOAT,
|
Symbol::NUM_DIV_FLOAT,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![float_type(), float_type()],
|
vec![float_type(flex(TVAR1)), float_type(flex(TVAR1))],
|
||||||
Box::new(result_type(float_type(), div_by_zero.clone())),
|
Box::new(result_type(float_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// mod : Float, Float -> Result Int [ DivByZero ]*
|
// mod : Float a, Float a -> Result (Float a) [ DivByZero ]*
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_MOD_FLOAT,
|
Symbol::NUM_MOD_FLOAT,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![float_type(), float_type()],
|
vec![float_type(flex(TVAR1)), float_type(flex(TVAR1))],
|
||||||
Box::new(result_type(float_type(), div_by_zero)),
|
Box::new(result_type(float_type(flex(TVAR1)), div_by_zero)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// sqrt : Float -> Float
|
// sqrt : Float a -> Float a
|
||||||
let sqrt_of_negative = SolvedType::TagUnion(
|
let sqrt_of_negative = SolvedType::TagUnion(
|
||||||
vec![(TagName::Global("SqrtOfNegative".into()), vec![])],
|
vec![(TagName::Global("SqrtOfNegative".into()), vec![])],
|
||||||
Box::new(SolvedType::Wildcard),
|
Box::new(SolvedType::Wildcard),
|
||||||
|
@ -323,81 +338,114 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_SQRT,
|
Symbol::NUM_SQRT,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![float_type()],
|
vec![float_type(flex(TVAR1))],
|
||||||
Box::new(result_type(float_type(), sqrt_of_negative)),
|
Box::new(result_type(float_type(flex(TVAR1)), sqrt_of_negative)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// round : Float -> Int
|
// round : Float a -> Int b
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_ROUND,
|
Symbol::NUM_ROUND,
|
||||||
top_level_function(vec![float_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR2))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// sin : Float -> Float
|
// sin : Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_SIN,
|
Symbol::NUM_SIN,
|
||||||
top_level_function(vec![float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// cos : Float -> Float
|
// cos : Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_COS,
|
Symbol::NUM_COS,
|
||||||
top_level_function(vec![float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// tan : Float -> Float
|
// tan : Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_TAN,
|
Symbol::NUM_TAN,
|
||||||
top_level_function(vec![float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// maxFloat : Float
|
// maxFloat : Float a
|
||||||
add_type(Symbol::NUM_MAX_FLOAT, float_type());
|
add_type(Symbol::NUM_MAX_FLOAT, float_type(flex(TVAR1)));
|
||||||
|
|
||||||
// minFloat : Float
|
// minFloat : Float a
|
||||||
add_type(Symbol::NUM_MIN_FLOAT, float_type());
|
add_type(Symbol::NUM_MIN_FLOAT, float_type(flex(TVAR1)));
|
||||||
|
|
||||||
// pow : Float, Float -> Float
|
// pow : Float a, Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_POW,
|
Symbol::NUM_POW,
|
||||||
top_level_function(vec![float_type(), float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1)), float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ceiling : Float -> Int
|
// ceiling : Float a -> Int b
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_CEILING,
|
Symbol::NUM_CEILING,
|
||||||
top_level_function(vec![float_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR2))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// powInt : Int, Int -> Int
|
// powInt : Int a, Int a -> Int a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_POW_INT,
|
Symbol::NUM_POW_INT,
|
||||||
top_level_function(vec![int_type(), int_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// floor : Float -> Int
|
// floor : Float a -> Int b
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_FLOOR,
|
Symbol::NUM_FLOOR,
|
||||||
top_level_function(vec![float_type()], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR2))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// atan : Float -> Float
|
// atan : Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_ATAN,
|
Symbol::NUM_ATAN,
|
||||||
top_level_function(vec![float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// acos : Float -> Float
|
// acos : Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_ACOS,
|
Symbol::NUM_ACOS,
|
||||||
top_level_function(vec![float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// asin : Float -> Float
|
// asin : Float a -> Float a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::NUM_ASIN,
|
Symbol::NUM_ASIN,
|
||||||
top_level_function(vec![float_type()], Box::new(float_type())),
|
top_level_function(
|
||||||
|
vec![float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Bool module
|
// Bool module
|
||||||
|
@ -461,16 +509,16 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
top_level_function(vec![str_type(), str_type()], Box::new(bool_type())),
|
top_level_function(vec![str_type(), str_type()], Box::new(bool_type())),
|
||||||
);
|
);
|
||||||
|
|
||||||
// countGraphemes : Str -> Int
|
// countGraphemes : Str -> Int a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::STR_COUNT_GRAPHEMES,
|
Symbol::STR_COUNT_GRAPHEMES,
|
||||||
top_level_function(vec![str_type()], Box::new(int_type())),
|
top_level_function(vec![str_type()], Box::new(int_type(flex(TVAR1)))),
|
||||||
);
|
);
|
||||||
|
|
||||||
// fromInt : Int -> Str
|
// fromInt : Int a -> Str
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::STR_FROM_INT,
|
Symbol::STR_FROM_INT,
|
||||||
top_level_function(vec![int_type()], Box::new(str_type())),
|
top_level_function(vec![int_type(flex(TVAR1))], Box::new(str_type())),
|
||||||
);
|
);
|
||||||
|
|
||||||
// List module
|
// List module
|
||||||
|
@ -484,7 +532,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::LIST_GET,
|
Symbol::LIST_GET,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![list_type(flex(TVAR1)), int_type()],
|
vec![list_type(flex(TVAR1)), int_type(flex(TVAR2))],
|
||||||
Box::new(result_type(flex(TVAR1), index_out_of_bounds)),
|
Box::new(result_type(flex(TVAR1), index_out_of_bounds)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -512,11 +560,11 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// set : List elem, Int, elem -> List elem
|
// set : List elem, Int a, elem -> List elem
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::LIST_SET,
|
Symbol::LIST_SET,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![list_type(flex(TVAR1)), int_type(), flex(TVAR1)],
|
vec![list_type(flex(TVAR1)), int_type(flex(TVAR2)), flex(TVAR1)],
|
||||||
Box::new(list_type(flex(TVAR1))),
|
Box::new(list_type(flex(TVAR1))),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -631,11 +679,11 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
top_level_function(vec![flex(TVAR1)], Box::new(list_type(flex(TVAR1)))),
|
top_level_function(vec![flex(TVAR1)], Box::new(list_type(flex(TVAR1)))),
|
||||||
);
|
);
|
||||||
|
|
||||||
// repeat : Int, elem -> List elem
|
// repeat : Int a, elem -> List elem
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::LIST_REPEAT,
|
Symbol::LIST_REPEAT,
|
||||||
top_level_function(
|
top_level_function(
|
||||||
vec![int_type(), flex(TVAR1)],
|
vec![int_type(flex(TVAR1)), flex(TVAR2)],
|
||||||
Box::new(list_type(flex(TVAR1))),
|
Box::new(list_type(flex(TVAR1))),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -649,10 +697,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// len : List * -> Int
|
// len : List * -> Int a
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::LIST_LEN,
|
Symbol::LIST_LEN,
|
||||||
top_level_function(vec![list_type(flex(TVAR1))], Box::new(int_type())),
|
top_level_function(
|
||||||
|
vec![list_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR2))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// isEmpty : List * -> Bool
|
// isEmpty : List * -> Bool
|
||||||
|
|
|
@ -166,8 +166,8 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// addWrap : Int, Int -> Int
|
// addWrap : Int, Int -> Int
|
||||||
add_type(Symbol::NUM_ADD_WRAP, {
|
add_type(Symbol::NUM_ADD_WRAP, {
|
||||||
let_tvars! { u, v, w };
|
let_tvars! { u, v, w, int };
|
||||||
unique_function(vec![int_type(u), int_type(v)], int_type(w))
|
unique_function(vec![int_type(u, int), int_type(v, int)], int_type(w, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
// sub or (-) : Num a, Num a -> Num a
|
// sub or (-) : Num a, Num a -> Num a
|
||||||
|
@ -199,8 +199,8 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// mulWrap : Int, Int -> Int
|
// mulWrap : Int, Int -> Int
|
||||||
add_type(Symbol::NUM_MUL_WRAP, {
|
add_type(Symbol::NUM_MUL_WRAP, {
|
||||||
let_tvars! { u, v, w };
|
let_tvars! { u, v, w , int };
|
||||||
unique_function(vec![int_type(u), int_type(v)], int_type(w))
|
unique_function(vec![int_type(u, int), int_type(v, int)], int_type(w, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
// mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
|
// mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
|
||||||
|
@ -257,38 +257,41 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// rem : Attr * Int, Attr * Int -> Attr * (Result (Attr * Int) (Attr * [ DivByZero ]*))
|
// rem : Attr * Int, Attr * Int -> Attr * (Result (Attr * Int) (Attr * [ DivByZero ]*))
|
||||||
add_type(Symbol::NUM_REM, {
|
add_type(Symbol::NUM_REM, {
|
||||||
let_tvars! { star1, star2, star3, star4, star5 };
|
let_tvars! { star1, star2, star3, star4, star5, int };
|
||||||
unique_function(
|
unique_function(
|
||||||
vec![int_type(star1), int_type(star2)],
|
vec![int_type(star1, int), int_type(star2, int)],
|
||||||
result_type(star3, int_type(star4), lift(star5, div_by_zero())),
|
result_type(star3, int_type(star4, int), lift(star5, div_by_zero())),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// maxInt : Int
|
// maxInt : Int
|
||||||
add_type(Symbol::NUM_MAX_INT, {
|
add_type(Symbol::NUM_MAX_INT, {
|
||||||
let_tvars! { star };
|
let_tvars! { star, int };
|
||||||
int_type(star)
|
int_type(star, int)
|
||||||
});
|
});
|
||||||
|
|
||||||
// minInt : Int
|
// minInt : Int
|
||||||
add_type(Symbol::NUM_MIN_INT, {
|
add_type(Symbol::NUM_MIN_INT, {
|
||||||
let_tvars! { star };
|
let_tvars! { star, int };
|
||||||
int_type(star)
|
int_type(star, int)
|
||||||
});
|
});
|
||||||
|
|
||||||
// divFloor or (//) : Int, Int -> Result Int [ DivByZero ]*
|
// divFloor or (//) : Int, Int -> Result Int [ DivByZero ]*
|
||||||
add_type(Symbol::NUM_DIV_INT, {
|
add_type(Symbol::NUM_DIV_INT, {
|
||||||
let_tvars! { star1, star2, star3, star4, star5 };
|
let_tvars! { star1, star2, star3, star4, star5, int };
|
||||||
unique_function(
|
unique_function(
|
||||||
vec![int_type(star1), int_type(star2)],
|
vec![int_type(star1, int), int_type(star2, int)],
|
||||||
result_type(star3, int_type(star4), lift(star5, div_by_zero())),
|
result_type(star3, int_type(star4, int), lift(star5, div_by_zero())),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// bitwiseAnd : Attr * Int, Attr * Int -> Attr * Int
|
// bitwiseAnd : Attr * Int, Attr * Int -> Attr * Int
|
||||||
add_type(Symbol::NUM_BITWISE_AND, {
|
add_type(Symbol::NUM_BITWISE_AND, {
|
||||||
let_tvars! { star1, star2, star3 };
|
let_tvars! { star1, star2, star3, int };
|
||||||
unique_function(vec![int_type(star1), int_type(star2)], int_type(star3))
|
unique_function(
|
||||||
|
vec![int_type(star1, int), int_type(star2, int)],
|
||||||
|
int_type(star3, int),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// divFloat : Float, Float -> Float
|
// divFloat : Float, Float -> Float
|
||||||
|
@ -302,8 +305,8 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// round : Float -> Int
|
// round : Float -> Int
|
||||||
add_type(Symbol::NUM_ROUND, {
|
add_type(Symbol::NUM_ROUND, {
|
||||||
let_tvars! { star1, star2 };
|
let_tvars! { star1, star2, int };
|
||||||
unique_function(vec![float_type(star1)], int_type(star2))
|
unique_function(vec![float_type(star1)], int_type(star2, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
// sqrt : Float -> Float
|
// sqrt : Float -> Float
|
||||||
|
@ -391,20 +394,23 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// ceiling : Float -> Int
|
// ceiling : Float -> Int
|
||||||
add_type(Symbol::NUM_CEILING, {
|
add_type(Symbol::NUM_CEILING, {
|
||||||
let_tvars! { star1, star2 };
|
let_tvars! { star1, star2, int };
|
||||||
unique_function(vec![float_type(star1)], int_type(star2))
|
unique_function(vec![float_type(star1)], int_type(star2, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
// powInt : Int, Int -> Int
|
// powInt : Int, Int -> Int
|
||||||
add_type(Symbol::NUM_POW_INT, {
|
add_type(Symbol::NUM_POW_INT, {
|
||||||
let_tvars! { star1, star2, star3 };
|
let_tvars! { star1, star2, star3 , int };
|
||||||
unique_function(vec![int_type(star1), int_type(star2)], int_type(star3))
|
unique_function(
|
||||||
|
vec![int_type(star1, int), int_type(star2, int)],
|
||||||
|
int_type(star3, int),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// floor : Float -> Int
|
// floor : Float -> Int
|
||||||
add_type(Symbol::NUM_FLOOR, {
|
add_type(Symbol::NUM_FLOOR, {
|
||||||
let_tvars! { star1, star2 };
|
let_tvars! { star1, star2 , int};
|
||||||
unique_function(vec![float_type(star1)], int_type(star2))
|
unique_function(vec![float_type(star1)], int_type(star2, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
// atan : Float -> Float
|
// atan : Float -> Float
|
||||||
|
@ -479,8 +485,8 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// len : Attr * (List *) -> Attr * Int
|
// len : Attr * (List *) -> Attr * Int
|
||||||
add_type(Symbol::LIST_LEN, {
|
add_type(Symbol::LIST_LEN, {
|
||||||
let_tvars! { star1, a, star2 };
|
let_tvars! { star1, a, star2 , int };
|
||||||
unique_function(vec![list_type(star1, a)], int_type(star2))
|
unique_function(vec![list_type(star1, a)], int_type(star2, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
fn list_was_empty() -> SolvedType {
|
fn list_was_empty() -> SolvedType {
|
||||||
|
@ -536,7 +542,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
);
|
);
|
||||||
|
|
||||||
add_type(Symbol::LIST_GET, {
|
add_type(Symbol::LIST_GET, {
|
||||||
let_tvars! { a, u, star1, star2, star3, star4 };
|
let_tvars! { a, u, star1, star2, star3, star4, int};
|
||||||
|
|
||||||
unique_function(
|
unique_function(
|
||||||
vec![
|
vec![
|
||||||
|
@ -547,7 +553,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]),
|
SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
int_type(star2),
|
int_type(star2, int),
|
||||||
],
|
],
|
||||||
result_type(star3, attr_type(u, a), lift(star4, index_out_of_bounds)),
|
result_type(star3, attr_type(u, a), lift(star4, index_out_of_bounds)),
|
||||||
)
|
)
|
||||||
|
@ -559,7 +565,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
// Attr (u | v) a
|
// Attr (u | v) a
|
||||||
// -> Attr * (List (Attr u a))
|
// -> Attr * (List (Attr u a))
|
||||||
add_type(Symbol::LIST_SET, {
|
add_type(Symbol::LIST_SET, {
|
||||||
let_tvars! { u, v, w, star1, star2, a };
|
let_tvars! { u, v, w, star1, star2, a, int};
|
||||||
|
|
||||||
unique_function(
|
unique_function(
|
||||||
vec![
|
vec![
|
||||||
|
@ -570,7 +576,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]),
|
SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
int_type(star1),
|
int_type(star1, int),
|
||||||
SolvedType::Apply(Symbol::ATTR_ATTR, vec![container(u, vec![v]), flex(a)]),
|
SolvedType::Apply(Symbol::ATTR_ATTR, vec![container(u, vec![v]), flex(a)]),
|
||||||
],
|
],
|
||||||
SolvedType::Apply(
|
SolvedType::Apply(
|
||||||
|
@ -627,10 +633,10 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
// , Attr Shared a
|
// , Attr Shared a
|
||||||
// -> Attr * (List (Attr Shared a))
|
// -> Attr * (List (Attr Shared a))
|
||||||
add_type(Symbol::LIST_REPEAT, {
|
add_type(Symbol::LIST_REPEAT, {
|
||||||
let_tvars! { a, star1, star2 };
|
let_tvars! { a, star1, star2, int };
|
||||||
|
|
||||||
unique_function(
|
unique_function(
|
||||||
vec![int_type(star1), shared(flex(a))],
|
vec![int_type(star1, int), shared(flex(a))],
|
||||||
SolvedType::Apply(
|
SolvedType::Apply(
|
||||||
Symbol::ATTR_ATTR,
|
Symbol::ATTR_ATTR,
|
||||||
vec![
|
vec![
|
||||||
|
@ -1162,14 +1168,14 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
|
|
||||||
// Str.countGraphemes : Attr * Str, -> Attr * Int
|
// Str.countGraphemes : Attr * Str, -> Attr * Int
|
||||||
add_type(Symbol::STR_COUNT_GRAPHEMES, {
|
add_type(Symbol::STR_COUNT_GRAPHEMES, {
|
||||||
let_tvars! { star1, star2 };
|
let_tvars! { star1, star2, int };
|
||||||
unique_function(vec![str_type(star1)], int_type(star2))
|
unique_function(vec![str_type(star1)], int_type(star2, int))
|
||||||
});
|
});
|
||||||
|
|
||||||
// fromInt : Attr * Int -> Attr * Str
|
// fromInt : Attr * Int -> Attr * Str
|
||||||
add_type(Symbol::STR_FROM_INT, {
|
add_type(Symbol::STR_FROM_INT, {
|
||||||
let_tvars! { star1, star2 };
|
let_tvars! { star1, star2, int };
|
||||||
unique_function(vec![int_type(star1)], str_type(star2))
|
unique_function(vec![int_type(star1, int)], str_type(star2))
|
||||||
});
|
});
|
||||||
|
|
||||||
// Result module
|
// Result module
|
||||||
|
@ -1242,9 +1248,8 @@ fn lift(u: VarId, a: SolvedType) -> SolvedType {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn float_type(u: VarId) -> SolvedType {
|
fn float_type(u: VarId) -> SolvedType {
|
||||||
let b_64 = builtin_aliases::binary64_type();
|
let inner_type = lift(u, flex(u));
|
||||||
let attr_b_64 = lift(u, b_64);
|
let fp = builtin_aliases::floatingpoint_type(inner_type.clone());
|
||||||
let fp = builtin_aliases::floatingpoint_type(attr_b_64);
|
|
||||||
let attr_fb = lift(u, fp);
|
let attr_fb = lift(u, fp);
|
||||||
let num = builtin_aliases::num_type(attr_fb);
|
let num = builtin_aliases::num_type(attr_fb);
|
||||||
|
|
||||||
|
@ -1252,16 +1257,19 @@ fn float_type(u: VarId) -> SolvedType {
|
||||||
Symbol::ATTR_ATTR,
|
Symbol::ATTR_ATTR,
|
||||||
vec![
|
vec![
|
||||||
flex(u),
|
flex(u),
|
||||||
SolvedType::Alias(Symbol::NUM_F64, Vec::new(), Box::new(num)),
|
SolvedType::Alias(
|
||||||
|
Symbol::NUM_FLOAT,
|
||||||
|
vec![("range".into(), inner_type)],
|
||||||
|
Box::new(num),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn int_type(u: VarId) -> SolvedType {
|
fn int_type(u: VarId, range: VarId) -> SolvedType {
|
||||||
let signed_64 = builtin_aliases::signed64_type();
|
let inner_type = lift(u, flex(range));
|
||||||
let attr_signed_64 = lift(u, signed_64);
|
let integer = builtin_aliases::integer_type(inner_type.clone());
|
||||||
let integer = builtin_aliases::integer_type(attr_signed_64);
|
|
||||||
let attr_fb = lift(u, integer);
|
let attr_fb = lift(u, integer);
|
||||||
let num = builtin_aliases::num_type(attr_fb);
|
let num = builtin_aliases::num_type(attr_fb);
|
||||||
|
|
||||||
|
@ -1269,7 +1277,11 @@ fn int_type(u: VarId) -> SolvedType {
|
||||||
Symbol::ATTR_ATTR,
|
Symbol::ATTR_ATTR,
|
||||||
vec![
|
vec![
|
||||||
flex(u),
|
flex(u),
|
||||||
SolvedType::Alias(Symbol::NUM_I64, Vec::new(), Box::new(num)),
|
SolvedType::Alias(
|
||||||
|
Symbol::NUM_INT,
|
||||||
|
vec![("range".into(), inner_type)],
|
||||||
|
Box::new(num),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,7 +212,8 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
|
||||||
/// Num.maxInt : Int
|
/// Num.maxInt : Int
|
||||||
fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let int_var = var_store.fresh();
|
let int_var = var_store.fresh();
|
||||||
let body = Int(int_var, i64::MAX);
|
let int_percision_var = var_store.fresh();
|
||||||
|
let body = Int(int_var, int_percision_var, i64::MAX);
|
||||||
|
|
||||||
Def {
|
Def {
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -226,7 +227,8 @@ fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
/// Num.minInt : Int
|
/// Num.minInt : Int
|
||||||
fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let int_var = var_store.fresh();
|
let int_var = var_store.fresh();
|
||||||
let body = Int(int_var, i64::MIN);
|
let int_percision_var = var_store.fresh();
|
||||||
|
let body = Int(int_var, int_percision_var, i64::MIN);
|
||||||
|
|
||||||
Def {
|
Def {
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -846,7 +848,7 @@ fn num_is_odd(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::Eq,
|
op: LowLevel::Eq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(arg_var, Int(var_store.fresh(), 1)),
|
(arg_var, Int(var_store.fresh(), var_store.fresh(), 1)),
|
||||||
(
|
(
|
||||||
arg_var,
|
arg_var,
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
|
@ -930,6 +932,7 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let float_var = var_store.fresh();
|
let float_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
|
let percision_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -943,7 +946,7 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(float_var, Var(Symbol::ARG_1)),
|
(float_var, Var(Symbol::ARG_1)),
|
||||||
(float_var, Float(unbound_zero_var, 0.0)),
|
(float_var, Float(unbound_zero_var, percision_var, 0.0)),
|
||||||
],
|
],
|
||||||
ret_var: bool_var,
|
ret_var: bool_var,
|
||||||
},
|
},
|
||||||
|
@ -1896,6 +1899,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
|
let percision_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -1909,7 +1913,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(num_var, Var(Symbol::ARG_2)),
|
(num_var, Var(Symbol::ARG_2)),
|
||||||
(num_var, Float(unbound_zero_var, 0.0)),
|
(num_var, Float(unbound_zero_var, percision_var, 0.0)),
|
||||||
],
|
],
|
||||||
ret_var: bool_var,
|
ret_var: bool_var,
|
||||||
},
|
},
|
||||||
|
@ -1958,6 +1962,7 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
|
let unbound_zero_percision_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -1971,7 +1976,10 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(num_var, Var(Symbol::ARG_2)),
|
(num_var, Var(Symbol::ARG_2)),
|
||||||
(num_var, Int(unbound_zero_var, 0)),
|
(
|
||||||
|
num_var,
|
||||||
|
Int(unbound_zero_var, unbound_zero_percision_var, 0),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
ret_var: bool_var,
|
ret_var: bool_var,
|
||||||
},
|
},
|
||||||
|
@ -2025,6 +2033,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let list_var = var_store.fresh();
|
let list_var = var_store.fresh();
|
||||||
let len_var = var_store.fresh();
|
let len_var = var_store.fresh();
|
||||||
let zero_var = var_store.fresh();
|
let zero_var = var_store.fresh();
|
||||||
|
let zero_percision_var = var_store.fresh();
|
||||||
let list_elem_var = var_store.fresh();
|
let list_elem_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
|
@ -2039,7 +2048,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(len_var, Int(zero_var, 0)),
|
(len_var, Int(zero_var, zero_percision_var, 0)),
|
||||||
(
|
(
|
||||||
len_var,
|
len_var,
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
|
@ -2061,7 +2070,10 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
// List.#getUnsafe list 0
|
// List.#getUnsafe list 0
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
op: LowLevel::ListGetUnsafe,
|
op: LowLevel::ListGetUnsafe,
|
||||||
args: vec![(list_var, Var(Symbol::ARG_1)), (len_var, Int(zero_var, 0))],
|
args: vec![
|
||||||
|
(list_var, Var(Symbol::ARG_1)),
|
||||||
|
(len_var, Int(zero_var, zero_percision_var, 0)),
|
||||||
|
],
|
||||||
ret_var: list_elem_var,
|
ret_var: list_elem_var,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -2102,6 +2114,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let list_var = var_store.fresh();
|
let list_var = var_store.fresh();
|
||||||
let len_var = var_store.fresh();
|
let len_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
|
let num_percision_var = var_store.fresh();
|
||||||
let list_elem_var = var_store.fresh();
|
let list_elem_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
|
@ -2116,7 +2129,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(len_var, Int(num_var, 0)),
|
(len_var, Int(num_var, num_percision_var, 0)),
|
||||||
(
|
(
|
||||||
len_var,
|
len_var,
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
|
@ -2155,7 +2168,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
ret_var: len_var,
|
ret_var: len_var,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(arg_var, Int(num_var, 1)),
|
(arg_var, Int(num_var, num_percision_var, 1)),
|
||||||
],
|
],
|
||||||
ret_var: len_var,
|
ret_var: len_var,
|
||||||
},
|
},
|
||||||
|
|
|
@ -735,8 +735,8 @@ fn pattern_to_vars_by_symbol(
|
||||||
}
|
}
|
||||||
|
|
||||||
NumLiteral(_, _)
|
NumLiteral(_, _)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
@ -864,7 +864,9 @@ fn canonicalize_pending_def<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Alias { name, ann, vars } => {
|
Alias {
|
||||||
|
name, ann, vars, ..
|
||||||
|
} => {
|
||||||
let symbol = name.value;
|
let symbol = name.value;
|
||||||
let can_ann = canonicalize_annotation(env, scope, &ann.value, ann.region, var_store);
|
let can_ann = canonicalize_annotation(env, scope, &ann.value, ann.region, var_store);
|
||||||
|
|
||||||
|
@ -1407,7 +1409,9 @@ fn to_pending_def<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Alias { name, vars, ann } => {
|
Alias {
|
||||||
|
name, vars, ann, ..
|
||||||
|
} => {
|
||||||
let region = Region::span_across(&name.region, &ann.region);
|
let region = Region::span_across(&name.region, &ann.region);
|
||||||
|
|
||||||
match scope.introduce(
|
match scope.introduce(
|
||||||
|
|
|
@ -56,8 +56,8 @@ pub enum Expr {
|
||||||
Num(Variable, i64),
|
Num(Variable, i64),
|
||||||
|
|
||||||
// Int and Float store a variable to generate better error messages
|
// Int and Float store a variable to generate better error messages
|
||||||
Int(Variable, i64),
|
Int(Variable, Variable, i64),
|
||||||
Float(Variable, f64),
|
Float(Variable, Variable, f64),
|
||||||
Str(InlinableString),
|
Str(InlinableString),
|
||||||
List {
|
List {
|
||||||
list_var: Variable, // required for uniqueness of the list
|
list_var: Variable, // required for uniqueness of the list
|
||||||
|
@ -1168,8 +1168,8 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
// Num stores the `a` variable in `Num a`. Not the same as the variable
|
// Num stores the `a` variable in `Num a`. Not the same as the variable
|
||||||
// stored in Int and Float below, which is strictly for better error messages
|
// stored in Int and Float below, which is strictly for better error messages
|
||||||
other @ Num(_, _)
|
other @ Num(_, _)
|
||||||
| other @ Int(_, _)
|
| other @ Int(_, _, _)
|
||||||
| other @ Float(_, _)
|
| other @ Float(_, _, _)
|
||||||
| other @ Str { .. }
|
| other @ Str { .. }
|
||||||
| other @ RuntimeError(_)
|
| other @ RuntimeError(_)
|
||||||
| other @ EmptyRecord
|
| other @ EmptyRecord
|
||||||
|
|
|
@ -363,8 +363,8 @@ fn fix_values_captured_in_closure_pattern(
|
||||||
}
|
}
|
||||||
Identifier(_)
|
Identifier(_)
|
||||||
| NumLiteral(_, _)
|
| NumLiteral(_, _)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(_, _)
|
| Shadowed(_, _)
|
||||||
|
@ -414,8 +414,8 @@ fn fix_values_captured_in_closure_expr(
|
||||||
}
|
}
|
||||||
|
|
||||||
Num(_, _)
|
Num(_, _)
|
||||||
| Int(_, _)
|
| Int(_, _, _)
|
||||||
| Float(_, _)
|
| Float(_, _, _)
|
||||||
| Str(_)
|
| Str(_)
|
||||||
| Var(_)
|
| Var(_)
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub fn int_expr_from_result(
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
// Int stores a variable to generate better error messages
|
// Int stores a variable to generate better error messages
|
||||||
match result {
|
match result {
|
||||||
Ok(int) => Expr::Int(var_store.fresh(), int),
|
Ok(int) => Expr::Int(var_store.fresh(), var_store.fresh(), int),
|
||||||
Err((raw, error)) => {
|
Err((raw, error)) => {
|
||||||
let runtime_error = InvalidInt(error, base, region, raw.into());
|
let runtime_error = InvalidInt(error, base, region, raw.into());
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ pub fn float_expr_from_result(
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
// Float stores a variable to generate better error messages
|
// Float stores a variable to generate better error messages
|
||||||
match result {
|
match result {
|
||||||
Ok(float) => Expr::Float(var_store.fresh(), float),
|
Ok(float) => Expr::Float(var_store.fresh(), var_store.fresh(), float),
|
||||||
Err((raw, error)) => {
|
Err((raw, error)) => {
|
||||||
let runtime_error = InvalidFloat(error, region, raw.into());
|
let runtime_error = InvalidFloat(error, region, raw.into());
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ pub enum Pattern {
|
||||||
ext_var: Variable,
|
ext_var: Variable,
|
||||||
destructs: Vec<Located<RecordDestruct>>,
|
destructs: Vec<Located<RecordDestruct>>,
|
||||||
},
|
},
|
||||||
IntLiteral(i64),
|
IntLiteral(Variable, i64),
|
||||||
NumLiteral(Variable, i64),
|
NumLiteral(Variable, i64),
|
||||||
FloatLiteral(f64),
|
FloatLiteral(Variable, f64),
|
||||||
StrLiteral(Box<str>),
|
StrLiteral(Box<str>),
|
||||||
Underscore,
|
Underscore,
|
||||||
|
|
||||||
|
@ -86,8 +86,8 @@ pub fn symbols_from_pattern_help(pattern: &Pattern, symbols: &mut Vec<Symbol>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NumLiteral(_, _)
|
NumLiteral(_, _)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
@ -191,7 +191,7 @@ pub fn canonicalize_pattern<'a>(
|
||||||
let problem = MalformedPatternProblem::MalformedFloat;
|
let problem = MalformedPatternProblem::MalformedFloat;
|
||||||
malformed_pattern(env, problem, region)
|
malformed_pattern(env, problem, region)
|
||||||
}
|
}
|
||||||
Ok(float) => Pattern::FloatLiteral(float),
|
Ok(float) => Pattern::FloatLiteral(var_store.fresh(), float),
|
||||||
},
|
},
|
||||||
ptype => unsupported_pattern(env, ptype, region),
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
},
|
},
|
||||||
|
@ -224,9 +224,9 @@ pub fn canonicalize_pattern<'a>(
|
||||||
}
|
}
|
||||||
Ok(int) => {
|
Ok(int) => {
|
||||||
if *is_negative {
|
if *is_negative {
|
||||||
Pattern::IntLiteral(-int)
|
Pattern::IntLiteral(var_store.fresh(), -int)
|
||||||
} else {
|
} else {
|
||||||
Pattern::IntLiteral(int)
|
Pattern::IntLiteral(var_store.fresh(), int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -455,8 +455,8 @@ fn add_bindings_from_patterns(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NumLiteral(_, _)
|
NumLiteral(_, _)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(_, _)
|
| Shadowed(_, _)
|
||||||
|
|
|
@ -32,7 +32,7 @@ mod test_can {
|
||||||
let actual_out = can_expr_with(&arena, test_home(), input);
|
let actual_out = can_expr_with(&arena, test_home(), input);
|
||||||
|
|
||||||
match actual_out.loc_expr.value {
|
match actual_out.loc_expr.value {
|
||||||
Expr::Float(_, actual) => {
|
Expr::Float(_, _, actual) => {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
}
|
}
|
||||||
actual => {
|
actual => {
|
||||||
|
@ -46,11 +46,11 @@ mod test_can {
|
||||||
let actual_out = can_expr_with(&arena, test_home(), input);
|
let actual_out = can_expr_with(&arena, test_home(), input);
|
||||||
|
|
||||||
match actual_out.loc_expr.value {
|
match actual_out.loc_expr.value {
|
||||||
Expr::Int(_, actual) => {
|
Expr::Int(_, _, actual) => {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
}
|
}
|
||||||
actual => {
|
actual => {
|
||||||
panic!("Expected an I64, but got: {:?}", actual);
|
panic!("Expected an Int *, but got: {:?}", actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ mod test_can {
|
||||||
fn correct_annotated_body() {
|
fn correct_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64
|
f : Int * -> Int *
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
f
|
f
|
||||||
|
@ -265,7 +265,7 @@ mod test_can {
|
||||||
fn correct_annotated_body_with_comments() {
|
fn correct_annotated_body_with_comments() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64 # comment
|
f : Int * -> Int * # comment
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
f
|
f
|
||||||
|
@ -281,7 +281,7 @@ mod test_can {
|
||||||
fn name_mismatch_annotated_body() {
|
fn name_mismatch_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64
|
f : Int * -> Int *
|
||||||
g = \ a -> a
|
g = \ a -> a
|
||||||
|
|
||||||
g
|
g
|
||||||
|
@ -307,7 +307,7 @@ mod test_can {
|
||||||
fn name_mismatch_annotated_body_with_comment() {
|
fn name_mismatch_annotated_body_with_comment() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64 # comment
|
f : Int * -> Int * # comment
|
||||||
g = \ a -> a
|
g = \ a -> a
|
||||||
|
|
||||||
g
|
g
|
||||||
|
@ -333,7 +333,7 @@ mod test_can {
|
||||||
fn separated_annotated_body() {
|
fn separated_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64
|
f : Int * -> Int *
|
||||||
|
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ mod test_can {
|
||||||
fn separated_annotated_body_with_comment() {
|
fn separated_annotated_body_with_comment() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64
|
f : Int * -> Int *
|
||||||
# comment
|
# comment
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
|
@ -375,9 +375,9 @@ mod test_can {
|
||||||
fn shadowed_annotation() {
|
fn shadowed_annotation() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64 -> I64
|
f : Int * -> Int *
|
||||||
|
|
||||||
f : I64 -> I64
|
f : Int * -> Int *
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"#
|
||||||
|
@ -397,7 +397,7 @@ mod test_can {
|
||||||
fn correct_nested_unannotated_body() {
|
fn correct_nested_unannotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64
|
f : Int *
|
||||||
f =
|
f =
|
||||||
g = 42
|
g = 42
|
||||||
|
|
||||||
|
@ -416,9 +416,9 @@ mod test_can {
|
||||||
fn correct_nested_annotated_body() {
|
fn correct_nested_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64
|
f : Int *
|
||||||
f =
|
f =
|
||||||
g : I64
|
g : Int *
|
||||||
g = 42
|
g = 42
|
||||||
|
|
||||||
g + 1
|
g + 1
|
||||||
|
@ -436,11 +436,11 @@ mod test_can {
|
||||||
fn correct_nested_body_annotated_multiple_lines() {
|
fn correct_nested_body_annotated_multiple_lines() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64
|
f : Int *
|
||||||
f =
|
f =
|
||||||
g : I64
|
g : Int *
|
||||||
g = 42
|
g = 42
|
||||||
h : I64
|
h : Int *
|
||||||
h = 5
|
h = 5
|
||||||
z = 4
|
z = 4
|
||||||
g + h + z
|
g + h + z
|
||||||
|
@ -458,10 +458,10 @@ mod test_can {
|
||||||
fn correct_nested_body_unannotated_multiple_lines() {
|
fn correct_nested_body_unannotated_multiple_lines() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64
|
f : Int *
|
||||||
f =
|
f =
|
||||||
g = 42
|
g = 42
|
||||||
h : I64
|
h : Int *
|
||||||
h = 5
|
h = 5
|
||||||
z = 4
|
z = 4
|
||||||
g + h + z
|
g + h + z
|
||||||
|
@ -478,7 +478,7 @@ mod test_can {
|
||||||
fn correct_double_nested_body() {
|
fn correct_double_nested_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : I64
|
f : Int *
|
||||||
f =
|
f =
|
||||||
g =
|
g =
|
||||||
h = 42
|
h = 42
|
||||||
|
@ -499,7 +499,7 @@ mod test_can {
|
||||||
fn annotation_followed_with_unrelated_affectation() {
|
fn annotation_followed_with_unrelated_affectation() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
F : I64
|
F : Int *
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
|
@ -520,9 +520,9 @@ mod test_can {
|
||||||
fn two_annotations_followed_with_unrelated_affectation() {
|
fn two_annotations_followed_with_unrelated_affectation() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r#"
|
||||||
G : I64
|
G : Int *
|
||||||
|
|
||||||
F : I64
|
F : Int *
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
|
|
|
@ -11,30 +11,48 @@ use roc_types::types::Reason;
|
||||||
use roc_types::types::Type::{self, *};
|
use roc_types::types::Type::{self, *};
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn int_literal(num_var: Variable, expected: Expected<Type>, region: Region) -> Constraint {
|
pub fn int_literal(
|
||||||
|
num_var: Variable,
|
||||||
|
percision_var: Variable,
|
||||||
|
expected: Expected<Type>,
|
||||||
|
region: Region,
|
||||||
|
) -> Constraint {
|
||||||
let num_type = Variable(num_var);
|
let num_type = Variable(num_var);
|
||||||
let reason = Reason::IntLiteral;
|
let reason = Reason::IntLiteral;
|
||||||
let expected_literal = ForReason(reason, num_int(), region);
|
|
||||||
|
|
||||||
exists(
|
exists(
|
||||||
vec![num_var],
|
vec![num_var],
|
||||||
And(vec![
|
And(vec![
|
||||||
Eq(num_type.clone(), expected_literal, Category::Int, region),
|
Eq(
|
||||||
|
num_type.clone(),
|
||||||
|
ForReason(reason, num_int(Type::Variable(percision_var)), region),
|
||||||
|
Category::Int,
|
||||||
|
region,
|
||||||
|
),
|
||||||
Eq(num_type, expected, Category::Int, region),
|
Eq(num_type, expected, Category::Int, region),
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn float_literal(num_var: Variable, expected: Expected<Type>, region: Region) -> Constraint {
|
pub fn float_literal(
|
||||||
|
num_var: Variable,
|
||||||
|
percision_var: Variable,
|
||||||
|
expected: Expected<Type>,
|
||||||
|
region: Region,
|
||||||
|
) -> Constraint {
|
||||||
let num_type = Variable(num_var);
|
let num_type = Variable(num_var);
|
||||||
let reason = Reason::FloatLiteral;
|
let reason = Reason::FloatLiteral;
|
||||||
let expected_literal = ForReason(reason, num_float(), region);
|
|
||||||
|
|
||||||
exists(
|
exists(
|
||||||
vec![num_var],
|
vec![num_var],
|
||||||
And(vec![
|
And(vec![
|
||||||
Eq(num_type.clone(), expected_literal, Category::Float, region),
|
Eq(
|
||||||
|
num_type.clone(),
|
||||||
|
ForReason(reason, num_float(Type::Variable(percision_var)), region),
|
||||||
|
Category::Float,
|
||||||
|
region,
|
||||||
|
),
|
||||||
Eq(num_type, expected, Category::Float, region),
|
Eq(num_type, expected, Category::Float, region),
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
|
@ -72,11 +90,11 @@ pub fn str_type() -> Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn num_float() -> Type {
|
pub fn num_float(range: Type) -> Type {
|
||||||
Type::Alias(
|
Type::Alias(
|
||||||
Symbol::NUM_F64,
|
Symbol::NUM_FLOAT,
|
||||||
vec![],
|
vec![("range".into(), range.clone())],
|
||||||
Box::new(num_num(num_floatingpoint(num_binary64()))),
|
Box::new(num_num(num_floatingpoint(range))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,11 +126,11 @@ pub fn num_binary64() -> Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn num_int() -> Type {
|
pub fn num_int(range: Type) -> Type {
|
||||||
Type::Alias(
|
Type::Alias(
|
||||||
Symbol::NUM_I64,
|
Symbol::NUM_INT,
|
||||||
vec![],
|
vec![("range".into(), range.clone())],
|
||||||
Box::new(num_num(num_integer(num_signed64()))),
|
Box::new(num_num(num_integer(range))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ pub fn constrain_expr(
|
||||||
expected: Expected<Type>,
|
expected: Expected<Type>,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
match expr {
|
match expr {
|
||||||
Int(var, _) => int_literal(*var, expected, region),
|
Int(var, percision, _) => int_literal(*var, *percision, 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, _) => float_literal(*var, expected, region),
|
Float(var, percision, _) => float_literal(*var, *percision, 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() {
|
||||||
|
|
|
@ -57,8 +57,8 @@ fn headers_from_annotation_help(
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
| UnsupportedPattern(_)
|
| UnsupportedPattern(_)
|
||||||
| NumLiteral(_, _)
|
| NumLiteral(_, _)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_) => true,
|
| StrLiteral(_) => true,
|
||||||
|
|
||||||
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
||||||
|
@ -154,20 +154,20 @@ pub fn constrain_pattern(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
IntLiteral(_) => {
|
IntLiteral(precision_var, _) => {
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(Constraint::Pattern(
|
||||||
region,
|
region,
|
||||||
PatternCategory::Int,
|
PatternCategory::Int,
|
||||||
builtins::num_int(),
|
builtins::num_int(Type::Variable(*precision_var)),
|
||||||
expected,
|
expected,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatLiteral(_) => {
|
FloatLiteral(precision_var, _) => {
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(Constraint::Pattern(
|
||||||
region,
|
region,
|
||||||
PatternCategory::Float,
|
PatternCategory::Float,
|
||||||
builtins::num_float(),
|
builtins::num_float(Type::Variable(*precision_var)),
|
||||||
expected,
|
expected,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::builtins::{num_binary64, num_floatingpoint, num_integer, num_num, num_signed64};
|
use crate::builtins::{num_floatingpoint, num_integer, num_num};
|
||||||
use crate::expr::{exists, Info};
|
use crate::expr::{exists, Info};
|
||||||
use roc_can::annotation::IntroducedVariables;
|
use roc_can::annotation::IntroducedVariables;
|
||||||
use roc_can::constraint::Constraint::{self, *};
|
use roc_can::constraint::Constraint::{self, *};
|
||||||
|
@ -173,18 +173,19 @@ fn constrain_pattern(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
IntLiteral(_) => {
|
IntLiteral(inner_var, _) => {
|
||||||
let (a, b, c, num_type) = unique_int(var_store);
|
let (a, b, c, num_type) = unique_int(var_store);
|
||||||
|
|
||||||
state.constraints.push(exists(
|
state.constraints.push(exists(
|
||||||
vec![a, b, c],
|
vec![*inner_var, a, b, c],
|
||||||
Constraint::Pattern(pattern.region, PatternCategory::Int, num_type, expected),
|
Constraint::Pattern(pattern.region, PatternCategory::Int, num_type, expected),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
FloatLiteral(_) => {
|
FloatLiteral(inner_var, _) => {
|
||||||
let (a, b, c, num_type) = unique_float(var_store);
|
let (a, b, c, num_type) = unique_float(var_store);
|
||||||
|
|
||||||
state.constraints.push(exists(
|
state.constraints.push(exists(
|
||||||
vec![a, b, c],
|
vec![*inner_var, a, b, c],
|
||||||
Constraint::Pattern(pattern.region, PatternCategory::Float, num_type, expected),
|
Constraint::Pattern(pattern.region, PatternCategory::Float, num_type, expected),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -423,10 +424,9 @@ fn unique_int(var_store: &mut VarStore) -> (Variable, Variable, Variable, Type)
|
||||||
let num_uvar1 = var_store.fresh();
|
let num_uvar1 = var_store.fresh();
|
||||||
let num_uvar2 = var_store.fresh();
|
let num_uvar2 = var_store.fresh();
|
||||||
let num_uvar3 = var_store.fresh();
|
let num_uvar3 = var_store.fresh();
|
||||||
|
let num_uvar4 = var_store.fresh();
|
||||||
|
|
||||||
let signed_64 = num_signed64();
|
let integer = num_integer(Type::Variable(num_uvar4));
|
||||||
let attr_signed_64 = attr_type(Bool::variable(num_uvar1), signed_64);
|
|
||||||
let integer = num_integer(attr_signed_64);
|
|
||||||
let attr_int = attr_type(Bool::variable(num_uvar2), integer);
|
let attr_int = attr_type(Bool::variable(num_uvar2), integer);
|
||||||
let num = num_num(attr_int);
|
let num = num_num(attr_int);
|
||||||
let attr_num = attr_type(Bool::variable(num_uvar3), num);
|
let attr_num = attr_type(Bool::variable(num_uvar3), num);
|
||||||
|
@ -438,10 +438,9 @@ fn unique_float(var_store: &mut VarStore) -> (Variable, Variable, Variable, Type
|
||||||
let num_uvar1 = var_store.fresh();
|
let num_uvar1 = var_store.fresh();
|
||||||
let num_uvar2 = var_store.fresh();
|
let num_uvar2 = var_store.fresh();
|
||||||
let num_uvar3 = var_store.fresh();
|
let num_uvar3 = var_store.fresh();
|
||||||
|
let num_uvar4 = var_store.fresh();
|
||||||
|
|
||||||
let binary_64 = num_binary64();
|
let fp = num_floatingpoint(Type::Variable(num_uvar4));
|
||||||
let attr_binary_64 = attr_type(Bool::variable(num_uvar1), binary_64);
|
|
||||||
let fp = num_floatingpoint(attr_binary_64);
|
|
||||||
let attr_fp = attr_type(Bool::variable(num_uvar2), fp);
|
let attr_fp = attr_type(Bool::variable(num_uvar2), fp);
|
||||||
let num = num_num(attr_fp);
|
let num = num_num(attr_fp);
|
||||||
let attr_num = attr_type(Bool::variable(num_uvar3), num);
|
let attr_num = attr_type(Bool::variable(num_uvar3), num);
|
||||||
|
@ -478,7 +477,7 @@ pub fn constrain_expr(
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Int(var, _) => {
|
Int(var, _, _) => {
|
||||||
let (a, b, c, num_type) = unique_int(var_store);
|
let (a, b, c, num_type) = unique_int(var_store);
|
||||||
|
|
||||||
exists(
|
exists(
|
||||||
|
@ -494,7 +493,7 @@ pub fn constrain_expr(
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Float(var, _) => {
|
Float(var, _, _) => {
|
||||||
let (a, b, c, num_type) = unique_float(var_store);
|
let (a, b, c, num_type) = unique_float(var_store);
|
||||||
|
|
||||||
exists(
|
exists(
|
||||||
|
@ -532,7 +531,9 @@ pub fn constrain_expr(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Record { record_var, fields } => {
|
Record {
|
||||||
|
record_var, fields, ..
|
||||||
|
} => {
|
||||||
// NOTE: canonicalization guarantees at least one field
|
// NOTE: canonicalization guarantees at least one field
|
||||||
// zero fields generates an EmptyRecord
|
// zero fields generates an EmptyRecord
|
||||||
let mut field_types = SendMap::default();
|
let mut field_types = SendMap::default();
|
||||||
|
|
|
@ -762,8 +762,8 @@ mod test_fmt {
|
||||||
expr_formats_to(
|
expr_formats_to(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
f: { y : I64,
|
f: { y : Int *,
|
||||||
x : I64 ,
|
x : Int * ,
|
||||||
}
|
}
|
||||||
|
|
||||||
f"#
|
f"#
|
||||||
|
@ -772,8 +772,8 @@ mod test_fmt {
|
||||||
r#"
|
r#"
|
||||||
f :
|
f :
|
||||||
{
|
{
|
||||||
y : I64,
|
y : Int *,
|
||||||
x : I64,
|
x : Int *,
|
||||||
}
|
}
|
||||||
|
|
||||||
f"#
|
f"#
|
||||||
|
@ -787,8 +787,8 @@ mod test_fmt {
|
||||||
r#"
|
r#"
|
||||||
f :
|
f :
|
||||||
{
|
{
|
||||||
y : I64,
|
y : Int *,
|
||||||
x : I64,
|
x : Int *,
|
||||||
}
|
}
|
||||||
|
|
||||||
f"#
|
f"#
|
||||||
|
@ -800,7 +800,7 @@ mod test_fmt {
|
||||||
expr_formats_same(indoc!(
|
expr_formats_same(indoc!(
|
||||||
r#"
|
r#"
|
||||||
f :
|
f :
|
||||||
I64
|
Int *
|
||||||
|
|
||||||
f"#
|
f"#
|
||||||
));
|
));
|
||||||
|
@ -880,7 +880,7 @@ mod test_fmt {
|
||||||
r#"
|
r#"
|
||||||
f :
|
f :
|
||||||
{
|
{
|
||||||
x: I64 # comment 1
|
x: Int * # comment 1
|
||||||
,
|
,
|
||||||
# comment 2
|
# comment 2
|
||||||
}
|
}
|
||||||
|
@ -891,7 +891,7 @@ mod test_fmt {
|
||||||
r#"
|
r#"
|
||||||
f :
|
f :
|
||||||
{
|
{
|
||||||
x : I64,
|
x : Int *,
|
||||||
# comment 1
|
# comment 1
|
||||||
# comment 2
|
# comment 2
|
||||||
}
|
}
|
||||||
|
@ -2557,7 +2557,7 @@ mod test_fmt {
|
||||||
fn record_type() {
|
fn record_type() {
|
||||||
expr_formats_same(indoc!(
|
expr_formats_same(indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : { foo : I64 }
|
f : { foo : Int * }
|
||||||
f = { foo: 1000 }
|
f = { foo: 1000 }
|
||||||
|
|
||||||
a
|
a
|
||||||
|
@ -2608,11 +2608,11 @@ mod test_fmt {
|
||||||
// r#"
|
// r#"
|
||||||
// f :
|
// f :
|
||||||
// Result a
|
// Result a
|
||||||
// { x : I64
|
// { x : Int *
|
||||||
// , y : Float
|
// , y : Float
|
||||||
// }
|
// }
|
||||||
// c
|
// c
|
||||||
// -> I64
|
// -> Int *
|
||||||
// f =
|
// f =
|
||||||
// \_ -> 4
|
// \_ -> 4
|
||||||
// "#
|
// "#
|
||||||
|
|
|
@ -486,13 +486,28 @@ fn get_inplace_from_layout(layout: &Layout<'_>) -> InPlace {
|
||||||
|
|
||||||
pub fn build_exp_literal<'a, 'ctx, 'env>(
|
pub fn build_exp_literal<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
layout: &Layout<'_>,
|
||||||
literal: &roc_mono::ir::Literal<'a>,
|
literal: &roc_mono::ir::Literal<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
use roc_mono::ir::Literal::*;
|
use roc_mono::ir::Literal::*;
|
||||||
|
|
||||||
match literal {
|
match literal {
|
||||||
Int(num) => env.context.i64_type().const_int(*num as u64, true).into(),
|
Int(int) =>
|
||||||
Float(num) => env.context.f64_type().const_float(*num).into(),
|
(match layout {
|
||||||
|
Layout::Builtin(Builtin::Usize) => ptr_int(env.context, env.ptr_bytes),
|
||||||
|
Layout::Builtin(Builtin::Int128) => env.context.i128_type(), /* TODO file an issue: you can't currently have an int literal bigger than 64 bits long, and also (as we see here), you can't currently have (at least in Inkwell) a when-branch with an i128 literal in its pattren */
|
||||||
|
Layout::Builtin(Builtin::Int64) => env.context.i64_type(),
|
||||||
|
Layout::Builtin(Builtin::Int32) => env.context.i32_type(),
|
||||||
|
Layout::Builtin(Builtin::Int16) => env.context.i16_type(),
|
||||||
|
Layout::Builtin(Builtin::Int8) => env.context.i8_type(),
|
||||||
|
_ => panic!("Invalid layout for int literal = {:?}", layout),
|
||||||
|
}).const_int(*int as u64, false).into(),
|
||||||
|
Float(num) =>
|
||||||
|
(match layout {
|
||||||
|
Layout::Builtin(Builtin::Float64) => env.context.f64_type(),
|
||||||
|
Layout::Builtin(Builtin::Float32) => env.context.f32_type(),
|
||||||
|
_ => panic!("Invalid layout for float literal = {:?}", layout),
|
||||||
|
}).const_float(*num).into(),
|
||||||
Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(),
|
Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(),
|
||||||
Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(),
|
Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(),
|
||||||
Str(str_literal) => {
|
Str(str_literal) => {
|
||||||
|
@ -774,7 +789,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
use roc_mono::ir::Expr::*;
|
use roc_mono::ir::Expr::*;
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
Literal(literal) => build_exp_literal(env, literal),
|
Literal(literal) => build_exp_literal(env, layout, literal),
|
||||||
|
|
||||||
Call(call) => build_exp_call(env, layout_ids, scope, parent, layout, call),
|
Call(call) => build_exp_call(env, layout_ids, scope, parent, layout, call),
|
||||||
|
|
||||||
|
@ -1805,6 +1820,15 @@ fn build_switch_ir<'a, 'ctx, 'env>(
|
||||||
.build_bitcast(full_cond, env.context.i64_type(), "")
|
.build_bitcast(full_cond, env.context.i64_type(), "")
|
||||||
.into_int_value()
|
.into_int_value()
|
||||||
}
|
}
|
||||||
|
Layout::Builtin(Builtin::Float32) => {
|
||||||
|
// float matches are done on the bit pattern
|
||||||
|
cond_layout = Layout::Builtin(Builtin::Int32);
|
||||||
|
let full_cond = load_symbol(env, scope, cond_symbol);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.build_bitcast(full_cond, env.context.i32_type(), "")
|
||||||
|
.into_int_value()
|
||||||
|
}
|
||||||
Layout::Union(_) => {
|
Layout::Union(_) => {
|
||||||
// we match on the discriminant, not the whole Tag
|
// we match on the discriminant, not the whole Tag
|
||||||
cond_layout = Layout::Builtin(Builtin::Int64);
|
cond_layout = Layout::Builtin(Builtin::Int64);
|
||||||
|
@ -1832,8 +1856,11 @@ fn build_switch_ir<'a, 'ctx, 'env>(
|
||||||
//
|
//
|
||||||
// they either need to all be i8, or i64
|
// they either need to all be i8, or i64
|
||||||
let int_val = match cond_layout {
|
let int_val = match cond_layout {
|
||||||
Layout::Builtin(Builtin::Int128) => context.i128_type().const_int(*int as u64, false), /* TODO file an issue: you can't currently have an int literal bigger than 64 bits long, and also (as we see here), you can't currently have (at least in Inkwell) a when-branch with an i128 literal in its pattren */
|
Layout::Builtin(Builtin::Usize) => {
|
||||||
|
ptr_int(env.context, env.ptr_bytes).const_int(*int as u64, false)
|
||||||
|
}
|
||||||
Layout::Builtin(Builtin::Int64) => context.i64_type().const_int(*int as u64, false),
|
Layout::Builtin(Builtin::Int64) => context.i64_type().const_int(*int as u64, false),
|
||||||
|
Layout::Builtin(Builtin::Int128) => context.i128_type().const_int(*int as u64, false), /* TODO file an issue: you can't currently have an int literal bigger than 64 bits long, and also (as we see here), you can't currently have (at least in Inkwell) a when-branch with an i128 literal in its pattren */
|
||||||
Layout::Builtin(Builtin::Int32) => context.i32_type().const_int(*int as u64, false),
|
Layout::Builtin(Builtin::Int32) => context.i32_type().const_int(*int as u64, false),
|
||||||
Layout::Builtin(Builtin::Int16) => context.i16_type().const_int(*int as u64, false),
|
Layout::Builtin(Builtin::Int16) => context.i16_type().const_int(*int as u64, false),
|
||||||
Layout::Builtin(Builtin::Int8) => context.i8_type().const_int(*int as u64, false),
|
Layout::Builtin(Builtin::Int8) => context.i8_type().const_int(*int as u64, false),
|
||||||
|
@ -3053,7 +3080,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
use roc_mono::layout::Builtin::*;
|
use roc_mono::layout::Builtin::*;
|
||||||
|
|
||||||
match arg_builtin {
|
match arg_builtin {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 => {
|
Usize | Int128 | Int64 | Int32 | Int16 | Int8 => {
|
||||||
build_int_unary_op(env, arg.into_int_value(), arg_builtin, op)
|
build_int_unary_op(env, arg.into_int_value(), arg_builtin, op)
|
||||||
}
|
}
|
||||||
Float128 | Float64 | Float32 | Float16 => {
|
Float128 | Float64 | Float32 | Float16 => {
|
||||||
|
@ -3091,7 +3118,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let tag_lt = env.context.i8_type().const_int(2_u64, false);
|
let tag_lt = env.context.i8_type().const_int(2_u64, false);
|
||||||
|
|
||||||
match lhs_builtin {
|
match lhs_builtin {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 => {
|
Usize | Int128 | Int64 | Int32 | Int16 | Int8 => {
|
||||||
let are_equal = env.builder.build_int_compare(
|
let are_equal = env.builder.build_int_compare(
|
||||||
IntPredicate::EQ,
|
IntPredicate::EQ,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
|
@ -3515,7 +3542,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
|
||||||
use roc_mono::layout::Builtin::*;
|
use roc_mono::layout::Builtin::*;
|
||||||
|
|
||||||
match lhs_builtin {
|
match lhs_builtin {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 => build_int_binop(
|
Usize | Int128 | Int64 | Int32 | Int16 | Int8 => build_int_binop(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
|
@ -3766,6 +3793,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
|
||||||
// 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,
|
||||||
|
@ -3892,6 +3920,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let bd = env.builder;
|
let bd = env.builder;
|
||||||
|
|
||||||
|
// TODO: Handle differnt 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()]),
|
||||||
|
|
|
@ -165,6 +165,7 @@ pub fn basic_type_from_builtin<'ctx>(
|
||||||
Int16 => context.i16_type().as_basic_type_enum(),
|
Int16 => context.i16_type().as_basic_type_enum(),
|
||||||
Int8 => context.i8_type().as_basic_type_enum(),
|
Int8 => context.i8_type().as_basic_type_enum(),
|
||||||
Int1 => context.bool_type().as_basic_type_enum(),
|
Int1 => context.bool_type().as_basic_type_enum(),
|
||||||
|
Usize => ptr_int(context, ptr_bytes).as_basic_type_enum(),
|
||||||
Float128 => context.f128_type().as_basic_type_enum(),
|
Float128 => context.f128_type().as_basic_type_enum(),
|
||||||
Float64 => context.f64_type().as_basic_type_enum(),
|
Float64 => context.f64_type().as_basic_type_enum(),
|
||||||
Float32 => context.f32_type().as_basic_type_enum(),
|
Float32 => context.f32_type().as_basic_type_enum(),
|
||||||
|
|
|
@ -1273,7 +1273,7 @@ mod gen_list {
|
||||||
app "quicksort" provides [ main ] to "./platform"
|
app "quicksort" provides [ main ] to "./platform"
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -1396,7 +1396,7 @@ mod gen_list {
|
||||||
quicksortHelp list 0 (n - 1)
|
quicksortHelp list 0 (n - 1)
|
||||||
|
|
||||||
|
|
||||||
quicksortHelp : List (Num a), I64, I64 -> List (Num a)
|
quicksortHelp : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
|
@ -1408,7 +1408,7 @@ mod gen_list {
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -1419,7 +1419,7 @@ mod gen_list {
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -1431,7 +1431,7 @@ mod gen_list {
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, (Num a) -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
@ -1466,7 +1466,7 @@ mod gen_list {
|
||||||
quicksortHelp list 0 (List.len list - 1)
|
quicksortHelp list 0 (List.len list - 1)
|
||||||
|
|
||||||
|
|
||||||
quicksortHelp : List (Num a), I64, I64 -> List (Num a)
|
quicksortHelp : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
|
@ -1478,7 +1478,7 @@ mod gen_list {
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -1489,7 +1489,7 @@ mod gen_list {
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -1501,7 +1501,7 @@ mod gen_list {
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, Num a -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, Num a -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
# if j < high then
|
# if j < high then
|
||||||
if False then
|
if False then
|
||||||
|
@ -1539,7 +1539,7 @@ mod gen_list {
|
||||||
quicksortHelp list 0 (List.len list - 1)
|
quicksortHelp list 0 (List.len list - 1)
|
||||||
|
|
||||||
|
|
||||||
quicksortHelp : List (Num a), I64, I64 -> List (Num a)
|
quicksortHelp : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
|
@ -1551,7 +1551,7 @@ mod gen_list {
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -1562,7 +1562,7 @@ mod gen_list {
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -1574,7 +1574,7 @@ mod gen_list {
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, Num a -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, Num a -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
|
|
@ -15,6 +15,357 @@ mod helpers;
|
||||||
mod gen_num {
|
mod gen_num {
|
||||||
use roc_std::RocOrder;
|
use roc_std::RocOrder;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nat_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : Nat
|
||||||
|
i = 1
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
usize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn i128_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : I128
|
||||||
|
i = 128
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
128,
|
||||||
|
i128
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i64_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : I64
|
||||||
|
i = 64
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
64,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i32_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : I32
|
||||||
|
i = 32
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
32,
|
||||||
|
i32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i16_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : I16
|
||||||
|
i = 16
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
16,
|
||||||
|
i16
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i8_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : I8
|
||||||
|
i = 8
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
8,
|
||||||
|
i8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn i128_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : I128
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
i128
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i64_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : I64
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i32_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : I32
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
i32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i16_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : I16
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
i16
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn i8_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : I8
|
||||||
|
f = 0xA
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0xA,
|
||||||
|
i8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn u128_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : U128
|
||||||
|
i = 128
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
128,
|
||||||
|
u128
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u64_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : U64
|
||||||
|
i = 64
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
64,
|
||||||
|
u64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u32_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : U32
|
||||||
|
i = 32
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
32,
|
||||||
|
u32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u16_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : U16
|
||||||
|
i = 16
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
16,
|
||||||
|
u16
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u8_signed_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
i : U8
|
||||||
|
i = 8
|
||||||
|
|
||||||
|
i
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
8,
|
||||||
|
u8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn u128_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : U128
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
i128
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u64_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : U64
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
u64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u32_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : U32
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
u32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u16_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : U16
|
||||||
|
f = 0x123
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0x123,
|
||||||
|
u16
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn u8_hex_int_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : U8
|
||||||
|
f = 0xA
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0xA,
|
||||||
|
u8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn f64_float_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : F64
|
||||||
|
f = 3.6
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
3.6,
|
||||||
|
f64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn f32_float_alias() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
f : F32
|
||||||
|
f = 3.6
|
||||||
|
|
||||||
|
f
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
3.6,
|
||||||
|
f32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f64_sqrt() {
|
fn f64_sqrt() {
|
||||||
// FIXME this works with normal types, but fails when checking uniqueness types
|
// FIXME this works with normal types, but fails when checking uniqueness types
|
||||||
|
|
|
@ -135,7 +135,7 @@ mod gen_primitives {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : [ Pair I64 I64 ]
|
x : [ Pair (Int *) (Int *) ]
|
||||||
x = Pair 0x2 0x3
|
x = Pair 0x2 0x3
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
|
@ -152,7 +152,7 @@ mod gen_primitives {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : [A I64, B I64]
|
x : [A (Int *), B (Int *)]
|
||||||
x = A 0x2
|
x = A 0x2
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
|
@ -170,7 +170,7 @@ mod gen_primitives {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : [A I64, B I64]
|
x : [A (Int *), B (Int *)]
|
||||||
x = B 0x3
|
x = B 0x3
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
|
@ -293,7 +293,7 @@ mod gen_primitives {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
alwaysFloatIdentity : I64 -> (F64 -> F64)
|
alwaysFloatIdentity : Int * -> (Float * -> Float *)
|
||||||
alwaysFloatIdentity = \_ ->
|
alwaysFloatIdentity = \_ ->
|
||||||
(\a -> a)
|
(\a -> a)
|
||||||
|
|
||||||
|
@ -557,14 +557,14 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
len : LinkedList a -> I64
|
len : LinkedList a -> Int *
|
||||||
len = \list ->
|
len = \list ->
|
||||||
when list is
|
when list is
|
||||||
Nil -> 0
|
Nil -> 0
|
||||||
Cons _ rest -> 1 + len rest
|
Cons _ rest -> 1 + len rest
|
||||||
|
|
||||||
main =
|
main =
|
||||||
nil : LinkedList I64
|
nil : LinkedList (Int *)
|
||||||
nil = Nil
|
nil = Nil
|
||||||
|
|
||||||
len nil
|
len nil
|
||||||
|
@ -584,10 +584,10 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
nil : LinkedList I64
|
nil : LinkedList (Int *)
|
||||||
nil = Nil
|
nil = Nil
|
||||||
|
|
||||||
length : LinkedList a -> I64
|
length : LinkedList a -> Int *
|
||||||
length = \list ->
|
length = \list ->
|
||||||
when list is
|
when list is
|
||||||
Nil -> 0
|
Nil -> 0
|
||||||
|
@ -611,10 +611,10 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
one : LinkedList I64
|
one : LinkedList (Int *)
|
||||||
one = Cons 1 Nil
|
one = Cons 1 Nil
|
||||||
|
|
||||||
length : LinkedList a -> I64
|
length : LinkedList a -> Int *
|
||||||
length = \list ->
|
length = \list ->
|
||||||
when list is
|
when list is
|
||||||
Nil -> 0
|
Nil -> 0
|
||||||
|
@ -638,10 +638,10 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
one : LinkedList I64
|
one : LinkedList (Int *)
|
||||||
one = Cons 1 Nil
|
one = Cons 1 Nil
|
||||||
|
|
||||||
length : LinkedList a -> I64
|
length : LinkedList a -> Int *
|
||||||
length = \list ->
|
length = \list ->
|
||||||
when list is
|
when list is
|
||||||
Nil -> 0
|
Nil -> 0
|
||||||
|
@ -665,10 +665,10 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
three : LinkedList I64
|
three : LinkedList (Int *)
|
||||||
three = Cons 3 (Cons 2 (Cons 1 Nil))
|
three = Cons 3 (Cons 2 (Cons 1 Nil))
|
||||||
|
|
||||||
length : LinkedList a -> I64
|
length : LinkedList a -> Int *
|
||||||
length = \list ->
|
length = \list ->
|
||||||
when list is
|
when list is
|
||||||
Nil -> 0
|
Nil -> 0
|
||||||
|
@ -693,7 +693,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
three : LinkedList I64
|
three : LinkedList (Int *)
|
||||||
three = Cons 3 (Cons 2 (Cons 1 Nil))
|
three = Cons 3 (Cons 2 (Cons 1 Nil))
|
||||||
|
|
||||||
|
|
||||||
|
@ -721,10 +721,10 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
zero : LinkedList I64
|
zero : LinkedList (Int *)
|
||||||
zero = Nil
|
zero = Nil
|
||||||
|
|
||||||
sum : LinkedList I64 -> I64
|
sum : LinkedList (Int *) -> Int *
|
||||||
sum = \list ->
|
sum = \list ->
|
||||||
when list is
|
when list is
|
||||||
Nil -> 0
|
Nil -> 0
|
||||||
|
@ -748,7 +748,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||||
|
|
||||||
three : LinkedList I64
|
three : LinkedList (Int *)
|
||||||
three = Cons 3 (Cons 2 (Cons 1 Nil))
|
three = Cons 3 (Cons 2 (Cons 1 Nil))
|
||||||
|
|
||||||
sum : LinkedList (Num a) -> Num a
|
sum : LinkedList (Num a) -> Num a
|
||||||
|
@ -779,7 +779,7 @@ mod gen_primitives {
|
||||||
r#"
|
r#"
|
||||||
Maybe a : [ Nothing, Just a ]
|
Maybe a : [ Nothing, Just a ]
|
||||||
|
|
||||||
x : Maybe (Maybe I64)
|
x : Maybe (Maybe (Int *))
|
||||||
x = Just (Just 41)
|
x = Just (Just 41)
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
|
@ -796,7 +796,7 @@ mod gen_primitives {
|
||||||
r#"
|
r#"
|
||||||
Maybe a : [ Nothing, Just a ]
|
Maybe a : [ Nothing, Just a ]
|
||||||
|
|
||||||
x : Maybe (Maybe I64)
|
x : Maybe (Maybe (Int *))
|
||||||
x = Just Nothing
|
x = Just Nothing
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
|
@ -814,7 +814,7 @@ mod gen_primitives {
|
||||||
r#"
|
r#"
|
||||||
Maybe a : [ Nothing, Just a ]
|
Maybe a : [ Nothing, Just a ]
|
||||||
|
|
||||||
x : Maybe (Maybe I64)
|
x : Maybe (Maybe (Int *))
|
||||||
x = Nothing
|
x = Nothing
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
|
@ -908,7 +908,7 @@ mod gen_primitives {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
foo : I64
|
foo : Int *
|
||||||
|
|
||||||
|
|
||||||
foo
|
foo
|
||||||
|
@ -1033,11 +1033,11 @@ mod gen_primitives {
|
||||||
runEffect : Effect a -> a
|
runEffect : Effect a -> a
|
||||||
runEffect = \@Effect thunk -> thunk {}
|
runEffect = \@Effect thunk -> thunk {}
|
||||||
|
|
||||||
foo : Effect F64
|
foo : Effect (Float *)
|
||||||
foo =
|
foo =
|
||||||
succeed 3.14
|
succeed 3.14
|
||||||
|
|
||||||
main : F64
|
main : Float *
|
||||||
main =
|
main =
|
||||||
runEffect foo
|
runEffect foo
|
||||||
|
|
||||||
|
@ -1058,14 +1058,14 @@ mod gen_primitives {
|
||||||
# succeed : a -> ({} -> a)
|
# succeed : a -> ({} -> a)
|
||||||
succeed = \x -> \{} -> x
|
succeed = \x -> \{} -> x
|
||||||
|
|
||||||
foo : {} -> F64
|
foo : {} -> Float *
|
||||||
foo =
|
foo =
|
||||||
succeed 3.14
|
succeed 3.14
|
||||||
|
|
||||||
# runEffect : ({} -> a) -> a
|
# runEffect : ({} -> a) -> a
|
||||||
runEffect = \thunk -> thunk {}
|
runEffect = \thunk -> thunk {}
|
||||||
|
|
||||||
main : F64
|
main : Float *
|
||||||
main =
|
main =
|
||||||
runEffect foo
|
runEffect foo
|
||||||
"#
|
"#
|
||||||
|
@ -1145,7 +1145,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
main : Bool
|
main : Bool
|
||||||
main =
|
main =
|
||||||
myList : ConsList I64
|
myList : ConsList (Int *)
|
||||||
myList = empty
|
myList = empty
|
||||||
|
|
||||||
isEmpty myList
|
isEmpty myList
|
||||||
|
@ -1176,7 +1176,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
main : Bool
|
main : Bool
|
||||||
main =
|
main =
|
||||||
myList : ConsList I64
|
myList : ConsList (Int *)
|
||||||
myList = Cons 0x1 Nil
|
myList = Cons 0x1 Nil
|
||||||
|
|
||||||
isEmpty myList
|
isEmpty myList
|
||||||
|
@ -1194,16 +1194,16 @@ mod gen_primitives {
|
||||||
r#"
|
r#"
|
||||||
app "test" provides [ main ] to "./platform"
|
app "test" provides [ main ] to "./platform"
|
||||||
|
|
||||||
State a : { count : I64, x : a }
|
State a : { count : Int *, x : a }
|
||||||
|
|
||||||
foo : State a -> I64
|
foo : State a -> Int *
|
||||||
foo = \state ->
|
foo = \state ->
|
||||||
if state.count == 0 then
|
if state.count == 0 then
|
||||||
0
|
0
|
||||||
else
|
else
|
||||||
1 + foo { count: state.count - 1, x: state.x }
|
1 + foo { count: state.count - 1, x: state.x }
|
||||||
|
|
||||||
main : I64
|
main : Int *
|
||||||
main =
|
main =
|
||||||
foo { count: 3, x: {} }
|
foo { count: 3, x: {} }
|
||||||
"#
|
"#
|
||||||
|
@ -1284,7 +1284,7 @@ mod gen_primitives {
|
||||||
_ ->
|
_ ->
|
||||||
Node color key value left right
|
Node color key value left right
|
||||||
|
|
||||||
main : RedBlackTree I64 {}
|
main : RedBlackTree (Int *) {}
|
||||||
main =
|
main =
|
||||||
insert 0 {} Empty
|
insert 0 {} Empty
|
||||||
"#
|
"#
|
||||||
|
@ -1325,7 +1325,7 @@ mod gen_primitives {
|
||||||
_ ->
|
_ ->
|
||||||
Empty
|
Empty
|
||||||
|
|
||||||
main : RedBlackTree I64
|
main : RedBlackTree (Int *)
|
||||||
main =
|
main =
|
||||||
balance Red 0 Empty Empty
|
balance Red 0 Empty Empty
|
||||||
"#
|
"#
|
||||||
|
@ -1348,7 +1348,7 @@ mod gen_primitives {
|
||||||
balance = \key, left ->
|
balance = \key, left ->
|
||||||
Node key left Empty
|
Node key left Empty
|
||||||
|
|
||||||
main : RedBlackTree I64
|
main : RedBlackTree (Int *)
|
||||||
main =
|
main =
|
||||||
balance 0 Empty
|
balance 0 Empty
|
||||||
"#
|
"#
|
||||||
|
@ -1395,7 +1395,7 @@ mod gen_primitives {
|
||||||
_ ->
|
_ ->
|
||||||
Empty
|
Empty
|
||||||
|
|
||||||
main : RedBlackTree I64 I64
|
main : RedBlackTree (Int *) (Int *)
|
||||||
main =
|
main =
|
||||||
balance Red 0 0 Empty Empty
|
balance Red 0 0 Empty Empty
|
||||||
"#
|
"#
|
||||||
|
@ -1445,7 +1445,7 @@ mod gen_primitives {
|
||||||
_ ->
|
_ ->
|
||||||
Node color key value left right
|
Node color key value left right
|
||||||
|
|
||||||
main : RedBlackTree I64 I64
|
main : RedBlackTree (Int *) (Int *)
|
||||||
main =
|
main =
|
||||||
balance Red 0 0 Empty Empty
|
balance Red 0 0 Empty Empty
|
||||||
"#
|
"#
|
||||||
|
@ -1465,7 +1465,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
ConsList a : [ Cons a (ConsList a), Nil ]
|
ConsList a : [ Cons a (ConsList a), Nil ]
|
||||||
|
|
||||||
balance : ConsList I64 -> I64
|
balance : ConsList (Int *) -> Int *
|
||||||
balance = \right ->
|
balance = \right ->
|
||||||
when right is
|
when right is
|
||||||
Cons 1 foo ->
|
Cons 1 foo ->
|
||||||
|
@ -1474,7 +1474,7 @@ mod gen_primitives {
|
||||||
_ -> 3
|
_ -> 3
|
||||||
_ -> 3
|
_ -> 3
|
||||||
|
|
||||||
main : I64
|
main : Int *
|
||||||
main =
|
main =
|
||||||
when balance Nil is
|
when balance Nil is
|
||||||
_ -> 3
|
_ -> 3
|
||||||
|
@ -1491,13 +1491,13 @@ mod gen_primitives {
|
||||||
|
|
||||||
ConsList a : [ Cons a (ConsList a), Nil ]
|
ConsList a : [ Cons a (ConsList a), Nil ]
|
||||||
|
|
||||||
balance : ConsList I64 -> I64
|
balance : ConsList (Int *) -> Int *
|
||||||
balance = \right ->
|
balance = \right ->
|
||||||
when right is
|
when right is
|
||||||
Cons 1 (Cons 1 _) -> 3
|
Cons 1 (Cons 1 _) -> 3
|
||||||
_ -> 3
|
_ -> 3
|
||||||
|
|
||||||
main : I64
|
main : Int *
|
||||||
main =
|
main =
|
||||||
when balance Nil is
|
when balance Nil is
|
||||||
_ -> 3
|
_ -> 3
|
||||||
|
@ -1519,7 +1519,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
ConsList a : [ Cons a (ConsList a), Nil ]
|
ConsList a : [ Cons a (ConsList a), Nil ]
|
||||||
|
|
||||||
balance : ConsList I64 -> I64
|
balance : ConsList (Int *) -> Int *
|
||||||
balance = \right ->
|
balance = \right ->
|
||||||
when right is
|
when right is
|
||||||
Cons 1 foo ->
|
Cons 1 foo ->
|
||||||
|
@ -1528,7 +1528,7 @@ mod gen_primitives {
|
||||||
_ -> 3
|
_ -> 3
|
||||||
_ -> 3
|
_ -> 3
|
||||||
|
|
||||||
main : I64
|
main : Int *
|
||||||
main =
|
main =
|
||||||
when balance Nil is
|
when balance Nil is
|
||||||
_ -> 3
|
_ -> 3
|
||||||
|
@ -1548,13 +1548,13 @@ mod gen_primitives {
|
||||||
|
|
||||||
ConsList a : [ Cons a (ConsList a), Nil ]
|
ConsList a : [ Cons a (ConsList a), Nil ]
|
||||||
|
|
||||||
foo : ConsList I64 -> I64
|
foo : ConsList (Int *) -> Int *
|
||||||
foo = \list ->
|
foo = \list ->
|
||||||
when list is
|
when list is
|
||||||
Cons _ (Cons x _) -> x
|
Cons _ (Cons x _) -> x
|
||||||
_ -> 0
|
_ -> 0
|
||||||
|
|
||||||
main : I64
|
main : Int *
|
||||||
main =
|
main =
|
||||||
foo (Cons 1 (Cons 32 Nil))
|
foo (Cons 1 (Cons 32 Nil))
|
||||||
"#
|
"#
|
||||||
|
@ -1571,15 +1571,15 @@ mod gen_primitives {
|
||||||
r#"
|
r#"
|
||||||
app "test" provides [ main ] to "./platform"
|
app "test" provides [ main ] to "./platform"
|
||||||
|
|
||||||
BTree : [ Node BTree BTree, Leaf I64 ]
|
BTree : [ Node BTree BTree, Leaf (Int *) ]
|
||||||
|
|
||||||
foo : BTree -> I64
|
foo : BTree -> Int *
|
||||||
foo = \btree ->
|
foo = \btree ->
|
||||||
when btree is
|
when btree is
|
||||||
Node (Node (Leaf x) _) _ -> x
|
Node (Node (Leaf x) _) _ -> x
|
||||||
_ -> 0
|
_ -> 0
|
||||||
|
|
||||||
main : I64
|
main : Int *
|
||||||
main =
|
main =
|
||||||
foo (Node (Node (Leaf 32) (Leaf 0)) (Leaf 0))
|
foo (Node (Node (Leaf 32) (Leaf 0)) (Leaf 0))
|
||||||
"#
|
"#
|
||||||
|
@ -1603,7 +1603,7 @@ mod gen_primitives {
|
||||||
A -> (\_ -> 3.14)
|
A -> (\_ -> 3.14)
|
||||||
B -> (\_ -> 3.14)
|
B -> (\_ -> 3.14)
|
||||||
|
|
||||||
main : F64
|
main : Float *
|
||||||
main =
|
main =
|
||||||
(foo {}) 0
|
(foo {}) 0
|
||||||
"#
|
"#
|
||||||
|
@ -1646,7 +1646,7 @@ mod gen_primitives {
|
||||||
Ok x -> transform x
|
Ok x -> transform x
|
||||||
Err e -> fail e
|
Err e -> fail e
|
||||||
|
|
||||||
main : Task {} F64
|
main : Task {} (Float *)
|
||||||
main = after (always "foo") (\_ -> always {})
|
main = after (always "foo") (\_ -> always {})
|
||||||
|
|
||||||
"#
|
"#
|
||||||
|
@ -1676,7 +1676,7 @@ mod gen_primitives {
|
||||||
@Effect inner
|
@Effect inner
|
||||||
|
|
||||||
|
|
||||||
main : Task {} F64
|
main : Task {} (Float *)
|
||||||
main = always {}
|
main = always {}
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
|
@ -1707,7 +1707,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
Task a err : Effect (Result a err)
|
Task a err : Effect (Result a err)
|
||||||
|
|
||||||
always : a -> Task a F64
|
always : a -> Task a (Float *)
|
||||||
always = \x -> effectAlways (Ok x)
|
always = \x -> effectAlways (Ok x)
|
||||||
|
|
||||||
# the problem is that this restricts to `Task {} *`
|
# the problem is that this restricts to `Task {} *`
|
||||||
|
@ -1722,7 +1722,7 @@ mod gen_primitives {
|
||||||
# but here it must be `forall b. Task b {}`
|
# but here it must be `forall b. Task b {}`
|
||||||
Err e -> fail e
|
Err e -> fail e
|
||||||
|
|
||||||
main : Task {} F64
|
main : Task {} (Float *)
|
||||||
main =
|
main =
|
||||||
after (always "foo") (\_ -> always {})
|
after (always "foo") (\_ -> always {})
|
||||||
"#
|
"#
|
||||||
|
@ -1774,7 +1774,7 @@ mod gen_primitives {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : Result I64 F64
|
x : Result (Int *) (Float *)
|
||||||
x = Ok 4
|
x = Ok 4
|
||||||
|
|
||||||
(Ok y) = x
|
(Ok y) = x
|
||||||
|
|
|
@ -41,6 +41,9 @@ pub fn helper<'a>(
|
||||||
module_src = &temp;
|
module_src = &temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let target = target_lexicon::Triple::host();
|
||||||
|
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
|
||||||
|
|
||||||
let exposed_types = MutMap::default();
|
let exposed_types = MutMap::default();
|
||||||
let loaded = roc_load::file::load_and_monomorphize_from_str(
|
let loaded = roc_load::file::load_and_monomorphize_from_str(
|
||||||
arena,
|
arena,
|
||||||
|
@ -49,6 +52,7 @@ pub fn helper<'a>(
|
||||||
stdlib,
|
stdlib,
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
|
ptr_bytes,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = loaded.expect("failed to load module");
|
let mut loaded = loaded.expect("failed to load module");
|
||||||
|
@ -73,9 +77,6 @@ pub fn helper<'a>(
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = target_lexicon::Triple::host();
|
|
||||||
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
|
|
||||||
|
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
// errors whose reporting we delay (so we can see that code gen generates runtime errors)
|
// errors whose reporting we delay (so we can see that code gen generates runtime errors)
|
||||||
let mut delayed_errors = Vec::new();
|
let mut delayed_errors = Vec::new();
|
||||||
|
@ -308,7 +309,9 @@ macro_rules! assert_opt_evals_to {
|
||||||
|
|
||||||
let context = Context::create();
|
let context = Context::create();
|
||||||
|
|
||||||
let stdlib = roc_builtins::unique::uniq_stdlib();
|
// don't use uniqueness types any more
|
||||||
|
// let stdlib = roc_builtins::unique::uniq_stdlib();
|
||||||
|
let stdlib = roc_builtins::std::standard_stdlib();
|
||||||
|
|
||||||
let (main_fn_name, errors, lib) =
|
let (main_fn_name, errors, lib) =
|
||||||
$crate::helpers::eval::helper(&arena, $src, stdlib, $leak, &context);
|
$crate::helpers::eval::helper(&arena, $src, stdlib, $leak, &context);
|
||||||
|
|
|
@ -50,6 +50,7 @@ pub fn helper<'a>(
|
||||||
stdlib,
|
stdlib,
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
|
8,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = loaded.expect("failed to load module");
|
let mut loaded = loaded.expect("failed to load module");
|
||||||
|
|
|
@ -947,6 +947,7 @@ pub fn load_and_typecheck(
|
||||||
stdlib: StdLib,
|
stdlib: StdLib,
|
||||||
src_dir: &Path,
|
src_dir: &Path,
|
||||||
exposed_types: SubsByModule,
|
exposed_types: SubsByModule,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> Result<LoadedModule, LoadingProblem> {
|
) -> Result<LoadedModule, LoadingProblem> {
|
||||||
use LoadResult::*;
|
use LoadResult::*;
|
||||||
|
|
||||||
|
@ -959,6 +960,7 @@ pub fn load_and_typecheck(
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
Phase::SolveTypes,
|
Phase::SolveTypes,
|
||||||
|
ptr_bytes,
|
||||||
)? {
|
)? {
|
||||||
Monomorphized(_) => unreachable!(""),
|
Monomorphized(_) => unreachable!(""),
|
||||||
TypeChecked(module) => Ok(module),
|
TypeChecked(module) => Ok(module),
|
||||||
|
@ -971,6 +973,7 @@ pub fn load_and_monomorphize<'a>(
|
||||||
stdlib: StdLib,
|
stdlib: StdLib,
|
||||||
src_dir: &Path,
|
src_dir: &Path,
|
||||||
exposed_types: SubsByModule,
|
exposed_types: SubsByModule,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem> {
|
) -> Result<MonomorphizedModule<'a>, LoadingProblem> {
|
||||||
use LoadResult::*;
|
use LoadResult::*;
|
||||||
|
|
||||||
|
@ -983,6 +986,7 @@ pub fn load_and_monomorphize<'a>(
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
Phase::MakeSpecializations,
|
Phase::MakeSpecializations,
|
||||||
|
ptr_bytes,
|
||||||
)? {
|
)? {
|
||||||
Monomorphized(module) => Ok(module),
|
Monomorphized(module) => Ok(module),
|
||||||
TypeChecked(_) => unreachable!(""),
|
TypeChecked(_) => unreachable!(""),
|
||||||
|
@ -996,6 +1000,7 @@ pub fn load_and_monomorphize_from_str<'a>(
|
||||||
stdlib: StdLib,
|
stdlib: StdLib,
|
||||||
src_dir: &Path,
|
src_dir: &Path,
|
||||||
exposed_types: SubsByModule,
|
exposed_types: SubsByModule,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem> {
|
) -> Result<MonomorphizedModule<'a>, LoadingProblem> {
|
||||||
use LoadResult::*;
|
use LoadResult::*;
|
||||||
|
|
||||||
|
@ -1008,6 +1013,7 @@ pub fn load_and_monomorphize_from_str<'a>(
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
Phase::MakeSpecializations,
|
Phase::MakeSpecializations,
|
||||||
|
ptr_bytes,
|
||||||
)? {
|
)? {
|
||||||
Monomorphized(module) => Ok(module),
|
Monomorphized(module) => Ok(module),
|
||||||
TypeChecked(_) => unreachable!(""),
|
TypeChecked(_) => unreachable!(""),
|
||||||
|
@ -1144,6 +1150,7 @@ fn load<'a>(
|
||||||
src_dir: &Path,
|
src_dir: &Path,
|
||||||
exposed_types: SubsByModule,
|
exposed_types: SubsByModule,
|
||||||
goal_phase: Phase,
|
goal_phase: Phase,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> Result<LoadResult<'a>, LoadingProblem>
|
) -> Result<LoadResult<'a>, LoadingProblem>
|
||||||
where
|
where
|
||||||
{
|
{
|
||||||
|
@ -1259,8 +1266,14 @@ where
|
||||||
// added. In that case, do nothing, and keep waiting
|
// added. In that case, do nothing, and keep waiting
|
||||||
// until we receive a Shutdown message.
|
// until we receive a Shutdown message.
|
||||||
if let Some(task) = find_task(&worker, injector, stealers) {
|
if let Some(task) = find_task(&worker, injector, stealers) {
|
||||||
run_task(task, worker_arena, src_dir, msg_tx.clone())
|
run_task(
|
||||||
.expect("Msg channel closed unexpectedly.");
|
task,
|
||||||
|
worker_arena,
|
||||||
|
src_dir,
|
||||||
|
msg_tx.clone(),
|
||||||
|
ptr_bytes,
|
||||||
|
)
|
||||||
|
.expect("Msg channel closed unexpectedly.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3341,6 +3354,7 @@ fn make_specializations<'a>(
|
||||||
mut layout_cache: LayoutCache<'a>,
|
mut layout_cache: LayoutCache<'a>,
|
||||||
specializations_we_must_make: ExternalSpecializations,
|
specializations_we_must_make: ExternalSpecializations,
|
||||||
mut module_timing: ModuleTiming,
|
mut module_timing: ModuleTiming,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> Msg<'a> {
|
) -> Msg<'a> {
|
||||||
let make_specializations_start = SystemTime::now();
|
let make_specializations_start = SystemTime::now();
|
||||||
let mut mono_problems = Vec::new();
|
let mut mono_problems = Vec::new();
|
||||||
|
@ -3351,6 +3365,7 @@ fn make_specializations<'a>(
|
||||||
subs: &mut subs,
|
subs: &mut subs,
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
|
ptr_bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
procs
|
procs
|
||||||
|
@ -3396,6 +3411,7 @@ fn build_pending_specializations<'a>(
|
||||||
decls: Vec<Declaration>,
|
decls: Vec<Declaration>,
|
||||||
mut module_timing: ModuleTiming,
|
mut module_timing: ModuleTiming,
|
||||||
mut layout_cache: LayoutCache<'a>,
|
mut layout_cache: LayoutCache<'a>,
|
||||||
|
ptr_bytes: u32,
|
||||||
// TODO remove
|
// TODO remove
|
||||||
exposed_to_host: MutMap<Symbol, Variable>,
|
exposed_to_host: MutMap<Symbol, Variable>,
|
||||||
) -> Msg<'a> {
|
) -> Msg<'a> {
|
||||||
|
@ -3410,6 +3426,7 @@ fn build_pending_specializations<'a>(
|
||||||
subs: &mut subs,
|
subs: &mut subs,
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
|
ptr_bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add modules' decls to Procs
|
// Add modules' decls to Procs
|
||||||
|
@ -3613,6 +3630,7 @@ fn run_task<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
src_dir: &Path,
|
src_dir: &Path,
|
||||||
msg_tx: MsgSender<'a>,
|
msg_tx: MsgSender<'a>,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> Result<(), LoadingProblem> {
|
) -> Result<(), LoadingProblem> {
|
||||||
use BuildTask::*;
|
use BuildTask::*;
|
||||||
|
|
||||||
|
@ -3685,6 +3703,7 @@ fn run_task<'a>(
|
||||||
decls,
|
decls,
|
||||||
module_timing,
|
module_timing,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
|
ptr_bytes,
|
||||||
exposed_to_host,
|
exposed_to_host,
|
||||||
)),
|
)),
|
||||||
MakeSpecializations {
|
MakeSpecializations {
|
||||||
|
@ -3704,6 +3723,7 @@ fn run_task<'a>(
|
||||||
layout_cache,
|
layout_cache,
|
||||||
specializations_we_must_make,
|
specializations_we_must_make,
|
||||||
module_timing,
|
module_timing,
|
||||||
|
ptr_bytes,
|
||||||
)),
|
)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
app "quicksort" provides [ swap, partition, partitionHelp, quicksort ] to "./platform"
|
app "quicksort" provides [ swap, partition, partitionHelp, quicksort ] to "./platform"
|
||||||
|
|
||||||
quicksort : List (Num a), I64, I64 -> List (Num a)
|
quicksort : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksort = \list, low, high ->
|
quicksort = \list, low, high ->
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
Pair partitionIndex partitioned ->
|
Pair partitionIndex partitioned ->
|
||||||
|
@ -9,7 +9,7 @@ quicksort = \list, low, high ->
|
||||||
|> quicksort (partitionIndex + 1) high
|
|> quicksort (partitionIndex + 1) high
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -21,7 +21,7 @@ swap = \i, j, list ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -33,7 +33,7 @@ partition = \low, high, initialList ->
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, (Num a) -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
app "quicksort" provides [ quicksort ] to "./platform"
|
app "quicksort" provides [ quicksort ] to "./platform"
|
||||||
|
|
||||||
quicksort = \originalList ->
|
quicksort = \originalList ->
|
||||||
quicksortHelp : List (Num a), I64, I64 -> List (Num a)
|
quicksortHelp : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
|
@ -13,7 +13,7 @@ quicksort = \originalList ->
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -24,7 +24,7 @@ quicksort = \originalList ->
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -36,7 +36,7 @@ quicksort = \originalList ->
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, (Num a) -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
|
|
@ -2,7 +2,7 @@ interface Quicksort
|
||||||
exposes [ swap, partition, quicksort ]
|
exposes [ swap, partition, quicksort ]
|
||||||
imports []
|
imports []
|
||||||
|
|
||||||
quicksort : List (Num a), I64, I64 -> List (Num a)
|
quicksort : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksort = \list, low, high ->
|
quicksort = \list, low, high ->
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
Pair partitionIndex partitioned ->
|
Pair partitionIndex partitioned ->
|
||||||
|
@ -11,7 +11,7 @@ quicksort = \list, low, high ->
|
||||||
|> quicksort (partitionIndex + 1) high
|
|> quicksort (partitionIndex + 1) high
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -23,7 +23,7 @@ swap = \i, j, list ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -35,7 +35,7 @@ partition = \low, high, initialList ->
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, (Num a) -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
|
|
@ -85,6 +85,7 @@ mod test_load {
|
||||||
stdlib,
|
stdlib,
|
||||||
dir.path(),
|
dir.path(),
|
||||||
exposed_types,
|
exposed_types,
|
||||||
|
8,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,6 +127,7 @@ mod test_load {
|
||||||
roc_builtins::std::standard_stdlib(),
|
roc_builtins::std::standard_stdlib(),
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
|
8,
|
||||||
);
|
);
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
let mut loaded_module = loaded.expect("Test module failed to load");
|
||||||
|
|
||||||
|
@ -288,6 +290,7 @@ mod test_load {
|
||||||
roc_builtins::std::standard_stdlib(),
|
roc_builtins::std::standard_stdlib(),
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
|
8,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
let mut loaded_module = loaded.expect("Test module failed to load");
|
||||||
|
@ -357,14 +360,14 @@ mod test_load {
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
hashmap! {
|
hashmap! {
|
||||||
"floatTest" => "F64",
|
"floatTest" => "Float *",
|
||||||
"divisionFn" => "F64, F64 -> Result F64 [ DivByZero ]*",
|
"divisionFn" => "Float a, Float a -> Result (Float a) [ DivByZero ]*",
|
||||||
"divisionTest" => "Result F64 [ DivByZero ]*",
|
"divisionTest" => "Result (Float *) [ DivByZero ]*",
|
||||||
"intTest" => "I64",
|
"intTest" => "Int *",
|
||||||
"x" => "F64",
|
"x" => "Float *",
|
||||||
"constantNum" => "Num *",
|
"constantNum" => "Num *",
|
||||||
"divDep1ByDep2" => "Result F64 [ DivByZero ]*",
|
"divDep1ByDep2" => "Result (Float *) [ DivByZero ]*",
|
||||||
"fromDep2" => "F64",
|
"fromDep2" => "Float *",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -377,10 +380,10 @@ mod test_load {
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
hashmap! {
|
hashmap! {
|
||||||
"swap" => "I64, I64, List a -> List a",
|
"swap" => "Int *, Int *, List a -> List a",
|
||||||
"partition" => "I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]",
|
"partition" => "Int b, Int b, List (Num a) -> [ Pair (Int b) (List (Num a)) ]",
|
||||||
"partitionHelp" => "I64, I64, List (Num a), I64, Num a -> [ Pair I64 (List (Num a)) ]",
|
"partitionHelp" => "Int b, Int c, List (Num a), Int c, Num a -> [ Pair (Int b) (List (Num a)) ]",
|
||||||
"quicksort" => "List (Num a), I64, I64 -> List (Num a)",
|
"quicksort" => "List (Num a), Int b, Int b -> List (Num a)",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -406,10 +409,10 @@ mod test_load {
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
hashmap! {
|
hashmap! {
|
||||||
"swap" => "I64, I64, List a -> List a",
|
"swap" => "Int *, Int *, List a -> List a",
|
||||||
"partition" => "I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]",
|
"partition" => "Int b, Int b, List (Num a) -> [ Pair (Int b) (List (Num a)) ]",
|
||||||
"partitionHelp" => "I64, I64, List (Num a), I64, Num a -> [ Pair I64 (List (Num a)) ]",
|
"partitionHelp" => "Int b, Int c, List (Num a), Int c, Num a -> [ Pair (Int b) (List (Num a)) ]",
|
||||||
"quicksort" => "List (Num a), I64, I64 -> List (Num a)",
|
"quicksort" => "List (Num a), Int b, Int b -> List (Num a)",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -454,7 +457,7 @@ mod test_load {
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
hashmap! {
|
hashmap! {
|
||||||
"blah2" => "F64",
|
"blah2" => "Float *",
|
||||||
"blah3" => "Str",
|
"blah3" => "Str",
|
||||||
"str" => "Str",
|
"str" => "Str",
|
||||||
"alwaysThree" => "* -> Str",
|
"alwaysThree" => "* -> Str",
|
||||||
|
@ -476,7 +479,7 @@ mod test_load {
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
hashmap! {
|
hashmap! {
|
||||||
"blah2" => "F64",
|
"blah2" => "Float *",
|
||||||
"blah3" => "Str",
|
"blah3" => "Str",
|
||||||
"str" => "Str",
|
"str" => "Str",
|
||||||
"alwaysThree" => "* -> Str",
|
"alwaysThree" => "* -> Str",
|
||||||
|
|
|
@ -1,423 +0,0 @@
|
||||||
#[macro_use]
|
|
||||||
extern crate pretty_assertions;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate maplit;
|
|
||||||
|
|
||||||
extern crate bumpalo;
|
|
||||||
extern crate inlinable_string;
|
|
||||||
extern crate roc_collections;
|
|
||||||
extern crate roc_load;
|
|
||||||
extern crate roc_module;
|
|
||||||
|
|
||||||
mod helpers;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_uniq_load {
|
|
||||||
use crate::helpers::fixtures_dir;
|
|
||||||
use bumpalo::Bump;
|
|
||||||
use inlinable_string::InlinableString;
|
|
||||||
use roc_builtins::unique;
|
|
||||||
use roc_can::def::Declaration::*;
|
|
||||||
use roc_can::def::Def;
|
|
||||||
use roc_collections::all::MutMap;
|
|
||||||
use roc_constrain::module::SubsByModule;
|
|
||||||
use roc_load::file::LoadedModule;
|
|
||||||
use roc_module::ident::ModuleName;
|
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
|
||||||
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
|
||||||
use roc_types::subs::Subs;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
// HELPERS
|
|
||||||
|
|
||||||
fn load_fixture(
|
|
||||||
dir_name: &str,
|
|
||||||
module_name: &str,
|
|
||||||
subs_by_module: SubsByModule,
|
|
||||||
) -> LoadedModule {
|
|
||||||
let arena = Bump::new();
|
|
||||||
let src_dir = fixtures_dir().join(dir_name);
|
|
||||||
let filename = src_dir.join(format!("{}.roc", module_name));
|
|
||||||
let loaded = roc_load::file::load_and_typecheck(
|
|
||||||
&arena,
|
|
||||||
filename,
|
|
||||||
unique::uniq_stdlib(),
|
|
||||||
src_dir.as_path(),
|
|
||||||
subs_by_module,
|
|
||||||
);
|
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
|
||||||
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module.can_problems.remove(&home).unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
|
|
||||||
let expected_name = loaded_module
|
|
||||||
.interns
|
|
||||||
.module_ids
|
|
||||||
.get_name(loaded_module.module_id)
|
|
||||||
.expect("Test ModuleID not found in module_ids");
|
|
||||||
|
|
||||||
// App module names are hardcoded and not based on anything user-specified
|
|
||||||
if expected_name != ModuleName::APP {
|
|
||||||
assert_eq!(expected_name, &InlinableString::from(module_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
loaded_module
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expect_def(
|
|
||||||
interns: &Interns,
|
|
||||||
subs: &mut Subs,
|
|
||||||
home: ModuleId,
|
|
||||||
def: &Def,
|
|
||||||
expected_types: &mut HashMap<&str, &str>,
|
|
||||||
) {
|
|
||||||
for (symbol, expr_var) in &def.pattern_vars {
|
|
||||||
let content = subs.get(*expr_var).content;
|
|
||||||
|
|
||||||
name_all_type_vars(*expr_var, subs);
|
|
||||||
|
|
||||||
let actual_str = content_to_string(content, subs, home, &interns);
|
|
||||||
let fully_qualified = symbol.fully_qualified(&interns, home).to_string();
|
|
||||||
let expected_type = expected_types
|
|
||||||
.remove(fully_qualified.as_str())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
panic!("Defs included an unexpected symbol: {:?}", fully_qualified)
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_eq!((&symbol, expected_type), (&symbol, actual_str.as_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expect_types(mut loaded_module: LoadedModule, mut expected_types: HashMap<&str, &str>) {
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
let mut subs = loaded_module.solved.into_inner();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module.can_problems.remove(&home).unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
|
|
||||||
for decl in loaded_module.declarations_by_id.remove(&home).unwrap() {
|
|
||||||
match decl {
|
|
||||||
Declare(def) => expect_def(
|
|
||||||
&loaded_module.interns,
|
|
||||||
&mut subs,
|
|
||||||
home,
|
|
||||||
&def,
|
|
||||||
&mut expected_types,
|
|
||||||
),
|
|
||||||
DeclareRec(defs) => {
|
|
||||||
for def in defs {
|
|
||||||
expect_def(
|
|
||||||
&loaded_module.interns,
|
|
||||||
&mut subs,
|
|
||||||
home,
|
|
||||||
&def,
|
|
||||||
&mut expected_types,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Builtin(_) => {}
|
|
||||||
cycle @ InvalidCycle(_, _) => {
|
|
||||||
panic!("Unexpected cyclic def in module declarations: {:?}", cycle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
expected_types,
|
|
||||||
HashMap::default(),
|
|
||||||
"Some expected types were not found in the defs"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TESTS
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn interface_with_deps() {
|
|
||||||
let arena = Bump::new();
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let src_dir = fixtures_dir().join("interface_with_deps");
|
|
||||||
let filename = src_dir.join("Primary.roc");
|
|
||||||
let loaded = roc_load::file::load_and_typecheck(
|
|
||||||
&arena,
|
|
||||||
filename,
|
|
||||||
roc_builtins::std::standard_stdlib(),
|
|
||||||
src_dir.as_path(),
|
|
||||||
subs_by_module,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module.can_problems.remove(&home).unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
|
|
||||||
let def_count: usize = loaded_module
|
|
||||||
.declarations_by_id
|
|
||||||
.remove(&loaded_module.module_id)
|
|
||||||
.unwrap()
|
|
||||||
.into_iter()
|
|
||||||
.map(|decl| decl.def_count())
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
let expected_name = loaded_module
|
|
||||||
.interns
|
|
||||||
.module_ids
|
|
||||||
.get_name(loaded_module.module_id)
|
|
||||||
.expect("Test ModuleID not found in module_ids");
|
|
||||||
|
|
||||||
assert_eq!(expected_name, &InlinableString::from("Primary"));
|
|
||||||
assert_eq!(def_count, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_unit() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("no_deps", "Unit", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"unit" => "Attr * Unit",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn import_alias() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "ImportAlias", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"unit" => "Attr * Dep1.Unit",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_and_typecheck() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "WithBuiltins", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"floatTest" => "Attr Shared F64",
|
|
||||||
"divisionFn" => "Attr Shared (Attr * F64, Attr * F64 -> Attr * (Result (Attr * F64) (Attr * [ DivByZero ]*)))",
|
|
||||||
"divisionTest" => "Attr * (Result (Attr * F64) (Attr * [ DivByZero ]*))",
|
|
||||||
"intTest" => "Attr * I64",
|
|
||||||
"x" => "Attr * F64",
|
|
||||||
"constantNum" => "Attr * (Num (Attr * *))",
|
|
||||||
"divDep1ByDep2" => "Attr * (Result (Attr * F64) (Attr * [ DivByZero ]*))",
|
|
||||||
"fromDep2" => "Attr * F64",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn load_astar() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "AStar", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"findPath" => "Attr * (Attr * { costFunction : Attr Shared (Attr Shared position, Attr Shared position -> Attr * F64), end : Attr Shared position, moveFunction : Attr Shared (Attr Shared position -> Attr * (Set (Attr * position))), start : Attr Shared position } -> Attr * (Result (Attr * (List (Attr Shared position))) (Attr * [ KeyNotFound ]*)))",
|
|
||||||
"initialModel" => "Attr * (Attr Shared position -> Attr * (Model (Attr Shared position)))",
|
|
||||||
"reconstructPath" => "Attr Shared (Attr Shared (Map (Attr * position) (Attr Shared position)), Attr Shared position -> Attr * (List (Attr Shared position)))",
|
|
||||||
"updateCost" => "Attr * (Attr Shared position, Attr Shared position, Attr Shared (Model (Attr Shared position)) -> Attr Shared (Model (Attr Shared position)))",
|
|
||||||
"cheapestOpen" => "Attr * (Attr * (Attr Shared position -> Attr * F64), Attr (* | a | b | c) (Model (Attr Shared position)) -> Attr * (Result (Attr Shared position) (Attr * [ KeyNotFound ]*)))",
|
|
||||||
"astar" => "Attr Shared (Attr Shared (Attr Shared position, Attr Shared position -> Attr * F64), Attr Shared (Attr Shared position -> Attr * (Set (Attr * position))), Attr Shared position, Attr Shared (Model (Attr Shared position)) -> Attr * [ Err (Attr * [ KeyNotFound ]*), Ok (Attr * (List (Attr Shared position))) ]*)",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_and_typecheck_quicksort() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Quicksort", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"swap" => "Attr * (Attr * I64, Attr * I64, Attr * (List (Attr Shared a)) -> Attr * (List (Attr Shared a)))",
|
|
||||||
"partition" => "Attr * (Attr Shared I64, Attr Shared I64, Attr b (List (Attr Shared (Num (Attr Shared a)))) -> Attr * [ Pair (Attr * I64) (Attr b (List (Attr Shared (Num (Attr Shared a))))) ])",
|
|
||||||
|
|
||||||
"partitionHelp" => "Attr Shared (Attr b I64, Attr Shared I64, Attr c (List (Attr Shared (Num (Attr Shared a)))), Attr Shared I64, Attr Shared (Num (Attr Shared a)) -> Attr * [ Pair (Attr b I64) (Attr c (List (Attr Shared (Num (Attr Shared a))))) ])",
|
|
||||||
"quicksort" => "Attr Shared (Attr b (List (Attr Shared (Num (Attr Shared a)))), Attr Shared I64, Attr Shared I64 -> Attr b (List (Attr Shared (Num (Attr Shared a)))))",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn quickcheck_nested_let() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("app_with_deps", "QuicksortOneDef", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"quicksort" => "Attr * (Attr b (List (Attr Shared (Num (Attr Shared a)))) -> Attr b (List (Attr Shared (Num (Attr Shared a)))))",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_principal_types() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("no_deps", "Principal", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"intVal" => "Attr * Str",
|
|
||||||
"identity" => "Attr * (a -> a)",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn load_dep_types() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Primary", subs_by_module);
|
|
||||||
|
|
||||||
// the inferred signature for withDefault is wrong, part of the alias in alias issue.
|
|
||||||
// "withDefault" => "Attr * (Attr * (Res.Res (Attr a b) (Attr * *)), Attr a b -> Attr a b)",
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"blah2" => "Attr * F64",
|
|
||||||
"blah3" => "Attr * Str",
|
|
||||||
"str" => "Attr * Str",
|
|
||||||
"alwaysThree" => "Attr * (* -> Attr * Str)",
|
|
||||||
"identity" => "Attr * (a -> a)",
|
|
||||||
"z" => "Attr * Str",
|
|
||||||
"w" => "Attr * (Dep1.Identity (Attr * {}))",
|
|
||||||
"succeed" => "Attr * (Attr b a -> Attr * (Dep1.Identity (Attr b a)))",
|
|
||||||
"yay" => "Attr * (Res.Res (Attr * {}) (Attr * err))",
|
|
||||||
"withDefault" => "Attr * (Attr (* | b | c) (Res.Res (Attr b a) (Attr c *)), Attr b a -> Attr b a)",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn load_custom_res() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Res", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"withDefault" =>"Attr * (Attr (* | b | c) (Res (Attr b a) (Attr c err)), Attr b a -> Attr b a)",
|
|
||||||
"map" => "Attr * (Attr (* | c | d) (Res (Attr c a) (Attr d err)), Attr * (Attr c a -> Attr e b) -> Attr * (Res (Attr e b) (Attr d err)))",
|
|
||||||
"andThen" => "Attr * (Attr (* | c | d) (Res (Attr c a) (Attr d err)), Attr * (Attr c a -> Attr f (Res (Attr e b) (Attr d err))) -> Attr f (Res (Attr e b) (Attr d err)))",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn imported_dep_regression() {
|
|
||||||
let subs_by_module = MutMap::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "OneDep", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"str" => "Attr * Str",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn load_records() {
|
|
||||||
// test_async(async {
|
|
||||||
// use roc::types::{ErrorType, Mismatch, Problem, TypeExt};
|
|
||||||
|
|
||||||
// let subs_by_module = MutMap::default();
|
|
||||||
// let loaded_module =
|
|
||||||
// load_fixture("interface_with_deps", "Records", subs_by_module);
|
|
||||||
|
|
||||||
// // NOTE: `a` here is unconstrained, so unifies with <type error>
|
|
||||||
// let expected_types = hashmap! {
|
|
||||||
// "Records.intVal" => "a",
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let a = ErrorType::FlexVar("a".into());
|
|
||||||
|
|
||||||
// let mut record = SendMap::default();
|
|
||||||
// record.insert("x".into(), a);
|
|
||||||
|
|
||||||
// let problem = Problem::Mismatch(
|
|
||||||
// Mismatch::TypeMismatch,
|
|
||||||
// ErrorType::Record(SendMap::default(), TypeExt::Closed),
|
|
||||||
// ErrorType::Record(record, TypeExt::FlexOpen("b".into())),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// assert_eq!(loaded_module.problems, vec![problem]);
|
|
||||||
// assert_eq!(expected_types.len(), loaded_module.declarations.len());
|
|
||||||
|
|
||||||
// let mut subs = loaded_module.solved.into_inner();
|
|
||||||
|
|
||||||
// for decl in loaded_module.declarations {
|
|
||||||
// let def = match decl {
|
|
||||||
// Declare(def) => def,
|
|
||||||
// rec_decl @ DeclareRec(_) => {
|
|
||||||
// panic!(
|
|
||||||
// "Unexpected recursive def in module declarations: {:?}",
|
|
||||||
// rec_decl
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// cycle @ InvalidCycle(_, _) => {
|
|
||||||
// panic!("Unexpected cyclic def in module declarations: {:?}", cycle);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// for (symbol, expr_var) in def.pattern_vars {
|
|
||||||
// let content = subs.get(expr_var).content;
|
|
||||||
|
|
||||||
// name_all_type_vars(expr_var, &mut subs);
|
|
||||||
|
|
||||||
// let actual_str = content_to_string(content, &mut subs);
|
|
||||||
// let expected_type = expected_types.get(symbol.as_str()).unwrap_or_else(|| {
|
|
||||||
// panic!("Defs included an unexpected symbol: {:?}", symbol)
|
|
||||||
// });
|
|
||||||
|
|
||||||
// assert_eq!((&symbol, expected_type), (&symbol, &actual_str.as_str()));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
|
|
@ -827,6 +827,11 @@ define_builtins! {
|
||||||
83 NUM_SUB_CHECKED: "subChecked"
|
83 NUM_SUB_CHECKED: "subChecked"
|
||||||
84 NUM_MUL_WRAP: "mulWrap"
|
84 NUM_MUL_WRAP: "mulWrap"
|
||||||
85 NUM_MUL_CHECKED: "mulChecked"
|
85 NUM_MUL_CHECKED: "mulChecked"
|
||||||
|
86 NUM_INT: "Int" imported
|
||||||
|
87 NUM_FLOAT: "Float" imported
|
||||||
|
88 NUM_AT_NATURAL: "@Natural"
|
||||||
|
89 NUM_NATURAL: "Natural" imported
|
||||||
|
90 NUM_NAT: "Nat" imported
|
||||||
}
|
}
|
||||||
2 BOOL: "Bool" => {
|
2 BOOL: "Bool" => {
|
||||||
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias
|
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias
|
||||||
|
|
|
@ -445,10 +445,10 @@ fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut V
|
||||||
num_alts: union.alternatives.len(),
|
num_alts: union.alternatives.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
IntLiteral(v) => {
|
IntLiteral(_, v) => {
|
||||||
all_tests.push(guarded(IsInt(*v)));
|
all_tests.push(guarded(IsInt(*v)));
|
||||||
}
|
}
|
||||||
FloatLiteral(v) => {
|
FloatLiteral(_, v) => {
|
||||||
all_tests.push(IsFloat(*v));
|
all_tests.push(IsFloat(*v));
|
||||||
}
|
}
|
||||||
StrLiteral(v) => {
|
StrLiteral(v) => {
|
||||||
|
@ -636,7 +636,7 @@ fn to_relevant_branch_help<'a>(
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
|
||||||
IntLiteral(int) => match test {
|
IntLiteral(_, int) => match test {
|
||||||
IsInt(is_int) if int == *is_int => {
|
IsInt(is_int) if int == *is_int => {
|
||||||
start.extend(end);
|
start.extend(end);
|
||||||
Some(Branch {
|
Some(Branch {
|
||||||
|
@ -647,7 +647,7 @@ fn to_relevant_branch_help<'a>(
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
|
||||||
FloatLiteral(float) => match test {
|
FloatLiteral(_, float) => match test {
|
||||||
IsFloat(test_float) if float == *test_float => {
|
IsFloat(test_float) if float == *test_float => {
|
||||||
start.extend(end);
|
start.extend(end);
|
||||||
Some(Branch {
|
Some(Branch {
|
||||||
|
@ -740,8 +740,8 @@ fn needs_tests(pattern: &Pattern) -> bool {
|
||||||
| AppliedTag { .. }
|
| AppliedTag { .. }
|
||||||
| BitLiteral { .. }
|
| BitLiteral { .. }
|
||||||
| EnumLiteral { .. }
|
| EnumLiteral { .. }
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_) => true,
|
| StrLiteral(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ fn simplify(pattern: &crate::ir::Pattern) -> Pattern {
|
||||||
use crate::ir::Pattern::*;
|
use crate::ir::Pattern::*;
|
||||||
|
|
||||||
match pattern {
|
match pattern {
|
||||||
IntLiteral(v) => Literal(Literal::Int(*v)),
|
IntLiteral(_, v) => Literal(Literal::Int(*v)),
|
||||||
FloatLiteral(v) => Literal(Literal::Float(*v)),
|
FloatLiteral(_, v) => Literal(Literal::Float(*v)),
|
||||||
StrLiteral(v) => Literal(Literal::Str(v.clone())),
|
StrLiteral(v) => Literal(Literal::Str(v.clone())),
|
||||||
|
|
||||||
// To make sure these are exhaustive, we have to "fake" a union here
|
// To make sure these are exhaustive, we have to "fake" a union here
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use self::InProgressProc::*;
|
use self::InProgressProc::*;
|
||||||
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
||||||
use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem};
|
use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem, TAG_SIZE};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
||||||
|
@ -691,6 +691,7 @@ pub struct Env<'a, 'i> {
|
||||||
pub problems: &'i mut std::vec::Vec<MonoProblem>,
|
pub problems: &'i mut std::vec::Vec<MonoProblem>,
|
||||||
pub home: ModuleId,
|
pub home: ModuleId,
|
||||||
pub ident_ids: &'i mut IdentIds,
|
pub ident_ids: &'i mut IdentIds,
|
||||||
|
pub ptr_bytes: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'i> Env<'a, 'i> {
|
impl<'a, 'i> Env<'a, 'i> {
|
||||||
|
@ -1492,7 +1493,7 @@ fn pattern_to_when<'a>(
|
||||||
(symbol, Located::at_zero(wrapped_body))
|
(symbol, Located::at_zero(wrapped_body))
|
||||||
}
|
}
|
||||||
|
|
||||||
IntLiteral(_) | NumLiteral(_, _) | FloatLiteral(_) | StrLiteral(_) => {
|
IntLiteral(_, _) | NumLiteral(_, _) | FloatLiteral(_, _) | StrLiteral(_) => {
|
||||||
// These patters are refutable, and thus should never occur outside a `when` expression
|
// These patters are refutable, and thus should never occur outside a `when` expression
|
||||||
// They should have been replaced with `UnsupportedPattern` during canonicalization
|
// They should have been replaced with `UnsupportedPattern` during canonicalization
|
||||||
unreachable!("refutable pattern {:?} where irrefutable pattern is expected. This should never happen!", pattern.value)
|
unreachable!("refutable pattern {:?} where irrefutable pattern is expected. This should never happen!", pattern.value)
|
||||||
|
@ -2357,19 +2358,41 @@ pub fn with_hole<'a>(
|
||||||
let arena = env.arena;
|
let arena = env.arena;
|
||||||
|
|
||||||
match can_expr {
|
match can_expr {
|
||||||
Int(_, num) => Stmt::Let(
|
Int(_, precision, num) => {
|
||||||
assigned,
|
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, false) {
|
||||||
Expr::Literal(Literal::Int(num)),
|
IntOrFloat::SignedIntType(precision) => Stmt::Let(
|
||||||
Layout::Builtin(Builtin::Int64),
|
assigned,
|
||||||
hole,
|
Expr::Literal(Literal::Int(num)),
|
||||||
),
|
Layout::Builtin(int_precision_to_builtin(precision)),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
IntOrFloat::UnsignedIntType(precision) => Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::Literal(Literal::Int(num)),
|
||||||
|
Layout::Builtin(int_precision_to_builtin(precision)),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
_ => unreachable!("unexpected float precision for integer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Float(_, num) => Stmt::Let(
|
Float(_, precision, num) => {
|
||||||
assigned,
|
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, true) {
|
||||||
Expr::Literal(Literal::Float(num)),
|
IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
|
||||||
Layout::Builtin(Builtin::Float64),
|
assigned,
|
||||||
hole,
|
Expr::Literal(Literal::Float(num as f64)),
|
||||||
),
|
Layout::Builtin(float_precision_to_builtin(precision)),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
IntOrFloat::DecimalFloatType(precision) => Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::Literal(Literal::Float(num as f64)),
|
||||||
|
Layout::Builtin(float_precision_to_builtin(precision)),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
_ => unreachable!("unexpected float precision for integer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Str(string) => Stmt::Let(
|
Str(string) => Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
|
@ -2378,17 +2401,29 @@ pub fn with_hole<'a>(
|
||||||
hole,
|
hole,
|
||||||
),
|
),
|
||||||
|
|
||||||
Num(var, num) => match num_argument_to_int_or_float(env.subs, var) {
|
Num(var, num) => match num_argument_to_int_or_float(env.subs, env.ptr_bytes, var, false) {
|
||||||
IntOrFloat::IntType => Stmt::Let(
|
IntOrFloat::SignedIntType(precision) => Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::Literal(Literal::Int(num)),
|
Expr::Literal(Literal::Int(num)),
|
||||||
Layout::Builtin(Builtin::Int64),
|
Layout::Builtin(int_precision_to_builtin(precision)),
|
||||||
hole,
|
hole,
|
||||||
),
|
),
|
||||||
IntOrFloat::FloatType => Stmt::Let(
|
IntOrFloat::UnsignedIntType(precision) => Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::Literal(Literal::Int(num)),
|
||||||
|
Layout::Builtin(int_precision_to_builtin(precision)),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::Literal(Literal::Float(num as f64)),
|
Expr::Literal(Literal::Float(num as f64)),
|
||||||
Layout::Builtin(Builtin::Float64),
|
Layout::Builtin(float_precision_to_builtin(precision)),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
IntOrFloat::DecimalFloatType(precision) => Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::Literal(Literal::Float(num as f64)),
|
||||||
|
Layout::Builtin(float_precision_to_builtin(precision)),
|
||||||
hole,
|
hole,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -2778,7 +2813,7 @@ pub fn with_hole<'a>(
|
||||||
stmt = Stmt::Let(
|
stmt = Stmt::Let(
|
||||||
tag_id_symbol,
|
tag_id_symbol,
|
||||||
Expr::Literal(Literal::Int(tag_id as i64)),
|
Expr::Literal(Literal::Int(tag_id as i64)),
|
||||||
Layout::Builtin(Builtin::Int64),
|
Layout::Builtin(TAG_SIZE),
|
||||||
arena.alloc(stmt),
|
arena.alloc(stmt),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4739,8 +4774,8 @@ fn store_pattern<'a>(
|
||||||
Underscore => {
|
Underscore => {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
IntLiteral(_)
|
IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| EnumLiteral { .. }
|
| EnumLiteral { .. }
|
||||||
| BitLiteral { .. }
|
| BitLiteral { .. }
|
||||||
| StrLiteral(_) => {}
|
| StrLiteral(_) => {}
|
||||||
|
@ -4754,7 +4789,7 @@ fn store_pattern<'a>(
|
||||||
|
|
||||||
if write_tag {
|
if write_tag {
|
||||||
// add an element for the tag discriminant
|
// add an element for the tag discriminant
|
||||||
arg_layouts.push(Layout::Builtin(Builtin::Int64));
|
arg_layouts.push(Layout::Builtin(TAG_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (_, layout) in arguments {
|
for (_, layout) in arguments {
|
||||||
|
@ -4779,8 +4814,8 @@ fn store_pattern<'a>(
|
||||||
Underscore => {
|
Underscore => {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
IntLiteral(_)
|
IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| EnumLiteral { .. }
|
| EnumLiteral { .. }
|
||||||
| BitLiteral { .. }
|
| BitLiteral { .. }
|
||||||
| StrLiteral(_) => {}
|
| StrLiteral(_) => {}
|
||||||
|
@ -4874,8 +4909,8 @@ fn store_record_destruct<'a>(
|
||||||
//
|
//
|
||||||
// internally. But `y` is never used, so we must make sure it't not stored/loaded.
|
// internally. But `y` is never used, so we must make sure it't not stored/loaded.
|
||||||
}
|
}
|
||||||
IntLiteral(_)
|
IntLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| EnumLiteral { .. }
|
| EnumLiteral { .. }
|
||||||
| BitLiteral { .. }
|
| BitLiteral { .. }
|
||||||
| StrLiteral(_) => {}
|
| StrLiteral(_) => {}
|
||||||
|
@ -5619,9 +5654,8 @@ fn call_by_name<'a>(
|
||||||
pub enum Pattern<'a> {
|
pub enum Pattern<'a> {
|
||||||
Identifier(Symbol),
|
Identifier(Symbol),
|
||||||
Underscore,
|
Underscore,
|
||||||
|
IntLiteral(Variable, i64),
|
||||||
IntLiteral(i64),
|
FloatLiteral(Variable, u64),
|
||||||
FloatLiteral(u64),
|
|
||||||
BitLiteral {
|
BitLiteral {
|
||||||
value: bool,
|
value: bool,
|
||||||
tag_name: TagName,
|
tag_name: TagName,
|
||||||
|
@ -5694,23 +5728,28 @@ fn from_can_pattern_help<'a>(
|
||||||
match can_pattern {
|
match can_pattern {
|
||||||
Underscore => Ok(Pattern::Underscore),
|
Underscore => Ok(Pattern::Underscore),
|
||||||
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
||||||
IntLiteral(v) => Ok(Pattern::IntLiteral(*v)),
|
IntLiteral(precision_var, int) => Ok(Pattern::IntLiteral(*precision_var, *int)),
|
||||||
FloatLiteral(v) => Ok(Pattern::FloatLiteral(f64::to_bits(*v))),
|
FloatLiteral(precision_var, float) => {
|
||||||
|
Ok(Pattern::FloatLiteral(*precision_var, f64::to_bits(*float)))
|
||||||
|
}
|
||||||
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
||||||
Shadowed(region, ident) => Err(RuntimeError::Shadowing {
|
Shadowed(region, ident) => Err(RuntimeError::Shadowing {
|
||||||
original_region: *region,
|
original_region: *region,
|
||||||
shadow: ident.clone(),
|
shadow: ident.clone(),
|
||||||
}),
|
}),
|
||||||
UnsupportedPattern(region) => Err(RuntimeError::UnsupportedPattern(*region)),
|
UnsupportedPattern(region) => Err(RuntimeError::UnsupportedPattern(*region)),
|
||||||
|
|
||||||
MalformedPattern(_problem, region) => {
|
MalformedPattern(_problem, region) => {
|
||||||
// TODO preserve malformed problem information here?
|
// TODO preserve malformed problem information here?
|
||||||
Err(RuntimeError::UnsupportedPattern(*region))
|
Err(RuntimeError::UnsupportedPattern(*region))
|
||||||
}
|
}
|
||||||
NumLiteral(var, num) => match num_argument_to_int_or_float(env.subs, *var) {
|
NumLiteral(var, num) => {
|
||||||
IntOrFloat::IntType => Ok(Pattern::IntLiteral(*num)),
|
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
|
||||||
IntOrFloat::FloatType => Ok(Pattern::FloatLiteral(*num as u64)),
|
IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*var, *num)),
|
||||||
},
|
IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*var, *num)),
|
||||||
|
IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(*var, *num as u64)),
|
||||||
|
IntOrFloat::DecimalFloatType(_) => Ok(Pattern::FloatLiteral(*var, *num as u64)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AppliedTag {
|
AppliedTag {
|
||||||
whole_var,
|
whole_var,
|
||||||
|
@ -5798,13 +5837,11 @@ fn from_can_pattern_help<'a>(
|
||||||
let mut arguments = arguments.clone();
|
let mut arguments = arguments.clone();
|
||||||
|
|
||||||
arguments.sort_by(|arg1, arg2| {
|
arguments.sort_by(|arg1, arg2| {
|
||||||
let ptr_bytes = 8;
|
|
||||||
|
|
||||||
let layout1 = layout_cache.from_var(env.arena, arg1.0, env.subs).unwrap();
|
let layout1 = layout_cache.from_var(env.arena, arg1.0, env.subs).unwrap();
|
||||||
let layout2 = layout_cache.from_var(env.arena, arg2.0, env.subs).unwrap();
|
let layout2 = layout_cache.from_var(env.arena, arg2.0, env.subs).unwrap();
|
||||||
|
|
||||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
let size1 = layout1.alignment_bytes(env.ptr_bytes);
|
||||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
let size2 = layout2.alignment_bytes(env.ptr_bytes);
|
||||||
|
|
||||||
size2.cmp(&size1)
|
size2.cmp(&size1)
|
||||||
});
|
});
|
||||||
|
@ -5855,13 +5892,11 @@ fn from_can_pattern_help<'a>(
|
||||||
let mut arguments = arguments.clone();
|
let mut arguments = arguments.clone();
|
||||||
|
|
||||||
arguments.sort_by(|arg1, arg2| {
|
arguments.sort_by(|arg1, arg2| {
|
||||||
let ptr_bytes = 8;
|
|
||||||
|
|
||||||
let layout1 = layout_cache.from_var(env.arena, arg1.0, env.subs).unwrap();
|
let layout1 = layout_cache.from_var(env.arena, arg1.0, env.subs).unwrap();
|
||||||
let layout2 = layout_cache.from_var(env.arena, arg2.0, env.subs).unwrap();
|
let layout2 = layout_cache.from_var(env.arena, arg2.0, env.subs).unwrap();
|
||||||
|
|
||||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
let size1 = layout1.alignment_bytes(env.ptr_bytes);
|
||||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
let size2 = layout2.alignment_bytes(env.ptr_bytes);
|
||||||
|
|
||||||
size2.cmp(&size1)
|
size2.cmp(&size1)
|
||||||
});
|
});
|
||||||
|
@ -6084,40 +6119,150 @@ fn optimize_low_level(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum IntPrecision {
|
||||||
|
I128,
|
||||||
|
I64,
|
||||||
|
I32,
|
||||||
|
I16,
|
||||||
|
I8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum FloatPrecision {
|
||||||
|
F64,
|
||||||
|
F32,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum IntOrFloat {
|
pub enum IntOrFloat {
|
||||||
IntType,
|
SignedIntType(IntPrecision),
|
||||||
FloatType,
|
UnsignedIntType(IntPrecision),
|
||||||
|
BinaryFloatType(FloatPrecision),
|
||||||
|
DecimalFloatType(FloatPrecision),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn float_precision_to_builtin(precision: FloatPrecision) -> Builtin<'static> {
|
||||||
|
use FloatPrecision::*;
|
||||||
|
match precision {
|
||||||
|
F64 => Builtin::Float64,
|
||||||
|
F32 => Builtin::Float32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn int_precision_to_builtin(precision: IntPrecision) -> Builtin<'static> {
|
||||||
|
use IntPrecision::*;
|
||||||
|
match precision {
|
||||||
|
I128 => Builtin::Int128,
|
||||||
|
I64 => Builtin::Int64,
|
||||||
|
I32 => Builtin::Int32,
|
||||||
|
I16 => Builtin::Int16,
|
||||||
|
I8 => Builtin::Int8,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the `a` in `Num a`, determines whether it's an int or a float
|
/// Given the `a` in `Num a`, determines whether it's an int or a float
|
||||||
pub fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat {
|
pub fn num_argument_to_int_or_float(
|
||||||
|
subs: &Subs,
|
||||||
|
ptr_bytes: u32,
|
||||||
|
var: Variable,
|
||||||
|
known_to_be_float: bool,
|
||||||
|
) -> IntOrFloat {
|
||||||
match subs.get_without_compacting(var).content {
|
match subs.get_without_compacting(var).content {
|
||||||
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
Content::FlexVar(_) if known_to_be_float => IntOrFloat::BinaryFloatType(FloatPrecision::F64),
|
||||||
|
Content::FlexVar(_) => IntOrFloat::SignedIntType(IntPrecision::I64), // We default (Num *) to I64
|
||||||
|
|
||||||
|
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
// TODO: we probably need to match on the type of the arg
|
// Recurse on the second argument
|
||||||
IntOrFloat::IntType
|
num_argument_to_int_or_float(subs, ptr_bytes, args[0].1, false)
|
||||||
}
|
}
|
||||||
Content::FlexVar(_) => {
|
|
||||||
// If this was still a (Num *), assume compiling it to an Int
|
|
||||||
IntOrFloat::IntType
|
|
||||||
}
|
|
||||||
Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => {
|
|
||||||
debug_assert!(args.len() == 1);
|
|
||||||
|
|
||||||
// TODO: we probably need to match on the type of the arg
|
Content::Alias(Symbol::NUM_I128, _, _)
|
||||||
IntOrFloat::FloatType
|
| Content::Alias(Symbol::NUM_SIGNED128, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_SIGNED128, _, _) => {
|
||||||
|
IntOrFloat::SignedIntType(IntPrecision::I128)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_INT, _, _)// We default Integer to I64
|
||||||
|
| Content::Alias(Symbol::NUM_I64, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_SIGNED64, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_SIGNED64, _, _) => {
|
||||||
|
IntOrFloat::SignedIntType(IntPrecision::I64)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_I32, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_SIGNED32, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_SIGNED32, _, _) => {
|
||||||
|
IntOrFloat::SignedIntType(IntPrecision::I32)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_I16, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_SIGNED16, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_SIGNED16, _, _) => {
|
||||||
|
IntOrFloat::SignedIntType(IntPrecision::I16)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_I8, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_SIGNED8, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_SIGNED8, _, _) => {
|
||||||
|
IntOrFloat::SignedIntType(IntPrecision::I8)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_U128, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_UNSIGNED128, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_UNSIGNED128, _, _) => {
|
||||||
|
IntOrFloat::UnsignedIntType(IntPrecision::I128)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_U64, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_UNSIGNED64, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_UNSIGNED64, _, _) => {
|
||||||
|
IntOrFloat::UnsignedIntType(IntPrecision::I64)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_U32, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_UNSIGNED32, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_UNSIGNED32, _, _) => {
|
||||||
|
IntOrFloat::UnsignedIntType(IntPrecision::I32)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_U16, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_UNSIGNED16, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_UNSIGNED16, _, _) => {
|
||||||
|
IntOrFloat::UnsignedIntType(IntPrecision::I16)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_U8, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_UNSIGNED8, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_UNSIGNED8, _, _) => {
|
||||||
|
IntOrFloat::UnsignedIntType(IntPrecision::I8)
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, attr_args)) => {
|
Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, attr_args)) => {
|
||||||
debug_assert!(attr_args.len() == 2);
|
debug_assert!(attr_args.len() == 2);
|
||||||
|
|
||||||
// Recurse on the second argument
|
// Recurse on the second argument
|
||||||
num_argument_to_int_or_float(subs, attr_args[1])
|
num_argument_to_int_or_float(subs, ptr_bytes, attr_args[1], false)
|
||||||
}
|
}
|
||||||
Content::Alias(Symbol::NUM_F64, args, _) | Content::Alias(Symbol::NUM_F32, args, _) => {
|
Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => {
|
||||||
debug_assert!(args.is_empty());
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
IntOrFloat::FloatType
|
// Recurse on the second argument
|
||||||
|
num_argument_to_int_or_float(subs, ptr_bytes, args[0].1, true)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_FLOAT, _, _) // We default FloatingPoint to F64
|
||||||
|
| Content::Alias(Symbol::NUM_F64, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_BINARY64, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_BINARY64, _, _) => {
|
||||||
|
IntOrFloat::BinaryFloatType(FloatPrecision::F64)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_F32, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_BINARY32, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_BINARY32, _, _) => {
|
||||||
|
IntOrFloat::BinaryFloatType(FloatPrecision::F32)
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_NAT, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_NATURAL, _, _)
|
||||||
|
| Content::Alias(Symbol::NUM_AT_NATURAL, _, _) => {
|
||||||
|
match ptr_bytes {
|
||||||
|
1 => IntOrFloat::UnsignedIntType(IntPrecision::I8),
|
||||||
|
2 => IntOrFloat::UnsignedIntType(IntPrecision::I16),
|
||||||
|
4 => IntOrFloat::UnsignedIntType(IntPrecision::I32),
|
||||||
|
8 => IntOrFloat::UnsignedIntType(IntPrecision::I64),
|
||||||
|
_ => panic!(
|
||||||
|
"Invalid target for Num type arguement: Roc does't support compiling to {}-bit systems.",
|
||||||
|
ptr_bytes * 8
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
panic!(
|
panic!(
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub const MAX_ENUM_SIZE: usize = (std::mem::size_of::<u8>() * 8) as usize;
|
||||||
|
|
||||||
/// If a (Num *) gets translated to a Layout, this is the numeric type it defaults to.
|
/// If a (Num *) gets translated to a Layout, this is the numeric type it defaults to.
|
||||||
const DEFAULT_NUM_BUILTIN: Builtin<'_> = Builtin::Int64;
|
const DEFAULT_NUM_BUILTIN: Builtin<'_> = Builtin::Int64;
|
||||||
|
pub const TAG_SIZE: Builtin<'_> = Builtin::Int64;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum LayoutProblem {
|
pub enum LayoutProblem {
|
||||||
|
@ -312,6 +313,7 @@ pub enum Builtin<'a> {
|
||||||
Int16,
|
Int16,
|
||||||
Int8,
|
Int8,
|
||||||
Int1,
|
Int1,
|
||||||
|
Usize,
|
||||||
Float128,
|
Float128,
|
||||||
Float64,
|
Float64,
|
||||||
Float32,
|
Float32,
|
||||||
|
@ -362,14 +364,60 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
Structure(flat_type) => layout_from_flat_type(env, flat_type),
|
Structure(flat_type) => layout_from_flat_type(env, flat_type),
|
||||||
|
|
||||||
|
// Ints
|
||||||
|
Alias(Symbol::NUM_I128, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int128))
|
||||||
|
}
|
||||||
Alias(Symbol::NUM_I64, args, _) => {
|
Alias(Symbol::NUM_I64, args, _) => {
|
||||||
debug_assert!(args.is_empty());
|
debug_assert!(args.is_empty());
|
||||||
Ok(Layout::Builtin(Builtin::Int64))
|
Ok(Layout::Builtin(Builtin::Int64))
|
||||||
}
|
}
|
||||||
|
Alias(Symbol::NUM_I32, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int32))
|
||||||
|
}
|
||||||
|
Alias(Symbol::NUM_I16, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int16))
|
||||||
|
}
|
||||||
|
Alias(Symbol::NUM_I8, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int8))
|
||||||
|
}
|
||||||
|
|
||||||
|
// I think unsigned and signed use the same layout
|
||||||
|
Alias(Symbol::NUM_U128, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int128))
|
||||||
|
}
|
||||||
|
Alias(Symbol::NUM_U64, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int64))
|
||||||
|
}
|
||||||
|
Alias(Symbol::NUM_U32, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int32))
|
||||||
|
}
|
||||||
|
Alias(Symbol::NUM_U16, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int16))
|
||||||
|
}
|
||||||
|
Alias(Symbol::NUM_U8, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Int8))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floats
|
||||||
Alias(Symbol::NUM_F64, args, _) => {
|
Alias(Symbol::NUM_F64, args, _) => {
|
||||||
debug_assert!(args.is_empty());
|
debug_assert!(args.is_empty());
|
||||||
Ok(Layout::Builtin(Builtin::Float64))
|
Ok(Layout::Builtin(Builtin::Float64))
|
||||||
}
|
}
|
||||||
|
Alias(Symbol::NUM_F32, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
Ok(Layout::Builtin(Builtin::Float32))
|
||||||
|
}
|
||||||
|
|
||||||
Alias(_, _, var) => Self::from_var(env, var),
|
Alias(_, _, var) => Self::from_var(env, var),
|
||||||
Error => Err(LayoutProblem::Erroneous),
|
Error => Err(LayoutProblem::Erroneous),
|
||||||
}
|
}
|
||||||
|
@ -654,6 +702,7 @@ impl<'a> Builtin<'a> {
|
||||||
const I16_SIZE: u32 = std::mem::size_of::<i16>() as u32;
|
const I16_SIZE: u32 = std::mem::size_of::<i16>() as u32;
|
||||||
const I8_SIZE: u32 = std::mem::size_of::<i8>() as u32;
|
const I8_SIZE: u32 = std::mem::size_of::<i8>() as u32;
|
||||||
const I1_SIZE: u32 = std::mem::size_of::<bool>() as u32;
|
const I1_SIZE: u32 = std::mem::size_of::<bool>() as u32;
|
||||||
|
const USIZE_SIZE: u32 = std::mem::size_of::<usize>() as u32;
|
||||||
const F128_SIZE: u32 = 16;
|
const F128_SIZE: u32 = 16;
|
||||||
const F64_SIZE: u32 = std::mem::size_of::<f64>() as u32;
|
const F64_SIZE: u32 = std::mem::size_of::<f64>() as u32;
|
||||||
const F32_SIZE: u32 = std::mem::size_of::<f32>() as u32;
|
const F32_SIZE: u32 = std::mem::size_of::<f32>() as u32;
|
||||||
|
@ -682,6 +731,7 @@ impl<'a> Builtin<'a> {
|
||||||
Int16 => Builtin::I16_SIZE,
|
Int16 => Builtin::I16_SIZE,
|
||||||
Int8 => Builtin::I8_SIZE,
|
Int8 => Builtin::I8_SIZE,
|
||||||
Int1 => Builtin::I1_SIZE,
|
Int1 => Builtin::I1_SIZE,
|
||||||
|
Usize => Builtin::USIZE_SIZE,
|
||||||
Float128 => Builtin::F128_SIZE,
|
Float128 => Builtin::F128_SIZE,
|
||||||
Float64 => Builtin::F64_SIZE,
|
Float64 => Builtin::F64_SIZE,
|
||||||
Float32 => Builtin::F32_SIZE,
|
Float32 => Builtin::F32_SIZE,
|
||||||
|
@ -707,6 +757,7 @@ impl<'a> Builtin<'a> {
|
||||||
Int16 => align_of::<i16>() as u32,
|
Int16 => align_of::<i16>() as u32,
|
||||||
Int8 => align_of::<i8>() as u32,
|
Int8 => align_of::<i8>() as u32,
|
||||||
Int1 => align_of::<bool>() as u32,
|
Int1 => align_of::<bool>() as u32,
|
||||||
|
Usize => align_of::<usize>() as u32,
|
||||||
Float128 => align_of::<i128>() as u32,
|
Float128 => align_of::<i128>() as u32,
|
||||||
Float64 => align_of::<f64>() as u32,
|
Float64 => align_of::<f64>() as u32,
|
||||||
Float32 => align_of::<f32>() as u32,
|
Float32 => align_of::<f32>() as u32,
|
||||||
|
@ -722,7 +773,7 @@ impl<'a> Builtin<'a> {
|
||||||
use Builtin::*;
|
use Builtin::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Float128 | Float64 | Float32
|
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
||||||
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => true,
|
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => true,
|
||||||
Str | Dict(_, _) | Set(_) | List(_, _) => false,
|
Str | Dict(_, _) | Set(_) | List(_, _) => false,
|
||||||
}
|
}
|
||||||
|
@ -733,7 +784,7 @@ impl<'a> Builtin<'a> {
|
||||||
use Builtin::*;
|
use Builtin::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Float128 | Float64 | Float32
|
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
||||||
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => false,
|
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => false,
|
||||||
List(mode, element_layout) => match mode {
|
List(mode, element_layout) => match mode {
|
||||||
MemoryMode::Refcounted => true,
|
MemoryMode::Refcounted => true,
|
||||||
|
@ -757,14 +808,64 @@ fn layout_from_flat_type<'a>(
|
||||||
match flat_type {
|
match flat_type {
|
||||||
Apply(symbol, args) => {
|
Apply(symbol, args) => {
|
||||||
match symbol {
|
match symbol {
|
||||||
|
// Ints
|
||||||
|
Symbol::NUM_NAT => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Usize))
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol::NUM_I128 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int128))
|
||||||
|
}
|
||||||
Symbol::NUM_I64 => {
|
Symbol::NUM_I64 => {
|
||||||
debug_assert_eq!(args.len(), 0);
|
debug_assert_eq!(args.len(), 0);
|
||||||
Ok(Layout::Builtin(Builtin::Int64))
|
Ok(Layout::Builtin(Builtin::Int64))
|
||||||
}
|
}
|
||||||
|
Symbol::NUM_I32 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int32))
|
||||||
|
}
|
||||||
|
Symbol::NUM_I16 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int16))
|
||||||
|
}
|
||||||
|
Symbol::NUM_I8 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int8))
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol::NUM_U128 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int128))
|
||||||
|
}
|
||||||
|
Symbol::NUM_U64 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int64))
|
||||||
|
}
|
||||||
|
Symbol::NUM_U32 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int32))
|
||||||
|
}
|
||||||
|
Symbol::NUM_U16 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int16))
|
||||||
|
}
|
||||||
|
Symbol::NUM_U8 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Int8))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floats
|
||||||
Symbol::NUM_F64 => {
|
Symbol::NUM_F64 => {
|
||||||
debug_assert_eq!(args.len(), 0);
|
debug_assert_eq!(args.len(), 0);
|
||||||
Ok(Layout::Builtin(Builtin::Float64))
|
Ok(Layout::Builtin(Builtin::Float64))
|
||||||
}
|
}
|
||||||
|
Symbol::NUM_F32 => {
|
||||||
|
debug_assert_eq!(args.len(), 0);
|
||||||
|
Ok(Layout::Builtin(Builtin::Float32))
|
||||||
|
}
|
||||||
|
|
||||||
Symbol::NUM_NUM | Symbol::NUM_AT_NUM => {
|
Symbol::NUM_NUM | Symbol::NUM_AT_NUM => {
|
||||||
// Num.Num should only ever have 1 argument, e.g. Num.Num Int.Integer
|
// Num.Num should only ever have 1 argument, e.g. Num.Num Int.Integer
|
||||||
debug_assert_eq!(args.len(), 1);
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
@ -774,6 +875,7 @@ fn layout_from_flat_type<'a>(
|
||||||
|
|
||||||
layout_from_num_content(content)
|
layout_from_num_content(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol::STR_STR => Ok(Layout::Builtin(Builtin::Str)),
|
Symbol::STR_STR => Ok(Layout::Builtin(Builtin::Str)),
|
||||||
Symbol::LIST_LIST => list_layout_from_elem(env, args[0]),
|
Symbol::LIST_LIST => list_layout_from_elem(env, args[0]),
|
||||||
Symbol::ATTR_ATTR => {
|
Symbol::ATTR_ATTR => {
|
||||||
|
@ -888,7 +990,7 @@ fn layout_from_flat_type<'a>(
|
||||||
let mut tag_layout = Vec::with_capacity_in(variables.len() + 1, arena);
|
let mut tag_layout = Vec::with_capacity_in(variables.len() + 1, arena);
|
||||||
|
|
||||||
// store the discriminant
|
// store the discriminant
|
||||||
tag_layout.push(Layout::Builtin(Builtin::Int64));
|
tag_layout.push(Layout::Builtin(TAG_SIZE));
|
||||||
|
|
||||||
for var in variables {
|
for var in variables {
|
||||||
// TODO does this cause problems with mutually recursive unions?
|
// TODO does this cause problems with mutually recursive unions?
|
||||||
|
@ -1119,7 +1221,7 @@ pub fn union_sorted_tags_help<'a>(
|
||||||
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, arena);
|
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, arena);
|
||||||
|
|
||||||
// add the tag discriminant (size currently always hardcoded to i64)
|
// add the tag discriminant (size currently always hardcoded to i64)
|
||||||
arg_layouts.push(Layout::Builtin(Builtin::Int64));
|
arg_layouts.push(Layout::Builtin(TAG_SIZE));
|
||||||
|
|
||||||
for var in arguments {
|
for var in arguments {
|
||||||
match Layout::from_var(&mut env, var) {
|
match Layout::from_var(&mut env, var) {
|
||||||
|
@ -1257,8 +1359,27 @@ fn layout_from_num_content<'a>(content: Content) -> Result<Layout<'a>, LayoutPro
|
||||||
Ok(Layout::Builtin(DEFAULT_NUM_BUILTIN))
|
Ok(Layout::Builtin(DEFAULT_NUM_BUILTIN))
|
||||||
}
|
}
|
||||||
Structure(Apply(symbol, args)) => match symbol {
|
Structure(Apply(symbol, args)) => match symbol {
|
||||||
|
// Ints
|
||||||
|
Symbol::NUM_NAT => Ok(Layout::Builtin(Builtin::Usize)),
|
||||||
|
|
||||||
Symbol::NUM_INTEGER => Ok(Layout::Builtin(Builtin::Int64)),
|
Symbol::NUM_INTEGER => Ok(Layout::Builtin(Builtin::Int64)),
|
||||||
|
Symbol::NUM_I128 => Ok(Layout::Builtin(Builtin::Int128)),
|
||||||
|
Symbol::NUM_I64 => Ok(Layout::Builtin(Builtin::Int64)),
|
||||||
|
Symbol::NUM_I32 => Ok(Layout::Builtin(Builtin::Int32)),
|
||||||
|
Symbol::NUM_I16 => Ok(Layout::Builtin(Builtin::Int16)),
|
||||||
|
Symbol::NUM_I8 => Ok(Layout::Builtin(Builtin::Int8)),
|
||||||
|
|
||||||
|
Symbol::NUM_U128 => Ok(Layout::Builtin(Builtin::Int128)),
|
||||||
|
Symbol::NUM_U64 => Ok(Layout::Builtin(Builtin::Int64)),
|
||||||
|
Symbol::NUM_U32 => Ok(Layout::Builtin(Builtin::Int32)),
|
||||||
|
Symbol::NUM_U16 => Ok(Layout::Builtin(Builtin::Int16)),
|
||||||
|
Symbol::NUM_U8 => Ok(Layout::Builtin(Builtin::Int8)),
|
||||||
|
|
||||||
|
// Floats
|
||||||
Symbol::NUM_FLOATINGPOINT => Ok(Layout::Builtin(Builtin::Float64)),
|
Symbol::NUM_FLOATINGPOINT => Ok(Layout::Builtin(Builtin::Float64)),
|
||||||
|
Symbol::NUM_F64 => Ok(Layout::Builtin(Builtin::Float64)),
|
||||||
|
Symbol::NUM_F32 => Ok(Layout::Builtin(Builtin::Float32)),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
panic!(
|
panic!(
|
||||||
"Invalid Num.Num type application: {:?}",
|
"Invalid Num.Num type application: {:?}",
|
||||||
|
@ -1293,16 +1414,62 @@ fn unwrap_num_tag<'a>(subs: &Subs, var: Variable) -> Result<Layout<'a>, LayoutPr
|
||||||
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
// TODO: we probably need to match on the type of the arg
|
let (_, precision_var) = args[0];
|
||||||
// and return the correct builtin ex: Builtin::{Int32, Int16}
|
|
||||||
Ok(Layout::Builtin(Builtin::Int64))
|
let precision = subs.get_without_compacting(precision_var).content;
|
||||||
|
|
||||||
|
match precision {
|
||||||
|
Content::Alias(symbol, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
|
||||||
|
let builtin = match symbol {
|
||||||
|
Symbol::NUM_SIGNED128 => Builtin::Int128,
|
||||||
|
Symbol::NUM_SIGNED64 => Builtin::Int64,
|
||||||
|
Symbol::NUM_SIGNED32 => Builtin::Int32,
|
||||||
|
Symbol::NUM_SIGNED16 => Builtin::Int16,
|
||||||
|
Symbol::NUM_SIGNED8 => Builtin::Int8,
|
||||||
|
Symbol::NUM_UNSIGNED128 => Builtin::Int128,
|
||||||
|
Symbol::NUM_UNSIGNED64 => Builtin::Int64,
|
||||||
|
Symbol::NUM_UNSIGNED32 => Builtin::Int32,
|
||||||
|
Symbol::NUM_UNSIGNED16 => Builtin::Int16,
|
||||||
|
Symbol::NUM_UNSIGNED8 => Builtin::Int8,
|
||||||
|
Symbol::NUM_NATURAL => Builtin::Usize,
|
||||||
|
_ => unreachable!("not a valid int variant: {:?} {:?}", symbol, args),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Layout::Builtin(builtin))
|
||||||
|
}
|
||||||
|
Content::FlexVar(_) | Content::RigidVar(_) => {
|
||||||
|
// default to i64
|
||||||
|
Ok(Layout::Builtin(Builtin::Int64))
|
||||||
|
}
|
||||||
|
_ => unreachable!("not a valid int variant: {:?}", precision),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => {
|
Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => {
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
// TODO: we probably need to match on the type of the arg
|
let (_, precision_var) = args[0];
|
||||||
// and return the correct builtin ex: Builtin::Float32
|
|
||||||
Ok(Layout::Builtin(Builtin::Float64))
|
let precision = subs.get_without_compacting(precision_var).content;
|
||||||
|
|
||||||
|
match precision {
|
||||||
|
Content::Alias(Symbol::NUM_BINARY32, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
|
||||||
|
Ok(Layout::Builtin(Builtin::Float32))
|
||||||
|
}
|
||||||
|
Content::Alias(Symbol::NUM_BINARY64, args, _) => {
|
||||||
|
debug_assert!(args.is_empty());
|
||||||
|
|
||||||
|
Ok(Layout::Builtin(Builtin::Float64))
|
||||||
|
}
|
||||||
|
Content::FlexVar(_) | Content::RigidVar(_) => {
|
||||||
|
// default to f64
|
||||||
|
Ok(Layout::Builtin(Builtin::Float64))
|
||||||
|
}
|
||||||
|
_ => unreachable!("not a valid float variant: {:?}", precision),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Content::FlexVar(_) | Content::RigidVar(_) => {
|
Content::FlexVar(_) | Content::RigidVar(_) => {
|
||||||
// If this was still a (Num *) then default to compiling it to i64
|
// If this was still a (Num *) then default to compiling it to i64
|
||||||
|
|
|
@ -61,6 +61,7 @@ mod test_mono {
|
||||||
stdlib,
|
stdlib,
|
||||||
src_dir,
|
src_dir,
|
||||||
exposed_types,
|
exposed_types,
|
||||||
|
8,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = loaded.expect("failed to load module");
|
let mut loaded = loaded.expect("failed to load module");
|
||||||
|
|
|
@ -1624,8 +1624,8 @@ fn to_diff<'b>(
|
||||||
let right = to_doc(alloc, Parens::Unnecessary, type2);
|
let right = to_doc(alloc, Parens::Unnecessary, type2);
|
||||||
|
|
||||||
let is_int = |t: &ErrorType| match t {
|
let is_int = |t: &ErrorType| match t {
|
||||||
ErrorType::Type(Symbol::NUM_I64, _) => true,
|
ErrorType::Type(Symbol::NUM_INT, _) => true,
|
||||||
ErrorType::Alias(Symbol::NUM_I64, _, _) => true,
|
ErrorType::Alias(Symbol::NUM_INT, _, _) => true,
|
||||||
|
|
||||||
ErrorType::Type(Symbol::NUM_NUM, args) => {
|
ErrorType::Type(Symbol::NUM_NUM, args) => {
|
||||||
matches!( &args.get(0) ,Some(ErrorType::Type(Symbol::NUM_INTEGER, _)) | Some(ErrorType::Alias(Symbol::NUM_INTEGER, _, _)))
|
matches!( &args.get(0) ,Some(ErrorType::Type(Symbol::NUM_INTEGER, _)) | Some(ErrorType::Alias(Symbol::NUM_INTEGER, _, _)))
|
||||||
|
@ -1636,8 +1636,8 @@ fn to_diff<'b>(
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
let is_float = |t: &ErrorType| match t {
|
let is_float = |t: &ErrorType| match t {
|
||||||
ErrorType::Type(Symbol::NUM_F64, _) => true,
|
ErrorType::Type(Symbol::NUM_FLOAT, _) => true,
|
||||||
ErrorType::Alias(Symbol::NUM_F64, _, _) => true,
|
ErrorType::Alias(Symbol::NUM_FLOAT, _, _) => true,
|
||||||
|
|
||||||
ErrorType::Type(Symbol::NUM_NUM, args) => {
|
ErrorType::Type(Symbol::NUM_NUM, args) => {
|
||||||
matches!(&args.get(0), Some(ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _)) | Some(ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _)))
|
matches!(&args.get(0), Some(ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _)) | Some(ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _)))
|
||||||
|
@ -1891,7 +1891,7 @@ fn diff_tag_union<'b>(
|
||||||
alloc.tag_name(field.clone()),
|
alloc.tag_name(field.clone()),
|
||||||
// TODO add spaces between args
|
// TODO add spaces between args
|
||||||
args.iter()
|
args.iter()
|
||||||
.map(|arg| to_doc(alloc, Parens::Unnecessary, arg.clone()))
|
.map(|arg| to_doc(alloc, Parens::InTypeParam, arg.clone()))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,6 +94,7 @@ mod test_reporting {
|
||||||
problems: &mut mono_problems,
|
problems: &mut mono_problems,
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
|
ptr_bytes: 8,
|
||||||
};
|
};
|
||||||
let _mono_expr = Stmt::new(
|
let _mono_expr = Stmt::new(
|
||||||
&mut mono_env,
|
&mut mono_env,
|
||||||
|
@ -446,9 +447,9 @@ mod test_reporting {
|
||||||
these names seem close though:
|
these names seem close though:
|
||||||
|
|
||||||
baz
|
baz
|
||||||
|
Nat
|
||||||
Str
|
Str
|
||||||
U8
|
U8
|
||||||
F64
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -960,7 +961,7 @@ mod test_reporting {
|
||||||
r#"
|
r#"
|
||||||
bar = { bar : 0x3 }
|
bar = { bar : 0x3 }
|
||||||
|
|
||||||
f : { foo : I64 } -> Bool
|
f : { foo : Int * } -> Bool
|
||||||
f = \_ -> True
|
f = \_ -> True
|
||||||
|
|
||||||
f bar
|
f bar
|
||||||
|
@ -977,11 +978,11 @@ mod test_reporting {
|
||||||
|
|
||||||
This `bar` value is a:
|
This `bar` value is a:
|
||||||
|
|
||||||
{ bar : I64 }
|
{ bar : Int a }
|
||||||
|
|
||||||
But `f` needs the 1st argument to be:
|
But `f` needs the 1st argument to be:
|
||||||
|
|
||||||
{ foo : I64 }
|
{ foo : Int a }
|
||||||
|
|
||||||
Tip: Seems like a record field typo. Maybe `bar` should be `foo`?
|
Tip: Seems like a record field typo. Maybe `bar` should be `foo`?
|
||||||
|
|
||||||
|
@ -1036,7 +1037,7 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
f : [ Red I64, Green Bool ] -> Bool
|
f : [ Red (Int *), Green Bool ] -> Bool
|
||||||
f = \_ -> True
|
f = \_ -> True
|
||||||
|
|
||||||
f (Blue 3.14)
|
f (Blue 3.14)
|
||||||
|
@ -1053,11 +1054,11 @@ mod test_reporting {
|
||||||
|
|
||||||
This `Blue` global tag application has the type:
|
This `Blue` global tag application has the type:
|
||||||
|
|
||||||
[ Blue F64 ]a
|
[ Blue (Float a) ]b
|
||||||
|
|
||||||
But `f` needs the 1st argument to be:
|
But `f` needs the 1st argument to be:
|
||||||
|
|
||||||
[ Green Bool, Red I64 ]
|
[ Green Bool, Red (Int a) ]
|
||||||
|
|
||||||
Tip: Seems like a tag typo. Maybe `Blue` should be `Red`?
|
Tip: Seems like a tag typo. Maybe `Blue` should be `Red`?
|
||||||
|
|
||||||
|
@ -1074,7 +1075,7 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : I64
|
x : Int *
|
||||||
x = if True then 3.14 else 4
|
x = if True then 3.14 else 4
|
||||||
|
|
||||||
x
|
x
|
||||||
|
@ -1091,11 +1092,11 @@ mod test_reporting {
|
||||||
|
|
||||||
The 1st branch is a float of type:
|
The 1st branch is a float of type:
|
||||||
|
|
||||||
F64
|
Float a
|
||||||
|
|
||||||
But the type annotation on `x` says it should be:
|
But the type annotation on `x` says it should be:
|
||||||
|
|
||||||
I64
|
Int b
|
||||||
|
|
||||||
Tip: You can convert between Int and Float using functions like
|
Tip: You can convert between Int and Float using functions like
|
||||||
`Num.toFloat` and `Num.round`.
|
`Num.toFloat` and `Num.round`.
|
||||||
|
@ -1109,7 +1110,7 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : I64
|
x : Int *
|
||||||
x =
|
x =
|
||||||
when True is
|
when True is
|
||||||
_ -> 3.14
|
_ -> 3.14
|
||||||
|
@ -1123,18 +1124,18 @@ mod test_reporting {
|
||||||
|
|
||||||
Something is off with the body of the `x` definition:
|
Something is off with the body of the `x` definition:
|
||||||
|
|
||||||
1│ x : I64
|
1│ x : Int *
|
||||||
2│ x =
|
2│ x =
|
||||||
3│> when True is
|
3│> when True is
|
||||||
4│> _ -> 3.14
|
4│> _ -> 3.14
|
||||||
|
|
||||||
This `when`expression produces:
|
This `when`expression produces:
|
||||||
|
|
||||||
F64
|
Float a
|
||||||
|
|
||||||
But the type annotation on `x` says it should be:
|
But the type annotation on `x` says it should be:
|
||||||
|
|
||||||
I64
|
Int b
|
||||||
|
|
||||||
Tip: You can convert between Int and Float using functions like
|
Tip: You can convert between Int and Float using functions like
|
||||||
`Num.toFloat` and `Num.round`.
|
`Num.toFloat` and `Num.round`.
|
||||||
|
@ -1148,7 +1149,7 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : I64 -> I64
|
x : Int * -> Int *
|
||||||
x = \_ -> 3.14
|
x = \_ -> 3.14
|
||||||
|
|
||||||
x
|
x
|
||||||
|
@ -1160,17 +1161,17 @@ mod test_reporting {
|
||||||
|
|
||||||
Something is off with the body of the `x` definition:
|
Something is off with the body of the `x` definition:
|
||||||
|
|
||||||
1│ x : I64 -> I64
|
1│ x : Int * -> Int *
|
||||||
2│ x = \_ -> 3.14
|
2│ x = \_ -> 3.14
|
||||||
^^^^
|
^^^^
|
||||||
|
|
||||||
The body is a float of type:
|
The body is a float of type:
|
||||||
|
|
||||||
F64
|
Float a
|
||||||
|
|
||||||
But the type annotation on `x` says it should be:
|
But the type annotation on `x` says it should be:
|
||||||
|
|
||||||
I64
|
Int b
|
||||||
|
|
||||||
Tip: You can convert between Int and Float using functions like
|
Tip: You can convert between Int and Float using functions like
|
||||||
`Num.toFloat` and `Num.round`.
|
`Num.toFloat` and `Num.round`.
|
||||||
|
@ -1373,7 +1374,7 @@ mod test_reporting {
|
||||||
Bool
|
Bool
|
||||||
U8
|
U8
|
||||||
F64
|
F64
|
||||||
Str
|
Nat
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -1482,7 +1483,7 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
{ x } : { x : I64 }
|
{ x } : { x : Int * }
|
||||||
{ x } = { x: 4.0 }
|
{ x } = { x: 4.0 }
|
||||||
|
|
||||||
x
|
x
|
||||||
|
@ -1494,17 +1495,17 @@ mod test_reporting {
|
||||||
|
|
||||||
Something is off with the body of this definition:
|
Something is off with the body of this definition:
|
||||||
|
|
||||||
1│ { x } : { x : I64 }
|
1│ { x } : { x : Int * }
|
||||||
2│ { x } = { x: 4.0 }
|
2│ { x } = { x: 4.0 }
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
The body is a record of type:
|
The body is a record of type:
|
||||||
|
|
||||||
{ x : F64 }
|
{ x : Float a }
|
||||||
|
|
||||||
But the type annotation says it should be:
|
But the type annotation says it should be:
|
||||||
|
|
||||||
{ x : I64 }
|
{ x : Int b }
|
||||||
|
|
||||||
Tip: You can convert between Int and Float using functions like
|
Tip: You can convert between Int and Float using functions like
|
||||||
`Num.toFloat` and `Num.round`.
|
`Num.toFloat` and `Num.round`.
|
||||||
|
@ -1643,7 +1644,7 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
x : { a : I64, b : F64, c : Bool }
|
x : { a : Int *, b : Float *, c : Bool }
|
||||||
x = { b: 4.0 }
|
x = { b: 4.0 }
|
||||||
|
|
||||||
x
|
x
|
||||||
|
@ -1655,17 +1656,17 @@ mod test_reporting {
|
||||||
|
|
||||||
Something is off with the body of the `x` definition:
|
Something is off with the body of the `x` definition:
|
||||||
|
|
||||||
1│ x : { a : I64, b : F64, c : Bool }
|
1│ x : { a : Int *, b : Float *, c : Bool }
|
||||||
2│ x = { b: 4.0 }
|
2│ x = { b: 4.0 }
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
The body is a record of type:
|
The body is a record of type:
|
||||||
|
|
||||||
{ b : F64 }
|
{ b : Float a }
|
||||||
|
|
||||||
But the type annotation on `x` says it should be:
|
But the type annotation on `x` says it should be:
|
||||||
|
|
||||||
{ a : I64, b : F64, c : Bool }
|
{ a : Int a, b : Float b, c : Bool }
|
||||||
|
|
||||||
Tip: Looks like the c and a fields are missing.
|
Tip: Looks like the c and a fields are missing.
|
||||||
"#
|
"#
|
||||||
|
@ -1787,7 +1788,7 @@ mod test_reporting {
|
||||||
|
|
||||||
The body is an integer of type:
|
The body is an integer of type:
|
||||||
|
|
||||||
I64
|
Int a
|
||||||
|
|
||||||
But the type annotation on `f` says it should be:
|
But the type annotation on `f` says it should be:
|
||||||
|
|
||||||
|
@ -1795,7 +1796,7 @@ mod test_reporting {
|
||||||
|
|
||||||
Tip: The type annotation uses the type variable `msg` to say that this
|
Tip: The type annotation uses the type variable `msg` to say that this
|
||||||
definition can produce any type of value. But in the body I see that
|
definition can produce any type of value. But in the body I see that
|
||||||
it will only produce a `I64` value of a single specific type. Maybe
|
it will only produce a `Int` value of a single specific type. Maybe
|
||||||
change the type annotation to be more specific? Maybe change the code
|
change the type annotation to be more specific? Maybe change the code
|
||||||
to be more general?
|
to be more general?
|
||||||
"#
|
"#
|
||||||
|
@ -2093,7 +2094,7 @@ mod test_reporting {
|
||||||
|
|
||||||
But `add` needs the 2nd argument to be:
|
But `add` needs the 2nd argument to be:
|
||||||
|
|
||||||
Num (Integer Signed64)
|
Num (Integer a)
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -2118,11 +2119,11 @@ mod test_reporting {
|
||||||
|
|
||||||
This argument is a float of type:
|
This argument is a float of type:
|
||||||
|
|
||||||
F64
|
Float a
|
||||||
|
|
||||||
But `add` needs the 2nd argument to be:
|
But `add` needs the 2nd argument to be:
|
||||||
|
|
||||||
Num (Integer Signed64)
|
Num (Integer a)
|
||||||
|
|
||||||
Tip: You can convert between Int and Float using functions like
|
Tip: You can convert between Int and Float using functions like
|
||||||
`Num.toFloat` and `Num.round`.
|
`Num.toFloat` and `Num.round`.
|
||||||
|
@ -2580,9 +2581,9 @@ mod test_reporting {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
Foo : { x : I64 }
|
Foo : { x : Int * }
|
||||||
|
|
||||||
f : Foo -> I64
|
f : Foo -> Int *
|
||||||
f = \r -> r.x
|
f = \r -> r.x
|
||||||
|
|
||||||
f { y: 3.14 }
|
f { y: 3.14 }
|
||||||
|
@ -2600,11 +2601,11 @@ mod test_reporting {
|
||||||
|
|
||||||
This argument is a record of type:
|
This argument is a record of type:
|
||||||
|
|
||||||
{ y : F64 }
|
{ y : Float a }
|
||||||
|
|
||||||
But `f` needs the 1st argument to be:
|
But `f` needs the 1st argument to be:
|
||||||
|
|
||||||
{ x : I64 }
|
{ x : Int a }
|
||||||
|
|
||||||
Tip: Seems like a record field typo. Maybe `y` should be `x`?
|
Tip: Seems like a record field typo. Maybe `y` should be `x`?
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ mod solve_expr {
|
||||||
stdlib,
|
stdlib,
|
||||||
dir.path(),
|
dir.path(),
|
||||||
exposed_types,
|
exposed_types,
|
||||||
|
8,
|
||||||
);
|
);
|
||||||
|
|
||||||
dir.close()?;
|
dir.close()?;
|
||||||
|
@ -169,7 +170,7 @@ mod solve_expr {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn float_literal() {
|
fn float_literal() {
|
||||||
infer_eq("0.5", "F64");
|
infer_eq("0.5", "Float *");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -762,7 +763,7 @@ mod solve_expr {
|
||||||
(\a -> a) 3.14
|
(\a -> a) 3.14
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"F64",
|
"Float *",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,7 +1027,7 @@ mod solve_expr {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn two_field_record() {
|
fn two_field_record() {
|
||||||
infer_eq("{ x: 5, y : 3.14 }", "{ x : Num *, y : F64 }");
|
infer_eq("{ x: 5, y : 3.14 }", "{ x : Num *, y : Float * }");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2385,7 +2386,7 @@ mod solve_expr {
|
||||||
threePointZero
|
threePointZero
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"F64",
|
"Float *",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2982,7 +2983,7 @@ mod solve_expr {
|
||||||
infer_eq_without_problem(
|
infer_eq_without_problem(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
partition : I64, I64, List I64 -> [ Pair I64 (List I64) ]
|
partition : Int a, Int *, List (Int b) -> [ Pair (Int a) (List (Int b)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok _ ->
|
Ok _ ->
|
||||||
|
@ -2994,7 +2995,7 @@ mod solve_expr {
|
||||||
partition
|
partition
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"I64, I64, List I64 -> [ Pair I64 (List I64) ]",
|
"Int a, Int *, List (Int b) -> [ Pair (Int a) (List (Int b)) ]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3004,7 +3005,7 @@ mod solve_expr {
|
||||||
infer_eq_without_problem(
|
infer_eq_without_problem(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -3015,7 +3016,7 @@ mod solve_expr {
|
||||||
_ ->
|
_ ->
|
||||||
list
|
list
|
||||||
|
|
||||||
partition : I64, I64, List I64 -> [ Pair I64 (List I64) ]
|
partition : I64, I64, List (Int a) -> [ Pair I64 (List (Int a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -3043,7 +3044,7 @@ mod solve_expr {
|
||||||
partition
|
partition
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"I64, I64, List I64 -> [ Pair I64 (List I64) ]",
|
"I64, I64, List (Int a) -> [ Pair I64 (List (Int a)) ]",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3077,6 +3078,15 @@ mod solve_expr {
|
||||||
),
|
),
|
||||||
"Result (Num *) [ OutOfBounds ]*",
|
"Result (Num *) [ OutOfBounds ]*",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
List.get
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"List a, Int * -> Result a [ OutOfBounds ]*",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3117,7 +3127,7 @@ mod solve_expr {
|
||||||
Num.toFloat
|
Num.toFloat
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Num * -> F64",
|
"Num * -> Float *",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3129,7 +3139,7 @@ mod solve_expr {
|
||||||
Num.pow
|
Num.pow
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"F64, F64 -> F64",
|
"Float a, Float a -> Float a",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3141,7 +3151,7 @@ mod solve_expr {
|
||||||
Num.ceiling
|
Num.ceiling
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"F64 -> I64",
|
"Float * -> Int *",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3153,7 +3163,7 @@ mod solve_expr {
|
||||||
Num.floor
|
Num.floor
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"F64 -> I64",
|
"Float * -> Int *",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3165,7 +3175,7 @@ mod solve_expr {
|
||||||
Num.powInt
|
Num.powInt
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"I64, I64 -> I64",
|
"Int a, Int a -> Int a",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3177,7 +3187,7 @@ mod solve_expr {
|
||||||
Num.atan
|
Num.atan
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"F64 -> F64",
|
"Float a -> Float a",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3444,7 +3454,7 @@ mod solve_expr {
|
||||||
negatePoint { x: 1, y: 2.1, z: 0x3 }
|
negatePoint { x: 1, y: 2.1, z: 0x3 }
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"{ x : Num a, y : F64, z : I64 }",
|
"{ x : Num a, y : F64, z : Int * }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4096,7 +4106,7 @@ mod solve_expr {
|
||||||
r#"
|
r#"
|
||||||
app "test" provides [ partitionHelp ] to "./platform"
|
app "test" provides [ partitionHelp ] to "./platform"
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,26 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
aliases.insert(symbol, alias);
|
aliases.insert(symbol, alias);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Int range : [ @Int range ]
|
||||||
|
add_alias(
|
||||||
|
Symbol::NUM_INT,
|
||||||
|
BuiltinAlias {
|
||||||
|
region: Region::zero(),
|
||||||
|
vars: vec![Located::at(Region::zero(), "range".into())],
|
||||||
|
typ: int_alias_content(flex(TVAR1)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Float range : [ @Float range ]
|
||||||
|
add_alias(
|
||||||
|
Symbol::NUM_FLOAT,
|
||||||
|
BuiltinAlias {
|
||||||
|
region: Region::zero(),
|
||||||
|
vars: vec![Located::at(Region::zero(), "range".into())],
|
||||||
|
typ: float_alias_content(flex(TVAR1)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Num range : [ @Num range ]
|
// Num range : [ @Num range ]
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_NUM,
|
Symbol::NUM_NUM,
|
||||||
|
@ -48,6 +68,26 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Natural : [ @Natural ]
|
||||||
|
add_alias(
|
||||||
|
Symbol::NUM_NATURAL,
|
||||||
|
BuiltinAlias {
|
||||||
|
region: Region::zero(),
|
||||||
|
vars: vec![],
|
||||||
|
typ: natural_alias_content(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Nat : Int Natural
|
||||||
|
add_alias(
|
||||||
|
Symbol::NUM_NAT,
|
||||||
|
BuiltinAlias {
|
||||||
|
region: Region::zero(),
|
||||||
|
vars: Vec::new(),
|
||||||
|
typ: int_alias_content(natural_type()),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Signed128 : [ @Signed128 ]
|
// Signed128 : [ @Signed128 ]
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_SIGNED128,
|
Symbol::NUM_SIGNED128,
|
||||||
|
@ -58,7 +98,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// I128 : Num (Integer Signed128)
|
// I128 : Int Signed128
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_I128,
|
Symbol::NUM_I128,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -68,7 +108,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// U128 : Num (Integer Unsigned128)
|
// U128 : Int Unsigned128
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_U128,
|
Symbol::NUM_U128,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -88,7 +128,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// I64 : Num (Integer Signed64)
|
// I64 : Int Signed64
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_I64,
|
Symbol::NUM_I64,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -98,7 +138,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// U64 : Num (Integer Unsigned64)
|
// U64 : Int Unsigned64
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_U64,
|
Symbol::NUM_U64,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -118,7 +158,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// I32 : Num (Integer Signed32)
|
// I32 : Int Signed32
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_I32,
|
Symbol::NUM_I32,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -128,7 +168,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// U32 : Num (Integer Unsigned32)
|
// U32 : Int Unsigned32
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_U32,
|
Symbol::NUM_U32,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -148,7 +188,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// I16 : Num (Integer Signed16)
|
// I16 : Int Signed16
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_I16,
|
Symbol::NUM_I16,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -158,7 +198,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// U16 : Num (Integer Unsigned16)
|
// U16 : Int Unsigned16
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_U16,
|
Symbol::NUM_U16,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -178,7 +218,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// I8 : Num (Integer Signed8)
|
// I8 : Int Signed8
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_I8,
|
Symbol::NUM_I8,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -188,7 +228,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// U8 : Num (Integer Unsigned8)
|
// U8 : Int Unsigned8
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_U8,
|
Symbol::NUM_U8,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -228,7 +268,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// F64 : Num (FloatingPoint Binary64)
|
// F64 : Float Binary64
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_F64,
|
Symbol::NUM_F64,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -238,7 +278,7 @@ pub fn aliases() -> MutMap<Symbol, BuiltinAlias> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// F32 : Num (FloatingPoint Binary32)
|
// F32 : Float Binary32
|
||||||
add_alias(
|
add_alias(
|
||||||
Symbol::NUM_F32,
|
Symbol::NUM_F32,
|
||||||
BuiltinAlias {
|
BuiltinAlias {
|
||||||
|
@ -312,27 +352,39 @@ fn floatingpoint_alias_content(range: SolvedType) -> SolvedType {
|
||||||
// FLOAT
|
// FLOAT
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn float_type() -> SolvedType {
|
pub fn float_type(range: SolvedType) -> SolvedType {
|
||||||
SolvedType::Alias(
|
SolvedType::Alias(
|
||||||
Symbol::NUM_F64,
|
Symbol::NUM_FLOAT,
|
||||||
Vec::new(),
|
vec![("range".into(), range.clone())],
|
||||||
Box::new(float_alias_content(binary64_type())),
|
Box::new(float_alias_content(range)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn float_alias_content(typ: SolvedType) -> SolvedType {
|
fn float_alias_content(range: SolvedType) -> SolvedType {
|
||||||
num_type(floatingpoint_type(typ))
|
num_type(floatingpoint_type(range))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nat
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn nat_type() -> SolvedType {
|
||||||
|
SolvedType::Alias(Symbol::NUM_NAT, vec![], Box::new(nat_alias_content()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn nat_alias_content() -> SolvedType {
|
||||||
|
int_alias_content(natural_type())
|
||||||
}
|
}
|
||||||
|
|
||||||
// INT
|
// INT
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn int_type() -> SolvedType {
|
pub fn int_type(range: SolvedType) -> SolvedType {
|
||||||
SolvedType::Alias(
|
SolvedType::Alias(
|
||||||
Symbol::NUM_I64,
|
Symbol::NUM_INT,
|
||||||
Vec::new(),
|
vec![("range".into(), range.clone())],
|
||||||
Box::new(int_alias_content(signed64_type())),
|
Box::new(int_alias_content(range)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +437,20 @@ fn binary32_alias_content() -> SolvedType {
|
||||||
single_private_tag(Symbol::NUM_AT_BINARY32, vec![])
|
single_private_tag(Symbol::NUM_AT_BINARY32, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn natural_type() -> SolvedType {
|
||||||
|
SolvedType::Alias(
|
||||||
|
Symbol::NUM_NATURAL,
|
||||||
|
vec![],
|
||||||
|
Box::new(natural_alias_content()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn natural_alias_content() -> SolvedType {
|
||||||
|
single_private_tag(Symbol::NUM_AT_NATURAL, vec![])
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn signed128_type() -> SolvedType {
|
pub fn signed128_type() -> SolvedType {
|
||||||
SolvedType::Alias(
|
SolvedType::Alias(
|
||||||
|
|
|
@ -14,7 +14,7 @@ use roc_types::types::Type::{self, *};
|
||||||
pub fn int_literal(num_var: Variable, expected: Expected<Type>, region: Region) -> Constraint {
|
pub fn int_literal(num_var: Variable, expected: Expected<Type>, region: Region) -> Constraint {
|
||||||
let num_type = Variable(num_var);
|
let num_type = Variable(num_var);
|
||||||
let reason = Reason::IntLiteral;
|
let reason = Reason::IntLiteral;
|
||||||
let int_type = builtin_type(Symbol::NUM_I64, vec![]);
|
let int_type = builtin_type(Symbol::NUM_INT, vec![]);
|
||||||
let expected_literal = ForReason(reason, int_type, region);
|
let expected_literal = ForReason(reason, int_type, region);
|
||||||
|
|
||||||
exists(
|
exists(
|
||||||
|
@ -30,7 +30,7 @@ pub fn int_literal(num_var: Variable, expected: Expected<Type>, region: Region)
|
||||||
pub fn float_literal(num_var: Variable, expected: Expected<Type>, region: Region) -> Constraint {
|
pub fn float_literal(num_var: Variable, expected: Expected<Type>, region: Region) -> Constraint {
|
||||||
let num_type = Variable(num_var);
|
let num_type = Variable(num_var);
|
||||||
let reason = Reason::FloatLiteral;
|
let reason = Reason::FloatLiteral;
|
||||||
let float_type = builtin_type(Symbol::NUM_F64, vec![]);
|
let float_type = builtin_type(Symbol::NUM_FLOAT, vec![]);
|
||||||
let expected_literal = ForReason(reason, float_type, region);
|
let expected_literal = ForReason(reason, float_type, region);
|
||||||
|
|
||||||
exists(
|
exists(
|
||||||
|
|
|
@ -752,9 +752,9 @@ fn annotate_usage_pattern(pattern: &Pattern, usage: &mut VarUsage) {
|
||||||
|
|
||||||
match pattern {
|
match pattern {
|
||||||
Identifier(_)
|
Identifier(_)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_, _)
|
||||||
| NumLiteral(_, _)
|
| NumLiteral(_, _)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(_, _)
|
| Shadowed(_, _)
|
||||||
|
@ -785,8 +785,8 @@ pub fn annotate_usage(expr: &Expr, usage: &mut VarUsage) {
|
||||||
match expr {
|
match expr {
|
||||||
RuntimeError(_)
|
RuntimeError(_)
|
||||||
| Num(_, _)
|
| Num(_, _)
|
||||||
| Int(_, _)
|
| Int(_, _, _)
|
||||||
| Float(_, _)
|
| Float(_, _, _)
|
||||||
| Str { .. }
|
| Str { .. }
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
| Accessor { .. }
|
| Accessor { .. }
|
||||||
|
|
|
@ -132,6 +132,7 @@ fn files_to_documentations(
|
||||||
std_lib.clone(),
|
std_lib.clone(),
|
||||||
src_dir,
|
src_dir,
|
||||||
MutMap::default(),
|
MutMap::default(),
|
||||||
|
8, // TODO: Is it okay to hardcode ptr_bytes here? I think it should be fine since we'er only type checking (also, 8 => 32bit system)
|
||||||
)
|
)
|
||||||
.expect("TODO gracefully handle load failing");
|
.expect("TODO gracefully handle load failing");
|
||||||
files_docs.extend(loaded.documentation.drain().map(|x| x.1));
|
files_docs.extend(loaded.documentation.drain().map(|x| x.1));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
app "closure" provides [ makeClosure ] to "./platform/"
|
app "closure" provides [ makeClosure ] to "./platform/"
|
||||||
|
|
||||||
makeClosure : ({} -> I64) as MyClosure
|
makeClosure : ({} -> Int *) as MyClosure
|
||||||
makeClosure =
|
makeClosure =
|
||||||
x = 42
|
x = 42
|
||||||
y = 42
|
y = 42
|
||||||
|
|
|
@ -5,7 +5,7 @@ ConsList a : [ Cons a (ConsList a), Nil ]
|
||||||
empty : ConsList a
|
empty : ConsList a
|
||||||
empty = Nil
|
empty = Nil
|
||||||
|
|
||||||
len : ConsList a -> I64
|
len : ConsList a -> Int *
|
||||||
len = \list ->
|
len = \list ->
|
||||||
when list is
|
when list is
|
||||||
Cons _ rest -> 1 + len rest
|
Cons _ rest -> 1 + len rest
|
||||||
|
|
|
@ -21,11 +21,11 @@ singleton = \key, value ->
|
||||||
Node Black key value Empty Empty
|
Node Black key value Empty Empty
|
||||||
|
|
||||||
# {-| Determine the number of key-value pairs in the dictionary. -}
|
# {-| Determine the number of key-value pairs in the dictionary. -}
|
||||||
size : Dict k v -> I64
|
size : Dict k v -> Int *
|
||||||
size = \dict ->
|
size = \dict ->
|
||||||
sizeHelp 0 dict
|
sizeHelp 0 dict
|
||||||
|
|
||||||
sizeHelp : I64, Dict k v -> I64
|
sizeHelp : Int *, Dict k v -> Int *
|
||||||
sizeHelp = \n, dict ->
|
sizeHelp = \n, dict ->
|
||||||
when dict is
|
when dict is
|
||||||
Empty ->
|
Empty ->
|
||||||
|
|
|
@ -5,7 +5,7 @@ app "quicksort"
|
||||||
|
|
||||||
quicksort = \originalList ->
|
quicksort = \originalList ->
|
||||||
|
|
||||||
quicksortHelp : List (Num a), I64, I64 -> List (Num a)
|
quicksortHelp : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
|
@ -17,7 +17,7 @@ quicksort = \originalList ->
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int a, Int a, List (Num b) -> [ Pair (Int a) (List (Num b)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -28,7 +28,7 @@ quicksort = \originalList ->
|
||||||
Err _ ->
|
Err _ ->
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, (Num a) -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int a, Int b, List (Num c), Int b, (Num c) -> [ Pair (Int a) (List (Num c)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
@ -44,7 +44,7 @@ quicksort = \originalList ->
|
||||||
Pair i list
|
Pair i list
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base
|
app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base
|
||||||
|
|
||||||
quicksort : List I64 -> List I64
|
quicksort : List Int * -> List Int *
|
||||||
quicksort = \originalList -> helper originalList
|
quicksort = \originalList -> helper originalList
|
||||||
|
|
||||||
helper : List I64 -> List I64
|
helper : List Int * -> List Int *
|
||||||
helper = \originalList ->
|
helper = \originalList ->
|
||||||
|
|
||||||
quicksortHelp : List (Num a), I64, I64 -> List (Num a)
|
quicksortHelp : List (Num a), Int *, Int * -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
|
@ -18,7 +18,7 @@ helper = \originalList ->
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
swap : I64, I64, List a -> List a
|
swap : Int *, Int *, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
@ -29,7 +29,7 @@ helper = \originalList ->
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ]
|
partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
|
@ -41,7 +41,7 @@ helper = \originalList ->
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
|
|
||||||
partitionHelp : I64, I64, List (Num a), I64, (Num a) -> [ Pair I64 (List (Num a)) ]
|
partitionHelp : Int *, Int *, List (Num a), Int *, (Num a) -> [ Pair (Int *) (List (Num a)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue