# Bc_rule Syntax

## Bc_rule

Backward-chaining rules have four parts:

1. A unique name.
2. A use clause.
3. An optional when clause.
4. An optional with clause.

    bc_rule ::= IDENTIFIER NL INDENT
                    use
                    [when]
                    [with]
                DEINDENT

The `IDENTIFIER` is the unique name for this rule and is used as the corresponding Python function name in the generated <rb_name>_bc.py file and also for the Python function name of the plan function (if any) associated with the rule. This name will show up in stack traces associated with exceptions raised during inferencing or plan execution.

## Use Clause

The `use` clause is the then part of the rule. It identifies the goal that this rule is prepared to prove.

    use ::= 'use' IDENTIFIER '(' {pattern,} ')' ['taking' '(' <python_arg_spec> ')'] NL
          | 'use' IDENTIFIER '(' {pattern,} ')' NL
             INDENT 'taking' '(' <python_arg_spec> ')' NL
             DEINDENT

Notice that it uses a single `IDENTIFIER`. The rule base name is implied as the rule base category name (the name of the root rule base, see extending clause) for the rule base containing this rule.

### Taking Clause

The `use` clause also defines parameters to the plan function (if one is used for this rule) with the optional `taking` sub-clause.

The python_arg_spec is not parsed by Pyke, but simply copied to the output plan function. Do not use `$` with these parameter names (or their default values).

## When Clause

The `when` clause is the if part of the rule. It defines the premises that must be true for this rule to succeed.

If the `when` clause is omitted, the only requirement for the rule to succeed is that the `use` clause pattern matches the goal.

If the `when` clause is specified, the rule succeeds for each combination of true premises (see backtracking).

    when ::= 'when' NL INDENT
                 {bc_premise NL}
             DEINDENT

    bc_premise ::= ['!'] [ name '.' ] name '(' {pattern,} ')' [ plan_spec ]
                 | compound_premise
                 | python_premise

    name ::= IDENTIFIER
           | '$'IDENTIFIER

Here are the links to the definitions for pattern, compound_premise and python_premise.

If the bc_premise includes the `!`, an AssertionError will be raised if the premise fails on the first try. This can help in debugging.

Note

This does not apply when the premise fails on backtracking (in which case it has already succeeded at least once).

If a single name is used in the bc_premise, the rule base category for the current rule base (the root rule base name, see extending clause) is assumed.

If two names are used in the bc_premise, the first may name a rule base category or some other knowledge base.

If a rule base category name is used (or assumed), the currently active rule base for that category is used to prove the premise.

Note

If the rule base category name is omitted, and therefore assumed to be the current rule base's rule base category, the current rule base does not have to be the active rule base for that category. It could be the case that a derived rule base is the active rule base. In that case, the derived rule base is used to prove the premise.

In this way, different rules may be used to prove the same premise, depending upon which rule base has been activated.

### Plan_spec

A plan_spec is required for each premise that returns a subordinate plan. This shows what should be done with that subordinate plan function.

Thus, a rule's plan function is composed first of the collected python_statements taken from its plan_specs (as described below), followed by the python_statements within its with clause (if any). The inclusion of any plan_spec containing a python_statement will cause a plan function to be generated for this rule, even if the rule lacks a `with` clause.

    plan_spec ::= [ 'step' NUMBER ] NL INDENT
                      {<python_statement> NL}
                  DEINDENT
                | 'as' '$'IDENTIFIER NL

Within each python_statement, the subordinate plan function is indicated by `$$`. The result of this function may be assigned to a Python variable, but not a pattern variable (`$variable`). Parameters from the rule's `taking` clause may be passed on to the subordinate plan functions.

When multiple premises have python_statements in their plan_specs, the python_statements in plan_specs without a `step` clause are executed first in the order that they appear in the `when` clause.

Then the python_statements in plan_specs with a `step` clause are executed in ascending NUMBER sequence. It is permissible for the NUMBER to be negative or a float.

If the `as` clause is used, the plan function is bound to the pattern variable as a Python function, but not automatically executed. This allows you to call the function (or not) when and as many times as you please. The parameters required are defined in the `taking` clause of the rule used to prove the premise.

Note

Within a forall or notany premise, the only `plan_spec` that may be used is the `as` clause.

## With Clause

The `with` clause contains Python statements to include in the plan produced by this rule. These Python statements may include pattern variables whose values will be cooked into these statements when the plan is created.

    with ::= 'with' NL INDENT
                 {<python_statement> NL}
             DEINDENT

The python_statements are included in the rule's plan function after all of the calls to the subordinate plan functions made from the plan_specs in the when clause.

If the `with` clause is omitted, but the `when` clause has plan_specs (excluding the as clause), a plan function is still generated for this rule so that the subordinate plan functions are still called.

The python_statements are not parsed. They are simply scanned for `$` pattern variables that don't occur within string literals or comments. The values bound to these variables are cooked into the code to produce the plan.

Thus, all pattern variables used within python_statements (both in the `plan_specs` and the `when` clause) must be bound to a value. This value is a constant value that never changes for this plan.

Note

This occurs after the entire top-level goal is proven so that it is permissible to bind these pattern variables to values following the execution of the rule containing them.

Copyright © 2007-2009 Bruce Frederiksen

Page last modified Mon, Oct 27 2008.