Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
5ad0a15
Merge branch 'probemoar' into dataframe-projector
7h3kk1d Oct 2, 2025
704e9f4
Speculative refactor extracting table renderer
7h3kk1d Oct 2, 2025
adfd919
Attempt to render table for probes.
7h3kk1d Oct 3, 2025
571591b
Merge remote-tracking branch 'origin/probemoar' into table-projector-…
7h3kk1d Oct 22, 2025
ed5b9af
tables at least rendering
7h3kk1d Oct 22, 2025
b0cf6c9
Merge remote-tracking branch 'origin/dev' into table-projector-refractor
7h3kk1d Oct 22, 2025
c88cde2
reformat
7h3kk1d Oct 22, 2025
05bb739
I have broken projectors but made refractors work
7h3kk1d Oct 24, 2025
6b96eb3
Fix submenu action to track current column in table modal
7h3kk1d Oct 24, 2025
429bed6
Refactor value_view to use span for table badge
7h3kk1d Oct 24, 2025
26ea407
Removing table code from probe code
7h3kk1d Oct 27, 2025
15eeaee
comment out debug
7h3kk1d Oct 27, 2025
35c3f01
Adding RichProbe signature
7h3kk1d Oct 27, 2025
391a300
cleanup
7h3kk1d Oct 27, 2025
43c8f93
Temp commit
7h3kk1d Oct 27, 2025
a101ce4
calculatin
7h3kk1d Oct 27, 2025
47db3e5
Enhance calculator modal close button styles and positioning
7h3kk1d Oct 27, 2025
b8997ab
First class modules
7h3kk1d Oct 28, 2025
f3aa2ee
halfbaked cards
7h3kk1d Oct 28, 2025
08c02a7
refactor: extract card types and utilities to dedicated modules
7h3kk1d Oct 28, 2025
3fbcf40
add click handlers for card mode toggling
7h3kk1d Oct 28, 2025
3ac7269
add CalculatorRenderer interface and fix module reference
7h3kk1d Oct 29, 2025
6b6b949
fix: add can_handle check for renderer compatibility in ProbeProj
7h3kk1d Oct 29, 2025
d20c1fa
refactor(projectors): introduce value parsing and standardize init fo…
7h3kk1d Oct 29, 2025
bff8aae
Merge remote-tracking branch 'origin/probemoar' into table-projector-…
7h3kk1d Nov 3, 2025
cf29da8
disable failing tests from probemoar
7h3kk1d Nov 4, 2025
ae6da67
fix warnings
7h3kk1d Nov 4, 2025
125a225
refactor(CardProj): remove unused imports for CardSyntax and CardUtil
7h3kk1d Nov 5, 2025
52c5863
refactor: remove unused imports across multiple modules
7h3kk1d Nov 5, 2025
79c01d0
Merge remote-tracking branch 'origin/probemoar' into table-projector-…
7h3kk1d Nov 6, 2025
6e3cb4a
Fix rich probe using latest value
7h3kk1d Nov 6, 2025
5281a1d
Get rid of close button for modal and instead make the icon toggle
7h3kk1d Nov 6, 2025
b4250c9
don't inline rewritten projector syntax
7h3kk1d Nov 6, 2025
38d099e
Prompt user for column name and use empty hole as default
7h3kk1d Nov 6, 2025
c9eeaa0
Add SVG icon for table badge in TableRenderer
7h3kk1d Nov 6, 2025
84fca98
Improve rich probe styling
7h3kk1d Nov 6, 2025
2a2ecdc
Change colors
7h3kk1d Nov 6, 2025
6eed8bd
Remove unused value_state from active_renderer and related logic
7h3kk1d Nov 6, 2025
9f4035d
refactor(CardRenderer): extract interface to .rei and remove internal…
7h3kk1d Nov 6, 2025
4233ac9
Add value back to render
7h3kk1d Nov 6, 2025
5468402
Stop reparsing expression
7h3kk1d Nov 6, 2025
5a7f3b5
Thread through sort
7h3kk1d Nov 6, 2025
4ccaaa5
Stop calculator during patterns and make table read only
7h3kk1d Nov 6, 2025
a72cfb2
Thread sort more
7h3kk1d Nov 6, 2025
3d5a82f
Actually stop calculator for patterns
7h3kk1d Nov 6, 2025
5312efb
Remove unused imports from CardRenderer
7h3kk1d Nov 20, 2025
7bb9657
Fix projector set syntax for non-refractors
7h3kk1d Nov 20, 2025
bdb03df
Fix set syntax and update model for auto probes
7h3kk1d Nov 20, 2025
07b4e59
Refactor segment function to remove debug logging
7h3kk1d Nov 20, 2025
d35a384
remove debug print_segment parameter
7h3kk1d Nov 20, 2025
06eb01b
Thread inline through term_to_seg and lift_syntax
7h3kk1d Nov 20, 2025
2e4dbaf
add comments for set syntax
7h3kk1d Nov 20, 2025
84ea718
Ensure segment is parenthesized when processing SetSyntax in the proj…
7h3kk1d Nov 20, 2025
2c2de90
Add coverage exclusion for Unicode utility file to fix regex test fai…
7h3kk1d Nov 7, 2025
1c30135
Stop using unboxing in tableproj
7h3kk1d Nov 20, 2025
55841b9
PR Cleanup
7h3kk1d Nov 20, 2025
616fd3c
Add comparison tests for built-in functions in evaluator
7h3kk1d Nov 21, 2025
97949f1
refmt
7h3kk1d Nov 21, 2025
f9bf5f8
Remove unused code
7h3kk1d Nov 21, 2025
34b6f2e
feat(calculator): switch to Bigint for arbitrary precision integers
7h3kk1d Nov 21, 2025
e9ebe54
Stop using Option.get in ProjectorPerform
7h3kk1d Nov 21, 2025
9c93072
Merge remote-tracking branch 'origin/dev' into table-projector-refractor
7h3kk1d Feb 4, 2026
b270920
Merge remote-tracking branch 'origin/probe-fixes' into table-projecto…
7h3kk1d Feb 4, 2026
3bc417c
Trim secondary segments when constructing syntax for refractors to al…
7h3kk1d Feb 4, 2026
6c93e95
Refactor build_column_menu to use explicit parameter types for improv…
7h3kk1d Feb 4, 2026
6fce622
Remove debug print statements from lift_syntax function for cleaner o…
7h3kk1d Feb 4, 2026
93462d8
Simplify focusable pointer function by removing debug print statement
7h3kk1d Feb 4, 2026
8d0567c
style(projectors): add scroll constraint to table modals
7h3kk1d Dec 2, 2025
69e9be5
feat(TableRenderer): add "Group By" action to column menu
7h3kk1d Dec 2, 2025
92bddf1
Merge remote-tracking branch 'origin/dataframe-projector' into table-…
7h3kk1d Feb 4, 2026
2e52488
Fix styling
7h3kk1d Feb 4, 2026
ee2f5bf
Merge remote-tracking branch 'origin/dataframe-projector' into table-…
7h3kk1d Feb 5, 2026
52147a3
Make auto probe models persistent
7h3kk1d Feb 5, 2026
8b43d5a
Refactor add_ids_from_auto_term to preserve existing models and optim…
7h3kk1d Feb 5, 2026
b2acebd
Merge branch 'dataframe-projector' into table-projector-refractor
7h3kk1d Feb 6, 2026
ba7870b
Add option type handling: drop Nones and provide default values in co…
7h3kk1d Feb 9, 2026
9f9075a
Add clear and noop column transformations to enhance column menu func…
7h3kk1d Feb 9, 2026
a0438b8
Remove comments
7h3kk1d Feb 9, 2026
db04bff
Merge remote-tracking branch 'origin/dataframe-projector' into table-…
7h3kk1d Feb 11, 2026
aff6787
Update table rich probe to match projector
7h3kk1d Feb 11, 2026
144cb72
Readd comparison functions
7h3kk1d Feb 11, 2026
6383832
Fix error message in get function for table retrieval
7h3kk1d Feb 11, 2026
8f32034
Merge branch 'dataframe-projector' into table-projector-refractor
7h3kk1d Feb 11, 2026
62955e2
Merge branch 'dataframe-projector' into table-projector-refractor
7h3kk1d Feb 11, 2026
fe67545
Merge remote-tracking branch 'origin/dataframe-projector' into table-…
7h3kk1d Feb 12, 2026
47f1e7a
Merge remote-tracking branch 'origin/dataframe-projector' into table-…
7h3kk1d Feb 12, 2026
b703642
Merge remote-tracking branch 'origin/dataframe-projector' into table-…
7h3kk1d Feb 12, 2026
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
24 changes: 20 additions & 4 deletions src/haz3lcore/ProbePerform.re
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,29 @@ let add_ids_from_auto_term =
(~syntax: CachedSyntax.t, ~info_map: Statics.Map.t, z: Zipper.t): Zipper.t => {
let auto_ids = Id.Map.bindings(z.refractors.autos.ids) |> List.map(fst);
let ids = List.concat_map(ids_from_term(~syntax, ~info_map), auto_ids);
/* Build a set for O(log n) membership checks */
let new_ids_set =
List.fold_left((map, id) => Id.Map.add(id, (), map), Id.Map.empty, ids);
Zipper.update_ephemerals(
_ =>
old_ephemerals => {
/* Keep existing entries that are still valid (preserves models) */
let kept =
Id.Map.filter(
(id, _) => Id.Map.mem(id, new_ids_set),
old_ephemerals,
);
/* Add new entries only for IDs not already present */
List.fold_left(
(map, id) => Id.Map.add(id, Refractors.mk_entry(Probe), map),
Id.Map.empty,
(map, id) =>
if (Id.Map.mem(id, map)) {
map; /* Already exists with model, keep it */
} else {
Id.Map.add(id, Refractors.mk_entry(Probe), map);
},
kept,
ids,
),
);
},
z,
);
};
Expand Down
7 changes: 4 additions & 3 deletions src/haz3lcore/projectors/ProjectorBase.re
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ type utility = {
/* Convert a segment to a term */
seg_to_term: Base.segment => option(Any.t),
/* Convert a term to a segment */
term_to_seg: Any.t => Base.segment,
term_to_seg: (~inline: bool, Any.t) => Base.segment,
seg_to_string: Base.segment => string,
/* Lifts term->term functions to syntax->syntax. This will
* proactively attempt to parenthesize resulting non-single
* piece terms. As such, sorts that do not have parentheses
* (currently all degenerate cases) will throw an error */
lift_syntax: (Any.t => Any.t, Base.segment) => option(Base.segment),
lift_syntax:
(~inline: bool, Any.t => Any.t, Base.segment) => option(Base.segment),
};

