Skip to content
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

Merged
merged 266 commits into from
Feb 11, 2025
Merged

Implement Labeled Tuples #1235

merged 266 commits into from
Feb 11, 2025

Conversation

WondAli
Copy link
Contributor

@WondAli WondAli commented Mar 5, 2024

Labeled Tuples

Overview

This PR introduces labeled tuples to Hazel, allowing tuple elements to be named using the = operator.

Note: This PR replaces an outdated implementation on a different branch, as I couldn't change the source branch on the old PR.

What Are Labeled Tuples?

Labeled tuples allow elements within a tuple to be named using the = operator. For example:

(x=1, y=2)

Here, x=1 and y=2 define labeled elements. These labels are only relevant within the enclosing tuple. Conceptually, = acts as a binary operator that pairs a label (a string) with an expression.

Labeled Tuple Features

Labeled elements can appear in any order when matched against a labeled tuple type, while unlabeled elements must maintain relative order.

Examples

  • (x=1, True, y=6) correctly matches the type (Bool, y=Int, x=Int).
  • let x=a, b = (y=2, x=4) binds 4 to a and 2 to b.

Dot Operator/Projection (.)

The dot operator allows extracting labeled elements from tuples:

(x=1, 2, 3).x  # Evaluates to 1 #

Singleton Labeled Tuples

A labeled tuple with a single element, such as (a=1), follows the same principles as multi-element labeled tuples but has some unique characteristics:

  • Syntactic Form:
    • A singleton labeled tuple is typically written as (a=1), but parentheses are optional, so a=1 is also valid.
  • Type-Checking & Label Inference:
    • If an unlabeled value is analyzed against a labeled tuple type, it is automatically wrapped as a singleton labeled tuple.
    • Example: Analyzing 1 against (a=Int) infers 1 as a=1.
  • Dot Operator Compatibility:
    • (a=1).a correctly extracts 1.

Implementation Strategy

Labeled tuples are implemented by extending existing constructs in expressions, patterns, and types:

  • TupLabel: Represents a labeled tuple element in expressions, patterns, and types.
  • Label: Represents the label itself, always appearing in the label position of TupLabel.
    • Any other sort present in label position other than a valid label or empty hole is placed in a MultiHole
  • Dot: In expressions represents tuple label projection (i.e., field access). The right-hand argument of Dot must be a Label.

Automatic label inference

  • Missing labels are introduced during the elaboration phase for tuples
  • Singleton labeled tuples are converted to tuples during Statics and the syntax is rewritten and stored in the info map.
    • During elaboration this syntax is pulled out of the info map to rewrite the syntax before evaluation

Future work

  • Introduce Label sort that keeps labels in their own syntactic context

@WondAli WondAli added the in-development for PRs that remain in development label Mar 5, 2024
@WondAli WondAli self-assigned this Mar 5, 2024
@WondAli WondAli mentioned this pull request Mar 5, 2024
@cyrus-
Copy link
Member

cyrus- commented May 1, 2024

@WondAli playing with this branch, looks like the labels aren't showing up in the types of the tuples (and so you get weird run-time errors when projecting out a label that doesn't exist). is there a specific issue with adding labels to product types?

@WondAli WondAli force-pushed the labeled-tuple-rewrite branch 2 times, most recently from b8e1f37 to 3c24406 Compare August 24, 2024 21:16
@WondAli WondAli force-pushed the labeled-tuple-rewrite branch from 3c24406 to fe24986 Compare August 24, 2024 21:22
src/haz3lcore/LabeledTuple.re Outdated Show resolved Hide resolved
src/haz3lcore/LabeledTuple.re Outdated Show resolved Hide resolved
src/haz3lcore/LabeledTuple.re Outdated Show resolved Hide resolved
src/haz3lcore/LabeledTuple.re Outdated Show resolved Hide resolved
src/haz3lcore/LabeledTuple.re Outdated Show resolved Hide resolved
src/haz3lcore/dynamics/DH.re Outdated Show resolved Hide resolved
src/haz3lcore/dynamics/DH.re Outdated Show resolved Hide resolved
@7h3kk1d
Copy link
Contributor

7h3kk1d commented Sep 13, 2024

Evaluation should continue around:

let x : (a=Int, b=String)= (a=1, b=? ) in (x.b, x.a)

@7h3kk1d
Copy link
Contributor

7h3kk1d commented Sep 19, 2024

There's another issue with the parsing for type annotations outside lets:

((a="Foo", b=8) : (a=String, b=Int))

Screenshot from 2024-09-19 13-50-26

Copy link
Member

@cyrus- cyrus- left a comment

Choose a reason for hiding this comment

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

  • floating point exponential notation isn't working anymore
  • see inline comments

src/haz3lcore/statics/Statics.re Outdated Show resolved Hide resolved
src/haz3lcore/statics/MakeTerm.re Outdated Show resolved Hide resolved
src/haz3lcore/zipper/EditorUtil.re Outdated Show resolved Hide resolved
@@ -201,6 +213,7 @@ let rec var_mention = (name: string, uexp: Exp.t): bool => {
| BuiltinFun(_) => false
| Cast(d, _, _) => var_mention(name, d)
| Ap(_, u1, u2)
| Dot(u1, u2)
Copy link
Member

Choose a reason for hiding this comment

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

check to make sure label positions are not being recursed into for variable mentions / recursive functions / etc.

Copy link
Contributor

Choose a reason for hiding this comment

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

@cyrus- since we don't have the label sort introduced, the variables in label position are still being evaluated:

Screenshot From 2025-02-10 10-24-37

I can try to make these indet, but it's not clear to me that it's preferable to stop dynamics for the expression. If we still allow evaluation I think we want to continue to recurse into the "label position" in SyntaxTest.

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems somewhat related to decisions for now evaluation should proceed in non-empty holes #1497 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

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

I've put everything in label position in multiholes if it's not a label.

@7h3kk1d

This comment was marked as resolved.

@hazelgrove hazelgrove deleted a comment from cyrus- Feb 10, 2025
@cyrus- cyrus- marked this pull request as ready for review February 11, 2025 16:51
@cyrus- cyrus- merged commit 119284e into dev Feb 11, 2025
2 checks passed
@cyrus- cyrus- deleted the labeled-tuple-rewrite branch February 11, 2025 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-development for PRs that remain in development
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants