695 assert symbol.hasSlot(); 696 if(isVarArg) { 697 symbol.setNeedsSlot(false); 698 } 699 } 700 } 701 } 702 703 /** 704 * Is the symbol local to (that is, defined in) the specified function? 705 * @param function the function 706 * @param symbol the symbol 707 * @return true if the symbol is defined in the specified function 708 */ 709 private boolean isLocal(final FunctionNode function, final Symbol symbol) { 710 final FunctionNode definingFn = lc.getDefiningFunction(symbol); 711 assert definingFn != null; 712 return definingFn == function; 713 } 714 715 private void checkConstAssignment(final IdentNode ident) { 716 // Check for reassignment of constant 717 final Symbol symbol = ident.getSymbol(); 718 if (symbol.isConst()) { 719 throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident); 720 } 721 } 722 723 @Override 724 public Node leaveBinaryNode(final BinaryNode binaryNode) { 725 if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) { 726 checkConstAssignment((IdentNode) binaryNode.lhs()); 727 } 728 switch (binaryNode.tokenType()) { 729 case ASSIGN: 730 return leaveASSIGN(binaryNode); 731 default: 732 return super.leaveBinaryNode(binaryNode); 733 } 734 } 735 736 private Node leaveASSIGN(final BinaryNode binaryNode) { 737 // If we're assigning a property of the this object ("this.foo = ..."), record it. 738 final Expression lhs = binaryNode.lhs(); 739 if (lhs instanceof AccessNode) { 740 final AccessNode accessNode = (AccessNode) lhs; 741 final Expression base = accessNode.getBase(); 742 if (base instanceof IdentNode) { 743 final Symbol symbol = ((IdentNode)base).getSymbol(); 744 if(symbol.isThis()) { 745 thisProperties.peek().add(accessNode.getProperty()); 746 } 747 } 748 } 749 return binaryNode; 750 } 751 752 @Override 753 public Node leaveUnaryNode(final UnaryNode unaryNode) { 754 if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) { 755 checkConstAssignment((IdentNode) unaryNode.getExpression()); 756 } 757 switch (unaryNode.tokenType()) { 758 case DELETE: 759 return leaveDELETE(unaryNode); 760 case TYPEOF: 761 return leaveTYPEOF(unaryNode); 762 default: 763 return super.leaveUnaryNode(unaryNode); 764 } 765 } 766 767 @Override 768 public Node leaveBlock(final Block block) { 769 // It's not necessary to guard the marking of symbols as locals with this "if" condition for 770 // correctness, it's just an optimization -- runtime type calculation is not used when the compilation 771 // is not an on-demand optimistic compilation, so we can skip locals marking then. 772 if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { 773 // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand 774 // compilation, and we're skipping parsing the function bodies for nested functions, this 775 // basically only means their parameters. It'd be enough to mistakenly declare to be a local a 776 // symbol in the outer function named the same as one of the parameters, though. | 695 assert symbol.hasSlot(); 696 if(isVarArg) { 697 symbol.setNeedsSlot(false); 698 } 699 } 700 } 701 } 702 703 /** 704 * Is the symbol local to (that is, defined in) the specified function? 705 * @param function the function 706 * @param symbol the symbol 707 * @return true if the symbol is defined in the specified function 708 */ 709 private boolean isLocal(final FunctionNode function, final Symbol symbol) { 710 final FunctionNode definingFn = lc.getDefiningFunction(symbol); 711 assert definingFn != null; 712 return definingFn == function; 713 } 714 715 @Override 716 public Node leaveBinaryNode(final BinaryNode binaryNode) { 717 switch (binaryNode.tokenType()) { 718 case ASSIGN: 719 return leaveASSIGN(binaryNode); 720 default: 721 return super.leaveBinaryNode(binaryNode); 722 } 723 } 724 725 private Node leaveASSIGN(final BinaryNode binaryNode) { 726 // If we're assigning a property of the this object ("this.foo = ..."), record it. 727 final Expression lhs = binaryNode.lhs(); 728 if (lhs instanceof AccessNode) { 729 final AccessNode accessNode = (AccessNode) lhs; 730 final Expression base = accessNode.getBase(); 731 if (base instanceof IdentNode) { 732 final Symbol symbol = ((IdentNode)base).getSymbol(); 733 if(symbol.isThis()) { 734 thisProperties.peek().add(accessNode.getProperty()); 735 } 736 } 737 } 738 return binaryNode; 739 } 740 741 @Override 742 public Node leaveUnaryNode(final UnaryNode unaryNode) { 743 switch (unaryNode.tokenType()) { 744 case DELETE: 745 return leaveDELETE(unaryNode); 746 case TYPEOF: 747 return leaveTYPEOF(unaryNode); 748 default: 749 return super.leaveUnaryNode(unaryNode); 750 } 751 } 752 753 @Override 754 public Node leaveBlock(final Block block) { 755 // It's not necessary to guard the marking of symbols as locals with this "if" condition for 756 // correctness, it's just an optimization -- runtime type calculation is not used when the compilation 757 // is not an on-demand optimistic compilation, so we can skip locals marking then. 758 if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { 759 // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand 760 // compilation, and we're skipping parsing the function bodies for nested functions, this 761 // basically only means their parameters. It'd be enough to mistakenly declare to be a local a 762 // symbol in the outer function named the same as one of the parameters, though. |