diff --git a/src/haz3lcore/zipper/Editor.re b/src/haz3lcore/zipper/Editor.re index b6b30f65bc..4840335ad9 100644 --- a/src/haz3lcore/zipper/Editor.re +++ b/src/haz3lcore/zipper/Editor.re @@ -238,4 +238,7 @@ let get_projector = (id: Id.t, ed: t) => Projector.Map.find(id, ed.state.zipper.projectors); let add_projector = (id: Id.t, p: Projector.t, ed: t) => - update_z(_ => Zipper.add_projector(id, p, ed.state.zipper), ed); + update_z( + z => {...z, projectors: Projector.Map.add(id, p, z.projectors)}, + ed, + ); diff --git a/src/haz3lcore/zipper/Projector.re b/src/haz3lcore/zipper/Projector.re index ed8475706f..eaac774a2e 100644 --- a/src/haz3lcore/zipper/Projector.re +++ b/src/haz3lcore/zipper/Projector.re @@ -174,7 +174,7 @@ let guy_of_rev = (id, t, (start, last)) => { last_id: Piece.id(start), }; let proj_info = (term_ranges, id: Id.t, t: t, acc: start_map) => { - print_endline("proj_info for id: " ++ Id.to_string(id)); + //print_endline("proj_info for id: " ++ Id.to_string(id)); switch (Id.Map.find_opt(id, term_ranges)) { | Some(range) => let guy = guy_of(id, t, range); @@ -185,7 +185,7 @@ let proj_info = (term_ranges, id: Id.t, t: t, acc: start_map) => { }; }; let proj_info_rev = (term_ranges, id: Id.t, t: t, acc: start_map) => { - print_endline("proj_info for id: " ++ Id.to_string(id)); + // print_endline("proj_info for id: " ++ Id.to_string(id)); switch (Id.Map.find_opt(id, term_ranges)) { | Some(range) => let guy = guy_of(id, t, range); diff --git a/src/haz3lcore/zipper/Zipper.re b/src/haz3lcore/zipper/Zipper.re index f229d4f454..39333be17a 100644 --- a/src/haz3lcore/zipper/Zipper.re +++ b/src/haz3lcore/zipper/Zipper.re @@ -30,16 +30,6 @@ type t = { projectors: Projector.Map.t, }; -let get_projectors = (z: t): Projector.Map.t => z.projectors; - -let get_projector = (id: Id.t, z: t): option(Projector.t) => - Projector.Map.find(id, z.projectors); - -let add_projector = (id: Id.t, p: Projector.t, z: t): t => { - ...z, - projectors: Projector.Map.add(id, p, z.projectors), -}; - let init: unit => t = () => { selection: Selection.mk([]), diff --git a/src/haz3lcore/zipper/action/Move.re b/src/haz3lcore/zipper/action/Move.re index 3b75437a8a..441df3a943 100644 --- a/src/haz3lcore/zipper/action/Move.re +++ b/src/haz3lcore/zipper/action/Move.re @@ -6,7 +6,7 @@ open Sexplib.Std; [@deriving (show({with_path: false}), sexp, yojson)] type movability = | CanEnter(int, int) - | SkipTo(Id.t) + | SkipTo(ProjectorAction.thing) | CanPass | CantEven; diff --git a/src/haz3lcore/zipper/action/ProjectorAction.re b/src/haz3lcore/zipper/action/ProjectorAction.re index 0736c7228d..599733b208 100644 --- a/src/haz3lcore/zipper/action/ProjectorAction.re +++ b/src/haz3lcore/zipper/action/ProjectorAction.re @@ -2,29 +2,53 @@ open Zipper; open Util; //open OptUtil.Syntax; -let get_id_before = (seg, ancestors, projectors) => +[@deriving (show({with_path: false}), sexp, yojson)] +type relation = + | Parent + | Sibling; + +[@deriving (show({with_path: false}), sexp, yojson)] +type thing = { + id: Id.t, + relation, +}; + +let get_id_before = (seg, ancestors, projectors): option(thing) => switch (Projector.split_seg(seg, projectors)) { - | Some(([_, ..._] as xs, _, _, _)) => Piece.id(ListUtil.last(xs)) + | Some(([_, ..._] as xs, _, _, _)) => + Some({id: Piece.id(ListUtil.last(xs)), relation: Sibling}) | Some(([], _, _, _)) => switch (Ancestors.parent(ancestors)) { | Some(a) => print_endline("prev_id: empty pre using parent"); - a.id; + print_endline("parent id: " ++ Id.show(a.id)); + Some({id: a.id, relation: Parent}); | None => print_endline("prev_id: empty pre no ancestor"); - Id.invalid; //TODO(andrew) + None; //TODO(andrew) //Id.invalid; } | None => print_endline("prev_id: None"); - Id.invalid; //TODO(andrew) + None; //TODO(andrew) //Id.invalid; }; -let get_id_after = (seg, projectors) => +let get_id_after = (seg, ancestors, projectors): option(thing) => switch (Projector.split_seg(seg, projectors)) { - | Some((_, _, [hd, ..._], _)) => Piece.id(hd) - | _ => + | Some((_, _, [hd, ..._], _)) => + Some({id: Piece.id(hd), relation: Sibling}) + | Some((_, _, [], _)) => + switch (Ancestors.parent(ancestors)) { + | Some(a) => + print_endline("next_id: empty pre using parent"); + print_endline("parent id: " ++ Id.show(a.id)); + Some({id: a.id, relation: Parent}); + | None => + print_endline("next_id: empty pre no ancestor"); + None; //TODO(andrew) //Id.invalid; + } + | None => print_endline("next_id: empty post"); - Id.invalid; //TODO(andrew) + None; //TODO(andrew) //Id.invalid; }; let neighbor_is = @@ -33,58 +57,64 @@ let neighbor_is = last_map: Projector.start_map, {relatives: {siblings, ancestors}, projectors, _}: t, ) - : (option(Id.t), option(Id.t)) => { + : (option(thing), option(thing)) => { let (l_nhbr, r_nhbr) = Siblings.neighbors(siblings); let seg = (siblings |> fst) @ (siblings |> snd); let l = switch (l_nhbr) { | Some(p) when Projector.Map.mem(Piece.id(p), last_map) => - Some(get_id_before(seg, ancestors, projectors)) + get_id_before(seg, ancestors, projectors) | _ => None }; let r = switch (r_nhbr) { | Some(p) when Projector.Map.mem(Piece.id(p), start_map) => - Some(get_id_after(seg, projectors)) + get_id_after(seg, ancestors, projectors) | _ => None }; (l, r); }; -let is_right_of = (id: Id.t, z) => +let id_right_of_z = (id: Id.t, z) => switch (z.relatives.siblings, z.relatives.ancestors) { | ((_, [r, ..._]), _) => Piece.id(r) == id | ((_, []), []) => true // end of program | ((_, []), _) => false }; -let is_left_of = (id: Id.t, z) => +let id_left_of_z = (id: Id.t, z) => switch (z.relatives.siblings, z.relatives.ancestors) { | (([_, ..._] as ls, _), _) => Piece.id(ListUtil.last(ls)) == id | (([], _), []) => true // beginning of program | (([], _), _) => false }; -let is_on = (d: Direction.t, id: Id.t) => +let id_on = (d: Direction.t, id: Id.t) => switch (d) { - | Left => is_left_of(id) - | Right => is_right_of(id) + | Left => id_left_of_z(id) + | Right => id_right_of_z(id) + }; + +let d2 = (relation, d) => + switch (relation) { + | Sibling => d + | Parent => Direction.toggle(d) }; -let skip_to = (d: Direction.t, id, z) => { +let skip_to = (d: Direction.t, {id, relation}, z) => { // print_endline("ProjectorAction.skip_to"); Zipper.do_until( Zipper.move(d), - is_on(d, id), + id_on(d2(relation, d), id), z, ); }; -let skip_select_to = (d: Direction.t, id, z) => { +let skip_select_to = (d: Direction.t, {id, relation}, z) => { // print_endline("ProjectorAction.skip_select_to"); Zipper.do_until( Zipper.select_caret(d), - is_on(d, id), + id_on(d2(relation, d), id), z, ); }; diff --git a/src/haz3lweb/view/Deco.re b/src/haz3lweb/view/Deco.re index 92fc01c3e3..86715ad6d8 100644 --- a/src/haz3lweb/view/Deco.re +++ b/src/haz3lweb/view/Deco.re @@ -68,9 +68,10 @@ module Deco = } ) { | _ => + print_endline("PROJECTOR CRASH: sel_of_piece"); //TODO(andrew): relax. this is the case when tiles are missing //measured info due to being hidden by a projector - [] + []; }; let start_shape = switch (Piece.nibs(p)) { @@ -350,7 +351,11 @@ module Deco = List.concat([ //[Node.div(~attr=Attr.id("caret"), [])], caret(zipper), - indication_deco(zipper), + try(indication_deco(zipper)) { + | _ => + print_endline("PROJECTOR CRASH: indication_deco"); + []; + }, selected_pieces(zipper), backpack(zipper), targets'(zipper.backpack, sel_seg),