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

Distinguish datatypes from other tables #223

Merged
merged 8 commits into from
Sep 12, 2023

Conversation

oflatt
Copy link
Member

@oflatt oflatt commented Sep 3, 2023

Tables with merge functions are fundamentally different than those without- we have places in the code where we check for a merge function or defaults. This PR clarifies that distinction.

It also enforces that the set keyword is only used on non-datatype tables, clarifying the confusion between set and union and making it clear when set is needed.

Depends on #222

@oflatt oflatt requested a review from a team as a code owner September 3, 2023 22:42
@oflatt oflatt requested review from mwillsey and yihozhang and removed request for a team September 3, 2023 22:42
Comment on lines +340 to 343
/// - The output is not a primitive
/// - No merge function is provided
/// - No default is provided
Function(FunctionDecl),
Copy link
Member

Choose a reason for hiding this comment

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

Oh I wasn't aware you could have functions with non primitive return values and custom merge functions...

Copy link
Member Author

Choose a reason for hiding this comment

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

It's currently a very under-tested feature! I plan to use it more in the future though, it's essential for encoding proofs.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It can be used to simulate the choice construct in Datalog literature by setting :merge old (as is used in proofs)

@saulshanabrook
Copy link
Member

I am giving this branch a test with the Python test suite to see if anything breaks and will let you know this week!

@oflatt
Copy link
Member Author

oflatt commented Sep 4, 2023

I am giving this branch a test with the Python test suite to see if anything breaks and will let you know this week!

Thanks! That's super helpful

@yihozhang
Copy link
Collaborator

yihozhang commented Sep 6, 2023

Does this PR disallow :merge old for datatypes?

@oflatt
Copy link
Member Author

oflatt commented Sep 6, 2023

Yep, datatypes can't have merge functions

@yihozhang
Copy link
Collaborator

Doesn't this cause issues for proofs? Proof terms are datatypes, right?

I like the ability to simulate the choice construct (for data types) in Datalog. I'm even thinking about having a :choice keyword in function declarations. Or maybe you are sure we don't need this anymore?

@saulshanabrook
Copy link
Member

I gave it a go on the Python bindings, and almost all the tests pass. The one that doesn't might be on my end, so I'll keep looking into it. It's a more complicated example that I am looking to refactor anyway a bit

egraphs-good/egglog-python#46

Comment on lines -562 to +619
default: None,
default: Some(Expr::Lit(Literal::Unit)),
Copy link
Member

Choose a reason for hiding this comment

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

I am curious why the relation now needs a default to work? It does make it a little more cumbersome to define relations with the function syntax. Would you ever want to define a function that returns Unit but doesn't have this as a default?

Copy link
Member Author

@oflatt oflatt Sep 8, 2023

Choose a reason for hiding this comment

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

Good question-
Unit is a primitive just like i64. Before, we had special logic for making default units, making them special in a weird way. Now, I make it explicit that the relation syntax is sugar for this function for convenience.

You can still have a function that returns Unit without this default and use set everywhere. But this is more convenient

Copy link
Member

Choose a reason for hiding this comment

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

Ah I see.

Is it true then that using a function that does not return a default as an action is a no-op? And that's why you needed the special case before and now with it removed you have added a default?

As a test, this rule seems to have no effect, when there is no default (based on the viz):

(datatype Expr)

(function trigger () Expr)

(function foo () i64)

(trigger)

(rule ((= x (trigger))) ((foo)))

(run 1)

But it does when there is a default:

(datatype Expr)

(function trigger () Expr)

(function foo () i64 : default 10)

(trigger)

(rule ((= x (trigger))) ((foo)))

(run 1)

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, shouldn't you get an exception when there isn't a default?
Otherwise, the action might fail halfway-through!

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, so if I am understanding that correctly, only functions with defaults can be used as actions?

@oflatt
Copy link
Member Author

oflatt commented Sep 8, 2023

Doesn't this cause issues for proofs? Proof terms are datatypes, right?

I like the ability to simulate the choice construct (for data types) in Datalog. I'm even thinking about having a :choice keyword in function declarations. Or maybe you are sure we don't need this anymore?

Yep, this PR supports proofs. For proofs we need a way to talk about stable ids for terms, so we need some kind of table which is stable (I call those datatypes). If you want something else, just use a non-datatype table instead.

Copy link
Collaborator

@yihozhang yihozhang left a comment

Choose a reason for hiding this comment

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

Thanks! This makes sense now. I left a small comment but looks great!

@@ -747,9 +752,6 @@ impl EGraph {
let value = if let Some(out) = function.nodes.get(values) {
out.value
} else if make_defaults {
if function.merge.on_merge.is_some() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why's this no longer needed?

Copy link
Member Author

Choose a reason for hiding this comment

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

make_defaults implies that this isn't a datatype. Either there is a merge function, or you get an exception because you tried to merge two primitives.

@oflatt oflatt merged commit 4d67f26 into egraphs-good:main Sep 12, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants