Work in progress: Bounds Checking

This commit is contained in:
Joshua Hoeflich 2021-08-08 12:01:48 -05:00
parent b8b20a376a
commit 17ec118f52
2 changed files with 99 additions and 51 deletions

View file

@ -7,9 +7,9 @@ use roc_types::builtin_aliases::{
ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u32_type, u64_type, ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u32_type, u64_type,
u8_type, u8_type,
}; };
use roc_types::types::RecordField;
use roc_types::solved_types::SolvedType; use roc_types::solved_types::SolvedType;
use roc_types::subs::VarId; use roc_types::subs::VarId;
use roc_types::types::RecordField;
use std::collections::HashMap; use std::collections::HashMap;
/// Example: /// Example:
@ -593,35 +593,51 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
); );
// fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8Problem ]* // fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8Problem ]*
let bad_utf8 = SolvedType::TagUnion( {
vec![( let bad_utf8 = SolvedType::TagUnion(
TagName::Global("BadUtf8".into()), vec![(
// vec![str_utf8_problem_type()], TagName::Global("BadUtf8".into()),
vec![str_utf8_byte_problem_type(), nat_type()], // vec![str_utf8_problem_type()],
)], vec![str_utf8_byte_problem_type(), nat_type()],
Box::new(SolvedType::Wildcard), )],
); Box::new(SolvedType::Wildcard),
);
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_FROM_UTF8, Symbol::STR_FROM_UTF8,
vec![list_type(u8_type())], vec![list_type(u8_type())],
Box::new(result_type(str_type(), bad_utf8.clone())), Box::new(result_type(str_type(), bad_utf8)),
); );
}
add_top_level_function_type!( // fromUtf8Range : List U8 -> Result Str [ BadUtf8 Utf8Problem, OutOfBounds ]*
Symbol::STR_FROM_UTF8_RANGE, {
vec![ let bad_utf8 = SolvedType::TagUnion(
list_type(u8_type()), vec![
SolvedType::Record { (
fields: vec![ TagName::Global("BadUtf8".into()),
("start".into(), RecordField::Required(nat_type())), vec![str_utf8_byte_problem_type(), nat_type()],
("count".into(), RecordField::Required(nat_type())), ),
], (TagName::Global("OutOfBounds".into()), vec![]),
ext: Box::new(SolvedType::EmptyRecord), ],
} Box::new(SolvedType::Wildcard),
], );
Box::new(result_type(str_type(), bad_utf8)),
); add_top_level_function_type!(
Symbol::STR_FROM_UTF8_RANGE,
vec![
list_type(u8_type()),
SolvedType::Record {
fields: vec![
("start".into(), RecordField::Required(nat_type())),
("count".into(), RecordField::Required(nat_type())),
],
ext: Box::new(SolvedType::EmptyRecord),
}
],
Box::new(result_type(str_type(), bad_utf8)),
);
}
// toBytes : Str -> List U8 // toBytes : Str -> List U8
add_top_level_function_type!( add_top_level_function_type!(

View file

@ -834,10 +834,14 @@ fn str_to_bytes() {
#[test] #[test]
fn str_from_utf8_range() { fn str_from_utf8_range() {
assert_evals_to!( assert_evals_to!(
r#" indoc!(
bytes = Str.toBytes "hello" r#"
Str.fromUtf8Range bytes { start: 0, count: 5 } bytes = Str.toBytes "hello"
"#, when Str.fromUtf8Range bytes { count: 5, start: 0 } is
Ok utf8String -> utf8String
_ -> ""
"#
),
RocStr::from("hello"), RocStr::from("hello"),
RocStr RocStr
); );
@ -846,10 +850,14 @@ fn str_from_utf8_range() {
#[test] #[test]
fn str_from_utf8_range_slice() { fn str_from_utf8_range_slice() {
assert_evals_to!( assert_evals_to!(
r#" indoc!(
bytes = Str.toBytes "hello" r#"
Str.fromUtf8Range bytes { start: 1, count: 4 } bytes = Str.toBytes "hello"
"#, when Str.fromUtf8Range bytes { count: 4, start: 1 } is
Ok utf8String -> utf8String
_ -> ""
"#
),
RocStr::from("ello"), RocStr::from("ello"),
RocStr RocStr
); );
@ -858,23 +866,47 @@ fn str_from_utf8_range_slice() {
#[test] #[test]
fn str_from_utf8_range_slice_not_end() { fn str_from_utf8_range_slice_not_end() {
assert_evals_to!( assert_evals_to!(
r#" indoc!(
bytes = Str.toBytes "hello" r#"
Str.fromUtf8Range bytes { start: 1, count: 3 } bytes = Str.toBytes "hello"
"#, when Str.fromUtf8Range bytes { count: 3, start: 1 } is
Ok utf8String -> utf8String
_ -> ""
"#
),
RocStr::from("ell"), RocStr::from("ell"),
RocStr RocStr
); );
} }
// #[test] #[test]
// fn str_from_utf8_range_slice() { fn str_from_utf8_range_order_does_not_matter() {
// assert_evals_to!( assert_evals_to!(
// r#" indoc!(
// bytes = Str.toBytes "hello" r#"
// Str.fromUtf8Range bytes { start: 6, count: 5 } bytes = Str.toBytes "hello"
// "#, when Str.fromUtf8Range bytes { start: 1, count: 3 } is
// RocStr::from("ello"), Ok utf8String -> utf8String
// RocStr _ -> ""
// ); "#
// } ),
RocStr::from("ell"),
RocStr
);
}
#[test]
fn str_from_utf8_range_out_of_bounds() {
assert_evals_to!(
indoc!(
r#"
bytes = Str.toBytes "hello"
when Str.fromUtf8Range bytes { start: 7, count: 3 } is
Ok _ -> ""
Err OutOfBounds -> "out of bounds"
"#
),
RocStr::from("out of bounds"),
RocStr
);
}