package bigstep;
import common.ProofRule;
import common.ProofRuleException;
/**
* Abstract base class for big step proof rules.
*
* @author Benedikt Meurer
* @version $Id$
*/
public abstract class BigStepProofRule extends ProofRule {
//
// Constructor (protected)
//
/**
* Allocates a new <code>BigStepProofRule</code> with
* the specified <code>name</code>. If <code>axiom</code>
* is <code>true</code> the rule has no premises.
*
* @param axiom <code>true</code> if the rule is an axiom.
* @param name the name of the rule.
*/
protected BigStepProofRule(boolean axiom, String name) {
super(axiom, name);
}
//
// Primitives
//
/**
* Applies this big step proof rule to the specified <code>node</code>
* via the given <code>context</code>.
*
* @param context the big step proof context via which the application
* of this rule to the <code>node</code> should be
* performed.
* @param node the big step proof node to which to apply this rule.
* @throws ProofRuleException if this rule cannot be applied to the
* <code>node</code>.
* @throws ClassCastException TODO
* @throws ClassCastException if the <code>node</code>s expression is
* an instance of an unsupported class or
* a similar error condition. Will be
* automatically converted into a
* {@link ProofRuleException}.
* @throws NullPointerException if either <code>context</code> or
* <code>node</code> is <code>null</code>.
*/
public abstract void apply(BigStepProofContext context, BigStepProofNode node) throws ProofRuleException, ClassCastException;
/**
* Updates the specified <code>node</code> as part of a previous rule
* application for <code>context</code>. This method is only interesting
* for non-axiom rules, like (APP) or (LET), that need to update their
* created proof nodes even after applications of other proof rules to
* subtrees.
*
* This method is only invoked for proof nodes that are not already
* proven (see {@link common.ProofNode#isProven()}). If <code>node</code>
* is proven, this represents a bug in the big step proof model logic.
*
* @param context the main proof context, which was previously specified
* as parameter to an {@link #apply(BigStepProofContext, BigStepProofNode)}
* invokation on another proof node, possibly with another
* proof rule.
* @param node the {@link BigStepProofNode} that may need to be updated.
*/
public void update(BigStepProofContext context, BigStepProofNode node) {
// Nothing to do here, derived classes may implement this
// method if required, for example the (LET) rule
}
//
// Rule Allocation
//
/**
* Allocates a new <code>BigStepProofRule</code> with the
* specified <code>name</code>, that does nothing, meaning
* that {@link #apply(BigStepProofContext, BigStepProofNode)}
* and {@link #update(BigStepProofContext, BigStepProofNode)}
* are noops.
*
* @param name the name of the rule to allocate.
*
* @return a newly allocated <code>BigStepProofRule</code>
* with the specified <code>name</code>, that does
* nothing.
*
* @see #toExnRule(int)
*/
protected BigStepProofRule newNoopRule(String name) {
return new BigStepProofRule(false, name) {
public void apply(BigStepProofContext context, BigStepProofNode node) throws ProofRuleException, ClassCastException {
throw new ProofRuleException(node, this);
}
};
}
/**
* Translates this big step proof rule to an appropriate
* exception rule, with the given sub node index <code>n</code>.
* For example, for <b>(APP)</b>, this generates <b>(APP-EXN-n)</b>.
*
* @param n the index of the sub node, starting at <code>0</code>.
*
* @return the new {@link BigStepProofRule} for the exception.
*
* @throws IllegalArgumentException if <code>n</code> is negative.
* @throws IllegalStateException if this rule is an axiom, for which
* no exception rule can be generated.
*/
BigStepProofRule toExnRule(int n) {
if (n < 0) {
throw new IllegalArgumentException("n is negative");
}
if (isAxiom()) {
throw new IllegalStateException("rule is an axiom");
}
return newNoopRule(getName() + "-EXN-" + (n + 1));
}
}