Skip to content

Commit

Permalink
Render arrows for V-to-𝘷-to-Asp-to-T movement
Browse files Browse the repository at this point in the history
  • Loading branch information
lynn committed May 13, 2024
1 parent d2701e8 commit 19cbd67
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/bot/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class KunaBot {
tall: false,
tree,
renderer: denotationRenderText,
showArrows: false,
}),
),
);
Expand Down
1 change: 1 addition & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ yargs
tall: argv.semantics,
tree: trees[0],
renderer: denotationRenderText,
showArrows: false,
});
const png = canvas.toBuffer('image/png');
fs.writeFileSync(argv.output as string, png);
Expand Down
25 changes: 25 additions & 0 deletions src/syntax/recover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class Scope {
class Recoverer {
private nextBinding = 0;
private nextCoindex = 0;
private nextMovementId = 0;

constructor() {}

Expand All @@ -187,6 +188,14 @@ class Recoverer {
return fixSerial(serial, terms, () => this.newCoindex());
}

private move(source: Tree, target: Tree) {
assertLeaf(source);
source.id ??= 'r' + this.nextMovementId++;
assertLeaf(target);
target.id ??= 'r' + this.nextMovementId++;
source.movedTo = target.id;
}

recover(tree: Tree, scope: Scope | undefined): StrictTree {
if ('children' in tree) {
if (tree.label === '*𝘷P') {
Expand Down Expand Up @@ -255,6 +264,22 @@ class Recoverer {
}
}

// v-to-Asp movement
if (tree.label === 'AspP' && right.label === '𝘷P') {
assertBranch(right);
const v =
right.left.label === '𝘷'
? right.left
: (right.right as Branch<Tree>).left;
this.move(v, left);
}

// Asp-to-T movement
if (tree.label === 'TP' && right.label === 'AspP') {
assertBranch(right);
this.move(right.left, left);
}

return fixed;
} else {
return tree;
Expand Down
62 changes: 50 additions & 12 deletions src/syntax/serial.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { Impossible, Ungrammatical, Unimplemented } from '../core/error';
import { splitNonEmpty } from '../core/misc';
import { Branch, Label, Leaf, Tree, effectiveLabel, makeNull } from '../tree';
import {
Branch,
Label,
Leaf,
Tree,
assertBranch,
assertLeaf,
effectiveLabel,
makeNull,
} from '../tree';

/**
* Toaq serials are too complicated to parse directly in the context-free
Expand Down Expand Up @@ -83,20 +92,27 @@ export function getFrame(verb: Tree): string {
}
}

let _i = 0;
function makeId(): string {
return 's' + _i++;
}

function makevP(verb: Tree, args: Tree[]): Tree {
const agent =
'word' in verb &&
!verb.word.covert &&
verb.word.entry?.type === 'predicate' &&
verb.word.entry.subject === 'agent';

const v = makeId();

switch (args.length) {
case 0: {
if (!('word' in verb)) throw new Impossible('Weird nullary verb');
return {
label: '𝘷P',
left: { label: '𝘷', word: { covert: true, value: 'BE' } },
right: { label: 'VP', word: verb.word },
left: { label: '𝘷', word: { covert: true, value: 'BE' }, id: v },
right: { id: makeId(), label: 'VP', word: verb.word, movedTo: v },
};
}
case 1: {
Expand All @@ -109,15 +125,19 @@ function makevP(verb: Tree, args: Tree[]): Tree {
left: subject,
right: {
label: "𝘷'",
left: { label: '𝘷', word: { covert: true, value: 'CAUSE' } },
right: { label: 'VP', word: verb.word },
left: { label: '𝘷', word: { covert: true, value: 'CAUSE' }, id: v },
right: { id: makeId(), label: 'VP', word: verb.word, movedTo: v },
},
};
} else {
return {
label: '𝘷P',
left: { label: '𝘷', word: { covert: true, value: 'BE' } },
right: { label: 'VP', left: verb, right: subject },
left: { label: '𝘷', word: { covert: true, value: 'BE' }, id: v },
right: {
label: 'VP',
left: { id: makeId(), ...verb, movedTo: v },
right: subject,
},
};
}
}
Expand All @@ -131,8 +151,13 @@ function makevP(verb: Tree, args: Tree[]): Tree {
left: {
label: '𝘷',
word: { covert: true, value: agent ? 'CAUSE' : 'BE' },
id: v,
},
right: {
label: 'VP',
left: { id: makeId(), ...verb, movedTo: v },
right: directObject,
},
right: { label: 'VP', left: verb, right: directObject },
},
};
}
Expand All @@ -143,11 +168,15 @@ function makevP(verb: Tree, args: Tree[]): Tree {
left: subject,
right: {
label: "𝘷'",
left: { label: '𝘷', word: { covert: true, value: 'CAUSE' } },
left: { label: '𝘷', word: { covert: true, value: 'CAUSE' }, id: v },
right: {
label: 'VP',
left: indirectObject,
right: { label: "V'", left: verb, right: directObject },
right: {
label: "V'",
left: { id: makeId(), ...verb, movedTo: v },
right: directObject,
},
},
},
};
Expand Down Expand Up @@ -211,8 +240,17 @@ function serialTovP(
args.push(makeNull('DP'));
}
const innerArgs: Tree[] = [...pros, ...args.slice(cCount)];
args.push(serialTovP(verbs.slice(1), innerArgs, newCoindex));
return makevP(verbs[0], args);
const v0 = verbs[0];
assertLeaf(v0);
const vP = serialTovP(verbs.slice(1), innerArgs, newCoindex);
assertBranch(vP);
const v = vP.left.label === '𝘷' ? vP.left : (vP.right as Branch<Tree>).left;
assertLeaf(v);
v.id ??= makeId();
v0.id ??= makeId();
v.movedTo = v0.id;
args.push(vP);
return makevP(v0, args);
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/tree/draw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class TreeDrawer {
constructor(
private theme: Theme,
private layerHeight: number,
private showArrows: boolean,
) {
const width = 8400;
const height = 4400;
Expand Down Expand Up @@ -167,12 +168,12 @@ class TreeDrawer {
this.ctx.beginPath();
const start = this.locations.get(i)!;
const end = this.locations.get(j)!;
const x0 = start.x - start.width / 2 - 15;
const y0 = start.y;
const x0 = start.x - start.width / 2;
const y0 = Math.max(end.y + 50, start.y + 20);
const x1 = end.x;
const y1 = end.y + 25;
const y1 = end.y + 20;
this.ctx.moveTo(x0, y0);
this.ctx.quadraticCurveTo(x1, y0, x1, y1);
this.ctx.bezierCurveTo((x0 + x1) / 2, y0 + 40, x1, y0, x1, y1);
this.ctx.stroke();
for (const dx of [-8, 8]) {
this.drawLine(x1, y1, x1 + dx, y1 + 8);
Expand All @@ -183,7 +184,7 @@ class TreeDrawer {
private fitCanvasToContents() {
const { minX, maxX, minY, maxY } = this.extent;
const cropWidth = maxX - minX;
const cropHeight = maxY - minY;
const cropHeight = maxY - minY + 30;
const temp = this.ctx.getImageData(minX, minY, cropWidth, cropHeight);
this.canvas.width = cropWidth;
this.canvas.height = cropHeight;
Expand All @@ -202,7 +203,7 @@ class TreeDrawer {
const placed = placer.placeTree(tree);
this.drawTree(this.rootX, this.rootY, placed);
await Promise.all(this.promises);
this.drawArrows();
if (this.showArrows) this.drawArrows();
this.fitCanvasToContents();
return this.canvas;
}
Expand All @@ -216,9 +217,10 @@ export function drawTreeToCanvas(options: {
denotation: CompactExpr,
theme: Theme,
) => RenderedDenotation<CanvasRenderingContext2D>;
showArrows: boolean;
}): Promise<Canvas> {
const { theme, tall, tree, renderer } = options;
const { theme, tall, tree, renderer, showArrows } = options;
const layerHeight = tall ? 150 : 100;
const drawer = new TreeDrawer(themes[theme], layerHeight);
const drawer = new TreeDrawer(themes[theme], layerHeight, showArrows);
return drawer.drawToCanvas(tree, renderer);
}
10 changes: 7 additions & 3 deletions src/web/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ export function Main(props: MainProps) {
);
case 'png-latex':
case 'png-text': {
const theme = darkMode.isDarkMode ? 'dark' : 'light';
const baseRenderer =
treeFormat === 'png-latex'
? denotationRenderLatex
Expand All @@ -144,8 +143,13 @@ export function Main(props: MainProps) {
? (e: CompactExpr, t: Theme) =>
baseRenderer(compactDenotation(e), t)
: baseRenderer;
const tall = mode.includes('semantics');
drawTreeToCanvas({ theme, tall, tree, renderer }).then(canvas => {
drawTreeToCanvas({
theme: darkMode.isDarkMode ? 'dark' : 'light',
tall: mode.includes('semantics'),
tree,
renderer,
showArrows: mode === 'syntax-tree',
}).then(canvas => {
setTimeout(() => {
if (treeImg.current) {
treeImg.current.src = canvas.toDataURL();
Expand Down

0 comments on commit 19cbd67

Please sign in to comment.