Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coroc: support for range loops over strings #138

Open
chriso opened this issue Dec 16, 2023 · 1 comment
Open

coroc: support for range loops over strings #138

chriso opened this issue Dec 16, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@chriso
Copy link
Contributor

chriso commented Dec 16, 2023

The desugaring pass should be updated to desugar for range loops over strings:

var s string
for range string { ... }
for index := range string { ... }
for index, rune := range string { ... }

At first glance it should simply be a matter of adding *types.Basic (with .Kind() == types.String) to the case where we handle *types.Array and *types.Slice here, however range loops are a bit different when strings are involved. When indexing a string you get back a byte. When using a for range loop with a string you get a rune along with an index representing its offset in the string. More info in https://go.dev/blog/strings.

The desugaring pass should use utf.DecodeRuneInString to parse runes from strings iteratively.

@chriso
Copy link
Contributor Author

chriso commented Dec 16, 2023

Test case:

diff --git i/compiler/coroutine_test.go w/compiler/coroutine_test.go
index 85fa53b..ca9be36 100644
--- i/compiler/coroutine_test.go
+++ w/compiler/coroutine_test.go
@@ -243,6 +243,16 @@ func TestCoroutineYield(t *testing.T) {
                        coro:   func() { IdentityGenericStructClosureInt(11) },
                        yields: []int{11, 100, 23, 12, 101, 45},
                },
+
+               {
+                       name: "range over string",
+                       coro: func() { RangeOverString("foo") },
+                       yields: []int{
+                               0, 0, 0,
+                               0, 1, 2,
+                               0, 'f', 1, 'o', 2, 'o',
+                       },
+               },
        }
 
        // This emulates the installation of function type information by the
diff --git i/compiler/testdata/coroutine.go w/compiler/testdata/coroutine.go
index 36b42ff..1a11938 100644
--- i/compiler/testdata/coroutine.go
+++ w/compiler/testdata/coroutine.go
@@ -636,3 +636,16 @@ func IdentityGenericStructClosureInt(n int) {
        fn(23)
        fn(45)
 }
+
+func RangeOverString(s string) {
+       for range s {
+               coroutine.Yield[int, any](0)
+       }
+       for i := range s {
+               coroutine.Yield[int, any](i)
+       }
+       for i, c := range s {
+               coroutine.Yield[int, any](i)
+               coroutine.Yield[int, any](int(c))
+       }
+}

@chriso chriso added the enhancement New feature or request label Dec 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant