-
Notifications
You must be signed in to change notification settings - Fork 62
Add dynamic mode to type projector #1858
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
base: dev
Are you sure you want to change the base?
Changes from 5 commits
a649815
1a40403
0216699
65d1851
3d15477
36d615c
85c2b4d
7909c30
88e8d76
1e5f9ca
db3a420
3961c95
853e029
be3aa4d
72e8101
a82b64c
b7c2577
0dd5810
173a5f4
6e4de9c
353b0e2
4c6658c
4d386e8
d8efcfd
9a8e9f6
9ab6e0c
ff67c1f
2ea4c26
930e42f
e1539bc
75666d3
2585f43
bbf9abf
10a2850
bd8fd25
d1e8ce3
c9d7cf2
b0b4285
b08f6a1
2e5350a
941e249
d6c64e2
e4a0034
06902fc
e08aa02
3c3eac3
bf5a0d2
a3cf6dc
2dbf027
df49af0
8e2a70a
5b1c7d3
5ff56a7
7b34b49
c76a164
995b9af
4ec5c6d
30f5593
698e981
64d6aa6
c270918
e4e1a7c
f1eea2e
222abd1
d5a0291
9b1af01
ff5523b
0f20fd1
c7d0ce2
52d2a2c
15a8df2
c2b73ee
1d1ff55
a324d73
7e12fdd
5c85788
e4b95b2
10c26b3
79cf327
c733274
aa26613
f6d3975
7f821c9
d8b16b2
4e6c1ae
ee65e54
94ab61a
14c1ed0
5c4fcb2
5d94433
9ab851d
457534b
e50c2c5
c37c8e0
23e38c3
2620112
4ae0e2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| open Virtual_dom.Vdom; | ||
| open Node; | ||
| open ProjectorBase; | ||
| open Language; | ||
|
|
||
| let self_ty = (info: option(Info.t)): option(Typ.t) => | ||
| switch (info) { | ||
| | Some(InfoExp({self, _})) => Self.typ_of_exp(self) | ||
| | Some(InfoPat({self, _})) => Self.typ_of_pat(self) | ||
| | _ => None | ||
| }; | ||
| module M: Projector = { | ||
| [@deriving (show({with_path: false}), sexp, yojson)] | ||
| type model = | ||
| | Expected | ||
| | Self; | ||
|
|
||
| [@deriving (show({with_path: false}), sexp, yojson)] | ||
| type action = | ||
| | ToggleDisplay; | ||
|
|
||
| let init = (any: Term.Any.t): option(model) => { | ||
| switch (any) { | ||
| | Exp(_) | ||
| | Pat(_) => Some(Expected) | ||
| | Any () => Some(Expected) /* Grout don't have sorts rn */ | ||
| | _ => None | ||
| }; | ||
| }; | ||
|
|
||
| let dynamics = true; | ||
| let focusable = Focusable.non; | ||
|
|
||
| let typ_view = (info: info, utility, view_seg: View.seg) => { | ||
| let dynamic_typ = | ||
| info.dynamics | ||
| |> Option.bind( | ||
| _, | ||
| (d: Dynamics.Info.t) => { | ||
| let statics = | ||
| Statics.mk(CoreSettings.on, Builtins.ctx_init(Some(Int))); | ||
| let type_of = (c: Dynamics.Probe.Closure.t) => { | ||
| IdTagged.rep_id(c.value) | ||
| |> Id.Map.find_opt(_, statics(c.value)) | ||
| |> Option.bind( | ||
| _, | ||
| fun | ||
| | InfoExp(e) => { | ||
| Some(e.ty); | ||
| } | ||
| | _ => None, | ||
| ); | ||
| }; | ||
| let types = List.map(type_of, d) |> Util.OptUtil.sequence; | ||
|
|
||
| Option.map(Typ.consistent_join(Ctx.empty), types); | ||
| }, | ||
| ) | ||
| |> Option.value(~default=Typ.fresh(Unknown(Internal))); | ||
| div( | ||
| ~attrs=[Attr.classes(["dyntype-cell"])], | ||
| [Typ(dynamic_typ) |> utility.term_to_seg |> view_seg(Sort.Typ)], | ||
| ); | ||
| }; | ||
|
|
||
| let update = (model, _, a: action) => | ||
| switch (a, model) { | ||
| | (ToggleDisplay, Expected) => Self | ||
| | (ToggleDisplay, Self) => Expected | ||
| }; | ||
|
|
||
| let syntax_str = (info: info) => { | ||
| let max_len = 30; | ||
| let seg = Segment.unparenthesize(info.syntax); | ||
| let str = info.utility.seg_to_string(seg); | ||
| let str = Re.Str.global_replace(Re.Str.regexp("\n"), " ", str); | ||
| String.length(str) > max_len | ||
| ? String.sub(str, 0, max_len) ++ "..." : str; | ||
| }; | ||
|
|
||
| let placeholder = (_m, info) => | ||
| ProjectorCore.Shape.inline(3 + String.length(syntax_str(info))); | ||
|
|
||
| let syntax_view = (info: info) => info |> syntax_str |> text; | ||
|
|
||
| let icon = div(~attrs=[Attr.classes(["icon"])], []); | ||
|
|
||
| let view = | ||
| ( | ||
| _: model, | ||
| info: info, | ||
| ~local: action => Ui_effect.t(unit), | ||
| ~parent as _, | ||
| ~view_seg, | ||
| ) => | ||
| View.{ | ||
| inline: | ||
| div( | ||
| ~attrs=[ | ||
| Attr.classes(["main"]), | ||
| Attr.on_double_click(_ => local(ToggleDisplay)), | ||
| ], | ||
| [syntax_view(info), icon], | ||
| ), | ||
| offside: | ||
| Some( | ||
| div( | ||
| ~attrs=[Attr.classes(["offside"])], | ||
| [typ_view(info, info.utility, view_seg)], | ||
| ), | ||
| ), | ||
| overlay: None, | ||
| }; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ type cls = | |||||
| | MultiHole | ||||||
| | SynSwitch | ||||||
| | Internal | ||||||
| | Inconsistent | ||||||
| | Arrow | ||||||
| | Prod | ||||||
| | TupLabel | ||||||
|
|
@@ -81,6 +82,7 @@ let cls_of_term: Grammar.typ_term('a) => cls = | |||||
| | Unknown(Hole(MultiHole(_))) => MultiHole | ||||||
| | Unknown(SynSwitch) => SynSwitch | ||||||
| | Unknown(Internal) => Internal | ||||||
| | Unknown(Inconsistent) => Inconsistent | ||||||
| | Atom(c) => Atom(c) | ||||||
| | List(_) => List | ||||||
| | Arrow(_) => Arrow | ||||||
|
|
@@ -99,6 +101,7 @@ let show_cls: cls => string = | |||||
| | Invalid => "Invalid type" | ||||||
| | MultiHole => "Broken type" | ||||||
| | EmptyHole => "Type hole" | ||||||
| | Inconsistent => "Join of Inconsistent types" | ||||||
| | SynSwitch => "Synthetic type" | ||||||
| | Internal => "Internal type" | ||||||
| | Atom(_) => "Base type" | ||||||
|
|
@@ -224,6 +227,8 @@ let join_type_provenance = | |||||
| | (Internal, SynSwitch) => SynSwitch | ||||||
| | (Internal | Hole(_), _) | ||||||
| | (_, Hole(_)) => Internal | ||||||
| | (Inconsistent, _) | ||||||
| | (_, Inconsistent) => Inconsistent | ||||||
| | (SynSwitch, SynSwitch) => SynSwitch | ||||||
| }; | ||||||
|
|
||||||
|
|
@@ -430,13 +435,23 @@ let equal = (t1: t, t2: t): bool => fast_equal(t1, t2); | |||||
| resolve parameter specifies whether, in the case of a type | ||||||
| variable and a succesful join, to return the resolved join type, | ||||||
| or to return the (first) type variable for readability */ | ||||||
| let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => { | ||||||
| let join' = join(~resolve, ctx); | ||||||
| let rec join = | ||||||
| ( | ||||||
| ~inconsistent: option(t)=?, | ||||||
| ~resolve=false, | ||||||
| ctx: Ctx.t, | ||||||
| ty1: t, | ||||||
| ty2: t, | ||||||
| ) | ||||||
| : option(t) => { | ||||||
| let join' = join(~inconsistent?, ~resolve, ctx); | ||||||
| switch (term_of(ty1), term_of(ty2)) { | ||||||
| | (_, Parens(ty2)) => join'(ty1, ty2) | ||||||
| | (Parens(ty1), _) => join'(ty1, ty2) | ||||||
| | (Unknown(p1), Unknown(p2)) => | ||||||
| Some(Unknown(join_type_provenance(p1, p2)) |> temp) | ||||||
| | (Unknown(Inconsistent), _) => Some(ty1) | ||||||
| | (_, Unknown(Inconsistent)) => Some(ty2) | ||||||
7h3kk1d marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| | (Unknown(_), _) => Some(ty2) | ||||||
| | (_, Unknown(_)) => Some(ty1) | ||||||
| | (Var(n1), Var(n2)) => | ||||||
|
|
@@ -466,7 +481,7 @@ let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => { | |||||
| }; | ||||||
| let+ ty_body = join(~resolve, ctx, ty1', ty2); | ||||||
7h3kk1d marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| Rec(tp1, ty_body) |> temp; | ||||||
| | (Rec(_), _) => None | ||||||
| | (Rec(_), _) => inconsistent | ||||||
| | (Forall(x1, ty1), Forall(x2, ty2)) => | ||||||
| let ty1' = | ||||||
| switch (TPat.tyvar_of_utpat(x2)) { | ||||||
|
|
@@ -482,25 +497,25 @@ let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => { | |||||
| be exposed to the user. We preserve the variable name of the | ||||||
| second type to preserve synthesized type variable names, which | ||||||
| come from user annotations. */ | ||||||
| | (Forall(_), _) => None | ||||||
| | (Forall(_), _) => inconsistent | ||||||
| | (Atom(c1), Atom(c2)) when c1 == c2 => Some(ty1) | ||||||
| | (Atom(_), _) => None | ||||||
| | (Atom(_), _) => inconsistent | ||||||
| | (Label(_), Label("")) => Some(ty1) | ||||||
| | (Label(""), Label(_)) => Some(ty2) | ||||||
| | (Label(name1), Label(name2)) | ||||||
| when LabeledTuple.match_labels(name1, name2) => | ||||||
| Some(ty1) | ||||||
| | (Label(_), _) => None | ||||||
| | (Label(_), _) => inconsistent | ||||||
| | (Arrow(ty1, ty2), Arrow(ty1', ty2')) => | ||||||
| let* ty1 = join'(ty1, ty1'); | ||||||
| let+ ty2 = join'(ty2, ty2'); | ||||||
| Arrow(ty1, ty2) |> temp; | ||||||
| | (Arrow(_), _) => None | ||||||
| | (Arrow(_), _) => inconsistent | ||||||
| | (TupLabel(lab1, ty1'), TupLabel(lab2, ty2')) => | ||||||
| let* lab = join'(lab1, lab2); | ||||||
| let+ ty = join'(ty1', ty2'); | ||||||
| TupLabel(lab, ty) |> temp; | ||||||
| | (TupLabel(_), _) => None | ||||||
| | (TupLabel(_), _) => inconsistent | ||||||
| | (Prod(tys1), Prod(tys2)) => | ||||||
| if (List.length(tys1) != List.length(tys2)) { | ||||||
| None; | ||||||
|
|
@@ -509,15 +524,15 @@ let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => { | |||||
| let+ tys = OptUtil.sequence(tys); | ||||||
| Prod(tys) |> temp; | ||||||
| } | ||||||
| | (Prod(_), _) => None | ||||||
| | (Prod(_), _) => inconsistent | ||||||
| | (Sum(sm1), Sum(sm2)) => | ||||||
| let+ sm' = ConstructorMap.join(equal, join(~resolve, ctx), sm1, sm2); | ||||||
|
||||||
| let+ sm' = ConstructorMap.join(equal, join(~resolve, ctx), sm1, sm2); | |
| let+ sm' = ConstructorMap.join(equal, join(~inconsistent?, ~resolve, ctx), sm1, sm2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar error in comment: "Grout don't have sorts" should be "Grouts don't have sorts" (plural subject requires plural verb form or singular "Grout doesn't have").