Enable Switch-case statement for mgc version
authorjzhou <jzhou>
Wed, 24 Nov 2010 23:56:24 +0000 (23:56 +0000)
committerjzhou <jzhou>
Wed, 24 Nov 2010 23:56:24 +0000 (23:56 +0000)
Robust/src/IR/Flat/BuildFlat.java
Robust/src/IR/Tree/BuildIR.java
Robust/src/IR/Tree/Kind.java
Robust/src/IR/Tree/SemanticCheck.java
Robust/src/Parse/java14.cup
Robust/src/Tests/SwitchCaseTest.java [new file with mode: 0644]

index 6a6219e427ab0cc94bb6e10b3323fa8ecae055d1..97b697b789a8341b0effd4f6fc083d4860644f3c 100644 (file)
@@ -1,6 +1,7 @@
 package IR.Flat;
 import IR.*;
 import IR.Tree.*;
+
 import java.util.*;
 
 public class BuildFlat {
@@ -1050,7 +1051,95 @@ public class BuildFlat {
 
     return new NodePair(cond.getBegin(), nopend);
   }
+  
+  private NodePair flattenSwitchStatementNode(SwitchStatementNode ssn) {
+    TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.INT));
+    NodePair cond=flattenExpressionNode(ssn.getCondition(),cond_temp);
+    FlatNop nopend=new FlatNop();
+    NodePair sbody = flattenSwitchBodyNode(ssn.getSwitchBody(), cond_temp, nopend);
+    
+    cond.getEnd().addNext(sbody.getBegin());
 
