Package ai.cfg.verifiers

Source Code of ai.cfg.verifiers.VariablesVerifier$ComputeVariablesSemantics

package ai.cfg.verifiers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.InstanceofExpression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;

import ai.actions.AnalysisErrorHandler;
import ai.cfg.CFGVertice;
import ai.cfg.MethodControlFlowGraph;
import ai.common.Pair;
import ai.domain.AbstractSemanticsIntf;
import ai.domain.DomainIntf;
import ai.domain.Variable;
import ai.domain.expressions.AbstractExpressionVisitor;
import ai.domain.intervals.eval.EvaluationUtils;
import ai.domain.widening.DefaultWideningOperator;
import ai.domain.widening.WideningOperator;
import ai.interpreter.Interpreter;
import ai.interpreter.StopCondition;

public class VariablesVerifier {
  public static class VerifierException extends RuntimeException{
    private static final long serialVersionUID = -1202020406445208236L;

    public VerifierException(String format, Object... args) {
      super(String.format(format, args));
    }
  }
 
  private static class Variables implements DomainIntf<Variables>{
    private final Set<Variable> vars;
   
    public Variables(Set<Variable> vars) {
      this.vars = vars;
    }

    @Override
    public boolean isBottom() {
      return false;
    }

    @Override
    public boolean isTop() {
      return false;
    }

    @Override
    public Variables join(Variables other) {
      if (!vars.equals(other.vars))
        throw new VerifierException("Not the same variable sets");
      return this;
    }

    @Override
    public Variables meet(Variables other) {
      throw new VerifierException("Not handled");
    }

    @Override
    public Variables widen(Variables other) {
      return join(other);
    }

    @Override
    public boolean leq(Variables other) {
      return false;
    }

    @Override
    public boolean equals(Variables other) {
      return this.vars.equals(other.vars);
    }

    @Override
    public Variables getBottom() {
      throw new VerifierException("Not handled");
    }
   
    private Variable getVar(SimpleName name){
      Variable var = EvaluationUtils.tryGetVariable(name);     
      if (var == null)
        throw new VerifierException("null variable");
      return var;
    }
   
    private Variables addVariable(SimpleName name, boolean asAssignment) {
      Variable var = getVar(name);
      if (asAssignment) {
        if (!vars.contains(var))
          throw new VerifierException("missing variable");
        return this;
      }
      if (vars.contains(var))
        throw new VerifierException("variable already exists");
      HashSet<Variable> newVars = new HashSet<Variable>(vars);
      newVars.add(var);
      return new Variables(newVars);
    }

    private Variables removeVariables(Collection<SimpleName> namesToRemove) {
      HashSet<Variable> newVars = new HashSet<Variable>(vars);
      for(SimpleName name: namesToRemove) {
        Variable var = getVar(name);     
        if (!newVars.contains(var))
          throw new VerifierException("variable not present");
        newVars.remove(var);
      }
      return new Variables(newVars);
    }
   
    public String toString(){
      return "Variables(" + vars +")";
    }
  }
 
  private static class VarExpressionVisitor extends AbstractExpressionVisitor {
    private final Set<Variable> vars;

    public VarExpressionVisitor(Set<Variable> vars){
      this.vars = vars;
    }

    @Override
    public boolean visit(ArrayAccess node) {
      return true;
    }

    @Override
    public boolean visit(ArrayCreation node) {
      return true;
    }

    @Override
    public boolean visit(ArrayInitializer node) {
      return true;
    }

    @Override
    public boolean visit(Assignment node) {
      return true;
    }

    @Override
    public boolean visit(BooleanLiteral node) {
      return true;
    }

    @Override
    public boolean visit(CastExpression node) {
      return true;
    }

    @Override
    public boolean visit(CharacterLiteral node) {
      return true;
    }
   
    private void acceptChild(ASTNode node) {
      if (node != null)
        node.accept(this);
    }
   
    private void acceptChildren(List<?> nodes) {
      if (nodes == null)
        return;
      for(Object node: nodes)
        ((ASTNode)node).accept(this);
    }

    @Override
    public boolean visit(ClassInstanceCreation node) {
      //do not visit subclass definition
      acceptChild(node.getExpression());
      acceptChildren(node.arguments());
      return false;
    }

    @Override
    public boolean visit(ConditionalExpression node) {
      return true;
    }

    @Override
    public boolean visit(FieldAccess node) {
      return false;
    }

    @Override
    public boolean visit(InfixExpression node) {
      return true;
    }

    @Override
    public boolean visit(InstanceofExpression node) {
      return true;
    }

    @Override
    public boolean visit(MethodInvocation node) {
      return true;
    }

