Skip to content

Commit

Permalink
Merge branch 'melds' of github.com:hazelgrove/tylr into mousemove
Browse files Browse the repository at this point in the history
  • Loading branch information
disconcision committed Nov 8, 2024
2 parents 5733f53 + 3bd4f9a commit 8d11f4d
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 53 deletions.
44 changes: 31 additions & 13 deletions src/core/editor/Modify.re
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,19 @@ let relabel =
// None means token was removed. Some(ctx) means token was molded (or deferred and
// tagged as an unmolded space), ctx includes the molded token.
let mold =
(ctx: Ctx.t, ~fill=Cell.dirty, tok: Token.Unmolded.t): option(Ctx.t) => {
open Options.Syntax;
(ctx: Ctx.t, ~fill=Cell.dirty, tok: Token.Unmolded.t)
: Result.t(Ctx.t, Cell.t) => {
open Result.Syntax;
let ((l, r), rest) = Ctx.unlink_stacks(ctx);
// Grouter.dbg := true;
let+ (tok, grouted, l) = Molder.mold(l, ~fill, tok);
// Grouter.dbg := false;
// P.log("--- Molder.mold/success");
// P.show("tok", Token.show(tok));
// P.show("grouted", Grouted.show(grouted));
// P.show("stack", Stack.show(l));
let connected = Stack.connect(tok, grouted, l);
// P.show("connected", Stack.show(connected));
connected.bound == l.bound
? Ctx.link_stacks((connected, r), rest)
: Ctx.map_hd(
Expand All @@ -107,7 +115,7 @@ let mold =
};

let rec remold = (~fill=Cell.dirty, ctx: Ctx.t): (Cell.t, Ctx.t) => {
// P.log("--- remold");
// P.log("--- Modify.remold");
// P.show("fill", Cell.show(fill));
// P.show("ctx", Ctx.show(ctx));
let ((l, r), tl) = Ctx.unlink_stacks(ctx);
Expand All @@ -120,8 +128,14 @@ let rec remold = (~fill=Cell.dirty, ctx: Ctx.t): (Cell.t, Ctx.t) => {
|> Ctx.map_hd(Frame.Open.cat(Stack.(to_slope(l'), to_slope(r'))))
|> remold(~fill)
| Ok((dn, fill)) =>
// P.log("--- Modify.remold/done");
// P.show("dn", Slope.Dn.show(dn));
// P.show("fill", Cell.show(fill));
let bounds = (l.bound, r.bound);
// Melder.dbg := true;
let cell = Melder.complete_bounded(~bounds, ~onto=L, dn, ~fill);
// Melder.dbg := false;
// P.show("completed", Cell.show(cell));
let hd = ({...l, slope: []}, {...r, slope: []});
let ctx = Ctx.link_stacks(hd, tl);
(cell, ctx);
Expand Down Expand Up @@ -227,7 +241,7 @@ let try_expand = (s: string, z: Zipper.t): option(Zipper.t) => {
// if expandable, consider all expandable const labels
let* expanded = expand(tok);
let ((l, r), tl) = Ctx.unlink_stacks(rest);
let* (t, grouted, rest) = Molder.mold(l, expanded);
let* (t, grouted, rest) = Result.to_option(Molder.mold(l, expanded));
if (t.mtrl == Space(Unmolded) || t.mtrl == tok.mtrl) {
None;
} else {
Expand Down Expand Up @@ -304,7 +318,6 @@ let delete_toks =
);
},
)
|> Chain.map_loop(Cell.mark_degrouted(~side=L))
// finally, unmold the tokens (only relabeling the last token)
|> Chain.mapi_link(i => Token.unmold(~relabel=i - 1 / 2 == n - 1));
};
Expand All @@ -317,9 +330,14 @@ let insert_toks =
toks
|> Chain.fold_left(
fill => (ctx, fill),
((ctx, fill), tok, next_fill) =>
((ctx, fill), tok, next_fill) => {
// P.log("--- insert_toks/tok");
// P.show("ctx", Ctx.show(ctx));
// P.show("fill", Cell.show(fill));
// P.show("tok", Token.Unmolded.show(tok));
switch (mold(ctx, ~fill, tok)) {
| Some(ctx) =>
| Ok(ctx) =>
// P.show("molded tok", Ctx.show(ctx));
let (face, rest) = Ctx.pull(~from=L, ctx);
switch (face, next_fill.marks.cursor) {
// if molded token is longer than original, then move cursor out of
Expand All @@ -337,13 +355,13 @@ let insert_toks =
(ctx, next_fill);
| _ => (ctx, next_fill)
};
| None =>
| Error(fill) =>
// removed empty token
let next_fill =
Option.is_some(fill.marks.cursor)
? Cell.mark_ends_dirty(fill) : next_fill;
Cell.mark_ends_dirty(Cell.Space.merge(fill, next_fill));
(ctx, next_fill);
},
}
},
);
};

