From 623db598bbe931682236a8a0959d1b541ee79636 Mon Sep 17 00:00:00 2001 From: adueck Date: Mon, 17 Apr 2023 21:15:55 -0400 Subject: [PATCH] full testing for roots and stems and render verb - need to add imperative --- .../src/new-verb-engine/render-verb.test.ts | 733 +++++++++++++++++- src/lib/src/new-verb-engine/render-verb.ts | 91 ++- .../new-verb-engine/roots-and-stems.test.ts | 146 ++++ .../src/new-verb-engine/roots-and-stems.ts | 1 - src/lib/src/new-verb-engine/rs-helpers.ts | 81 +- src/lib/src/phrase-building/vp-tools.ts | 7 +- 6 files changed, 972 insertions(+), 87 deletions(-) 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 2e7eb8d..5cbd911 100644 --- a/src/lib/src/new-verb-engine/render-verb.test.ts +++ b/src/lib/src/new-verb-engine/render-verb.test.ts @@ -3,6 +3,7 @@ import { vEntry } from "./rs-helpers"; import * as T from "../../../types"; const wahul = vEntry({"ts":1527815399,"i":15049,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","r":4,"c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"}); +const raawrul = vEntry({"ts":1527815214,"i":6954,"p":"راوړل","f":"raawRúl","g":"raawRul","e":"to bring, deliver (inanimate objects)","r":4,"c":"v. trans.","tppp":"راووړ","tppf":"raawoR","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"bring,brings,bringing,brought,brought"}); const achawul = vEntry({"ts":1527811872,"i":224,"p":"اچول","f":"achawul","g":"achawul","e":"to put, pour, drop, throw, put on","r":4,"c":"v. trans.","ec":"put,puts,putting,put,put"}); const ganul = vEntry({"ts":1527812000,"i":11398,"p":"ګڼل","f":"gaNul, guNul","g":"gaNul,guNul","e":"to count, consider, reckon, suppose, assume","r":4,"c":"v. trans.","tppp":"ګاڼه","tppf":"gaaNu","ec":"deem"}); const kawulStat = vEntry({"ts":1579015359582,"i":11030,"p":"کول","f":"kawul","g":"kawul","e":"to make ____ ____ (as in \"He's making me angry.\")","r":4,"c":"v. trans.","ssp":"کړ","ssf":"kR","prp":"کړل","prf":"kRul","pprtp":"کړی","pprtf":"kúRey","noOo":true,"ec":"make,makes,making,made,made"}); @@ -26,6 +27,7 @@ const kenaastul = vEntry({"ts":1527812759,"i":11124,"p":"کېناستل","f":"ke const ghadzedul = vEntry({"ts":1527812615,"i":9500,"p":"غځېدل","f":"ghadzedul","g":"ghadzedul","e":"stretch out, lie, be extended, expand","r":3,"c":"v. intrans.","ec":"stretch","ep":"out"}); const prexodul = vEntry({"ts":1527815190,"i":2495,"p":"پرېښودل","f":"prexodúl","g":"prexodul","e":"to leave, abandon, forsake, let go, allow","r":4,"c":"v. trans.","psp":"پرېږد","psf":"preGd","noOo":true,"separationAtP":3,"separationAtF":3,"ec":"abandon"}); const raawustul = vEntry({"ts":1527819827,"i":6955,"p":"راوستل","f":"raawustúl","g":"raawustul","e":"to bring, deliver (animate objects), obtain, extract","r":3,"c":"v. trans.","psp":"راول","psf":"raawul","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"bring,brings,bringing,brought,brought"}); +const leedul = vEntry({"ts":1527812275,"i":12049,"p":"لیدل","f":"leedul","g":"leedul","e":"to see","r":4,"c":"v. trans./gramm. trans.","psp":"وین","psf":"ween","tppp":"لید","tppf":"leed","ec":"see,sees,seeing,saw,seen"}); const bandawul = vEntry( {"ts":1527821309,"i":1792,"p":"بندول","f":"bandawul","g":"bandawul","e":"to close, block, stop, barricade, cut off, restrain, hold back","r":3,"c":"v. stat. comp. trans.","l":1577301753727,"ec":"close"}, {"ts":1577301753727,"i":1780,"p":"بند","f":"band","g":"band","e":"closed, blocked, stopped","c":"adj."}, @@ -42,7 +44,7 @@ const stureyKedul = vEntry( {"ts":1591033069786,"i":7878,"p":"ستړی کېدل","f":"stuRey kedul","g":"stuReykedul","e":"to get tired, fatigued","r":4,"c":"v. stat. comp. intrans.","l":1527815306,"ec":"get","ep":"tired"}, {"ts":1527815306,"i":7876,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","r":4,"c":"adj. / adv."}, ); - +const ooPh: T.PH = { type: "PH", ps: { p: "و", f: "óo" }}; test("basic tenses", () => { expect(renderVerb({ @@ -97,6 +99,537 @@ test("basic tenses", () => { }); }); +test("basic tenses with inflecting roots/stems", () => { + expect(renderVerb({ + verb: bandawul, + tense: "subjunctiveVerb", + person: T.Person.FirstSingMale, + presObj: T.Person.ThirdSingFemale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بنده", f: "bánda" }, + gender: "fem", + number: "singular", + }, + }, + ], + [ + { + type: "VB", + ps: { + long: [{ p: "کړم", f: "kRum" }], + short: [{ p: "کم", f: "kum" }], + }, + person: T.Person.FirstSingMale, + }, + ], + ], + }); +}); + +test("special endings", () => { + const tests: { + verb: T.VerbEntryNoFVars, + tense: "perfectivePast" | "imperfectivePast", + result: T.VerbRenderedOutput, + }[] = [ + // verbs ending in -awul + { + verb: achawul, + tense: "perfectivePast", + result: [ + [{ type: "PH", ps: { p: "وا", f: "wáa" }}], + [ + { + type: "VB", + ps: { + long: [{ p: "چولو", f: "chawulo" }], + short: [{ p: "چاوه", f: "chaawu" }], + }, + person: 4, + }, + ], + ], + }, + { + verb: achawul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "اچولو", f: "achawúlo" }], + short: [{ p: "اچاوه", f: "achaawú" }], + }, + person: 4, + }, + ], + ], + }, + // verbs with special tppp + { + verb: ganul, + tense: "perfectivePast", + result: [ + [ooPh], + [ + { + type: "VB", + ps: { + long: [{ p: "ګڼلو", f: "gaNulo" }], + short: [{ p: "ګاڼه", f: "gaaNu" }], + }, + person: 4, + }, + ], + ], + }, + { + verb: ganul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "ګڼلو", f: "gaNúlo" }], + short: [{ p: "ګاڼه", f: "gaaNú" }], + }, + person: 4, + }, + ], + ], + }, + // verbs with special tppp ending in a consonant + { + verb: khatul, + tense: "perfectivePast", + result: [ + [ooPh], + [ + { + type: "VB", + ps: { + long: [{ p: "ختلو", f: "khatulo" }], + short: [ + { p: "خوت", f: "khot" }, + // // TODO: is this even right? + // { p: "خوته", f: "khotu" }, + // { p: "خوتو", f: "khoto" }, + ], + }, + person: 4, + }, + ], + ], + }, + { + verb: leedul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "لیدلو", f: "leedúlo" }], + short: [ + { p: "لید", f: "léed" }, + // // TODO: is this even right? + // { p: "خوته", f: "khotu" }, + // { p: "خوتو", f: "khoto" }, + ], + }, + person: 4, + }, + ], + ], + }, + { + verb: raawrul, + tense: "perfectivePast", + result: [ + [{ type: "PH", ps: { p: "را", f: "ráa" }}], + [ + { + type: "VB", + ps: { + long: [{ p: "وړلو", f: "wRulo" }], + short: [{ p: "ووړ", f: "woR" }], + }, + person: 4, + }, + ], + ], + }, + // verbs ending in a dental ت or د + { + verb: rasedul, + tense: "perfectivePast", + result: [ + [ooPh], + [ + { + type: "VB", + ps: { + long: [{ p: "رسېدلو", f: "rasedulo" }], + short: [ + { p: "رسېد", f: "rased" }, + { p: "رسېده", f: "rasedu" }, + { p: "رسېدو", f: "rasedo" }, + ], + }, + person: 4, + }, + ], + ], + }, + { + verb: awuxtul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "اوښتلو", f: "awUxtúlo" }], + short: [ + { p: "اوښت", f: "awÚxt" }, + { p: "اوښته", f: "awUxtú" }, + { p: "اوښتو", f: "awUxtó" }, + ], + }, + person: 4, + }, + ], + ], + }, + // other verbs + { + verb: weshul, + tense: "perfectivePast", + result: [ + [ooPh], + [ + { + type: "VB", + ps: { + long: [{ p: "وېشلو", f: "weshulo" }], + short: [ + { p: "وېشه", f: "weshu" }, + { p: "وېشو", f: "wesho" }, + ], + }, + person: 4, + }, + ], + ], + }, + { + verb: kedulStat, + tense: "perfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "شولو", f: "shwulo" }], + short: [{ p: "شو", f: "sho" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: kedulStat, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "کېدلو", f: "kedúlo" }], + short: [{ p: "کېده", f: "kedú" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: kawulStat, + tense: "perfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "کړلو", f: "kRulo" }], + short: [ + { p: "کړ", f: "kuR" }, + { p: "کړه", f: "kRu" }, + { p: "کړو", f: "kRo" }, + ], + mini: [{ p: "که", f: "ku" }, { p: "کو", f: "ko" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: kawulDyn, + tense: "perfectivePast", + result: [ + [ooPh], + [ + { + type: "VB", + ps: { + long: [{ p: "کړلو", f: "kRulo" }], + short: [ + { p: "کړ", f: "kuR" }, + { p: "کړه", f: "kRu" }, + { p: "کړو", f: "kRo" }, + ], + mini: [{ p: "که", f: "ku" }, { p: "کو", f: "ko" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: kawulDyn, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "کولو", f: "kawúlo" }], + short: [{ p: "کاوه", f: "kaawú" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: tlul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "تللو", f: "tlúlo" }], + short: [{ p: "ته", f: "tú" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: tlul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "تللو", f: "tlúlo" }], + short: [{ p: "ته", f: "tú" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: raatlul, + tense: "imperfectivePast", + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "راتللو", f: "raatlúlo" }], + short: [{ p: "راته", f: "raatú" }], + }, + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: raatlul, + tense: "perfectivePast", + result: [ + [{ type: "PH", ps: { p: "را", f: "ráa" }}], + [ + { + type: "VB", + ps: [{ p: "غی", f: "ghey" }], + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + { + verb: wartlul, + tense: "perfectivePast", + result: [ + [{ type: "PH", ps: { p: "ور", f: "wár" }}], + [ + { + type: "VB", + ps: [{ p: "غی", f: "ghey" }], + person: T.Person.ThirdSingMale, + }, + ], + ], + }, + ]; + tests.forEach(x => { + expect(renderVerb({ + verb: x.verb, + tense: x.tense, + person: T.Person.ThirdSingMale, + voice: "active", + })).toEqual({ hasBa: false, vbs: x.result }); + }); + + expect(renderVerb({ + verb: kedulStat, + tense: "perfectivePast", + person: T.Person.FirstPlurMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "شولو", f: "shwuloo" }], + short: [{ p: "شو", f: "shoo" }], + }, + person: T.Person.FirstPlurMale, + }, + ], + ], + }); + expect(renderVerb({ + verb: tlul, + tense: "imperfectivePast", + person: T.Person.FirstSingMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "تللم", f: "tlúlum" }], + // TODO: Shouldn't be accent here on single syllable + short: [{ p: "تلم", f: "tlúm" }], + }, + person: T.Person.FirstSingMale, + }, + ], + ], + }); + expect(renderVerb({ + verb: tlul, + tense: "imperfectivePast", + person: T.Person.ThirdSingFemale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "تلله", f: "tlúla" }], + // TODO: Shouldn't be accent here on single syllable + short: [{ p: "تله", f: "tlá" }], + }, + person: T.Person.ThirdSingFemale, + }, + ], + ], + }); + // avoid redundant ل ending + expect(renderVerb({ + verb: khorul, + tense: "imperfectivePast", + person: T.Person.ThirdPlurMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "خوړل", f: "khoRúl" }], + short: [{ p: "خوړل", f: "khoRúl" }], + }, + person: T.Person.ThirdPlurMale, + }, + ], + ], + }); + expect(renderVerb({ + verb: khorul, + tense: "perfectivePast", + person: T.Person.ThirdPlurMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [ooPh], + [ + { + type: "VB", + ps: { + long: [{ p: "خوړل", f: "khoRul" }], + short: [{ p: "خوړل", f: "khoRul" }], + }, + person: T.Person.ThirdPlurMale, + }, + ], + ], + }); +}); + test("perfect tenses", () => { expect(renderVerb({ verb: wahul, @@ -113,6 +646,88 @@ test("perfect tenses", () => { ], ], }); + expect(renderVerb({ + verb: wahul, + tense: "subjunctivePerfect", + person: T.Person.FirstSingMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" }, + { type: "VB", ps: [{ p: "وم", f: "wum" }], person: T.Person.FirstSingMale }, + ], + ], + }); + expect(renderVerb({ + verb: wahul, + tense: "habitualPerfect", + person: T.Person.FirstSingMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" }, + { type: "VB", ps: [{ p: "یم", f: "yum" }], person: T.Person.FirstSingMale }, + ], + ], + }); + expect(renderVerb({ + verb: wahul, + tense: "habitualPerfect", + person: T.Person.ThirdPlurMale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلي", f: "wahúlee" }], gender: "masc", number: "plural" }, + { type: "VB", ps: [{ p: "وي", f: "wee" }], person: T.Person.ThirdPlurMale }, + ], + ], + }); + expect(renderVerb({ + verb: wahul, + tense: "futurePerfect", + person: T.Person.FirstSingMale, + voice: "active", + })).toEqual({ + hasBa: true, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" }, + { type: "VB", ps: [{ p: "یم", f: "yum" }], person: T.Person.FirstSingMale }, + ], + ], + }); + expect(renderVerb({ + verb: wahul, + tense: "pastPerfect", + person: T.Person.SecondSingFemale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" }, + { + type: "VB", + ps: { + long: [{ p: "ولې", f: "wule" }], + short: [{ p: "وې", f: "we" }], + }, + person: T.Person.SecondSingFemale, + }, + ], + ], + }); expect(renderVerb({ verb: wahul, tense: "wouldBePerfect", @@ -135,6 +750,44 @@ test("perfect tenses", () => { ], ], }); + expect(renderVerb({ + verb: wahul, + tense: "pastSubjunctivePerfect", + person: T.Person.SecondSingFemale, + voice: "active", + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" }, + { + type: "VB", + ps: [{ p: "وای", f: "waay" }, { p: "وی", f: "wey" }], + person: T.Person.SecondSingFemale, + }, + ], + ], + }); + expect(renderVerb({ + verb: wahul, + tense: "wouldHaveBeenPerfect", + person: T.Person.SecondSingFemale, + voice: "active", + })).toEqual({ + hasBa: true, + vbs: [ + [], + [ + { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" }, + { + type: "VB", + ps: [{ p: "وای", f: "waay" }, { p: "وی", f: "wey" }], + person: T.Person.SecondSingFemale, + }, + ], + ], + }); }); test("ability tenses", () => { @@ -169,4 +822,82 @@ test("ability tenses", () => { ], ], }); +}); + +test("ending on complex verbs", () => { + expect(renderVerb({ + verb: stureyKawul, + tense: "presentVerbModal", + person: T.Person.SecondSingMale, + voice: "active", + presObj: T.Person.ThirdSingFemale + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړې", f: "stuRe" }, + gender: "fem", + number: "singular", + }, + }, + right: { + type: "VB", + ps: { + long: [ + { p: "کولی", f: "kawúley" }, + { p: "کولای", f: "kawúlaay" }, + ], + short: [ + { p: "کوی", f: "kawéy" }, + { p: "کوای", f: "kawáay" }, + ], + }, + }, + }, + { + type: "VB", + ps: [{ p: "شې", f: "she" }], + person: T.Person.SecondSingMale, + }, + ], + ], + }); + expect(renderVerb({ + verb: stureyKawul, + tense: "presentVerb", + person: T.Person.SecondSingMale, + voice: "active", + presObj: T.Person.ThirdSingFemale + })).toEqual({ + hasBa: false, + vbs: [ + [], + [ + { + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړې", f: "stuRe" }, + gender: "fem", + number: "singular", + }, + }, + right: { + type: "VB", + ps: [{ p: "کوې", f: "kawé" }], + }, + person: T.Person.SecondSingMale, + }, + ], + ], + }); }); \ No newline at end of file diff --git a/src/lib/src/new-verb-engine/render-verb.ts b/src/lib/src/new-verb-engine/render-verb.ts index bcb8431..a90f688 100644 --- a/src/lib/src/new-verb-engine/render-verb.ts +++ b/src/lib/src/new-verb-engine/render-verb.ts @@ -17,20 +17,19 @@ import { isKawulVerb, isAbilityTense, isPerfectTense, isTlulVerb } from "../type import { tenseHasBa } from "../phrase-building/vp-tools"; import { isPastTense } from "../phrase-building/vp-tools"; import { makePsString, removeFVarients } from "../accent-and-ps-utils"; -import { pashtoConsonants } from "../pashto-consonants"; import { getPastParticiple, getRootStem } from "./roots-and-stems"; import { getAspect, isKedul, perfectTenseToEquative, verbEndingConcat } from "./rs-helpers"; - +import { accentOnNFromEnd, removeAccents } from "../accent-helpers"; // TODO: problem with laaR - no perfective split -// TODO: automatic 3rd person idiosyncronizing of raTul raaTu, shaRul, shaaRu, rasedul rased etc +// TODO: non past compounds with different object +// TODO: coverage of rs-helpers -// IMMEDIATE TODO: shwoo -> shoo - -export function renderVerb({ verb, tense, person, voice }: { +export function renderVerb({ verb, tense, person, voice, presObj }: { verb: T.VerbEntry, tense: T.VerbTense | T.PerfectTense | T.AbilityTense, // TODO: make T.Tense person: T.Person, voice: T.Voice, + presObj?: T.Person, }): { hasBa: boolean, vbs: T.VerbRenderedOutput, @@ -38,13 +37,14 @@ export function renderVerb({ verb, tense, person, voice }: { if (isPerfectTense(tense)) { return renderPerfectVerb({ verb, tense, voice, person }); } + const isPast = isPastTense(tense); + const rootPerson = isPast ? person : (presObj ?? person); const hasBa = tenseHasBa(tense); const genderNumber = { - gender: personGender(person), - number: personNumber(person), + gender: personGender(rootPerson), + number: personNumber(rootPerson), }; - const isPast = isPastTense(tense); const aspect = getAspect(tense); const type = isAbilityTense(tense) ? "ability" : "basic"; @@ -134,19 +134,25 @@ function addEnding({ verb, rs, ending, person, pastThird, aspect, basicForm }: { } function addToVBBasicEnd(vb: T.VBBasic, end: T.SingleOrLengthOpts): T.VBBasic { if ("long" in vb.ps) { + if (vb.ps.short[0].f === "ghl" && pastThird && basicForm) { + return { + ...vb, + ps: [{ p: "غی", f: "ghey" }], + }; + } const endLong = getLength(end, "long"); const endShort = getLength(end, "short"); - // TODO: this is hacky - const rsLong: T.PsString[] = vb.ps.long[0].f === "tlul" - ? [{ p: "تلل", f: "tlúl" }] - : vb.ps.long; + // TODO: this is hackyۉ return { ...vb, ps: { - long: verbEndingConcat(rsLong, endLong), + long: verbEndingConcat(vb.ps.long, endLong), short: pastThird && basicForm - ? ensure3rdPast(endShort, vb.ps.short, verb, aspect) + ? ensure3rdPast(vb.ps.short, endShort, verb, aspect) : verbEndingConcat(vb.ps.short, endShort), + ...vb.ps.mini ? { + mini: verbEndingConcat(vb.ps.mini, endShort), + } : {}, }, }; } @@ -171,8 +177,10 @@ function getEnding(person: T.Person, isPast: boolean) { // TODO: THIS IS PROBABLY SKEEEETCH function ensure3rdPast(rs: T.PsString[], ending: T.PsString[], verb: T.VerbEntry, aspect: T.Aspect): T.PsString[] { - if (isKedul(verb) && rs[0].p === "شو") { - return [{ p: "شو", f: "sho" }]; + if (isKedul(verb)) { + return aspect === "perfective" + ? [{ p: "شو", f: "sho" }] + : [{ p: "کېده", f: "kedú" }]; } if (isKawulVerb(verb) && rs[0].p === "کړ") { return [ @@ -182,30 +190,30 @@ function ensure3rdPast(rs: T.PsString[], ending: T.PsString[], verb: T.VerbEntry ]; } if (isTlulVerb(verb)) { - if (aspect === "perfective") { - return [{ p: "غی", f: "ghey" }]; - } - const specialTuShort: T.PsString = { + // should be imperfective at this point + // the perfective غی should already be covered in the function this is coming from + return [{ p: rs[0].p.slice(0, -1) + "ه", - f: rs[0].f.slice(0, -1) + (rs[0].f === "tl" ? "u" : "ú"), - }; - return [ - specialTuShort, - concatPsString(rs[0], { p: "و", f: "o" }), - ]; + f: rs[0].f.slice(0, -2) + "ú", + }]; } if (verb.entry.tppp && verb.entry.tppf) { - const tip = makePsString(verb.entry.tppp, verb.entry.tppf) + const tip = removeAccents(verb.entry.separationAtP !== undefined + ? makePsString(verb.entry.tppp.slice(verb.entry.separationAtP), verb.entry.tppf.slice(verb.entry.separationAtF)) + : makePsString(verb.entry.tppp, verb.entry.tppf)); + const aTip = aspect === "imperfective" + ? accentOnNFromEnd(tip, 0) + : tip; + return [aTip]; // if it ends in a consonant, the special form will also have another // variation ending with a ه - u - const endsInAConsonant = (pashtoConsonants.includes(tip.p.slice(-1)) || tip.f.slice(-1) === "w"); - return [ - tip, - ...endsInAConsonant ? [ - concatPsString(tip, { p: "ه", f: "u" }), - concatPsString(tip, { p: "و", f: "o" }), - ] : [], - ]; + // const endsInAConsonant = (pashtoConsonants.includes(tip.p.slice(-1)) || tip.f.slice(-1) === "w"); + // return [ + // aTip, + // ...endsInAConsonant ? [ + // ...verbEndingConcat([aTip], [{ p: "ه", f: "u" }, { p: "و", f: "o" }]), + // ] : [], + // ]; } const endsInAwul = ( (["awul", "awúl"].includes(removeFVarients(verb.entry.f).slice(-4))) @@ -215,12 +223,13 @@ function ensure3rdPast(rs: T.PsString[], ending: T.PsString[], verb: T.VerbEntry // TODO: check about verbs like tawul (if they exist) if (endsInAwul) { const base = { p: rs[0].p.slice(0, -1), f: rs[0].f.slice(0, -2) }; - return [concatPsString(base, { p: "اوه", f: "aawu" })]; + const aawuEnd = concatPsString(base, { p: "اوه", f: base.f.charAt(base.f.length-1) === "a" ? "awu" : "aawu" }); + return [aspect === "imperfective" + ? accentOnNFromEnd(aawuEnd, 0) + : aawuEnd]; } const endsInDental = ["د", "ت"].includes(rs[0].p.slice(-1)); // short endings like ورسېد - return (endsInDental ? [ - "", - ...ending, - ] : ending).map(e => concatPsString(rs[0], e)); + const ends = endsInDental ? [{ p: "", f: "" }, ...ending] : ending; + return verbEndingConcat(rs, ends); } diff --git a/src/lib/src/new-verb-engine/roots-and-stems.test.ts b/src/lib/src/new-verb-engine/roots-and-stems.test.ts index 6b5e672..546398e 100644 --- a/src/lib/src/new-verb-engine/roots-and-stems.test.ts +++ b/src/lib/src/new-verb-engine/roots-and-stems.test.ts @@ -42,6 +42,14 @@ const stureyKedul = vEntry( {"ts":1591033069786,"i":7878,"p":"ستړی کېدل","f":"stuRey kedul","g":"stuReykedul","e":"to get tired, fatigued","r":4,"c":"v. stat. comp. intrans.","l":1527815306,"ec":"get","ep":"tired"}, {"ts":1527815306,"i":7876,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","r":4,"c":"adj. / adv."}, ); +const bayaanedul = vEntry( + {"ts":1659037345120,"i":2055,"p":"بیانېدل","f":"bayaanedúl","g":"bayaanedul","e":"to be described, told, narrated, explained, declared","r":4,"c":"v. stat. comp. intrans.","l":1527814259}, + {"ts":1527814259,"i":2052,"p":"بیان","f":"bayáan","g":"bayaan","e":"description, statement, speaking, narration, sermon","r":4,"c":"n. m.","app":"بیانات","apf":"bayaanaat"}, +); +const khufaKedul = vEntry( + {"ts":1577898920635,"i":5845,"p":"خفه کېدل","f":"khufa kedul","g":"khufakedul","e":"to become sad, grieved, annoyed, upset; to be choked, to suffocate","r":4,"c":"v. stat. comp. intrans.","l":1527812798,"ec":"become","ep":"sad"}, + {"ts":1527812798,"i":5843,"p":"خفه","f":"khufa","g":"khufa","e":"sad, upset, angry; choked, suffocated","r":4,"c":"adj."}, +); const ooPH: T.PH= { type: "PH", ps: { p: "و", f: "óo" }}; @@ -440,6 +448,26 @@ describe("perfective stems", () => { }, ], }, + { + title: "has a perfective head from kawul dynamic", + tests: [ + { + verb: kawulDyn, + result: [ + [ooPH], + [ + { + type: "VB", + ps: { + long: [{ p: "کړ", f: "kR" }], + short: [{ p: "ک", f: "k" }], + }, + }, + ], + ], + }, + ], + }, { title: "irregular, inflecting stem for tlul", tests: [ @@ -550,6 +578,52 @@ describe("perfective stems", () => { ], ], }, + // noun complements don't inflect + { + verb: bayaanedul, + genderNumber: { gender: "fem", number: "plural" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "Comp", + ps: { p: "بیان", f: "bayáan" }, + }, + }, + ], + [ + { + type: "VB", + ps: [{ p: "ش", f: "sh" }], + }, + ], + ], + }, + // some adjectives can't inflect + { + verb: khufaKedul, + genderNumber: { gender: "fem", number: "plural" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "خفه", f: "khufa" }, + gender: "fem", + number: "plural", + }, + }, + ], + [ + { + type: "VB", + ps: [{ p: "ش", f: "sh" }], + }, + ], + ], + }, ], }, { @@ -743,6 +817,27 @@ describe("perfective roots", () => { }, ], }, + { + title: "has a perfective head from kawul dynamic", + tests: [ + { + verb: kawulDyn, + result: [ + [ooPH], + [ + { + type: "VB", + ps: { + long: [{ p: "کړل", f: "kRul" }], + short: [{ p: "کړ", f: "kR" }], + mini: [{ p: "ک", f: "k" }], + }, + }, + ], + ], + }, + ], + }, { title: "broken apart with complement seperately in the perfective", tests: [ @@ -1539,5 +1634,56 @@ describe("passive roots and stems", () => { }, ], ]); + expect(getRootStem({ + verb: stureyKawul, + aspect: "imperfective", + type: "basic", + voice: "passive", + genderNumber: { + gender: "masc", + number: "singular", + }, + rs: "stem", + })).toEqual([ + [], + [ + { + "type": "welded", + "left": { + "type": "welded", + "left": { + "type": "NComp", + "comp": { + "type": "AdjComp", + "ps": { + "p": "ستړی", + "f": "stuRey" + }, + "gender": "masc", + "number": "singular" + } + }, + "right": { + "type": "VB", + "ps": [ + { + "p": "کول", + "f": "kawul" + } + ] + } + }, + "right": { + "type": "VB", + "ps": [ + { + "p": "کېږ", + "f": "kéG" + } + ] + }, + } + ] + ]); }); }); 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 208731c..b393b3c 100644 --- a/src/lib/src/new-verb-engine/roots-and-stems.ts +++ b/src/lib/src/new-verb-engine/roots-and-stems.ts @@ -77,7 +77,6 @@ function getAbilityRs( ]; } -// TODO: kuRee shuwey etc export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, number }: { gender: T.Gender, number: T.NounNumber }): T.VBGenNum | T.WeldedGN { const v = removeFVarientsFromVerb(verb); if (voice === "passive") { diff --git a/src/lib/src/new-verb-engine/rs-helpers.ts b/src/lib/src/new-verb-engine/rs-helpers.ts index baef9ef..47c0bb0 100644 --- a/src/lib/src/new-verb-engine/rs-helpers.ts +++ b/src/lib/src/new-verb-engine/rs-helpers.ts @@ -2,7 +2,6 @@ import * as T from "../../../types"; import { removeFVarients } from "../accent-and-ps-utils"; import { accentOnNFromEnd, accentPsSyllable, countSyllables, removeAccents, removeAccentsWLength } from "../accent-helpers"; import { concatPsString, isUnisexSet, psStringFromEntry, trimOffPs } from "../p-text-helpers"; -import { getRootStem } from "./roots-and-stems"; import { inflectPattern1 } from "./new-inflectors"; import { getLength } from "../p-text-helpers"; import { equativeEndings } from "../grammar-units"; @@ -56,27 +55,27 @@ export function vEntry(e: any, c?: any): T.VerbEntryNoFVars { } as T.VerbEntryNoFVars; } -export function getAllRs(verb: T.VerbEntry): { - stem: { - perfective: T.RootsStemsOutput, - imperfective: T.RootsStemsOutput, - }, - root: { - perfective: T.RootsStemsOutput, - imperfective: T.RootsStemsOutput, - }, -} { - return { - stem: { - perfective: getRootStem({ verb, type: "basic", voice: "active", rs: "stem", aspect: "perfective", genderNumber: { gender: "masc", number: "singular" } }), - imperfective: getRootStem({ verb, type: "basic", voice: "active", rs: "stem", aspect: "imperfective", genderNumber: { gender: "masc", number: "singular" } }), - }, - root: { - perfective: getRootStem({ verb, type: "basic", voice: "active", rs: "root", aspect: "perfective", genderNumber: { gender: "masc", number: "singular" } }), - imperfective: getRootStem({ verb, type: "basic", voice: "active", rs: "root", aspect: "imperfective", genderNumber: { gender: "masc", number: "singular" } }), - }, - }; -} +// export function getAllRs(verb: T.VerbEntry): { +// stem: { +// perfective: T.RootsStemsOutput, +// imperfective: T.RootsStemsOutput, +// }, +// root: { +// perfective: T.RootsStemsOutput, +// imperfective: T.RootsStemsOutput, +// }, +// } { +// return { +// stem: { +// perfective: getRootStem({ verb, type: "basic", voice: "active", rs: "stem", aspect: "perfective", genderNumber: { gender: "masc", number: "singular" } }), +// imperfective: getRootStem({ verb, type: "basic", voice: "active", rs: "stem", aspect: "imperfective", genderNumber: { gender: "masc", number: "singular" } }), +// }, +// root: { +// perfective: getRootStem({ verb, type: "basic", voice: "active", rs: "root", aspect: "perfective", genderNumber: { gender: "masc", number: "singular" } }), +// imperfective: getRootStem({ verb, type: "basic", voice: "active", rs: "root", aspect: "imperfective", genderNumber: { gender: "masc", number: "singular" } }), +// }, +// }; +// } /** * adds a verb ending, creating all the variations with a set of root psStrings @@ -87,18 +86,16 @@ export function getAllRs(verb: T.VerbEntry): { * @returns */ export function verbEndingConcat(ps: T.PsString[], end: T.PsString[]): T.PsString[] { - if (ps[0].f === "shw") { - if (end[1]?.f === "o") { - return [{ p: "شو", f: "sho" }]; - } - if (end[0].f === "oo") { - return [{ p: "شو", f: "oo" }]; - } + if (ps[0].f === "shw" && end[0].f === "oo") { + return [{ p: "شو", f: "shoo" }]; } return ps.flatMap(v => ( end.map(e => { if (v.f.charAt(v.f.length-1) === "X") { - return concatPsString(trimOffPs(v, 0, 1), accentPsSyllable(e)) + // faster to do concatPsString(trimOffPs(v, 0, 1), accentSyllable(e)) + // but this covers cases like adding the 3rd person no-ending to a string with the + // trailing accent marker and still getting the accent right + return accentOnNFromEnd(concatPsString(trimOffPs(v, 0, 1), e), 0); } if (e.p === "ل" && ["ul", "úl"].includes(v.f.slice(-2))) { return v; @@ -199,14 +196,15 @@ export function addAbilityEnding(vb: T.VBA): T.VBA { if (vb.type === "welded") { return { ...vb, - right: addToVBBasicEnd(vb.right, abilityEnding), + right: addToEnd(vb.right, abilityEnding), }; } - return addToVBBasicEnd(vb, abilityEnding); -} - -export function addToVBBasicEnd(vb: T.VBBasic, end: T.PsString[]): T.VBBasic { - if ("long" in vb.ps) { + return addToEnd(vb, abilityEnding); + function addToEnd(vb: T.VBBasic, end: T.PsString[]): T.VBBasic { + /* istanbul ignore next */ + if (!("long" in vb.ps)) { + throw new Error("should have long and short form for adding to ability ending"); + } return { ...vb, ps: { @@ -215,17 +213,16 @@ export function addToVBBasicEnd(vb: T.VBBasic, end: T.PsString[]): T.VBBasic { }, }; } - return { - ...vb, - ps: verbEndingConcat(vb.ps, end), - }; } + export function possiblePPartLengths(vba: T.VBNoLenghts): T.VBBasic; export function possiblePPartLengths(vba: T.VBNoLenghts): T.VBA; export function possiblePPartLengths(vba: T.VBNoLenghts): T.VBA { const shortenableEndings = ["ښتل", "ستل", "وتل"]; const wrul = ["وړل", "راوړل", "وروړل", "دروړل"]; + // can't find a case where this is used - type safety + /* istanbul ignore next */ if ("right" in vba) { return { ...vba, @@ -302,5 +299,7 @@ export function perfectTenseToEquative(t: T.PerfectTense): keyof typeof equative ? "pastSubjunctive" : t === "wouldBePerfect" ? "past" - : "subjunctive" + : t === "wouldHaveBeenPerfect" + ? "pastSubjunctive" + : "subjunctive"; } \ No newline at end of file diff --git a/src/lib/src/phrase-building/vp-tools.ts b/src/lib/src/phrase-building/vp-tools.ts index 799ead4..7dc87aa 100644 --- a/src/lib/src/phrase-building/vp-tools.ts +++ b/src/lib/src/phrase-building/vp-tools.ts @@ -199,7 +199,7 @@ export function isPastTense(tense: T.Tense): boolean { } export function tenseHasBa(tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense): boolean { - return [ + const withBa: Parameters[0][] = [ "imperfectiveFuture", "perfectiveFuture", "habitualPerfectivePast", @@ -210,8 +210,9 @@ export function tenseHasBa(tense: T.VerbTense | T.PerfectTense | T.AbilityTense "habitualImperfectivePastModal", "futurePerfect", "wouldBePerfect", - "wouldBeHaveBeenPerfect", - ].includes(tense); + "wouldHaveBeenPerfect", + ]; + return withBa.includes(tense); } export function removeDuplicates(psv: T.PsString[]): T.PsString[] {