TacletApp.java :  » Testing » KeY » de » uka » ilkd » key » rule » Java Open Source

Java Open Source » Testing » KeY 
KeY » de » uka » ilkd » key » rule » TacletApp.java
// This file is part of KeY - Integrated Deductive Software Design
// Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
//                         Universitaet Koblenz-Landau, Germany
//                         Chalmers University of Technology, Sweden
//
// The KeY system is protected by the GNU General Public License. 
// See LICENSE.TXT for details.
//
//

package de.uka.ilkd.key.rule;

import java.util.Arrays;
import java.util.HashSet;

import de.uka.ilkd.key.collection.ListOfString;
import de.uka.ilkd.key.collection.SLListOfString;
import de.uka.ilkd.key.java.ProgramElement;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.*;
import de.uka.ilkd.key.logic.op.*;
import de.uka.ilkd.key.logic.sort.ProgramSVSort;
import de.uka.ilkd.key.logic.sort.Sort;
import de.uka.ilkd.key.proof.*;
import de.uka.ilkd.key.rule.conditions.NewDepOnAnonUpdates;
import de.uka.ilkd.key.rule.inst.*;
import de.uka.ilkd.key.util.Debug;

/** 
 * A TacletApp object contains information required for a concrete application. 
 * These information may consist of
 * <ul>
 * <li> instantiations of the schemavariables </li>
 * <li> position of the find term </li>
 * </ul>
 * Its methods <code>complete</code> or <code>sufficientlyComplete</code> are
 * used to determine if the information is complete or at least sufficient
 * (can be completed using meta variables) complete, so that is can be
 * applied. 
 */
public abstract class TacletApp implements RuleApp {

    /** the taclet for which the application information is collected */
    private Taclet taclet;

    /** 
     * contains the instantiations of the schemavarioables of the
     * Taclet 
     */
    protected SVInstantiations instantiations;

    /**
     * constraint under which the taclet application can be performed
     */
    protected Constraint       matchConstraint;
  
    /**
     * metavariables that have been created during the matching
     */
    protected SetOfMetavariable matchNewMetavariables;

    /**
     * choosen instantiations for the if sequent formulas
     */
    ListOfIfFormulaInstantiation ifInstantiations = null;

    /** set of schemavariables that appear in the Taclet and need to be
     * instantiated but are not instantiated yet. This means
     * SchemaVariables in addrule-sections have to be ignored
     */
    private SetOfSchemaVariable missingVars = null;

    /** subset of missingVars that cannot be instantiated using
     * metavariables
     */
    private SetOfSchemaVariable neededMissingVars = null;

    /**
     * the instantiations of the following SVs must not be changed;
     * they must not be instantiated with metavariables either
     */
    protected SetOfSchemaVariable fixedVars = SetAsListOfSchemaVariable.EMPTY_SET;
    /**
     * the update context given by the current instantiations must not
     * be changed
     */
    protected boolean updateContextFixed = false;
    
    /** constructs a TacletApp for the given taclet, with an empty instantiation 
     *  map 
     */
    TacletApp(Taclet taclet) {
  this ( taclet, SVInstantiations.EMPTY_SVINSTANTIATIONS, Constraint.BOTTOM,
         SetAsListOfMetavariable.EMPTY_SET, null );
    }

    TacletApp ( Taclet                       taclet,
    SVInstantiations             instantiations,
    Constraint                   matchConstraint,
    SetOfMetavariable            matchNewMetavariables,
    ListOfIfFormulaInstantiation ifInstantiations ) {
  this.taclet                = taclet;
  this.instantiations        = instantiations;
  this.matchConstraint       = matchConstraint;
  this.matchNewMetavariables = matchNewMetavariables;
  this.ifInstantiations      = ifInstantiations;
    }

    /** constructs a TacletApp for the given taclet. With some information about
     * required instantiations.
     */
    TacletApp(Taclet taclet, SVInstantiations instantiations) {
  this ( taclet, instantiations, Constraint.BOTTOM,
         SetAsListOfMetavariable.EMPTY_SET, null );
    }

    /** collects all bound variables above the occurrence of the schemavariable
     * whose prefix is given
     * @param prefix the TacletPrefix of the schemavariable
     * @param instantiations the SVInstantiations so that the
     * find(if)-expression matches 
     * @return set of the bound variables 
     */
    protected static SetOfQuantifiableVariable 
  boundAtOccurrenceSet(TacletPrefix prefix,
           SVInstantiations instantiations) {  
  return collectPrefixInstantiations(prefix, 
             instantiations);
    }


    /** collects all bound variables above the occurrence of the schemavariable
     * whose prefix is given
     * @param prefix the TacletPrefix of the schemavariable
     * @param instantiations the SVInstantiations so that the
     * find(if)-expression matches 
     * @param pos the posInOccurrence describing the position of the
     * schemavariable 
     * @return set of the bound variables 
     */
    protected static SetOfQuantifiableVariable
  boundAtOccurrenceSet ( TacletPrefix     prefix,
             SVInstantiations instantiations,
             PosInOccurrence  pos ) {
    
  SetOfQuantifiableVariable result =
      boundAtOccurrenceSet(prefix, instantiations);
    
  if ( prefix.context () )
      result = result.union ( collectBoundVarsAbove ( pos ) );
    
  return result;    
    }


    /** collects all those logic variable that are instances of the variableSV
     * of the given prefix
     * @param pre the TacletPrefix of a SchemaVariable that is bound
     * @param instantiations the SVInstantiations to look at
     * @return the set of the logic variables whose elements are the
     * instantiations of a bound SchemaVariable appearing in the TacletPrefix
     */ 
    private static SetOfQuantifiableVariable collectPrefixInstantiations
  (TacletPrefix pre, SVInstantiations instantiations) {

  SetOfQuantifiableVariable instanceSet 
      = SetAsListOfQuantifiableVariable.EMPTY_SET;
  IteratorOfSchemaVariable it = pre.prefix().iterator();
  while (it.hasNext()) {
      SchemaVariable var = it.next();
      instanceSet = 
    instanceSet.add((LogicVariable)
        ((Term)instantiations.getInstantiation(var)).op());
  }
  return instanceSet;
    }


    /** returns the taclet the application information is collected for
     * @return the Taclet the application information is collected for
     */
    public Taclet taclet() {
  return taclet;
    }

    /** returns the rule the application information is collected for
     * @return the Rule the application information is collected for
     */
    public Rule rule() {
  return taclet;
    }

    /**
     * returns the instantiations for the application of the Taclet at the
     * specified position.
     * @return the SVInstantiations needed to instantiate the Taclet
     */
    public SVInstantiations instantiations() {
  return instantiations;
    }


    public Constraint       constraint () {
  return matchConstraint;
    }


    public SetOfMetavariable newMetavariables () {
  return matchNewMetavariables;
    }


    public MatchConditions  matchConditions () {
  return new MatchConditions ( instantiations   (),
             constraint       (),
             newMetavariables (),
                                     RenameTable.EMPTY_TABLE);
    }


    public ListOfIfFormulaInstantiation ifFormulaInstantiations () {
  return ifInstantiations;
    }


