builtin(str): implement withCapacity

Signed-off-by: Prajwal S N <prajwalnadig21@gmail.com>
This commit is contained in:
Prajwal S N 2022-10-07 18:48:24 +05:30
parent f0786121fb
commit 9013e4ce11
No known key found for this signature in database
GPG Key ID: D0FECEE245BC2695
11 changed files with 59 additions and 2 deletions

View File

@ -144,6 +144,7 @@ comptime {
exportStrFn(str.strTrimLeft, "trim_left");
exportStrFn(str.strTrimRight, "trim_right");
exportStrFn(str.strCloneTo, "clone_to");
exportStrFn(str.withCapacity, "with_capacity");
inline for (INTEGERS) |T| {
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");

View File

@ -2596,6 +2596,10 @@ pub fn reserve(string: RocStr, capacity: usize) callconv(.C) RocStr {
}
}
pub fn withCapacity(capacity: usize) callconv(.C) RocStr {
return RocStr.allocate(0, capacity);
}
pub fn getScalarUnsafe(string: RocStr, index: usize) callconv(.C) extern struct { bytesParsed: usize, scalar: u32 } {
const slice = string.asSlice();
const bytesParsed = @intCast(usize, std.unicode.utf8ByteSequenceLength(slice[index]) catch unreachable);

View File

@ -43,6 +43,7 @@ interface Str
appendScalar,
walkScalars,
walkScalarsUntil,
withCapacity,
]
imports [
Bool.{ Bool },
@ -144,6 +145,9 @@ Utf8Problem : { byteIndex : Nat, problem : Utf8ByteProblem }
isEmpty : Str -> Bool
concat : Str, Str -> Str
## Returns a string of the specified capacity without any content
withCapacity : Nat -> Str
## Combine a list of strings into a single string, with a separator
## string in between each.
##

View File

@ -361,6 +361,7 @@ pub const STR_RESERVE: &str = "roc_builtins.str.reserve";
pub const STR_APPEND_SCALAR: &str = "roc_builtins.str.append_scalar";
pub const STR_GET_SCALAR_UNSAFE: &str = "roc_builtins.str.get_scalar_unsafe";
pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to";
pub const STR_WITH_CAPACITY: &str = "roc_builtins.str.with_capacity";
pub const LIST_MAP: &str = "roc_builtins.list.map";
pub const LIST_MAP2: &str = "roc_builtins.list.map2";

View File

@ -121,6 +121,7 @@ map_symbol_to_lowlevel_and_arity! {
StrGetScalarUnsafe; STR_GET_SCALAR_UNSAFE; 2,
StrToNum; STR_TO_NUM; 1,
StrGetCapacity; STR_CAPACITY; 1,
StrWithCapacity; STR_WITH_CAPACITY; 1,
ListLen; LIST_LEN; 1,
ListWithCapacity; LIST_WITH_CAPACITY; 1,

View File

@ -6035,6 +6035,20 @@ fn run_low_level<'a, 'ctx, 'env>(
bitcode::STR_TRIM_RIGHT,
)
}
StrWithCapacity => {
// Str.withCapacity : Nat -> Str
debug_assert_eq!(args.len(), 1);
let str_len = load_symbol(scope, &args[0]);
call_str_bitcode_fn(
env,
&[],
&[str_len],
BitcodeReturns::Str,
bitcode::STR_WITH_CAPACITY,
)
}
ListLen => {
// List.len : List * -> Nat
debug_assert_eq!(args.len(), 1);
@ -6157,7 +6171,7 @@ fn run_low_level<'a, 'ctx, 'env>(
list_prepend(env, original_wrapper, elem, elem_layout)
}
StrGetUnsafe => {
// List.getUnsafe : Str, Nat -> u8
// Str.getUnsafe : Str, Nat -> u8
debug_assert_eq!(args.len(), 2);
let wrapper_struct = load_symbol(scope, &args[0]);

View File

@ -302,6 +302,7 @@ impl<'a> LowLevelCall<'a> {
StrSubstringUnsafe => {
self.load_args_and_call_zig(backend, bitcode::STR_SUBSTRING_UNSAFE)
}
StrWithCapacity => self.load_args_and_call_zig(backend, bitcode::STR_WITH_CAPACITY),
// List
ListLen => match backend.storage.get(&self.arguments[0]) {

View File

@ -30,6 +30,7 @@ pub enum LowLevel {
StrAppendScalar,
StrGetScalarUnsafe,
StrGetCapacity,
StrWithCapacity,
ListLen,
ListWithCapacity,
ListReserve,
@ -249,6 +250,7 @@ map_symbol_to_lowlevel! {
StrGetScalarUnsafe <= STR_GET_SCALAR_UNSAFE,
StrToNum <= STR_TO_NUM,
StrGetCapacity <= STR_CAPACITY,
StrWithCapacity <= STR_WITH_CAPACITY,
ListLen <= LIST_LEN,
ListGetCapacity <= LIST_CAPACITY,
ListWithCapacity <= LIST_WITH_CAPACITY,

View File

@ -1296,6 +1296,7 @@ define_builtins! {
50 STR_REPLACE_EACH: "replaceEach"
51 STR_REPLACE_FIRST: "replaceFirst"
52 STR_REPLACE_LAST: "replaceLast"
53 STR_WITH_CAPACITY: "withCapacity"
}
6 LIST: "List" => {
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias

View File

@ -881,7 +881,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
Unreachable => arena.alloc_slice_copy(&[irrelevant]),
ListLen | StrIsEmpty | StrToScalars | StrCountGraphemes | StrCountUtf8Bytes
| StrGetCapacity | ListGetCapacity => arena.alloc_slice_copy(&[borrowed]),
ListWithCapacity => arena.alloc_slice_copy(&[irrelevant]),
ListWithCapacity | StrWithCapacity => arena.alloc_slice_copy(&[irrelevant]),
ListReplaceUnsafe => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
StrGetUnsafe | ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]),
ListConcat => arena.alloc_slice_copy(&[owned, owned]),

View File

@ -1930,3 +1930,31 @@ fn when_on_strings() {
i64
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn with_capacity() {
assert_evals_to!(
indoc!(
r#"
Str.withCapacity 10
"#
),
RocStr::from(""),
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn with_capacity_concat() {
assert_evals_to!(
indoc!(
r#"
Str.withCapacity 10 |> Str.concat "Forty-two"
"#
),
RocStr::from("Forty-two"),
RocStr
);
}