aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/ir/Expression.java
blob: e62eb732d52e2fa8e0497ce391dd8a8691fc0d32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.ir;

import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;

/**
 * Common superclass for all expression nodes. Expression nodes can have
 * an associated symbol as well as a type.
 *
 */
public abstract class Expression extends Node {
    private static final long serialVersionUID = 1L;

    static final String OPT_IDENTIFIER = "%";

    protected Expression(final long token, final int start, final int finish) {
        super(token, start, finish);
    }

    Expression(final long token, final int finish) {
        super(token, finish);
    }

    Expression(final Expression expr) {
        super(expr);
    }

    /**
     * Returns the type of the expression.
     *
     * @return the type of the expression.
     */
    public abstract Type getType();

    /**
     * Returns {@code true} if this expression depends exclusively on state that is constant
     * or local to the currently running function and thus inaccessible to other functions.
     * This implies that a local expression must not call any other functions (neither directly
     * nor implicitly through a getter, setter, or object-to-primitive type conversion).
     *
     * @return true if this expression does not depend on state shared with other functions.
     */
    public boolean isLocal() {
        return false;
    }

    /**
     * Is this a self modifying assignment?
     * @return true if self modifying, e.g. a++, or a*= 17
     */
    public boolean isSelfModifying() {
        return false;
    }

    /**
     * Returns widest operation type of this operation.
     *
     * @return the widest type for this operation
     */
    public Type getWidestOperationType() {
        return Type.OBJECT;
    }

    /**
     * Returns true if the type of this expression is narrower than its widest operation type (thus, it is
     * optimistically typed).
     * @return true if this expression is optimistically typed.
     */
    public final boolean isOptimistic() {
        return getType().narrowerThan(getWidestOperationType());
    }

    void optimisticTypeToString(final StringBuilder sb) {
        optimisticTypeToString(sb, isOptimistic());
    }

    void optimisticTypeToString(final StringBuilder sb, final boolean optimistic) {
        sb.append('{');
        final Type type = getType();
        final String desc = type == Type.UNDEFINED ? "U" : type.getDescriptor();

        sb.append(desc.charAt(desc.length() - 1) == ';' ? "O" : desc);
        if (isOptimistic() && optimistic) {
            sb.append(OPT_IDENTIFIER);
            final int pp = ((Optimistic)this).getProgramPoint();
            if (UnwarrantedOptimismException.isValid(pp)) {
                sb.append('_').append(pp);
            }
        }
        sb.append('}');
    }

    /**
     * Returns true if the runtime value of this expression is always false when converted to boolean as per ECMAScript
     * ToBoolean conversion. Used in control flow calculations.
     * @return true if this expression's runtime value converted to boolean is always false.
     */
    public boolean isAlwaysFalse() {
        return false;
    }

    /**
     * Returns true if the runtime value of this expression is always true when converted to boolean as per ECMAScript
     * ToBoolean conversion. Used in control flow calculations.
     * @return true if this expression's runtime value converted to boolean is always true.
     */
    public boolean isAlwaysTrue() {
        return false;
    }

    /**
     * Returns true if the expression is not null and {@link #isAlwaysFalse()}.
     * @param test a test expression used as a predicate of a branch or a loop.
     * @return true if the expression is not null and {@link #isAlwaysFalse()}.
     */
    public static boolean isAlwaysFalse(final Expression test) {
        return test != null && test.isAlwaysFalse();
    }


    /**
     * Returns true if the expression is null or {@link #isAlwaysTrue()}. Null is considered to be always true as a
     * for loop with no test is equivalent to a for loop with always-true test.
     * @param test a test expression used as a predicate of a branch or a loop.
     * @return true if the expression is null or {@link #isAlwaysFalse()}.
     */
    public static boolean isAlwaysTrue(final Expression test) {
        return test == null || test.isAlwaysTrue();
    }
}