Skip to content

Commit d678b52

Browse files
committed
Merge remote-tracking branch 'origin/dynamic_statics' into tables-all-revamp
2 parents f7572cd + d117fb2 commit d678b52

File tree

82 files changed

+2621
-628
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+2621
-628
lines changed

src/CLI/Print.re

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ let exp_to_segment_settings: ExpToSegment.Settings.t = {
1111
hide_fixpoints: false,
1212
show_filters: true,
1313
show_unknown_as_hole: true,
14+
raise_if_padding: false,
1415
};
1516

1617
let segmentize =

src/haz3lcore/derived/CachedStatics.re

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ type t = {
77
elaborated: Exp.t,
88
info_map: Statics.Map.t,
99
error_ids: list(Id.t),
10-
targets: Sample.targets /* Maps expr/pat IDs to capture specs for sampling */
10+
targets: Sample.targets, /* Maps expr/pat IDs to capture specs for sampling */
11+
dynamic_info_map: Statics.Map.t,
12+
dynamic_error_ids: list(Id.t),
1113
};
1214

1315
let empty: t = {
@@ -22,6 +24,8 @@ let empty: t = {
2224
info_map: Id.Map.empty,
2325
error_ids: [],
2426
targets: Sample.no_targets,
27+
dynamic_info_map: Id.Map.empty,
28+
dynamic_error_ids: [],
2529
};
2630

2731
let elaborate =
@@ -46,19 +50,59 @@ let all_probeable_ids = (info_map: Statics.Map.t): Id.Map.t(unit) =>
4650
Id.Map.empty,
4751
);
4852

