package de.unisiegen.tpml.core.smallstep ; import java.lang.reflect.InvocationTargetException ; import java.lang.reflect.Method ; import de.unisiegen.tpml.core.AbstractProofRule ; import de.unisiegen.tpml.core.AbstractProofRuleSet ; import de.unisiegen.tpml.core.expressions.Expression ; import de.unisiegen.tpml.core.interpreters.Store ; import de.unisiegen.tpml.core.languages.Language ; /** * Abstract base class for small step proof rule sets. * * @author Benedikt Meurer * @author Christian Fehler * @version $Rev:377 $ * @see de.unisiegen.tpml.core.AbstractProofRuleSet */ public abstract class AbstractSmallStepProofRuleSet extends AbstractProofRuleSet { // // Constructor (protected) // /** * Allocates a new <code>AbstractSmallStepProofRuleSet</code> for the * specified <code>language</code>. * * @param language the {@link Language} to which the small step proof rules in * this set belong. * @throws NullPointerException if <code>language</code> is * <code>null</code>. */ protected AbstractSmallStepProofRuleSet ( Language language ) { super ( language ) ; } // // Rule registration // /** * Convenience wrapper for the * {@link AbstractProofRuleSet#register(AbstractProofRule)} method, which * registers a new small step rule with the given <code>name</code>. * * @param group the group id of the small step rule, see the description of * the {@link AbstractProofRule#getGroup()} method for details. * @param name the name of the new small step rule. * @param axiom whether the new small step rule is an axiom. * @see SmallStepProofRule#isAxiom() */ protected void register ( int group , String name , boolean axiom ) { register ( new DefaultSmallStepProofRule ( group , name , axiom ) ) ; } /** * Convenience wrapper for the * {@link AbstractProofRuleSet#unregister(AbstractProofRule)} method, which * takes a rule name rather than an {@link AbstractProofRule} object. The * <code>rule</code> must have been previously registered. * * @param name the name of the rule to unregister. * @throws java.util.NoSuchElementException if no rule of the given * <code>name</code> was registered previously. * @throws NullPointerException if <code>name</code> is <code>null</code>. * @see AbstractProofRuleSet#unregister(AbstractProofRule) */ protected void unregister ( String name ) { unregister ( getRuleByName ( name ) ) ; } // // Evaluation // /** * Evaluates the next small steps for the <code>expression</code> and * returns the resulting {@link Expression}. The resulting {@link Store} is * available from the <code>context</code> and the * {@link de.unisiegen.tpml.core.ProofStep}s are added to the * <code>context</code> as well. This method determines the class of the * <code>expression</code> (i.e. <tt>Application</tt> for applications) * and then looks for a method named <tt>evaluateClass</tt> (i.e. * <tt>evaluateApplication</tt> for applications). The method is passed the * <code>context</code> and the <code>expression</code>. If no such * method exists, a method for the parent class of the <code>expression</code> * will be search and so on. If no method is found, the * <code>expression</code> will be returned and <code>context</code> will * not be modified. * * @param context the small step proof context. * @param expression the expression for which to evaluate the next small step. * @return the resulting expression. * @throws NullPointerException if <code>context</code> or * <code>expression</code> is <code>null</code>. * @see #lookupMethod(String, Class) */ public Expression evaluate ( SmallStepProofContext context , Expression expression ) { if ( context == null ) { throw new NullPointerException ( "context is null" ) ; //$NON-NLS-1$ } if ( expression == null ) { throw new NullPointerException ( "expression is null" ) ; //$NON-NLS-1$ } try { // determine the specific evaluate method Method method = lookupMethod ( "evaluate" , expression.getClass ( ) ) ; //$NON-NLS-1$ return ( Expression ) method.invoke ( this , context , expression ) ; } catch ( ClassCastException e ) { // no way to further evaluate the expression return expression ; } catch ( NoSuchMethodException e ) { // no way to further evaluate the expression return expression ; } catch ( RuntimeException e ) { // rethrow the exception, as something is really completely broken throw e ; } catch ( InvocationTargetException e ) { throw new RuntimeException ( e.getTargetException ( ).getMessage ( ) ) ; } catch ( Exception e ) { // rethrow as runtime exception, something is really completely broken throw new RuntimeException ( e ) ; } } /** * Looks up the method with the given <code>baseName</code> and * <code>clazz</code>. I.e. if <code>baseName</code> is <tt>"apply"</tt> * and <code>clazz</code> is <tt>Application</tt>, the method * <code>applyApplication()</code> will be looked up. * * @param baseName the basename of the method. * @param clazz class whose name is used in the method name. * @return the {@link Method} object. * @throws NoSuchMethodException if the method cannot be found. * @throws NullPointerException if <code>baseName</code> or * <code>clazz</code> is <code>null</code>. */ @ SuppressWarnings ( "unchecked" ) protected Method lookupMethod ( String baseName , Class clazz ) throws NoSuchMethodException { // try for this class and all super classes up to Expression Class tmpClazz = clazz ; while ( tmpClazz != Expression.class ) { // try to find a suitable method for ( Method method : getClass ( ).getMethods ( ) ) { if ( method.getName ( ).equals ( baseName + tmpClazz.getSimpleName ( ) ) ) { return method ; } } tmpClazz = tmpClazz.getSuperclass ( ) ; } throw new NoSuchMethodException ( baseName ) ; } }