Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ generic std gap is planned here even when moq never calls it.
- [Drop order in std's folds and iterators](/quest/m3/ts-drop-order.md) - the values that drop still refused in std's consumers and collects drop as std's do
- [A slice of one value behind any &mut](/quest/m3/ts-slice-of-one.md) - `slice::from_mut` and `array::from_mut` of a `&mut u8`, or of an object no place names, translate
- [std's calls of a closure that have no mapping](/quest/m3/ts-closure-calls.md) - `try_fold`, `partition`, `repeat_with`, `sort_by_cached_key`, and `LazyCell::new` translate, dropping what their closures own as std's do
- [A function pointer or a boxed closure as a string pattern](/quest/m3/ts-fn-patterns.md) - `s.split(p)` of a `fn(char) -> bool` or a `Box<dyn FnMut(char) -> bool>` translates, dropping a box it owns where std does
- [std's char methods that have no mapping](/quest/m3/ts-char-methods.md) - `is_alphabetic`, `to_lowercase`, `len_utf8`, the escapes, and the rest of `char` translate, called or as values, by std's Unicode version
- [Waiting: a slice object for a mutable part of other values](/quest/m3/ts-slice-object.md) - waits on a moq profile showing the `Proxy` view's traps matter, then decides on an `rt.ByteSlice`-like form
- [Port the workflow guard to kixelated/quest](/quest/m3/quest-workflow-guard.md) - quest's environment guard parses YAML as this repository's does
- [A crate's own find and for_each](/quest/m3/ts-iter-own-calls.md) - a crate's iterator that overrides `find`, `rfind`, `find_map`, or `for_each` translates, each called where std's adaptors and consumers call it
Expand Down
36 changes: 36 additions & 0 deletions quest/m3/ts-char-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# [M] std's char methods that have no mapping

## Goal

[rust2-ts](/ts/README.md) translates every stable `char` method and conversion, called or
named as a function value, as in `s.split(char::is_alphabetic)` or
`chars.map(char::len_utf8)`. Each returns what std's does for every `char`, by std's
Unicode version, proven by differential tests against native Rust over every code point.

## Plan

Found in [#495](https://github.com/moq-dev/rust2/pull/495). Probed on main at
`7c41f2b1`, each of these fails as "unsupported call", both called and as a value:

- Classes: `is_alphabetic`, `is_lowercase`, `is_uppercase`, `is_alphanumeric`,
`is_control`, `is_numeric`, and `is_digit`.
- Case: `to_lowercase` and `to_uppercase`, and `Display` of the `ToLowercase` and
`ToUppercase` they return.
- Escapes: `escape_unicode`, `escape_debug`, and `escape_default`, and `Display` of
what each returns.
- Encoding: `len_utf8`, `len_utf16`, `encode_utf16`, and `char::decode_utf16`.
- Conversions: `char::from_digit` and `char::try_from(u32)`.

`encode_utf8` into a `[u8; 4]` fails instead as "a mutable reference to a value JS copies".

`is_whitespace`, `from_u32`, `to_digit`, `make_ascii_*`, the `is_ascii_*` family,
`From<u8>`, and `u32::from` already translate, and a mapped method already translates as a
value: the gap is the call's mapping, not the function value.

JS's own Unicode data (`\p{...}` regexes, `toLowerCase`) follows the engine's Unicode
version, which may differ from std's `char::UNICODE_VERSION`, and its case mapping is of
strings, not chars. Compare that against lowering core's own tables before choosing, and
measure the cost of either. The case and escape iterators are std iterators, which may
need their own `rt.Iter` and `Display`.

Public API: the translator's output, and the runtime's functions each needs.
29 changes: 29 additions & 0 deletions quest/m3/ts-fn-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# [S] A function pointer or a boxed closure as a string pattern

## Goal

[rust2-ts](/ts/README.md) translates a `str` search whose pattern is a function pointer,
`fn(char) -> bool`, or a boxed closure, `Box<F>` or `Box<dyn FnMut(char) -> bool>`, by
value or behind a reference. The search calls it as std's does, and drops a box it owns
where std drops it: as a search that returns a value returns, or with the iterator it
returns. Differential tests against native Rust prove it for every `str` search taking a
pattern.

## Plan

Found in [#495](https://github.com/moq-dev/rust2/pull/495), which made a reference to a
closure translate as a pattern. On main at `7c41f2b1`, each of these fails as "unsupported
call to `core::str::<impl str>::split::<...>`" (or `contains`):

- `s.contains(p)` and `s.split(p)` of `p: fn(char) -> bool`, and `s.split(&p)`.
- `s.split(b)` and `s.contains(b)` of `b: Box<dyn FnMut(char) -> bool>`, and
`s.contains(&mut b)`.
- `s.split(b)` and `s.contains(b)` of `b: Box<{closure}>`.

`pattern` in `ts/src/lower/library.rs` matches no `ty::FnPtr` and no `Box`.
`called_through` already sees through a `Box` to the closure it owns, and
`called_closures` drops an owned closure where std does. Check how a `Box<dyn FnMut>` is
called and dropped elsewhere before mapping it. A boxed closure that owns a value that
drops is the case to test hardest.

Public API: the translator's output.