17.3. Compound Predicates

Technically, a query consists of a single compound predicate. A compound predicate starts with an optional declaration of query variables. Its main part is a predicate list, which defines the properties of the compound predicate.

Queries and Compound Predicates
[58]Query::=CompoundPredicate 
[59]CompoundPredicate::={ VariableDeclarationNoInitializer ';' } PredicateList  
[60]PredicateList::=ConnectedPredicate { ',' ConnectedPredicate }  
[61]ContextPredicate::='(*' PredicateList '*)'  
[62]BranchPredicate::='[' PredicateList ']'  
[63]ConnectedPredicate::=ConditionPredicate | PrimaryPredicate { PrimaryPredicate }  
[64]ConditionPredicate::='(' Expression ')'  
[65]PrimaryPredicate::=ContextPredicate | BranchPredicate | SimplePredicate  

The in-parameter of a predicate list is the in-parameter of its first connected predicate which has an in-parameter, or the predicate list has no in-parameter if no such connected predicate exists. The out-parameter of the predicate list is the out-parameter of its last connected predicate which has an out-parameter, or the predicate list has no out-parameter if no such connected predicate exists.

A predicate list is fulfilled if and only if all of its contained connected predicates are fulfilled.

Context predicates and branch predicates inherit their in- and out-parameters from the contained predicate list. They are fulfilled if and only if the contained predicate list is fulfilled.

17.3.1. Places

A place denotes a set of predicate parameters which are associated with each other. A place also has a set of associated query variables. One of these query variables may be the label of the place. One of these query variables is the main variable of the place. Places may be node places, main variables of node places are bound to nodes of the current extent (Chapter 3, Data Model Interface).

Initially, a place is created for each predicate parameter, and the parameter is associated with this place. Later on, places my be merged, resulting in a single place which contains all associations of the merged places. Places are merged in two cases:

  1. If two places have the same label variable, they are merged.

  2. A predicate list may merge places of neighbouring primary predicates (Section 17.3.3, “Connecting Primary Predicates”).

Like a predicate, a place imposes conditions on its query variables which have to be fulfilled for the place to match for a binding of the variables.

The main variable is determined as follows:

  • If the place is a node place and has a label variable q whose values have to be wrapped in order to be represented as nodes (Section 3.1, “Compile-Time Model”), then an additional query variable is declared and associated with the place. It wraps the values of q. Its identifier is the identifier of q with the single character $ prepended. Its preliminary type is determined by the invocation of the method getWrapperClassFor of the current compile-time model (Section 3.1, “Compile-Time Model”) with the type of q as argument. The wrapper variable is the main variable of the place. For a binding of the query variables, the bound value of q must be equal to the result of the invocation of the method unwrapA on the current run-time model (Section 3.2, “Run-Time Model”) with the bound value of the wrapper variable as argument. A is the type affix (Section 6.1, “Type Affixes and Type Letters”) of the type of q.

  • Otherwise, if the place is a node place without label variable, and if there are associated predicate parameters whose values are not representable as nodes, an unnamed variable is declared implicitly, its type being the type of the first parameter (in order of association) which needs a wrapper. Now one proceeds as before, with q being replaced by the implicitly declared variable.

  • Otherwise, if the place is a node place, the main variable is declared implicitly, its preliminary type being Object.

  • Otherwise, the place is not a node place. If the place has a label, the main variable is the label variable. If the place has no label, the main variable is declared implicitly, its preliminary type being the type of the first parameter (in order of association).

For each associated predicate parameter, there is a query variable of suitable type. Depending on the type of the predicate parameters, a single query variable is sufficient for all parameters, or the compiler has to provide several distinct, implicitly declared query variables. The query variable for the parameters are determined as follows:

  • If there exist parameters of numeric type, let N be the first (in order of association) of these types. If the place is a node place, it follows from the previous statements that there is a wrapper variable which wraps a query variable s. Otherwise, if the place is not a node place, let s be the main variable. If s does not have a numeric type, a compile-time error occurs. Now for each parameter having a numeric type T, its query variable is determined:

    • If T and the type of some query variable v of the place are assignable to int, or if there exists a query variable v having type T, the query variable for the parameter is v.

    • Otherwise, an implicit query variable t is declared in the place, its type being T. This variable is the query variable for the parameter. For a binding of the query variables, the bound value of t, converted to the type of s by a casting conversion, has to be equal to the bound value of s in order for the place to match.

  • For each of the remaining parameters of non-numeric type T:

    • If the place has a wrapper variable and values of type T have to be wrapped, the preliminary type of the wrapper variable is replaced by the intersection (Section 6.2, “Intersection Types”) of the preliminary type and the type returned by the invocation of the method getWrapperClassFor of the current compile-time model (Section 3.1, “Compile-Time Model”) with T as argument. The preliminary type of the wrapped variable is replaced by the intersection of the preliminary type and T. The wrapped variable is the query variable for the parameter.

    • Otherwise, if the place has a wrapper variable, but values of type T need not be wrapped, or if the place is not a node place, the preliminary type of the main variable is replaced by the intersection of the preliminary type and T. The main variable is the query variable for the parameter.

Afterwards, the actual types of query variables are set to their preliminary types.

When we speak of the bound value of a predicate parameter in the context of a binding of query variables, the bound value of the query variable associated with this predicate parameter is to be understood.

17.3.2. Connected Predicates

A connected predicate is either a single condition predicate, or a list of primary predicates. If it is a condition predicate, it has no in- and out-parameters, and it is fulfilled if and only if the contained expression evaluates to true. It is a compile-time error if the type of this expression is not boolean.

If the connected predicate consists of a list of primary predicates, its in-parameter is the in-parameter of the first primary predicate which has an in-parameter and which is not a context predicate or a branch predicate, or it has no in-parameter if no such predicate exists. The same holds for the out-parameter, with the role of the first primary predicate replaced by the last primary predicate. A list of primary predicates is fulfilled if and only if all of its primary predicates are fulfilled.

A list of primary predicates also defines the node places: A place is a node place if and only if an in- or out-parameter of a primary predicate of a list is associated with the place.

17.3.3. Connecting Primary Predicates

A list of primary predicates is connected by a pairwise connection of neighbouring primary predicates. The primary predicates of an ordered pair (L, R) are neighbouring if L is not a branch predicate and L textually precedes R with at most branch predicates inbetween. For every ordered pair (L, R) of neighbouring primary predicates, the connection is established as follows:

  • If L has a closed out-parameter and R has a closed in-parameter, an implicit standard edge predicate (Section 17.5.5, “Standard Edge Predicates”) is inserted. If R is a branch predicate, the standard edge is a forward branch edge, otherwise it is a forward successor edge. The in-parameter of the edge predicate is associated with the place of L's out-parameter, the out-parameter of the edge predicate is associated with the place of R's in-parameter.

  • Otherwise, if L has an out-parameter and R has an in-parameter, their places are merged to a single place.

  • Otherwise, if L has an open out-parameter and R has no in-parameter, or if L has no out-parameter and R has an open in-parameter, a compile-time error occurs.

  • Otherwise, L and R are not connected.