    /**
     * resolves collisions between bound SchemaVariables in an SVInstantiation
     *
     * @param insts the original SVInstantiations
     * @return the resolved SVInstantiations
     */
    protected static SVInstantiations resolveCollisionVarSV
  (Taclet taclet, SVInstantiations insts) {

  HashMapFromLogicVariableToSchemaVariable collMap =
      new HashMapFromLogicVariableToSchemaVariable();
  IteratorOfEntryOfSchemaVariableAndInstantiationEntry it = 
      insts.pairIterator();
  while (it.hasNext()) {
      EntryOfSchemaVariableAndInstantiationEntry pair = it.next();
      if (pair.key().isVariableSV()) {
    SchemaVariable varSV = pair.key();    
    Term value = ((TermInstantiation)pair.value()).getTerm();
    if (!collMap.containsKey((LogicVariable)value.op())) {
        collMap.put((LogicVariable)value.op(), varSV);
    } else {
        insts = replaceInstantiation(taclet, insts, varSV);  
    }
      }
  }
  return insts;
    }

    /**
     * delivers the term below the (unique) quantifier of a bound
     * SchemaVariable in the given term.
     *
     * @param varSV the searched Bound Schemavariable
     * @param term the term to be searched in
     * @return the term below the given quantifier in the given term
     */
    private static Term getTermBelowQuantifier(SchemaVariable varSV, Term term) {
  for (int i=0; i<term.arity(); i++) {
      for (int j=0; j<term.varsBoundHere(i).size(); j++) {
    if (term.varsBoundHere(i).getQuantifiableVariable(j)==varSV) {
        return term.sub(i);
    } 
      }
      Term rec=getTermBelowQuantifier(varSV, term.sub(i));
      if (rec!=null) {
    return rec;
      }
  }
  return null;
    }

    /**
     * delivers the term below the (unique) quantifier of 
     * a bound SchemaVariable varSV in the find and if-parts of the Taclet 
     *
     * @param varSV the searched bound SchemaVariable 
     * @return the term below the given quantifier in the find and if-parts of 
     * the Taclet
     */
    private static Term getTermBelowQuantifier(Taclet taclet, SchemaVariable varSV) {
  IteratorOfConstrainedFormula it=taclet.ifSequent().iterator();
  while (it.hasNext()) {
      Term result=getTermBelowQuantifier(varSV, it.next().formula());
      if (result!=null) {
    return result;
      }
  }

  if (taclet instanceof FindTaclet) {
      return getTermBelowQuantifier(varSV, ((FindTaclet)taclet).find());
  } else  
      return null;
    }


    /** returns true iff the instantiation of a bound SchemaVariable contains the given
    * Logicvariable 
    * @param boundVars ArrayOfQuantifiableVariable with the
    * bound SchemaVariables
    * @param x the LogicVariable that is looked for
    * @param insts the SVInstantiations where to get the necessary
    * instantiations of the bound SchemaVariables
    * @return true iff the instantiation of a Bound Schemavariable contains the given
    * Logicvariable 
    */
    private static boolean contains(ArrayOfQuantifiableVariable boundVars,
           LogicVariable x,
           SVInstantiations insts) {
  for (int i=0; i<boundVars.size(); i++) {
      Term instance = (Term) insts.getInstantiation
    ((SchemaVariable)boundVars.getQuantifiableVariable(i));
      if (instance.op() == x) {
    return true;
      } 
  }
  
  return false;
    }

    /**
     * returns a new SVInstantiations that modifies the given
     * SVInstantiations insts at the bound SchemaVariable varSV to a new LogicVariable.
     */
    protected static SVInstantiations replaceInstantiation
  (Taclet taclet, SVInstantiations insts, SchemaVariable varSV){
  Term term=getTermBelowQuantifier(taclet, varSV);
  LogicVariable newVariable = new LogicVariable 
      (new Name(((Term)insts.getInstantiation(varSV)).op()
          .name().toString()+"0"),
       ((Term)insts.getInstantiation(varSV)).sort());
  // __CHANGE__ How to name the new variable? TODO
  Term newVariableTerm 
      = TermFactory.DEFAULT.createVariableTerm(newVariable);
  return replaceInstantiation(insts, term, varSV, newVariableTerm);
    }

    /**
     * returns a new SVInstantiations that modifies the given
     * SVInstantiations insts at the bound SchemaVariable u to the Term (that is
     * a LogicVariable) y.
     */
    private static SVInstantiations replaceInstantiation
  (SVInstantiations insts, Term t,  SchemaVariable u, Term y){

  SVInstantiations result = insts;
  LogicVariable x = (LogicVariable)
      ((Term)insts.getInstantiation(u)).op();
  if (t.op() instanceof SchemaVariable) {
      if (!((SchemaVariable)t.op()).isVariableSV()) {
    SchemaVariable sv=(SchemaVariable)t.op();
    ClashFreeSubst cfSubst
        = new ClashFreeSubst(x,y); 
    result = result.replace
        (sv, 
         cfSubst.apply((Term)insts.getInstantiation(sv)));
      }
  } else {
      for (int i=0; i<t.arity(); i++) {
    if (!contains(t.varsBoundHere(i), x, insts)) {         
        result = replaceInstantiation(result, t.sub(i),
              u, y);
    }
      }
    
  }

  result=result.replace(u, y);
  return result;
    }

    /** applies the specified rule at the specified position 
     * if all schema variables have been instantiated
     * @param goal the Goal at which the Taclet is applied
     * @param services the Services encapsulating all java information
     * @return list of new created goals 
     */
    public ListOfGoal execute(Goal goal, Services services) {

  if (!complete()) {    
      throw new IllegalStateException("Tried to apply rule \n"+taclet
              +"\nthat is not complete.");
  }
        goal.addAppliedRuleApp(this);  
  return taclet().apply(goal, services, this);
    }    

    /** applies the specified rule at the specified position 
     * if all schema variables have been instantiated
     * and creates a new goal if the if-sequent does not match.
     * The new goal proves that the if sequent can be derived.
     * @param goal the Goal where to apply the rule
     * @param services the Services encapsulating all java information
     * @return list of new created goals 
     */
    /*
    public ListOfGoal executeForceIf(Goal goal, Services services) {
  if (!complete()) {
      throw new IllegalStateException("Applied rule not complete.");
  }
  goal.addAppliedRuleApp(this);  
  return taclet().apply(goal, services, this, true);
    }    
    */

    /** calculate needed SchemaVariables that have not been
     * instantiated yet. This means to ignore SchemaVariables that
     * appear only in addrule-sections of Taclets
     * @return SetOfSchemaVariable that need to be instantiated but
     * are not
     */
    protected SetOfSchemaVariable calculateNonInstantiatedSV() {
  if (missingVars == null) {
      missingVars = SetAsListOfSchemaVariable.EMPTY_SET;
      TacletSchemaVariableCollector coll =
    new TacletSchemaVariableCollector(instantiations());
      coll.visitWithoutAddrule(taclet());
      IteratorOfSchemaVariable it = coll.varIterator();
      while (it.hasNext()) {
    SchemaVariable var=it.next();
    if (!instantiations().isInstantiated(var) &&
                        !isDependingOnModifiesSV(var)) {
        missingVars = missingVars.add(var);  
    }
      }
  }
  return missingVars;
    }


    private NewDepOnAnonUpdates getDependingOnModifies(SchemaVariable var) {
        if ( !var.isFormulaSV () ) return null;
        
        NewDepOnAnonUpdates result = null;
        final IteratorOfVariableCondition it = taclet.getVariableConditions ();
        while ( it.hasNext () ) {
            final VariableCondition vc = it.next();
            if ( vc instanceof NewDepOnAnonUpdates
                 && ((NewDepOnAnonUpdates)vc).getUpdateSV() == var ) {
                assert result == null :
                    "" + vc + "is a duplicate dependency condition for " +
                    "schema variable " + var;
                result = (NewDepOnAnonUpdates)vc;
            }
        }

        return result;        
    }
    
