More on the CHR Language

## 9.5 More on the CHR Language

- Declarations
- ECLiPSe Clauses
- Options
- CHR Built-In Predicates

The following subsections describe declarations, clauses, options and built-in predicates of the CHR language.

### 9.5.1 Declarations

Declarations name the constraint handler, its constraints, specify their syntax and use in built-in labeling.

Declaration | ::= | `handler` Name`.`
| ::= | `constraints` SpecList`.`
| ::= | `operator(`Precedence`,`Associativity`,`Name`).`
| ::= | `label_with` Constraint `if` Guard`.`

The optional `handler` declaration documents the name of the constraint handler. Currently it can be omitted, but will be useful in future releases for combining handlers.

The mandatory `constraints` declaration lists the constraints defined in the handler. A “SpecList” is a list of Name`/`Arity pairs for the constraints. The declaration of a constraint must appear before the constraint handling rules and ECLiPSe clauses which define it, otherwise a syntax error is raised. There can be several constraints declarations.

The optional `operator` declaration declares an operator, with the same arguments as op/3 in ECLiPSe. However, while the usual operator declarations are ignored during compilation from chr to pl files, the CHR operator declarations are taken into account (see also the subsection on clauses).

The optional `label_with` declaration specifies when the ECLiPSe clauses of a constraint can be used for built-in labeling (see subsection on labeling).

Example, contd.: The first lines of the minmax handler are declarations:

    handler minmax.

    constraints leq/2, neq/2, minimum/3, maximum/3.

    operator(700, xfx, leq).
    operator(700, xfx, neq).

### 9.5.2 ECLiPSe Clauses

A constraint handler program may also include arbitrary ECLiPSe code (written with the four operators `:- /[1,2]` and `?- /[1,2]`).

Clause | ::= | Head `:-` Body.
| ::= | Head `?-` Body.
| ::= | `:-` Body.
| ::= | `?-` Body.

Note that :-/1 and ?-/1 behave different from each other in CHR programs. Clauses starting with :- are copied into the pl file by the CHR compiler, clauses with ?- are executed by the compiler. As the op declaration needs both copying and execution, we have introduced the special operator declaration (see previous subsection on declarations). A "Head" can be a "Constraint", such clauses are used for built-in labeling only (see section on labeling).

### 9.5.3 Options

The option command allows the user to set options in the CHR compiler.

Option | ::= | `option(`Option`,` On_or_off`).`

Options can be switched on or off. Default is on. Advanced users may switch an option off to improve the efficiency of the handler at the cost of safety. Options are:

- `check_guard_bindings`: When executing a guard, it is checked that no global variables (variables of the rule heads) are touched (see subsection on how CHRs work). If the option is on, guards involving cut, if-then-else or negation may not work correctly if a global variable has been touched before. If switched off, guard checking may be significantly faster, but only safe if the user makes sure that global variables are not touched. To ensure that the variables are sufficiently bound, tests like nonvar/1 or delays can be added to the predicates used in the guards.
- `already_in_store`: Before adding a user-defined constraint to the constraint store, it is checked if there is an identical one already in the store. If there is, the new constraint needs not to be added. The handling of the duplicate constraint is avoided. This option can be set to `off`, because the checking may be too expensive if duplicate constraints rarely occur. Specific duplicate constraints can still be removed by a simpagation rule of the form `Constraint \ Constraint <=> true`.
- `already_in_heads`: In two-headed simplification rules, the intention is often to simplify the two head constraints into a stronger version of one of the constraints. However, a straightforward encoding of the rule may include the case where the new constraint is identical to the corresponding head constraint. Removing the head constraint and adding it again in the body is inefficient and may cause termination problems. If the `already_in_heads` option is on, in such a case the head constraint is kept and the body constraint ignored. Note however, that this optimization currently only works if the body constraint is the only goal of the body or the first goal in the conjunction comprising the body of the rule (see the example handler for domains). The option may be too expensive if identical head-body constraints rarely occur.
- Note that the ECLiPSe environment flag `debug_compile` (set and unset with `dbgcomp` and `nodbgcomp`) is also taken into account by the CHR compiler. The default is on. If switched off, the resulting code is more efficient, but cannot be debugged anymore (see section 9.8).

### 9.5.4 CHR Built-In Predicates

There are some built-in predicates to compile chr files, for debugging, built-in labeling and to inspect the constraint store and remove its constraints:

- chr2pl(File) compiles “File” from a chr to pl file.
- chr(File) compiles “File” from a chr to pl file and loads the pl file.
- `chr_trace` activates the standard debugger and shows constraint handling.
- `chr_notrace` stops either debugger.
- chr_labeling provides built-in labeling (see corresponding subsection).
- chr_label_with(Constraint) checks if “Constraint” satisfies a label_with declaration (used for built-in labeling).
- chr_resolve(Constraint) uses the ECLiPSe clauses to solve a constraint (used for built-in labeling).
- chr_get_constraint(Constraint) gets a constraint unifying with “Constraint” from the constraint store and removes it, gets another constraint on backtracking.
- chr_get_constraint(Variable,Constraint) is the same as chr_get_constraint/1 except that the constraint constrains the variable “Variable”.