Expand Down Expand Up @@ -413,12 +431,12 @@ let insert = (s: string, z: Zipper.t) => {
open Options.Syntax;
let z = delete_sel(L, z);

// P.log("--- insert");
// P.log("--- Modify.insert");
let- () = try_expand(s, z);
let- () = try_move(s, z);
let- () = try_extend(s, z);

// P.log("--- insert/molding");
// P.log("--- Modify.insert/molding");
// P.show("z.ctx", Ctx.show(z.ctx));
let (toks, ctx) = relabel(s, z.ctx);
// P.show("toks", Chain.show(Cell.pp, Token.Unmolded.pp, toks));
Expand Down
2 changes: 1 addition & 1 deletion src/core/material/Walker.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
open Stds;
open Walk;

let debug = ref(false);
let dbg = ref(false);

let mtrlize_tile = ((l, r, s, from)) =>
Grammar.v
Expand Down
30 changes: 28 additions & 2 deletions src/core/parser/Grouter.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ open Sexplib.Std;
open Ppx_yojson_conv_lib.Yojson_conv.Primitives;
open Stds;

let dbg = ref(false);

let rec split_cell_padding = (~side: Dir.t, c: Cell.t) =>
switch (Cell.get(c)) {
| None => Cell.(empty, c)
Expand Down Expand Up @@ -147,6 +149,12 @@ let fill_default =
// assumes cs already squashed sans padding
let fill_swing = (cs: Cells.t, sw: Walk.Swing.t, ~from: Dir.t) => {
let cs = Dir.pick(from, (List.rev, Fun.id), cs);
// if (dbg^) {
// P.log("--- Grouter.fill_swing");
// P.show("from", Dir.show(from));
// P.show("sw", Walk.Swing.show(sw));
// P.show("cs", Cells.show(cs));
// };
let (bot, top) = Walk.Swing.(bot(sw), top(sw));
switch (bot) {
| Space(nt) =>
Expand Down Expand Up @@ -195,10 +203,16 @@ let fill_swing = (cs: Cells.t, sw: Walk.Swing.t, ~from: Dir.t) => {
};

let fill_swings =
(~repair, ~from, cells: list(Cell.t), swings: list(Walk.Swing.t)) =>
(~repair, ~from, cells: list(Cell.t), swings: list(Walk.Swing.t)) => {
// if (dbg^) {
// P.log("--- Grouter.fill_swings");
// P.show("from", Dir.show(from));
// P.show("cells", Cells.show(Dir.pick(from, (List.rev, Fun.id), cells)));
// };
cells
|> Dir.pick(from, (List.rev, Fun.id))
|> (repair ? List.concat_map(degrout) : Fun.id)
// |> (dbg^ ? P.oshow("degrouted", Cells.show) : Fun.id)
|> Dir.pick(from, (List.rev, Fun.id))
|> Lists.split_bins(List.length(swings))
|> Oblig.Delta.minimize(~to_zero=!repair, c_bins =>
Expand All @@ -210,6 +224,7 @@ let fill_swings =
})
|> Options.for_all
);
};

let fill = (~repair, ~from, cs, (swings, stances): Walk.t) => {
open Options.Syntax;
Expand All @@ -223,5 +238,16 @@ let fill = (~repair, ~from, cs, (swings, stances): Walk.t) => {
// obligation delta. the given cells are expected to be oriented the same way as the
// given walks according to from.
let pick = (~repair=false, ~from: Dir.t, cs: list(Cell.t), ws: list(Walk.t)) => {
Oblig.Delta.minimize(~to_zero=!repair, fill(~repair, ~from, cs), ws);
// if (dbg^) {
// P.log("--- Grouter.pick");
// P.show("from", Dir.show(from));
// P.show("cs", Cells.show(cs));
// P.log("ws");
// ws |> List.iter(w => P.show("w", Walk.show(w)));
// };
Oblig.Delta.minimize(
~to_zero=!repair,
fill(~repair, ~from, cs),
ws,
);
};
39 changes: 27 additions & 12 deletions src/core/parser/Melder.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,22 @@ open Stds;

exception Bug__failed_to_push_space;

let debug = ref(true);
let dbg = ref(true);

// assumes w is already oriented toward side.
// used to complete zigg top when it takes precedence over pushed wald.
let complete_wald = (~side: Dir.t, ~fill=Cell.empty, w: Wald.t): Terr.t => {
let from = Dir.toggle(side);
let exited = Walker.exit(~from, Node(Wald.face(w).mtrl));
let baked = Grouter.pick(~repair=true, ~from, [fill], exited);
// exited |> Oblig.Delta.minimize(Baker.bake(~from, ~fill=Fill.unit(fill)));
switch (baked) {
| Some(baked) => Grouted.complete_wald(baked, w)
let grouted = Grouter.pick(~repair=true, ~from, [fill], exited);
switch (grouted) {
| Some(grouted) => Grouted.complete_wald(grouted, w)
| None =>
assert(!Cell.is_empty(fill));
print_endline("warning: dropping fill " ++ Cell.show(fill));
let baked =
Grouter.pick(~repair=true, ~from, [], exited)
|> Options.get_fail("bug: expected bake to succeed sans fill");
// walker bug if no exits
// let exited = List.hd(exited);
// let baked = Baker.bake_sans_fill(~from, exited);
|> Options.get_fail("bug: expected grouter to succeed sans fill");
Grouted.complete_wald(baked, w);
};
};
Expand All @@ -30,10 +26,25 @@ let complete_terr = (~onto: Dir.t, ~fill=Cell.empty, terr: Terr.t): Cell.t => {
let orient = Dir.pick(onto, (Meld.rev, Fun.id));
let exited = Walker.exit(~from=onto, Node(Terr.face(terr).mtrl));
let grouted = Grouter.pick(~repair=true, ~from=onto, [fill], exited);
// exited
// |> Oblig.Delta.minimize(Baker.bake(~from=onto, ~fill=Fill.unit(fill)));
// if (dbg^) {
// P.log("--- Melder.complete_terr");
// P.show("onto", Dir.show(onto));
// P.show("fill", Cell.show(fill));
// P.show("terr", Terr.show(terr));
// };
switch (grouted) {
| Some(grouted) => Cell.put(orient(Grouted.complete_terr(grouted, terr)))
| Some(grouted) =>
let m = Grouted.complete_terr(grouted, terr);
// if (dbg^) {
// P.log("--- Melder.complete_terr/grouted");
// P.show("grouted", Grouted.show(grouted));
// P.show("completed meld", Meld.show(m));
// P.show("oriented meld", Meld.show(orient(m)));
// Cell.dbg := true;
// P.show("oriented cell", Cell.show(Cell.put(orient(m))));
// Cell.dbg := false;
// };
Cell.put(orient(m));
| None =>
assert(!Cell.is_empty(fill));
print_endline("warning: dropping fill " ++ Cell.show(fill));
Expand All @@ -55,6 +66,10 @@ let complete_bounded =
let fill = complete_slope(~onto, ~fill, slope);
let fc_onto = bd_onto |> Bound.map(t => Terr.face(t).mtrl);
let fc_from = bd_from |> Bound.map(t => Terr.face(t).mtrl);
// if (dbg^) {
// P.log("--- Melder.complete_bounded");
// P.show("completed slope", Cell.show(fill));
// };
Walker.walk_eq(~from=onto, fc_onto, fc_from)
|> Grouter.pick(~repair=true, [fill], ~from=onto)
|> Option.map(grouted => snd(Chain.hd(grouted)))
Expand Down
29 changes: 16 additions & 13 deletions src/core/parser/Molder.re
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,27 @@ let complete_pending_ghosts = (~bounds, l: Stack.t, ~fill) => {
// returns None if input token is empty
let rec mold =
(stack: Stack.t, ~fill=Cell.empty, t: Token.Unmolded.t)
: option((Token.t, Grouted.t, Stack.t)) =>
: Result.t((Token.t, Grouted.t, Stack.t), Cell.t) =>
switch (
candidates(t)
|> Oblig.Delta.minimize(tok =>
Melder.push(tok, ~fill, stack, ~onto=L, ~repair=remold)
|> Option.map(((grouted, stack)) => (tok, grouted, stack))
)
) {
// pushed token was empty ghost connected via neq-relation
| Some((tok, grouted, _) as molded) =>
| Some((tok, grouted, _stack) as molded) =>
// remove empty ghost connected via neq-relation
// P.log("--- Molder.mold/success");
// P.show("tok", Token.show(tok));
// P.show("grouted", Grouted.show(grouted));
// P.show("stack", Stack.show(stack));
Mtrl.is_tile(tok.mtrl) && tok.text == "" && Grouted.is_neq(grouted)
? None : Some(molded)
? Error(Cell.mark_degrouted(fill, ~side=R)) : Ok(molded)
| None =>
let deferred = Token.Unmolded.defer(t);
Token.is_empty(deferred)
? None
: Some(
? Error(Cell.mark_degrouted(fill, ~side=R))
: Ok(
{
let (fill, slope) = Slope.Dn.unroll(fill);
let stack = Stack.cat(slope, stack);
Expand All @@ -102,19 +106,18 @@ let rec mold =
and remold =
(~fill, (l, r): Stack.Frame.t)
: Result.t((Slope.Dn.t, Cell.t), (Cell.t, Stack.Frame.t)) => {
// open Result.Syntax;
// P.log("--- remold");
// P.log("--- Molder.remold");
// P.show("fill", Cell.show(fill));
// P.show("(l, r)", Stack.Frame.show((l, r)));
let bounds = (l.bound, r.bound);
switch (r.slope) {
| [] =>
// P.log("--- remold/done");
// P.log("--- Molder.remold/done");
// P.show("l", Stack.show(l));
// P.show("fill", Cell.show(fill));
Ok((l.slope, fill))
| [hd, ...tl] =>
// P.log("--- remold/continue");
// P.log("--- Molder.remold/continue");
// P.show("hd", Terr.show(hd));
// insert any pending ghosts if next terr has newlines
let (l, fill) =
Expand All @@ -134,19 +137,19 @@ and remold =
})
|> Option.value(~default=Slope.Up.unroll(hd.cell));
switch (mold(l, ~fill, Token.unmold(hd_w))) {
| None =>
| Error(fill) =>
let (c, up) = unroll_tl_w_hd_cell();
let fill = fill |> Cell.pad(~r=c) |> Cell.mark_ends_dirty;
(l, r_tl) |> Stack.Frame.cat(([], up)) |> remold(~fill);
| Some((t, grouted, rest)) when t.mtrl == hd_w.mtrl =>
| Ok((t, grouted, rest)) when t.mtrl == hd_w.mtrl =>
// fast path for when hd_w retains original meld
let connected = Stack.connect(t, grouted, rest) |> Stack.extend(tl_w);
if (connected.bound == l.bound) {
remold(~fill=hd.cell, (connected, r_tl));
} else {
Error((hd.cell, (connected, r_tl)));
};
| Some((t, grouted, rest)) =>
| Ok((t, grouted, rest)) =>
let connected = Stack.connect(t, grouted, rest);
// check if connection changed the stack bound
if (connected.bound == l.bound) {
Expand Down
17 changes: 6 additions & 11 deletions src/core/structure/Cell.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ open Sexplib.Std;
open Ppx_yojson_conv_lib.Yojson_conv.Primitives;
open Stds;

let dbg = ref(false);

module Wald = {
[@deriving (sexp, yojson)]
type t('tok, 'cell) =
Expand Down Expand Up @@ -93,12 +95,6 @@ let rec pp = (out, {marks, meld}: t) => {
};
let show = Fmt.to_to_string(pp);

// module Wald = Meld.Wald;

// include Meld.Cell;
// [@deriving (show({with_path: false}), sexp, yojson)]
// type t = Meld.Cell.t(Meld.t);
// let empty = mk();
let is_empty = (~require_unmarked=false, c: t) =>
Option.is_none(c.meld) && (!require_unmarked || Marks.is_empty(c.marks));

Expand Down Expand Up @@ -138,6 +134,10 @@ let rec mark_degrouted = (~side: Dir.t, c: t) =>
{...c, meld: Some(M(l, w, r))};
}
};
let unmark_degrouted = (c: t) => {
let marks = {...c.marks, degrouted: Path.Map.empty};
{...c, marks};
};

let rec end_path = (~sans_padding=false, ~side: Dir.t, c: t) =>
switch (c.meld) {
Expand Down Expand Up @@ -261,11 +261,6 @@ module Space = {
};
let is_space = c => Option.is_some(get(c));

let unmark_degrouted = (c: t) => {
let marks = {...c.marks, degrouted: Path.Map.empty};
{...c, marks};
};

let mk = (cs: list(t), ts: list(Token.t)) =>
switch (cs, ts) {
| ([c], []) => c
Expand Down
3 changes: 2 additions & 1 deletion src/core/structure/marks/Marks.re
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ module Cell = {
cursor: Options.merge(~f=Path.Cursor.union, l.cursor, r.cursor),
obligs: Path.Map.union((_, t, _) => Some(t), l.obligs, r.obligs),
dirty: Path.Map.union((_, (), ()) => Some(), l.dirty, r.dirty),
degrouted: Path.Map.union((_, (), ()) => Some(), l.dirty, r.dirty),
degrouted:
Path.Map.union((_, (), ()) => Some(), l.degrouted, r.degrouted),
};
let union_all = List.fold_left(union, empty);

Expand Down

0 comments on commit 8d11f4d

Please sign in to comment.