From 4deff6110bfed23c991c7f0d4f3ede479042ff3d Mon Sep 17 00:00:00 2001 From: adueck Date: Tue, 27 Jun 2023 16:59:06 +0400 Subject: [PATCH] a lot more working --- src/components/src/blocks/Block.tsx | 173 ++++++++++++------ .../src/vp-explorer/VPExplorerQuiz.tsx | 2 - src/demo-components/VPBuilderDemo.tsx | 52 ------ src/lib/src/accent-helpers.ts | 68 ------- src/lib/src/fmaps.ts | 85 +++++++++ src/lib/src/misc-helpers.ts | 49 +---- .../src/new-verb-engine/render-verb.test.ts | 32 +++- src/lib/src/new-verb-engine/render-verb.ts | 23 +-- .../src/new-verb-engine/roots-and-stems.ts | 13 +- src/lib/src/pashto-inflector.ts | 9 +- src/lib/src/phrase-building/blocks-utils.ts | 5 + src/lib/src/phrase-building/compile.ts | 32 ++-- src/lib/src/phrase-building/render-vp.ts | 50 ++--- src/lib/src/verb-conjugation.ts | 9 +- src/types.ts | 17 +- 15 files changed, 319 insertions(+), 300 deletions(-) create mode 100644 src/lib/src/fmaps.ts diff --git a/src/components/src/blocks/Block.tsx b/src/components/src/blocks/Block.tsx index 5104a4b..ab1f7f9 100644 --- a/src/components/src/blocks/Block.tsx +++ b/src/components/src/blocks/Block.tsx @@ -3,7 +3,7 @@ import classNames from "classnames"; import { getEnglishFromRendered, } from "../../../lib/src/phrase-building/np-tools"; -import { getEnglishPersonInfo, getEnglishParticipleInflection } from "../../../lib/src/misc-helpers"; +import { getEnglishPersonInfo, getEnglishParticipleInflection, getEnglishGenNumInfo } from "../../../lib/src/misc-helpers"; import { useState } from "react"; import { getLength } from "../../../lib/src/p-text-helpers"; import { roleIcon } from "../vp-explorer/VPExplorerExplanationModal"; @@ -26,6 +26,10 @@ function Block({ opts, block, king, script }: { const role = king === "subject" ? "king" : king === "object" ? "servant" : undefined; return } + if (block.block.type === "objectSelection") { + const role = king === "object" ? "king" : king === "subject" ? "servant" : undefined; + return ; + } if (block.block.type === "predicateSelection") { const english = getEnglishFromRendered(block.block.selection); return
@@ -38,33 +42,19 @@ function Block({ opts, block, king, script }: { if (block.block.type === "negative") { return } - return
TODO
- // if (block.block.type === "perfectiveHead") { - // return - // } - // if (block.block.type === "verb") { - // return ; - // } - // if (block.block.type === "objectSelection") { - // const role = king === "object" ? "king" : king === "subject" ? "servant" : undefined; - // return ; - // } - // if (block.block.type === "perfectParticipleBlock") { - // return ; - // } - // if (block.block.type === "perfectEquativeBlock") { - // return ; - // } - // if (block.block.type === "modalVerbBlock") { - // return ; - // } - // if (block.block.type === "modalVerbKedulPart") { - // return - // } - // if (block.block.type === "complement") { - // return ; - // } - return null; + if (block.block.type === "PH") { + return ; + } + if (block.block.type === "VB") { + return ; + } + if (block.block.type === "complement") { + return + } + if (block.block.type === "NComp") { + return + } + return } export default Block; @@ -75,12 +65,72 @@ function Border({ children, extraClassName, padding }: { children: JSX.Element | style={{ padding: padding ? padding : "1rem", textAlign: "center", + gap: "0.5rem", }} > <>{children}
} +function VBBlock({ opts, block, script }: { + opts: T.TextOptions, + script: "p" | "f", + block: T.VBBasic | T.VBGenNum | (T.VBBasic & { + person: T.Person; + }), +}) { + const [length, setLength] = useState("long"); + const [version, setVersion] = useState(0); + const ps = getLength(block.ps, length); + function changeVersion() { + setVersion(o => (o + 1) % ps.length); + } + function changeLength() { + setLength(o => ( + o === "long" + ? "short" + : o === "short" && "mini" in block.ps + ? "mini" + : "long" + )); + } + const infInfo = "gender" in block + ? getEnglishGenNumInfo(block.gender, block.number) + : "person" in block + ? getEnglishPersonInfo(block.person, "short") + : ""; + return
+
+ {"long" in block.ps &&
{length}
} + {ps.length > 1 &&
v. {version + 1}
} +
+ + <> + {ps[version][script]} + + +
VBlock
+ {infInfo} +
+} + +function WeldedBlock({ opts, welded, script }: { + opts: T.TextOptions, + script: "p" | "f", + welded: T.Welded, +}) { + return
+ + {welded.left.type === "NComp" + ? + : welded.left.type === "VB" + ? + : } + + +
+} + // function VerbSBlock({ opts, v, script }: { // opts: T.TextOptions, // script: "p" | "f", @@ -142,20 +192,20 @@ function Border({ children, extraClassName, padding }: { children: JSX.Element | // // } -// function PerfHeadBlock({ opts, ps, script }: { -// opts: T.TextOptions, -// ps: T.PsString, -// script: "p" | "f", +function PerfHeadBlock({ opts, ps, script }: { + opts: T.TextOptions, + ps: T.PsString, + script: "p" | "f", -// }) { -// return
-// -// {ps[script]} -// -//
perf. head
-// {'\u00A0'} -//
; -// } +}) { + return
+ + {ps[script]} + +
perf. head
+ {'\u00A0'} +
; +} // function ModalAuxBlock({ opts, aux, script }: { // opts: T.TextOptions, @@ -182,7 +232,7 @@ function NegBlock({ opts, imperative, script }: { {negativeParticle[imperative ? "imperative" : "nonImperative"][script]}
Neg.
- {imperative ? "don't" : "not"} + {imperative ? "don't" : "not"} ; } @@ -207,7 +257,7 @@ function EquativeBlock({ opts, eq, script }: { {getLength(eq.ps, length)[0][script]}
Equative
- {getEnglishPersonInfo(eq.person, "short")} + {getEnglishPersonInfo(eq.person, "short")} ; } @@ -240,6 +290,25 @@ function ObjectBlock({ opts, obj, role, script }: { ; } +function NCompBlock({ opts, comp, script }: { + script: "p" | "f", + opts: T.TextOptions, + comp: T.Comp, +}) { + return
+ + {comp.ps[script]} + + {comp.type === "AdjComp" + ?
adj. {getEnglishGenNumInfo(comp.gender, comp.number)}
+ :
TODO
} + + todo + {/* {adj.e} */} + +
; +} + function ComplementBlock({ opts, comp, script, inside }: { script: "p" | "f", opts: T.TextOptions, @@ -255,7 +324,7 @@ function ComplementBlock({ opts, comp, script, inside }: { {adj.ps[0][script]}
Adj. ({getEnglishParticipleInflection(adj.person, "short")})
- {adj.e} + {adj.e} ; } @@ -268,7 +337,7 @@ function ComplementBlock({ opts, comp, script, inside }: { {adv.ps[0][script]}
Loc. Adv.
- {adv.e} + {adv.e} ; } return
@@ -286,13 +355,13 @@ function ComplementBlock({ opts, comp, script, inside }: { {!inside && <>
 
- {comp.e} + {comp.e} }
:
Sandwich
- {comp.e} + {comp.e}
} ; } @@ -310,13 +379,13 @@ export function APBlock({ opts, children, english, script }: { {ap.selection.ps[0][script]}
AP
- {english} + {english} ; } return
AP
- {english} + {english}
; } @@ -355,7 +424,7 @@ function CompNounBlock({ opts, noun, script }: {
Comp. Noun
- {noun.e} + {noun.e} } @@ -388,7 +457,7 @@ export function NPBlock({ opts, children, inside, english, script }: { ({getEnglishPersonInfo(np.selection.person, "short")}) : <>} - {!inside && {english}} + {!inside && {english}} } @@ -438,7 +507,7 @@ function Adjectives({ opts, children, script }: { } -function EnglishBelow({ children: e }: { children: string | undefined }) { +function SubText({ children: e }: { children: string | undefined }) { return
(t => `${t}Modal`); - -const testTenses = [ - ...testVerbTenses, - ...testPerfectTenses, - ...testAbilityTenses, -]; - function VPBuilderDemo({ opts }: { opts: T.TextOptions, }) { const [verbTs, setVerbTs] = useStickyState(0, "verbTs1"); const [verbTypeShowing, setVerbTypeShowing] = useStickyState("simple", "vTypeShowing"); const [transitivityShowing, setTransitivityShowing] = useStickyState("intransitive", "transitivityShowing1"); - const [testPerson, setTestPerson] = useStickyState({ - type: "pronoun", - distance: "far", - person: 0, - }, "testPronoun"); - const [testVoice, setTestVoice] = useStickyState("active", "testVoice"); - const [testTense, setTestTense] = useStickyState("presentVerb", "testTense"); // const onlyGrammTrans = (arr: Transitivity[]) => ( // arr.length === 1 && arr[0] === "grammatically transitive" // ); @@ -227,20 +189,6 @@ function VPBuilderDemo({ opts }: {
- - - {v?.verb.entry &&
, 3>; - } - return { - masc: removeFromSide(inf.masc), - fem: removeFromSide(inf.fem), - }; -} - /** * Determines if a string has any accents on it * @@ -175,60 +164,3 @@ export function hasAccents(s: string | T.PsString): boolean { if (typeof s !== "string") return hasAccents(s.f); return accentReplacer.some((x) => s.includes(x.accented)); } - -export function removeVerbAccent([a, b]: T.VerbRenderedOutput): T.VerbRenderedOutput { - return [ - removeVHeadAccent(a), - removeVAccent(b), - ]; -} - -function removeVHeadAccent([v]: [T.VHead] | []): [T.VHead] | [] { - if (v === undefined) { - return []; - } - if (v.type === "PH") { - return [{ - ...v, - ps: removeAccents(v.ps), - }]; - } - return [{ - ...v, - comp: removeCompAccent(v.comp), - }]; -} - -function removeCompAccent(comp: T.Comp): T.Comp { - return { - ...comp, - ps: removeAccents(comp.ps), - } -} - -function removeVAccent(v: [T.VB, T.VBE] | [T.VBE]): [T.VB, T.VBE]| [T.VBE] { - return v.map(removeVBAccent) as [T.VB, T.VBE]| [T.VBE]; -} - -function removeVBAccent(v: V): V { - if (v.type === "welded") { - return { - ...v, - left: removeWeldedLeftAccent(v.left), - } - } - return { - ...v, - ps: applyToSingOrLengthOpts(removeAccents, v.ps), - }; -} - -function removeWeldedLeftAccent(v: T.NComp | T.VBBasic | T.Welded) { - if (v.type === "NComp") { - return { - ...v, - comp: removeCompAccent(v.comp), - }; - } - return removeVBAccent(v); -} diff --git a/src/lib/src/fmaps.ts b/src/lib/src/fmaps.ts new file mode 100644 index 0000000..ae816fe --- /dev/null +++ b/src/lib/src/fmaps.ts @@ -0,0 +1,85 @@ +import * as T from "../../types"; + +export function fmapSingleOrLengthOpts(f: (x: A) => B, x: T.SingleOrLengthOpts): T.SingleOrLengthOpts { + if ("long" in x) { + return { + long: f(x.long), + short: f(x.short), + ..."mini" in x && x.mini ? { + mini: f(x.mini), + } : {}, + }; + } else { + return f(x); + } +} + +export function mapInflections(f: (x: T.PsString) => T.PsString, inf: T.UnisexInflections): T.UnisexInflections { + function handleSide(inf: T.InflectionSet): T.InflectionSet { + return inf.map(x => x.map(f)) as T.ArrayFixed, 3>; + } + return { + masc: handleSide(inf.masc), + fem: handleSide(inf.fem), + }; +} + +export function mapVerbRenderedOutput(f: (a: T.PsString) => T.PsString, [a, b]: T.VerbRenderedOutput): T.VerbRenderedOutput { + return [ + fmapVHead(a), + fmapV(b), + ]; + function fmapVHead([v]: [T.VHead] | []): [T.VHead] | [] { + if (v === undefined) { + return []; + } + if (v.type === "PH") { + return [{ + ...v, + ps: f(v.ps), + }]; + } + return [{ + ...v, + comp: fmapComp(v.comp), + }]; + } + function fmapComp(comp: T.Comp): T.Comp { + return { + ...comp, + ps: f(comp.ps), + }; + } + function fmapV(v: [T.VB, T.VBE] | [T.VBE]): [T.VB, T.VBE]| [T.VBE] { + return v.map(fmapVB) as [T.VB, T.VBE]| [T.VBE]; + } + function fmapVB(v: V): V { + if (v.type === "welded") { + return { + ...v, + left: fmapWeldedLeft(v.left), + right: fmapVB(v.right), + }; + } + return { + ...v, + ps: fmapSingleOrLengthOpts((x) => x.map(f), v.ps), + }; + } + function fmapWeldedLeft(v: T.NComp | T.VBBasic | T.Welded) { + if (v.type === "NComp") { + return { + ...v, + comp: fmapComp(v.comp), + }; + } + return fmapVB(v); + } +} + + + + + + + diff --git a/src/lib/src/misc-helpers.ts b/src/lib/src/misc-helpers.ts index a71c52a..0577642 100644 --- a/src/lib/src/misc-helpers.ts +++ b/src/lib/src/misc-helpers.ts @@ -7,20 +7,7 @@ */ import * as T from "../../types"; - -export function applyToSingOrLengthOpts(f: (x: X) => X, x: T.SingleOrLengthOpts): T.SingleOrLengthOpts { - if ("long" in x) { - return { - long: f(x.long), - short: f(x.short), - ..."mini" in x && x.mini ? { - mini: f(x.mini), - } : {}, - }; - } else { - return f(x); - } -} +import { fmapSingleOrLengthOpts } from "./fmaps"; export const blank: T.PsString = { p: "_____", @@ -110,19 +97,6 @@ export function hasPersInfs(info: T.NonComboVerbInfo | T.PassiveRootsAndStems | ); } -export function functionOnOptLengths(x: T.SingleOrLengthOpts, f: (y: U) => F): T.SingleOrLengthOpts { - if ("long" in x) { - return { - long: f(x.long), - short: f(x.short), - ...("mini" in x && x.mini) ? { - mini: f(x.mini), - } : {}, - }; - } - return f(x); -} - // TODO: deprecated using new verb rendering thing export function chooseParticipleInflection( pPartInfs: T.SingleOrLengthOpts | T.SingleOrLengthOpts, @@ -166,17 +140,10 @@ export function spaceInForm(form: T.FullForm): boolean { } export function getPersonFromVerbForm(form: T.SingleOrLengthOpts, person: T.Person): T.SentenceForm { - if ("long" in form) { - return { - long: getPersonFromVerbForm(form.long, person) as T.ArrayOneOrMore, - short: getPersonFromVerbForm(form.short, person) as T.ArrayOneOrMore, - ...form.mini ? { - mini: getPersonFromVerbForm(form.mini, person) as T.ArrayOneOrMore, - } : {}, - }; - } - const [row, col] = getVerbBlockPosFromPerson(person); - return form[row][col]; + return fmapSingleOrLengthOpts(x => { + const [row, col] = getVerbBlockPosFromPerson(person); + return x[row][col]; + }, form); } export function getVerbBlockPosFromPerson(person: T.Person): [0 | 1 | 2 | 3 | 4 | 5, 0 | 1] { @@ -207,7 +174,7 @@ export function getEnglishPersonInfo(person: T.Person, version?: "short" | "long ? "1st" : [2,3,8,9].includes(person) ? "2nd" - : "3rd") + (version !== "short" ? " pers." : ""); + : "3rd") + " pers."; const number = personIsPlural(person) ? "plur" : "sing"; const n = version === "short" ? (number === "plur" ? "pl" : "sg") : number; @@ -218,6 +185,10 @@ export function getEnglishPersonInfo(person: T.Person, version?: "short" | "long return `${p} ${n}. ${g}.`; } +export function getEnglishGenNumInfo(gender: T.Gender, number: T.NounNumber): string { + return `${gender === "masc" ? "masc" : "fem"} ${number === "plural" ? "plur." : "sing."}`; +} + export function getEnglishParticipleInflection(person: T.Person, version?: "short" | "long"): string { const number = personIsPlural(person) ? "plural" : "singular"; const n = version === "short" diff --git a/src/lib/src/new-verb-engine/render-verb.test.ts b/src/lib/src/new-verb-engine/render-verb.test.ts index a910ba7..e49538d 100644 --- a/src/lib/src/new-verb-engine/render-verb.test.ts +++ b/src/lib/src/new-verb-engine/render-verb.test.ts @@ -52,6 +52,7 @@ test("basic tenses", () => { verb: wahul, tense: "presentVerb", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -68,6 +69,7 @@ test("basic tenses", () => { verb: wahul, tense: "subjunctiveVerb", person: T.Person.SecondSingMale, + complementPerson: T.Person.SecondSingMale, voice: "active", negative: false, })).toEqual({ @@ -83,6 +85,7 @@ test("basic tenses", () => { verb: wahul, tense: "habitualPerfectivePast", person: T.Person.ThirdSingFemale, + complementPerson: T.Person.ThirdSingFemale, voice: "active", negative: false, })).toEqual({ @@ -108,7 +111,7 @@ test("basic tenses with inflecting roots/stems", () => { verb: bandawul, tense: "subjunctiveVerb", person: T.Person.FirstSingMale, - presObj: T.Person.ThirdSingFemale, + complementPerson: T.Person.ThirdSingFemale, voice: "active", negative: false, })).toEqual({ @@ -521,6 +524,7 @@ test("special endings", () => { verb: x.verb, tense: x.tense, person: T.Person.ThirdSingMale, + complementPerson: T.Person.ThirdSingMale, voice: "active", negative: false, })).toEqual({ hasBa: false, vbs: x.result }); @@ -530,6 +534,7 @@ test("special endings", () => { verb: kedulStat, tense: "perfectivePast", person: T.Person.FirstPlurMale, + complementPerson: T.Person.FirstPlurMale, voice: "active", negative: false, })).toEqual({ @@ -552,6 +557,7 @@ test("special endings", () => { verb: tlul, tense: "imperfectivePast", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -575,6 +581,7 @@ test("special endings", () => { verb: tlul, tense: "imperfectivePast", person: T.Person.ThirdSingFemale, + complementPerson: T.Person.ThirdSingFemale, voice: "active", negative: false, })).toEqual({ @@ -599,6 +606,7 @@ test("special endings", () => { verb: khorul, tense: "imperfectivePast", person: T.Person.ThirdPlurMale, + complementPerson: T.Person.ThirdPlurMale, voice: "active", negative: false, })).toEqual({ @@ -621,6 +629,7 @@ test("special endings", () => { verb: khorul, tense: "perfectivePast", person: T.Person.ThirdPlurMale, + complementPerson: T.Person.ThirdPlurMale, voice: "active", negative: false, })).toEqual({ @@ -646,6 +655,7 @@ test("imperative tenses", () => { verb: wahul, tense: "imperfectiveImperative", person: T.Person.SecondSingMale, + complementPerson: T.Person.SecondSingMale, voice: "active", negative: false, })).toEqual({ @@ -661,6 +671,7 @@ test("imperative tenses", () => { verb: wahul, tense: "perfectiveImperative", person: T.Person.SecondSingFemale, + complementPerson: T.Person.SecondSingFemale, voice: "active", negative: false, })).toEqual({ @@ -676,6 +687,7 @@ test("imperative tenses", () => { verb: wahul, tense: "imperfectiveImperative", person: T.Person.SecondPlurMale, + complementPerson: T.Person.SecondPlurMale, voice: "active", negative: false, })).toEqual({ @@ -691,6 +703,7 @@ test("imperative tenses", () => { verb: wahul, tense: "perfectiveImperative", person: T.Person.SecondPlurFemale, + complementPerson: T.Person.SecondPlurFemale, voice: "active", negative: false, })).toEqual({ @@ -709,6 +722,7 @@ test("ability tenses", () => { verb: wahul, tense: "presentVerbModal", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -744,6 +758,7 @@ test("basic tenses", () => { verb: wahul, tense: "presentVerb", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -760,6 +775,7 @@ test("basic tenses", () => { verb: wahul, tense: "subjunctiveVerb", person: T.Person.SecondSingMale, + complementPerson: T.Person.SecondSingMale, voice: "active", negative: false, })).toEqual({ @@ -775,6 +791,7 @@ test("basic tenses", () => { verb: wahul, tense: "habitualPerfectivePast", person: T.Person.ThirdSingFemale, + complementPerson: T.Person.ThirdSingFemale, voice: "active", negative: false, })).toEqual({ @@ -800,6 +817,7 @@ test("perfect tenses", () => { verb: wahul, tense: "presentPerfect", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -816,6 +834,7 @@ test("perfect tenses", () => { verb: wahul, tense: "subjunctivePerfect", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -832,6 +851,7 @@ test("perfect tenses", () => { verb: wahul, tense: "habitualPerfect", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -848,6 +868,7 @@ test("perfect tenses", () => { verb: wahul, tense: "habitualPerfect", person: T.Person.ThirdPlurMale, + complementPerson: T.Person.ThirdPlurMale, voice: "active", negative: false, })).toEqual({ @@ -864,6 +885,7 @@ test("perfect tenses", () => { verb: wahul, tense: "futurePerfect", person: T.Person.FirstSingMale, + complementPerson: T.Person.FirstSingMale, voice: "active", negative: false, })).toEqual({ @@ -880,6 +902,7 @@ test("perfect tenses", () => { verb: wahul, tense: "pastPerfect", person: T.Person.SecondSingFemale, + complementPerson: T.Person.SecondSingFemale, voice: "active", negative: false, })).toEqual({ @@ -903,6 +926,7 @@ test("perfect tenses", () => { verb: wahul, tense: "wouldBePerfect", person: T.Person.SecondSingFemale, + complementPerson: T.Person.SecondSingFemale, voice: "active", negative: false, })).toEqual({ @@ -926,6 +950,7 @@ test("perfect tenses", () => { verb: wahul, tense: "pastSubjunctivePerfect", person: T.Person.SecondSingFemale, + complementPerson: T.Person.SecondSingFemale, voice: "active", negative: false, })).toEqual({ @@ -946,6 +971,7 @@ test("perfect tenses", () => { verb: wahul, tense: "wouldHaveBeenPerfect", person: T.Person.SecondSingFemale, + complementPerson: T.Person.SecondSingFemale, voice: "active", negative: false, })).toEqual({ @@ -970,7 +996,7 @@ test("ending on complex verbs", () => { tense: "presentVerbModal", person: T.Person.SecondSingMale, voice: "active", - presObj: T.Person.ThirdSingFemale, + complementPerson: T.Person.ThirdSingFemale, negative: false, })).toEqual({ hasBa: false, @@ -1015,7 +1041,7 @@ test("ending on complex verbs", () => { tense: "presentVerb", person: T.Person.SecondSingMale, voice: "active", - presObj: T.Person.ThirdSingFemale, + complementPerson: T.Person.ThirdSingFemale, negative: false, })).toEqual({ hasBa: false, diff --git a/src/lib/src/new-verb-engine/render-verb.ts b/src/lib/src/new-verb-engine/render-verb.ts index 1c95c0c..4dd8ecc 100644 --- a/src/lib/src/new-verb-engine/render-verb.ts +++ b/src/lib/src/new-verb-engine/render-verb.ts @@ -5,6 +5,9 @@ import { personGender, personNumber, } from "../misc-helpers"; +import { + fmapSingleOrLengthOpts, +} from "../fmaps"; import { concatPsString, getLength, @@ -24,13 +27,13 @@ import { getAspect, isKedul, perfectTenseToEquative, verbEndingConcat } from "./ import { accentOnNFromEnd, accentPsSyllable, removeAccents } from "../accent-helpers"; // TODO: problem with laaR - no perfective split -export function renderVerb({ verb, tense, person, voice, presObj, negative }: { +export function renderVerb({ verb, tense, person, voice, negative, complementPerson }: { verb: T.VerbEntry, negative: boolean, tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense, // TODO: make T.Tense person: T.Person, + complementPerson: T.Person, voice: T.Voice, - presObj?: T.Person, }): { hasBa: boolean, vbs: T.VerbRenderedOutput, @@ -39,13 +42,7 @@ export function renderVerb({ verb, tense, person, voice, presObj, negative }: { return renderPerfectVerb({ verb, tense, voice, person }); } const isPast = isPastTense(tense); - const rootPerson = isPast ? person : (presObj ?? person); - const hasBa = tenseHasBa(tense); - const genderNumber = { - gender: personGender(rootPerson), - number: personNumber(rootPerson), - }; const aspect = getAspect(tense, negative); const isImperative = isImperativeTense(tense); const type = isAbilityTense(tense) ? "ability" : "basic"; @@ -57,7 +54,10 @@ export function renderVerb({ verb, tense, person, voice, presObj, negative }: { aspect, voice, type, - genderNumber, + genderNumber: { + gender: personGender(complementPerson), + number: personNumber(complementPerson), + }, }); // #2 add the verb ending to it const ending = getEnding(person, isPast, isImperative, aspect); @@ -98,10 +98,7 @@ function renderPerfectVerb({ tense, verb, voice, person }: { const equativeBlock: T.VBE = { type: "VB", person, - ps: "long" in equative ? { - long: equative.long[row][col], - short: equative.short[row][col], - } : equative[row][col], + ps: fmapSingleOrLengthOpts(x => x[row][col], equative), }; return { hasBa, diff --git a/src/lib/src/new-verb-engine/roots-and-stems.ts b/src/lib/src/new-verb-engine/roots-and-stems.ts index b393b3c..c9e0f20 100644 --- a/src/lib/src/new-verb-engine/roots-and-stems.ts +++ b/src/lib/src/new-verb-engine/roots-and-stems.ts @@ -15,6 +15,7 @@ import { accentOnNFromEnd, countSyllables, removeAccents } from "../accent-helpe import { isKawulVerb, isTlulVerb } from "../type-predicates"; import { vEntry, addAbilityEnding, weld, removeL, addTrailingAccent, tlulPerfectiveStem, getLongVB, possiblePPartLengths, isStatComp, statCompImperfectiveSpace, makeComplement, vTransitivity, isKedul } from "./rs-helpers"; import { inflectPattern3 } from "./new-inflectors"; +import { fmapSingleOrLengthOpts } from "../fmaps"; const statVerb = { intransitive: vEntry({"ts":1581086654898,"i":11100,"p":"کېدل","f":"kedul","g":"kedul","e":"to become _____","r":2,"c":"v. intrans.","ssp":"ش","ssf":"sh","prp":"شول","prf":"shwul","pprtp":"شوی","pprtf":"shúwey","noOo":true,"ec":"become"}), @@ -116,14 +117,10 @@ export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, n }; function addTail(ps: T.SingleOrLengthOpts): T.SingleOrLengthOpts { - if ("long" in ps) { - return { - long: addTail(ps.long) as T.PsString[], - short: addTail(ps.short) as T.PsString[], - }; - } - const withTail = concatPsString(ps[0], { p: "ی", f: "ey"}); - return inflectPattern3(withTail, { gender, number }); + return fmapSingleOrLengthOpts((x) => { + const withTail = concatPsString(x[0], { p: "ی", f: "ey"}); + return inflectPattern3(withTail, { gender, number }); + }, ps); } } diff --git a/src/lib/src/pashto-inflector.ts b/src/lib/src/pashto-inflector.ts index 79a09b8..e48a19a 100644 --- a/src/lib/src/pashto-inflector.ts +++ b/src/lib/src/pashto-inflector.ts @@ -30,6 +30,7 @@ import { splitUpSyllables, } from "./accent-helpers"; import * as T from "../../types"; +import { fmapSingleOrLengthOpts } from "./fmaps"; const endingInSingleARegex = /[^a]'?’?[aá]'?’?$/; const endingInHeyOrAynRegex = /[^ا][هع]$/; @@ -661,11 +662,5 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections, } export function inflectYey(ps: T.SingleOrLengthOpts): T.SingleOrLengthOpts { - if ("long" in ps) { - return { - long: inflectYey(ps.long) as T.UnisexInflections, - short: inflectYey(ps.short) as T.UnisexInflections, - } - } - return inflectRegularYeyUnisex(ps.p, ps.f); + return fmapSingleOrLengthOpts((x) => inflectRegularYeyUnisex(x.p, x.f), ps); } diff --git a/src/lib/src/phrase-building/blocks-utils.ts b/src/lib/src/phrase-building/blocks-utils.ts index 041a92a..39b420a 100644 --- a/src/lib/src/phrase-building/blocks-utils.ts +++ b/src/lib/src/phrase-building/blocks-utils.ts @@ -25,6 +25,11 @@ export function getSubjectSelection(blocks: T.EPSBlock[] | T.EPSBlockComplete[] return b.block; } +export function getComplementFromBlocks(blocks: T.Block[][]): T.Rendered | T.UnselectedComplementSelection | undefined { + const b = blocks[0].find(f => f.block.type === "complement"); + return b?.block as T.Rendered | T.UnselectedComplementSelection | undefined; +} + export function getSubjectSelectionFromBlocks(blocks: T.Block[][]): T.Rendered { const b = blocks[0].find(f => f.block.type === "subjectSelection"); if (!b || b.block.type !== "subjectSelection") { diff --git a/src/lib/src/phrase-building/compile.ts b/src/lib/src/phrase-building/compile.ts index 0dda645..a008b8f 100644 --- a/src/lib/src/phrase-building/compile.ts +++ b/src/lib/src/phrase-building/compile.ts @@ -1,7 +1,7 @@ import * as T from "../../../types"; import { capitalizeFirstLetter, - concatPsString, getLong, getShort, + concatPsString, getLong, } from "../p-text-helpers"; import { negativeParticle } from "../grammar-units"; import * as grammarUnits from "../grammar-units"; @@ -14,6 +14,7 @@ import { completeVPSelection } from "./vp-tools"; import { renderVP } from "./render-vp"; import { getAPsFromBlocks, + getComplementFromBlocks, getObjectSelectionFromBlocks, getPredicateSelectionFromBlocks, getSubjectSelectionFromBlocks, @@ -249,7 +250,13 @@ function getPsFromWelded(v: T.Welded): T.PsString[] { } return getPsFromWelded(v); } - return [...getPsFromSide(v.left), ...getPsFromSide(v.right)]; + const left = getPsFromSide(v.left); + const right = getPsFromSide(v.right); + return left.flatMap(leftVar => ( + right.flatMap(rightVar => ( + concatPsString(leftVar, " ", rightVar) + )) + )); } function getEngAPs(blocks: T.Block[][]): string { @@ -261,16 +268,17 @@ function getEngAPs(blocks: T.Block[][]): string { } function getEngComplement(blocks: T.Block[][]): string | undefined { - return "TODO"; - // const comp = getComplementFromBlocks(blocks); - // if (!comp) return undefined; - // if (comp.selection.type === "unselected") { - // return "____"; - // } - // if (comp.selection.type === "sandwich") { - // return getEnglishFromRendered({ type: "AP", selection: comp.selection }); - // } - // return comp.selection.e; + console.log("getting comp"); + const comp = getComplementFromBlocks(blocks); + console.log({ blocks, comp }); + if (!comp) return undefined; + if (comp.selection.type === "unselected") { + return "____"; + } + if (comp.selection.type === "sandwich") { + return getEnglishFromRendered({ type: "AP", selection: comp.selection }); + } + return comp.selection.e; } function putKidsInKidsSection(blocksWVars: T.Block[][], kids: T.Kid[], enforceKidsSectionBlankout: boolean): (T.Block | T.Kid | T.PsString)[][] { diff --git a/src/lib/src/phrase-building/render-vp.ts b/src/lib/src/phrase-building/render-vp.ts index a97397e..be879e8 100644 --- a/src/lib/src/phrase-building/render-vp.ts +++ b/src/lib/src/phrase-building/render-vp.ts @@ -1,42 +1,23 @@ import * as T from "../../../types"; import { - applyToSingOrLengthOpts, - getVerbBlockPosFromPerson, -} from "../misc-helpers"; -import { conjugateVerb } from "../verb-conjugation"; -import { - hasBaParticle, - getLong, - isImperativeBlock, - splitOffLeapfrogWordFull, - getShort, -} from "../p-text-helpers"; -import { removeAccents, removeAccentsWLength, removeVerbAccent } from "../accent-helpers"; + mapVerbRenderedOutput, +} from "../fmaps"; +import { removeAccents } from "../accent-helpers"; import { getPersonFromNP, - removeBa, isPastTense, - getTenseVerbForm, } from "./vp-tools"; import { - isAdjectiveEntry, isImperativeTense, - isLocativeAdverbEntry, - isAbilityTense, - isNounEntry, isPattern4Entry, - isPerfectTense, - isTlulVerb, } from "../type-predicates"; import { renderVerb } from "../new-verb-engine/render-verb"; import { renderEnglishVPBase } from "./english-vp-rendering"; -import { personGender } from "../misc-helpers"; import { renderNPSelection } from "./render-np"; import { getObjectSelection, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils"; import { renderAPSelection } from "./render-ap"; import { findPossesivesToShrink, orderKids, getMiniPronounPs } from "./render-common"; import { renderComplementSelection } from "./render-complement"; -import { makeNounSelection } from "./make-selections"; export function renderVP(VP: T.VPSelectionComplete): T.VPRendered { const subject = getSubjectSelection(VP.blocks).selection; @@ -58,7 +39,7 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered { const inflectSubject = isPast && isTransitive && !isMascSingAnimatePattern4(subject); const inflectObject = !isPast && isFirstOrSecondPersPronoun(object); // Render Elements - const firstBlocks = renderVPBlocks(VP.blocks, { + const firstBlocks = renderVPBlocks(VP.blocks, VP.externalComplement, { inflectSubject, inflectObject, king, @@ -68,6 +49,7 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered { verb: VP.verb.verb, tense: VP.verb.tense, person: kingPerson, + complementPerson: objectPerson || kingPerson, voice: VP.verb.voice, negative: VP.verb.negative, }); @@ -119,14 +101,15 @@ function removeAbbreviated(blocks: T.VPSBlockComplete[], form: T.FormVersion, ki if (form.removeKing && king === "object") return false; } return true; - }) + }); } function insertNegative(blocks: T.VerbRenderedOutput, negative: boolean, imperative: boolean): T.Block[][] { if (!negative) { return [blocks.flat().map(makeBlock)]; }; - const blocksA = removeVerbAccent(blocks).flat().map(makeBlock); + const blocksA = blocks.flat().map(makeBlock); + const blocksNoAccentA = mapVerbRenderedOutput(removeAccents, blocks).flat().map(makeBlock); const neg = makeBlock({ type: "negative", imperative }); const nonStandPerfectiveSplit = hasNonStandardPerfectiveSplit(blocks); if (blocks[1].length === 2) { @@ -135,21 +118,21 @@ function insertNegative(blocks: T.VerbRenderedOutput, negative: boolean, imperat return [ insertFromEnd(swapEndingBlocks(blocksA), neg, 2), insertFromEnd(swapEndingBlocks(blocksA, 2), neg, 3), - insertFromEnd(blocksA, neg, 1), + insertFromEnd(blocksNoAccentA, neg, 1), ] } return [ insertFromEnd(swapEndingBlocks(blocksA), neg, 2), - insertFromEnd(blocksA, neg, 1), + insertFromEnd(blocksNoAccentA, neg, 1), ]; } if (nonStandPerfectiveSplit) { return [ - insertFromEnd(blocksA, neg, 1), - insertFromEnd(blocksA, neg, 2), + insertFromEnd(blocksNoAccentA, neg, 1), + insertFromEnd(blocksNoAccentA, neg, 2), ]; } else { - return [insertFromEnd(blocksA, neg, 1)]; + return [insertFromEnd(blocksNoAccentA, neg, 1)]; } } @@ -172,8 +155,6 @@ function insertFromEnd(arr: X[], x: X, n: number): X[] { ]; } - - function hasNonStandardPerfectiveSplit([[ph]]: T.VerbRenderedOutput): boolean { if (!ph) { return false; @@ -196,7 +177,7 @@ function shrinkServant(np: T.NPSelection): T.MiniPronoun { } -function renderVPBlocks(blocks: T.VPSBlockComplete[], config: { +function renderVPBlocks(blocks: T.VPSBlockComplete[], externalComplement: T.VPSelectionComplete["externalComplement"], config: { inflectSubject: boolean, inflectObject: boolean, king: "subject" | "object", @@ -207,7 +188,8 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: { const adverbPerson = typeof object.selection === "object" ? getPersonFromNP(object.selection) : getPersonFromNP(subject.selection); - return blocks.reduce((blocks, { block }): T.Block[] => { + const b = externalComplement ? [...blocks, { block: externalComplement }] : blocks + return b.reduce((blocks, { block }): T.Block[] => { if (block.type === "subjectSelection") { return [ ...blocks, diff --git a/src/lib/src/verb-conjugation.ts b/src/lib/src/verb-conjugation.ts index 887a550..63cc7c5 100644 --- a/src/lib/src/verb-conjugation.ts +++ b/src/lib/src/verb-conjugation.ts @@ -32,8 +32,11 @@ import { inflectYey, } from "./pashto-inflector"; import { - accentOnNFromEnd, removeAccents, removeAccentsFromInflections, + accentOnNFromEnd, removeAccents, } from "./accent-helpers"; +import { + mapInflections, +} from "./fmaps"; import { pashtoConsonants } from "./pashto-consonants"; import { checkForIrregularConjugation, @@ -289,7 +292,7 @@ function makeJoinedModalContent(info: T.NonComboVerbInfo, aspectIn: T.Aspect): T function makeStativeCompoundSeperatedAspectContent(info: T.StativeCompoundVerbInfo, aspect: T.Aspect): T.AspectContent { const transitivity = getTransitivity(info); const complement: T.UnisexInflections = aspect === "imperfective" - ? removeAccentsFromInflections(info.complement) + ? mapInflections(removeAccents, info.complement) : info.complement; const presentComplement = (transitivity === "transitive" && complementInflects(complement)) ? unisexInfToObjectMatrix(complement) // transitive verb requires an object matrix for the complex @@ -406,7 +409,7 @@ function makePerfectContent(info: T.NonComboVerbInfo): T.PerfectContent { const pastPart: (" " | T.SingleOrLengthOpts | T.SingleOrLengthOpts)[] = (info.type === "stative compound") // for stative compounds - ? [removeAccentsFromInflections(info.complement), " ", stativeAux[transitivity].participle.past] + ? [mapInflections(removeAccents, info.complement), " ", stativeAux[transitivity].participle.past] // for regular compounds : [inflectYey(noPersInfs(info.participle.past))] diff --git a/src/types.ts b/src/types.ts index d9a921e..2fbe948 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,9 +6,9 @@ * */ -type Prettify = { - [K in keyof T]: T[K]; -} & {}; +// type prettify = { +// [k in keyof t]: t[k]; +// } & {}; export type PsStringField = "p" | "f"; export type PsString = { @@ -1105,13 +1105,16 @@ export type NComp = { // - locative adv // - sandwich (TODO) // - noun -/** complement block */ -export type Comp = { +export type Comp = AdjComp | OtherComp + +export type AdjComp = { type: "AdjComp", ps: PsString, - gender: Gender, number: NounNumber, -} | { + gender: Gender, +}; + +export type OtherComp = { type: "Comp", ps: PsString, };