module Focusable = {
Expand Down Expand Up @@ -223,6 +224,6 @@ module Cook = (C: Projector) : Cooked => {
});
let placeholder = m =>
m |> Sexplib.Sexp.of_string |> C.model_of_sexp |> C.placeholder;
let update = (m, i, a) =>
let update = (m: model, i: info, a: action): model =>
C.update(m |> deserialize_m, i, a |> deserialize_a) |> serialize_m;
};
14 changes: 8 additions & 6 deletions src/haz3lcore/projectors/ProjectorInfo.re
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,29 @@ open Language;
* See ProjectorBase.utility definition for more information */
let utility: ProjectorBase.utility = {
let seg_to_term = MakeTerm.for_projection;
let term_to_seg =
let term_to_seg = (inline, any) =>
ExpToSegment.any_to_segment(
~settings={
...ExpToSegment.Settings.of_core(~inline=true, CoreSettings.off),
...ExpToSegment.Settings.of_core(~inline, CoreSettings.off),
show_unknown_as_hole: false,
fold_fn_bodies: `NoFold,
},
any,
);
let lift_syntax =
(fn: Any.t => Any.t, seg: Base.segment): option(Base.segment) =>
(inline, fn: Any.t => Any.t, seg: Base.segment): option(Base.segment) => {
switch (seg |> seg_to_term) {
| None => None
| Some(s) => Some(s |> fn |> term_to_seg)
| Some(s) => Some(s |> fn |> term_to_seg(inline))
};
};
/* NOTE: Setting indent to anything other than "" has serious
* perf implications when there are lots of probes on the screen */
let seg_to_string = Printer.of_segment(~holes="?", ~indent="");
{
term_to_seg,
term_to_seg: (~inline, any) => term_to_seg(inline, any),
seg_to_term,
lift_syntax,
lift_syntax: (~inline) => lift_syntax(inline),
seg_to_string,
};
};
Expand Down
107 changes: 80 additions & 27 deletions src/haz3lcore/projectors/ProjectorPerform.re
Original file line number Diff line number Diff line change
Expand Up @@ -184,37 +184,90 @@ let go =
| Some(z) => Ok(z)
| None => Error(Cant_project)
}
| SetSyntax(idx, seg) =>
Ok(
update(
p =>
{
...p,
syntax: Segment.parenthesize(seg),
},
projector_idx_to_id(idx),
z,
),
)
| SetSyntax(idx, kind, seg) =>
let id = idx_to_id(kind, idx);
// Ensure seg is parenthesized unless it already is
let parenthesized_piece =
Segment.unparenthesize(seg) |> Segment.parenthesize;
if (ProjectorCore.Kind.is_refractor(kind)) {
let parenthesized_seg = [parenthesized_piece];
// Check for existing refractors (automatic ephemeral or manual) that control this projector
let original_id = id;
let ephemeral_model =
Id.Map.find_opt(original_id, z.refractors.autos.ephemerals)
|> Option.map((pr: Refractors.entry) => pr.model);
let manual_refractor_model =
List.assoc_opt(original_id, z.refractors.manuals)
|> Option.map((pr: Refractors.entry) => pr.model);
switch (manual_refractor_model, ephemeral_model) {
| (Some(refractor_model), _) =>
// Manual refractor exists: update the selection to this projector's term range,
// replace with new syntax, and create a new refractor probe monitoring the updated term
let new_id =
MakeTerm.from_zip_for_sem(
Zipper.unzip(~direction=Right, parenthesized_seg),
).
term
|> Language.Exp.rep_id;

let new_z = {
open OptUtil.Syntax;
let* (l, r) = TermData.extremes_shards(id, term_data);
let+ z = Select.shard_range(l, r, z);
let z = Zipper.replace_selection(Right, parenthesized_seg, z);
ZipperBase.add_manual(~model=refractor_model, new_id, kind, z);
};

switch (new_z) {
| Some(z) => Ok(z)
| None => Error(Cant_project)
};
| (_, Some(_)) =>
// Ephemeral refractor exists: update selection and replace syntax,
// but don't create new refractor as this is handled automatically

let new_z = {
open OptUtil.Syntax;
let* (l, r) = TermData.extremes_shards(id, term_data);
let+ z = Select.shard_range(l, r, z);
let z = Zipper.replace_selection(Right, parenthesized_seg, z);
z;
};

switch (new_z) {
| Some(z) => Ok(z)
| None => Error(Cant_project)
};
| (None, None) => assert(false)
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert(false) on line 241 indicates a case that is expected to never happen (when a refractor is being processed but neither manual nor ephemeral refractor exists). However, using assert(false) causes the program to crash at runtime if this assumption is violated. Consider using a more graceful error handling approach, such as returning Error(Cant_project) or adding a descriptive error message explaining what invariant was violated.

Suggested change
| (None, None) => assert(false)
| (None, None) =>
// Invariant violation: refractor-kind projector without manual or ephemeral refractor.
// Fail gracefully instead of crashing.
Error(Cant_project)

Copilot uses AI. Check for mistakes.
};
} else {
Ok(
update(
pr =>
{
...pr,
syntax: parenthesized_piece,
},
id,
z,
),
);
};
| SetModel(idx, kind, new_model) =>
let id = idx_to_id(kind, idx);
Ok(
if (ProjectorCore.Kind.is_refractor(kind)) {
Zipper.update_manuals(
map =>
ListUtil.assoc_update(
id,
fun
| Some(entry: Refractors.entry) =>
Some(
Refractors.{
kind: entry.kind,
model: new_model,
},
)
| None => None,
map,
),
Zipper.update_refractor(
id,
fun
| Some(entry: Refractors.entry) =>
Some(
Refractors.{
kind: entry.kind,
model: new_model,
},
)
| None => None,
z,
);
} else {
Expand Down
1 change: 1 addition & 0 deletions src/haz3lcore/projectors/implementations/CSVProjector.re
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ module M: Projector = {

switch (
info.utility.lift_syntax(
~inline=true,
fun
| Exp(any) =>
Exp({
Expand Down
Loading