From be555822901cfae2f561c402d3dfc44fa48ede9b Mon Sep 17 00:00:00 2001 From: Brian Carroll Date: Thu, 18 Nov 2021 09:59:52 +0000 Subject: [PATCH] Enable some more gen_wasm string builtins --- compiler/gen_wasm/src/low_level.rs | 29 +- compiler/test_gen/src/wasm_str.rs | 468 ++++++++++++++++++----------- 2 files changed, 318 insertions(+), 179 deletions(-) diff --git a/compiler/gen_wasm/src/low_level.rs b/compiler/gen_wasm/src/low_level.rs index 7698826b63..e3bbc2fe6e 100644 --- a/compiler/gen_wasm/src/low_level.rs +++ b/compiler/gen_wasm/src/low_level.rs @@ -28,11 +28,32 @@ pub fn decode_low_level<'a>( match lowlevel { StrConcat => return BuiltinCall(bitcode::STR_CONCAT), + StrJoinWith => return NotImplemented, // needs Array + StrIsEmpty => { + code_builder.i64_const(i64::MIN); + code_builder.i64_eq(); + } + StrStartsWith => return BuiltinCall(bitcode::STR_STARTS_WITH), + StrStartsWithCodePt => return BuiltinCall(bitcode::STR_STARTS_WITH_CODE_PT), + StrEndsWith => return BuiltinCall(bitcode::STR_ENDS_WITH), + StrSplit => return NotImplemented, // needs Array + StrCountGraphemes => return NotImplemented, // test needs Array + StrFromInt => return NotImplemented, // choose builtin based on storage size + StrFromUtf8 => return NotImplemented, // needs Array + StrTrimLeft => return BuiltinCall(bitcode::STR_TRIM_LEFT), + StrTrimRight => return BuiltinCall(bitcode::STR_TRIM_RIGHT), + StrFromUtf8Range => return NotImplemented, // needs Array + StrToUtf8 => return NotImplemented, // needs Array + StrRepeat => return BuiltinCall(bitcode::STR_REPEAT), + StrFromFloat => { + // linker errors for __ashlti3, __fixunsdfti, __multi3, __udivti3, __umodti3 + // https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html + // https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html + return NotImplemented; + } + StrTrim => return BuiltinCall(bitcode::STR_TRIM), - StrJoinWith | StrIsEmpty | StrStartsWith | StrStartsWithCodePt | StrEndsWith | StrSplit - | StrCountGraphemes | StrFromInt | StrFromUtf8 | StrTrimLeft | StrTrimRight - | StrFromUtf8Range | StrToUtf8 | StrRepeat | StrFromFloat | StrTrim | ListLen - | ListGetUnsafe | ListSet | ListSingle | ListRepeat | ListReverse | ListConcat + ListLen | ListGetUnsafe | ListSet | ListSingle | ListRepeat | ListReverse | ListConcat | ListContains | ListAppend | ListPrepend | ListJoin | ListRange | ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith | ListSublist diff --git a/compiler/test_gen/src/wasm_str.rs b/compiler/test_gen/src/wasm_str.rs index a937c5e8b8..7dafb39a5f 100644 --- a/compiler/test_gen/src/wasm_str.rs +++ b/compiler/test_gen/src/wasm_str.rs @@ -346,54 +346,54 @@ fn str_concat_empty() { assert_evals_to!(r#"Str.concat "" """#, RocStr::default(), RocStr); } -// #[test] -// fn small_str_is_empty() { -// assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool); -// } +#[test] +fn small_str_is_empty() { + assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool); +} -// #[test] -// fn big_str_is_empty() { -// assert_evals_to!( -// r#"Str.isEmpty "this is more than 15 chars long""#, -// false, -// bool -// ); -// } +#[test] +fn big_str_is_empty() { + assert_evals_to!( + r#"Str.isEmpty "this is more than 15 chars long""#, + false, + bool + ); +} -// #[test] -// fn empty_str_is_empty() { -// assert_evals_to!(r#"Str.isEmpty """#, true, bool); -// } +#[test] +fn empty_str_is_empty() { + assert_evals_to!(r#"Str.isEmpty """#, true, bool); +} -// #[test] -// fn str_starts_with() { -// assert_evals_to!(r#"Str.startsWith "hello world" "hell""#, true, bool); -// assert_evals_to!(r#"Str.startsWith "hello world" """#, true, bool); -// assert_evals_to!(r#"Str.startsWith "nope" "hello world""#, false, bool); -// assert_evals_to!(r#"Str.startsWith "hell" "hello world""#, false, bool); -// assert_evals_to!(r#"Str.startsWith "" "hello world""#, false, bool); -// } +#[test] +fn str_starts_with() { + assert_evals_to!(r#"Str.startsWith "hello world" "hell""#, true, bool); + assert_evals_to!(r#"Str.startsWith "hello world" """#, true, bool); + assert_evals_to!(r#"Str.startsWith "nope" "hello world""#, false, bool); + assert_evals_to!(r#"Str.startsWith "hell" "hello world""#, false, bool); + assert_evals_to!(r#"Str.startsWith "" "hello world""#, false, bool); +} -// #[test] -// fn str_starts_with_code_point() { -// assert_evals_to!( -// &format!(r#"Str.startsWithCodePt "foobar" {}"#, 'f' as u32), -// true, -// bool -// ); -// assert_evals_to!( -// &format!(r#"Str.startsWithCodePt "zoobar" {}"#, 'f' as u32), -// false, -// bool -// ); -// } +#[test] +fn str_starts_with_code_point() { + assert_evals_to!( + &format!(r#"Str.startsWithCodePt "foobar" {}"#, 'f' as u32), + true, + bool + ); + assert_evals_to!( + &format!(r#"Str.startsWithCodePt "zoobar" {}"#, 'f' as u32), + false, + bool + ); +} -// #[test] -// fn str_ends_with() { -// assert_evals_to!(r#"Str.endsWith "hello world" "world""#, true, bool); -// assert_evals_to!(r#"Str.endsWith "nope" "hello world""#, false, bool); -// assert_evals_to!(r#"Str.endsWith "" "hello world""#, false, bool); -// } +#[test] +fn str_ends_with() { + assert_evals_to!(r#"Str.endsWith "hello world" "world""#, true, bool); + assert_evals_to!(r#"Str.endsWith "nope" "hello world""#, false, bool); + assert_evals_to!(r#"Str.endsWith "" "hello world""#, false, bool); +} // #[test] // fn str_count_graphemes_small_str() { @@ -414,37 +414,37 @@ fn str_concat_empty() { // ); // } -// #[test] -// fn str_starts_with_same_big_str() { -// assert_evals_to!( -// r#"Str.startsWith "123456789123456789" "123456789123456789""#, -// true, -// bool -// ); -// } +#[test] +fn str_starts_with_same_big_str() { + assert_evals_to!( + r#"Str.startsWith "123456789123456789" "123456789123456789""#, + true, + bool + ); +} -// #[test] -// fn str_starts_with_different_big_str() { -// assert_evals_to!( -// r#"Str.startsWith "12345678912345678910" "123456789123456789""#, -// true, -// bool -// ); -// } +#[test] +fn str_starts_with_different_big_str() { + assert_evals_to!( + r#"Str.startsWith "12345678912345678910" "123456789123456789""#, + true, + bool + ); +} -// #[test] -// fn str_starts_with_same_small_str() { -// assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool); -// } +#[test] +fn str_starts_with_same_small_str() { + assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool); +} -// #[test] -// fn str_starts_with_different_small_str() { -// assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool); -// } -// #[test] -// fn str_starts_with_false_small_str() { -// assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool); -// } +#[test] +fn str_starts_with_different_small_str() { + assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool); +} +#[test] +fn str_starts_with_false_small_str() { + assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool); +} // #[test] // fn str_from_int() { @@ -900,121 +900,239 @@ fn str_concat_empty() { // ); // } -// #[test] -// fn str_repeat_small() { -// assert_evals_to!( -// indoc!(r#"Str.repeat "Roc" 3"#), -// RocStr::from("RocRocRoc"), -// RocStr -// ); -// } +#[test] +fn str_repeat_small() { + assert_evals_to!( + indoc!(r#"Str.repeat "Roc" 3"#), + RocStr::from("RocRocRoc"), + RocStr + ); +} -// #[test] -// fn str_repeat_big() { -// assert_evals_to!( -// indoc!(r#"Str.repeat "more than 16 characters" 2"#), -// RocStr::from("more than 16 charactersmore than 16 characters"), -// RocStr -// ); -// } +#[test] +fn str_repeat_big() { + assert_evals_to!( + indoc!(r#"Str.repeat "more than 16 characters" 2"#), + RocStr::from("more than 16 charactersmore than 16 characters"), + RocStr + ); +} -// #[test] -// fn str_repeat_empty_string() { -// assert_evals_to!(indoc!(r#"Str.repeat "" 3"#), RocStr::from(""), RocStr); -// } +#[test] +fn str_repeat_empty_string() { + assert_evals_to!(indoc!(r#"Str.repeat "" 3"#), RocStr::from(""), RocStr); +} -// #[test] -// fn str_repeat_zero_times() { -// assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr); -// } +#[test] +fn str_repeat_zero_times() { + assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr); +} -// #[test] -// fn str_trim_empty_string() { -// assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr); -// } +#[test] +fn str_trim_empty_string() { + assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr); +} -// #[test] -// fn str_trim_small_blank_string() { -// assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr); -// } +#[test] +fn str_trim_small_blank_string() { + assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr); +} -// #[test] -// fn str_trim_small_to_small() { -// assert_evals_to!( -// indoc!(r#"Str.trim " hello world ""#), -// RocStr::from("hello world"), -// RocStr -// ); -// } +#[test] +fn str_trim_small_to_small() { + assert_evals_to!( + indoc!(r#"Str.trim " hello world ""#), + RocStr::from("hello world"), + RocStr + ); +} -// #[test] -// fn str_trim_large_to_large_unique() { -// assert_evals_to!( -// indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#), -// RocStr::from("hello world from a large string"), -// RocStr -// ); -// } +#[test] +fn str_trim_large_to_large_unique() { + assert_evals_to!( + indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#), + RocStr::from("hello world from a large string"), + RocStr + ); +} -// #[test] -// fn str_trim_large_to_small_unique() { -// assert_evals_to!( -// indoc!(r#"Str.trim (Str.concat " " "hello world ")"#), -// RocStr::from("hello world"), -// RocStr -// ); -// } +#[test] +fn str_trim_large_to_small_unique() { + assert_evals_to!( + indoc!(r#"Str.trim (Str.concat " " "hello world ")"#), + RocStr::from("hello world"), + RocStr + ); +} -// #[test] -// fn str_trim_large_to_large_shared() { -// assert_evals_to!( -// indoc!( -// r#" -// original : Str -// original = " hello world world " +#[test] +fn str_trim_large_to_large_shared() { + assert_evals_to!( + indoc!( + r#" + original : Str + original = " hello world world " -// { trimmed: Str.trim original, original: original } -// "# -// ), -// ( -// RocStr::from(" hello world world "), -// RocStr::from("hello world world"), -// ), -// (RocStr, RocStr) -// ); -// } + { trimmed: Str.trim original, original: original } + "# + ), + ( + RocStr::from(" hello world world "), + RocStr::from("hello world world"), + ), + (RocStr, RocStr) + ); +} -// #[test] -// fn str_trim_large_to_small_shared() { -// assert_evals_to!( -// indoc!( -// r#" -// original : Str -// original = " hello world " +#[test] +fn str_trim_large_to_small_shared() { + assert_evals_to!( + indoc!( + r#" + original : Str + original = " hello world " -// { trimmed: Str.trim original, original: original } -// "# -// ), -// ( -// RocStr::from(" hello world "), -// RocStr::from("hello world"), -// ), -// (RocStr, RocStr) -// ); -// } + { trimmed: Str.trim original, original: original } + "# + ), + ( + RocStr::from(" hello world "), + RocStr::from("hello world"), + ), + (RocStr, RocStr) + ); +} -// #[test] -// fn str_trim_small_to_small_shared() { -// assert_evals_to!( -// indoc!( -// r#" -// original : Str -// original = " hello world " +#[test] +fn str_trim_small_to_small_shared() { + assert_evals_to!( + indoc!( + r#" + original : Str + original = " hello world " -// { trimmed: Str.trim original, original: original } -// "# -// ), -// (RocStr::from(" hello world "), RocStr::from("hello world"),), -// (RocStr, RocStr) -// ); -// } + { trimmed: Str.trim original, original: original } + "# + ), + (RocStr::from(" hello world "), RocStr::from("hello world"),), + (RocStr, RocStr) + ); +} + +#[test] +fn str_trim_left_small_blank_string() { + assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr); +} + +#[test] +fn str_trim_left_small_to_small() { + assert_evals_to!( + indoc!(r#"Str.trimLeft " hello world ""#), + RocStr::from("hello world "), + RocStr + ); +} + +#[test] +fn str_trim_left_large_to_large_unique() { + assert_evals_to!( + indoc!(r#"Str.trimLeft (Str.concat " " "hello world from a large string ")"#), + RocStr::from("hello world from a large string "), + RocStr + ); +} + +#[test] +fn str_trim_left_large_to_small_unique() { + assert_evals_to!( + indoc!(r#"Str.trimLeft (Str.concat " " "hello world ")"#), + RocStr::from("hello world "), + RocStr + ); +} + +#[test] +fn str_trim_right_small_blank_string() { + assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr); +} + +#[test] +fn str_trim_right_small_to_small() { + assert_evals_to!( + indoc!(r#"Str.trimRight " hello world ""#), + RocStr::from(" hello world"), + RocStr + ); +} + +#[test] +fn str_trim_right_large_to_large_unique() { + assert_evals_to!( + indoc!(r#"Str.trimRight (Str.concat " hello world from a large string" " ")"#), + RocStr::from(" hello world from a large string"), + RocStr + ); +} + +#[test] +fn str_trim_right_large_to_small_unique() { + assert_evals_to!( + indoc!(r#"Str.trimRight (Str.concat " hello world" " ")"#), + RocStr::from(" hello world"), + RocStr + ); +} + +#[test] +fn str_trim_right_large_to_large_shared() { + assert_evals_to!( + indoc!( + r#" + original : Str + original = " hello world world " + + { trimmed: Str.trimRight original, original: original } + "# + ), + ( + RocStr::from(" hello world world "), + RocStr::from(" hello world world"), + ), + (RocStr, RocStr) + ); +} + +#[test] +fn str_trim_right_large_to_small_shared() { + assert_evals_to!( + indoc!( + r#" + original : Str + original = " hello world " + + { trimmed: Str.trimRight original, original: original } + "# + ), + ( + RocStr::from(" hello world "), + RocStr::from(" hello world"), + ), + (RocStr, RocStr) + ); +} + +#[test] +fn str_trim_right_small_to_small_shared() { + assert_evals_to!( + indoc!( + r#" + original : Str + original = " hello world " + + { trimmed: Str.trimRight original, original: original } + "# + ), + (RocStr::from(" hello world "), RocStr::from(" hello world"),), + (RocStr, RocStr) + ); +}