castToNat working

This commit is contained in:
Joshua Hoeflich 2021-08-18 11:31:48 -05:00
parent 92da003fba
commit b4f575736b
3 changed files with 151 additions and 20 deletions

View file

@ -4,8 +4,8 @@ use roc_module::symbol::Symbol;
use roc_region::all::Region;
use roc_types::builtin_aliases::{
bool_type, dict_type, float_type, i128_type, int_type, list_type, nat_type, num_type,
ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u32_type, u64_type,
u8_type, u16_type
ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u16_type, u32_type,
u64_type, u8_type,
};
use roc_types::solved_types::SolvedType;
use roc_types::subs::VarId;
@ -509,11 +509,17 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
);
// bytesToU16 : List U8, Nat -> U16
add_top_level_function_type!(
Symbol::NUM_BYTES_TO_U16,
vec![list_type(u8_type()), nat_type()],
Box::new(u16_type()),
);
{
let position_out_of_bounds = SolvedType::TagUnion(
vec![(TagName::Global("OutOfBounds".into()), vec![])],
Box::new(SolvedType::Wildcard),
);
add_top_level_function_type!(
Symbol::NUM_BYTES_TO_U16,
vec![list_type(u8_type()), nat_type()],
Box::new(result_type(u16_type(), position_out_of_bounds)),
);
}
// bytesToU32 : List U8, Nat -> U32
add_top_level_function_type!(

View file

@ -1092,26 +1092,113 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.bytesToU16 : List U8, Nat -> U16
fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def {
let len_var = var_store.fresh();
let list_var = var_store.fresh();
let nat_var = var_store.fresh();
let ret_var = var_store.fresh();
let elem_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::NumBytesToU16,
args: vec![
(list_var, Var(Symbol::ARG_1)),
(nat_var, Var(Symbol::ARG_2)),
],
ret_var,
let ret_var = var_store.fresh();
let bool_var = var_store.fresh();
let add_var = var_store.fresh();
let cast_var = var_store.fresh();
// Perform a bounds check. If it passes, run LowLevel::NumBytesToU16
let body = If {
cond_var: bool_var,
branch_var: var_store.fresh(),
branches: vec![(
// if-condition
no_region(
// index + 1 < List.len list
RunLowLevel {
op: LowLevel::NumLt,
args: vec![
(
len_var,
RunLowLevel {
op: LowLevel::NumAdd,
args: vec![
(add_var, Var(Symbol::ARG_2)),
(
add_var,
RunLowLevel {
ret_var: cast_var,
args: vec![(cast_var, Num(var_store.fresh(), 1))],
op: LowLevel::NumCastToNat,
},
),
],
ret_var: add_var,
},
),
(
len_var,
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_var, Var(Symbol::ARG_1))],
ret_var: len_var,
},
),
],
ret_var: bool_var,
},
),
// then-branch
no_region(
// Ok
tag(
"Ok",
vec![RunLowLevel {
op: LowLevel::NumBytesToU16,
args: vec![
(list_var, Var(Symbol::ARG_1)),
(len_var, Var(Symbol::ARG_2)),
],
ret_var: elem_var,
}],
var_store,
),
),
)],
final_else: Box::new(
// else-branch
no_region(
// Err
tag(
"Err",
vec![tag("OutOfBounds", Vec::new(), var_store)],
var_store,
),
),
),
};
defn(
symbol,
vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)],
vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)],
var_store,
body,
ret_var,
)
// let list_var = var_store.fresh();
// let nat_var = var_store.fresh();
// let ret_var = var_store.fresh();
// let body = RunLowLevel {
// op: LowLevel::NumBytesToU16,
// args: vec![
// (list_var, Var(Symbol::ARG_1)),
// (nat_var, Var(Symbol::ARG_2)),
// ],
// ret_var,
// };
// defn(
// symbol,
// vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)],
// var_store,
// body,
// ret_var,
// )
}
/// Num.bytesToU32 : List U8, Nat -> U32

View file

@ -1628,21 +1628,59 @@ mod gen_num {
// TODO: Once we know what the function should do, let's give these real names!
#[test]
fn potato_1() {
assert_evals_to!("Num.bytesToU16 [] 1", 40, u16);
assert_evals_to!(
indoc!(
r#"
bytes = Str.toUtf8 "hello"
when Num.bytesToU16 bytes 0 is
Ok v -> v
Err OutOfBounds -> 1
"#
),
40,
usize
);
}
#[test]
fn potato_2() {
assert_evals_to!("Num.bytesToU16 [] 0", 40, u16);
assert_evals_to!(
indoc!(
r#"
bytes = Str.toUtf8 "hello"
when Num.bytesToU16 bytes 234 is
Ok v -> v
Err OutOfBounds -> 1
"#
),
1,
usize
);
}
#[test]
fn potato_3() {
assert_evals_to!("Num.bytesToU32 [] 1", 41, u32);
assert_evals_to!(
indoc!(
r#"
bytes = Str.toUtf8 "hello"
when Num.bytesToU16 bytes 4 is
Ok v -> v
Err OutOfBounds -> 1
"#
),
1,
usize
);
}
#[test]
fn potato_4() {
assert_evals_to!("Num.bytesToU32 [] 1", 41, u32);
}
#[test]
fn potato_5() {
assert_evals_to!("Num.bytesToU32 [] 0", 41, u32);
}
}