From ec38d6639d762110d414a0ffecec017d4ec0cc4d Mon Sep 17 00:00:00 2001 From: jzhou Date: Wed, 24 Nov 2010 23:56:24 +0000 Subject: [PATCH] Enable Switch-case statement for mgc version --- Robust/src/IR/Flat/BuildFlat.java | 92 +++++++++++++++++++ Robust/src/IR/Tree/BuildIR.java | 28 ++++++ Robust/src/IR/Tree/Kind.java | 3 + Robust/src/IR/Tree/SemanticCheck.java | 51 ++++++++++- Robust/src/Parse/java14.cup | 127 +++++++++++++++++++------- Robust/src/Tests/SwitchCaseTest.java | 38 ++++++++ 6 files changed, 305 insertions(+), 34 deletions(-) create mode 100644 Robust/src/Tests/SwitchCaseTest.java diff --git a/Robust/src/IR/Flat/BuildFlat.java b/Robust/src/IR/Flat/BuildFlat.java index 6a6219e4..97b697b7 100644 --- a/Robust/src/IR/Flat/BuildFlat.java +++ b/Robust/src/IR/Flat/BuildFlat.java @@ -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 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); diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index 2e9f1aa2..aef10756 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -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 slv = new Vector(); + for(int j=0; j 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 { diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 9ee773bb..6f129037 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -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 index 00000000..96999089 --- /dev/null +++ b/Robust/src/Tests/SwitchCaseTest.java @@ -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 +... +*///:~ -- 2.34.1