From c19a6b4d860947d70253b96713a4191fa3b2e590 Mon Sep 17 00:00:00 2001 From: Ziyang Li Date: Wed, 12 Apr 2023 01:14:08 -0400 Subject: [PATCH] Adding resource folder --- res/.keep | 0 res/icons/scallop-logo-transp-128.png | Bin 0 -> 6969 bytes res/icons/scallop-logo-ws-512.png | Bin 0 -> 24610 bytes res/notes/design/grammar.md | 85 ++++++++++++++++++++++++++ res/notes/design/group_by.md | 53 ++++++++++++++++ 5 files changed, 138 insertions(+) create mode 100644 res/.keep create mode 100644 res/icons/scallop-logo-transp-128.png create mode 100644 res/icons/scallop-logo-ws-512.png create mode 100644 res/notes/design/grammar.md create mode 100644 res/notes/design/group_by.md diff --git a/res/.keep b/res/.keep new file mode 100644 index 0000000..e69de29 diff --git a/res/icons/scallop-logo-transp-128.png b/res/icons/scallop-logo-transp-128.png new file mode 100644 index 0000000000000000000000000000000000000000..456127e5ea2162e81e5d7479b457c4175b7e3343 GIT binary patch literal 6969 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 literal 0 HcmV?d00001 diff --git a/res/notes/design/grammar.md b/res/notes/design/grammar.md new file mode 100644 index 0000000..2475488 --- /dev/null +++ b/res/notes/design/grammar.md @@ -0,0 +1,85 @@ +# Grammar + +``` +SCALLOP_PROGRAM ::= ITEM* + +ITEM ::= TYPE_DECL + | RELATION_DECL + | CONST_DECL + | QUERY_DECL + +TYPE ::= u8 | u16 | u32 | u64 | u128 | usize + | i8 | i16 | i32 | i64 | i128 | isize + | f32 | f64 | char | bool + | String + | CUSTOM_TYPE_NAME + +TYPE_DECL ::= type CUSTOM_TYPE_NAME = TYPE + | type CUSTOM_TYPE_NAME <: TYPE + | type ENUM_TYPE_NAME = VARIANT1 [= VAL1] | VARIANT2 [= VAL2] | ... + | type RELATION_NAME(TYPE*) + | type RELATION_NAME(VAR1: TYPE1, VAR2: TYPE2, ...) + +CONST_DECL ::= const CONSTANT_NAME : TYPE = CONSTANT + | const CONSTANT_NAME1 [: TYPE1] = CONSTANT1, CONSTANT_NAME2 [: TYPE2] = CONSTANT2, ... + +RELATION_DECL ::= FACT_DECL + | FACTS_SET_DECL + | RULE_DECL + +CONSTANT ::= true | false | NUMBER_LITERAL | STRING_LITERAL + +CONST_TUPLE ::= CONSTANT | (CONSTANT1, CONSTANT2, ...) + +FOREIGN_FN ::= hash | string_length | string_concat | substring | abs + +BIN_OP ::= + | - | * | / | % | == | != | <= | < | >= | > | && | || | ^ + +UNARY_OP ::= ! | - + +CONST_EXPR ::= CONSTANT + | CONST_EXPR BIN_OP CONST_EXPR | UNARY_OP CONST_EXPR + | $ FOREIGN_FN(CONST_EXPR*) + | if CONST_EXPR then CONST_EXPR else CONST_EXPR + | ( CONST_EXPR ) + +TAG ::= true | false | NUMBER_LITERAL // true/false is for boolean tags; NUMBER_LITERAL is used for probabilities + +FACT_DECL ::= rel RELATION_NAME(CONST_EXPR*) // Untagged fact + | rel TAG :: RELATION_NAME(CONST_EXPR*) // Tagged fact + +FACTS_SET_DECL ::= rel RELATION_NAME = {CONST_TUPLE1, CONST_TUPLE2, ...} // Untagged tuples + | rel RELATION_NAME = {TAG1 :: CONST_TUPLE1, TAG2 :: CONST_TUPLE2, ...} // Tagged tuples + | rel RELATION_NAME = {TAG1 :: CONST_TUPLE1; TAG2 :: CONST_TUPLE2; ...} // Tagged tuples forming annotated disjunction + +EXPR ::= VARIABLE | CONSTANT + | EXPR BIN_OP EXPR | UNARY_OP EXPR + | $ FOREIGN_FN(EXPR*) + | if EXPR then EXPR else EXPR + | ( EXPR ) + +ATOM ::= RELATION_NAME(EXPR*) + +RULE_DECL ::= rel ATOM :- FORMULA | rel ATOM = FORMULA // Normal rule + | rel TAG :: ATOM :- FORMULA | rel TAG :: ATOM = FORMULA // Tagged rule + +FORMULA ::= ATOM + | not ATOM | ~ ATOM // negation + | FORMULA1, FORMULA2, ... | FORMULA and FORMULA | FORMULA /\ FORMULA // conjunction + | FORMULA or FORMULA | FORMULA \/ FORMULA // disjunction + | FORMULA implies FORMULA | FORMULA => FORMULA // implies + | CONSTRAINT | AGGREGATION + | ( FORMULA ) + +CONSTRAINT ::= EXPR // When expression returns a boolean value + +AGGREGATOR ::= count | sum | prod | min | max | exists | forall | unique + +AGGREGATION ::= VAR* = AGGREGATOR(VAR* : FORMULA) // Normal aggregation + | VAR* = AGGREGATOR(VAR* : FORMULA where VAR* : FORMULA) // Aggregation with group-by condition + | VAR* = AGGREGATOR[VAR*](VAR* : FORMULA) // Aggregation with arg (only applied to AGGREGATOR = min or max) + | VAR* = AGGREGATOR[VAR*](VAR* : FORMULA where VAR* : FORMULA) // Aggregation with arg and group-by condition (only applied to AGGREGATOR = min or max) + +QUERY_DECL ::= query RELATION_NAME + | query ATOM +``` diff --git a/res/notes/design/group_by.md b/res/notes/design/group_by.md new file mode 100644 index 0000000..f0d6678 --- /dev/null +++ b/res/notes/design/group_by.md @@ -0,0 +1,53 @@ +# Design of Group By + +## Examples + +### Example 1 + +The following count does not have a group by variable + +``` scl +rel num_cars(n) :- n = count(o: is_a(o, "car")) +``` + +### Example 2 + +The following count does have a group by variable `c`. +The body of the rule `is_a(o, "car"), color(o, c)` bounds two variables: `o` and `c`. +We want the variables that occur in the head that is not "to-aggregate" or "argument" values. + +``` scl +rel num_cars_of_color(c, n) :- n = count(o: is_a(o, "car"), color(o, c)) +``` + +### Example 3 + +The following count does have a group by variable `c`, note that `s` is not a group-by variable: + +``` scl +rel num_cars_of_color(c, n) :- n = count(o: is_a(o, "car"), color(o, c), shape(o, s)) +``` + +Although we have `shape(o, s)`, but we are not storing `s` in the head. +Therefore we do not treat `s` as a group-by variable. + +### Example 4 + +``` scl +rel num_cars_of_color(c, n) :- n = count(o: is_a(o, "car"), color(o, c) where c: all_colors(c)) +``` + +body_bounded_vars: o, c +group_by_bounded_vars: c +group_by_vars: c + +### Example 5 + +``` scl +rel eval_yn(e, b) :- b = exists(o: eval_obj(f, o) where e: exists_expr(e, f)) +``` + +body_bounded_vars: f, o +group_by_bounded_vars: e, f +group_by_vars: e +to_agg_vars: o