refactoring the lattice implementation / having a way to declare the variable with...
authoryeom <yeom>
Tue, 15 Mar 2011 02:05:04 +0000 (02:05 +0000)
committeryeom <yeom>
Tue, 15 Mar 2011 02:05:04 +0000 (02:05 +0000)
Robust/src/Analysis/SSJava/CompositeLocation.java [new file with mode: 0644]
Robust/src/Analysis/SSJava/FlowDownCheck.java
Robust/src/Analysis/SSJava/Location.java [new file with mode: 0644]
Robust/src/Analysis/SSJava/NTuple.java [new file with mode: 0644]
Robust/src/Analysis/SSJava/SSJavaAnalysis.java
Robust/src/IR/AnnotationDescriptor.java
Robust/src/IR/Tree/BuildIR.java
Robust/src/Parse/java14.cup
Robust/src/Util/Lattice.java

diff --git a/Robust/src/Analysis/SSJava/CompositeLocation.java b/Robust/src/Analysis/SSJava/CompositeLocation.java
new file mode 100644 (file)
index 0000000..a93d163
--- /dev/null
@@ -0,0 +1,17 @@
+package Analysis.SSJava;
+
+import IR.ClassDescriptor;
+
+public class CompositeLocation extends Location {
+
+  private NTuple<Location> locTuple;
+
+  public CompositeLocation(ClassDescriptor cd) {
+    super(cd);
+  }
+
+  public void addSingleLocation(Location loc) {
+    locTuple.addElement(loc);
+  }
+
+}
index a4b0e6f7b451e56521e44894c2cb962b6e013f08..d31bac8cae19373d318b4983665bc44f50477003 100644 (file)
@@ -3,12 +3,14 @@ package Analysis.SSJava;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.StringTokenizer;
 import java.util.Vector;
 
 import IR.AnnotationDescriptor;
 import IR.ClassDescriptor;
 import IR.FieldDescriptor;
 import IR.MethodDescriptor;
+import IR.Operation;
 import IR.State;
 import IR.SymbolTable;
 import IR.TypeDescriptor;
@@ -20,6 +22,7 @@ import IR.Tree.BlockStatementNode;
 import IR.Tree.DeclarationNode;
 import IR.Tree.ExpressionNode;
 import IR.Tree.Kind;
+import IR.Tree.OpNode;
 import Util.Lattice;
 
 public class FlowDownCheck {
@@ -154,6 +157,10 @@ public class FlowDownCheck {
     case Kind.AssignmentNode:
       checkAssignmentNode(md, nametable, (AssignmentNode) en, td);
       return;
+
+    case Kind.OpNode:
+      checkOpNode(md, nametable, (OpNode) en, td);
+      return;
     }
     /*
      * switch(en.kind()) { case Kind.AssignmentNode:
@@ -197,18 +204,114 @@ public class FlowDownCheck {
      */
   }
 
