IRTranslator.java revision 1220:8bbea2def25f
1156952Sume/* 2156952Sume * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3156952Sume * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4156952Sume * 5156952Sume * This code is free software; you can redistribute it and/or modify it 6156952Sume * under the terms of the GNU General Public License version 2 only, as 7156952Sume * published by the Free Software Foundation. Oracle designates this 8156952Sume * particular file as subject to the "Classpath" exception as provided 9156952Sume * by Oracle in the LICENSE file that accompanied this code. 10156952Sume * 11156952Sume * This code is distributed in the hope that it will be useful, but WITHOUT 12156952Sume * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13156952Sume * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14156952Sume * version 2 for more details (a copy is included in the LICENSE file that 15156952Sume * accompanied this code). 16156952Sume * 17156952Sume * You should have received a copy of the GNU General Public License version 18156952Sume * 2 along with this work; if not, write to the Free Software Foundation, 19270838Sume * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20156952Sume * 21270838Sume * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22270838Sume * or visit www.oracle.com if you need additional information or have any 23156952Sume * questions. 24156952Sume */ 25156952Sumepackage jdk.nashorn.api.tree; 26156952Sume 27156952Sumeimport java.util.ArrayList; 28156952Sumeimport java.util.Comparator; 29156952Sumeimport java.util.List; 30156952Sumeimport jdk.nashorn.internal.ir.AccessNode; 31156952Sumeimport jdk.nashorn.internal.ir.BinaryNode; 32156952Sumeimport jdk.nashorn.internal.ir.Block; 33156952Sumeimport jdk.nashorn.internal.ir.BlockStatement; 34156952Sumeimport jdk.nashorn.internal.ir.BreakNode; 35156952Sumeimport jdk.nashorn.internal.ir.CallNode; 36156952Sumeimport jdk.nashorn.internal.ir.CaseNode; 37156952Sumeimport jdk.nashorn.internal.ir.CatchNode; 38156952Sumeimport jdk.nashorn.internal.ir.ContinueNode; 39156952Sumeimport jdk.nashorn.internal.ir.DebuggerNode; 40156952Sumeimport jdk.nashorn.internal.ir.EmptyNode; 41156952Sumeimport jdk.nashorn.internal.ir.ErrorNode; 42156952Sumeimport jdk.nashorn.internal.ir.Expression; 43156952Sumeimport jdk.nashorn.internal.ir.ExpressionStatement; 44156952Sumeimport jdk.nashorn.internal.ir.ForNode; 45165254Sumeimport jdk.nashorn.internal.ir.FunctionNode; 46165254Sumeimport jdk.nashorn.internal.ir.IdentNode; 47165254Sumeimport jdk.nashorn.internal.ir.IfNode; 48165254Sumeimport jdk.nashorn.internal.ir.IndexNode; 49156952Sumeimport jdk.nashorn.internal.ir.LabelNode; 50170242Sumeimport jdk.nashorn.internal.ir.LexicalContext; 51156952Sumeimport jdk.nashorn.internal.ir.LiteralNode; 52156952Sumeimport jdk.nashorn.internal.ir.Node; 53156952Sumeimport jdk.nashorn.internal.ir.ObjectNode; 54156952Sumeimport jdk.nashorn.internal.ir.PropertyNode; 55156952Sumeimport jdk.nashorn.internal.ir.ReturnNode; 56156952Sumeimport jdk.nashorn.internal.ir.RuntimeNode; 57156952Sumeimport jdk.nashorn.internal.ir.SplitNode; 58156952Sumeimport jdk.nashorn.internal.ir.Statement; 59156952Sumeimport jdk.nashorn.internal.ir.SwitchNode; 60156952Sumeimport jdk.nashorn.internal.ir.TernaryNode; 61156952Sumeimport jdk.nashorn.internal.ir.ThrowNode; 62156952Sumeimport jdk.nashorn.internal.ir.TryNode; 63156952Sumeimport jdk.nashorn.internal.ir.UnaryNode; 64156952Sumeimport jdk.nashorn.internal.ir.VarNode; 65156952Sumeimport jdk.nashorn.internal.ir.WhileNode; 66156952Sumeimport jdk.nashorn.internal.ir.WithNode; 67156952Sumeimport jdk.nashorn.internal.ir.visitor.NodeVisitor; 68156952Sumeimport jdk.nashorn.internal.parser.Lexer; 69156952Sumeimport jdk.nashorn.internal.parser.TokenType; 70156952Sume 71156952Sume/** 72156952Sume * This class translates from nashorn IR Node objects 73156952Sume * to nashorn parser API Tree objects. 74156952Sume */ 75156952Sumefinal class IRTranslator extends NodeVisitor<LexicalContext> { 76156952Sume 77156952Sume public IRTranslator() { 78156952Sume super(new LexicalContext()); 79156952Sume } 80156952Sume 81156952Sume // currently translated Statement 82156952Sume private StatementTreeImpl curStat; 83156952Sume // currently translated Expression 84156952Sume private ExpressionTreeImpl curExpr; 85156952Sume 86156952Sume // entry point for translator 87156952Sume CompilationUnitTree translate(final FunctionNode node) { 88156952Sume if (node == null) { 89156952Sume return null; 90156952Sume } 91156952Sume 92156952Sume assert (node.getKind() == FunctionNode.Kind.SCRIPT) : "script function expected"; 93156952Sume 94156952Sume final Block body = node.getBody(); 95156952Sume return new CompilationUnitTreeImpl(node, 96156952Sume translateStats(body != null? getOrderedStatements(body.getStatements()) : null)); 97170242Sume } 98156952Sume 99156952Sume @Override 100156952Sume public boolean enterAccessNode(final AccessNode accessNode) { 101156952Sume curExpr = new MemberSelectTreeImpl(accessNode, translateExpr(accessNode.getBase())); 102156952Sume return false; 103156952Sume } 104156952Sume 105156952Sume @Override 106156952Sume public boolean enterBlock(final Block block) { 107156952Sume return handleBlock(block, false); 108156952Sume } 109156952Sume 110156952Sume @Override 111156952Sume public boolean enterBinaryNode(final BinaryNode binaryNode) { 112156952Sume if (binaryNode.isAssignment()) { 113156952Sume final ExpressionTree srcTree = translateExpr(binaryNode.getAssignmentSource()); 114156952Sume final ExpressionTree destTree = translateExpr(binaryNode.getAssignmentDest()); 115156952Sume 116156952Sume if (binaryNode.tokenType() == TokenType.ASSIGN) { 117156952Sume curExpr = new AssignmentTreeImpl(binaryNode, destTree, srcTree); 118156952Sume } else { 119156952Sume curExpr = new CompoundAssignmentTreeImpl(binaryNode, destTree, srcTree); 120156952Sume } 121156952Sume } else { 122156952Sume final ExpressionTree leftTree = translateExpr(binaryNode.lhs()); 123156952Sume final ExpressionTree rightTree = translateExpr(binaryNode.rhs()); 124156952Sume 125156952Sume if (binaryNode.tokenType() == TokenType.INSTANCEOF) { 126156952Sume curExpr = new InstanceOfTreeImpl(binaryNode, leftTree, rightTree); 127156952Sume } else { 128156952Sume curExpr = new BinaryTreeImpl(binaryNode, leftTree, rightTree); 129156952Sume } 130156952Sume } 131156952Sume 132156952Sume return false; 133156952Sume } 134156952Sume 135156952Sume @Override 136156952Sume public boolean enterBreakNode(final BreakNode breakNode) { 137156952Sume curStat = new BreakTreeImpl(breakNode); 138156952Sume return false; 139156952Sume } 140156952Sume 141156952Sume @Override 142156952Sume public boolean enterCallNode(final CallNode callNode) { 143156952Sume curExpr = null; 144156952Sume callNode.getFunction().accept(this); 145156952Sume final ExpressionTree funcTree = curExpr; 146156952Sume final List<? extends ExpressionTree> argTrees = translateExprs(callNode.getArgs()); 147156952Sume curExpr = new FunctionCallTreeImpl(callNode, funcTree, argTrees); 148156952Sume return false; 149156952Sume } 150156952Sume 151156952Sume @Override 152156952Sume public boolean enterCaseNode(final CaseNode caseNode) { 153156952Sume assert false : "should not reach here!"; 154156952Sume return false; 155156952Sume } 156156952Sume 157156952Sume @Override 158156952Sume public boolean enterCatchNode(final CatchNode catchNode) { 159156952Sume assert false : "should not reach here"; 160156952Sume return false; 161156952Sume } 162156952Sume 163156952Sume @Override 164156952Sume public boolean enterContinueNode(final ContinueNode continueNode) { 165156952Sume curStat = new ContinueTreeImpl(continueNode); 166156952Sume return false; 167156952Sume } 168156952Sume 169156952Sume @Override 170156952Sume public boolean enterDebuggerNode(final DebuggerNode debuggerNode) { 171156952Sume curStat = new DebuggerTreeImpl(debuggerNode); 172156952Sume return false; 173156952Sume } 174156952Sume 175156952Sume @Override 176156952Sume public boolean enterEmptyNode(final EmptyNode emptyNode) { 177156952Sume curStat = new EmptyStatementTreeImpl(emptyNode); 178156952Sume return false; 179156952Sume } 180156952Sume 181156952Sume @Override 182156952Sume public boolean enterErrorNode(final ErrorNode errorNode) { 183156952Sume curExpr = new ErroneousTreeImpl(errorNode); 184156952Sume return false; 185156952Sume } 186156952Sume 187156952Sume @Override 188156952Sume public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { 189156952Sume curStat = new ExpressionStatementTreeImpl(expressionStatement, 190156952Sume translateExpr(expressionStatement.getExpression())); 191156952Sume return false; 192156952Sume } 193156952Sume 194156952Sume @Override 195156952Sume public boolean enterBlockStatement(final BlockStatement blockStatement) { 196156952Sume final Block block = blockStatement.getBlock(); 197156952Sume if (blockStatement.isSynthetic()) { 198156952Sume assert block != null && block.getStatements() != null && block.getStatements().size() == 1; 199156952Sume curStat = translateStat(block.getStatements().get(0)); 200156952Sume } else { 201156952Sume curStat = new BlockTreeImpl(blockStatement, 202156952Sume translateStats(block != null? block.getStatements() : null)); 203156952Sume } 204156952Sume return false; 205156952Sume } 206156952Sume 207156952Sume @Override 208156952Sume public boolean enterForNode(final ForNode forNode) { 209156952Sume if (forNode.isForIn()) { 210156952Sume curStat = new ForInLoopTreeImpl(forNode, 211156952Sume translateExpr(forNode.getInit()), 212156952Sume translateExpr(forNode.getModify()), 213156952Sume translateBlock(forNode.getBody())); 214156952Sume } else { 215156952Sume curStat = new ForLoopTreeImpl(forNode, 216156952Sume translateExpr(forNode.getInit()), 217156952Sume translateExpr(forNode.getTest()), 218156952Sume translateExpr(forNode.getModify()), 219156952Sume translateBlock(forNode.getBody())); 220156952Sume } 221156952Sume 222156952Sume return false; 223156952Sume } 224156952Sume 225156952Sume @Override 226156952Sume public boolean enterFunctionNode(final FunctionNode functionNode) { 227156952Sume assert !functionNode.isDeclared() : "should not reach here for function declaration"; 228156952Sume 229156952Sume final List<? extends ExpressionTree> paramTrees 230156952Sume = translateExprs(functionNode.getParameters()); 231156952Sume final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody(), true); 232156952Sume curExpr = new FunctionExpressionTreeImpl(functionNode, paramTrees, blockTree); 233156952Sume 234156952Sume return false; 235156952Sume } 236156952Sume 237156952Sume @Override 238156952Sume public boolean enterIdentNode(final IdentNode identNode) { 239156952Sume curExpr = new IdentifierTreeImpl(identNode); 240156952Sume return false; 241156952Sume } 242156952Sume 243156952Sume @Override 244156952Sume public boolean enterIfNode(final IfNode ifNode) { 245156952Sume curStat = new IfTreeImpl(ifNode, 246156952Sume translateExpr(ifNode.getTest()), 247156952Sume translateBlock(ifNode.getPass()), 248156952Sume translateBlock(ifNode.getFail())); 249156952Sume return false; 250156952Sume } 251156952Sume 252156952Sume @Override 253156952Sume public boolean enterIndexNode(final IndexNode indexNode) { 254156952Sume curExpr = new ArrayAccessTreeImpl(indexNode, 255156952Sume translateExpr(indexNode.getBase()), 256156952Sume translateExpr(indexNode.getIndex())); 257156952Sume return false; 258156952Sume } 259156952Sume 260156952Sume @Override 261156952Sume public boolean enterLabelNode(final LabelNode labelNode) { 262156952Sume curStat = new LabeledStatementTreeImpl(labelNode, 263156952Sume translateBlock(labelNode.getBody())); 264170242Sume return false; 265170242Sume } 266 267 @Override 268 public boolean enterLiteralNode(final LiteralNode<?> literalNode) { 269 final Object value = literalNode.getValue(); 270 if (value instanceof Lexer.RegexToken) { 271 curExpr = new RegExpLiteralTreeImpl(literalNode); 272 } else if (literalNode.isArray()) { 273 final List<Expression> exprNodes = literalNode.getElementExpressions(); 274 final List<ExpressionTreeImpl> exprTrees = new ArrayList<>(exprNodes.size()); 275 for (final Node node : exprNodes) { 276 if (node == null) { 277 exprTrees.add(null); 278 } else { 279 curExpr = null; 280 node.accept(this); 281 assert curExpr != null : "null for " + node; 282 exprTrees.add(curExpr); 283 } 284 } 285 curExpr = new ArrayLiteralTreeImpl(literalNode, exprTrees); 286 } else { 287 curExpr = new LiteralTreeImpl(literalNode); 288 } 289 290 return false; 291 } 292 293 @Override 294 public boolean enterObjectNode(final ObjectNode objectNode) { 295 final List<PropertyNode> propNodes = objectNode.getElements(); 296 final List<PropertyTreeImpl> propTrees = new ArrayList<>(propNodes.size()); 297 for (final PropertyNode propNode : propNodes) { 298 propTrees.add(new PropertyTreeImpl(propNode, 299 translateExpr(propNode.getKey()), 300 translateExpr(propNode.getValue()), 301 (FunctionExpressionTree) translateExpr(propNode.getGetter()), 302 (FunctionExpressionTree) translateExpr(propNode.getSetter()))); 303 } 304 curExpr = new ObjectLiteralTreeImpl(objectNode, propTrees); 305 return false; 306 } 307 308 @Override 309 public boolean enterPropertyNode(final PropertyNode propertyNode) { 310 assert false : "should not reach here!"; 311 return false; 312 } 313 314 @Override 315 public boolean enterReturnNode(final ReturnNode returnNode) { 316 curStat = new ReturnTreeImpl(returnNode, 317 translateExpr(returnNode.getExpression())); 318 return false; 319 } 320 321 @Override 322 public boolean enterRuntimeNode(final RuntimeNode runtimeNode) { 323 assert false : "should not reach here: RuntimeNode"; 324 return false; 325 } 326 327 @Override 328 public boolean enterSplitNode(final SplitNode splitNode) { 329 assert false : "should not reach here!"; 330 return false; 331 } 332 333 @Override 334 public boolean enterSwitchNode(final SwitchNode switchNode) { 335 final List<CaseNode> caseNodes = switchNode.getCases(); 336 final List<CaseTreeImpl> caseTrees = new ArrayList<>(caseNodes.size()); 337 for (final CaseNode caseNode : caseNodes) { 338 final Block body = caseNode.getBody(); 339 caseTrees.add( 340 new CaseTreeImpl(caseNode, 341 translateExpr(caseNode.getTest()), 342 translateStats(body != null? body.getStatements() : null))); 343 } 344 345 curStat = new SwitchTreeImpl(switchNode, 346 translateExpr(switchNode.getExpression()), 347 caseTrees); 348 return false; 349 } 350 351 @Override 352 public boolean enterTernaryNode(final TernaryNode ternaryNode) { 353 curExpr = new ConditionalExpressionTreeImpl(ternaryNode, 354 translateExpr(ternaryNode.getTest()), 355 translateExpr(ternaryNode.getTrueExpression()), 356 translateExpr(ternaryNode.getFalseExpression())); 357 return false; 358 } 359 360 @Override 361 public boolean enterThrowNode(final ThrowNode throwNode) { 362 curStat = new ThrowTreeImpl(throwNode, 363 translateExpr(throwNode.getExpression())); 364 return false; 365 } 366 367 @Override 368 public boolean enterTryNode(final TryNode tryNode) { 369 final List<? extends CatchNode> catchNodes = tryNode.getCatches(); 370 final List<CatchTreeImpl> catchTrees = new ArrayList<>(catchNodes.size()); 371 for (final CatchNode catchNode : catchNodes) { 372 catchTrees.add(new CatchTreeImpl(catchNode, 373 translateIdent(catchNode.getException()), 374 (BlockTree) translateBlock(catchNode.getBody()), 375 translateExpr(catchNode.getExceptionCondition()))); 376 } 377 378 curStat = new TryTreeImpl(tryNode, 379 (BlockTree) translateBlock(tryNode.getBody()), 380 catchTrees, 381 (BlockTree) translateBlock(tryNode.getFinallyBody())); 382 383 return false; 384 } 385 386 @Override 387 public boolean enterUnaryNode(final UnaryNode unaryNode) { 388 if (unaryNode.tokenType() == TokenType.NEW) { 389 curExpr = new NewTreeImpl(unaryNode, 390 translateExpr(unaryNode.getExpression())); 391 } else { 392 curExpr = new UnaryTreeImpl(unaryNode, 393 translateExpr(unaryNode.getExpression())); 394 } 395 return false; 396 } 397 398 @Override 399 public boolean enterVarNode(final VarNode varNode) { 400 final Expression initNode = varNode.getInit(); 401 if (initNode instanceof FunctionNode && ((FunctionNode)initNode).isDeclared()) { 402 final FunctionNode funcNode = (FunctionNode) initNode; 403 404 final List<? extends ExpressionTree> paramTrees 405 = translateExprs(funcNode.getParameters()); 406 final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody(), true); 407 curStat = new FunctionDeclarationTreeImpl(varNode, paramTrees, blockTree); 408 } else { 409 curStat = new VariableTreeImpl(varNode, translateExpr(initNode)); 410 } 411 412 return false; 413 } 414 415 @Override 416 public boolean enterWhileNode(final WhileNode whileNode) { 417 final ExpressionTree condTree = translateExpr(whileNode.getTest()); 418 final StatementTree statTree = translateBlock(whileNode.getBody()); 419 420 if (whileNode.isDoWhile()) { 421 curStat = new DoWhileLoopTreeImpl(whileNode, condTree, statTree); 422 } else { 423 curStat = new WhileLoopTreeImpl(whileNode, condTree, statTree); 424 } 425 426 return false; 427 } 428 429 @Override 430 public boolean enterWithNode(final WithNode withNode) { 431 curStat = new WithTreeImpl(withNode, 432 translateExpr(withNode.getExpression()), 433 translateBlock(withNode.getBody())); 434 435 return false; 436 } 437 438 private StatementTree translateBlock(final Block blockNode) { 439 return translateBlock(blockNode, false); 440 } 441 442 private StatementTree translateBlock(final Block blockNode, final boolean sortStats) { 443 if (blockNode == null) { 444 return null; 445 } 446 curStat = null; 447 handleBlock(blockNode, sortStats); 448 return curStat; 449 } 450 451 private boolean handleBlock(final Block block, final boolean sortStats) { 452 // FIXME: revisit this! 453 if (block.isSynthetic()) { 454 final int statCount = block.getStatementCount(); 455 switch (statCount) { 456 case 0: { 457 final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish()); 458 curStat = new EmptyStatementTreeImpl(emptyNode); 459 return false; 460 } 461 case 1: { 462 curStat = translateStat(block.getStatements().get(0)); 463 return false; 464 } 465 default: { 466 // fall through 467 break; 468 } 469 } 470 } 471 472 final List<? extends Statement> stats = block.getStatements(); 473 curStat = new BlockTreeImpl(block, 474 translateStats(sortStats? getOrderedStatements(stats) : stats)); 475 return false; 476 } 477 478 private List<? extends Statement> getOrderedStatements(final List<? extends Statement> stats) { 479 final List<? extends Statement> statList = new ArrayList<>(stats); 480 statList.sort(Comparator.comparingInt(Node::getSourceOrder)); 481 return statList; 482 } 483 484 private List<? extends StatementTree> translateStats(final List<? extends Statement> stats) { 485 if (stats == null) { 486 return null; 487 } 488 final List<StatementTreeImpl> statTrees = new ArrayList<>(stats.size()); 489 for (final Statement stat : stats) { 490 curStat = null; 491 stat.accept(this); 492 assert curStat != null; 493 statTrees.add(curStat); 494 } 495 return statTrees; 496 } 497 498 private List<? extends ExpressionTree> translateExprs(final List<? extends Expression> exprs) { 499 if (exprs == null) { 500 return null; 501 } 502 final List<ExpressionTreeImpl> exprTrees = new ArrayList<>(exprs.size()); 503 for (final Expression expr : exprs) { 504 curExpr = null; 505 expr.accept(this); 506 assert curExpr != null; 507 exprTrees.add(curExpr); 508 } 509 return exprTrees; 510 } 511 512 private ExpressionTreeImpl translateExpr(final Expression expr) { 513 if (expr == null) { 514 return null; 515 } 516 517 curExpr = null; 518 expr.accept(this); 519 assert curExpr != null : "null for " + expr; 520 return curExpr; 521 } 522 523 private StatementTreeImpl translateStat(final Statement stat) { 524 if (stat == null) { 525 return null; 526 } 527 528 curStat = null; 529 stat.accept(this); 530 assert curStat != null : "null for " + stat; 531 return curStat; 532 } 533 534 private static IdentifierTree translateIdent(final IdentNode ident) { 535 return new IdentifierTreeImpl(ident); 536 } 537} 538