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
1 change: 0 additions & 1 deletion quest/m2/ts-model/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,4 @@ Public API: the translator's output for moq-net's model.

## Required

- [The std calls moq's main added to the model](/quest/m2/ts-model/main-std.md) - `VecDeque::range`, and `str::rsplit_once` and `split_terminator` by a `char`, translate
- [A crate's own iterator traits](/quest/m2/ts-model/iter-traits.md) - hashlink's double-ended, exact-size, and fused iterators, and their `size_hint`
17 changes: 0 additions & 17 deletions quest/m2/ts-model/main-std.md

This file was deleted.

1 change: 1 addition & 0 deletions quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ generic std gap is planned here even when moq never calls it.
- [A vector's exact capacity as it shrinks](/quest/m3/ts-vec-exact-capacity.md) - a deque made from a `Vec` splits its slices where std's does
- [A B-tree's searches call Ord as std's do](/quest/m3/ts-btree-search-order.md) - a B-tree's lookups and inserts call a key's own `Ord` in std's order and number
- [Rc and Arc of a slice](/quest/m3/ts-shared-slices.md) - `Rc<[T]>` and `Arc<[T]>` from a `Vec`, a slice, or an iterator translate
- [The rest of str's searches](/quest/m3/ts-str-searches.md) - `find`, `strip_prefix`, `replace`, `rsplit`, `splitn`, `matches`, `lines`, and the rest of `str`'s searches translate
- [Adding to a String](/quest/m3/ts-string-add.md) - `String + &str` translates as `+=` does
- [The rest of a vector's methods](/quest/m3/ts-vec-rest.md) - `append`, `resize`, `split_off`, `try_reserve`, and `Vec::from(VecDeque)` translate
- [A reversed zip's per-pair cost](/quest/m3/ts-zip-rev-overhead.md) - a reversed by-index zip costs per pair what a forward one does, or the gap is explained
Expand Down
24 changes: 24 additions & 0 deletions quest/m3/ts-str-searches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# [M] The rest of str's searches

## Goal

[rust2-ts](/ts/README.md) translates `str`'s pattern searches and text iterators still
refused, each by every pattern std takes, searching in std's order from each end, proven by
differential tests against native Rust.

## Plan

Found translating the [std calls moq's main added to the model](https://github.com/moq-dev/rust2/pull/434),
by a census of a crate calling each by a `char`. These refuse as unsupported calls:

- `find`, `strip_prefix`, `strip_suffix`, `trim_matches`, and `replace`;
- the iterators `rsplit`, `rsplit_terminator`, `splitn`, `rsplitn`, `split_inclusive`,
`matches`, `rmatches`, and `rmatch_indices`;
- `char_indices`, `lines`, and `split_whitespace`.

The runtime's `Searcher` in `rt/str.ts` already searches from both ends and `Split` holds
std's `allow_trailing_empty`, so most map onto them as `split`, `split_terminator`, and
`rsplit_once` do. A predicate's calls are visible, so each must call it on the chars std's
does, in order. No consumer calls them yet; they are planned here as part of std.

Public API: the translator's output.
2 changes: 2 additions & 0 deletions quest/m3/ts-vec-rest.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ elements through raw pointers, so each refuses with its span:
- `Vec::append`, `resize`, `resize_with`, `split_off`, `extend_from_within`, and
`try_reserve`, and `VecDeque`'s `append`, `resize`, and `split_off`.
- `From<VecDeque<T>>` for `Vec<T>`.
- `VecDeque::range_mut` of items JS copies, which `range` and `iter_mut` translate but its
places do not.

A vector's capacity follows only std's guarantees, at least its length and what
`with_capacity` and `reserve` ask for, and doubles as it grows (decided with the
Expand Down
24 changes: 23 additions & 1 deletion ts/fixtures/lang/caller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,28 @@ const drains = Array.from({ length: 32 * 13 * 13 }, (_, i) => {
/** `strs::iters` of each kind, on no text, text of each UTF-8 width, and parts between `/`s, empty ones too. */
const iters = Array.from({ length: 12 }, (_, kind) => [[], [2, 7, 9, 14], [0, 2, 0, 0, 7, 9], [14, 0]].map((data) => Uint8Array.of(...op("strs::iters"), kind, ...data))).flat();

/**
* `strs::strs`' splits and `rsplit_once` by `/`, and `strs::slices`' by an empty and a
* one-char pattern, on no text, a separator alone, twice, and at either end, read from
* either end.
*/
const separatorEnds = [[], [0], [0, 0], [0, 2], [2, 0], [0, 2, 0], [0x80, 2, 0], [2, 0x80, 0x80], [0, 0x82, 0x80, 7]];
const splitEnds = separatorEnds.flatMap((data) => [
...[1, 3].map((kind) => Uint8Array.of(...op("strs::strs"), kind, ...data)),
...[2, 2 | 8].map((kind) => Uint8Array.of(...op("strs::slices"), kind, ...data)),
]);

/**
* `collections::deque_ranges` of each form of range, over no items and over items whose
* front wraps past the buffer's end, at bounds empty, at either end, past it, and backwards.
*/
const dequeRangesOp = op("collections::deque_ranges");
const dequeRanges = [0, 0x18, 0xa8].flatMap((high) =>
Array.from({ length: 8 }, (_, form) =>
[[0, 0], [0, 3], [2, 2], [1, 4], [5, 5], [3, 1], [6, 7]].flatMap(([a, b]) => [[], [7, 8, 9]].map((items) => Uint8Array.of(...dequeRangesOp, high | form, a, b, ...items))),
).flat(),
);

/** `strs::hinted` of each adaptor and each pair of range lengths, each way, on `aé` alone. */
const hintedOp = op("strs::hinted");
const hinted = Array.from({ length: 10 * 7 * 21 }, (_, i) => Uint8Array.of(...hintedOp, i % 10, Math.floor(i / 10) % 7, Math.floor(i / 70)));
Expand Down Expand Up @@ -919,4 +941,4 @@ const sortCases = [
...Array.from({ length: 20 * 5 }, (_, i) => Uint8Array.of(...op("sorts::btrees"), i % 20, Math.floor(i / 20), 2, 9)),
];

export const cases: Uint8Array[] = [...loops, ...durations, ...ints(), ...utf8, ...floats, ...formats, ...parsed, ...singlesCases, ...singlesFormats, ...singlesParsed, ...dyns, ...cells, ...shared, ...locks, ...guards, ...maps, ...mappedLocks, ...relocks, ...tries, ...mutexMaps, ...printed, ...downgrades, ...leaks, ...placeCompares, ...rwlocks, ...onces, ...bounds, ...unsafeCells, ...edits, ...subslices, ...consumers, ...closures, ...elements, ...ranges, ...reducers, ...sliceEdits, ...drains, ...iters, ...hinted, ...peekedOthers, ...hints, ...reserves, ...setOps, ...zeros, ...writes, ...floatsMulAdds, ...singlesMulAdds, ...unlikeEqs, ...ownNes, ...rangeFroms, ...compares, ...unlikeCompares, ...rangeMethods, ...wraps(), ...refOrders, ...saturates(), ...methods(), ...separated, ...asciiCases, ...gets, ...capacityCases, ...ringsCases, ...remadeCases, ...sortCases];
export const cases: Uint8Array[] = [...loops, ...durations, ...ints(), ...utf8, ...floats, ...formats, ...parsed, ...singlesCases, ...singlesFormats, ...singlesParsed, ...dyns, ...cells, ...shared, ...locks, ...guards, ...maps, ...mappedLocks, ...relocks, ...tries, ...mutexMaps, ...printed, ...downgrades, ...leaks, ...placeCompares, ...rwlocks, ...onces, ...bounds, ...unsafeCells, ...edits, ...subslices, ...consumers, ...closures, ...elements, ...ranges, ...reducers, ...sliceEdits, ...drains, ...iters, ...splitEnds, ...dequeRanges, ...hinted, ...peekedOthers, ...hints, ...reserves, ...setOps, ...zeros, ...writes, ...floatsMulAdds, ...singlesMulAdds, ...unlikeEqs, ...ownNes, ...rangeFroms, ...compares, ...unlikeCompares, ...rangeMethods, ...wraps(), ...refOrders, ...saturates(), ...methods(), ...separated, ...asciiCases, ...gets, ...capacityCases, ...ringsCases, ...remadeCases, ...sortCases];
85 changes: 85 additions & 0 deletions ts/fixtures/lang/expected/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,91 @@ export function deques(data: rt.ByteSlice, out: rt.ByteVec): void {
rt.byteVecPush(out, rt.dequeIndex(q2, b2));
}

/**
* `VecDeque::range` by each form of range, over a ring buffer whose front items wrap past
* its end, read from both ends and cloned midway, with `{:?}` of what is left after each
* step, which shows the two slices std's splits it into; a range past the length or
* backwards panics as std's does.
*/
export function dequeRanges(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void {
let _31!: rt.u8;
let it!: rt.Iter<rt.u8>;
let item!: rt.u8 | undefined;
let _7_0!: rt.usize;
let _7_1!: rt.usize;
let _7_2Data!: Uint8Array;
let _7_2Start!: number;
let _7_2Len!: number;
if (!(data.length >= 2)) {
_7_0 = 0;
_7_1 = 0;
_7_2Data = data.data;
_7_2Start = data.start;
_7_2Len = data.length;
} else {
const _13: rt.usize = rt.usizeRem(data.data[data.start] as rt.usize, 8);
const _17: rt.usize = rt.usizeRem(data.data[data.start + 1] as rt.usize, 8);
_7_0 = _13;
_7_1 = _17;
_7_2Data = data.data;
_7_2Start = data.start + 2;
_7_2Len = data.length - 2;
}
const a: rt.usize = _7_0;
const b: rt.usize = _7_1;
const q: rt.VecDeque<rt.u8> = rt.dequeFromVec(rt.iterToArray(rt.iterSlice(rt.byteSliceView(new rt.ByteSlice(_7_2Data, _7_2Start, _7_2Len))), undefined, 1, true), 1, true) as rt.VecDeque<rt.u8>;
const _26: rt.u8 = rt.u8Rem(rt.u8Div(kind, 8), 4);
let iterStart: rt.u8 = 0;
const iterEnd: rt.u8 = _26;
while ((_31 = iterStart++) < iterEnd) {
rt.dequePushFront(q, 240 | _31);
}
const _39: rt.u8 = rt.u8Rem(kind, 8);
if (_39 === 0) {
it = rt.dequeRange(q, new rt.Range(a, b));
} else if (_39 === 1) {
const _44: rt.RangeInclusive<rt.usize> = new rt.RangeInclusive(a, b, rt.usizeStep);
it = rt.dequeRange(q, _44);
} else if (_39 === 2) {
it = rt.dequeRange(q, { end: b });
} else if (_39 === 3) {
it = rt.dequeRange(q, new rt.RangeFrom(a, rt.usizeStep));
} else if (_39 === 4) {
it = rt.dequeRange(q, undefined);
} else if (_39 === 5) {
it = rt.dequeRange(q, [{ tag: "Excluded", _0: a } as rt.RangeBound<rt.usize>, { tag: "Included", _0: b } as rt.RangeBound<rt.usize>] as [rt.RangeBound<rt.usize>, rt.RangeBound<rt.usize>]);
} else if (_39 === 6) {
it = rt.dequeRange(q, { end: b, inclusive: true });
} else {
it = rt.dequeRange(q, new rt.Range(a, a));
}
rt.byteVecPush(out, it.len() & 0xff);
const args2: rt.Fmt[] = [(f: rt.Formatter) => rt.fmtDequeIter(it, f, rt.u8Debug, "Iter")];
rt.byteVecExtendFromSlice(out, rt.stringAsBytes(rt.fmtFormat([args2[0]])));
let i2: rt.i32 = 0;
while (true) {
if ((rt.u8Shr(kind, rt.i32Add(5, rt.i32Rem(i2, 3))) & 1) === 1) {
item = rt.iterToOption(it.nextBack());
} else {
item = rt.iterToOption(it.next());
}
if (item !== undefined) {
rt.byteVecPush(out, item);
const args4: rt.Fmt[] = [(f: rt.Formatter) => rt.fmtDequeIter(it, f, rt.u8Debug, "Iter")];
rt.byteVecExtendFromSlice(out, rt.stringAsBytes(rt.fmtFormat([args4[0]])));
if (i2 === 1) {
rt.iterExtendBytes(out, rt.iterRev(it.clone()), undefined, true);
}
i2 = rt.i32Add(i2, 1);
} else {
rt.byteVecPush(out, 253);
const _117: rt.RangeFrom<rt.usize> = new rt.RangeFrom(rt.min(a, q.n), rt.usizeStep);
rt.iterExtendBytes(out, rt.iterRev(rt.dequeRange(q, _117)), undefined, true);
return;
}
}
}

/** `vec![a, b]` and `vec![x; n]`, of bytes, numbers, `Copy` tuples, and types that clone. */
export function vecs(data: rt.ByteSlice, out: rt.ByteVec): void {
let name!: string;
Expand Down
20 changes: 10 additions & 10 deletions ts/fixtures/lang/expected/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { cells as cells_cells } from "./cells.ts";
import { chars as chars_chars } from "./chars.ts";
import { chunks } from "./chunks.ts";
import { iters as clones_iters } from "./clones.ts";
import { hashMaps, sets, btreeMaps, deques as collections_deques, vecs as collections_vecs, stores, optionals, setOps, unlikeEqs, ownNes, cellEqs, unlikeCompares, refOrders } from "./collections.ts";
import { hashMaps, sets, btreeMaps, deques as collections_deques, dequeRanges, vecs as collections_vecs, stores, optionals, setOps, unlikeEqs, ownNes, cellEqs, unlikeCompares, refOrders } from "./collections.ts";
import { combinators } from "./combinators.ts";
import { conversions } from "./conversions.ts";
import { arcs as counts_arcs, clonedArcs, cyclicArcs, uniqueArcs, clonedRcs, cyclicRcs, rcs, uniqueRcs, copies as counts_copies } from "./counts.ts";
Expand Down Expand Up @@ -285,7 +285,7 @@ export function cases(): [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec)
downgraded(data97, out98);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["borrows::leaks", (_2198: rt.u8, data98: rt.ByteSlice, out99: rt.ByteVec): undefined => {
leaks(data98, out99);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["elements::vecs", (_2199: rt.u8, data99: rt.ByteSlice, out100: rt.ByteVec): undefined => {
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["collections::deque_ranges", dequeRanges as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["elements::vecs", (_2199: rt.u8, data99: rt.ByteSlice, out100: rt.ByteVec): undefined => {
elements_vecs(data99, out100);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["elements::arrays", (_2200: rt.u8, data100: rt.ByteSlice, out101: rt.ByteVec): undefined => {
elements_arrays(data100, out101);
Expand All @@ -309,16 +309,16 @@ export function cases(): [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec)
emptyParts(data109, out110);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["hashes::own", (_2210: rt.u8, data110: rt.ByteSlice, out111: rt.ByteVec): undefined => {
hashes_own(data110, out111);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["refs::compared", (a0159: rt.u8, a1159: rt.ByteSlice, a2159: rt.ByteVec): undefined => {
compared(a0159, a1159.data, a1159.start, a1159.length, a2159);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["rings::slices", (a0160: rt.u8, a1160: rt.ByteSlice, a2160: rt.ByteVec): undefined => {
rings_slices(a0160, a1160.data, a1160.start, a1160.length, a2160);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["refs::compared", (a0160: rt.u8, a1160: rt.ByteSlice, a2160: rt.ByteVec): undefined => {
compared(a0160, a1160.data, a1160.start, a1160.length, a2160);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["rings::slices", (a0161: rt.u8, a1161: rt.ByteSlice, a2161: rt.ByteVec): undefined => {
rings_slices(a0161, a1161.data, a1161.start, a1161.length, a2161);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["fmt::objects", (_2211: rt.u8, data111: rt.ByteSlice, out112: rt.ByteVec): undefined => {
fmt_objects(data111, out112);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["sorts::sorts", (a0161: rt.u8, a1161: rt.ByteSlice, a2161: rt.ByteVec): undefined => {
sorts(a0161, a1161.data, a1161.start, a1161.length, a2161);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["sorts::disorders", disorders as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["sorts::btrees", (a0163: rt.u8, a1163: rt.ByteSlice, a2163: rt.ByteVec): undefined => {
sorts_btrees(a0163, a1163.data, a1163.start, a1163.length, a2163);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["sorts::sorts", (a0162: rt.u8, a1162: rt.ByteSlice, a2162: rt.ByteVec): undefined => {
sorts(a0162, a1162.data, a1162.start, a1162.length, a2162);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["sorts::disorders", disorders as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["sorts::btrees", (a0164: rt.u8, a1164: rt.ByteSlice, a2164: rt.ByteVec): undefined => {
sorts_btrees(a0164, a1164.data, a1164.start, a1164.length, a2164);
}] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined]];
}

Expand Down
Loading