+  void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, TypeDescriptor td) {
+
+    Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(md.getClassDesc());
+
+    checkExpressionNode(md, nametable, on.getLeft(), null);
+    if (on.getRight() != null)
+      checkExpressionNode(md, nametable, on.getRight(), null);
+
+    TypeDescriptor ltd = on.getLeft().getType();
+    TypeDescriptor rtd = on.getRight() != null ? on.getRight().getType() : null;
+
+    if (ltd.getAnnotationMarkers().size() == 0) {
+      // constant value
+      // TODO
+      // ltd.addAnnotationMarker(new AnnotationDescriptor(Lattice.TOP));
+    }
+    if (rtd != null && rtd.getAnnotationMarkers().size() == 0) {
+      // constant value
+      // TODO
+      // rtd.addAnnotationMarker(new AnnotationDescriptor(Lattice.TOP));
+    }
+
+    System.out.println("checking op node");
+    System.out.println("td=" + td);
+    System.out.println("ltd=" + ltd);
+    System.out.println("rtd=" + rtd);
+
+    Operation op = on.getOp();
+
+    switch (op.getOp()) {
+
+    case Operation.UNARYPLUS:
+    case Operation.UNARYMINUS:
+    case Operation.LOGIC_NOT:
+      // single operand
+      on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
+      break;
+
+    case Operation.LOGIC_OR:
+    case Operation.LOGIC_AND:
+    case Operation.COMP:
+    case Operation.BIT_OR:
+    case Operation.BIT_XOR:
+    case Operation.BIT_AND:
+    case Operation.ISAVAILABLE:
+    case Operation.EQUAL:
+    case Operation.NOTEQUAL:
+    case Operation.LT:
+    case Operation.GT:
+    case Operation.LTE:
+    case Operation.GTE:
+    case Operation.ADD:
+    case Operation.SUB:
+    case Operation.MULT:
+    case Operation.DIV:
+    case Operation.MOD:
+    case Operation.LEFTSHIFT:
+    case Operation.RIGHTSHIFT:
+    case Operation.URIGHTSHIFT:
+
+      Set<String> operandSet = new HashSet<String>();
+      String leftLoc = ltd.getAnnotationMarkers().get(0).getMarker();
+      String rightLoc = rtd.getAnnotationMarkers().get(0).getMarker();
+
+      operandSet.add(leftLoc);
+      operandSet.add(rightLoc);
+
+      // TODO
+      // String glbLoc = locOrder.getGLB(operandSet);
+      // on.getType().addAnnotationMarker(new AnnotationDescriptor(glbLoc));
+      // System.out.println(glbLoc + "<-" + leftLoc + " " + rightLoc);
+
+      break;
+
+    default:
+      throw new Error(op.toString());
+    }
+
+    if (td != null) {
+      String lhsLoc = td.getAnnotationMarkers().get(0).getMarker();
+      if (locOrder.isGreaterThan(lhsLoc, on.getType().getAnnotationMarkers().get(0).getMarker())) {
+        throw new Error("The location of LHS is higher than RHS: " + on.printNode(0));
+      }
+    }
+
+  }
+
   void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
       TypeDescriptor td) {
 
+    boolean postinc = true;
+    if (an.getOperation().getBaseOp() == null
+        || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
+            .getBaseOp().getOp() != Operation.POSTDEC))
+      postinc = false;
+    if (!postinc)
+      checkExpressionNode(md, nametable, an.getSrc(), td);
+
     ClassDescriptor cd = md.getClassDesc();
     Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd);
 
+    System.out.println("an=" + an.printNode(0));
     String destLocation = an.getDest().getType().getAnnotationMarkers().elementAt(0).getMarker();
     String srcLocation = an.getSrc().getType().getAnnotationMarkers().elementAt(0).getMarker();
 
     if (!locOrder.isGreaterThan(srcLocation, destLocation)) {
-      throw new Error("Value flow from " + srcLocation + " to " + destLocation
-          + "does not respect location hierarchy.");
+      throw new Error("The value flow from " + srcLocation + " to " + destLocation
+          + " does not respect location hierarchy.");
     }
 
   }
@@ -230,13 +333,35 @@ public class FlowDownCheck {
       throw new Error(vd.getSymbol() + " has more than one location.");
     }
 
-    // check if location is defined
-    String locationID = annotationVec.elementAt(0).getMarker();
-    Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
+    AnnotationDescriptor ad = annotationVec.elementAt(0);
+
+    if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
 
-    if (lattice == null || (!lattice.containsKey(locationID))) {
-      throw new Error("Location " + locationID
-          + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
+      // check if location is defined
+      String locationID = ad.getMarker();
+      Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
+
+
+      if (lattice == null || (!lattice.containsKey(locationID))) {
+        throw new Error("Location " + locationID
+            + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
+      }
+
+    } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
+      if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
+
+        if (ad.getData().length() == 0) {
+          throw new Error("Delta function of " + vd.getSymbol() + " does not have any locations: "
+              + cd.getSymbol() + ".");
+        }
+
+        StringTokenizer token = new StringTokenizer(ad.getData(), ",");
+        while (token.hasMoreTokens()) {
+          String deltaOperand = token.nextToken();
+
+        }
+
+      }
     }
 
   }