    /**
     * @param sv a schema variable
     * @return true iff sv there is a variable condition of the form
     *         \newDepOnMod(modifies,sv)
     */
    public boolean isDependingOnModifiesSV(SchemaVariable sv){
        return getDependingOnModifies (sv ) != null;
    }

    
    /** Calculate needed SchemaVariables that have not been
     * instantiated yet and cannot be instantiated using
     * metavariables. This is a subset of
     * calculateNonInstantiatedSV();
     * @return SetOfSchemaVariable that need to be instantiated but
     * are not
     */
    protected SetOfSchemaVariable calculateNeededNonInstantiatedSV() {
        if ( neededMissingVars == null ) {
            IteratorOfSchemaVariable it =
                calculateNonInstantiatedSV ().iterator ();
            SchemaVariable var;
            SVInstantiations svi = instantiations ();

            neededMissingVars = SetAsListOfSchemaVariable.EMPTY_SET;

            while ( it.hasNext () ) {
                var = it.next ();
                if ( isDependingOnModifiesSV ( var ) )
                    continue;
                if ( canUseMVAPriori ( var ) ) {
                    GenericSortCondition c =
                        GenericSortCondition.forceInstantiation
                        ( ( (SortedSchemaVariable)var ).sort (), true );
                    if ( c == null )
                        continue; // then the sort is not generic
                    else {
                        try {
                            svi = svi.add ( c );
                            continue; // then the sort can be guessed
                        } catch ( GenericSortException e ) {
                            Debug.out ( "Exception thrown by class TacletApp " +
                                        "at svi.add()" );
                        }
                    }
                }

                neededMissingVars = neededMissingVars.add ( var );
            }
        }
        return neededMissingVars;
    }

    /** creates a new Tacletapp where the SchemaVariable sv is
     * instantiated with the the given Term term. Sort equality is
     * checked. If the check fails an IllegalArgumentException is
     * thrown
     * @param sv the SchemaVariable to be instantiated
     * @param term the Term the SchemaVariable is instantiated with
     * @return the new TacletApp
     */
    public TacletApp addCheckedInstantiation(SchemaVariable sv, 
               Term term,
                                             Services services,
                                             boolean interesting) {

  if (sv.isVariableSV() && 
      !(term.op() instanceof LogicVariable)) {
      throw new IllegalInstantiationException("Could not add "+
         "the instantiation of "+sv+" because "+
    term+" is no variable.");
  }               
              
        
        MatchConditions cond = matchConditions();
        
        if (sv instanceof SortedSchemaVariable) {
            cond = ((SortedSchemaVariable)sv).match(term, cond, services);
        } else {
            cond = sv.match(term.op(), cond, services);
        }
                  
        if (cond == null) {
            throw new IllegalInstantiationException("Instantiation " + term + " is not matched by " + sv);
        } 
              
        cond = taclet().checkVariableConditions(sv, term, cond, services);
        
        if (cond == null) {
            throw new IllegalInstantiationException("Instantiation " + term + " of " + sv + 
                    "does not satisfy the variable conditions");
        }
        
        if (interesting) {
            cond = cond.setInstantiations(cond.getInstantiations().makeInteresting(sv));
        }
        
        return addInstantiation(cond.getInstantiations());

    }


    /**
     * returns the variables that have not yet been instantiated and
     * need to be instantiated to apply the Taclet. (These are not all
     * SchemaVariables like the one that appear only in the addrule
     * sections)
     * @return SetOfSchemaVariable with SchemaVariables that have not
     * been instantiated yet 
     */
    public SetOfSchemaVariable uninstantiatedVars() {
  return calculateNonInstantiatedSV();
    }
    
    /**
     * returns the variables that are currently uninstantiated and
     * cannot be instantiated automatically using metavariables
     * @return SetOfSchemaVariable with SchemaVariables that have not
     * been instantiated yet 
     */
    public SetOfSchemaVariable neededUninstantiatedVars() {
  return calculateNeededNonInstantiatedSV();
    }
    
    

    /**
     * @return A TacletApp with this.sufficientlyComplete() or null
     */
    public TacletApp tryToInstantiate(Goal goal, Services services) {
        final VariableNamer varNamer = services.getVariableNamer();
        final TermBuilder tb = TermBuilder.DF;
        
        TacletApp app = this;
        ListOfString proposals = SLListOfString.EMPTY_LIST;

        final IteratorOfSchemaVariable it = uninstantiatedVars().iterator();
        while (it.hasNext()) {
            SchemaVariable var = it.next();
            
            if (LoopInvariantProposer.inLoopInvariantRuleSet(taclet().ruleSets())){ 
                Object inv = LoopInvariantProposer.DEFAULT.tryToInstantiate(this, var, services);              
                if (inv instanceof Term){
                    app = app.addCheckedInstantiation(var, (Term)inv, services, true);
                } else if (inv instanceof ListOfTerm){
                    app = app.addInstantiation(var, ((ListOfTerm)inv).toArray(), true);
                } else if (inv instanceof SetOfLocationDescriptor) {
                    app = app.addInstantiation(var, ((SetOfLocationDescriptor)inv).toArray(), true);
                }   
                if (inv != null) continue;
            } 
            if(var instanceof SortedSchemaVariable) {
                SortedSchemaVariable sv = (SortedSchemaVariable)var;
                if (sv.sort() == ProgramSVSort.VARIABLE) {
                    String proposal = varNamer.getSuggestiveNameProposalForProgramVariable
                    (sv, this, goal, services, proposals);
                    ProgramElement pe = 
                        TacletInstantiationsTableModel.getProgramElement(app, proposal, sv, services);
                    app = app.addCheckedInstantiation(sv, pe, services, true);
                    proposals = proposals.append(proposal);
                } else if (sv.sort() == ProgramSVSort.LABEL) {
                    boolean nameclash;
                    do {
                        String proposal = VariableNameProposer.DEFAULT.
                            getProposal(this, sv, services, goal.node(), proposals);
                        ProgramElement pe = TacletInstantiationsTableModel.
                            getProgramElement(app, proposal, sv, services);
                        proposals = proposals.prepend(proposal);
                        try {
                            app = app.addCheckedInstantiation(sv, pe, services, true);
                        } catch (IllegalInstantiationException iie) {
                            // name clash
                            nameclash=true;
                        }
                        nameclash=false;
                    } while (nameclash);                    
                } else if ( sv.isSkolemTermSV () ) {
                    // if the sort of the schema variable is generic,
                    // ensure that it is instantiated
                    app = forceGenericSortInstantiation(app, sv);
                    if ( app == null ) return null;
    
                    String proposal = VariableNameProposer.DEFAULT
                        .getProposal(app, sv, services, goal.node(), proposals);

                    proposals = proposals.append(proposal);

                    app = app.createSkolemConstant ( proposal,
                        sv,
                        true, services );

                } else if ( sv.isVariableSV () ) {
                    // if the sort of the schema variable is generic,
                    // ensure that it is instantiated
                    app = forceGenericSortInstantiation ( app, sv );
                    if ( app == null ) return null;
                    
                    String proposal = VariableNameProposer.DEFAULT
                    .getProposal( this, sv, services, goal.node(), null );
                    final LogicVariable v = new LogicVariable ( new Name ( proposal ),
                            getRealSort ( sv, services ) );                
                    app = app.addCheckedInstantiation ( sv, tb.var(v), services, true );
                } else if ( !( sv.isTermSV () && canUseMVAPriori ( sv ) ) ) {
                    return null;
                }
            }      
        }
        
        if (app != this) {
            final MatchConditions appMC = 
                app.taclet().checkConditions(app.matchConditions(), services);
            if (appMC == null) {              
                return null;
            } else {
                app = app.setMatchConditions(appMC);
            }
        }
              
        if (!app.sufficientlyComplete()) {         
            return null;
        }
        return app;
    }
    
