@hyperfixi/testing-framework 4.0.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +331 -1
- package/package.json +7 -7
- package/src/multilingual/command-shapes-gate.ts +76 -0
- package/src/multilingual/command-shapes.1.test.ts +9 -0
- package/src/multilingual/command-shapes.2.test.ts +9 -0
- package/src/multilingual/command-shapes.3.test.ts +9 -0
- package/src/multilingual/command-shapes.cases.json +6816 -0
- package/src/multilingual/command-shapes.cases.test.ts +122 -0
- package/src/multilingual/command-shapes.oracle.test.ts +204 -0
- package/src/multilingual/command-shapes.ts +839 -0
- package/src/multilingual/direct-path-shapes.ts +9 -2
- package/src/multilingual/value-matrix.names.test.ts +11 -1
- package/src/multilingual/value-matrix.ts +28 -3
|
@@ -376,8 +376,15 @@ export async function initDirectPathHosts(): Promise<DirectPathHosts> {
|
|
|
376
376
|
for (const steps of scriptOf(c)) parts.push(await run(host, c, code, lang, steps));
|
|
377
377
|
return parts.join(' ‖ ');
|
|
378
378
|
};
|
|
379
|
-
|
|
380
|
-
|
|
379
|
+
// Two failure channels: parse errors, and the tokenizer THROWING on a
|
|
380
|
+
// character it does not know (the text a refused translation leaves as written).
|
|
381
|
+
const rejects = (host: ScriptHost, code: string): string | undefined => {
|
|
382
|
+
try {
|
|
383
|
+
return host.parse(code)?.errors?.[0]?.message.split('\n')[0];
|
|
384
|
+
} catch (e) {
|
|
385
|
+
return (e as Error).message.split('\n')[0] ?? 'threw';
|
|
386
|
+
}
|
|
387
|
+
};
|
|
381
388
|
|
|
382
389
|
return {
|
|
383
390
|
async runCase(c) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* leaves out; the matrix shards run the names themselves.
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect } from 'vitest';
|
|
7
|
-
import { collidingNames, generateCells } from './value-matrix';
|
|
7
|
+
import { KEYWORD_NAMES, collidingNames, generateCells } from './value-matrix';
|
|
8
8
|
|
|
9
9
|
const names = new Map(collidingNames().map(entry => [entry.name, entry]));
|
|
10
10
|
|
|
@@ -29,6 +29,16 @@ describe('value matrix: colliding names', () => {
|
|
|
29
29
|
expect(names.has('an')).toBe(true);
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
// Upstream runs each as a variable; English's own parse dropped `set input
|
|
33
|
+
// to "a"`, and every language wrote `when` as its keyword (P49).
|
|
34
|
+
it('takes the English words upstream runs as variables (KEYWORD_NAMES)', () => {
|
|
35
|
+
for (const name of KEYWORD_NAMES) expect(names.has(name), name).toBe(true);
|
|
36
|
+
expect(KEYWORD_NAMES).toContain('input'); // an event name
|
|
37
|
+
expect(KEYWORD_NAMES).toContain('when'); // a structure word
|
|
38
|
+
expect(KEYWORD_NAMES).toContain('index'); // a value-lexicon word (P28)
|
|
39
|
+
expect(names.has('if')).toBe(false); // P53
|
|
40
|
+
});
|
|
41
|
+
|
|
32
42
|
it("leaves out upstream's `no` and the templates' variables", () => {
|
|
33
43
|
expect(names.has('no')).toBe(false);
|
|
34
44
|
expect(names.has('i')).toBe(false);
|
|
@@ -550,6 +550,30 @@ let collidingNamesMemo: readonly CollidingName[] | undefined;
|
|
|
550
550
|
*/
|
|
551
551
|
const CODE_NAMES: readonly string[] = ['userData'];
|
|
552
552
|
|
|
553
|
+
/**
|
|
554
|
+
* Names spelled like English vocabulary that upstream and the engine run as
|
|
555
|
+
* variables where a value stands: event names, which every tokenizer reads as
|
|
556
|
+
* an event (`set input to "a"` dropped from English's own parse), structure
|
|
557
|
+
* words (`when`, which every language wrote as its keyword), and words of the
|
|
558
|
+
* value lexicon (`index`, which bn and four others wrote natively) — P49, P28.
|
|
559
|
+
* Not a name the window already holds (`focus`, `length`), nor `then`: the
|
|
560
|
+
* fixture sets each name there, and a `then` on the window makes upstream
|
|
561
|
+
* take it for a promise. Not yet `if` or `end`, which open and close a block
|
|
562
|
+
* in every language's reader (OPEN_ITEMS P53: 93 and 505 failing pairs).
|
|
563
|
+
*/
|
|
564
|
+
export const KEYWORD_NAMES: readonly string[] = [
|
|
565
|
+
'click',
|
|
566
|
+
'input',
|
|
567
|
+
'change',
|
|
568
|
+
'keyup',
|
|
569
|
+
'submit',
|
|
570
|
+
'load',
|
|
571
|
+
'drop',
|
|
572
|
+
'when',
|
|
573
|
+
'index',
|
|
574
|
+
'value',
|
|
575
|
+
];
|
|
576
|
+
|
|
553
577
|
/**
|
|
554
578
|
* Variables spelled like a structure word of a language the matrix translates
|
|
555
579
|
* into: every one- or two-letter name semantic's `nameCollision` finds
|
|
@@ -580,14 +604,15 @@ export function collidingNames(): readonly CollidingName[] {
|
|
|
580
604
|
const tokens = tokenize(word, 'en').tokens;
|
|
581
605
|
return tokens.length === 1 && tokens[0]?.kind !== 'identifier';
|
|
582
606
|
};
|
|
583
|
-
collidingNamesMemo = candidates
|
|
584
|
-
.filter(word => !reserved.has(word) && !englishKeyword(word))
|
|
607
|
+
collidingNamesMemo = [...new Set([...candidates, ...KEYWORD_NAMES])]
|
|
608
|
+
.filter(word => !reserved.has(word) && (KEYWORD_NAMES.includes(word) || !englishKeyword(word)))
|
|
585
609
|
.flatMap(name => {
|
|
586
610
|
const readings = FOREIGN_LANGUAGES.map(language => ({
|
|
587
611
|
language,
|
|
588
612
|
collision: nameCollision(name, language),
|
|
589
613
|
}));
|
|
590
|
-
|
|
614
|
+
const structure = readings.some(reading => reading.collision === 'structure');
|
|
615
|
+
if (!structure && !KEYWORD_NAMES.includes(name)) return [];
|
|
591
616
|
const pronounIn = readings.filter(r => r.collision === 'pronoun').map(r => r.language);
|
|
592
617
|
return [{ name, pronounIn }];
|
|
593
618
|
});
|