53+
/* Collect IDs of expressions/patterns with partially unknown types.
54+
* Used for live_typing to automatically probe terms that need dynamic type feedback.
55+
* Note: We check the SELF (synthesized) type, not the fixed TY, because
56+
* an expression like `1 : ?` analyzed against String would have ty=String
57+
* but self=Unknown - we need dynamic feedback for the Unknown part. */
58+
let ids_with_unknown_types = (info_map: Statics.Map.t): Id.Map.t(unit) =>
59+
Id.Map.fold(
60+
(id, info, acc) =>
61+
switch (info) {
62+
| Info.InfoExp({self: Common(Just(ty)), _})
63+
when Typ.contains_unknown(ty) =>
64+
Id.Map.add(id, (), acc)
65+
| Info.InfoPat({self: Common(Just(ty)), _})
66+
when Typ.contains_unknown(ty) =>
67+
Id.Map.add(id, (), acc)
68+
| _ => acc
69+
},
70+
info_map,
71+
Id.Map.empty,
72+
);
73+
4974
/* Compute targets from probe_ids. For each ID, determine whether it's
5075
* an expression or pattern target, then look up the appropriate refs to capture.
5176
* When probe_all is enabled, we target everything in info_map that passes
52-
* should_probe, ignoring the passed probe_ids (which are a subset anyway). */
77+
* should_probe, ignoring the passed probe_ids (which are a subset anyway).
78+
* When live_typing is enabled, we also include expressions with unknown types. */
5379
let compute_targets =
5480
(
5581
~settings: CoreSettings.t,
5682
~info_map: Statics.Map.t,
5783
~probe_ids: Id.Map.t(unit),
5884
)
5985
: Sample.targets => {
86+
/* Start with explicit probe IDs */
87+
let base_ids = probe_ids;
88+
/* If probe_all is enabled, include all probeable expressions */
89+
let base_ids =
90+
settings.probe_all
91+
? Id.Map.union(
92+
(_, _, _) => Some(),
93+
base_ids,
94+
all_probeable_ids(info_map),
95+
)
96+
: base_ids;
97+
/* If live_typing is enabled, include expressions with unknown types */
6098
let effective_probe_ids =
61-
settings.probe_all ? all_probeable_ids(info_map) : probe_ids;
99+
settings.live_typing
100+
? Id.Map.union(
101+
(_, _, _) => Some(),
102+
base_ids,
103+
ids_with_unknown_types(info_map),
104+
)
105+
: base_ids;
62106
Id.Map.fold(
63107
(id, (), acc) => {
64108
let refs =
@@ -110,6 +154,8 @@ let init_from_term =
110154
info_map,
111155
error_ids,
112156
targets,
157+
dynamic_info_map: Statics.Map.empty,
158+
dynamic_error_ids: [],
113159
};
114160
};
115161

src/haz3lcore/pretty/ExpToSegment.re

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ module Settings = {
4444
hide_fixpoints: bool,
4545
show_filters: bool,
4646
show_unknown_as_hole: bool,
47+
raise_if_padding: bool,
4748
};
4849

4950
let of_core = (~inline, ~fold_fn_bodies=?, settings: CoreSettings.t) => {
@@ -61,6 +62,7 @@ module Settings = {
6162
hide_fixpoints: !settings.evaluation.show_fixpoints,
6263
show_filters: settings.evaluation.show_stepper_filters,
6364
show_unknown_as_hole: true,
65+
raise_if_padding: false,
6466
};
6567

6668
let editable = (~inline) => {
@@ -75,6 +77,7 @@ module Settings = {
7577
hide_fixpoints: false,
7678
show_filters: true,
7779
show_unknown_as_hole: true,
80+
raise_if_padding: false,
7881
};
7982
};
8083
};
@@ -969,9 +972,12 @@ let mk_form =
969972

970973
/* HACK[Matt]: Sometimes terms that should have multiple ids won't because
971974
evaluation only ever gives them one */
972-
let pad_ids = (n: int, ids: list(Id.t)): list(Id.t) => {
975+
let pad_ids = (~settings: Settings.t, n: int, ids: list(Id.t)): list(Id.t) => {
973976
let len = List.length(ids);
974977
if (len < n) {
978+
if (settings.raise_if_padding) {
979+
raise(Failure("Padding required but not enough ids provided."));
980+
};
975981
ids @ List.init(n - len, _ => Id.mk());
976982
} else {
977983
ListUtil.split_n(n, ids) |> fst;
@@ -1072,6 +1078,7 @@ let project_table_if = (should_project, pieces) =>
10721078
that the expression has no Closures or DynamicErrorHoles
10731079
*/
10741080
let rec exp_to_pretty = (~settings: Settings.t, exp: Exp.t): pretty => {
1081+
let pad_ids = pad_ids(~settings);
10751082
let go = (~inline=settings.inline) =>
10761083
exp_to_pretty(
10771084
~settings={
@@ -1624,6 +1631,7 @@ let rec exp_to_pretty = (~settings: Settings.t, exp: Exp.t): pretty => {
16241631
}
16251632
and pat_to_pretty = (~settings: Settings.t, pat: Pat.t): pretty => {
16261633
let go = pat_to_pretty(~settings: Settings.t);
1634+
let pad_ids = pad_ids(~settings);
16271635
let wrap = wrap_with_secondary(~secondary=settings.secondary);
16281636
/* Use settings-aware concatenation and form building */
16291637
let (@) = concat_segment(~secondary=settings.secondary);
@@ -1794,6 +1802,7 @@ and pat_to_pretty = (~settings: Settings.t, pat: Pat.t): pretty => {
17941802
}
17951803
and typ_to_pretty = (~settings: Settings.t, typ: Typ.t): pretty => {
17961804
let go = typ_to_pretty(~settings: Settings.t);
1805+
let pad_ids = pad_ids(~settings);
17971806
let wrap = wrap_with_secondary(~secondary=settings.secondary);
17981807
/* Use settings-aware concatenation and form building */
17991808
let (@) = concat_segment(~secondary=settings.secondary);
@@ -2037,6 +2046,7 @@ and typ_to_pretty = (~settings: Settings.t, typ: Typ.t): pretty => {
20372046
}
20382047
and tpat_to_pretty = (~settings: Settings.t, tpat: TPat.t): pretty => {
20392048
let wrap = wrap_with_secondary(~secondary=settings.secondary);
2049+
let pad_ids = pad_ids(~settings);
20402050
/* Use settings-aware concatenation and form building */
20412051
switch (tpat |> IdTagged.term_of) {
20422052
| Invalid(t) =>

src/haz3lcore/pretty/PadIds.re

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
open Language;
2+
3+
/* Number of IDs required for ExpToSegment compatibility per type constructor */
4+
let necessary_ids: Typ.t => int =
5+
ty => {
6+
switch (ty.term) {
7+
| Prod([]) => 1 /* Empty product (unit-like) */
8+
| Prod(tys) => List.length(tys) - 1 /* One ID per separator */
9+
| Sum(tys) => List.length(tys) + 1 /* Constructors + prefix */
10+
| _ => 1 /* Default for other type constructors */
11+
};
12+
};
13+
14+
/**
15+
* Pads type IDs to ensure ExpToSegment uses them instead of creating new ones,
16+
* preserving ID correspondence for styling. Test_PadIds property test that checks
17+
* ExpToSegment compatibility and padding equivalence.
18+
*/
19+
let pad_typ_ids = (ty: Typ.t): Typ.t => {
20+
Typ.map_term(
21+
~f_typ=
22+
(cont, ty) => {
23+
let current_ids = ty.annotation.ids;
24+
let needed_ids = necessary_ids(ty);
25+
let ids =
26+
current_ids
27+
@ List.init(needed_ids - List.length(current_ids), _ => Id.mk());
28+
cont({
29+
...ty,
30+
annotation: {
31+
ids,
32+
secondary: ty.annotation.secondary,
33+
},
34+
});
35+
},
36+
ty,
37+
);
38+
};

src/haz3lcore/projectors/ProjectorBase.re

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ module View = {
121121
(
122122
~single_line: bool=?,
123123
~background: bool=?,
124+
~is_dynamic: Id.t => bool=?,
124125
~text_only: bool=?,
125126
Sort.t,
126127
list(syntax)

src/haz3lcore/projectors/implementations/ProbeProj.re

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,23 @@ module SampleLength = {
245245
let set = (id: int, length: int): unit => Hashtbl.add(lengths, id, length);
246246
};
247247

248+
/* Remove opaque values like function literals */
249+
let rm_opaques: list(Sample.Env.entry) => list(Sample.Env.entry) =
250+
List.filter_map((en: Sample.Env.entry) =>
251+
switch (en.value) {
252+
| Opaque => None
253+
| Val(_) => Some(en)
254+
}
255+
);
256+
257+
let cur_ap = (info: info) =>
258+
switch (info.statics) {
259+
| Some(InfoExp({term: {term: Ap(_), _} as ap, _}))
260+
| Some(InfoExp({term: {term: TypAp(_), _} as ap, _})) =>
261+
Some(Exp.rep_id(ap))
262+
| _ => None
263+
};
264+
248265
/* Select samples to display, using stateful window offset.
249266
* This wraps Sample.Selection with WindowState for offset persistence.
250267
* Optionally takes pre-filtered samples to avoid redundant filtering. */

src/haz3lcore/projectors/implementations/TableRenderer.re

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,6 @@ let convert_column =
243243
),
244244
]),
245245
),
246-
None,
247-
None,
248246
),
249247
)
250248
)
@@ -269,8 +267,6 @@ let rename_column =
269267
tup_label(label(new_name), dot(var("r"), label(old_name))),
270268
]),
271269
),
272-
None,
273-
None,
274270
)
275271
)
276272
),
@@ -289,8 +285,6 @@ let add_column_after =
289285
var("r"),
290286
tuple([tup_label(label(new_column), empty_hole())]),
291287
),
292-
None,
293-
None,
294288
),
295289
)
296290
)
@@ -307,12 +301,7 @@ let group_by_column = (info: info, column: string): Base.segment => {
307301
var("group_on_key"),
308302
tuple([
309303
deferral(InAp),
310-
fn(
311-
Pat.var("row"),
312-
dot(var("row"), label(column)),
313-
None,
314-
None,
315-
),
304+
fn(Pat.var("row"), dot(var("row"), label(column))),
316305
]),
317306
)
318307
),
@@ -333,8 +322,6 @@ let filter_by_column = (op, info: info, column: string): Base.segment => {
333322
fn(
334323
Pat.var("row"),
335324
bin_op(op, dot(var("row"), label(column)), empty_hole()),
336-
None,
337-
None,
338325
),
339326
]),
340327
)
@@ -532,8 +519,6 @@ let sort_column_with_direction =
532519
dot(var("r2"), label(header)),
533520
]),
534521
),
535-
None,
536-
None,
537522
),
538523
deferral(InAp),
539524
]),

0 commit comments

Comments
 (0)