A rule is a horn clause that has one predicate (or more; see below) as a head, and one or more literals in the body. The literals can be predicates, negated predicates, or constraints. All variables of a rule must be grounded, i.e., a variable must occur at least once as an argument of a positive predicate in the body of a rule. Soufflé permits arithmetic and string functors assuming that their arguments are grounded.

Consider the following example, that has relation `A` and `B` with two number attributes.

``````.decl A, B(x:number, y:number)  // declaration of relation B
B(x,y) :- A(x,y).            // rules of relation B
B(x,z) :- A(x,y), B(y,z).
.output B
``````

Relation `B` has two rules: `B(x,y) :- A(x,y).` and `B(x,y) :- A(x,y), B(y,z).` The first rule says, there is a tuple in `B` if this tuple shows up in `A`. The second rule says there is a tuple `(x,z)` in `B`, if there is a tuple in `(x,y)` in `A` and a tuple `(y,z)` in `B`.

For the first rule, variables `x` and `y` are grounded, since they show up as variables in the positive predicate `B(x,y)`. Similiar, the variables `x`, `y`, and `z` are grounded because they occur in the positive predicates `A(x,y)` and `B(y,z)`.

However, note that the following example has an ungrounded variable:

``````.decl fib(idx:number, value:number)
fib(1,1).
fib(2,1).
fib(idx, x + y) :- fib(idx-1, x), fib(idx-2, y), idx <= 10.
.output fib
``````

The reason for this is that variable `idx` is not bound as an argument of a positive predicate in the body. In the example, variable `idx` occurrs in the predicates `fib(idx-1, x)` and `fib(idx-2, y)` but as arguments of a functor rather than as a direct argument. To make variable `idx` bound, we can shift the index by one and obtain a program whose variables are grounded:

``````.decl fib(idx:number, value:number)
fib(1,1).
fib(2,1).
fib(idx+1, x + y) :- fib(idx, x), fib(idx-1, y), idx <= 9.
.output fib
``````

And the program can produce the following output,

``````---------------
fib
idx	value
===============
1	1
2	1
3	2
4	3
5	5
6	8
7	13
8	21
9	34
10	55
===============
``````

### Type System

Variables in a rule have no explicit type declaration. Hence, Soufflé’s typesystem must automatically deduce the type of variables in a rule, depending on how they are used as arguments in predicates, functors, and constraints. Besides deducing their type, its other task is to check their appropiate use. Soufflé’s typesystem supports subtypes and union types, e.g., `.type A <: B` and `.type C = A|B` that makes the semantics of the typesystem more complex. For example,

``````.type A <: number
.type B <: number
.type C = A | B

.decl P(x:A)
.decl Q(x:B)
.decl R(x:C)

R(x) :- P(x), Q(x).
``````

In the above example, the type of variable is of type `C`. The reason is that the right-hand side of the body constraints the variable `x` such that `x` must be of type `A` / `B` or a supertype of them. The left-hand side constrain the type of variable to type `C` or a subtype of it. We also refer to grounded variable occurrences in the body of a rule as `sources` and the variable occurrences in the head of a rule / constraints / negation etc. as `sinks`. The reason for this is that sources may produce a concrete assignment and the the sinks use as concrete assignment.

### Negation in Rules

A rules of the form

``````CanRenovate(person, building) :- Owner(person, building), !Heritage(building).
``````

expresses the rule that an owner can renovate a building with the condition that the building is not classified as heritage. Thus the literal “Heritage(building)” is negated (via “!”) in the body of the rule. Not all negations are semantically permissible. For example,

``````A(x) :- ! B(x).
B(x) :- ! A(x).
``````

is a circular definition. One cannot determine if anything belongs to the relation “A” without determining if it belongs to relation “B”. But to determine if it is a “B” one needs to determine if the item belongs to “A”. Such circular definitions are forbidden. Technically, rules involving negation must be stratifiable.

Negated literals do not bind variables. For example,

``````A(x,y) :- R(x), !S(y).
``````

is not valid as the set of values that “y” can take is not clear. This can be rewritten as,

``````A(x,y) :- R(x), Scope(y), !S(y).
``````

where the relation “Scope” defines the set of values that “y” can take.

``````A(x,y), C(x,y) :- B(x,y).
``````

which is syntactic sugar for

``````A(x,y) :- B(x,y).
C(x,y) :- B(x,y).
``````

### Disjunction

A rule of the form

``````LivesAt(person, building) :-
Owner(owner, building),
( person=owner ; Housemate(owner, person) ).
``````

expresses the rule that a person lives in a building if they are the owner, or a housemate of the owner. Thus the conditions `person=owner` and `Housemate(owner, person)` are joined by `;` to indicate that either must hold.

### Query Plan

Rules may have qualifiers, which are used to change the execution behavior / semantics. Qualifiers are used to set a query plan for a rule. The qualifer `.plan` let’s the programmer chose a query plan for a rule.

## Syntax

In the following, we define rule declarations in Soufflé more formally using syntax diagrams and EBNF. The syntax diagrams were produced with Bottlecaps.

### Rule

A rule has one or more heads followed by symbol `:-` and a disjunctive term. A query plan is optional for a rule. ``````rule ::= atom ( ',' atom )* ':-' disjunction '.' query_plan?
``````

### Qualified Name

A qualified name is a sequence of identifiers separated by `.` to disambiguate relations that are instantiated by components. ``````qualified_name ::= IDENT ( '.' IDENT )*
``````

### Atom

An atom consists of a relation name followed by comma-separated arguments in parenthesis. ``````atom ::= qualified_name '(' ( argument ( ',' argument )* )? ')'
``````

### Disjunction

A disjunction is a list of conjunction separated by ‘;’. ``````disjunction ::= conjunction ( ';' conjunction )*
``````

### Conjunction

A conjunctive term is a list of (negated) atoms / constraints / disjunctions separated by ‘,’. ``````conjunction ::= '!'* ( atom | constraint | '(' disjunction ')' ) ( ',' '!'* ( atom | constraint | '(' disjunction ')' ) )*
``````

### Query Plan

A query plan gives for each version of a rule a permutation. The permutation dictates the execution order in the loop nest. ``````query_plan ::= '.plan' NUMBER ':' '(' ( NUMBER ( ',' NUMBER )* )? ')' ( ',' NUMBER ':' '(' ( NUMBER ( ',' NUMBER )* )? ')' )*
``````