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. // Iterate over graphemes of string.
iter!(for pattern in str.as_str().graphemes(true)); 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); 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. /// A sequence of bytes.
/// ///
/// This is conceptually similar to an array of [integers]($int) between `{0}` /// 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 /// You can convert
/// - a [string]($str) or an [array]($array) of integers to bytes with the /// - a [string]($str) or an [array]($array) of integers to bytes with the
/// [`bytes`]($bytes) constructor /// [`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 /// - 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 /// 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 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 {..}}` \ - `{for value in array {..}}` \
Iterates over the items in the [array]($array). The destructuring syntax Iterates over the items in the [array]($array). The destructuring syntax
described in [Let binding]($scripting/#bindings) can also be used here. 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). Iterates over the key-value pairs of the [dictionary]($dictionary).
The pairs can also be destructured by using `{for (key, value) in dict {..}}`. 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 To control the execution of the loop, Typst provides the `{break}` and
`{continue}` statements. The former performs an early exit from the loop while `{continue}` statements. The former performs an early exit from the loop while
the latter skips ahead to the next iteration of the loop. 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 (1, 2) {}
#for x in (a: 1, b: 2) {} #for x in (a: 1, b: 2) {}
#for x in "foo" {} #for x in "foo" {}
#for x in bytes("😊") {}
--- ---
// Placeholder. // Placeholder.
#for _ in (1, 2) {} #for _ in (1, 2) {}
#for _ in (a: 1, b: 2) {} #for _ in (a: 1, b: 2) {}
#for _ in "foo" {} #for _ in "foo" {}
#for _ in bytes("😊") {}
--- ---
// Destructuring. // Destructuring.
#for (k, v) in (("a", 1), ("b", 2), ("c", 3)) {} #for (a,b,c) in (("a", 1, bytes(())), ("b", 2, bytes(""))) {}
#for (k, ..) in (("a", 1), ("b", 2), ("c", 3)) {} #for (a, ..) in (("a", 1, bytes(())), ("b", 2, bytes(""))) {}
#for (k, v) in (a: 1, b: 2, c: 3) {} #for (k, v) in (a: 1, b: 2, c: 3) {}
#for (.., 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] {} #for x in [1, 2] {}
--- ---
// Error: 11-25 cannot loop over bytes // Error: 11-25 cannot loop over arguments
#for _ in bytes((22, 0)) {} #for _ in arguments("a") {}
--- ---
// Error: 16-21 cannot loop over integer // Error: 16-21 cannot loop over integer
@ -44,6 +46,22 @@
// Error: 6-12 cannot destructure string // Error: 6-12 cannot destructure string
#for (x, y) in ("foo", "bar") {} #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 // Error: 6-12 cannot destructure integer
#for (x, y) in (1, 2) {} #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)) {}