@@ -276,12 +401,30 @@ public class FlowDownCheck {
     }
 
     // check if location is defined
-    String locationID = annotationVec.elementAt(0).getMarker();
-    Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
+    AnnotationDescriptor ad = annotationVec.elementAt(0);
+    if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
+      String locationID = annotationVec.elementAt(0).getMarker();
+      Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
+
+
+      if (lattice == null || (!lattice.containsKey(locationID))) {
+        throw new Error("Location " + locationID
+            + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
+      }
+    } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
+      if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
 
-    if (lattice == null || (!lattice.containsKey(locationID))) {
-      throw new Error("Location " + locationID
-          + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
+        if (ad.getData().length() == 0) {
+          throw new Error("Delta function of " + fd.getSymbol() + " does not have any locations: "
+              + cd.getSymbol() + ".");
+        }
+
+        StringTokenizer token = new StringTokenizer(ad.getData(), ",");
+        while (token.hasMoreTokens()) {
+          String deltaOperand = token.nextToken();
+          // TODO: set delta operand to corresponding type descriptor
+        }
+      }
     }
 
   }
diff --git a/Robust/src/Analysis/SSJava/Location.java b/Robust/src/Analysis/SSJava/Location.java
new file mode 100644 (file)
index 0000000..ca0ec5a
--- /dev/null
@@ -0,0 +1,73 @@
+package Analysis.SSJava;
+
+import IR.ClassDescriptor;
+
+public class Location {
+
+  public static final int TOP = 1;
+  public static final int NORMAL = 2;
+  public static final int BOTTOM = 3;
+
+  private int type;
+  private ClassDescriptor cd;
+  private String loc;
+
+  public Location(ClassDescriptor cd, String loc) {
+    this.cd = cd;
+    this.loc = loc;
+    this.type = NORMAL;
+  }
+
+  public Location(ClassDescriptor cd) {
+    this.cd = cd;
+  }
+
+  public void setType(int type) {
+    this.type = type;
+  }
+
+  public ClassDescriptor getClassDescriptor() {
+    return cd;
+  }
+
+  public String getLocIdentifier() {
+    return loc;
+  }
+
+  public int getType() {
+    return this.type;
+  }
+
+  public boolean equals(Object o) {
+    if (!(o instanceof Location)) {
+      return false;
+    }
+
+    Location loc = (Location) o;
+
+    if (loc.getClassDescriptor().equals(getClassDescriptor())) {
+      if (loc.getLocIdentifier() == null || getLocIdentifier() == null) {
+        if (loc.getType() == getType()) {
+          return true;
+        }
+      } else {
+        if (loc.getLocIdentifier().equals(getLocIdentifier())) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  public int hashCode() {
+
+    int hash = cd.hashCode();
+    if (loc != null) {
+      hash += loc.hashCode();
+    }
+    return hash;
+
+  }
+
+}
diff --git a/Robust/src/Analysis/SSJava/NTuple.java b/Robust/src/Analysis/SSJava/NTuple.java
new file mode 100644 (file)
index 0000000..77c81fd
--- /dev/null
@@ -0,0 +1,45 @@
+package Analysis.SSJava;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NTuple<T> {
+
+  private List<T> elements;
+
+  public NTuple(T ... elements) {
+    this.elements = Arrays.asList(elements);
+  }
+
+  public String toString() {
+    return elements.toString();
+  }
+
+  public T at(int index) {
+    return elements.get(index);
+  }
+
+  public int size() {
+    return elements.size();
+  }
+
+  public void addElement(T newElement) {
+    this.elements.add(newElement);
+  }
+
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || o.getClass() != this.getClass()) {
+      return false;
+    }
+    return (((NTuple) o).elements).equals(elements);
+  }
+
+  public int hashCode() {
+    return elements.hashCode();
+  }
+
+}
index 35cd5500d7fe038a0d45c53342606f24d95c59d3..68065bf885e343046690ee9af3830a6c30c5e437 100644 (file)
@@ -6,6 +6,7 @@ import IR.State;
 
 public class SSJavaAnalysis {
 
+  public static final String DELTA = "delta";
   State state;
   HashSet toanalyze;
 
index f831378d0ce0987507e2db554a5a5627cafcce6f..1f81496824b9b8297326bd1adca32c360df00c98 100644 (file)
@@ -9,7 +9,7 @@ public class AnnotationDescriptor extends Descriptor {
   public static final int FULL_ANNOTATION = 3;
 
   private String marker;
-  private Set arrayedValues; // for single annotation
+  private String data; // for single annotation
   private int type;
 
   public AnnotationDescriptor(String annotationName) {
@@ -19,6 +19,14 @@ public class AnnotationDescriptor extends Descriptor {
     this.type = MARKER_ANNOTATION;
   }
 
+  public AnnotationDescriptor(String annotationName, String data) {
+    // constructor for marker annotation
+    super(annotationName);
+    this.marker = annotationName;
+    this.type = SINGLE_ANNOTATION;
+    this.data = data;
+  }
+
   public int getType() {
     return type;
   }
@@ -38,6 +46,10 @@ public class AnnotationDescriptor extends Descriptor {
   public String getMarker() {
     return marker;
   }
+  
+  public String getData(){
+    return data;
+  }
 
   public boolean equals(Object o) {
     if (o instanceof AnnotationDescriptor) {
index b2e2a1ec0378dee173f2cdaedbae655c6a4daa7d..ef028a6186ffbdef024131b54d27fe529777c87f 100644 (file)
@@ -4,7 +4,6 @@ import Util.Lattice;
 
 import java.util.*;
 
-import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;
 
 
 public class BuildIR {
@@ -142,12 +141,12 @@ public class BuildIR {
     }
   }
 
- public void parseInitializers(ClassDescriptor cn){
-       Vector fv=cn.getFieldVec();
+public void parseInitializers(ClassDescriptor cn){
+  Vector fv=cn.getFieldVec();
     int pos = 0;
-       for(int i=0;i<fv.size();i++) {
-           FieldDescriptor fd=(FieldDescriptor)fv.get(i);
-           if(fd.getExpressionNode()!=null) {
+  for(int i=0;i<fv.size();i++) {
+      FieldDescriptor fd=(FieldDescriptor)fv.get(i);
+      if(fd.getExpressionNode()!=null) {
          Iterator methodit = cn.getMethods();
           while(methodit.hasNext()){
             MethodDescriptor currmd=(MethodDescriptor)methodit.next();
@@ -159,8 +158,8 @@ public class BuildIR {
             }
           }
           pos++;
-           }
-       }
+      }
+  }
     }  
 
   private ClassDescriptor parseEnumDecl(ClassDescriptor cn, ParseNode pn) {
@@ -495,17 +494,18 @@ public class BuildIR {
     }
   }
   
-  private void parseLocationOrder(ClassDescriptor cd, ParseNode pn){
-    ParseNodeVector pnv=pn.getChildren();
-    Lattice<String> locOrder=new Lattice<String>();
-    for(int i=0; i<pnv.size(); i++) {
-      ParseNode loc=pnv.elementAt(i);
+  private void parseLocationOrder(ClassDescriptor cd, ParseNode pn) {
+    ParseNodeVector pnv = pn.getChildren();
+    Lattice<String> locOrder =
+        new Lattice<String>("_top_","_bottom_");
+    for (int i = 0; i < pnv.size(); i++) {
+      ParseNode loc = pnv.elementAt(i);
       String lowerLoc=loc.getChildren().elementAt(0).getLabel();
-      String higherLoc=loc.getChildren().elementAt(1).getLabel();
+      String higherLoc= loc.getChildren().elementAt(1).getLabel();
       locOrder.put(higherLoc, lowerLoc);
-      locOrder.put(lowerLoc,null);
-      if(locOrder.isIntroducingCycle(higherLoc)){
-        throw new Error("Error: the order relation "+lowerLoc+" < "+higherLoc+" introduces a cycle.");
+      if (locOrder.isIntroducingCycle(higherLoc)) {
+        throw new Error("Error: the order relation " + lowerLoc + " < " + higherLoc
+            + " introduces a cycle.");
       }
     }
     state.addLocationOrder(cd, locOrder);
@@ -1369,21 +1369,22 @@ public class BuildIR {
     return m;
   }
   
-  private void parseAnnotationList(ParseNode pn, Modifiers m){
-      ParseNodeVector pnv=pn.getChildren();
-      for(int i=0; i<pnv.size(); i++) {
-        ParseNode body_list=pnv.elementAt(i);
-        if(isNode(body_list,"annotation_body")){
-          ParseNode body_node=body_list.getFirstChild();
-          if (isNode(body_node,"marker_annotation")){          
-            m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
-          }else if(isNode(body_node,"single_annotation")){
-            throw new Error("Annotation with single piece of data is not supported yet.");
-          } else if(isNode(body_node,"normal_annotation")){
-            throw new Error("Annotation with multiple data members is not supported yet.");
-          }   
+  private void parseAnnotationList(ParseNode pn, Modifiers m) {
+    ParseNodeVector pnv = pn.getChildren();
+    for (int i = 0; i < pnv.size(); i++) {
+      ParseNode body_list = pnv.elementAt(i);
+      if (isNode(body_list, "annotation_body")) {
+        ParseNode body_node = body_list.getFirstChild();
+        if (isNode(body_node, "marker_annotation")) {
+          m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
+        } else if (isNode(body_node, "single_annotation")) {
+          m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal(),
+              body_node.getChild("element_value").getTerminal()));
+        } else if (isNode(body_node, "normal_annotation")) {
+          throw new Error("Annotation with multiple data members is not supported yet.");
         }
-      }    
+      }
+    }
   }
 
   private boolean isNode(ParseNode pn, String label) {
index d25c325b668c1330d58cf46de56b0617a162319a..c6b069ff875c1e4703b0bbbfcb6b76390e613d6f 100644 (file)
@@ -839,7 +839,7 @@ marker_annotation_body ::=
        :}
         ;
 single_element_annotation_body ::=
-                IDENTIFIER:id LPAREN element_value:ev RPAREN {:
+                IDENTIFIER:id LPAREN STRING_LITERAL:ev RPAREN {:
                 ParseNode pn=new ParseNode("single_annotation");
                pn.addChild("name").addChild(id);
                pn.addChild("element_value").addChild(ev);
index d687ded962e7d0131eccf00edee5eb74aae0da28..feb71d791ad385615c9bf51ad02973721a4a08f7 100644 (file)
@@ -6,24 +6,60 @@ import java.util.Iterator;
 import java.util.Set;
 
 public class Lattice<T> {
+
   private Hashtable<T, Set<T>> table;
   int size;
 
-  public Lattice() {
+  private T top;
+  private T bottom;
+
+  public Lattice(T top, T bottom) {
     table = new Hashtable<T, Set<T>>();
+    this.top = top;
+    this.bottom = bottom;
+
+    table.put(top, new HashSet<T>());
+
+  }
+
+  public T getTopItem() {
+    return top;
+  }
+
+  public T getBottomItem() {
+    return bottom;
   }
 
   public boolean put(T key, T value) {
     Set<T> s;
+
+    Set<T> topNeighbor = table.get(top);
+
     if (table.containsKey(key)) {
       s = table.get(key);
     } else {
+      // new key, need to be connected with top
+      topNeighbor.add(key);
+
       s = new HashSet<T>();
       table.put(key, s);
     }
-    if (value!=null && !s.contains(value)) {
+    if (value != null && !s.contains(value)) {
       size++;
       s.add(value);
+
+      if (!table.containsKey(value)) {
+        Set<T> lowerNeighbor = new HashSet<T>();
+        lowerNeighbor.add(bottom);
+        table.put(value, lowerNeighbor);
+      }
+
+      // if value is already connected with top, it is no longer to be
+      topNeighbor.remove(value);
+
+      // if key is already connected with bottom,, it is no longer to be
+      table.get(key).remove(getBottomItem());
+
       return true;
     } else
       return false;