    /**
     * If the sort of the given schema variable is generic, add a
     * condition to the instantiations of the given taclet app that
     * requires the sort to be instantiated
     * @return the new taclet app, or <code>null</code> if the sort of
     * <code>sv</code> is generic and cannot be instantiated (at least
     * at the time)
     */
    private static TacletApp
  forceGenericSortInstantiation (TacletApp app,
               SortedSchemaVariable sv) {
        final GenericSortCondition c =
            GenericSortCondition.forceInstantiation ( sv.sort (), false );
        if ( c != null ) {
            try {
                app = app.setInstantiation ( app.instantiations ().add ( c ) );
            } catch ( GenericSortException e ) {
                return null;
            }
        }
        return app;
    }

    /**
     * Examine all schema variables of the taclet that are currently
     * not instantiated, and for each one whose sort is generic add a
     * condition to the instantiations object <code>insts</code> that
     * requires this sort to be instantiated
     * @return the instantiations object after adding all the
     * conditions, or <code>null</code> if any of the generic sorts
     * found cannot be instantiated (at least at the time)
     */
    private SVInstantiations forceGenericSortInstantiations (SVInstantiations insts) {
        final IteratorOfSchemaVariable it  = uninstantiatedVars().iterator ();

      // force all generic sorts to be instantiated
      try {
    while ( it.hasNext () ) {
        final SchemaVariable sv = it.next ();
        final GenericSortCondition c =
            GenericSortCondition.forceInstantiation
                    ( ( (SortedSchemaVariable)sv ).sort (), true );
        if ( c != null )                             
            insts = insts.add ( c );                                                                        
    }
      } catch ( GenericSortException e ) {
    Debug.fail ( "TacletApp cannot be made complete" );    
      }
        return insts;
    }

    /**
     * Make the instantiation complete using metavariables and convert plain
     * instantiations to metavariables and user constraint entries if possible.
     * Pre-condition: this.sufficientlyComplete()
     */
    public TacletApp instantiateWithMV ( Goal p_goal ) {

  Debug.assertTrue ( this.sufficientlyComplete (),
         "TacletApp cannot be made complete" );

  final Proof proof = p_goal.proof ();
    
        Services services = proof.getServices();
        
  SVInstantiations  insts   = instantiations   ();
  SetOfMetavariable newVars = newMetavariables ();
  Constraint        constr = constraint ();

  if ( newVars != SetAsListOfMetavariable.EMPTY_SET ) {
            // Replace temporary metavariables that were introduced
            // when matching the taclet with real MVs
            final IteratorOfMetavariable mvIt = newVars.iterator ();
            newVars = SetAsListOfMetavariable.EMPTY_SET;
            SetOfMetavariable removeVars = SetAsListOfMetavariable.EMPTY_SET; 
            Constraint replaceC = Constraint.BOTTOM;            
            while ( mvIt.hasNext () ) {
                final Metavariable mv = mvIt.next();
                if ( mv.isTemporaryVariable() ) {
                    String s = "" + mv.name ();
                    s += "_"+MetavariableDeliverer.mv_Counter(s, p_goal);
                    final Metavariable newMV = proof.getMetavariableDeliverer ()
                        .createNewVariable (s , mv.sort () );
                    newVars = newVars.add ( newMV );
                    removeVars = removeVars.add ( mv );
                    final Term newT = TermFactory.DEFAULT.createFunctionTerm ( newMV );
                    final Term t = TermFactory.DEFAULT.createFunctionTerm ( mv );
                    replaceC = replaceC.unify ( t, newT, services );
                } else
                    newVars = newVars.add ( mv );
            }
            
            if ( !replaceC.isBottom () ) {
                constr = removeTemporaryMVsFromConstraint ( constr,
                                                            removeVars,
                                                            replaceC,
                                                            services);
                insts = removeTemporaryMVsFromInstantiations ( insts, replaceC );
            }
        }
  
  // Replace plain instantiations of termSV

  final IteratorOfEntryOfSchemaVariableAndInstantiationEntry it    =
      insts.pairIterator ();

  while ( it.hasNext () ) {
      final EntryOfSchemaVariableAndInstantiationEntry entry = it.next ();
      final SchemaVariable sv = entry.key ();

      if ( introduceMVFor ( entry, sv ) ) {
                final Metavariable mv = getMVFor ( sv, proof, p_goal, insts );
                newVars = newVars.add ( mv );
                final Term t = TermFactory.DEFAULT.createFunctionTerm ( mv );
                proof.getUserConstraint ().addEquality ( t,
                             ( (TermInstantiation)entry.value () ).getTerm () );
                insts = insts.replace ( sv, t );
            }
        }

  return handleUninstantiatedSVs(proof, p_goal, insts, constr, newVars);
    }


    /**
     * Replace temporary metavariables (that were introduced when
     * matching the taclet parts) within <code>insts</code> with
     * definite metavariables
     * @param replaceC a constraint that unifies each temporary
     * metavariable with the corresponding definite metavariable
     */
    private static SVInstantiations
  removeTemporaryMVsFromInstantiations (SVInstantiations insts,
                Constraint replaceC) {
        final IteratorOfEntryOfSchemaVariableAndInstantiationEntry it =
            insts.pairIterator ();

        while ( it.hasNext () ) {
            final EntryOfSchemaVariableAndInstantiationEntry entry = it.next ();
            final SchemaVariable sv = entry.key ();

            if ( sv.isFormulaSV() || sv.isTermSV() ) {
                final Object inst = entry.value().getInstantiation ();
                // NB: this only works because of the implementation of
                // <code>Metavariable.compareTo</code>, in which temporary MVs
                // are regarded as greater than normal MVs
                final SyntacticalReplaceVisitor srVisitor =
                    new SyntacticalReplaceVisitor ( replaceC );
                ( (Term)inst ).execPostOrder ( srVisitor );
                insts = insts.replace ( sv, srVisitor.getTerm () );
            }
        }
        return insts;
    }

    /**
     * Replace temporary metavariables (that were introduced when
     * matching the taclet parts) within <code>constr</code> with
     * definite metavariables
     * @param removeVars the set of temporary metavariables to be
     * removed
     * @param replaceC a constraint that unifies each temporary
     * metavariable with the corresponding definite metavariable
     * @param services the Services 
     */
    private static Constraint
  removeTemporaryMVsFromConstraint (Constraint constr,
            SetOfMetavariable removeVars,
            Constraint replaceC,
                                          Services services) {
        // that's tricky ...
        constr = constr.join ( replaceC, services );
        return constr.removeVariables ( removeVars );
    }

    /**
     * @return true iff it is possible to use a metavariable to make
     * the given instantiation indirect, i.e. to instantiate the
     * schema variable with a metavariable instead of a term, and to
     * add the real instantiation to the user constraint
     */
    private boolean introduceMVFor (EntryOfSchemaVariableAndInstantiationEntry entry,
                                    SchemaVariable sv) {
        return sv.isTermSV () && !sv.isListSV()
               && !taclet ().getIfFindVariables ().contains ( sv )
               && canUseMVAPosteriori ( sv,
                            ( (TermInstantiation)entry.value () ).getTerm () );
    }

