Skip to content

replace strings with gadts in projector models #1615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/haz3lcore/pretty/ExpToSegment.re
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,10 @@ let fold_fun_if = (condition, f_name: string, pieces) =>
let str = FoldProj.sexp_of_t({text: f_name}) |> Sexplib.Sexp.to_string;
switch (MakeTerm.for_projection([syntax])) {
| None => failwith("ExpToSegment.fold_fun_if")
| Some(any) => [
ProjectorInit.init_or_noop_from_str(Fold, syntax, any, str),
| Some(_) => [
Base.Projector(
ProjectorCore.mk(Fold, syntax, V(Fold, {text: str})),
),
]
};
} else {
Expand Down
34 changes: 1 addition & 33 deletions src/haz3lcore/projectors/ProjectorBase.re
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ module type Projector = {
* need other state beyond the underlying syntax */
[@deriving (show({with_path: false}), sexp, yojson)]
type model;
let kind: ProjectorCore.Kind.gadt(model);
/* An internal action type to be used in actions which
* update the model. Use `unit` if the basic projector
* actions (type `action`) above suffice */
Expand Down Expand Up @@ -169,39 +170,6 @@ module type Projector = {
let update: (model, info, action) => model;
};

/* A cooked projector is the same as the base module
* signature except model & action are serialized so
* they may be used by the Editor without it having
* specialized knowledge of projector internals */
module type Cooked =
Projector with type model = string and type action = string;

module Cook = (C: Projector) : Cooked => {
[@deriving (show({with_path: false}), sexp, yojson)]
type model = string;
[@deriving (show({with_path: false}), sexp, yojson)]
type action = string;
let serialize_m = m => m |> C.sexp_of_model |> Sexplib.Sexp.to_string;
let deserialize_m = s => s |> Sexplib.Sexp.of_string |> C.model_of_sexp;
let serialize_a = a => a |> C.sexp_of_action |> Sexplib.Sexp.to_string;
let deserialize_a = s => s |> Sexplib.Sexp.of_string |> C.action_of_sexp;
let init = any => C.init(any) |> Option.map(serialize_m);
let focusable = C.focusable;
let dynamics = C.dynamics;
let view = (m, info, ~local, ~parent, ~view_seg) =>
C.view(
deserialize_m(m),
info,
~local=a => local(serialize_a(a)),
~parent,
~view_seg,
);
let placeholder = m =>
m |> Sexplib.Sexp.of_string |> C.model_of_sexp |> C.placeholder;
let update = (m, i, a) =>
C.update(m |> deserialize_m, i, a |> deserialize_a) |> serialize_m;
};

/* Projectors currently are all convex */
let shapes = (_: ProjectorCore.t(syntax)): Nibs.shapes =>
Nib.Shape.(Convex, Convex);
125 changes: 124 additions & 1 deletion src/haz3lcore/projectors/ProjectorCore.re
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,60 @@
| Card
| TextArea;

[@deriving (show({with_path: false}), sexp, yojson)]
type type_model =
| Expected
| Self;

Check warning on line 33 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L31-L33

Added lines #L31 - L33 were not covered by tests

[@deriving (show({with_path: false}), sexp, yojson)]
type card_mode =
| Show
| Choose(int)
| Flipped;

Check warning on line 39 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L36-L39

Added lines #L36 - L39 were not covered by tests

[@deriving (show({with_path: false}), sexp, yojson)]
type fold_model = {
[@default "⋱"]
text: string,
};

Check warning on line 45 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L44-L45

Added lines #L44 - L45 were not covered by tests

type gadt('a) =
| Fold: gadt(fold_model)
| Info: gadt(type_model)
| Probe: gadt(unit)
| Checkbox: gadt(unit)
| Slider: gadt(unit)
| SliderF: gadt(unit)
| Card: gadt(card_mode)
| TextArea: gadt(unit);

let of_gadt = (type a, kind: gadt(a)): t =>
switch (kind) {
| Fold => Fold
| Info => Info
| Probe => Probe
| Checkbox => Checkbox
| Slider => Slider
| SliderF => SliderF
| Card => Card
| TextArea => TextArea

Check warning on line 66 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L58-L66

Added lines #L58 - L66 were not covered by tests
};

type w =
| W(gadt('a)): w;

let (let.gadt) = (type b, kind: t, f: w => b) =>
switch (kind) {
| Fold => f(W(Fold))
| Info => f(W(Info))
| Probe => f(W(Probe))
| Checkbox => f(W(Checkbox))
| Slider => f(W(Slider))
| SliderF => f(W(SliderF))
| Card => f(W(Card))
| TextArea => f(W(TextArea))

Check warning on line 81 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L73-L81

Added lines #L73 - L81 were not covered by tests
};

let livelit_projectors: list(t) = [
Checkbox,
Slider,
Expand Down Expand Up @@ -69,13 +123,82 @@
};
};

type model =
| V(Kind.gadt('a), 'a): model;

let pp_model = (f, model) =>
Format.fprintf(

Check warning on line 130 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L130

Added line #L130 was not covered by tests
f,
switch (model) {
| V(Fold, _) => "Fold"
| V(Info, _) => "Info"
| V(Probe, _) => "Probe"
| V(Checkbox, _) => "Checkbox"
| V(Slider, _) => "Slider"
| V(SliderF, _) => "SliderF"
| V(Card, _) => "Card"
| V(TextArea, _) => "TextArea"

Check warning on line 140 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L133-L140

Added lines #L133 - L140 were not covered by tests
},
);

let model_of_sexp = (sexp: Sexplib.Sexp.t): model =>
// take s-expressions of the form ("fold", m), deserialize m, and turn it into V(Fold, m)
switch (sexp) {
| List([Atom("fold"), m]) => V(Fold, m |> Kind.fold_model_of_sexp)
| List([Atom("info"), m]) => V(Info, m |> Kind.type_model_of_sexp)
| List([Atom("probe"), _]) => V(Probe, ())
| List([Atom("checkbox"), _]) => V(Checkbox, ())
| List([Atom("slider"), _]) => V(Slider, ())
| List([Atom("sliderf"), _]) => V(SliderF, ())
| List([Atom("card"), m]) => V(Card, m |> Kind.card_mode_of_sexp)
| List([Atom("text"), _]) => V(TextArea, ())
| _ => failwith("Unknown projector kind")

Check warning on line 155 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L146-L155

Added lines #L146 - L155 were not covered by tests
};

let sexp_of_model = (model: model): Sexplib.Sexp.t =>
switch (model) {
| V(Fold, m) => List([Atom("fold"), m |> Kind.sexp_of_fold_model])
| V(Info, m) => List([Atom("info"), m |> Kind.sexp_of_type_model])
| V(Probe, _) => List([Atom("probe"), () |> sexp_of_unit])
| V(Checkbox, _) => List([Atom("checkbox"), () |> sexp_of_unit])
| V(Slider, _) => List([Atom("slider"), () |> sexp_of_unit])
| V(SliderF, _) => List([Atom("sliderf"), () |> sexp_of_unit])
| V(Card, m) => List([Atom("card"), m |> Kind.sexp_of_card_mode])
| V(TextArea, _) => List([Atom("text"), () |> sexp_of_unit])

Check warning on line 167 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L159-L167

Added lines #L159 - L167 were not covered by tests
};

let model_of_yojson = (yojson: Yojson.Safe.t): model =>
switch (yojson) {
| `List([`String("fold"), m]) => V(Fold, m |> Kind.fold_model_of_yojson)
| `List([`String("info"), m]) => V(Info, m |> Kind.type_model_of_yojson)
| `List([`String("probe"), _]) => V(Probe, ())
| `List([`String("checkbox"), _]) => V(Checkbox, ())
| `List([`String("slider"), _]) => V(Slider, ())
| `List([`String("sliderf"), _]) => V(SliderF, ())
| `List([`String("card"), m]) => V(Card, m |> Kind.card_mode_of_yojson)
| `List([`String("text"), _]) => V(TextArea, ())
| _ => failwith("Unknown projector kind")

