Allow for-loop to iterate over bytes (#3317)

This commit is contained in:
Leedehai 2024-02-02 03:51:44 -05:00 committed by GitHub
parent 464a15bdca
commit 42f59af812
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 41 additions and 14 deletions

View File

@ -152,7 +152,11 @@ impl Eval for ast::ForLoop<'_> {
// Iterate over graphemes of string.
iter!(for pattern in str.as_str().graphemes(true));
}
(Pattern::Destructuring(_), Value::Str(_)) => {
(Pattern::Normal(_) | Pattern::Placeholder(_), Value::Bytes(bytes)) => {
// Iterate over the integers of bytes.
iter!(for pattern in bytes.as_slice());
}
(Pattern::Destructuring(_), Value::Str(_) | Value::Bytes(_)) => {
bail!(pattern.span(), "cannot destructure values of {}", iterable_type);
}
_ => {

View File

@ -13,12 +13,13 @@ use crate::foundations::{cast, func, scope, ty, Array, Reflect, Repr, Str, Value
/// A sequence of bytes.
///
/// This is conceptually similar to an array of [integers]($int) between `{0}`
/// and `{255}`, but represented much more efficiently.
/// and `{255}`, but represented much more efficiently. You can iterate over it
/// using a [for loop]($scripting/#loops).
///
/// You can convert
/// - a [string]($str) or an [array]($array) of integers to bytes with the
/// [`bytes`]($bytes) constructor
/// - bytes to a string with the [`str`]($str) constructor
/// - bytes to a string with the [`str`]($str) constructor, with UTF-8 encoding
/// - bytes to an array of integers with the [`array`]($array) constructor
///
/// When [reading]($read) data from a file, you can decide whether to load it

View File

@ -188,13 +188,6 @@ together into one larger array.
For loops can iterate over a variety of collections:
- `{for letter in "abc" {..}}` \
Iterates over the characters of the [string]($str).
(Technically, iterates over the grapheme clusters of the string. Most of the
time, a grapheme cluster is just a single character/codepoint. However, some
constructs like flag emojis that consist of multiple codepoints are still only
one cluster.)
- `{for value in array {..}}` \
Iterates over the items in the [array]($array). The destructuring syntax
described in [Let binding]($scripting/#bindings) can also be used here.
@ -203,6 +196,17 @@ For loops can iterate over a variety of collections:
Iterates over the key-value pairs of the [dictionary]($dictionary).
The pairs can also be destructured by using `{for (key, value) in dict {..}}`.
- `{for letter in "abc" {..}}` \
Iterates over the characters of the [string]($str). Technically, it iterates
over the grapheme clusters of the string. Most of the time, a grapheme cluster
is just a single codepoint. However, a grapheme cluster could contain multiple
codepoints, like a flag emoji.
- `{for byte in bytes("😀") {..}}` \
Iterates over the [bytes]($bytes), which can be converted from a [string]($str)
or [read]($read) from a file without encoding. Each byte value is an
[integer]($int) between `{0}` and `{255}`.
To control the execution of the loop, Typst provides the `{break}` and
`{continue}` statements. The former performs an early exit from the loop while
the latter skips ahead to the next iteration of the loop.

View File

@ -6,17 +6,19 @@
#for x in (1, 2) {}
#for x in (a: 1, b: 2) {}
#for x in "foo" {}
#for x in bytes("😊") {}
---
// Placeholder.
#for _ in (1, 2) {}
#for _ in (a: 1, b: 2) {}
#for _ in "foo" {}
#for _ in bytes("😊") {}
---
// Destructuring.
#for (k, v) in (("a", 1), ("b", 2), ("c", 3)) {}
#for (k, ..) in (("a", 1), ("b", 2), ("c", 3)) {}
#for (a,b,c) in (("a", 1, bytes(())), ("b", 2, bytes(""))) {}
#for (a, ..) in (("a", 1, bytes(())), ("b", 2, bytes(""))) {}
#for (k, v) in (a: 1, b: 2, c: 3) {}
#for (.., v) in (a: 1, b: 2, c: 3) {}
@ -25,8 +27,8 @@
#for x in [1, 2] {}
---
// Error: 11-25 cannot loop over bytes
#for _ in bytes((22, 0)) {}
// Error: 11-25 cannot loop over arguments
#for _ in arguments("a") {}
---
// Error: 16-21 cannot loop over integer
@ -44,6 +46,22 @@
// Error: 6-12 cannot destructure string
#for (x, y) in ("foo", "bar") {}
---
// Error: 6-12 cannot destructure values of bytes
#for (x, y) in bytes("😊") {}
---
// Error: 6-12 cannot destructure bytes
#for (x, y) in (bytes((1,2)), bytes((1,2))) {}
---
// Error: 6-12 cannot destructure integer
#for (x, y) in (1, 2) {}
---
// Error: 10-11 not enough elements to destructure
#for (x, y) in ((1,), (2,)) {}
---
// Error: 6-12 too many elements to destructure
#for (x, y) in ((1,2,3), (4,5,6)) {}