package de.unisiegen.tpml.core.bigstep ; import java.lang.reflect.Method ; import de.unisiegen.tpml.core.AbstractProofRule ; import de.unisiegen.tpml.core.AbstractProofRuleSet ; import de.unisiegen.tpml.core.languages.Language ; /** * Abstract base class for big step proof rule sets, that are used for the * {@link de.unisiegen.tpml.core.bigstep.BigStepProofModel}s. * * @author Benedikt Meurer * @author Christian Fehler * @version $Rev:377M $ * @see de.unisiegen.tpml.core.AbstractProofRuleSet * @see de.unisiegen.tpml.core.bigstep.BigStepProofModel */ public abstract class AbstractBigStepProofRuleSet extends AbstractProofRuleSet { // // Constructor (protected) // /** * Allocates a new <code>AbstractBigStepProofRuleSet</code> for the * specified <code>language</code>. * * @param language the {@link Language} to which the big step proof rules in * this set belong. * @throws NullPointerException if <code>language</code> is * <code>null</code>. */ protected AbstractBigStepProofRuleSet ( Language language ) { super ( language ) ; } // // Rule registration // /** * Convenience wrapper for the {@link #register(int, String, Method, Method)} * method, which simply passes <code>null</code> for the * <code>updateMethod</code> parameter. The rule is prepended to the list, * which is important for guessing, as the last registered proof rule will be * used first when guessing. So, for example, for the big step interpreter, * the <b>(APP)</b> must be registered first. * * @param group the group id of the big step rule, see the description of the * {@link AbstractProofRule#getGroup()} method for details. * @param name the name of the big step proof rule to create. * @param applyMethod the implementation of the apply method for the big step * interpreter. * @throws NullPointerException if <code>name</code> or * <code>applyMethod</code> is <code>null</code>. * @see #register(int, String, Method, Method) */ protected void register ( int group , String name , Method applyMethod ) { register ( group , name , applyMethod , null ) ; } /** * Registers the rule with the given <code>name</code> and the * <code>applyMethod</code> and <code>updateMethod</code>. The * <code>updateMethod</code> may be <code>null</code>. The rule is * prepended to the list, which is important for guessing, as the last * registered proof rule will be used first when guessing. So, for example, * for the big step interpreter, the <b>(APP)</b> must be registered first. * * @param group the group id of the big step rule, see the description of the * {@link AbstractProofRule#getGroup()} method for details. * @param name the name of the rule. * @param applyMethod the <code>apply()</code> method. * @param updateMethod the <code>update()</code> method or <code>null</code>. * @throws NullPointerException if <code>name</code> or * <code>applyMethod</code> is <code>null</code>. * @see #register(int, String, Method) * @see AbstractProofRuleSet#register(AbstractProofRule) */ protected void register ( int group , String name , final Method applyMethod , final Method updateMethod ) { if ( name == null ) { throw new NullPointerException ( "name is null" ) ; //$NON-NLS-1$ } if ( applyMethod == null ) { throw new NullPointerException ( "applyMethod is null" ) ; //$NON-NLS-1$ } // register a new proof rule with the name and methods register ( new AbstractBigStepProofRule ( group , name ) { @ Override protected void applyInternal ( BigStepProofContext context , BigStepProofNode node ) throws Exception { applyMethod.invoke ( AbstractBigStepProofRuleSet.this , context , node ) ; } @ Override protected void updateInternal ( BigStepProofContext context , BigStepProofNode node ) throws Exception { if ( updateMethod != null ) { updateMethod.invoke ( AbstractBigStepProofRuleSet.this , context , node ) ; } } } ) ; } /** * Convenience wrapper for the {@link #register(int, String, Method)} method, * which determines the {@link Method} for the specified * <code>applyMethodName</code> and uses it for the <code>applyMethod</code>. * The rule is prepended to the list, which is important for guessing, as the * last registered proof rule will be used first when guessing. So, for * example, for the big step interpreter, the <b>(APP)</b> must be registered * first. * * @param group the group id of the big step rule, see the description of the * {@link AbstractProofRule#getGroup()} method for details. * @param name the name of the rule. * @param applyMethodName the name of the <code>apply</code> method. * @throws NullPointerException if either <code>name</code> or * <code>applyMethodName</code> is <code>null</code>. * @see #register(int, String, Method) */ protected void registerByMethodName ( int group , String name , String applyMethodName ) { register ( group , name , getMethodByName ( applyMethodName ) ) ; } /** * Convenience wrapper for the {@link #register(int, String, Method, Method)} * method, which determines the {@link Method}s for the specified * <code>applyMethodName</code> and <code>updateMethodName</code> and uses * them for the {@link Method} parameters. * * @param group the group id of the big step rule, see the description of the * {@link AbstractProofRule#getGroup()} method for details. * @param name the name of the rule. * @param applyMethodName the name of the <code>apply</code> method. * @param updateMethodName the name of the <code>update</code> method. * @throws NullPointerException if either <code>name</code>, * <code>applyMethodName</code> or <code>updateMethodName</code> * is <code>null</code>. * @see #register(int, String, Method, Method) */ protected void registerByMethodName ( int group , String name , String applyMethodName , String updateMethodName ) { register ( group , name , getMethodByName ( applyMethodName ) , getMethodByName ( updateMethodName ) ) ; } /** * 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 #register(int, String, Method, Method) * @see AbstractProofRuleSet#unregister(AbstractProofRule) */ protected void unregister ( String name ) { unregister ( getRuleByName ( name ) ) ; } /** * Returns the {@link Method} with the specified <code>methodName</code>, * which has two parameters, a <code>BigStepProofContext</code> and a * <code>BigStepProofNode</code>. * * @param methodName the name of the method to look up. * @return the {@link Method} with the specified <code>methodName</code>. * @throws NullPointerException if <code>methodName</code> is * <code>null</code>. * @see #registerByMethodName(int, String, String) * @see #registerByMethodName(int, String, String, String) */ private Method getMethodByName ( String methodName ) { if ( methodName == null ) { throw new NullPointerException ( "methodName is null" ) ; //$NON-NLS-1$ } try { // lookup the method with the parameters BigStepProofContext and // BigStepProofNode return getClass ( ).getMethod ( methodName , new Class [ ] { BigStepProofContext.class , BigStepProofNode.class } ) ; } catch ( RuntimeException e ) { // just re-throw the exception throw e ; } catch ( Exception e ) { // translate the exception to a runtime exception throw new RuntimeException ( "Method " + methodName + " not found" , e ) ; //$NON-NLS-1$ //$NON-NLS-2$ } } }