    /**
     * Instantiate all uninstantiated schema variables with
     * metavariables; it is assumed that this is possible (currently
     * checked using an assertion)
     * @return a new taclet app in which all schema variables are
     * instantiated
     */
    private TacletApp handleUninstantiatedSVs (Proof proof,
                                               Goal goal,
                                               SVInstantiations insts,
                                               Constraint constr,
                                               SetOfMetavariable newVars) {
        insts = forceGenericSortInstantiations ( insts );

        final IteratorOfSchemaVariable it = uninstantiatedVars ().iterator ();
        while ( it.hasNext () ) {
            final SchemaVariable sv = it.next ();
            if (isDependingOnModifiesSV(sv))
                continue;
            Debug.assertTrue ( canUseMVAPriori ( sv ),
                               "Should be able to instantiate "
                               + sv
                               + " using metavariables, but am not" );
            
            final Metavariable mv = getMVFor(sv, proof, goal, insts);
            newVars = newVars.add ( mv );
            final Term t = TermFactory.DEFAULT.createFunctionTerm ( mv );
            insts = insts.add ( sv, t );
            NameSV nameSV = new NameSV(new Name(NameSV.MV_NAME_PREFIX+sv.name()));
            insts = insts.addInteresting (nameSV, mv.name());
        }

        return setMatchConditions ( new MatchConditions ( insts,
                                                          constr,
                                                          newVars,
                                                          RenameTable.EMPTY_TABLE ) );
    }

    /**
     * Create a Metavariable the given SchemaVariable can be
     * instantiated with
     * @return an appropriate mv, or null if for some reason the
     * creation failed
     */
    private Metavariable getMVFor (SchemaVariable sv,
                                   Proof proof,
                                   Goal goal,
                                   SVInstantiations insts) {
        final Sort realSort = insts.getGenericSortInstantiations().
            getRealSort(sv, proof.getServices());
        SchemaVariable nameSV = insts.lookupVar(
            new Name(NameSV.MV_NAME_PREFIX+sv.name()));
        Name proposal = (Name) insts.getInstantiation(nameSV);
        String s = (proposal==null) ? "" : proposal.toString();
        return getMVFor ( sv, realSort, proof, goal, s );
    }

    /**
     * Create a Metavariable the given SchemaVariable can be
     * instantiated with
     * @return an appropriate mv, or null if for some reason the
     * creation failed
     */
    private Metavariable getMVFor ( SchemaVariable p_sv,
            Sort           p_sort,
            Proof          p_proof,
                                    Goal goal,
                                    String nameProposal ) {
        if ("".equals(nameProposal)) {
            nameProposal = TacletInstantiationsTableModel
        .getNameProposalForMetavariable ( goal, this, p_sv );
        }
  return p_proof.getMetavariableDeliverer().
            createNewVariable(nameProposal, p_sort);
    }


    /**
     * @param services the Services class allowing access to the type model
     * @return p_s iff p_s is not a generic sort, the concrete sort
     * p_s is instantiated with currently otherwise 
     * @throws GenericSortException iff p_s is a generic sort which is
     * not yet instantiated
     */
    public Sort getRealSort ( SchemaVariable p_sv, Services services )  {
  return instantiations ().getGenericSortInstantiations ()
      .getRealSort ( p_sv, services );
    }

    /**
     * Create a new constant named "instantiation" and instantiate
     * "sv" with. This constant will later (by
     * "createSkolemFunctions") be replaced by a function having
     * the occurring metavariables as arguments
     * @param services the Services class allowing access to the type model
     */
    public TacletApp createSkolemConstant ( String         instantiation,
                 SchemaVariable sv,
                 boolean        interesting, 
                                               Services services ) {
  return createSkolemConstant ( instantiation,
           sv,
           getRealSort ( sv, services ),
           interesting );
    }
    
    public TacletApp createSkolemConstant ( String         instantiation,
                 SchemaVariable sv,
                 Sort           sort,
                 boolean        interesting ) {
  Function c = new RigidFunction ( new Name ( instantiation ),
            sort,
            new Sort [0] );
  return addInstantiation ( sv,
          TermFactory.DEFAULT.createFunctionTerm ( c ),
          interesting );
    }
    

    /**
     * Create skolem functions (for variables declared via "\\new(c,
     * \\dependingOn(phi))" or via "\\new(upd, \\dependingOnMod(#modifiers))")
     * to replace previously created constants with
     */
    public TacletApp createSkolemFunctions ( Namespace p_func_ns, Services services ) {
        SVInstantiations insts = instantiations ();

        final IteratorOfSchemaVariable svIt = insts.svIterator ();        
        while ( svIt.hasNext () )
            insts = createTermSkolemFunctions ( svIt.next (), insts, p_func_ns );
        
        final IteratorOfVariableCondition vcIt = taclet.getVariableConditions ();
        while ( vcIt.hasNext () ) {
            final VariableCondition vc = vcIt.next();
            if ( vc instanceof NewDepOnAnonUpdates )
                insts = createModifiesSkolemFunctions((NewDepOnAnonUpdates)vc,
                                                      insts, services);
        }
        
        if ( insts == instantiations () ) return this;
        return setInstantiation ( insts );
    }

    /**
     * Instantiate a SkolemTermSV
     */
    private SVInstantiations createTermSkolemFunctions(SchemaVariable depSV,
                                                       SVInstantiations insts,
                                                       Namespace p_func_ns) {
        if ( !depSV.isSkolemTermSV () ) return insts;

        final Term tempDepVar = (Term)insts.getInstantiation ( depSV );

        Debug.assertTrue ( tempDepVar != null,
                           "Name for skolemterm variable missing" );

        return createSkolemFunction ( insts, p_func_ns, depSV, tempDepVar,
                                      determineArgMVs ( insts, depSV ) );
    }
        
    /**
     * Instantiate a schemavariable for an anonymous update (FormulaSV)
     */
    private SVInstantiations
        createModifiesSkolemFunctions(NewDepOnAnonUpdates cond,
                                      SVInstantiations insts,
                                      Services services) {
        final SchemaVariable modifies = cond.getModifiesSV ();
        final SchemaVariable updateSV = cond.getUpdateSV ();
        
        if (insts.isInstantiated ( updateSV )) {
            System.err.println(
                "Modifies skolem functions already created - ignoring.");
            return insts;
        }
        
        final ListOfObject locationList =
            (ListOfObject)insts.getInstantiation ( modifies );
        final AnonymisingUpdateFactory auf =
            new AnonymisingUpdateFactory
            ( new UpdateFactory ( services, new UpdateSimplifier () ) );
        final Term[] mvArgs = toTermArray ( determineArgMVs ( insts, updateSV ) );
        return insts.add ( updateSV,
                           auf.createAnonymisingUpdateAsFor
                                  ( toLocationDescriptorArray ( locationList ),
                                    mvArgs, services ) );
    }
    
    private static LocationDescriptor[]
               toLocationDescriptorArray(ListOfObject locationList) {
        final LocationDescriptor[] locations =
            new LocationDescriptor [locationList.size ()];

        for ( int i = 0; i < locations.length; i++ ) {
            locations[i] = (LocationDescriptor)locationList.head ();
            locationList = locationList.tail ();
        }
        return locations;
    }

    
    /**
     * Determine the metavariables that have to be added as arguments to newly
     * created skolem symbols (as basis of the occurs check)
     */
    private SetOfMetavariable determineArgMVs (SVInstantiations insts,
                                               SchemaVariable depSV) {
        return
            determineExplicitArgMVs ( insts, depSV )
            .union ( determineArgMVsFromUpdate ( insts ) );
    }

