package smallstep;
import java.util.HashMap;
import common.ProofRule;
/**
* Represents a small step proof rule.
*
* @author Benedikt Meurer
* @version $Id$
*/
final class SmallStepProofRule extends ProofRule {
//
// Constants
//
/**
* The definition of the small step rules as pairs of
* strings and booleans, where the string is the name
* of the rule and the boolean value indicates whether
* the rule is an axiom or a meta rule.
*
* The EXN rules are generated automatically for each
* meta rule.
*/
private static final Object[] RULES = {
// application rules
"APP-LEFT", false,
"APP-RIGHT", false,
"BETA-V", true,
// condition rules
"COND-EVAL", false,
"COND-FALSE", true,
"COND-TRUE", true,
// let rules
"LET-EVAL", false,
"LET-EXEC", true,
// operator rules
"BOP", true,
"UOP", true,
// recursion rules
"UNFOLD", true,
// imperative rules
"ASSIGN", true,
"DEREF", true,
"REF", true,
"SEQ-EVAL", false,
"SEQ-EXEC", true,
"WHILE", true,
"COND-1-EVAL", false,
"COND-1-FALSE", true,
"COND-1-TRUE", true,
// tuple rules
"FST", true,
"SND", true,
"PROJ", true,
"TUPLE", false,
// list rules
"CONS", true,
"LIST", false,
"HD", true,
"TL", true,
"HD-EMPTY", true,
"TL-EMPTY", true,
"IS-EMPTY-TRUE", true,
"IS-EMPTY-FALSE", true,
// && rules
"AND-EVAL", false,
"AND-FALSE", true,
"AND-TRUE", true,
// || rules
"OR-EVAL", false,
"OR-FALSE", true,
"OR-TRUE", true,
};
//
// Class attributes
//
/**
* A mapping of rule names to rules, generated automatically
* from the {@link #RULES} when the class is loaded.
*
* @see #RULES
*/
private static HashMap<String, SmallStepProofRule> rules;
//
// Class loading
//
static {
// generate the rules mapping from the RULES array
rules = new HashMap<String, SmallStepProofRule>();
for (int n = 0; n < RULES.length; n += 2) {
// generate the rule
boolean axiom = ((Boolean)RULES[n + 1]).booleanValue();
String name = (String)RULES[n + 0];
// determine the associated EXN rule
SmallStepProofRule exnRule = null;
if (!axiom) {
// generate the associated EXN rule
exnRule = new SmallStepProofRule(axiom, name + "-EXN", null);
rules.put(name + "-EXN", exnRule);
}
// generate the proof rule
rules.put(name, new SmallStepProofRule(axiom, name, exnRule));
}
}
//
// Class methods
//
/**
* Returns the <code>SmallStepProofRule</code> with
* the specified <code>name</code>.
*
* @return the <code>SmallStepProofRule</code> with
* the specified <code>name</code>.
*
* @throws IllegalArgumentException if the <code>name</code> does not
* refer to a valid small step rule.
*/
static SmallStepProofRule getRule(String name) {
SmallStepProofRule rule = rules.get(name);
if (rule == null) {
throw new IllegalArgumentException("name is invalid");
}
else {
return rule;
}
}
/**
* Returns all available <code>SmallStepProofRule</code>s,
* except the <b>EXN</b> rules.
*
* @return all available <code>SmallStepProofRule</code>s.
*/
static SmallStepProofRule[] getRules() {
SmallStepProofRule[] rules = new SmallStepProofRule[RULES.length / 2];
for (int n = 0; n < rules.length; ++n) {
rules[n] = getRule((String)RULES[n * 2]);
}
return rules;
}
//
// Attributes
//
/**
* The <b>EXN</b> rule associated with this meta-rule. This
* is <code>null</code> for axioms and exception rules.
*
* @see #getExnRule()
*/
private SmallStepProofRule exnRule;
//
// Constructor (private)
//
/**
* Allocates a new small step proof rule with the given
* <code>name</code>. If <code>axiom</code> is <code>true</code>
* the rule has no premises.
*
* @param axiom whether the rule has no premises.
* @param name the name of the small step rule.
* @param exnRule the <b>EXN</b> rule for this meta rule.
*/
private SmallStepProofRule(boolean axiom, String name, SmallStepProofRule exnRule) {
super(axiom, name);
this.exnRule = exnRule;
}
//
// Primitives
//
/**
* Returns the <b>EXN</b> rule for this meta rule. If this
* rule is an axiom or an <b>EXN</b> rule itself, this
* method will return a reference to this rule (this does
* not really make sense, but its convenient to use).
*
* @return the <b>EXN</b> rule for this meta rule.
*/
public SmallStepProofRule getExnRule() {
if (this.exnRule != null) {
return this.exnRule;
}
else {
return this;
}
}
}