Check warning on line 180 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L171-L180

Added lines #L171 - L180 were not covered by tests
};

let yojson_of_model = (model: model): Yojson.Safe.t =>
switch (model) {
| V(Fold, m) => `List([`String("fold"), m |> Kind.yojson_of_fold_model])
| V(Info, m) => `List([`String("info"), m |> Kind.yojson_of_type_model])
| V(Probe, _) => `List([`String("probe"), () |> yojson_of_unit])
| V(Checkbox, _) => `List([`String("checkbox"), () |> yojson_of_unit])
| V(Slider, _) => `List([`String("slider"), () |> yojson_of_unit])
| V(SliderF, _) => `List([`String("sliderf"), () |> yojson_of_unit])
| V(Card, m) => `List([`String("card"), m |> Kind.yojson_of_card_mode])
| V(TextArea, _) => `List([`String("text"), () |> yojson_of_unit])

Check warning on line 192 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L184-L192

Added lines #L184 - L192 were not covered by tests
};

/* Projectors in syntax */
[@deriving (show({with_path: false}), sexp, yojson)]
type t('syntax) = {
id: Id.t,
kind: Kind.t,
syntax: 'syntax,
model: string,
model,

Check warning on line 201 in src/haz3lcore/projectors/ProjectorCore.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorCore.re#L201

Added line #L201 was not covered by tests
};

