From f8964c67994ddd54309abebdc86011180ae44ac6 Mon Sep 17 00:00:00 2001
From: lingdocs <71590811+lingdocs@users.noreply.github.com>
Date: Wed, 30 Mar 2022 15:47:22 +0500
Subject: [PATCH] got perfect working! (I think)
---
src/components/VerbPicker.tsx | 88 +++++++++++++++----
src/lib/phrase-building/compile-vp.ts | 2 +-
.../phrase-building/english-vp-rendering.ts | 57 ++++++++++--
src/lib/phrase-building/render-vp.ts | 51 ++++++++---
src/lib/phrase-building/vp-tools.ts | 10 ++-
src/types/gen-g.d.ts | 14 +--
6 files changed, 178 insertions(+), 44 deletions(-)
diff --git a/src/components/VerbPicker.tsx b/src/components/VerbPicker.tsx
index 66d468b..b4dfdd7 100644
--- a/src/components/VerbPicker.tsx
+++ b/src/components/VerbPicker.tsx
@@ -9,14 +9,15 @@ import {
ButtonSelect,
getVerbInfo,
} from "@lingdocs/pashto-inflector";
+import { isEquativeTense } from "../lib/phrase-building/vp-tools";
// import { useState } from "react";
const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{
label:
present
,
- value: "present",
+ value: "presentVerb",
}, {
label: subjunctive
,
- value: "subjunctive",
+ value: "subjunctiveVerb",
}, {
label: imperf. future
,
value: "imperfectiveFuture",
@@ -37,6 +38,29 @@ const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{
value: "habitualPerfectivePast",
}];
+const equativeTenseOptions: { label: string | JSX.Element, value: EquativeTense }[] = [{
+ label: "Present Perfect",
+ value: "present",
+}, {
+ label: "Habitual Perfect",
+ value: "habitual",
+}, {
+ label: "Subjunctive Perfect",
+ value: "subjunctive",
+}, {
+ label: "Future Perfect",
+ value: "future",
+}, {
+ label: "Past Perfect",
+ value: "past",
+}, {
+ label: "Would Be Perfect",
+ value: "wouldBe",
+}, {
+ label: "Past Subjunctive Perfect",
+ value: "pastSubjunctive",
+}];
+
// type Filters = {
// stative: boolean,
// dynamic: boolean,
@@ -62,12 +86,21 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
}
onChange(makeVerbSelection(v, verb));
}
- function onTenseSelect({ value }: { label: string, value: VerbTense }) {
+ function onTenseSelect({ value }: { label: string, value: VerbTense | EquativeTense }) {
if (verb) {
- onChange({
- ...verb,
- tense: value,
- });
+ if (isEquativeTense(value)) {
+ onChange({
+ ...verb,
+ tense: value,
+ tenseCategory: "perfect",
+ });
+ } else {
+ onChange({
+ ...verb,
+ tense: value,
+ tenseCategory: verb.tenseCategory === "perfect" ? "basic" : verb.tenseCategory,
+ });
+ }
}
}
function onPosNegSelect(value: string) {
@@ -78,12 +111,21 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
});
}
}
- function onTenseCategorySelect(value: "basic" | "modal") {
+ function onTenseCategorySelect(value: "basic" | "modal" | "perfect") {
if (verb) {
- onChange({
- ...verb,
- tenseCategory: value,
- });
+ if (value === "perfect") {
+ onChange({
+ ...verb,
+ tenseCategory: value,
+ tense: isEquativeTense(verb.tense) ? verb.tense : "present",
+ });
+ } else {
+ onChange({
+ ...verb,
+ tenseCategory: value,
+ tense: isEquativeTense(verb.tense) ? "presentVerb" : verb.tense,
+ });
+ }
}
}
function notInstransitive(t: "transitive" | "intransitive" | "grammatically transitive"): "transitive" | "grammatically transitive" {
@@ -123,6 +165,9 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
}, {
label: "Modal",
value: "modal",
+ }, {
+ label: "Perfect",
+ value: "perfect",
}]}
handleChange={onTenseCategorySelect}
/>
@@ -135,8 +180,13 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
onChange={onTenseSelect}
className="mb-2"
// @ts-ignore
- options={tenseOptions}
- placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.label : "Select Tense..."}
+ options={verb?.tenseCategory === "perfect" ? equativeTenseOptions : tenseOptions}
+ placeholder={verb ? (() => {
+ const label = (verb.tenseCategory === "perfect")
+ ? equativeTenseOptions.find(o => o.value === verb.tense)?.label
+ : tenseOptions.find(o => o.value === verb.tense)?.label;
+ return label || "Select Tense...";
+ })() : undefined}
{...zIndexProps}
/>
{verb &&
@@ -223,11 +273,17 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
type: "verb",
verb: verb,
dynAuxVerb,
- tense: oldVerbSelection ? oldVerbSelection.tense : "present",
+ ...oldVerbSelection ? {
+ // TODO: carry it over from the old selection!!
+ tense: "presentVerb",
+ tenseCategory: "basic",
+ } : {
+ tense: "presentVerb",
+ tenseCategory: "basic",
+ },
object,
transitivity,
isCompound,
- tenseCategory: oldVerbSelection ? oldVerbSelection.tenseCategory : "basic",
negative: oldVerbSelection ? oldVerbSelection.negative : false,
...("grammaticallyTransitive" in info) ? {
changeTransitivity: function (t) {
diff --git a/src/lib/phrase-building/compile-vp.ts b/src/lib/phrase-building/compile-vp.ts
index 6082b64..afbf14a 100644
--- a/src/lib/phrase-building/compile-vp.ts
+++ b/src/lib/phrase-building/compile-vp.ts
@@ -20,7 +20,7 @@ export function compileVP(VP: VPRendered, form: Form, combineLengths?: true): {
NPs,
kids,
verb,
- hasLeapfrog: VP.verb.tenseCategory === "modal",
+ hasLeapfrog: VP.verb.tenseCategory !== "basic",
negative: VP.verb.negative,
isCompound: VP.isCompound,
});
diff --git a/src/lib/phrase-building/english-vp-rendering.ts b/src/lib/phrase-building/english-vp-rendering.ts
index 014f7da..6481c4a 100644
--- a/src/lib/phrase-building/english-vp-rendering.ts
+++ b/src/lib/phrase-building/english-vp-rendering.ts
@@ -5,6 +5,16 @@ import {
parseEc,
} from "@lingdocs/pashto-inflector";
+function engHave(s: T.Person): string {
+ function isThirdPersonSing(p: T.Person): boolean {
+ return (
+ p === T.Person.ThirdSingMale ||
+ p === T.Person.ThirdSingFemale
+ );
+ }
+ return isThirdPersonSing(s) ? "has" : "have";
+}
+
export function renderEnglishVPBase({ subjectPerson, object, vs }: {
subjectPerson: T.Person,
object: NPSelection | ObjectNP,
@@ -12,7 +22,6 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
}): string[] {
const ec = parseEc(vs.verb.entry.ec || "");
const ep = vs.verb.entry.ep;
- const tense = vs.tense;
function engEquative(tense: "past" | "present", s: T.Person): string {
const [row, col] = getVerbBlockPosFromPerson(s);
return grammarUnits.englishEquative[tense][row][col];
@@ -33,17 +42,17 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
`$SUBJ will${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
]);
// TODO: Pull these out to a seperate entity and import it
- const builders: Record<
+ const basicBuilders: Record<
VerbTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
> = {
- present: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
+ presentVerb: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${isToBe(ec)
? `${engEquative("present", s)}${n ? " not" : ""}`
: `${n ? engPresC(s, ["don't", "doesn't"]) : ""} ${n ? ec[0] : engPresC(s, ec)}`}`,
`$SUBJ ${engEquative("present", s)}${n ? " not" : ""} ${ec[2]}`,
]),
- subjunctive: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
+ subjunctiveVerb: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
`that $SUBJ ${n ? " won't" : " will"} ${isToBe(ec) ? "be" : ec[0]}`,
`should $SUBJ ${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
]),
@@ -76,10 +85,10 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
VerbTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
> = {
- present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ presentVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ can${n ? "'t" : ""} ${isToBe(v) ? "be" : v[0]}`,
]),
- subjunctive: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ subjunctiveVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`that $SUBJ can${n ? "'t" : ""} ${isToBe(v) ? "be" : v[0]}`,
]),
imperfectiveFuture: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
@@ -105,6 +114,38 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
`$SUBJ would ${n ? " not" : ""} be able to ${isToBe(v) ? "be" : v[0]}`,
]),
};
- const base = (vs.tenseCategory === "basic" ? builders : modalBuilders)[tense](subjectPerson, ec, vs.negative);
+ const perfectBuilders: Record<
+ EquativeTense,
+ (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
+ > = {
+ present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ ${engHave(s)}${n ? " not" : ""} ${v[4]}`,
+ ]),
+ past: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ had${n ? " not" : ""} ${v[4]}`,
+ ]),
+ habitual: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ ${engHave(s)}${n ? " not" : ""} ${v[4]}`,
+ ]),
+ subjunctive: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `that $SUBJ will have${n ? " not" : ""} ${v[4]}`,
+ ]),
+ future: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ will${n ? " not" : ""} have ${v[4]}`,
+ ]),
+ wouldBe: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ would${n ? " not" : ""} have ${v[4]}`,
+ ]),
+ pastSubjunctive: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ would${n ? " not" : ""} have ${v[4]}`,
+ `$SUBJ should${n ? " not" : ""} have ${v[4]}`,
+ ]),
+ }
+ const base = (
+ (vs.tenseCategory === "perfect")
+ ? perfectBuilders[vs.tense]
+ : vs.tenseCategory === "basic"
+ ? basicBuilders[vs.tense]
+ : modalBuilders[vs.tense])(subjectPerson, ec, vs.negative);
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
-}
\ No newline at end of file
+}
diff --git a/src/lib/phrase-building/render-vp.ts b/src/lib/phrase-building/render-vp.ts
index 3f561af..3bff533 100644
--- a/src/lib/phrase-building/render-vp.ts
+++ b/src/lib/phrase-building/render-vp.ts
@@ -19,6 +19,7 @@ import {
getPersonFromNP,
removeBa,
isPastTense,
+ isEquativeTense,
} from "./vp-tools";
import { isPattern4Entry } from "../type-predicates";
import { renderEnglishVPBase } from "./english-vp-rendering";
@@ -140,24 +141,24 @@ function renderVerbSelection(vs: VerbSelection, person: T.Person, objectPerson:
return {
...vs,
person,
- ...getPsVerbConjugation(conj, vs.tense, vs.tenseCategory, person, objectPerson),
+ ...getPsVerbConjugation(conj, vs, person, objectPerson),
}
}
-function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, tenseCategory: "basic" | "modal", person: T.Person, objectPerson: T.Person | undefined): {
+function getPsVerbConjugation(conj: T.VerbConjugation, vs: VerbSelection, person: T.Person, objectPerson: T.Person | undefined): {
ps: {
head: T.PsString | undefined,
rest: T.SingleOrLengthOpts,
},
hasBa: boolean,
} {
- const f = getTenseVerbForm(conj, tense, tenseCategory);
+ const f = getTenseVerbForm(conj, vs.tense, vs.tenseCategory);
const block = getMatrixBlock(f, objectPerson, person);
- const perfective = isPerfective(tense);
+ const perfective = isPerfective(vs.tense);
const verbForm = getVerbFromBlock(block, person);
const hasBa = hasBaParticle(getLong(verbForm)[0]);
if (perfective) {
- const past = isPastTense(tense);
+ const past = isPastTense(vs.tense);
const splitInfo = conj.info[past ? "root" : "stem"].perfectiveSplit;
if (!splitInfo) return { ps: { head: undefined, rest: verbForm }, hasBa };
// TODO: Either solve this in the inflector or here, it seems silly (or redundant)
@@ -253,12 +254,12 @@ function getMatrixBlock(f: {
return f[personToLabel(person)];
}
-function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense, tenseCategory: "basic" | "modal"): T.VerbForm {
+function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense | EquativeTense, tenseCategory: "basic" | "modal" | "perfect"): T.VerbForm {
if (tenseCategory === "basic") {
- if (tense === "present") {
+ if (tense === "presentVerb") {
return conj.imperfective.nonImperative;
}
- if (tense === "subjunctive") {
+ if (tense === "subjunctiveVerb") {
return conj.perfective.nonImperative;
}
if (tense === "imperfectiveFuture") {
@@ -280,11 +281,34 @@ function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense, tenseCatego
return conj.perfective.habitualPast;
}
}
- if (tenseCategory === "modal") {
+ if (tenseCategory === "perfect") {
if (tense === "present") {
- return conj.imperfective.modal.nonImperative;
+ return conj.perfect.present;
+ }
+ if (tense === "past") {
+ return conj.perfect.past;
+ }
+ if (tense === "future") {
+ return conj.perfect.future;
+ }
+ if (tense === "habitual") {
+ return conj.perfect.habitual;
}
if (tense === "subjunctive") {
+ return conj.perfect.subjunctive;
+ }
+ if (tense === "wouldBe") {
+ return conj.perfect.affirmational;
+ }
+ if (tense === "pastSubjunctive") {
+ return conj.perfect.pastSubjunctiveHypothetical;
+ }
+ }
+ if (tenseCategory === "modal") {
+ if (tense === "presentVerb") {
+ return conj.imperfective.modal.nonImperative;
+ }
+ if (tense === "subjunctiveVerb") {
return conj.perfective.modal.nonImperative;
}
if (tense === "imperfectiveFuture") {
@@ -376,11 +400,12 @@ function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlur
return [0,1,2,3,6,7,8,9].includes(o.person);
}
-function isPerfective(t: VerbTense): boolean {
- if (t === "present" || t === "imperfectiveFuture" || t === "imperfectivePast" || t === "habitualImperfectivePast") {
+function isPerfective(t: VerbTense | EquativeTense): boolean {
+ if (isEquativeTense(t)) return false;
+ if (t === "presentVerb" || t === "imperfectiveFuture" || t === "imperfectivePast" || t === "habitualImperfectivePast") {
return false;
}
- if (t === "perfectiveFuture" || t === "subjunctive" || t === "perfectivePast" || t === "habitualPerfectivePast") {
+ if (t === "perfectiveFuture" || t === "subjunctiveVerb" || t === "perfectivePast" || t === "habitualPerfectivePast") {
return true;
}
throw new Error("tense not implemented yet");
diff --git a/src/lib/phrase-building/vp-tools.ts b/src/lib/phrase-building/vp-tools.ts
index e371d70..63f34c2 100644
--- a/src/lib/phrase-building/vp-tools.ts
+++ b/src/lib/phrase-building/vp-tools.ts
@@ -27,6 +27,14 @@ export function removeBa(ps: T.PsString): T.PsString {
return psRemove(ps, concatPsString(grammarUnits.baParticle, " "));
}
-export function isPastTense(tense: VerbTense): boolean {
+export function isEquativeTense(t: VerbTense | EquativeTense): t is EquativeTense {
+ return (t === "present" || t === "future" || t === "habitual" || t === "past" || t === "wouldBe" || t === "subjunctive" || t === "pastSubjunctive");
+}
+
+export function isPastTense(tense: VerbTense | EquativeTense): boolean {
+ if (isEquativeTense(tense)) {
+ // equative tenses are used HERE for the perfect forms, which are all considered past tense
+ return true;
+ }
return tense.toLowerCase().includes("past");
}
\ No newline at end of file
diff --git a/src/types/gen-g.d.ts b/src/types/gen-g.d.ts
index d68d87d..9f40127 100644
--- a/src/types/gen-g.d.ts
+++ b/src/types/gen-g.d.ts
@@ -26,8 +26,8 @@ type VPRendered = {
englishBase?: string[],
}
-type VerbTense = "present"
- | "subjunctive"
+type VerbTense = "presentVerb"
+ | "subjunctiveVerb"
| "perfectiveFuture"
| "imperfectiveFuture"
| "perfectivePast"
@@ -39,8 +39,6 @@ type VerbSelection = {
type: "verb",
verb: VerbEntry,
dynAuxVerb?: VerbEntry,
- tense: VerbTense,
- tenseCategory: "basic" | "modal",
object: VerbObject, // TODO: should have a locked in (but number changeable noun) here for dynamic compounds
transitivity: import("@lingdocs/pashto-inflector").Types.Transitivity,
isCompound: "stative" | "dynamic" | false,
@@ -49,7 +47,13 @@ type VerbSelection = {
// TODO: changeStativeDynamic
// TODO: add in aspect element here??
negative: boolean,
-};
+} & ({
+ tense: VerbTense,
+ tenseCategory: "basic" | "modal",
+} | {
+ tense: EquativeTense,
+ tenseCategory: "perfect"
+});
type VerbRendered = Omit & {
ps: {