package typing;
import java.util.Collection;
import java.util.LinkedList;
import expressions.Lambda;
import expressions.And;
import expressions.Application;
import expressions.Condition;
import expressions.Constant;
import expressions.Expression;
import expressions.Identifier;
import expressions.InfixOperation;
import expressions.Let;
import expressions.LetRec;
import expressions.Or;
import expressions.Recursion;
import expressions.Tuple;
/**
* Represents a type rule.
*
* @author Benedikt Meurer
* @version $Id$
*/
public final class Rule {
/**
* Returns the name of the type rule.
*
* @return the name of the type rule.
*/
public String getName() {
return this.name;
}
/**
* Returns <code>true</code> if <code>obj</code>
* is the same type rule as this object.
*
* @param obj another object.
*
* @return <code>true</code> if <code>obj</code>
* is the same type rule as this object.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
// we have only a private constructor,
// so the comparison is simple here
return (this == obj);
}
/**
* Returns the string representation of the type rule.
*
* @return the string representation of the rule.
*
* @see #getName()
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "(" + getName() + ")";
}
/**
* The <b>(CONST)</b> type rule.
*/
public static final Rule CONST = new Rule("CONST");
/**
* The polymorphic <b>(P-CONST)</b> type rule.
*/
public static final Rule P_CONST = new Rule("P-CONST");
/**
* The <b>(ID)</b> type rule.
*/
public static final Rule ID = new Rule("ID");
/**
* The polymorphic <b>(P-ID)</b> type rule.
*/
public static final Rule P_ID = new Rule("P-ID");
/**
* The <b>(APP)</b> type rule.
*/
public static final Rule APP = new Rule("APP");
/**
* The <b>(COND)</b> type rule.
*/
public static final Rule COND = new Rule("COND");
/**
* The <b>(ABSTR)</b> type rule.
*/
public static final Rule ABSTR = new Rule("ABSTR");
/**
* The <b>(LET)</b> type rule.
*/
public static final Rule LET = new Rule("LET");
/**
* The polymorphic <b>(P-LET)</b> type rule.
*/
public static final Rule P_LET = new Rule("P-LET");
/**
* The <b>(LET-REC)</b> type rule.
*/
public static final Rule LET_REC = new Rule("LET-REC");
/**
* The <b>(REC)</b> type rule.
*/
public static final Rule REC = new Rule("REC");
/**
* The <b>(INFIX)</b> type rule.
*/
public static final Rule INFIX = new Rule("INFIX");
/**
* The <b>(AND)</b> type rule.
*/
public static final Rule AND = new Rule("AND");
/**
* The <b>(OR)</b> type rule.
*/
public static final Rule OR = new Rule("OR");
/**
* The <b>(TUPLE)</b> type rule.
*/
public static final Rule TUPLE = new Rule("TUPLE");
/**
* Returns the list of all available rules.
*
* @return the list of all available rules.
*/
public static Collection<Rule> getAllRules() {
LinkedList<Rule> rules = new LinkedList<Rule>();
rules.add(CONST);
rules.add(P_CONST);
rules.add(ID);
rules.add(P_ID);
rules.add(APP);
rules.add(COND);
rules.add(ABSTR);
rules.add(LET);
rules.add(P_LET);
rules.add(LET_REC);
rules.add(REC);
rules.add(INFIX);
rules.add(AND);
rules.add(OR);
rules.add(TUPLE);
return rules;
}
/**
* Returns the type rule that can be applied to
* the <code>expression</code> in the specified
* type <code>environment</code>.
*
* @param expression the {@link expressions.Expression} for which
* to determine the type {@link Rule}.
* @param environment the type {@link Environment}.
*
* @return the type rule for <code>expression</code> in the
* <code>environment</code>.
*
* @throws UnknownIdentifierException if <code>expression</code> is
* an unknown identifier.
*/
public static Rule getRuleForExpression(Expression expression, Environment environment) throws UnknownIdentifierException {
if (expression instanceof Constant) {
Type type = Type.getTypeForExpression(expression);
return (type instanceof PolyType) ? Rule.P_CONST : Rule.CONST;
}
else if (expression instanceof Identifier) {
Type type = environment.get(((Identifier)expression).getName());
return (type instanceof PolyType) ? Rule.P_ID : Rule.ID;
}
else if (expression instanceof Application) {
return Rule.APP;
}
else if (expression instanceof Condition) {
return Rule.COND;
}
else if (expression instanceof Lambda) {
return Rule.ABSTR;
}
else if (expression instanceof Let) {
Expression e1 = ((Let)expression).getE1();
return e1.isValue() ? Rule.P_LET : Rule.LET;
}
else if (expression instanceof LetRec) {
return Rule.LET_REC;
}
else if (expression instanceof Recursion) {
return Rule.REC;
}
else if (expression instanceof InfixOperation) {
return Rule.INFIX;
}
else if (expression instanceof And) {
return Rule.AND;
}
else if (expression instanceof Or) {
return Rule.OR;
}
else if (expression instanceof Tuple) {
return Rule.TUPLE;
}
else {
throw new IllegalArgumentException("Invalid expression " + expression);
}
}
private Rule(String name) {
this.name = name;
}
// member attributes
private String name;
}