let mk = (kind, syntax, model) => {
Expand Down
5 changes: 3 additions & 2 deletions src/haz3lcore/projectors/ProjectorInfo.re
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@
let from_semantics =
(statics: Statics.Map.t, dynamics: Dynamics.Map.t, p: Base.projector)
: ProjectorCore.Shape.t => {
let (module P) = ProjectorInit.to_module(p.kind);
P.placeholder(p.model, mk_info(p, ~statics, ~dynamics));
let V(kind, model) = p.model;
let (module P) = ProjectorInit.to_module(kind);
P.placeholder(model, mk_info(p, ~statics, ~dynamics));

Check warning on line 44 in src/haz3lcore/projectors/ProjectorInfo.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorInfo.re#L44

Added line #L44 was not covered by tests
};

let mk =
Expand Down
44 changes: 18 additions & 26 deletions src/haz3lcore/projectors/ProjectorInit.re
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,32 @@
* it can be instantiated. The first-class module created by
* this function must be reified whenever projector methods
* are to be called; see `shape` below for an example */
let to_module = (kind: ProjectorCore.Kind.t): (module Cooked) =>
let to_module =
(type a, kind: ProjectorCore.Kind.gadt(a))
: (module Projector with type model = a) =>
switch (kind) {
| Fold => (module Cook(FoldProj.M))
| Info => (module Cook(TypeProj.M))
| Probe => (module Cook(ProbeProj.M))
| Slider => (module Cook(SliderProj.M))
| SliderF => (module Cook(SliderFProj.M))
| Checkbox => (module Cook(CheckboxProj.M))
| TextArea => (module Cook(TextAreaProj.M))
| Card => (module Cook(CardProj.M))
| Fold => (module FoldProj.M)
| Info => (module TypeProj.M)
| Probe => (module ProbeProj.M)
| Slider => (module SliderProj.M)
| SliderF => (module SliderFProj.M)
| Checkbox => (module CheckboxProj.M)
| TextArea => (module TextAreaProj.M)
| Card => (module CardProj.M)

Check warning on line 18 in src/haz3lcore/projectors/ProjectorInit.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorInit.re#L12-L18

Added lines #L12 - L18 were not covered by tests
};

let init =
(kind: ProjectorCore.Kind.t, syntax: syntax, any: Term.Any.t)
: option(syntax) => {
let (module P) = to_module(kind);
open ProjectorCore.Kind;
let.gadt W(kind_gadt) = kind;
let (module P) = to_module(kind_gadt);

Check warning on line 26 in src/haz3lcore/projectors/ProjectorInit.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorInit.re#L26

Added line #L26 was not covered by tests
switch (P.init(any)) {
| None => None
| Some(model) => Some(Projector(ProjectorCore.mk(kind, syntax, model)))
| Some(model) =>

Check warning on line 29 in src/haz3lcore/projectors/ProjectorInit.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorInit.re#L29

Added line #L29 was not covered by tests
Some(
Base.Projector(ProjectorCore.mk(kind, syntax, V(kind_gadt, model))),

Check warning on line 31 in src/haz3lcore/projectors/ProjectorInit.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/ProjectorInit.re#L31

Added line #L31 was not covered by tests
)
};
};

Expand All @@ -32,18 +39,3 @@
| Some(pr) => pr
| None => syntax
};