    @Override
    public boolean visit(SimpleName node) {
      Variable var = EvaluationUtils.tryGetVariable(node);
      if (var!=null && !vars.contains(var))
        throw new VerifierException("Missing variable: '%s' expr: '%s'", var, node);
      return false;
    }

    @Override
    public boolean visit(QualifiedName node) {
      return false;
    }

    @Override
    public boolean visit(NullLiteral node) {
      return false;
    }

    @Override
    public boolean visit(NumberLiteral node) {
      return false;
    }

    @Override
    public boolean visit(ParenthesizedExpression node) {
      return true;
    }

    @Override
    public boolean visit(PostfixExpression node) {
      return true;
    }

    @Override
    public boolean visit(PrefixExpression node) {
      return true;
    }

    @Override
    public boolean visit(StringLiteral node) {
      return false;
    }

    @Override
    public boolean visit(SuperFieldAccess node) {
      return false;
    }

    @Override
    public boolean visit(SuperMethodInvocation node) {
      return true;
    }

    @Override
    public boolean visit(ThisExpression node) {
      return false;
    }

    @Override
    public boolean visit(TypeLiteral node) {
      return false;
    }

    @Override
    public boolean visit(VariableDeclarationExpression node) {
      return false;
    }
   
  }
 
  private static class ComputeVariablesSemantics implements AbstractSemanticsIntf<Variables> {

    @Override
    public Variables processArgument(Variables input, SimpleName name) {
      return input.addVariable(name, false);
    }

    @Override
    public Variables processEmptyEdge(Variables input, List<SimpleName> variablesToRemove) {
      return input.removeVariables(variablesToRemove);
    }

    @Override
    public Variables processExpression(Variables input, Expression expression) {
      expression.accept(new VarExpressionVisitor(input.vars));
      return input;
    }

    @Override
    public Variables processNewVariable(Variables input, SimpleName name, Expression initializerOrNull,
        boolean asAssignment) {
      if (initializerOrNull != null)
        initializerOrNull.accept(new VarExpressionVisitor(input.vars));
      return input.addVariable(name, asAssignment);
    }

    @Override
    public Variables getInitialValue() {
      return new Variables(new HashSet<Variable>());
    }

    @Override
    public Variables processFinallyOrException(Variables input, SingleVariableDeclaration excOrNull) {
      if (excOrNull != null)
        return input.addVariable(excOrNull.getName(), false);
      return input;
    }

    @Override
    public Variables processConstructorInvocation(Variables input, ConstructorInvocation constructorInvocation) {
      constructorInvocation.accept(new VarExpressionVisitor(input.vars));
      return input;
    }

    @Override
    public Variables processSuperConstructorInvocation(Variables input,
        SuperConstructorInvocation superConstructorInvocation) {
      superConstructorInvocation.accept(new VarExpressionVisitor(input.vars));
      return input;
    }

    @Override
    public Pair<Variables, Variables> processCondition(Variables input, Expression conditionOrNull) {
      if (conditionOrNull != null) {
        try {
          conditionOrNull.accept(new VarExpressionVisitor(input.vars));
        } catch (RuntimeException e) {
          System.err.println("Error evaluating: " + conditionOrNull);
          throw e;
        }
      }
      return Pair.create(input, input);
    }

    @Override
    public Pair<Variables, ArrayList<Variables>> processSwitchCases(Variables input, Expression expr,
        Expression[] switchCases) {
      expr.accept(new VarExpressionVisitor(input.vars));
      ArrayList<Variables> res = new ArrayList<Variables>(switchCases.length);
      for(int i=0; i< switchCases.length; i++)
        res.add(input);
      return Pair.create(input, res);
    }

    @Override
    public WideningOperator<Variables> getWideningOperator() {
      return new DefaultWideningOperator<Variables>();
    }
   
  }
 
  public static Map<CFGVertice, Set<Variable>> verifyGraphVariables(MethodControlFlowGraph graph,
      AnalysisErrorHandler aeh) {
    ComputeVariablesSemantics semantics = new ComputeVariablesSemantics();
    Map<CFGVertice, Variables> x;
    try {
      x = Interpreter.analyse(graph, semantics, new StopCondition.NoStopCondition());
    } catch (RuntimeException e) {
      if (aeh.handleError(graph.getCodeFragment(), e, semantics))
        return null;
      throw e;
    }
   
    Map<CFGVertice, Set<Variable>> result = new HashMap<CFGVertice, Set<Variable>>();
    for(Map.Entry<CFGVertice, Variables> entry: x.entrySet())
      result.put(entry.getKey(), entry.getValue().vars);
    return result;
  }
}
TOP

Related Classes of ai.cfg.verifiers.VariablesVerifier$ComputeVariablesSemantics

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.