1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.nashorn.api.tree; 26 27 import java.util.ArrayList; 28 import java.util.Comparator; 29 import java.util.List; 30 import java.util.Map; 31 import jdk.nashorn.internal.ir.AccessNode; 32 import jdk.nashorn.internal.ir.BinaryNode; 33 import jdk.nashorn.internal.ir.Block; 34 import jdk.nashorn.internal.ir.BlockStatement; 35 import jdk.nashorn.internal.ir.BreakNode; 36 import jdk.nashorn.internal.ir.CallNode; 37 import jdk.nashorn.internal.ir.CaseNode; 38 import jdk.nashorn.internal.ir.CatchNode; 39 import jdk.nashorn.internal.ir.ClassNode; 40 import jdk.nashorn.internal.ir.ContinueNode; 41 import jdk.nashorn.internal.ir.DebuggerNode; 42 import jdk.nashorn.internal.ir.EmptyNode; 43 import jdk.nashorn.internal.ir.ErrorNode; 44 import jdk.nashorn.internal.ir.Expression; 45 import jdk.nashorn.internal.ir.ExpressionStatement; 46 import jdk.nashorn.internal.ir.ForNode; 47 import jdk.nashorn.internal.ir.FunctionNode; 48 import jdk.nashorn.internal.ir.IdentNode; 49 import jdk.nashorn.internal.ir.IfNode; 50 import jdk.nashorn.internal.ir.IndexNode; 51 import jdk.nashorn.internal.ir.LabelNode; 52 import jdk.nashorn.internal.ir.LiteralNode; 53 import jdk.nashorn.internal.ir.Node; 54 import jdk.nashorn.internal.ir.ObjectNode; 55 import jdk.nashorn.internal.ir.PropertyNode; 56 import jdk.nashorn.internal.ir.ReturnNode; 57 import jdk.nashorn.internal.ir.RuntimeNode; 58 import jdk.nashorn.internal.ir.SplitNode; 59 import jdk.nashorn.internal.ir.Statement; 60 import jdk.nashorn.internal.ir.SwitchNode; 61 import jdk.nashorn.internal.ir.TemplateLiteral; 62 import jdk.nashorn.internal.ir.TernaryNode; 63 import jdk.nashorn.internal.ir.ThrowNode; 64 import jdk.nashorn.internal.ir.TryNode; 65 import jdk.nashorn.internal.ir.UnaryNode; 66 import jdk.nashorn.internal.ir.VarNode; 67 import jdk.nashorn.internal.ir.WhileNode; 68 import jdk.nashorn.internal.ir.WithNode; 69 import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor; 70 import jdk.nashorn.internal.parser.Lexer; 71 import jdk.nashorn.internal.parser.TokenType; 72 73 /** 74 * This class translates from nashorn IR Node objects 75 * to nashorn parser API Tree objects. 76 */ 77 final class IRTranslator extends SimpleNodeVisitor { 78 IRTranslator()79 public IRTranslator() { 80 } 81 82 // currently translated Statement 83 private StatementTreeImpl curStat; 84 // currently translated Expression 85 private ExpressionTreeImpl curExpr; 86 87 // entry point for translator translate(final FunctionNode node)88 CompilationUnitTree translate(final FunctionNode node) { 89 if (node == null) { 90 return null; 91 } 92 93 assert node.getKind() == FunctionNode.Kind.SCRIPT || 94 node.getKind() == FunctionNode.Kind.MODULE : 95 "script or module function expected"; 96 97 final Block body = node.getBody(); 98 return new CompilationUnitTreeImpl(node, 99 translateStats(body != null? getOrderedStatements(body.getStatements()) : null), 100 translateModule(node)); 101 } 102 103 @Override enterAccessNode(final AccessNode accessNode)104 public boolean enterAccessNode(final AccessNode accessNode) { 105 curExpr = new MemberSelectTreeImpl(accessNode, translateExpr(accessNode.getBase())); 106 return false; 107 } 108 109 @Override enterBlock(final Block block)110 public boolean enterBlock(final Block block) { 111 return handleBlock(block, false); 112 } 113 114 @Override enterBinaryNode(final BinaryNode binaryNode)115 public boolean enterBinaryNode(final BinaryNode binaryNode) { 116 if (binaryNode.isAssignment()) { 117 final ExpressionTree srcTree = translateExpr(binaryNode.getAssignmentSource()); 118 final ExpressionTree destTree = translateExpr(binaryNode.getAssignmentDest()); 119 120 if (binaryNode.isTokenType(TokenType.ASSIGN)) { 121 curExpr = new AssignmentTreeImpl(binaryNode, destTree, srcTree); 122 } else { 123 curExpr = new CompoundAssignmentTreeImpl(binaryNode, destTree, srcTree); 124 } 125 } else { 126 final ExpressionTree leftTree = translateExpr(binaryNode.lhs()); 127 final ExpressionTree rightTree = translateExpr(binaryNode.rhs()); 128 129 if (binaryNode.isTokenType(TokenType.INSTANCEOF)) { 130 curExpr = new InstanceOfTreeImpl(binaryNode, leftTree, rightTree); 131 } else { 132 curExpr = new BinaryTreeImpl(binaryNode, leftTree, rightTree); 133 } 134 } 135 136 return false; 137 } 138 139 @Override enterBreakNode(final BreakNode breakNode)140 public boolean enterBreakNode(final BreakNode breakNode) { 141 curStat = new BreakTreeImpl(breakNode); 142 return false; 143 } 144 145 @Override enterCallNode(final CallNode callNode)146 public boolean enterCallNode(final CallNode callNode) { 147 curExpr = null; 148 callNode.getFunction().accept(this); 149 final ExpressionTree funcTree = curExpr; 150 final List<? extends ExpressionTree> argTrees = translateExprs(callNode.getArgs()); 151 curExpr = new FunctionCallTreeImpl(callNode, funcTree, argTrees); 152 return false; 153 } 154 155 @Override enterCaseNode(final CaseNode caseNode)156 public boolean enterCaseNode(final CaseNode caseNode) { 157 assert false : "should not reach here!"; 158 return false; 159 } 160 161 @Override enterCatchNode(final CatchNode catchNode)162 public boolean enterCatchNode(final CatchNode catchNode) { 163 assert false : "should not reach here"; 164 return false; 165 } 166 167 @Override enterContinueNode(final ContinueNode continueNode)168 public boolean enterContinueNode(final ContinueNode continueNode) { 169 curStat = new ContinueTreeImpl(continueNode); 170 return false; 171 } 172 173 @Override enterDebuggerNode(final DebuggerNode debuggerNode)174 public boolean enterDebuggerNode(final DebuggerNode debuggerNode) { 175 curStat = new DebuggerTreeImpl(debuggerNode); 176 return false; 177 } 178 179 @Override enterEmptyNode(final EmptyNode emptyNode)180 public boolean enterEmptyNode(final EmptyNode emptyNode) { 181 curStat = new EmptyStatementTreeImpl(emptyNode); 182 return false; 183 } 184 185 @Override enterErrorNode(final ErrorNode errorNode)186 public boolean enterErrorNode(final ErrorNode errorNode) { 187 curExpr = new ErroneousTreeImpl(errorNode); 188 return false; 189 } 190 191 @Override enterExpressionStatement(final ExpressionStatement expressionStatement)192 public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { 193 if (expressionStatement.destructuringDeclarationType() != null) { 194 final ExpressionTree expr = translateExpr(expressionStatement.getExpression()); 195 assert expr instanceof AssignmentTree : "destructuring decl. statement does not have assignment"; 196 final AssignmentTree assign = (AssignmentTree)expr; 197 curStat = new DestructuringDeclTreeImpl(expressionStatement, assign.getVariable(), assign.getExpression()); 198 } else { 199 curStat = new ExpressionStatementTreeImpl(expressionStatement, 200 translateExpr(expressionStatement.getExpression())); 201 } 202 return false; 203 } 204 205 @Override enterBlockStatement(final BlockStatement blockStatement)206 public boolean enterBlockStatement(final BlockStatement blockStatement) { 207 final Block block = blockStatement.getBlock(); 208 if (blockStatement.isSynthetic()) { 209 assert block != null && block.getStatements() != null && block.getStatements().size() == 1; 210 curStat = translateStat(block.getStatements().get(0)); 211 } else { 212 curStat = new BlockTreeImpl(blockStatement, 213 translateStats(block != null? block.getStatements() : null)); 214 } 215 return false; 216 } 217 218 @Override enterForNode(final ForNode forNode)219 public boolean enterForNode(final ForNode forNode) { 220 if (forNode.isForIn()) { 221 curStat = new ForInLoopTreeImpl(forNode, 222 translateExpr(forNode.getInit()), 223 translateExpr(forNode.getModify()), 224 translateBlock(forNode.getBody())); 225 } else if (forNode.isForOf()) { 226 curStat = new ForOfLoopTreeImpl(forNode, 227 translateExpr(forNode.getInit()), 228 translateExpr(forNode.getModify()), 229 translateBlock(forNode.getBody())); 230 } else { 231 curStat = new ForLoopTreeImpl(forNode, 232 translateExpr(forNode.getInit()), 233 translateExpr(forNode.getTest()), 234 translateExpr(forNode.getModify()), 235 translateBlock(forNode.getBody())); 236 } 237 238 return false; 239 } 240 241 @Override enterFunctionNode(final FunctionNode functionNode)242 public boolean enterFunctionNode(final FunctionNode functionNode) { 243 assert !functionNode.isDeclared() || functionNode.isAnonymous() : "should not reach here for function declaration"; 244 245 final List<? extends ExpressionTree> paramTrees = translateParameters(functionNode); 246 final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody(), true); 247 curExpr = new FunctionExpressionTreeImpl(functionNode, paramTrees, blockTree); 248 249 return false; 250 } 251 252 @Override enterIdentNode(final IdentNode identNode)253 public boolean enterIdentNode(final IdentNode identNode) { 254 curExpr = new IdentifierTreeImpl(identNode); 255 return false; 256 } 257 258 @Override enterIfNode(final IfNode ifNode)259 public boolean enterIfNode(final IfNode ifNode) { 260 curStat = new IfTreeImpl(ifNode, 261 translateExpr(ifNode.getTest()), 262 translateBlock(ifNode.getPass()), 263 translateBlock(ifNode.getFail())); 264 return false; 265 } 266 267 @Override enterIndexNode(final IndexNode indexNode)268 public boolean enterIndexNode(final IndexNode indexNode) { 269 curExpr = new ArrayAccessTreeImpl(indexNode, 270 translateExpr(indexNode.getBase()), 271 translateExpr(indexNode.getIndex())); 272 return false; 273 } 274 275 @Override enterLabelNode(final LabelNode labelNode)276 public boolean enterLabelNode(final LabelNode labelNode) { 277 curStat = new LabeledStatementTreeImpl(labelNode, 278 translateBlock(labelNode.getBody())); 279 return false; 280 } 281 282 @Override enterLiteralNode(final LiteralNode<?> literalNode)283 public boolean enterLiteralNode(final LiteralNode<?> literalNode) { 284 final Object value = literalNode.getValue(); 285 if (value instanceof Lexer.RegexToken) { 286 curExpr = new RegExpLiteralTreeImpl(literalNode); 287 } else if (literalNode.isArray()) { 288 final List<Expression> exprNodes = literalNode.getElementExpressions(); 289 final List<ExpressionTreeImpl> exprTrees = new ArrayList<>(exprNodes.size()); 290 for (final Node node : exprNodes) { 291 if (node == null) { 292 exprTrees.add(null); 293 } else { 294 curExpr = null; 295 node.accept(this); 296 assert curExpr != null : "null for " + node; 297 exprTrees.add(curExpr); 298 } 299 } 300 curExpr = new ArrayLiteralTreeImpl(literalNode, exprTrees); 301 } else { 302 curExpr = new LiteralTreeImpl(literalNode); 303 } 304 305 return false; 306 } 307 308 @Override enterObjectNode(final ObjectNode objectNode)309 public boolean enterObjectNode(final ObjectNode objectNode) { 310 final List<PropertyNode> propNodes = objectNode.getElements(); 311 final List<? extends PropertyTree> propTrees = translateProperties(propNodes); 312 curExpr = new ObjectLiteralTreeImpl(objectNode, propTrees); 313 return false; 314 } 315 316 @Override enterPropertyNode(final PropertyNode propertyNode)317 public boolean enterPropertyNode(final PropertyNode propertyNode) { 318 assert false : "should not reach here!"; 319 return false; 320 } 321 322 @Override enterReturnNode(final ReturnNode returnNode)323 public boolean enterReturnNode(final ReturnNode returnNode) { 324 curStat = new ReturnTreeImpl(returnNode, 325 translateExpr(returnNode.getExpression())); 326 return false; 327 } 328 329 @Override enterRuntimeNode(final RuntimeNode runtimeNode)330 public boolean enterRuntimeNode(final RuntimeNode runtimeNode) { 331 assert false : "should not reach here: RuntimeNode"; 332 return false; 333 } 334 335 @Override enterSplitNode(final SplitNode splitNode)336 public boolean enterSplitNode(final SplitNode splitNode) { 337 assert false : "should not reach here!"; 338 return false; 339 } 340 341 @Override enterSwitchNode(final SwitchNode switchNode)342 public boolean enterSwitchNode(final SwitchNode switchNode) { 343 final List<CaseNode> caseNodes = switchNode.getCases(); 344 final List<CaseTreeImpl> caseTrees = new ArrayList<>(caseNodes.size()); 345 for (final CaseNode caseNode : caseNodes) { 346 final Block body = caseNode.getBody(); 347 caseTrees.add( 348 new CaseTreeImpl(caseNode, 349 translateExpr(caseNode.getTest()), 350 translateStats(body != null? body.getStatements() : null))); 351 } 352 353 curStat = new SwitchTreeImpl(switchNode, 354 translateExpr(switchNode.getExpression()), 355 caseTrees); 356 return false; 357 } 358 359 @Override enterTemplateLiteral(final TemplateLiteral templateLiteral)360 public boolean enterTemplateLiteral(final TemplateLiteral templateLiteral) { 361 curExpr = new TemplateLiteralTreeImpl(templateLiteral, translateExprs(templateLiteral.getExpressions())); 362 return false; 363 } 364 365 @Override enterTernaryNode(final TernaryNode ternaryNode)366 public boolean enterTernaryNode(final TernaryNode ternaryNode) { 367 curExpr = new ConditionalExpressionTreeImpl(ternaryNode, 368 translateExpr(ternaryNode.getTest()), 369 translateExpr(ternaryNode.getTrueExpression()), 370 translateExpr(ternaryNode.getFalseExpression())); 371 return false; 372 } 373 374 @Override enterThrowNode(final ThrowNode throwNode)375 public boolean enterThrowNode(final ThrowNode throwNode) { 376 curStat = new ThrowTreeImpl(throwNode, 377 translateExpr(throwNode.getExpression())); 378 return false; 379 } 380 381 @Override enterTryNode(final TryNode tryNode)382 public boolean enterTryNode(final TryNode tryNode) { 383 final List<? extends CatchNode> catchNodes = tryNode.getCatches(); 384 final List<CatchTreeImpl> catchTrees = new ArrayList<>(catchNodes.size()); 385 for (final CatchNode catchNode : catchNodes) { 386 catchTrees.add(new CatchTreeImpl(catchNode, 387 translateExpr(catchNode.getException()), 388 (BlockTree) translateBlock(catchNode.getBody()), 389 translateExpr(catchNode.getExceptionCondition()))); 390 } 391 392 curStat = new TryTreeImpl(tryNode, 393 (BlockTree) translateBlock(tryNode.getBody()), 394 catchTrees, 395 (BlockTree) translateBlock(tryNode.getFinallyBody())); 396 397 return false; 398 } 399 400 @Override enterUnaryNode(final UnaryNode unaryNode)401 public boolean enterUnaryNode(final UnaryNode unaryNode) { 402 if (unaryNode.isTokenType(TokenType.NEW)) { 403 curExpr = new NewTreeImpl(unaryNode, 404 translateExpr(unaryNode.getExpression())); 405 } else if (unaryNode.isTokenType(TokenType.YIELD) || 406 unaryNode.isTokenType(TokenType.YIELD_STAR)) { 407 curExpr = new YieldTreeImpl(unaryNode, 408 translateExpr(unaryNode.getExpression())); 409 } else if (unaryNode.isTokenType(TokenType.SPREAD_ARGUMENT) || 410 unaryNode.isTokenType(TokenType.SPREAD_ARRAY)) { 411 curExpr = new SpreadTreeImpl(unaryNode, 412 translateExpr(unaryNode.getExpression())); 413 } else { 414 curExpr = new UnaryTreeImpl(unaryNode, 415 translateExpr(unaryNode.getExpression())); 416 } 417 return false; 418 } 419 420 @Override enterVarNode(final VarNode varNode)421 public boolean enterVarNode(final VarNode varNode) { 422 final Expression initNode = varNode.getInit(); 423 if (initNode instanceof FunctionNode && ((FunctionNode)initNode).isDeclared()) { 424 final FunctionNode funcNode = (FunctionNode) initNode; 425 426 final List<? extends ExpressionTree> paramTrees = translateParameters(funcNode); 427 final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody(), true); 428 curStat = new FunctionDeclarationTreeImpl(varNode, paramTrees, blockTree); 429 } else if (initNode instanceof ClassNode && ((ClassNode)initNode).isStatement()) { 430 final ClassNode classNode = (ClassNode) initNode; 431 432 curStat = new ClassDeclarationTreeImpl(varNode, 433 translateIdent(classNode.getIdent()), 434 translateExpr(classNode.getClassHeritage()), 435 translateProperty(classNode.getConstructor()), 436 translateProperties(classNode.getClassElements())); 437 } else { 438 curStat = new VariableTreeImpl(varNode, translateIdent(varNode.getName()), translateExpr(initNode)); 439 } 440 441 return false; 442 } 443 444 @Override enterWhileNode(final WhileNode whileNode)445 public boolean enterWhileNode(final WhileNode whileNode) { 446 final ExpressionTree condTree = translateExpr(whileNode.getTest()); 447 final StatementTree statTree = translateBlock(whileNode.getBody()); 448 449 if (whileNode.isDoWhile()) { 450 curStat = new DoWhileLoopTreeImpl(whileNode, condTree, statTree); 451 } else { 452 curStat = new WhileLoopTreeImpl(whileNode, condTree, statTree); 453 } 454 455 return false; 456 } 457 458 @Override enterWithNode(final WithNode withNode)459 public boolean enterWithNode(final WithNode withNode) { 460 curStat = new WithTreeImpl(withNode, 461 translateExpr(withNode.getExpression()), 462 translateBlock(withNode.getBody())); 463 464 return false; 465 } 466 467 /** 468 * Callback for entering a ClassNode 469 * 470 * @param classNode the node 471 * @return true if traversal should continue and node children be traversed, false otherwise 472 */ 473 @Override enterClassNode(final ClassNode classNode)474 public boolean enterClassNode(final ClassNode classNode) { 475 assert !classNode.isStatement(): "should not reach here for class declaration"; 476 final IdentNode className = classNode.getIdent(); 477 curExpr = new ClassExpressionTreeImpl(classNode, 478 className != null? translateIdent(className) : null, 479 translateExpr(classNode.getClassHeritage()), 480 translateProperty(classNode.getConstructor()), 481 translateProperties(classNode.getClassElements())); 482 483 return false; 484 } 485 translateBlock(final Block blockNode)486 private StatementTree translateBlock(final Block blockNode) { 487 return translateBlock(blockNode, false); 488 } 489 translateBlock(final Block blockNode, final boolean sortStats)490 private StatementTree translateBlock(final Block blockNode, final boolean sortStats) { 491 if (blockNode == null) { 492 return null; 493 } 494 curStat = null; 495 handleBlock(blockNode, sortStats); 496 return curStat; 497 } 498 handleBlock(final Block block, final boolean sortStats)499 private boolean handleBlock(final Block block, final boolean sortStats) { 500 // FIXME: revisit this! 501 if (block.isSynthetic()) { 502 final int statCount = block.getStatementCount(); 503 switch (statCount) { 504 case 0: { 505 final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish()); 506 curStat = new EmptyStatementTreeImpl(emptyNode); 507 return false; 508 } 509 case 1: { 510 curStat = translateStat(block.getStatements().get(0)); 511 return false; 512 } 513 default: { 514 // fall through 515 break; 516 } 517 } 518 } 519 520 final List<? extends Statement> stats = block.getStatements(); 521 curStat = new BlockTreeImpl(block, 522 translateStats(sortStats? getOrderedStatements(stats) : stats)); 523 return false; 524 } 525 getOrderedStatements(final List<? extends Statement> stats)526 private List<? extends Statement> getOrderedStatements(final List<? extends Statement> stats) { 527 final List<? extends Statement> statList = new ArrayList<>(stats); 528 statList.sort(Comparator.comparingInt(Node::getSourceOrder)); 529 return statList; 530 } 531 translateStats(final List<? extends Statement> stats)532 private List<? extends StatementTree> translateStats(final List<? extends Statement> stats) { 533 if (stats == null) { 534 return null; 535 } 536 final List<StatementTreeImpl> statTrees = new ArrayList<>(stats.size()); 537 for (final Statement stat : stats) { 538 curStat = null; 539 stat.accept(this); 540 assert curStat != null; 541 statTrees.add(curStat); 542 } 543 return statTrees; 544 } 545 translateParameters(final FunctionNode func)546 private List<? extends ExpressionTree> translateParameters(final FunctionNode func) { 547 final Map<IdentNode, Expression> paramExprs = func.getParameterExpressions(); 548 if (paramExprs != null) { 549 final List<IdentNode> params = func.getParameters(); 550 final List<ExpressionTreeImpl> exprTrees = new ArrayList<>(params.size()); 551 for (final IdentNode ident : params) { 552 final Expression expr = paramExprs.containsKey(ident)? paramExprs.get(ident) : ident; 553 curExpr = null; 554 expr.accept(this); 555 assert curExpr != null; 556 exprTrees.add(curExpr); 557 } 558 return exprTrees; 559 } else { 560 return translateExprs(func.getParameters()); 561 } 562 } 563 translateExprs(final List<? extends Expression> exprs)564 private List<? extends ExpressionTree> translateExprs(final List<? extends Expression> exprs) { 565 if (exprs == null) { 566 return null; 567 } 568 final List<ExpressionTreeImpl> exprTrees = new ArrayList<>(exprs.size()); 569 for (final Expression expr : exprs) { 570 curExpr = null; 571 expr.accept(this); 572 assert curExpr != null; 573 exprTrees.add(curExpr); 574 } 575 return exprTrees; 576 } 577 translateExpr(final Expression expr)578 private ExpressionTreeImpl translateExpr(final Expression expr) { 579 if (expr == null) { 580 return null; 581 } 582 583 curExpr = null; 584 expr.accept(this); 585 assert curExpr != null : "null for " + expr; 586 return curExpr; 587 } 588 translateStat(final Statement stat)589 private StatementTreeImpl translateStat(final Statement stat) { 590 if (stat == null) { 591 return null; 592 } 593 594 curStat = null; 595 stat.accept(this); 596 assert curStat != null : "null for " + stat; 597 return curStat; 598 } 599 translateIdent(final IdentNode ident)600 private static IdentifierTree translateIdent(final IdentNode ident) { 601 return new IdentifierTreeImpl(ident); 602 } 603 translateProperties(final List<PropertyNode> propNodes)604 private List<? extends PropertyTree> translateProperties(final List<PropertyNode> propNodes) { 605 final List<PropertyTree> propTrees = new ArrayList<>(propNodes.size()); 606 for (final PropertyNode propNode : propNodes) { 607 propTrees.add(translateProperty(propNode)); 608 } 609 return propTrees; 610 } 611 translateProperty(final PropertyNode propNode)612 private PropertyTree translateProperty(final PropertyNode propNode) { 613 return new PropertyTreeImpl(propNode, 614 translateExpr(propNode.getKey()), 615 translateExpr(propNode.getValue()), 616 (FunctionExpressionTree) translateExpr(propNode.getGetter()), 617 (FunctionExpressionTree) translateExpr(propNode.getSetter())); 618 } 619 translateModule(final FunctionNode func)620 private ModuleTree translateModule(final FunctionNode func) { 621 return func.getKind() == FunctionNode.Kind.MODULE? 622 ModuleTreeImpl.create(func) : null; 623 } 624 } 625