let init_or_noop_from_str =
(
kind: ProjectorCore.Kind.t,
syntax: syntax,
any: Term.Any.t,
model_str: string,
)
: syntax => {
let (module P) = to_module(kind);
switch (P.init(any)) {
| None => syntax
| Some(_) => Projector(ProjectorCore.mk(kind, syntax, model_str))
};
};
4 changes: 3 additions & 1 deletion src/haz3lcore/projectors/ProjectorPerform.re
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ let go =
),
)
| Focus(id, kind, d) =>
open ProjectorCore.Kind;
let.gadt W(kind) = kind;
switch (d) {
| None =>
/* Focus by mouse click */
Expand All @@ -171,7 +173,7 @@ let go =
| None => ()
};
Ok(z);
}
};
| Escape(id, d) => Ok(jump_to_side_of_id(d, z, id))
};
};
22 changes: 11 additions & 11 deletions src/haz3lcore/projectors/implementations/CardProj.re
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@
open ProjectorBase;

[@deriving (show({with_path: false}), sexp, yojson)]
type mode =
| Show
| Choose(int)
| Flipped;
type mode = ProjectorCore.Kind.card_mode;

Check warning on line 6 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L6

Added line #L6 was not covered by tests

[@deriving (show({with_path: false}), sexp, yojson)]
type model = {mode};
type model = mode;

Check warning on line 9 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L9

Added line #L9 was not covered by tests
[@deriving (show({with_path: false}), sexp, yojson)]
type action =
| SetMode(mode);

let model_of_sexp = (sexp: Sexplib.Sexp.t): model =>
switch (model_of_sexp(sexp)) {
| exception _ => {mode: Show}
| exception _ => Show

Check warning on line 16 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L16

Added line #L16 was not covered by tests
| m => m
};

Expand Down Expand Up @@ -454,6 +451,8 @@
);
};

open ProjectorCore.Kind;

module Singleton = {
let view =
(
Expand Down Expand Up @@ -605,16 +604,17 @@
[@deriving (show({with_path: false}), sexp, yojson)]
type a = action;

module M: Projector = {
module M: Projector with type model = m = {
[@deriving (show({with_path: false}), sexp, yojson)]
type model = m;
let kind = ProjectorCore.Kind.Card;
[@deriving (show({with_path: false}), sexp, yojson)]
type action = a;
let focusable = Focusable.non;
let dynamics = false;

let init = (info: TermBase.Any.t): option(model) =>
SyntaxTerm.get_opt(info) != None ? Some({mode: Show}) : None;
SyntaxTerm.get_opt(info) != None ? Some(Show) : None;

Check warning on line 617 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L617

Added line #L617 was not covered by tests

let placeholder = (_, info): ProjectorCore.Shape.t => {
horizontal: SyntaxTerm.width_of_any(info),
Expand All @@ -623,7 +623,7 @@

let update = (_model, _, action) =>
switch (action) {
| SetMode(mode) => {mode: mode}
| SetMode(mode) => mode

Check warning on line 626 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L626

Added line #L626 was not covered by tests
};

let view =
Expand All @@ -638,9 +638,9 @@
inline:
switch (SyntaxTerm.get(info)) {
| (sort, Card(card)) =>
Singleton.view(info, model.mode, parent, local, to_sort(sort), card)
Singleton.view(info, model, parent, local, to_sort(sort), card)

Check warning on line 641 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L641

Added line #L641 was not covered by tests
| (sort, Hand(hand)) =>
Hand.view(info, model.mode, parent, local, to_sort(sort), hand)
Hand.view(info, model, parent, local, to_sort(sort), hand)

Check warning on line 643 in src/haz3lcore/projectors/implementations/CardProj.re

View check run for this annotation

Codecov / codecov/patch

src/haz3lcore/projectors/implementations/CardProj.re#L643

Added line #L643 was not covered by tests
},
offside: None,
overlay: None,
Expand Down
3 changes: 2 additions & 1 deletion src/haz3lcore/projectors/implementations/CheckboxProj.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ open Util;
open ProjectorBase;
open Virtual_dom.Vdom;

module M: Projector = {
module M: Projector with type model = unit = {
[@deriving (show({with_path: false}), sexp, yojson)]
type model = unit;
let kind = ProjectorCore.Kind.Checkbox;
[@deriving (show({with_path: false}), sexp, yojson)]
type action = unit;

Expand Down
Loading