Skip to content

Commit cf6baf3

Browse files
committed
make use of lazy iteration
1 parent 5a79fb1 commit cf6baf3

20 files changed

+318
-248
lines changed

src/compound.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,25 @@ export class IterableResult<const T> {
157157
static empty(): IterableResult<never> {
158158
return new IterableResult(function* () {});
159159
}
160+
collect(): ReadonlyArray<T> {
161+
const array: Array<T> = [];
162+
const error: Array<ResultError> = [];
163+
for (const result of this.iterable()) {
164+
switch (result.type) {
165+
case "value":
166+
array.push(result.value);
167+
break;
168+
case "error":
169+
error.push(result.error);
170+
break;
171+
}
172+
}
173+
if (error.length > 0) {
174+
throw new AggregateError(error);
175+
} else {
176+
return array;
177+
}
178+
}
160179
filter(mapper: (value: T) => boolean): IterableResult<T> {
161180
return this.flatMap((value) =>
162181
mapper(value) ? IterableResult.single(value) : IterableResult.empty()

src/main.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
resetElementsToDefault,
2424
} from "./settings_frontend.ts";
2525
import { translate } from "./translator/translator.ts";
26+
import { ResultError } from "./compound.ts";
2627

2728
const DICTIONARY_AUTO_PARSE_THRESHOLD = 9000;
2829

@@ -243,15 +244,24 @@ function main() {
243244
outputList.innerHTML = "";
244245
errorList.innerHTML = "";
245246
errorDisplay.innerText = "";
246-
const result = translate(inputTextBox.value);
247-
if (!result.isError()) {
248-
for (const translation of result.unwrap()) {
249-
const list = document.createElement("li");
250-
list.innerHTML = translation;
251-
outputList.appendChild(list);
247+
const iterableResult = translate(inputTextBox.value);
248+
const errors: Array<ResultError> = [];
249+
let yielded = false;
250+
for (const result of iterableResult.iterable()) {
251+
switch (result.type) {
252+
case "value": {
253+
yielded = true;
254+
const list = document.createElement("li");
255+
list.innerHTML = result.value;
256+
outputList.appendChild(list);
257+
break;
258+
}
259+
case "error":
260+
errors.push(result.error);
261+
break;
252262
}
253-
} else {
254-
const errors = result.errors;
263+
}
264+
if (!yielded) {
255265
switch (errors.length) {
256266
case 0:
257267
errorDisplay.innerText = UNKNOWN_ERROR_MESSAGE;

src/repl.ts

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,33 @@ if (import.meta.main) {
1515
if (input == null) {
1616
break;
1717
}
18-
const result = translate(input);
19-
if (result.isError()) {
20-
// deno-lint-ignore no-console
21-
console.error(new AggregateError(result.errors));
22-
} else {
23-
const translations = result.unwrap();
24-
for (const translation of translations) {
25-
const count = translation.match(/<strong>/g)?.length ?? 0;
26-
const text = unescape(
27-
translation.replaceAll(/<\/?strong>/g, "%c"),
28-
{ entityList },
29-
);
30-
// deno-lint-ignore no-console
31-
console.log(
32-
` - ${text}`,
33-
...repeatArray(["font-weight: bold", ""], count).flat(),
34-
);
18+
const iterableResult = translate(input);
19+
let errorHeaderShown = false;
20+
for (const result of iterableResult.iterable()) {
21+
switch (result.type) {
22+
case "value": {
23+
const translation = result.value;
24+
const count = translation.match(/<strong>/g)?.length ?? 0;
25+
const text = unescape(
26+
translation.replaceAll(/<\/?strong>/g, "%c"),
27+
{ entityList },
28+
);
29+
// deno-lint-ignore no-console
30+
console.log(
31+
` - ${text}`,
32+
...repeatArray(["font-weight: bold", ""], count).flat(),
33+
);
34+
break;
35+
}
36+
case "error": {
37+
if (!errorHeaderShown) {
38+
// deno-lint-ignore no-console
39+
console.error("Errors have occurred:");
40+
errorHeaderShown = true;
41+
}
42+
// deno-lint-ignore no-console
43+
console.error(`- ${result.error.message}`);
44+
}
3545
}
3646
}
3747
}

src/translator/adjective.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as Dictionary from "../../dictionary/type.ts";
22
import { nullableAsArray } from "../../misc/misc.ts";
3-
import { ArrayResult } from "../compound.ts";
3+
import { IterableResult } from "../compound.ts";
44
import * as TokiPona from "../parser/ast.ts";
55
import * as English from "./ast.ts";
66
import { UntranslatableError } from "./error.ts";
@@ -28,12 +28,12 @@ export function adjective(
2828
reduplicationCount: number;
2929
emphasis: null | TokiPona.Emphasis;
3030
}>,
31-
): ArrayResult<English.AdjectivePhrase & { type: "simple" }> {
31+
): IterableResult<English.AdjectivePhrase & { type: "simple" }> {
3232
const { definition, reduplicationCount, emphasis } = options;
33-
return ArrayResult.concat<{ emphasis: boolean; so: null | string }>(
34-
ArrayResult.from(() => new ArrayResult([so(emphasis)]))
33+
return IterableResult.concat<{ emphasis: boolean; so: null | string }>(
34+
IterableResult.from(() => IterableResult.single(so(emphasis)))
3535
.map((so) => ({ emphasis: false, so })),
36-
new ArrayResult([{ emphasis: emphasis != null, so: null }]),
36+
IterableResult.single({ emphasis: emphasis != null, so: null }),
3737
)
3838
.map(({ emphasis, so }) => ({
3939
type: "simple",
@@ -53,10 +53,10 @@ export function compoundAdjective(
5353
reduplicationCount: number;
5454
emphasis: null | TokiPona.Emphasis;
5555
}>,
56-
): ArrayResult<English.AdjectivePhrase & { type: "compound" }> {
56+
): IterableResult<English.AdjectivePhrase & { type: "compound" }> {
5757
const { adjectives, reduplicationCount, emphasis } = options;
5858
if (reduplicationCount === 1) {
59-
return ArrayResult.combine(
59+
return IterableResult.combine(
6060
...adjectives
6161
.map((definition) =>
6262
adjective({ definition, reduplicationCount: 1, emphasis })
@@ -69,7 +69,7 @@ export function compoundAdjective(
6969
emphasis: false,
7070
}));
7171
} else {
72-
return ArrayResult.errors([
72+
return IterableResult.errors([
7373
new UntranslatableError("reduplication", "compound adjective"),
7474
]);
7575
}

src/translator/as_string.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as Dictionary from "../../dictionary/type.ts";
2-
import { ArrayResult } from "../compound.ts";
2+
import { IterableResult } from "../compound.ts";
33
import { adjective, compoundAdjective } from "./adjective.ts";
44
import * as EnglishComposer from "./composer.ts";
55
import { nounAsPlainString, simpleNounForms } from "./noun.ts";
@@ -8,12 +8,12 @@ import { partialVerb, verb } from "./verb.ts";
88

99
export function definitionAsPlainString(
1010
definition: Dictionary.Definition,
11-
): ArrayResult<string> {
11+
): IterableResult<string> {
1212
switch (definition.type) {
1313
case "noun":
1414
return nounAsPlainString(definition);
1515
case "personal pronoun":
16-
return ArrayResult.concat(
16+
return IterableResult.concat(
1717
pronoun({
1818
definition,
1919
reduplicationCount: 1,
@@ -45,9 +45,9 @@ export function definitionAsPlainString(
4545
plural: definition.plural,
4646
});
4747
case "adverb":
48-
return new ArrayResult([definition.adverb]);
48+
return IterableResult.single(definition.adverb);
4949
case "interjection":
50-
return new ArrayResult([definition.interjection]);
50+
return IterableResult.single(definition.interjection);
5151
case "verb": {
5252
return partialVerb({ definition, reduplicationCount: 1, emphasis: false })
5353
.flatMap((partialVerb) =>
@@ -56,19 +56,19 @@ export function definitionAsPlainString(
5656
.map((verb) => EnglishComposer.verb(verb, 0));
5757
}
5858
case "filler":
59-
return new ArrayResult([
59+
return IterableResult.single(
6060
`${definition.before}${definition.repeat}${definition.after}`,
61-
]);
61+
);
6262
case "particle definition":
63-
return new ArrayResult([definition.definition]);
63+
return IterableResult.single(definition.definition);
6464
case "noun preposition":
6565
return nounAsPlainString(definition.noun)
6666
.map((noun) => `${noun} ${definition.preposition}`);
6767
case "numeral":
68-
return new ArrayResult([`${definition.numeral}`]);
68+
return IterableResult.single(`${definition.numeral}`);
6969
case "preposition":
70-
return new ArrayResult([definition.preposition]);
70+
return IterableResult.single(definition.preposition);
7171
case "modal verb":
72-
return new ArrayResult([definition.verb]);
72+
return IterableResult.single(definition.verb);
7373
}
7474
}

src/translator/clause.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { nullableAsArray, throwError } from "../../misc/misc.ts";
2-
import { ArrayResult } from "../compound.ts";
2+
import { IterableResult } from "../compound.ts";
33
import * as TokiPona from "../parser/ast.ts";
44
import * as English from "./ast.ts";
55
import { FilteredError, TranslationTodoError } from "./error.ts";
@@ -71,7 +71,7 @@ function phraseClause(phrases: TokiPona.MultiplePhrases) {
7171
});
7272
}
7373
function liClause(clause: TokiPona.Clause & { type: "li clause" }) {
74-
return ArrayResult.combine(
74+
return IterableResult.combine(
7575
multiplePhrasesAsNoun({
7676
phrases: clause.subjects,
7777
place: "subject",
@@ -134,27 +134,25 @@ function oClause(clause: TokiPona.Clause & { type: "o clause" }) {
134134
includeGerund: true,
135135
andParticle: "en",
136136
})
137-
: new ArrayResult([
138-
{
139-
type: "simple",
140-
determiner: [],
141-
adjective: [],
142-
noun: noEmphasis("you"),
143-
quantity: "plural",
144-
perspective: "second",
145-
postAdjective: null,
146-
postCompound: null,
147-
preposition: [],
148-
emphasis: false,
149-
},
150-
]);
151-
return ArrayResult.combine(subject, predicate(clause.predicates, "o"))
137+
: IterableResult.single({
138+
type: "simple",
139+
determiner: [],
140+
adjective: [],
141+
noun: noEmphasis("you"),
142+
quantity: "plural",
143+
perspective: "second",
144+
postAdjective: null,
145+
postCompound: null,
146+
preposition: [],
147+
emphasis: false,
148+
});
149+
return IterableResult.combine(subject, predicate(clause.predicates, "o"))
152150
.flatMap(([subject, predicate]) => {
153151
const subjectPerspective = perspective(subject);
154-
return ArrayResult.concat(
152+
return IterableResult.concat(
155153
verb(predicate, subjectPerspective, subject.quantity)
156154
.map((verb) => iWish(subject, verb)),
157-
ArrayResult.from(() =>
155+
IterableResult.from(() =>
158156
verb(
159157
addModalToAll(
160158
noAdverbs(noEmphasis("should")),
@@ -173,7 +171,9 @@ function oClause(clause: TokiPona.Clause & { type: "o clause" }) {
173171
);
174172
});
175173
}
176-
export function clause(clause: TokiPona.Clause): ArrayResult<English.Clause> {
174+
export function clause(
175+
clause: TokiPona.Clause,
176+
): IterableResult<English.Clause> {
177177
switch (clause.type) {
178178
case "phrases":
179179
return phraseClause(clause.phrases);
@@ -200,10 +200,12 @@ export function clause(clause: TokiPona.Clause): ArrayResult<English.Clause> {
200200
}
201201
export function contextClause(
202202
contextClause: TokiPona.ContextClause,
203-
): ArrayResult<ReadonlyArray<English.Clause>> {
203+
): IterableResult<ReadonlyArray<English.Clause>> {
204204
switch (contextClause.type) {
205205
case "prepositions":
206-
return ArrayResult.combine(...contextClause.prepositions.map(preposition))
206+
return IterableResult.combine(
207+
...contextClause.prepositions.map(preposition),
208+
)
207209
.map((prepositions) =>
208210
prepositions.map((preposition) => ({
209211
...preposition,
@@ -220,12 +222,14 @@ export function contextClause(
220222
emphasis: false,
221223
}]);
222224
case "anu":
223-
return ArrayResult.errors([
225+
return IterableResult.errors([
224226
new TranslationTodoError(`${contextClause.type} context clause`),
225227
]);
226228
default:
227-
return ArrayResult.concat<ReadonlyArray<English.Clause>>(
228-
new ArrayResult(nullableAsArray(unwrapSingleWord(contextClause)))
229+
return IterableResult.concat<ReadonlyArray<English.Clause>>(
230+
IterableResult.fromArray(
231+
nullableAsArray(unwrapSingleWord(contextClause)),
232+
)
229233
.flatMap((wordUnit) =>
230234
fromSimpleDefinition(
231235
wordUnit,

src/translator/determiner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { zip } from "@std/collections/zip";
22
import * as Dictionary from "../../dictionary/type.ts";
3-
import { ArrayResult } from "../compound.ts";
3+
import { IterableResult } from "../compound.ts";
44
import * as English from "./ast.ts";
55
import { FilteredError } from "./error.ts";
66
import { simpleNounForms } from "./noun.ts";
@@ -50,7 +50,7 @@ export function determiner(
5050
reduplicationCount: number;
5151
emphasis: boolean;
5252
}>,
53-
): ArrayResult<English.Determiner> {
53+
): IterableResult<English.Determiner> {
5454
const { definition } = options;
5555
return simpleNounForms({
5656
singular: definition.determiner,

0 commit comments

Comments
 (0)