    private SetOfMetavariable determineExplicitArgMVs(SVInstantiations insts,
                                                      SchemaVariable depSV) {
        final IteratorOfNewDependingOn it = taclet ().varsNewDependingOn ();
        SetOfMetavariable mvs = SetAsListOfMetavariable.EMPTY_SET;
        while ( it.hasNext () ) {
            final NewDependingOn newDepOn = it.next ();
            if ( depSV != newDepOn.first () ) continue;
            
            final Term dominantTerm =
                (Term)insts.getInstantiation ( newDepOn.second () );

            assert dominantTerm != null :
                "Variable depends on uninstantiated variable";
            mvs = mvs.union ( dominantTerm.metaVars () );                
        }
        return mvs;
    }

    private SetOfMetavariable determineArgMVsFromUpdate(SVInstantiations insts) {
        final IteratorOfUpdatePair it = insts.getUpdateContext ().iterator ();
        SetOfMetavariable mvs = SetAsListOfMetavariable.EMPTY_SET;
        while ( it.hasNext () ) {
            final UpdatePair pair = it.next ();
            final IUpdateOperator upOp = pair.updateOperator ();
            for ( int i = 0; i != upOp.arity (); ++i ) {
                if ( i == upOp.targetPos () ) continue;
                mvs = mvs.union ( pair.sub ( i ).metaVars () );
            }
        }
        return mvs;
    }

    
    private SVInstantiations createSkolemFunction (SVInstantiations insts,
                                                   Namespace p_func_ns,
                                                   SchemaVariable depSV,
                                                   Term tempDepVar,
                                                   SetOfMetavariable mvs) {
        if ( mvs == SetAsListOfMetavariable.EMPTY_SET ) {
            // if the term contains no metavariables, we just use the
            // (nullary) constant <code>tempDepVar</code> as skolem symbol
            p_func_ns.add ( tempDepVar.op () );
            return insts;
        }

        final Term[] argTerms = toTermArray ( mvs );
        final Function skolemFunc = new RigidFunction ( tempDepVar.op ().name (),
                                                        tempDepVar.sort (),
                                                        extractSorts ( argTerms ) );
        final Term skolemTerm =
            TermFactory.DEFAULT.createFunctionTerm ( skolemFunc, argTerms );

        p_func_ns.add ( skolemFunc );
        return insts.replace ( depSV, skolemTerm );
    }

    private Term[] toTermArray(SetOfMetavariable mvs) {
        final Metavariable[] mvArray = mvs.toArray ();
        Arrays.sort ( mvArray );
        
        // Create function with correct arguments
        final Term[] argTerms = new Term [mvArray.length];
        
        for ( int i = 0; i != mvArray.length; ++i )
            argTerms[i] = TermFactory.DEFAULT.createFunctionTerm ( mvArray[i] );

        return argTerms;
    }

    private Sort[] extractSorts(Term[] argTerms) {
        final Sort[] argSorts = new Sort [argTerms.length];
        for ( int i = 0; i != argTerms.length; ++i )
            argSorts[i] = argTerms[i].sort ();
        return argSorts;
    }

    
    /** adds a new instantiation to this TacletApp 
     * @param sv the SchemaVariable to be instantiated
     * @param term the Term the SchemaVariable is instantiated with
     * @return the new TacletApp
     */
    public abstract TacletApp addInstantiation(SchemaVariable sv, Term term,
                                               boolean interesting);
    

    public abstract TacletApp addInstantiation(SchemaVariable sv, Object[] list,
            boolean interesting);
    
    
    /** 
     * adds a new instantiation to this TacletApp. This method does not 
     * check (beside some very rudimentary tests) if the instantiation is possible.
     * If you cannot guarantee that adding the entry <code>(sv, pe)</code> will 
     * result in a valid taclet instantiation, you have to use 
     * {@link #addCheckedInstantiation(SchemaVariable, ProgramElement, Services, boolean)}
     * instead
     * @param sv the SchemaVariable to be instantiated
     * @param pe the ProgramElement the SV is instantiated with
     * @param interesting a boolean marking if the instantiation of this
     *  sv needs to be saved for later proof loading (<code>interesting==true</code>)
     *  or if it can be derived deterministically (e.g. by matching) 
     *  (<code>interesting==false</code>)
     * @return a new taclet application equal to this one but including the
     * newly added instantiation entry <code>(sv, pe)</code> 
     */
    public abstract TacletApp addInstantiation(SchemaVariable sv, 
                 ProgramElement pe,
                                               boolean interesting);

    
    /** 
     * checks if the instantiation of <code>sv</code> with <code>pe</code>
     * is possible. If the resulting instantiation is valid a new taclet application
     * with an extended instantiation mapping is created and returned. Otherwise an
     * exception is thrown.   
     * @param sv the SchemaVariable to be instantiated
     * @param pe the ProgramElement the SV is instantiated with
     * @param services the Services
     * @param interesting a boolean marking if the instantiation of this
     *  sv needs to be saved for later proof loading (<code>interesting==true</code>)
     *  or if it can be derived deterministically (e.g. by matching) 
     *  (<code>interesting==false</code>)
     * @return a new taclet application equal to this one but including the
     * newly added instantiation entry <code>(sv, pe)</code>, if the
     * instantiation results in a valid taclet application otherwise an exception is thrown
     * @throws IllegalInstantiationException exception thrown if 
     *  <code>sv</code> cannot be instantiated with <code>pe</code> no matter if in general
     *   or due to side conditions posed by this particular application 
     *  
     */
    public TacletApp addCheckedInstantiation
        (SchemaVariable sv, ProgramElement pe, 
                Services services, boolean interesting) {
      
        MatchConditions cond = matchConditions();
        
        if (sv instanceof ProgramSV) {
            cond = ((ProgramSV)sv).match(pe, cond, services);
        } else {
            throw new IllegalInstantiationException("Cannot match program element '"+ pe +
                    "'("+(pe == null ? null : pe.getClass().getName())+") to non program sv " + sv);
        }
                               
        if (cond == null) {           
            throw new IllegalInstantiationException("Instantiation " + pe + 
                    "(" + (pe == null ? null : pe.getClass().getName())+
                    ") is not matched by " + sv);
        }
        
        cond = taclet().checkConditions(cond, services);
        
        if (cond == null) {
            throw new IllegalInstantiationException("Instantiation " + pe + " of " + sv + 
                    "does not satisfy variable conditions");
        }
        
        if (interesting) {
            cond = cond.setInstantiations(cond.getInstantiations().makeInteresting(sv));
        }
        
        return addInstantiation(cond.getInstantiations());
             
    }

    public TacletApp addInstantiation(SchemaVariable sv, Name name) {
        return 
      addInstantiation(SVInstantiations.
           EMPTY_SVINSTANTIATIONS.addInteresting(sv, name));
    }


    /**
     * creates a new Taclet application containing all the
     * instantiations given 
     * by the SVInstantiations
     * @param svi the SVInstantiations whose entries are the needed
     * instantiations 
     * @return the new Taclet application
     */
    public abstract TacletApp addInstantiation(SVInstantiations svi);


