Skip to content

Commit 45b9d81

Browse files
Merge pull request #8437 from roc-lang/str-trim-start-end
add Str.trim_{start,end} builtins
2 parents df66010 + 840ac29 commit 45b9d81

File tree

7 files changed

+166
-0
lines changed

7 files changed

+166
-0
lines changed

src/build/builtin_compiler/main.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ fn replaceStrIsEmptyWithLowLevel(env: *ModuleEnv) !std.ArrayList(CIR.Def.Idx) {
107107
if (env.common.findIdent("Builtin.Str.trim")) |str_trim_ident| {
108108
try low_level_map.put(str_trim_ident, .str_trim);
109109
}
110+
if (env.common.findIdent("Builtin.Str.trim_start")) |str_trim_start_ident| {
111+
try low_level_map.put(str_trim_start_ident, .str_trim_start);
112+
}
113+
if (env.common.findIdent("Builtin.Str.trim_end")) |str_trim_end_ident| {
114+
try low_level_map.put(str_trim_end_ident, .str_trim_end);
115+
}
110116
if (env.common.findIdent("Builtin.Str.caseless_ascii_equals")) |str_caseless_ascii_equals_ident| {
111117
try low_level_map.put(str_caseless_ascii_equals_ident, .str_caseless_ascii_equals);
112118
}

src/build/roc/Builtin.roc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Builtin :: [].{
44
concat : Str, Str -> Str
55
contains : Str, Str -> Bool
66
trim : Str -> Str
7+
trim_start : Str -> Str
8+
trim_end : Str -> Str
79
caseless_ascii_equals : Str, Str -> Bool
810
with_ascii_lowercased : Str -> Str
911
with_ascii_uppercased : Str -> Str

src/canonicalize/Expression.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,8 @@ pub const Expr = union(enum) {
404404
str_concat,
405405
str_contains,
406406
str_trim,
407+
str_trim_start,
408+
str_trim_end,
407409
str_caseless_ascii_equals,
408410
str_with_ascii_lowercased,
409411
str_with_ascii_uppercased,

src/eval/interpreter.zig

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2841,6 +2841,52 @@ pub const Interpreter = struct {
28412841
out.is_initialized = true;
28422842
return out;
28432843
},
2844+
.str_trim_start => {
2845+
// Str.trim_start : Str -> Str
2846+
std.debug.assert(args.len == 1);
2847+
2848+
const str_arg = args[0];
2849+
std.debug.assert(str_arg.ptr != null);
2850+
2851+
const roc_str_arg: *const RocStr = @ptrCast(@alignCast(str_arg.ptr.?));
2852+
2853+
const result_str = builtins.str.strTrimStart(roc_str_arg.*, roc_ops);
2854+
2855+
// Allocate space for the result string
2856+
const result_layout = str_arg.layout; // Str layout
2857+
var out = try self.pushRaw(result_layout, 0);
2858+
out.is_initialized = false;
2859+
2860+
// Copy the result string structure to the output
2861+
const result_ptr: *RocStr = @ptrCast(@alignCast(out.ptr.?));
2862+
result_ptr.* = result_str;
2863+
2864+
out.is_initialized = true;
2865+
return out;
2866+
},
2867+
.str_trim_end => {
2868+
// Str.trim_end : Str -> Str
2869+
std.debug.assert(args.len == 1);
2870+
2871+
const str_arg = args[0];
2872+
std.debug.assert(str_arg.ptr != null);
2873+
2874+
const roc_str_arg: *const RocStr = @ptrCast(@alignCast(str_arg.ptr.?));
2875+
2876+
const result_str = builtins.str.strTrimEnd(roc_str_arg.*, roc_ops);
2877+
2878+
// Allocate space for the result string
2879+
const result_layout = str_arg.layout; // Str layout
2880+
var out = try self.pushRaw(result_layout, 0);
2881+
out.is_initialized = false;
2882+
2883+
// Copy the result string structure to the output
2884+
const result_ptr: *RocStr = @ptrCast(@alignCast(out.ptr.?));
2885+
result_ptr.* = result_str;
2886+
2887+
out.is_initialized = true;
2888+
return out;
2889+
},
28442890
.str_caseless_ascii_equals => {
28452891
// Str.caseless_ascii_equals : Str, Str -> Bool
28462892
std.debug.assert(args.len == 2);

src/eval/test/low_level_interp_test.zig

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,60 @@ test "e_low_level_lambda - Str.trim with a non-whitespace string" {
537537
try testing.expectEqualStrings("\"hello\"", value);
538538
}
539539

540+
test "e_low_level_lambda - Str.trim_start with an empty string" {
541+
const src =
542+
\\x = Str.trim_start("")
543+
;
544+
const value = try evalModuleAndGetString(src, 0, test_allocator);
545+
defer test_allocator.free(value);
546+
try testing.expectEqualStrings("\"\"", value);
547+
}
548+
549+
test "e_low_level_lambda - Str.trim_start with a whitespace string" {
550+
const src =
551+
\\x = Str.trim_start(" ")
552+
;
553+
const value = try evalModuleAndGetString(src, 0, test_allocator);
554+
defer test_allocator.free(value);
555+
try testing.expectEqualStrings("\"\"", value);
556+
}
557+
558+
test "e_low_level_lambda - Str.trim_start with a non-whitespace string" {
559+
const src =
560+
\\x = Str.trim_start(" hello ")
561+
;
562+
const value = try evalModuleAndGetString(src, 0, test_allocator);
563+
defer test_allocator.free(value);
564+
try testing.expectEqualStrings("\"hello \"", value);
565+
}
566+
567+
test "e_low_level_lambda - Str.trim_end with an empty string" {
568+
const src =
569+
\\x = Str.trim_end("")
570+
;
571+
const value = try evalModuleAndGetString(src, 0, test_allocator);
572+
defer test_allocator.free(value);
573+
try testing.expectEqualStrings("\"\"", value);
574+
}
575+
576+
test "e_low_level_lambda - Str.trim_end with a whitespace string" {
577+
const src =
578+
\\x = Str.trim_end(" ")
579+
;
580+
const value = try evalModuleAndGetString(src, 0, test_allocator);
581+
defer test_allocator.free(value);
582+
try testing.expectEqualStrings("\"\"", value);
583+
}
584+
585+
test "e_low_level_lambda - Str.trim_end with a non-whitespace string" {
586+
const src =
587+
\\x = Str.trim_end(" hello ")
588+
;
589+
const value = try evalModuleAndGetString(src, 0, test_allocator);
590+
defer test_allocator.free(value);
591+
try testing.expectEqualStrings("\" hello\"", value);
592+
}
593+
540594
test "e_low_level_lambda - List.concat with two non-empty lists" {
541595
const src =
542596
\\x = List.concat([1, 2], [3, 4])
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# META
2+
~~~ini
3+
description=Str.trim_end should work with various string combinations
4+
type=repl
5+
~~~
6+
# SOURCE
7+
~~~roc
8+
» Str.trim_end(" Hello")
9+
» Str.trim_end("Hello ")
10+
» Str.trim_end(" Hello World ")
11+
» Str.trim_end("Hello World")
12+
» Str.trim_end(" ")
13+
» Str.trim_end("")
14+
~~~
15+
# OUTPUT
16+
" Hello"
17+
---
18+
"Hello"
19+
---
20+
" Hello World"
21+
---
22+
"Hello World"
23+
---
24+
""
25+
---
26+
""
27+
# PROBLEMS
28+
NIL
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# META
2+
~~~ini
3+
description=Str.trim_start should work with various string combinations
4+
type=repl
5+
~~~
6+
# SOURCE
7+
~~~roc
8+
» Str.trim_start(" Hello")
9+
» Str.trim_start("Hello ")
10+
» Str.trim_start(" Hello World ")
11+
» Str.trim_start("Hello World")
12+
» Str.trim_start(" ")
13+
» Str.trim_start("")
14+
~~~
15+
# OUTPUT
16+
"Hello"
17+
---
18+
"Hello "
19+
---
20+
"Hello World "
21+
---
22+
"Hello World"
23+
---
24+
""
25+
---
26+
""
27+
# PROBLEMS
28+
NIL

0 commit comments

Comments
 (0)