/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ package x10.compiler.ws.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; import polyglot.ast.Assign; import polyglot.ast.Block; import polyglot.ast.Call; import polyglot.ast.Catch; import polyglot.ast.Do; import polyglot.ast.Eval; import polyglot.ast.Expr; import polyglot.ast.For; import polyglot.ast.If; import polyglot.ast.LocalDecl; import polyglot.ast.Receiver; import polyglot.ast.Return; import polyglot.ast.Stmt; import polyglot.ast.Switch; import polyglot.ast.Term; import polyglot.ast.Try; import polyglot.ast.While; import polyglot.types.MethodDef; import polyglot.types.Name; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.util.Pair; import x10.ast.Async; import x10.ast.AtStmt; import x10.ast.Finish; import x10.ast.FinishExpr; import x10.ast.ForLoop; import x10.ast.Offer; import x10.ast.StmtSeq; import x10.ast.When; import x10.compiler.ws.WSTransformState; import polyglot.types.Context; import polyglot.types.TypeSystem; /** * @author Haichuan * * X10 Work-Stealing can only translate the following patterns directly * finish S => finish frame * async S => async frame * aVar = async S => translate to async{ aVar = S }, and need move aVar in async frame * foo() or a.foo() => invocation to the foo()'s WS wrapper method * aVar = foo() or aVar = a.foo(); => invocation to the foo()'s WS wrapper, * and move results * * And for local decl, * val s; => Just create an inner class field * val s = foo(); => create a inner class field and return trans assign call; * * Besides the previous directly translation, other statements if they contain one of above * code pattern need to be translated. * * Category I: control flows, such as return, if, for forloop, while, do while, switch * These statements will be processed by specific frame generation code * * Category II: compound statements, * e.g. Eval: a = foo(abc()); a = foo() + abc(); * e.g. If: if's condition * e.g. for forloop, while, swtich's condition, updates, and initial codes contains target code * e.g. return's result contains target content * */ public class CodePatternDetector { public static enum Pattern{ Finish, FinishExprAssign, //used in collecting finish Async, At, // at(p) S AsyncAt, // async at(p) S When, LocalDecl, //local declare with the initializer is concurrent call Call, //only the first level call is target call; AssignCall, //only the first level call is target call; If, For, ForLoop, //should not happen after ExpressionFlattener While, DoWhile, Switch, Try, Simple, Block, StmtSeq, //need flatten Unsupport, // async, future's place is not here }; /** * Check an input statement and return the corresponding restored statement * * * @param stmt * @return */ public static Pattern detectAndTransform(final Stmt stmt, final WSTransformState wts){ if(stmt instanceof StmtSeq){ return Pattern.StmtSeq; //the stmt should be unwrapped } if(!WSUtil.isComplexCodeNode(stmt, wts)){ return Pattern.Simple; // no need any transformation } if(stmt instanceof LocalDecl){ return Pattern.LocalDecl; //local decl with concurrent call - should not happen } if(stmt instanceof Async){ Stmt asyncBodyStmt = WSUtil.unwrapToOneStmt(((Async)stmt).body()); if(asyncBodyStmt instanceof AtStmt){ return Pattern.AsyncAt; //async at one place } else{ return Pattern.Async; } } if(stmt instanceof AtStmt){ return Pattern.At; } if(stmt instanceof Finish){ return Pattern.Finish; } if(stmt instanceof When){ return Pattern.When; } if(stmt instanceof Eval){ //After code flatten, the eval should be call/assigncall/finishAssign Expr expr = ((Eval)stmt).expr(); if(expr instanceof Call){ return Pattern.Call; } else if(expr instanceof Assign){ Expr rightExpr = ((Assign)expr).right(); if(rightExpr instanceof Call){ return Pattern.AssignCall; } else if(rightExpr instanceof FinishExpr){ return Pattern.FinishExprAssign; } else { return Pattern.Unsupport; } } else { return Pattern.Unsupport; } } //next if if(stmt instanceof If){ return Pattern.If; } //next For if(stmt instanceof For){ return Pattern.For; } if(stmt instanceof ForLoop){ return Pattern.ForLoop; //Should not happen } if(stmt instanceof While){ return Pattern.While; } if(stmt instanceof Do){ return Pattern.DoWhile; } if(stmt instanceof Switch){ return Pattern.Switch; } if(stmt instanceof Block){ return Pattern.Block; } if(stmt instanceof Try){ //we only support try's block is complex, right now Try tryStmt = (Try)stmt; for(Catch c : tryStmt.catchBlocks()){ if(WSUtil.isComplexCodeNode(c.body(), wts)){ return Pattern.Unsupport; } } if(WSUtil.isComplexCodeNode(tryStmt.finallyBlock(), wts)){ return Pattern.Unsupport; } return Pattern.Try; } //other statements no support right now return Pattern.Unsupport; } /** * Detect whether this pattern is a control flow pattern, * such as block, if, forloop, for, do...while, while, switch * * @param pattern * @return */ public static boolean isControlFlowPattern(Pattern pattern){ if(pattern == Pattern.Block || pattern == Pattern.If || pattern == Pattern.For || pattern == Pattern.ForLoop || pattern == Pattern.DoWhile || pattern == Pattern.While || pattern == Pattern.Switch || pattern == Pattern.FinishExprAssign){ return true; } return false; } }