    /**
     * creates a new Taclet application containing all the
     * instantiations given 
     * by the SVInstantiations and forget the old ones
     * @param svi the SVInstantiations whose entries are the needed
     * instantiations 
     * @return the new Taclet application
     */
    protected abstract TacletApp setInstantiation(SVInstantiations svi);


    /**
     * creates a new Taclet application containing all the
     * instantiations, constraints and new metavariables given 
     * by the mc object and forget the old ones
     */
    protected abstract TacletApp setMatchConditions ( MatchConditions mc );


    /**
     * creates a new Taclet application containing all the
     * instantiations, constraints, new metavariables and if formula
     * instantiations given and forget the old ones
     */
    protected abstract TacletApp
  setAllInstantiations ( MatchConditions              mc,
             ListOfIfFormulaInstantiation ifInstantiations );


    /**
     * Creates a new Taclet application by matching the given formulas
     * against the formulas of the if sequent, adding SV
     * instantiations, constraints and metavariables as needed. This
     * will fail if the if formulas have already been instantiated.
     */
    public TacletApp setIfFormulaInstantiations
  ( ListOfIfFormulaInstantiation p_list,
    Services                     p_services,
    Constraint                   p_userConstraint ) {
  assert p_list != null && ifInstsCorrectSize ( taclet, p_list ) &&
      ifInstantiations == null :
      "If instantiations list has wrong size or is null " +
      "or the if formulas have already been instantiated";
    
  MatchConditions  mc = taclet ().matchIf ( p_list.iterator (),
              matchConditions (),
              p_services,
              p_userConstraint );
  
  return mc == null ? null : setAllInstantiations ( mc, p_list );
    }


    /**
     * Find all possible instantiations of the if sequent formulas
     * within the sequent "p_seq".
     * @return a list of tacletapps with the found if formula
     * instantiations
     */
    public ListOfTacletApp
  findIfFormulaInstantiations ( Sequent     p_seq,
                                Services    p_services,
              Constraint  p_userConstraint ) {
  
  Debug.assertTrue ( ifInstantiations == null,
         "The if formulas have already been instantiated" );

  if ( taclet ().ifSequent () == Sequent.EMPTY_SEQUENT )
      return SLListOfTacletApp.EMPTY_LIST.prepend ( this );        
        
  return
      findIfFormulaInstantiationsHelp
      ( createSemisequentList ( taclet ().ifSequent ()  // Matching starting
              .succedent () ),    // with the last formula
        createSemisequentList ( taclet ().ifSequent ()
              .antecedent () ),
        IfFormulaInstSeq.createList(p_seq, false),
        IfFormulaInstSeq.createList(p_seq, true),
        SLListOfIfFormulaInstantiation.EMPTY_LIST,
        matchConditions (),
        p_services,
        p_userConstraint );
  
    }

    
    /**
     * Recursive function for matching the remaining tail of an if sequent
     * @param p_ifSeqTail tail of the current semisequent as list
     * @param p_ifSeqTail2nd the following semisequent
     * (i.e. antecedent) or null
     * @param p_toMatch list of the formulas to match the current if
     * semisequent formulas with
     * @param p_toMatch2nd list of the formulas of the antecedent
     * @param p_matchCond match conditions until now, i.e. after
     * matching the first formulas of the if sequent
     */
    private ListOfTacletApp findIfFormulaInstantiationsHelp
  ( ListOfConstrainedFormula      p_ifSeqTail,
    ListOfConstrainedFormula      p_ifSeqTail2nd,
    ListOfIfFormulaInstantiation  p_toMatch,
    ListOfIfFormulaInstantiation  p_toMatch2nd,
    ListOfIfFormulaInstantiation  p_alreadyMatched,
    MatchConditions               p_matchCond,
    Services                      p_services,
    Constraint                    p_userConstraint ) {

  while ( p_ifSeqTail == SLListOfConstrainedFormula.EMPTY_LIST ) {
      if ( p_ifSeqTail2nd == null ) {
    // All formulas have been matched, collect the results
    TacletApp res = setAllInstantiations ( p_matchCond,
                   p_alreadyMatched );
    if ( res != null )
        return SLListOfTacletApp.EMPTY_LIST.prepend ( res );
    return SLListOfTacletApp.EMPTY_LIST;
      } else {
    // Change from succedent to antecedent
    p_ifSeqTail    = p_ifSeqTail2nd;
    p_ifSeqTail2nd = null;
    p_toMatch      = p_toMatch2nd;
      }
  }

  // Match the current formula
  IfMatchResult mr        = taclet ().matchIf ( p_toMatch.iterator (),
                  p_ifSeqTail.head ().formula (),
                  p_matchCond,
                  p_services,
                  p_userConstraint );

  // For each matching formula call the method again to match
  // the remaining terms
  ListOfTacletApp                  res    = SLListOfTacletApp.EMPTY_LIST;
  IteratorOfIfFormulaInstantiation itCand = mr.getFormulas        ().iterator ();
  IteratorOfMatchConditions        itMC   = mr.getMatchConditions ().iterator ();
  p_ifSeqTail                             = p_ifSeqTail.tail ();
  while ( itCand.hasNext () ) {
      res = res.prepend
    ( findIfFormulaInstantiationsHelp ( p_ifSeqTail,
                p_ifSeqTail2nd,
                p_toMatch,
                p_toMatch2nd,
                p_alreadyMatched
                .prepend ( itCand.next () ),
                itMC.next (),
                p_services,
                p_userConstraint ) );
  }

  return res;
    }

    private ListOfConstrainedFormula createSemisequentList ( Semisequent p_ss ) {
  ListOfConstrainedFormula res = SLListOfConstrainedFormula.EMPTY_LIST;

  IteratorOfConstrainedFormula it  = p_ss.iterator ();
  while ( it.hasNext () )
      res = res.prepend ( it.next () );

  return res;  
    }


    /**
     * returns a new PosTacletApp that is equal to this TacletApp except
     * that the position is set to the given PosInOccurrence
     * @param pos the PosInOccurrence of the newl created PosTacletApp
     * @return the new TacletApp
     */
    public PosTacletApp setPosInOccurrence(PosInOccurrence pos) {
  if (taclet() instanceof NoFindTaclet) {
      throw new IllegalStateException("Cannot add position to an taclet"
              +" without find");
  }
  return PosTacletApp.createPosTacletApp((FindTaclet)taclet      (), 
                 instantiations          (),
                 constraint              (),
                 newMetavariables        (),
                 ifFormulaInstantiations (),
                 pos);
    }


    /** returns true iff all necessary informations are collected, so
     * that the Taclet can be applied.
     * @return true iff all necessary informations are collected, so
     * that the Taclet can be applied.
     */
    public abstract boolean complete();


    /**
     * @return true iff the taclet instantiation can be made complete
     * using metavariables
     */
    public abstract boolean sufficientlyComplete();


    /**
     * @return true iff the SV instantiations can be made complete
     * using metavariables
     */
    public boolean instsSufficientlyComplete() {
  return neededUninstantiatedVars () == SetAsListOfSchemaVariable.EMPTY_SET;
    }


    /**
     * @return true iff the if instantiation list is not null or no if
     * sequent is needed
     */
    public boolean ifInstsComplete() {
  return ifInstantiations != null ||
      ( taclet ().ifSequent () == Sequent.EMPTY_SEQUENT );
    }


    /**
     * returns the PositionInOccurrence (representing a ConstrainedFormula and
     * a position in the corresponding formula)
     * @return the PosInOccurrence
     */
    public abstract PosInOccurrence posInOccurrence();


