Copyright © 1998, 2001 by Ian Horswill, see comment within this file.

New Page 4

The rules macro

Programmers typically write girl code by defining signals in terms of other signals.  This supports a "backward-chaining" style of programming where defines propositions in terms of necessary and sufficient conditions.  In this case, the definitions of the propositions (their necessary and sufficient conditions) are explicit in the code, but their entailments (what you can infer from a proposition) are left implicit; to know the entailment of a proposition, you have to look at the code for all the other propositions to find where it's used.

It is often more convenient to specify a set of propositions in terms of their entailments rather than their definitions.  The rules macro allows you to define a set of propositions and their entailments using a set of if/then rules like you would find in a production system.  Girl then solves for their definitions at compile time.

Macro syntax

(rules rule ...)
(rule rule)
Returns a signal that implements the specified rules.

Rule syntax

(if signal-expression  consequent)
(when
signal-expression  consequents ...)
Runs or activates consequents on ever clock tick in when signal-expression evaluates to true.
(unless signal-expression  consequents ...)
Runs or activates consequents on ever clock tick in when signal-expression evaluates to false.
(let ((variable  value  declarations ...)
      
...
 
rules ...)
(let* ((
variable  value  declarations ...)
       
...
 
rules ...)
(letrec ((
variable  value  declarations ...)
         
...
 
rules ...)
Runs all rules within a lexical scope that includes the specified variables.  Note that the declarations are optional.

Consequent syntax

The consequent of a rule may be:

Another rule (including let, let*, or letrec forms containing rules)
In this case, the subrule runs whenever the parent rule is true.
An accumulator
This is a signal created with the accumulate procedure.  Accumulators are signals that get their inputs from rules or from signals that use the drives declaration.
The result of a call to (proposition)
This is just an easy way to get an accumulator that is a Boolean and takes the or of its inputs.
(set! register  signal)
The register is set to the current value of signal whenever the test of the rule is true.
(action  args ...)
Calls action using circuit semantics.  The action (plan, behavior, etc.) is allowed to run and its arguments are set to the values of the signal expressions args.  If the rule's test becomes false, then the action will stop running unless something else (another rule, a plan, an active-when clause, etc.) enables it.  Note that this does make it hard to tell if the action is trying to stop itself.

The following signal procedures are also exported by the plans package specifically for use as rule consequents:

(start! action  args ...)
Whenever the test of the rule is true, the action (plan, behavior, generic action, etc.) is started and its arguments are set to the current values of the specified signals.  The action continues to run until explicitly stopped or until it terminates itself, regardless of whether the test continues to be true.  If the test of the rule continues to be true, it will continue to update the arguments to track changes in the signals.  However, the action is not continually restarted.  This only matters when the action is a plan; it means the plan is not continually reset to its beginning.  If the rule's test is true when the action tries to terminate itself, the action will immediately restart itself.  In the case of plans, they will reset reset to their beginnings.
(stop! action)
Whenever the test of the rule is true, the action is stopped.  Note that this can only cancel an action that is running because it was started with start! or called from another plan; it cannot override an active-when clause in the plan.

In addition, the role-passing package exports start-indirect! and stop-indirect!, which allow indirection through the role binding mechanisms.

The ruleset macro

Note: The ruleset macro is now deprecated.  Use rules instead.

Macro syntax

Rules are defined with the ruleset macro.

(ruleset (propositions ...)
   rules ...)
This creates a set of signals to represent propositions and rules.   It returns propositions ... as a list.

Rule syntax

The rules within a ruleset expression can be any of the following forms:

(if signal consequent alternative)
Signal is tested on every clock cycle.  When it is true, consequent is true.  When it is false, alternative is true.
(when signal consequents ...)
Signal is tested on every clock cycle.  When it is true, all the consequents are made true.  This rule has no effect when signal is false.
(unless signal consequents ...)
Signal is tested on every clock cycle.  When it is false, all the consequents are made true.  This rule has no effect when signal is true.