WaryClashFreeSubst.java :  » Testing » KeY » de » uka » ilkd » key » logic » Java Open Source

Java Open Source » Testing » KeY 
KeY » de » uka » ilkd » key » logic » WaryClashFreeSubst.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.logic;

import de.uka.ilkd.key.logic.op.*;
import de.uka.ilkd.key.rule.soundness.SVSkolemFunction;

public class WaryClashFreeSubst extends ClashFreeSubst {

    /** depth of recursion of the <code>apply</code> method */
    private int                       depth            = 0;
    /** the formula should be prepended with a quantifier */
    private boolean                   createQuantifier = false;

    /** variable with which the original variable should be
     * substituted below modalities */
    private QuantifiableVariable      newVar           = null;
    private Term                      newVarTerm       = null;

    /** variables occurring within the original term and within the
     * term to be substituted */
    private SetOfQuantifiableVariable warysvars            = null;
   
    public WaryClashFreeSubst ( QuantifiableVariable v, Term s ) {
  super ( v, s );
  warysvars = null;
    }

    /** 
     * substitute <code>s</code> for <code>v</code> in <code>t</code>,
     * avoiding collisions by replacing bound variables in
     * <code>t</code> if necessary.
     */
    public Term apply(Term t) {
  Term res;

  if ( depth == 0 ) {
      if ( !getSubstitutedTerm ().isRigid () )
    findUsedVariables ( t );
  }

  ++depth;
  try {
      res = super.apply ( t );
  } finally { --depth; }

  if ( createQuantifier && depth == 0 ) res = addWarySubst ( res );
    
  return res;
    }

    /**
     * Determine a set of variables that do already appear within
     * <code>t</code> or the substituted term, and whose names should
     * not be used for free variables
     */
    private void findUsedVariables ( Term t ) {
  VariableCollectVisitor vcv;

  vcv   = new VariableCollectVisitor ();
  getSubstitutedTerm ().execPostOrder ( vcv );
  warysvars = vcv.vars ();

  vcv   = new VariableCollectVisitor ();
  t.execPostOrder ( vcv );
  warysvars = warysvars.union ( vcv.vars () );  
    }

    /**
     * Create a new logic variable to be used for substitutions below
     * modalities
     */
    private void createVariable () {
  if ( !createQuantifier ) {
      createQuantifier = true;
      
      if ( getSubstitutedTerm ().freeVars ().contains ( getVariable () ) )
                // in this case one might otherwise get collisions, as the
                // substitution might be carried out partially within the scope
                // of the original substitution operator
          newVar = newVarFor ( getVariable (), warysvars );
      else
          newVar = getVariable ();
      newVarTerm = tf.createVariableTerm ( (LogicVariable)newVar );
  }  
    }

    /**
     * substitute <code>s</code> for <code>v</code> in
     * <code>t</code>, avoiding collisions by replacing bound
     * variables in <code>t</code> if necessary.  It is
     * assumed, that <code>t</code> contains a free occurrence of
     * <code>v</code>.
     */
    protected Term apply1(Term t) {
  // don't move to a different modality level
  if ( !getSubstitutedTerm ().isRigid () ) {
      if ( t.op () instanceof Modality )
    return applyOnModality ( t );    
      if ( t.op () instanceof IUpdateOperator )
    return applyOnUpdate   ( t );
      if ( t.op () instanceof SVSkolemFunction )
    return applyToSVSkolem ( t );
  }
  return super.apply1 ( t );
    }

    /**
     * Apply the substitution (that replaces a variable with a
     * non-rigid term) on t, which has a modality as top-level
     * operator. This is done by creating a (top-level) existential
     * quantifier. This method is only called from <code>apply1</code>
     * for substitutions with non-rigid terms
     *
     * PRECONDITION: <code>warysvars != null</code>
     */
    private Term applyOnModality ( Term t ) {
  return applyBelowModality ( t );
    }

    /**
     * Apply the substitution (that replaces a variable with a
     * non-rigid term) on t, which has an update operator as top-level
     * operator. This is done by creating a (top-level) existential
     * quantifier. This method is only called from <code>apply1</code>
     * for substitutions with non-rigid terms
     *
     * PRECONDITION: <code>warysvars != null</code>
     */
    private Term applyOnUpdate ( Term t ) {
        final IUpdateOperator updOp = (IUpdateOperator)t.op ();
        
  // only the last child is below the update
  final Term target = updOp.target ( t );
  if ( !target.freeVars ().contains ( getVariable () ) )
      return super.apply1 ( t );

  final Term[] newSubterms = new Term[t.arity()];
  final ArrayOfQuantifiableVariable[] newBoundVars =
      new ArrayOfQuantifiableVariable[t.arity()];

  for ( int i = 0; i < t.arity (); i++ ) {
            if ( i != updOp.targetPos () )
                applyOnSubterm ( t, i, newSubterms, newBoundVars );
        }

  newBoundVars[updOp.targetPos()] = t.varsBoundHere ( updOp.targetPos() );
        final boolean addSubst =
            subTermChanges ( t.varsBoundHere ( updOp.targetPos () ), target );
        newSubterms[updOp.targetPos ()] = addSubst ? substWithNewVar ( target )
                                                   : target;

        return tf.createTerm ( t.op (),
                               newSubterms,
                               newBoundVars,
                               t.javaBlock ());
    }

    /**
     * Apply the substitution to a term/formula below a modality or update
     */
    private Term applyBelowModality (Term t) {
        return substWithNewVar ( t );
    }

    /**
     * Prepend the given term with a wary substitution (substituting
     * <code>newVar</code> with <code>getSubstitutedTerm()</code>)
     */
    private Term addWarySubst (Term t) {
        createVariable ();
        return tf.createSubstitutionTerm ( Op.SUBST,
                                           newVar,
                                           getSubstitutedTerm (),
                                           t );
    }

    /**
     * Rename the original variable to be substituted to <code>newVar</code> 
     */
    private Term substWithNewVar (Term t) {
        createVariable ();
        final ClashFreeSubst cfs = new ClashFreeSubst ( getVariable (),
                                                        newVarTerm );
        return cfs.apply ( t );
    }
    
    /**
     * Apply the substitution to a non-rigid skolem function
     */
    private Term applyToSVSkolem ( Term t ) {
      return applyBelowModality(t);
    }

}
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.