Skip to content

Commit

Permalink
principled editor meta for projectors
Browse files Browse the repository at this point in the history
  • Loading branch information
disconcision committed May 18, 2024
1 parent 1c2e452 commit 2e1299f
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 209 deletions.
25 changes: 4 additions & 21 deletions src/haz3lcore/Measured.re
Original file line number Diff line number Diff line change
Expand Up @@ -199,35 +199,18 @@ let find_t = (t: Tile.t, map): measurement => {
let last = ListUtil.assoc_err(Tile.r_shard(t), shards, "find_t");
(first, last);
}) {
| _ =>
print_endline("FuCkNASTY hackzz");
let s = shards |> List.hd;
(s |> snd, s |> snd);
| _ => failwith("find_t: inconsistent shard infor between tile and map")
// let s = shards |> List.hd;
// (s |> snd, s |> snd);
};
{origin: first.origin, last: last.last};
};
// let find_a = ({shards: (l, r), _} as a: Ancestor.t, map) =>
// List.assoc(l @ r, Id.Map.find(a.id, map.tiles));
let find_p = (~msg="", p: Piece.t, map): measurement =>
try(
p
|> Piece.get(
w => find_w(w, map),
g =>
//TODO(andrew): find better way to reconcile this
try(find_g(g, map)) {
| _ =>
find_t(
{
id: g.id,
label: [String.make(2, ' ')],
mold: Mold.mk_op(Any, []),
shards: [0],
children: [],
},
map,
)
},
g => find_g(g, map),
t => find_t(t, map),
)
) {
Expand Down
138 changes: 61 additions & 77 deletions src/haz3lcore/zipper/Editor.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,61 @@ open Sexplib.Std;
open Util;

module Meta = {
type t = {
col_target: int,
touched: Touched.t,
segment_real: Segment.t,
measured_real: Measured.t,
z_projected: Zipper.t,
segment_projected: Segment.t,
measured_projected: Measured.t,
term_projected: Term.UExp.t,
/* Derived data for projected zipper */
type projected = {
z: Zipper.t,
segment: Segment.t,
measured: Measured.t,
term: Term.UExp.t,
term_ranges: TermRanges.t,
terms: TermMap.t,
tiles: TileMap.t,
holes: list(Grout.t),
buffer_ids: list(Id.t),
};

type t = {
col_target: int,
touched: Touched.t,
projected,
};

let init_projected = (z_projected: Zipper.t): projected => {
let segment = Zipper.unselect_and_zip(z_projected);
let (term, terms) = MakeTerm.go(segment);
{
z: z_projected,
segment,
term,
terms,
term_ranges: TermRanges.mk(segment),
tiles: TileMap.mk(segment),
holes: Segment.holes(segment),
measured: Measured.of_segment(segment),
buffer_ids: Selection.buffer_ids(z_projected.selection),
};
};

let init = (z: Zipper.t) => {
let segment_real = Zipper.unselect_and_zip(z);
let measured_real = Measured.of_segment(segment_real);
let is_proj = !Id.Map.is_empty(z.projectors);
let z_projected = is_proj ? ProjectorAction.of_zipper(z) : z;
let segment_projected =
is_proj ? Zipper.unselect_and_zip(z_projected) : segment_real;
let (term_projected, terms) = MakeTerm.go(segment_projected);
{
col_target: 0,
touched: Touched.empty,
z_projected,
segment_real,
measured_real,
measured_projected: Measured.of_segment(segment_projected),
segment_projected,
term_ranges: TermRanges.mk(segment_projected),
tiles: TileMap.mk(segment_projected),
term_projected,
terms,
holes: Segment.holes(segment_projected),
buffer_ids: Selection.buffer_ids(z.selection),
projected: z |> ProjectorAction.of_zipper |> init_projected,
};
};

module type S = {
let touched: Touched.t;
let measured_projected: Measured.t;
let measured: Measured.t;
let term_ranges: TermRanges.t;
let col_target: int;
};
let module_of_t = (m: t): (module S) =>
(module
{
let touched = m.touched;
let measured_projected = m.measured_projected;
let term_ranges = m.term_ranges;
let measured = m.projected.measured;
let term_ranges = m.projected.term_ranges;
let col_target = m.col_target;
});

Expand All @@ -64,58 +66,40 @@ module Meta = {
let yojson_of_t = _ => failwith("Editor.Meta.yojson_of_t");
let t_of_yojson = _ => failwith("Editor.Meta.t_of_yojson");

let next_projected = (z, ~touched, ~old) => {
let segment = Zipper.unselect_and_zip(z);
let (term, terms) = MakeTerm.go(segment);
let measured = Measured.of_segment(~touched, ~old, segment);
{
z,
segment,
term,
terms,
measured,
term_ranges: TermRanges.mk(segment),
tiles: TileMap.mk(segment),
holes: Segment.holes(segment),
buffer_ids: Selection.buffer_ids(z.selection),
};
};

let next =
(~effects: list(Effect.t)=[], a: Action.t, z: Zipper.t, meta: t): t => {
let {touched, measured_real, measured_projected, col_target, _} = meta;
let touched = Touched.update(Time.tick(), effects, touched);
//TODO(andrew): gate appropriate things on edit
let is_edit = Action.is_edit(a);
let is_proj = !Id.Map.is_empty(z.projectors);
let segment_real =
is_edit ? Zipper.unselect_and_zip(z) : meta.segment_real;
let measured_real =
Measured.of_segment(~touched, ~old=measured_real, segment_real);
let z_projected = is_proj ? ProjectorAction.of_zipper(z) : z;
let segment_projected =
is_proj
? Projector.of_segment(z.projectors, segment_real) : segment_real;
let measured_projected =
is_proj
? Measured.of_segment(
~touched,
~old=measured_projected,
segment_projected,
)
: measured_real;
let term_ranges =
is_edit ? TermRanges.mk(segment_projected) : meta.term_ranges;
let touched = Touched.update(Time.tick(), effects, meta.touched);
let col_target =
switch (a) {
| Move(Local(Up | Down))
| Select(Resize(Local(Up | Down))) => col_target
| Select(Resize(Local(Up | Down))) => meta.col_target
| _ => Zipper.caret_point(meta.projected.measured, meta.projected.z).col
};
let z_projected = ProjectorAction.of_zipper(z);
let projected =
switch (Action.is_edit(a)) {
| false => {...meta.projected, z: z_projected}
| _ =>
print_endline("Editor.next.caret_point");
Zipper.caret_point(measured_projected, z_projected).col;
next_projected(z_projected, ~touched, ~old=meta.projected.measured)
};
let (term_projected, terms) =
is_edit
? MakeTerm.go(segment_projected) : (meta.term_projected, meta.terms);
{
col_target,
touched,
z_projected,
measured_real,
measured_projected,
segment_real,
segment_projected,
term_ranges,
tiles: is_edit ? TileMap.mk(segment_projected) : meta.tiles,
term_projected,
terms,
//NOTE(andrew): this is seg_project bc otherwise Code.of_hole crashes
holes: is_edit ? Segment.holes(segment_projected) : meta.holes,
buffer_ids: Selection.buffer_ids(z.selection),
};
{touched, col_target, projected};
};
};

Expand Down Expand Up @@ -240,10 +224,10 @@ let map_projectors = (f: (Id.t, Projector.t) => Projector.t, ed: t) =>
let get_projected_piece = (ed: t, id: Id.t): option(Piece.t) => {
/* Assumes for the moment that the projected thing is either
* a tile or a grout (not secondary or segment) */
switch (Id.Map.find_opt(id, ed.state.meta.tiles)) {
switch (Id.Map.find_opt(id, ed.state.meta.projected.tiles)) {
| Some(tile) => Some(Tile(tile))
| None =>
List.find_opt((g: Grout.t) => g.id == id, ed.state.meta.holes)
List.find_opt((g: Grout.t) => g.id == id, ed.state.meta.projected.holes)
|> Option.map(g => Piece.Grout(g))
};
};
52 changes: 13 additions & 39 deletions src/haz3lcore/zipper/Printer.re
Original file line number Diff line number Diff line change
Expand Up @@ -60,69 +60,43 @@ let to_rows =
};
};

let pretty_print = (~measured: Measured.t, z: Zipper.t): string =>
let pretty_print =
(~holes: option(string)=Some(""), ~measured: Measured.t, z: Zipper.t)
: string =>
to_rows(
~holes=None,
~holes,
~measured,
~caret=None,
~indent=" ",
~segment=seg_of_zip(z),
)
|> String.concat("\n");

let to_string_editor =
(~holes: option(string)=Some(""), editor: Editor.t): string =>
let zipper_to_string =
(~holes: option(string)=Some(""), z: Zipper.t): string =>
to_rows(
~holes,
~measured=editor.state.meta.measured_real,
~measured=Zipper.measured(z),
~caret=None,
~indent="",
~segment=seg_of_zip(editor.state.zipper),
~segment=seg_of_zip(z),
)
|> String.concat("\n");

let to_string_editor =
(~holes: option(string)=Some(""), editor: Editor.t): string =>
zipper_to_string(~holes, editor.state.zipper);

let to_string_selection = (editor: Editor.t): string =>
to_rows(
~measured=editor.state.meta.measured_real,
~measured=Zipper.measured(editor.state.zipper),
~caret=None,
~indent=" ",
~holes=None,
~segment=editor.state.zipper.selection.content,
)
|> String.concat("\n");

let to_log = (~measured: Measured.t, z: Zipper.t): t => {
code:
to_rows(
~holes=None,
~measured,
~caret=Some(Zipper.caret_point(measured, z)),
~indent=" ",
~segment=seg_of_zip(z),
),
selection: z.selection.content |> of_segment(~holes=None) |> lines_to_list,
backpack:
List.map(
(s: Selection.t) =>
s.content |> of_segment(~holes=None) |> lines_to_list,
z.backpack,
),
};

let to_log_flat = (~measured, z: Zipper.t): string => {
let {code, selection, backpack} = to_log(~measured, z);
Printf.sprintf(
"CODE:\n%s\nSELECTION:\n%s\n%s\n",
String.concat("\n", code),
String.concat("\n", selection),
backpack
|> List.mapi((i, b) =>
Printf.sprintf("BP(%d):\n %s\n", i, String.concat("\n", b))
)
|> String.concat(""),
);
};

let zipper_of_string =
(~zipper_init=Zipper.init(), str: string): option(Zipper.t) => {
let insert = (z: option(Zipper.t), c: string): option(Zipper.t) => {
Expand Down
47 changes: 23 additions & 24 deletions src/haz3lcore/zipper/Zipper.re
Original file line number Diff line number Diff line change
Expand Up @@ -317,30 +317,6 @@ let move = (d: Direction.t, z: t): option(t) =>
let select = (d: Direction.t, z: t): option(t) =>
d == z.selection.focus ? grow_selection(z) : shrink_selection(z);

// let id_on = (d: Direction.t, id: Id.t, z: t): bool =>
// switch (d) {
// | Left =>
// switch (z.relatives.siblings, z.relatives.ancestors) {
// | (([_, ..._] as ls, _), _) => Piece.id(ListUtil.last(ls)) == id
// | _ => false
// }
// | Right =>
// switch (z.relatives.siblings, z.relatives.ancestors) {
// | ((_, [r, ..._]), _) => Piece.id(r) == id
// | _ => false
// }
// };

/* Loop action until pred is satisfied */
// let rec do_until =
// (action: t => option(t), pred: t => bool, z: t): option(t) =>
// pred(z)
// ? Some(z)
// : {
// let* z = action(z);
// do_until(action, pred, z);
// };

let pick_up = (z: t): t => {
let (selected, z) = update_selection(Selection.empty, z);
let selection =
Expand Down Expand Up @@ -468,9 +444,32 @@ let caret_direction = (z: t): option(Direction.t) =>
}
};

let get_projector = (z: t, id: Id.t): option(Projector.t) =>
Projector.Map.find(id, z.projectors);

let measured = z => {
z |> unselect_and_zip |> Measured.of_segment;
};

let base_point = (measured: Measured.t, z: t): Measured.Point.t => {
switch (representative_piece(z)) {
| Some((p, d)) =>
/* NOTE(andrew): Below conversion necessary because sometimes
* we call this with measured based on projected zipper
* measurements but also z is the non-projected zipper.
* This should work okay since the core movement/selection
* actions in Zipper avoid cursor positions around pieces
* which would be absent in the projected zipper. The problem
* is the projected tile itself. Specifically because looking
* up measurements is not currently homogenous; it takes a
* piece, not an id. Piece-based lookups will fail if (say)
* a Grout becomes a Tile. Hence we convert pieces that
* would be projected to their placeholders before lookup */
let p =
switch (get_projector(z, Piece.id(p))) {
| Some(pr) => Projector.placeholder(pr, Piece.id(p))
| None => p
};
let seg = Piece.disassemble(p);
switch (d) {
| Left =>
Expand Down
Loading

0 comments on commit 2e1299f

Please sign in to comment.