+    return new NodePair(cond.getBegin(), sbody.getEnd());
+  }
+  
+  private NodePair flattenSwitchBodyNode(BlockNode bn, TempDescriptor cond_temp, FlatNode endnode) {
+    FlatNode begin=null;
+    FlatNode end=endnode;
+    NodePair prev_true_branch = null;
+    NodePair prev_false_branch = null;
+    for(int i=0; i<bn.size(); i++) {
+      SwitchBlockNode sbn = (SwitchBlockNode)bn.get(i);
+      HashSet oldbs=breakset;
+      breakset=new HashSet();
+      
+      NodePair body=flattenBlockNode(sbn.getSwitchBlockStatement());
+      Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
+      FlatNode cond_begin = null;
+      NodePair prev_fnp = null;
+      for(int j = 0; j < slnv.size(); j++) {
+        SwitchLabelNode sln = slnv.elementAt(j);
+        NodePair left = null;
+        NodePair false_np = null;
+        if(sln.isDefault()) {
+          left = body;
+        } else {
+          TempDescriptor cond_tmp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
+          TempDescriptor temp_left=TempDescriptor.tempFactory("leftop", sln.getCondition().getType());
+          Operation op=new Operation(Operation.EQUAL);
+          left=flattenExpressionNode(sln.getCondition(), temp_left);
+          FlatOpNode fon=new FlatOpNode(cond_tmp, temp_left, cond_temp, op);
+          left.getEnd().addNext(fon);
+
+          FlatCondBranch fcb=new FlatCondBranch(cond_tmp);
+          fcb.setTrueProb(State.TRUEPROB);
+
+          FlatNop nop=new FlatNop();
+          false_np=new NodePair(nop,nop);
+
+          fon.addNext(fcb);
+          fcb.addTrueNext(body.getBegin());
+          fcb.addFalseNext(false_np.getBegin());
+        }
+        if((prev_fnp != null) && (prev_fnp.getEnd() != null)) {
+          prev_fnp.getEnd().addNext(left.getBegin());
+        }
+        prev_fnp = false_np;
+        
+        if (begin==null) {
+          begin = left.getBegin();
+        }
+        if(cond_begin == null) {
+          cond_begin = left.getBegin();
+        }
+      }
+      if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
+        prev_false_branch.getEnd().addNext(cond_begin);
+      }
+      prev_false_branch = prev_fnp;
+      if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
+        prev_true_branch.getEnd().addNext(body.getBegin());
+      }
+      prev_true_branch = body;
+      for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
+        FlatNode fn=(FlatNode)breakit.next();
+        breakit.remove();
+        fn.addNext(endnode);
+      }
+      breakset=oldbs;
+    }
+    if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
+      prev_true_branch.getEnd().addNext(endnode);
+    }
+    if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
+      prev_false_branch.getEnd().addNext(endnode);
+    }
+    if(begin == null) {
+      end=begin=new FlatNop();
+    }
+    return new NodePair(begin,end);
+  }
+  
   private NodePair flattenLoopNode(LoopNode ln) {
     HashSet oldbs=breakset;
     HashSet oldcs=continueset;
@@ -1380,6 +1469,9 @@ public class BuildFlat {
 
     case Kind.IfStatementNode:
       return flattenIfStatementNode((IfStatementNode)bsn);
+      
+    case Kind.SwitchStatementNode:
+      return flattenSwitchStatementNode((SwitchStatementNode)bsn);
 
     case Kind.LoopNode:
       return flattenLoopNode((LoopNode)bsn);
index 2e9f1aa247de83f80bcc483ff0b19388e2ad855e..aef1075662b7ebc614296305149ae54e4fa213ed 100644 (file)
@@ -1030,6 +1030,34 @@ public class BuildIR {
       blockstatements.add(new IfStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
                                               parseSingleBlock(pn.getChild("statement").getFirstChild()),
                                               pn.getChild("else_statement")!=null ? parseSingleBlock(pn.getChild("else_statement").getFirstChild()) : null));
+    } else if ((state.MGC) && (isNode(pn,"switch_statement"))) {
+      // TODO add version for normal Java later
+      blockstatements.add(new SwitchStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
+          parseSingleBlock(pn.getChild("statement").getFirstChild())));
+    } else if ((state.MGC) && (isNode(pn,"switch_block_list"))) {
+      // TODO add version for normal Java later
+      ParseNodeVector pnv=pn.getChildren();
+      for(int i=0; i<pnv.size(); i++) {
+        ParseNode sblockdecl=pnv.elementAt(i);
+        
+        if(isNode(sblockdecl, "switch_block")) {
+          ParseNode lpn=sblockdecl.getChild("switch_labels").getChild("switch_label_list");
+          ParseNodeVector labelv=lpn.getChildren();
+          Vector<SwitchLabelNode> slv = new Vector<SwitchLabelNode>();
+          for(int j=0; j<labelv.size(); j++) {
+            ParseNode labeldecl=labelv.elementAt(j);
+            if(isNode(labeldecl, "switch_label")) {
+              slv.addElement(new SwitchLabelNode(parseExpression(labeldecl.getChild("constant_expression").getFirstChild()), false));
+            } else if(isNode(labeldecl, "default_switch_label")) {
+              slv.addElement(new SwitchLabelNode(null, true));
+            }
+          }
+          
+          blockstatements.add(new SwitchBlockNode(slv, 
+              parseSingleBlock(sblockdecl.getChild("switch_statements").getFirstChild())));
+          
+        }
+      }
     } else if (isNode(pn,"taskexit")) {
       Vector vfe=null;
       if (pn.getChild("flag_effects_list")!=null)
index 4bbe21fa1de2e5015247e8546b6ce2fc0841a086..38edb43ed782fe820d4aa66f4b40dd43e0a979af 100644 (file)
@@ -30,4 +30,7 @@ public class Kind {
   public final static int ArrayInitializerNode=27;
   public final static int SynchronizedNode=28;
   public final static int GenReachNode=29;
+  public final static int SwitchStatementNode=30;
+  public final static int SwitchLabelNode=31;
+  public final static int SwitchBlockNode=32;
 }
index ba82bb1ba9f47dbfe45c7005e9e4294061c80c40..a629acadc836801fe31bc92fbfb7b3e90bb91645 100644 (file)
@@ -297,6 +297,10 @@ public class SemanticCheck {
     case Kind.IfStatementNode:
       checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
       return;
+      
+    case Kind.SwitchStatementNode:
+      checkSwitchStatementNode(md, nametable, (SwitchStatementNode)bsn);
+      return;
 
     case Kind.LoopNode:
       checkLoopNode(md, nametable, (LoopNode)bsn);
@@ -412,6 +416,51 @@ public class SemanticCheck {
     if (isn.getFalseBlock()!=null)
       checkBlockNode(md, nametable, isn.getFalseBlock());
   }
+  
+  void checkSwitchStatementNode(Descriptor md, SymbolTable nametable, SwitchStatementNode ssn) {
+    checkExpressionNode(md, nametable, ssn.getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+    
+    BlockNode sbn = ssn.getSwitchBody();
+    boolean hasdefault = false;
+    for(int i = 0; i < sbn.size(); i++) {
+      boolean containdefault = checkSwitchBlockNode(md, nametable, (SwitchBlockNode)sbn.get(i));
+      if(hasdefault && containdefault) {
+        throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+      }
+      hasdefault = containdefault;
+    }
+  }
+  
+  boolean checkSwitchBlockNode(Descriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
+    Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
+    int defaultb = 0;
+    for(int i = 0; i < slnv.size(); i++) {
+      if(slnv.elementAt(i).isdefault) {
+        defaultb++;
+      } else {
+        checkConstantExpressionNode(md, nametable, slnv.elementAt(i).getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+      }
+    }
+    if(defaultb > 1) {
+      throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+    } else {
+      checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
+      return (defaultb > 0);
+    }
+  }
+  
+  void checkConstantExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
+    switch(en.kind()) {
+    case Kind.FieldAccessNode:
+      checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
+      return;
+     
+    case Kind.LiteralNode:
+      checkLiteralNode(md,nametable,(LiteralNode)en,td);
+      return;
+    }
+    throw new Error();
+  }
 
   void checkExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
     switch(en.kind()) {
@@ -611,7 +660,7 @@ public class SemanticCheck {
           cd = ((MethodDescriptor)md).getClassDesc();
           SymbolTable fieldtbl = cd.getFieldTable();
           FieldDescriptor fd=(FieldDescriptor)fieldtbl.get(varname);
-          if((fd == null) || (!fd.isStatic()) || (!fd.isVolatile())){
+          if((fd == null) || (!fd.isStatic())){
             // no such field in the class or it is not a static field
             throw new Error("Name "+varname+" should not be used in static block: "+md);
           } else {
index 9ee773bb216b25fa488a01bf17412fd59712e533..6f129037654dbe40a3d4c2c3f79546001a93f8d0 100644 (file)
@@ -177,10 +177,10 @@ non terminal ParseNode empty_statement;
 non terminal ParseNode expression_statement, statement_expression;
 non terminal ParseNode if_then_statement;
 non terminal ParseNode if_then_else_statement, if_then_else_statement_no_short_if;
-//non terminal ParseNode switch_statement, switch_block;
-//non terminal ParseNode switch_block_statement_groups;
-//non terminal ParseNode switch_block_statement_group;
-//non terminal ParseNode switch_labels, switch_label;
+non terminal ParseNode switch_statement, switch_block;
+non terminal ParseNode switch_block_statement_groups;
+non terminal ParseNode switch_block_statement_group;
+non terminal ParseNode switch_labels, switch_label;
 non terminal ParseNode while_statement, while_statement_no_short_if;
 non terminal ParseNode do_statement;
 non terminal ParseNode for_statement, for_statement_no_short_if;
@@ -223,7 +223,7 @@ non terminal ParseNode assignment_expression;
 non terminal ParseNode assignment;
 non terminal ParseNode assignment_operator;
 non terminal ParseNode expression_opt, expression;
-//non terminal ParseNode constant_expression;
+non terminal ParseNode constant_expression;
 //failure aware computation keywords
 terminal FLAG;
 terminal OPTIONAL;
@@ -1328,7 +1328,7 @@ statement_without_trailing_substatement ::=
                block:st {: RESULT=st; :}
        |       empty_statement:st {: RESULT=st; :}
        |       expression_statement:st {: RESULT=st; :}
-//     |       switch_statement
+       |       switch_statement:st {: RESULT=st; :}
        |       do_statement:dos {:RESULT=dos; :}
        |       break_statement:st {: RESULT=st; :}
        |       continue_statement:st {: RESULT=st; :}
@@ -1394,30 +1394,86 @@ if_then_else_statement_no_short_if ::=
                RESULT=pn;
        :}
        ;
-//switch_statement ::=
-//             SWITCH LPAREN expression RPAREN switch_block
-//     ;
-//switch_block ::=
-//             LBRACE switch_block_statement_groups switch_labels RBRACE
-//     |       LBRACE switch_block_statement_groups RBRACE
-//     |       LBRACE switch_labels RBRACE
-//     |       LBRACE RBRACE
-//     ;
-//switch_block_statement_groups ::=
-//             switch_block_statement_group
-//     |       switch_block_statement_groups switch_block_statement_group
-//     ;
-//switch_block_statement_group ::=
-//             switch_labels block_statements
-//     ;
-//switch_labels ::=
-//             switch_label
-//     |       switch_labels switch_label
-//     ;
-//switch_label ::=
-//             CASE constant_expression COLON
-//     |       DEFAULT COLON
-//     ;
+switch_statement ::=
+               SWITCH LPAREN expression:exp RPAREN switch_block:body
+               {:
+                   ParseNode pn=new ParseNode("switch_statement");
+                   pn.addChild("condition").addChild(exp);
+                   pn.addChild("statement").addChild(body);
+                   RESULT=pn;
+               :}
+       ;
+switch_block ::=
+               LBRACE switch_block_statement_groups:sbsg switch_labels:sl RBRACE
+               {: 
+                   ParseNode pn = new ParseNode("switch_block");
+                   pn.addChild("switch_labels").addChild(sl);
+                   pn.addChild("switch_statements").addChild(new ParseNode("empty"));
+                   sbsg.addChild(pn);
+                   RESULT=sbsg; 
+               :}
+       |       LBRACE switch_block_statement_groups:sbsg RBRACE
+           {: 
+                   RESULT=sbsg; 
+               :}
+       |       LBRACE switch_labels:sl RBRACE 
+           {: 
+               ParseNode pnb = new ParseNode("switch_block_list");
+                   ParseNode pn = new ParseNode("switch_block");
+                   pn.addChild("switch_labels").addChild(sl);
+                   pn.addChild("switch_statements").addChild(new ParseNode("empty"));
+                   pnb.addChild(pn);
+                   RESULT=pnb; 
+               :}
+       |       LBRACE RBRACE {: RESULT=new ParseNode("empty"); :}
+       ;
+switch_block_statement_groups ::=
+               switch_block_statement_group:sbsg
+               {: 
+                   ParseNode pn = new ParseNode("switch_block_list");
+                   pn.addChild(sbsg);
+                   RESULT=pn;
+               :}
+       |       switch_block_statement_groups:sbsgs switch_block_statement_group:sbsg
+           {:
+               sbsgs.addChild(sbsg);
+               RESULT=sbsgs;
+           :}
+       ;
+switch_block_statement_group ::=
+               switch_labels:sls block_statements:body
+               {: 
+                   ParseNode pn=new ParseNode("switch_block");
+                   pn.addChild("switch_labels").addChild(sls);
+                   pn.addChild("switch_statements").addChild(body);
+                   RESULT=pn; 
+               :}
+       ;
+switch_labels ::=
+               switch_label:sl
+               {: 
+                   ParseNode pn=new ParseNode("switch_label_list");
+                   pn.addChild(sl);
+                   RESULT=pn; 
+               :}
+       |       switch_labels:sls switch_label:sl
+           {: 
+                   sls.addChild(sl); 
+                   RESULT=sls;
+               :}
+       ;
+switch_label ::=
+               CASE constant_expression:ce COLON
+               {: 
+                   ParseNode pn=new ParseNode("switch_label");
+                   pn.addChild(ce);
+                   RESULT=pn;
+               :}
+       |       DEFAULT COLON
+           {: 
+                   RESULT=new ParseNode("default_switch_label"); 
+               :}
+       ;
 
 while_statement ::=
                WHILE LPAREN expression:exp RPAREN statement:st {: 
@@ -2132,9 +2188,14 @@ expression ::=   assignment_expression:exp {:
        ;
 // note that this constraint must be enforced during semantic checking
 // 'constant_expression' should include enumerated constants.
-//constant_expression ::=
-//             expression
-//     ;
+constant_expression ::=
+               expression:exp 
+               {:
+                   ParseNode pn = new ParseNode("constant_expression");
+                   pn.addChild(exp);
+                   RESULT=pn;
+               :}
+       ;
 
 
 genreach_statement ::=
diff --git a/Robust/src/Tests/SwitchCaseTest.java b/Robust/src/Tests/SwitchCaseTest.java
new file mode 100644 (file)
index 0000000..9699908
--- /dev/null
@@ -0,0 +1,38 @@
+public class SwitchCaseTest {
+  public SwitchCaseTest(){}
+  
+  public static void main(String[] args) {
+    Random rand = new Random(47);
+    for(int i = 0; i < 30; i++) {
+      int c = rand.nextInt(26) + 'a';
+      System.out.printString((char)c + ", " + c + ": ");
+      switch(c) {
+        case 'a':
+        case 'e':
+        case 'i':
+        case 'o':
+        case 'u': System.out.printString("vowel\n");
+                  //break;
+        case 'y':
+        case 'w': System.out.printString("Sometimes a vowel\n");
+                  break;
+        default: System.out.printString("consonant\n");
+      }
+    }
+  }
+} /* Output:
+y, 121: Sometimes a vowel
+n, 110: consonant
+z, 122: consonant
+b, 98: consonant
+r, 114: consonant
+n, 110: consonant
+y, 121: Sometimes a vowel
+g, 103: consonant
+c, 99: consonant
+f, 102: consonant
+o, 111: vowel
+w, 119: Sometimes a vowel
+z, 122: consonant
+...
+*///:~