-
Notifications
You must be signed in to change notification settings - Fork 52
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
Implement Labeled Tuples #1235
Draft
WondAli
wants to merge
120
commits into
dev
Choose a base branch
from
labeled-tuple-rewrite
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Implement Labeled Tuples #1235
Changes from 110 commits
Commits
Show all changes
120 commits
Select commit
Hold shift + click to select a range
3d2a351
labeled tuple rewrite
WondAli 6889f4f
Merge branch 'dev' into labeled-tuple-rewrite
WondAli c137ded
working dot operator + bug fixes to precedence
WondAli 5af500f
may need to revert some tuplabel code since no longer consistent with…
WondAli 9927605
allow for unmatched labels in one direction
WondAli 55500e6
updated casting for labels
WondAli f08c114
left-associativity for dot operator
WondAli 7ab1470
dot now treats labels as tuples of size 1
WondAli 1cdeb3a
multiple bug fixes and implemented labels as function arguments. TODO…
WondAli 0598c9c
code cleanup, quality improvement. Also fixes to casting (mostly)
WondAli b3e7c84
casting bug fix
WondAli dfdf051
merged with dev
WondAli 07275db
minor changes to dot in statics and matching
WondAli 44841b8
standalone labels as singleton tuples + shifting error handling for u…
WondAli 56d9a50
fixed bug concerning rearranging function arguments
WondAli 3d294dd
documentation in progress
WondAli cbe3125
merge complete
WondAli e0952df
renamed some variables to be more accurate
WondAli bf1137c
dot operator update
WondAli 9ab0f49
dot operator static fixes
WondAli db194f8
Creation of Label term, bug fixes, documentation updates
WondAli c20706a
fixes to labeled expressions as singleton tuples
WondAli fe24986
minor test_elaboration update
WondAli 773fa9b
singleton tuple fixes
WondAli e76f5e2
fix statics to check for mismatched labels
WondAli a802eb7
fix to let elaboration so that dot operators operate on annotated typ…
WondAli 65eec8e
merge (not working)
WondAli 4753f3f
fix to precedence and cast ground_caes_of
WondAli cae4bb5
elaborator fixes
WondAli bc22754
updated parser for dot operator
WondAli e810400
debug
7h3kk1d 840f06f
Temp commit
7h3kk1d 58fc12c
Add rearrange2
7h3kk1d 2b1eda8
I got some version of elaboration working
7h3kk1d 2be5a46
Fix formatting
7h3kk1d f7a2666
Cleanup
7h3kk1d a2c34df
Revert makefile changes
7h3kk1d 50536fe
Cleanup debugging code
7h3kk1d 4226bb4
More cleanup
7h3kk1d 8eef13c
Got a version of evaluation to work
7h3kk1d 998caeb
Stop elaborating labels in Dot
7h3kk1d 000b853
updates to elaboration, label extraction, ap in progress
WondAli 76247f0
merged with labeled-tuple-rewrite
WondAli 8379dec
Missing labeled tuple labels elboration (#1399)
WondAli d5dfa8f
cleaned LabeledTuple util file
WondAli 7d707c9
Rearranging does not occur past elaboration. Functions reworked to al…
WondAli 20c51f9
Add support for fast_equal on TupLabel expressions
7h3kk1d 49c11d9
Add test for elaboration adding labels to labeled tuples
7h3kk1d 38b10c1
Inline expectation
7h3kk1d c315caa
Fix typos
7h3kk1d 5707718
Add test for rearranging labels during elaboration
7h3kk1d e4fb061
Merge remote-tracking branch 'origin/dev' into labeled-tuple-rewrite
7h3kk1d 8d6528e
Add test for labeled tuple projection evaluation
7h3kk1d a5c83bc
Add statics test for labeled parameter in function
7h3kk1d f4d778e
Added tests to assure that types are inconsistent when unlabeled vari…
7h3kk1d 32173ea
removed function implicit labelling and rearranging in type consisten…
WondAli 318cfb3
Add basic elaboration tests for singleton tuples
7h3kk1d c8ef191
Modify singleton labeled tuple elaboration
7h3kk1d 22cd8d6
Add parser tests for singleton tuples
7h3kk1d f04c976
Wrap all tuplabels in tuples in parser
7h3kk1d 78e817c
Remove is_contained logic
7h3kk1d 7008809
More tests
7h3kk1d 59ff548
Add assertions that there's no static errors in static tests
7h3kk1d 158a62d
Merge branch 'dev' into labeled-tuple-rewrite
7h3kk1d 0669d9c
Ensure more tests are fully consistent
7h3kk1d c27642b
Stop recalculating statics in tests
7h3kk1d bcd9fe2
Add support for displaying TupLabel with label and type in view_ty fu…
7h3kk1d 926c5c7
Add labeled tuples doc page
7h3kk1d 5f790cb
revert scratch file
7h3kk1d 39cbba1
Revert init.ml
7h3kk1d b242321
Add sdocumentation page for labeled tuples
7h3kk1d de85c69
Tests for multiple labels
7h3kk1d 3c36566
Update Makefile to include dev profile in watch-test
7h3kk1d 72b4cac
Add test case for singleton labeled tuple adding label
7h3kk1d 828da51
Make labeled tuple not need parens in display
7h3kk1d 7688a2b
Add test case for let statement that adds labels during elaboration
7h3kk1d c86e5f0
Add support for lifting single values into a singleton labeled tuple …
7h3kk1d dac5119
Refmt
7h3kk1d 3420d2c
Additional test for singleton labels
7h3kk1d 1fa320c
SIngleton labels kind of work
7h3kk1d c87048d
Remove singleton product from type view
7h3kk1d 01f84c5
Fix the duplicate singleton label statics
7h3kk1d e018126
Fix stack overflow
7h3kk1d 11804a2
Fix warning in test statics
7h3kk1d 523177e
First attempt singleton labeled tuple elaboration
7h3kk1d c4db0d0
Remove debug comment
7h3kk1d 03208ff
Fix test
7h3kk1d 0f8521a
More singleton label elaborator fixes
7h3kk1d 1bee9bb
Update init
7h3kk1d e66dd80
Add tests for singleton labeled argument function application
7h3kk1d b42c613
Progress on elaborating singleton tuples with mismatched labels
7h3kk1d 9a918ef
Fix warnings
7h3kk1d a603ae7
Merge remote-tracking branch 'origin/dev' into labeled-tuple-rewrite
7h3kk1d 61937e7
Merge remote-tracking branch 'origin/dev' into labeled-tuple-rewrite
7h3kk1d d88395e
Closer to getting singleton labeled tuples to work
7h3kk1d 7c5abb5
Fix unused warnings
7h3kk1d d163367
Errored statuses showed up right
7h3kk1d 0343f51
Extract functions to be slightly more legible
7h3kk1d 8d3d3e6
Merge branch 'dev' into labeled-tuple-rewrite
7h3kk1d 12eef70
Fixed singleton labeled tuple in function application
7h3kk1d 868ed9b
Fix statics test
7h3kk1d effab75
Merge remote-tracking branch 'origin/dev' into labeled-tuple-rewrite
7h3kk1d d1cd408
Add some information on the lifted type to the cursor inspector
7h3kk1d ece70b4
label uniqueness checking
WondAli 3624020
Start elaborating singleton labeled tuple patterns
7h3kk1d ecbd7ce
Singleton labeled tuple pattern elaboration disabled under ascription
7h3kk1d 24de2fa
Fix assertions
7h3kk1d 58029ad
Stop debugging
7h3kk1d 69fb726
Remove unnecessary module name
7h3kk1d 4a78f89
Fix tests and strip casts out of some of the tests
7h3kk1d 30e3b9c
Bugfix: statics now check that the first argument in a TupLabel is a …
WondAli 5529383
Progress on improving cursor inspector for automatic labelling
7h3kk1d 4a8776c
Fix unused module open
7h3kk1d 7166f28
Add sugar to info
7h3kk1d 6e71d52
Add more labeling information to cursor inspector
7h3kk1d ddaaaa9
Add pattern labels to cursor inspector
7h3kk1d 88931f4
Remove lifted_ty from Info types
7h3kk1d 3a96a5a
Cursor inspector changes
7h3kk1d 68f85ab
updated dot operator to use labels
WondAli bd36673
Fix cursor inspector message
7h3kk1d File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,311 @@ | ||
open Util; | ||
|
||
exception Exception; | ||
|
||
[@deriving (show({with_path: false}), sexp, yojson)] | ||
type label = string; | ||
|
||
let equal: (option((label, 'a)), option((label, 'b))) => bool = | ||
(left, right) => { | ||
switch (left, right) { | ||
| (Some((s1, _)), Some((s2, _))) => String.equal(s1, s2) | ||
| (_, _) => false | ||
}; | ||
}; | ||
|
||
let length = String.length; | ||
|
||
let compare = String.compare; | ||
|
||
let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; | ||
|
||
// returns a pair containing a list of option(t) and a list of 'a | ||
// if 'a is a tuplabel, separates the label from the element held by it. | ||
let separate_labels: | ||
('a => option((label, 'a)), list('a)) => | ||
(list(option(label)), list('a)) = | ||
(get_label, es) => { | ||
let results = | ||
List.fold_left( | ||
((ls, ns), e) => | ||
switch (get_label(e)) { | ||
| Some((s1, e)) => (ls @ [Some(s1)], ns @ [e]) | ||
| None => (ls @ [None], ns @ [e]) | ||
}, | ||
([], []), | ||
es, | ||
); | ||
results; | ||
}; | ||
|
||
// returns a pair containing a list of option(t) and a list of 'a | ||
// if 'a is a tuplabel, extracts the label but keeps the tuplabel together | ||
let separate_and_keep_labels: | ||
('a => option((label, 'a)), list('a)) => | ||
(list(option(label)), list('a)) = | ||
(get_label, es) => { | ||
let results = | ||
List.fold_left( | ||
((ls, ns), e) => | ||
switch (get_label(e)) { | ||
| Some((s1, _)) => (ls @ [Some(s1)], ns @ [e]) | ||
| None => (ls @ [None], ns @ [e]) | ||
}, | ||
([], []), | ||
es, | ||
); | ||
results; | ||
}; | ||
|
||
// TODO consider adding a t = (option(label), 'a) | ||
|
||
let separate_labeled = (xs: list((option(label), 'a))) => { | ||
List.partition_map( | ||
((l, a)) => | ||
switch (l) { | ||
| None => Right(a) | ||
| Some(l) => Left((l, a)) | ||
}, | ||
xs, | ||
); | ||
}; | ||
|
||
// TODO Performance | ||
let intersect = (xs, ys) => { | ||
List.filter_map(x => List.find_opt((==)(x), ys), xs); | ||
}; | ||
|
||
// TODO: can just use get_duplicate_labels and check if empty. | ||
// Takes a list of strings and returns true if there are no duplicates. | ||
let rec is_uniquely_labeled_base: list(label) => bool = | ||
labels => { | ||
let contains_duplicates = | ||
switch (labels) { | ||
| [] => false | ||
| [hd, ...tl] => | ||
List.exists(l => hd == l, tl) || is_uniquely_labeled_base(tl) | ||
}; | ||
!contains_duplicates; | ||
}; | ||
|
||
// TODO: Performance | ||
// Takes a list of strings and returns a list of duplicates and list of uniques. | ||
// Can also be modified to get unique labels. | ||
let get_duplicate_and_unique_labels_base: | ||
list(label) => (list(label), list(label)) = | ||
labels => { | ||
let (duplicates, uniques) = | ||
List.fold_left( | ||
(acc, label) => { | ||
let (dupes, uniqs) = acc; | ||
List.exists(l => label == l, uniqs) | ||
? List.exists(l => label == l, dupes) | ||
? (dupes, uniqs) : (dupes @ [label], uniqs) | ||
: (dupes, uniqs @ [label]); | ||
}, | ||
([], []), | ||
labels, | ||
); | ||
(duplicates, uniques); | ||
}; | ||
|
||
// Takes in a get_label function and a list of elements and applys is_uniquely_labeled_base | ||
let is_uniquely_labeled: 'a. ('a => option((label, 'a)), list('a)) => bool = | ||
(get_label, es) => { | ||
let labels = fst(separate_and_keep_labels(get_label, es)); | ||
let labels = | ||
labels | ||
|> List.filter(x => Option.is_some(x)) | ||
|> OptUtil.sequence | ||
|> OptUtil.get(() => []); | ||
is_uniquely_labeled_base(labels); | ||
}; | ||
|
||
let get_duplicate_and_unique_labels: | ||
'a. | ||
('a => option((label, 'a)), list('a)) => (list(label), list(label)) | ||
= | ||
(get_label, es) => { | ||
let labels = fst(separate_and_keep_labels(get_label, es)); | ||
let labels = | ||
labels | ||
|> List.filter(x => Option.is_some(x)) | ||
|> OptUtil.sequence | ||
|> OptUtil.get(() => []); | ||
get_duplicate_and_unique_labels_base(labels); | ||
}; | ||
|
||
// Assumes all labels are unique | ||
// Rearranges all the labels in l2 to match the order of the labels in l1. Labels are optional and should me reordered for all present labels first and then unlabled fields matched up pairwise. So labeled fields can be reordered and unlabeled ones can't. Also add labels to the unlabeled. | ||
// TODO Handle the unequal length case and extra labels case | ||
let rec rearrange_base: | ||
'b. | ||
( | ||
~show_b: 'b => string=?, | ||
list(option(label)), | ||
list((option(label), 'b)) | ||
) => | ||
list((option(label), 'b)) | ||
= | ||
(~show_b=?, l1: list(option(label)), l2: list((option(label), 'b))) => { | ||
let l1_labels = List.filter_map(Fun.id, l1); | ||
let l2_labels = List.filter_map(fst, l2); | ||
let common_labels = intersect(l1_labels, l2_labels); | ||
|
||
switch (l1, l2) { | ||
| ([], _) => l2 | ||
| (_, []) => [] | ||
| ([Some(expected_label), ...remaining_expectations], remaining) => | ||
let maybe_found = List.assoc_opt(Some(expected_label), remaining); | ||
|
||
switch (maybe_found) { | ||
| Some(found) => | ||
[(Some(expected_label), found)] | ||
@ rearrange_base( | ||
~show_b?, | ||
remaining_expectations, | ||
List.remove_assoc(Some(expected_label), remaining), | ||
) | ||
| None => | ||
let ( | ||
pre: list((option(label), 'b)), | ||
current: option((option(label), 'b)), | ||
post: list((option(label), 'b)), | ||
) = | ||
ListUtil.split(remaining, ((label: option(label), _)) => { | ||
switch (label) { | ||
| Some(label) => !List.mem(label, common_labels) | ||
| None => true | ||
} | ||
}); | ||
|
||
switch (current) { | ||
| Some((_existing_label, b)) => | ||
[(Some(expected_label), b)] | ||
@ rearrange_base(~show_b?, remaining_expectations, pre @ post) | ||
| None => remaining | ||
}; | ||
}; | ||
| ([None, ...remaining_expectations], remaining) => | ||
// Pick the first one that's not in common labels and then keep the rest in remaining | ||
let ( | ||
pre: list((option(label), 'b)), | ||
current: option((option(label), 'b)), | ||
post: list((option(label), 'b)), | ||
) = | ||
ListUtil.split(remaining, ((label: option(label), _)) => { | ||
switch (label) { | ||
| Some(label) => !List.mem(label, common_labels) | ||
| None => true | ||
} | ||
}); | ||
switch (current) { | ||
| Some((_existing_label, b)) => | ||
[(None, b)] | ||
@ rearrange_base(~show_b?, remaining_expectations, pre @ post) | ||
| None => remaining | ||
}; | ||
}; | ||
}; | ||
|
||
// Basically another way to call rearrange_base using the raw lists, functions to extract labels from TupLabels, and constructor for new TupLabels. | ||
// Maintains the same ids if possible | ||
// TODO: clean up more | ||
let rearrange: | ||
'a 'b. | ||
( | ||
'a => option((label, 'a)), | ||
'b => option((label, 'b)), | ||
list('a), | ||
list('b), | ||
(label, 'b) => 'b | ||
) => | ||
list('b) | ||
= | ||
(get_label1, get_label2, l1, l2, constructor) => { | ||
// TODO: Error handling in case of bad arguments | ||
let l1' = fst(separate_and_keep_labels(get_label1, l1)); | ||
let (l2_labels, l2_vals) = separate_and_keep_labels(get_label2, l2); | ||
let l2' = List.combine(l2_labels, l2_vals); | ||
let l2_reordered = rearrange_base(l1', l2'); | ||
List.map( | ||
((optional_label, b)) => | ||
switch (optional_label) { | ||
| Some(label) => | ||
// TODO: probably can keep the same ids in a cleaner way | ||
switch (get_label2(b)) { | ||
| Some(_) => b | ||
| None => constructor(label, b) | ||
} | ||
| None => b | ||
}, | ||
l2_reordered, | ||
); | ||
}; | ||
|
||
// rearrange two other lists to match the first list of labels. | ||
// TODO: Ensure that the two lists match up with each other | ||
// TODO: This function currently exists only to make the elaborator code cleaner. Probably can make more efficient | ||
let rearrange2: | ||
'a 'b. | ||
( | ||
list(option(label)), | ||
'a => option((label, 'a)), | ||
'b => option((label, 'b)), | ||
list('a), | ||
list('b), | ||
(label, 'a) => 'a, | ||
(label, 'b) => 'b | ||
) => | ||
(list('a), list('b)) | ||
= | ||
(labels, get_label1, get_label2, l1, l2, constructor1, constructor2) => { | ||
let (l1_labels, l1_vals) = separate_and_keep_labels(get_label1, l1); | ||
let l1' = List.combine(l1_labels, l1_vals); | ||
let l1_reordered = rearrange_base(labels, l1'); | ||
let l1_rearranged = | ||
List.map( | ||
((optional_label, b)) => | ||
switch (optional_label) { | ||
| Some(label) => | ||
// TODO: probably can keep the same ids in a cleaner way | ||
switch (get_label1(b)) { | ||
| Some(_) => b | ||
| None => constructor1(label, b) | ||
} | ||
| None => b | ||
}, | ||
l1_reordered, | ||
); | ||
let (l2_labels, l2_vals) = separate_and_keep_labels(get_label2, l2); | ||
let l2' = List.combine(l2_labels, l2_vals); | ||
let l2_reordered = rearrange_base(labels, l2'); | ||
let l2_rearranged = | ||
List.map( | ||
((optional_label, b)) => | ||
switch (optional_label) { | ||
| Some(label) => | ||
// TODO: probably can keep the same ids in a cleaner way | ||
switch (get_label2(b)) { | ||
| Some(_) => b | ||
| None => constructor2(label, b) | ||
} | ||
| None => b | ||
}, | ||
l2_reordered, | ||
); | ||
(l1_rearranged, l2_rearranged); | ||
}; | ||
|
||
let find_label: ('a => option((label, 'a)), list('a), label) => option('a) = | ||
(filt, es, label) => { | ||
find_opt( | ||
e => { | ||
switch (filt(e)) { | ||
| Some((s, _)) => compare(s, label) == 0 | ||
| None => false | ||
} | ||
}, | ||
es, | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Personal note: It would be great if we had
map2
from https://ocaml.janestreet.com/ocaml-core/109.20.00/doc/core/Option.htmlThere 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.
This exists in OptUtil