-
Notifications
You must be signed in to change notification settings - Fork 54
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
Changes from all commits
0acee28
18aaaf2
7f4b58e
9d47f2c
8f78900
b6fe9c4
5d47d73
f6df3ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,7 +91,7 @@ pub enum NCommand { | |
value: Expr, | ||
}, | ||
Sort(Symbol, Option<(Symbol, Vec<Expr>)>), | ||
Function(FunctionDecl), | ||
Function(NormFunctionDecl), | ||
AddRuleset(Symbol), | ||
NormRule { | ||
name: Symbol, | ||
|
@@ -132,7 +132,7 @@ impl NCommand { | |
value: value.clone(), | ||
}, | ||
NCommand::Sort(name, params) => Command::Sort(*name, params.clone()), | ||
NCommand::Function(f) => Command::Function(f.clone()), | ||
NCommand::Function(f) => Command::Function(f.to_fdecl()), | ||
NCommand::AddRuleset(name) => Command::AddRuleset(*name), | ||
NCommand::NormRule { | ||
name, | ||
|
@@ -335,7 +335,29 @@ pub enum Command { | |
sort: Symbol, | ||
}, | ||
Sort(Symbol, Option<(Symbol, Vec<Expr>)>), | ||
/// Declare an egglog function. | ||
/// The function is a datatype when: | ||
/// - The output is not a primitive | ||
/// - No merge function is provided | ||
/// - No default is provided | ||
Function(FunctionDecl), | ||
/// Declare an egglog relation, which is simply sugar | ||
/// for a function returning the `Unit` type. | ||
/// Example: | ||
/// ```lisp | ||
/// (relation path (i64 i64)) | ||
/// (relation edge (i64 i64)) | ||
/// ``` | ||
|
||
/// Desugars to: | ||
/// ```lisp | ||
/// (function path (i64 i64) Unit :default ()) | ||
/// (function edge (i64 i64) Unit :default ()) | ||
/// ``` | ||
Relation { | ||
constructor: Symbol, | ||
inputs: Vec<Symbol>, | ||
}, | ||
AddRuleset(Symbol), | ||
Rule { | ||
name: Symbol, | ||
|
@@ -387,6 +409,10 @@ impl ToSexp for Command { | |
Command::Sort(name, None) => list!("sort", name), | ||
Command::Sort(name, Some((name2, args))) => list!("sort", name, list!( name2, ++ args)), | ||
Command::Function(f) => f.to_sexp(), | ||
Command::Relation { | ||
constructor, | ||
inputs, | ||
} => list!("relation", constructor, list!(++ inputs)), | ||
Command::AddRuleset(name) => list!("ruleset", name), | ||
Command::Rule { | ||
name, | ||
|
@@ -498,12 +524,43 @@ impl NormRunConfig { | |
} | ||
} | ||
|
||
/// A normalized function declaration- the desugared | ||
/// version of a [`FunctionDecl`]. | ||
/// TODO so far only the merge action is normalized, | ||
/// not the default value or merge expression. | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
pub struct NormFunctionDecl { | ||
pub name: Symbol, | ||
pub schema: Schema, | ||
// todo desugar default, merge | ||
pub default: Option<Expr>, | ||
pub merge: Option<Expr>, | ||
pub merge_action: Vec<NormAction>, | ||
pub cost: Option<usize>, | ||
pub unextractable: bool, | ||
} | ||
|
||
impl NormFunctionDecl { | ||
pub fn to_fdecl(&self) -> FunctionDecl { | ||
FunctionDecl { | ||
name: self.name, | ||
schema: self.schema.clone(), | ||
default: self.default.clone(), | ||
merge: self.merge.clone(), | ||
merge_action: self.merge_action.iter().map(|a| a.to_action()).collect(), | ||
cost: self.cost, | ||
unextractable: self.unextractable, | ||
} | ||
} | ||
} | ||
|
||
/// Represents the declaration of a function | ||
/// directly parsed from source syntax. | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
pub struct FunctionDecl { | ||
pub name: Symbol, | ||
pub schema: Schema, | ||
pub default: Option<Expr>, | ||
// TODO we should desugar merge and merge action | ||
pub merge: Option<Expr>, | ||
pub merge_action: Vec<Action>, | ||
pub cost: Option<usize>, | ||
|
@@ -559,7 +616,7 @@ impl FunctionDecl { | |
}, | ||
merge: None, | ||
merge_action: vec![], | ||
default: None, | ||
default: Some(Expr::Lit(Literal::Unit)), | ||
Comment on lines
-562
to
+619
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question- You can still have a function that returns There was a problem hiding this comment. Choose a reason for hiding this commentThe 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):
But it does when there is a default:
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? |
||
cost: None, | ||
unextractable: false, | ||
} | ||
|
@@ -710,8 +767,15 @@ impl Display for Fact { | |
#[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
pub enum Action { | ||
Let(Symbol, Expr), | ||
/// `set` a table to a particular result. | ||
/// `set` should not be used on datatypes- | ||
/// instead, use `union`. | ||
Set(Symbol, Vec<Expr>, Expr), | ||
Delete(Symbol, Vec<Expr>), | ||
/// `union` two datatypes, making them equal | ||
/// in the implicit, global equality relation | ||
/// of egglog. | ||
/// All rules match modulo this equality relation. | ||
Union(Expr, Expr), | ||
Extract(Expr, Expr), | ||
Panic(String), | ||
|
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.
Oh I wasn't aware you could have functions with non primitive return values and custom merge functions...
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.
It's currently a very under-tested feature! I plan to use it more in the future though, it's essential for encoding proofs.
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.
It can be used to simulate the
choice
construct in Datalog literature by setting:merge old
(as is used in proofs)