    /** compares the given Object with this one and returns true iff both are
     * from type TacletApp with equal taclets, instantiations and positions.
     */
    public boolean equals(Object o) {
  if (o==this) return true;
  if (!(o instanceof TacletApp)) return false;
  TacletApp s=(TacletApp)o;
  return (s.taclet().equals(taclet()) 
    && s.instantiations().equals(instantiations()));
    }

    public int hashCode() {
        int result = 17;
        result = 37 * result + taclet.hashCode();
        result = 37 * result + instantiations.hashCode();
        return result;
    }
    
    public String toString() {
  return "Application of Taclet " +taclet()+ " with "
      +instantiations() + " and " + ifFormulaInstantiations();
    }


    /**
     * checks if there are name conflicts (i.e. there are
     * two matched bound SchemaVariable that are matched to variables with an
     * equal name); if yes a new TacletApp is returned that equals this
     * TacletApp except that the name conflict is resolved by replacing the
     * instantiation of one of the conflict-causing SchemaVariables by a 
     * bound SchemaVariable with a new name; 
     * if the check is negative, the same TacletApp is returned.
     *
     * @return a conflict resolved TacletApp, remainder equal to this TacletApp
     */
    public TacletApp prepareUserInstantiation() {
  TacletApp result = this;
  SchemaVariable varSV = varSVNameConflict();
  while (varSV!=null) {
      result = setInstantiation(replaceInstantiation
            (taclet, result.instantiations(), varSV));
      varSV = result.varSVNameConflict();
  }
  return result;
    }

    protected abstract SetOfQuantifiableVariable contextVars(SchemaVariable sv);

    /**
     * creates a new variable namespace by adding names of the instantiations
     * of the schema variables in the context of the given schema
     * variable and (if the TacletApp's prefix has the context flag set)
     * by adding names of the logic variables of the context.
     *
     * @param sv the schema variable to be considered
     * @param var_ns the old variable namespace
     * @return the new created variable namespace
     */
    public Namespace extendVarNamespaceForSV(Namespace var_ns, 
               SchemaVariable sv) {
  Namespace ns=new Namespace(var_ns);
        IteratorOfSchemaVariable it=taclet().getPrefix(sv).prefix().iterator();
  while (it.hasNext()) {
      LogicVariable var = (LogicVariable) 
    ((Term)instantiations().getInstantiation(it.next())).op();
      ns.add(var);
  }
  if (taclet().getPrefix(sv).context()) {      
      IteratorOfQuantifiableVariable lit
    = contextVars(sv).iterator();
      while (lit.hasNext()) {
    ns.add(lit.next());
      }
  }
  return ns;
    }


    /**
     * returns the bound SchemaVariable that causes a name conflict (i.e. there are
     * two matched bound SchemaVariables that are matched to variables with an
     * equal name, the returned SchemaVariable is (an arbitrary) one of these
     * SchemaVariables) or null if there is no such conflict
     *
     * @return null iff there is no conflict and one of the
     * conflict-causing bound SchemaVariables
     */
    public SchemaVariable varSVNameConflict() {
  IteratorOfSchemaVariable svIt=uninstantiatedVars().iterator();
  while (svIt.hasNext()) { 
      SchemaVariable sv=svIt.next();
      if (sv.isTermSV() || sv.isFormulaSV()) {
    TacletPrefix prefix=taclet().getPrefix(sv);
    HashSet names=new HashSet();      
    if (prefix.context()) {
        IteratorOfQuantifiableVariable contextIt
      = contextVars(sv).iterator();
        while (contextIt.hasNext()) {
      names.add(contextIt.next().name());
        }
    }
    IteratorOfSchemaVariable varSVIt=prefix.iterator();
    while(varSVIt.hasNext()) {
        SchemaVariable varSV=varSVIt.next();
        Term inst = (Term)
      instantiations().getInstantiation(varSV);
        if (inst!=null) {
      Name name = inst.op().name();
      if (!names.contains(name)) {
          names.add(name);
      } else {
          return varSV;
      }
        }
    }
      }
  }
  return null;
    }


    /**
     * For a given SV of the taclet decide a priori whether an
     * instantiation via metavariable is possible
     * @return true iff p_var is a termSV with empty prefix
     */
    public boolean canUseMVAPriori ( SchemaVariable p_var ) {
  if ( !p_var.isTermSV () ||
       fixedVars.contains ( p_var ) )
      return false;
  else {
      TacletPrefix prefix = taclet ().getPrefix ( p_var );
      return (prefix.prefix ().size () == 0 && !prefix.context ());
  }
    }


    /**
     * For a given SV of the taclet decide a posteriori whether an
     * instantiation via metavariable is possible
     * @param p_term Term to instantiate the schemavariable with
     */
    protected boolean canUseMVAPosteriori ( SchemaVariable p_var, Term p_term ) {
        // disabled
        return false;
//  return canUseMVAPriori ( p_var ) && p_term.isRigid ();
    }    


    /**
     * @return true iff the list of if instantiations has the correct
     * size or is null
     */
    protected static boolean ifInstsCorrectSize ( Taclet                       p_taclet,
              ListOfIfFormulaInstantiation p_list ) {        
  return p_list == null ||
      p_list.size () == ( p_taclet.ifSequent ().antecedent ().size () +
        p_taclet.ifSequent ().succedent  ().size () );
    }

    /**
     * @return true iff the Taclet may be applied for the
     * given mode (interactive/non-interactive, activated rule sets)
     */
    public boolean admissible(boolean       interactive,
            ListOfRuleSet ruleSets) {
  return taclet ().admissible (interactive, ruleSets);
    }

    /** checks if the variable conditions of type 'x not free in y' are
     * hold by the found instantiations. The variable conditions is used
     * implicit in the prefix. (Used to calculate the prefix)
     * @param taclet the Taclet that is tried to be instantiated. A match for the
     * find (or/and if) has been found.
     * @param instantiations the SVInstantiations so that the find(if)
     * expression matches
     * @param pos the PosInOccurrence where the Taclet is applied
     * @return true iff all variable conditions x not free in y are hold
     */
    public static boolean checkVarCondNotFreeIn
  ( Taclet taclet, SVInstantiations instantiations, PosInOccurrence pos ) {
        
        IteratorOfSchemaVariable it = instantiations.svIterator();
  while (it.hasNext()) {
      SchemaVariable sv = it.next();
      if (sv.isTermSV() || sv.isFormulaSV()) {
    if (!((Term)instantiations.getInstantiation(sv)).
        freeVars().subset(boundAtOccurrenceSet
              (taclet.getPrefix(sv), 
               instantiations, pos))) {
          
        return false;
    }
      }
  }
  return true;
    }

    /** collects all bound vars that are bound above the subterm described by
     * the given term position information
     * @param pos the PosInOccurrence describing a subterm in Term
     * @return a set of logic variables that are bound above the specified
     * subterm 
     */
    protected static SetOfQuantifiableVariable collectBoundVarsAbove
  ( PosInOccurrence pos ) {
  SetOfQuantifiableVariable result = SetAsListOfQuantifiableVariable.EMPTY_SET;
    
  PIOPathIterator             it   = pos.iterator ();
  int                         i;
  ArrayOfQuantifiableVariable vars;
    
  while ( ( i = it.next () ) != -1 ) {
      vars = it.getSubTerm ().varsBoundHere ( i );
      for ( i = 0; i < vars.size (); i++ ) 
    result = result.add ( vars.getQuantifiableVariable ( i ) );
  }
    
  return result;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.