1 /*
2  * Copyright (c) 2010, 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 
26 package jdk.nashorn.internal.ir;
27 
28 import jdk.nashorn.internal.codegen.types.Type;
29 import jdk.nashorn.internal.ir.annotations.Immutable;
30 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
31 
32 /**
33  * IR representation of a property access (period operator.)
34  */
35 @Immutable
36 public final class AccessNode extends BaseNode {
37     private static final long serialVersionUID = 1L;
38 
39     /** Property name. */
40     private final String property;
41 
42     /**
43      * Constructor
44      *
45      * @param token     token
46      * @param finish    finish
47      * @param base      base node
48      * @param property  property
49      */
AccessNode(final long token, final int finish, final Expression base, final String property)50     public AccessNode(final long token, final int finish, final Expression base, final String property) {
51         super(token, finish, base, false, false);
52         this.property = property;
53     }
54 
AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id, final boolean isSuper)55     private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction,
56                        final Type type, final int id, final boolean isSuper) {
57         super(accessNode, base, isFunction, type, id, isSuper);
58         this.property = property;
59     }
60 
61     /**
62      * Assist in IR navigation.
63      * @param visitor IR navigating visitor.
64      */
65     @Override
accept(final NodeVisitor<? extends LexicalContext> visitor)66     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
67         if (visitor.enterAccessNode(this)) {
68             return visitor.leaveAccessNode(
69                 setBase((Expression)base.accept(visitor)));
70         }
71         return this;
72     }
73 
74     @Override
toString(final StringBuilder sb, final boolean printType)75     public void toString(final StringBuilder sb, final boolean printType) {
76         final boolean needsParen = tokenType().needsParens(getBase().tokenType(), true);
77 
78         if (printType) {
79             optimisticTypeToString(sb);
80         }
81 
82         if (needsParen) {
83             sb.append('(');
84         }
85 
86         base.toString(sb, printType);
87 
88         if (needsParen) {
89             sb.append(')');
90         }
91         sb.append('.');
92 
93         sb.append(property);
94     }
95 
96     /**
97      * Get the property name
98      *
99      * @return the property name
100      */
getProperty()101     public String getProperty() {
102         return property;
103     }
104 
setBase(final Expression base)105     private AccessNode setBase(final Expression base) {
106         if (this.base == base) {
107             return this;
108         }
109         return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
110     }
111 
112     @Override
setType(final Type type)113     public AccessNode setType(final Type type) {
114         if (this.type == type) {
115             return this;
116         }
117         return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
118     }
119 
120     @Override
setProgramPoint(final int programPoint)121     public AccessNode setProgramPoint(final int programPoint) {
122         if (this.programPoint == programPoint) {
123             return this;
124         }
125         return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
126     }
127 
128     @Override
setIsFunction()129     public AccessNode setIsFunction() {
130         if (isFunction()) {
131             return this;
132         }
133         return new AccessNode(this, base, property, true, type, programPoint, isSuper());
134     }
135 
136     @Override
setIsSuper()137     public AccessNode setIsSuper() {
138         if (isSuper()) {
139             return this;
140         }
141         return new AccessNode(this, base, property, isFunction(), type, programPoint, true);
142     }
143 }
144