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