jdk/src/share/classes/sun/tools/tree/MethodExpression.java
author prr
Tue, 15 Jul 2014 11:22:14 -0700
changeset 25522 10d789df41bb
parent 5506 202f599c92aa
child 25799 1afc4675dc75
permissions -rw-r--r--
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes Reviewed-by: psandoz, prr Contributed-by: otaviopolianasantana@gmail.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     2
 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.tools.tree;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import sun.tools.java.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import sun.tools.asm.Assembler;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.PrintStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.Hashtable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 * WARNING: The contents of this source file are not part of any
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * supported API.  Code that depends on them does so at its own risk:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * they are subject to change or removal without notice.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
public
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
class MethodExpression extends NaryExpression {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
    Identifier id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
    ClassDefinition clazz;   // The class in which the called method is defined
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    MemberDefinition field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    Expression implementation;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    private boolean isSuper;  // Set if qualified by 'super' or '<class>.super'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
     * constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
    public MethodExpression(long where, Expression right, Identifier id, Expression args[]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
        super(METHOD, where, Type.tError, right, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
        this.id = id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    public MethodExpression(long where, Expression right, MemberDefinition field, Expression args[]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
        super(METHOD, where, field.getType().getReturnType(), right, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
        this.id = field.getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
        this.field = field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
        this.clazz = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    // This is a hack used only within certain access methods generated by
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    // 'SourceClass.getAccessMember'.  It allows an 'invokespecial' instruction
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    // to be forced even though 'super' does not appear within the call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    // Such access methods are needed for access to protected methods when using
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    // the qualified '<class>.super.<method>(...)' notation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    public MethodExpression(long where, Expression right,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
                            MemberDefinition field, Expression args[], boolean forceSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
        this(where, right, field, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
        this.isSuper = forceSuper;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    public Expression getImplementation() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
            return implementation;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
        return this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     * Check expression type
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
        ClassDeclaration c = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
        boolean isArray = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        boolean staticRef = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        // Access method to use if required.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        MemberDefinition implMethod = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        // When calling a constructor, we may need to add an
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        // additional argument to transmit the outer instance link.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        Expression args[] = this.args;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        if (id.equals(idInit)){
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
            ClassDefinition conCls = ctxClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
                Expression conOuter = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
                if (right instanceof SuperExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
                    // outer.super(...)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
                    conCls = conCls.getSuperClass().getClassDefinition(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
                    conOuter = ((SuperExpression)right).outerArg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
                } else if (right instanceof ThisExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
                    // outer.this(...)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
                    conOuter = ((ThisExpression)right).outerArg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
                args = NewInstanceExpression.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
                    insertOuterLink(env, ctx, where, conCls, conOuter, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
            } catch (ClassNotFound ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
                // the same error is handled elsewhere
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
        Type argTypes[] = new Type[args.length];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        // The effective accessing class, for access checking.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
        // This is normally the immediately enclosing class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        ClassDefinition sourceClass = ctxClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
            if (right == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
                staticRef = ctx.field.isStatic();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
                // Find the first outer scope that mentions the method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
                ClassDefinition cdef = ctxClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
                MemberDefinition m = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                for (; cdef != null; cdef = cdef.getOuterClass()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                    m = cdef.findAnyMethod(env, id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
                    if (m != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
                if (m == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                    // this is the scope for error diagnosis
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                    c = ctx.field.getClassDeclaration();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
                    // found the innermost scope in which m occurs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                    c = cdef.getClassDeclaration();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                    // Maybe an inherited method hides an apparent method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                    // Keep looking at enclosing scopes to find out.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                    if (m.getClassDefinition() != cdef) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                        ClassDefinition cdef2 = cdef;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
                        while ((cdef2 = cdef2.getOuterClass()) != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
                            MemberDefinition m2 = cdef2.findAnyMethod(env, id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
                            if (m2 != null && m2.getClassDefinition() == cdef2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                                env.error(where, "inherited.hides.method",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                                          id, cdef.getClassDeclaration(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                                          cdef2.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                if (id.equals(idInit)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                    int thisN = ctx.getThisNumber();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                    if (!ctx.field.isConstructor()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                        env.error(where, "invalid.constr.invoke");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                        return vset.addVar(thisN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                    // As a consequence of the DA/DU rules in the JLS (draft of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
                    // forthcoming 2e), all variables are both definitely assigned
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                    // and definitely unassigned in unreachable code.  Normally, this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                    // correctly suppresses DA/DU-related errors in such code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                    // The use of the DA status of the 'this' variable for the extra
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                    // check below on correct constructor usage, however, does not quite
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                    // fit into this DA/DU scheme.  The current representation of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                    // Vsets for unreachable dead-ends, does not allow 'clearVar'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                    // to work, as the DA/DU bits (all on) are implicitly represented
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                    // by the fact that the Vset is a dead-end.  The DA/DU status
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
                    // of the 'this' variable is supposed to be temporarily
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                    // cleared at the beginning of a constructor and during the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
                    // checking of constructor arguments (see below in this method).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
                    // Since 'clearVar' has no effect on dead-ends, we may
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
                    // find the 'this' variable in an erroneously definitely-assigned state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                    // As a workaround, we suppress the following error message when
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                    // the Vset is a dead-end, i.e., when we are in unreachable code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                    // Unfortunately, the special-case treatment of reachability for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                    // if-then and if-then-else allows unreachable code in some circumstances,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                    // thus it is possible that no error message will be emitted at all.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                    // While this behavior is strictly incorrect (thus we call this a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                    // workaround), the problematic code is indeed unreachable and will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                    // not be executed.  In fact, it will be entirely omitted from the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                    // translated program, and can cause no harm at runtime.  A correct
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                    // solution would require modifying the representation of the DA/DU
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                    // analysis to use finite Vsets only, restricting the universe
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                    // of variables about which assertions are made (even in unreachable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                    // code) to variables that are actually in scope. Alternatively, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                    // Vset extension and the dead-end marker (currently a reserved value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                    // of the extension) could be represented orthogonally.  In either case,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                    // 'clearVar' could then be made to work on (non-canonical) dead ends.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                    // See file 'Vset.java'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                    if (!vset.isReallyDeadEnd() && vset.testVar(thisN)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                        env.error(where, "constr.invoke.not.first");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                    vset = vset.addVar(thisN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                    if (right instanceof SuperExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                        // supers require this specific kind of checking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                        vset = right.checkAmbigName(env, ctx, vset, exp, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
                        vset = right.checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                    vset = right.checkAmbigName(env, ctx, vset, exp, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                    if (right.type == Type.tPackage) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                        FieldExpression.reportFailedPackagePrefix(env, right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                    if (right instanceof TypeExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                        staticRef = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                if (right.type.isType(TC_CLASS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                    c = env.getClassDeclaration(right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
                } else if (right.type.isType(TC_ARRAY)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                    isArray = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                    c = env.getClassDeclaration(Type.tObject);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                    if (!right.type.isType(TC_ERROR)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                        env.error(where, "invalid.method.invoke", right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                    return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                // Normally, the effective accessing class is the innermost
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                // class surrounding the current method call, but, for calls
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                // of the form '<class>.super.<method>(...)', it is <class>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                // This allows access to protected members of a superclass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                // from within a class nested within one of its subclasses.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                // Otherwise, for example, the call below to 'matchMethod'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                // may fail due to the rules for visibility of inaccessible
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                // members.  For consistency, we treat qualified 'this' in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                // the same manner, as error diagnostics will be affected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                // QUERY: Are there subtle unexplored language issues here?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                if (right instanceof FieldExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                    Identifier id = ((FieldExpression)right).id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                    if (id == idThis) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                        sourceClass = ((FieldExpression)right).clazz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                    } else if (id == idSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                        isSuper = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                        sourceClass = ((FieldExpression)right).clazz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                } else if (right instanceof SuperExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                    isSuper = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                // Fix for 4158650.  When we extend a protected inner
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                // class in a different package, we may not have access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                // to the type of our superclass.  Allow the call to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                // the superclass constructor from within our constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                // Note that this check does not apply to constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                // calls in new instance expressions -- those are part
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                // of NewInstanceExpression#check().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                if (id != idInit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                    // Required by JLS 6.6.1.  Fixes 4143715.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                    // (See also 4094658.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                    if (!FieldExpression.isTypeAccessible(where, env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
                                                          right.type,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
                                                          sourceClass)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                        ClassDeclaration cdecl =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
                            sourceClass.getClassDeclaration();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                        if (staticRef) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                            env.error(where, "no.type.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                                      id, right.type.toString(), cdecl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                            env.error(where, "cant.access.member.type",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                                      id, right.type.toString(), cdecl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
            // Compose a list of argument types
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            boolean hasErrors = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
            // "this" is not defined during argument checking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            if (id.equals(idInit)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                vset = vset.clearVar(ctx.getThisNumber());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            for (int i = 0 ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
                vset = args[i].checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
                argTypes[i] = args[i].type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
                hasErrors = hasErrors || argTypes[i].isType(TC_ERROR);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            // "this" is defined after the constructor invocation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
            if (id.equals(idInit)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                vset = vset.addVar(ctx.getThisNumber());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
            // Check if there are any type errors in the arguments
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
            if (hasErrors) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            // Get the method field, given the argument types
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            clazz = c.getClassDefinition(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                field = clazz.matchMethod(env, sourceClass, id, argTypes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                    if (id.equals(idInit)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                        if (diagnoseMismatch(env, args, argTypes))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                            return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                        String sig = clazz.getName().getName().toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                        sig = Type.tMethod(Type.tError, argTypes).typeString(sig, false, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                        env.error(where, "unmatched.constr", sig, c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                    String sig = id.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
                    sig = Type.tMethod(Type.tError, argTypes).typeString(sig, false, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                    if (clazz.findAnyMethod(env, id) == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                        if (ctx.getField(env, id) != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                            env.error(where, "invalid.method", id, c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                            env.error(where, "undef.meth", sig, c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                    } else if (diagnoseMismatch(env, args, argTypes)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                        env.error(where, "unmatched.meth", sig, c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                    return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            type = field.getType().getReturnType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            // Make sure that static references are allowed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            if (staticRef && !field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                env.error(where, "no.static.meth.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                          field, field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            if (field.isProtected()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                && !(right == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                && !(right instanceof SuperExpression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                     // Extension of JLS 6.6.2 for qualified 'super'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                     || (right instanceof FieldExpression &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                         ((FieldExpression)right).id == idSuper))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                && !sourceClass.protectedAccess(env, field, right.type)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                env.error(where, "invalid.protected.method.use",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                          field.getName(), field.getClassDeclaration(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                          right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            // In <class>.super.<method>(), we cannot simply evaluate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            // <class>.super to an object reference (as we would for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            // <class>.super.<field>) and then perform an 'invokespecial'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
            // An 'invokespecial' must be performed from within (a subclass of)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
            // the class in which the target method is located.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
            if (right instanceof FieldExpression &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                ((FieldExpression)right).id == idSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                if (!field.isPrivate()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                    // The private case is handled below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                    // Use an access method unless the effective accessing class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                    // (the class qualifying the 'super') is the same as the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                    // immediately enclosing class, i.e., the qualification was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                    // unnecessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                    if (sourceClass != ctxClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                        implMethod = sourceClass.getAccessMember(env, ctx, field, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            // Access method for private field if not in the same class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            if (implMethod == null && field.isPrivate()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
                ClassDefinition cdef = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                if (cdef != ctxClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
                    implMethod = cdef.getAccessMember(env, ctx, field, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            // Make sure that we are not invoking an abstract method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
            if (field.isAbstract() && (right != null) && (right.op == SUPER)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                env.error(where, "invoke.abstract", field, field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            if (field.reportDeprecated(env)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                if (field.isConstructor()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                    env.error(where, "warn.constr.is.deprecated", field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                    env.error(where, "warn.meth.is.deprecated",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                              field, field.getClassDefinition());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            // Check for recursive constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
            if (field.isConstructor() && ctx.field.equals(field)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                env.error(where, "recursive.constr", field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
            // When a package-private class defines public or protected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            // members, those members may sometimes be accessed from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            // outside of the package in public subclasses.  In these
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            // cases, we need to massage the method call to refer to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
            // to an accessible subclass rather than the package-private
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            // parent class.  Part of fix for 4135692.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            // Find out if the class which contains this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            // call has access to the class which declares the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            // public or protected method referent.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
            // We don't perform this translation on constructor calls.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
            if (sourceClass == ctxClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                ClassDefinition declarer = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                if (!field.isConstructor() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                    declarer.isPackagePrivate() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                    !declarer.getName().getQualifier()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                    .equals(sourceClass.getName().getQualifier())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                    //System.out.println("The access of member " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                    //             field + " declared in class " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                    //             declarer +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                    //             " is not allowed by the VM from class  " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                    //             accessor +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                    //             ".  Replacing with an access of class " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
                    //             clazz);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                    // We cannot make this access at the VM level.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                    // Construct a member which will stand for this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                    // method in clazz and set `field' to refer to it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                    field =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                        MemberDefinition.makeProxyMember(field, clazz, env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
            sourceClass.addDependency(field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            if (sourceClass != ctxClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
                ctxClass.addDependency(field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        } catch (ClassNotFound ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            env.error(where, "class.not.found", ee.name, ctx.field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        } catch (AmbiguousMember ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
            env.error(where, "ambig.field", id, ee.field1, ee.field2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        // Make sure it is qualified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
        if ((right == null) && !field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
            right = ctx.findOuterLink(env, where, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            vset = right.checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        // Cast arguments
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        argTypes = field.getType().getArgumentTypes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        for (int i = 0 ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            args[i] = convert(env, ctx, argTypes[i], args[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        if (field.isConstructor()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
            MemberDefinition m = field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            if (implMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                m = implMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            int nargs = args.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            Expression[] newargs = args;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
            if (nargs > this.args.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                // Argument was added above.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                // Maintain the model for hidden outer args in outer.super(...):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                Expression rightI;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                if (right instanceof SuperExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                    rightI = new SuperExpression(right.where, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                    ((SuperExpression)right).outerArg = args[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                } else if (right instanceof ThisExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                    rightI = new ThisExpression(right.where, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                    throw new CompilerError("this.init");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                if (implMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                    // Need dummy argument for access method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                    // Dummy argument follows outer instance link.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                    // Leave 'this.args' equal to 'newargs' but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                    // without the outer instance link.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                    newargs = new Expression[nargs+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                    this.args = new Expression[nargs];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                    newargs[0] = args[0]; // outer instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                    this.args[0] = newargs[1] = new NullExpression(where); // dummy argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                    for (int i = 1 ; i < nargs ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                        this.args[i] = newargs[i+1] = args[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                    // Strip outer instance link from 'this.args'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                    // ASSERT(this.arg.length == nargs-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                    for (int i = 1 ; i < nargs ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                        this.args[i-1] = args[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                implementation = new MethodExpression(where, rightI, m, newargs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                implementation.type = type; // Is this needed?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                // No argument was added.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
                if (implMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
                    // Need dummy argument for access method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                    // Dummy argument is first, as there is no outer instance link.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                    newargs = new Expression[nargs+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                    newargs[0] = new NullExpression(where);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
                    for (int i = 0 ; i < nargs ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                        newargs[i+1] = args[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                implementation = new MethodExpression(where, right, m, newargs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
            // Have ordinary method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            // Argument should have been added only for a constructor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            if (args.length > this.args.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                throw new CompilerError("method arg");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
            if (implMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                //System.out.println("Calling " + field + " via " + implMethod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
                Expression oldargs[] = this.args;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                    Expression call = new MethodExpression(where, null, implMethod, oldargs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                    implementation = new CommaExpression(where, right, call);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                    // Access method needs an explicit 'this' pointer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                    int nargs = oldargs.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                    Expression newargs[] = new Expression[nargs+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                    newargs[0] = right;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                    for (int i = 0; i < nargs; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
                        newargs[i+1] = oldargs[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                    implementation = new MethodExpression(where, null, implMethod, newargs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
        // Follow super() by variable initializations
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        if (ctx.field.isConstructor() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            field.isConstructor() && (right != null) && (right.op == SUPER)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
            Expression e = makeVarInits(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
            if (e != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
                if (implementation == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                    implementation = (Expression)this.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                implementation = new CommaExpression(where, implementation, e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        // Throw the declared exceptions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        ClassDeclaration exceptions[] = field.getExceptions(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        if (isArray && (field.getName() == idClone) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
               (field.getType().getArgumentTypes().length == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            /* Arrays pretend that they have "public Object clone()" that doesn't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
             * throw anything, according to the language spec.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            exceptions = new ClassDeclaration[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
            /* See if there's a bogus catch for it, to issue a warning. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
            for (Context p = ctx; p != null; p = p.prev) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
                if (p.node != null && p.node.op == TRY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                    ((TryStatement) p.node).arrayCloneWhere = where;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        for (int i = 0 ; i < exceptions.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
            if (exp.get(exceptions[i]) == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                exp.put(exceptions[i], this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        // Mark all blank finals as definitely assigned following 'this(...)'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        // Correctness follows inductively from the requirement that all blank finals
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        // be definitely assigned at the completion of every constructor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        if (ctx.field.isConstructor() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
            field.isConstructor() && (right != null) && (right.op == THIS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
            ClassDefinition cls = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
            for (MemberDefinition f = cls.getFirstMember() ; f != null ; f = f.getNextMember()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                if (f.isVariable() && f.isBlankFinal() && !f.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                    // Static variables should also be considered defined as well, but this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                    // is handled in 'SourceClass.checkMembers', and we should not interfere.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
                    vset = vset.addVar(ctx.getFieldNumber(f));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
     * Check void expression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
    public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
        return checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
     * We're about to report a "unmatched method" error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
     * Try to issue a better diagnostic by comparing the actual argument types
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
     * with the method (or methods) available.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
     * In particular, if there is an argument which fails to match <em>any</em>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
     * method, we report a type mismatch error against that particular argument.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
     * The diagnostic will report a target type taken from one of the methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
     * Return false if we couldn't think of anything smart to say.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
    boolean diagnoseMismatch(Environment env, Expression args[],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                             Type argTypes[]) throws ClassNotFound {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
        Type margType[] = new Type[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
        boolean saidSomething = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        int start = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        while (start < argTypes.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            int code = clazz.diagnoseMismatch(env, id, argTypes, start, margType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            String opName = (id.equals(idInit)) ? "constructor" : opNames[op];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            if (code == -2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                env.error(where, "wrong.number.args", opName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                saidSomething = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            if (code < 0)  break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            int i = code >> 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            boolean castOK = (code & 2) != 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
            boolean ambig = (code & 1) != 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
            Type targetType = margType[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
            // At least one argument is offensive to all overloadings.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
            // targetType is one of the argument types it does not match.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
            String ttype = ""+targetType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            // The message might be slightly misleading, if there are other
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
            // argument types that also would match.  Hint at this:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
            //if (ambig)  ttype = "{"+ttype+";...}";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
            if (castOK)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
                env.error(args[i].where, "explicit.cast.needed", opName, argTypes[i], ttype);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
                env.error(args[i].where, "incompatible.type", opName, argTypes[i], ttype);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
            saidSomething = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
            start = i+1;        // look for other bad arguments, too
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
        return saidSomething;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
     * Inline
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
    static final int MAXINLINECOST = Statement.MAXINLINECOST;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
    private
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
    Expression inlineMethod(Environment env, Context ctx, Statement s, boolean valNeeded) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        if (env.dump()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
            System.out.println("INLINE METHOD " + field + " in " + ctx.field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        LocalMember v[] = LocalMember.copyArguments(ctx, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        Statement body[] = new Statement[v.length + 2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        int n = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
            body[0] = new ExpressionStatement(where, right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            if ((right != null) && (right.op == SUPER)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                right = new ThisExpression(right.where, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
            body[0] = new VarDeclarationStatement(where, v[n++], right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        for (int i = 0 ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
            body[i + 1] = new VarDeclarationStatement(where, v[n++], args[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        //System.out.print("BEFORE:"); s.print(System.out); System.out.println();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
        // Note: If !valNeeded, then all returns in the body of the method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
        // change to void returns.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
        body[body.length - 1] = (s != null) ? s.copyInline(ctx, valNeeded) : null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
        //System.out.print("COPY:"); body[body.length - 1].print(System.out); System.out.println();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
        LocalMember.doneWithArguments(ctx, v);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        // Make sure the type matches what the return statements are returning.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        Type type = valNeeded ? this.type : Type.tVoid;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
        Expression e = new InlineMethodExpression(where, type, field, new CompoundStatement(where, body));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
        return valNeeded ? e.inlineValue(env, ctx) : e.inline(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
    public Expression inline(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
            return implementation.inline(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                right = field.isStatic() ? right.inline(env, ctx) : right.inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
            for (int i = 0 ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                args[i] = args[i].inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
            // ctxClass is the current class trying to inline this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
            ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
            Expression e = this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            if (env.opt() && field.isInlineable(env, clazz.isFinal()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                // Don't inline if a qualified non-static method: the call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
                // itself might throw NullPointerException as a side effect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
                ((right == null) || (right.op==THIS) || field.isStatic()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                // We only allow the inlining if the current class can access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                // the field, the field's class, and right's declared type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                ctxClass.permitInlinedAccess(env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                              field.getClassDeclaration()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                ctxClass.permitInlinedAccess(env, field) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                (right==null || ctxClass.permitInlinedAccess(env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                              env.getClassDeclaration(right.type)))  &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                ((id == null) || !id.equals(idInit)) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                (!ctx.field.isInitializer()) && ctx.field.isMethod() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                (ctx.getInlineMemberContext(field) == null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                Statement s = (Statement)field.getValue(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                if ((s == null) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                    (s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST))  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                    e = inlineMethod(env, ctx, s, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
            return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
            throw new CompilerError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
    public Expression inlineValue(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            return implementation.inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
            if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                right = field.isStatic() ? right.inline(env, ctx) : right.inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
            if (field.getName().equals(idInit)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                ClassDefinition refc = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
                UplevelReference r = refc.getReferencesFrozen();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                if (r != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                    r.willCodeArguments(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
            for (int i = 0 ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                args[i] = args[i].inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            // ctxClass is the current class trying to inline this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
            if (env.opt() && field.isInlineable(env, clazz.isFinal()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
                // Don't inline if a qualified non-static method: the call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                // itself might throw NullPointerException as a side effect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
                ((right == null) || (right.op==THIS) || field.isStatic()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                // We only allow the inlining if the current class can access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
                // the field, the field's class, and right's declared type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
                ctxClass.permitInlinedAccess(env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
                              field.getClassDeclaration()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                ctxClass.permitInlinedAccess(env, field) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
                (right==null || ctxClass.permitInlinedAccess(env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
                              env.getClassDeclaration(right.type)))  &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                (!ctx.field.isInitializer()) && ctx.field.isMethod() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                (ctx.getInlineMemberContext(field) == null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                Statement s = (Statement)field.getValue(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                if ((s == null) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                    (s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST))  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                    return inlineMethod(env, ctx, s, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
            return this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
            throw new CompilerError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
    public Expression copyInline(Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
            return implementation.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
        return super.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
    public int costInline(int thresh, Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            return implementation.costInline(thresh, env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
        // for now, don't allow calls to super() to be inlined.  We may fix
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
        // this later
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
        if ((right != null) && (right.op == SUPER)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            return thresh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
        return super.costInline(thresh, env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
     * Grab all instance initializer code from the class definition,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
     * and return as one bolus.  Note that we are assuming the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
     * the relevant fields have already been checked.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
     * (See the pre-pass in SourceClass.checkMembers which ensures this.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
    private Expression makeVarInits(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
        // insert instance initializers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
        ClassDefinition clazz = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
        Expression e = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
        for (MemberDefinition f = clazz.getFirstMember() ; f != null ; f = f.getNextMember()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
            if ((f.isVariable() || f.isInitializer()) && !f.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                    f.check(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
                } catch (ClassNotFound ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                    env.error(f.getWhere(), "class.not.found", ee.name,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                              f.getClassDefinition());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                Expression val = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
                if (f.isUplevelValue()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
                    if (f != clazz.findOuterMember()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
                        // it's too early to accumulate these
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
                        continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                    IdentifierExpression arg =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
                        new IdentifierExpression(where, f.getName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
                    if (!arg.bind(env, ctx)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
                        throw new CompilerError("bind "+arg.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                    val = arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
                } else if (f.isInitializer()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
                    Statement s = (Statement)f.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
                    val = new InlineMethodExpression(where, Type.tVoid, f, s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
                    val = (Expression)f.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
                // append all initializers to "e":
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
                // This section used to check for variables which were
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                // initialized to their default values and elide such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
                // initialization.  This is specifically disallowed by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                // JLS 12.5 numeral 4, which requires a textual ordering
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
                // on the execution of initializers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
                if ((val != null)) { //  && !val.equals(0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
                    long p = f.getWhere();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                    val = val.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                    Expression init = val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
                    if (f.isVariable()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                        Expression v = new ThisExpression(p, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
                    v = new FieldExpression(p, v, f);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
                    init = new AssignExpression(p, v, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
                    e = (e == null) ? init : new CommaExpression(p, e, init);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
        return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
     * Code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
    public void codeValue(Environment env, Context ctx, Assembler asm) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
            throw new CompilerError("codeValue");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
        int i = 0;              // argument index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
        if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
            if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
                right.code(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
        } else if (right == null) {
25522
10d789df41bb 8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents: 5506
diff changeset
   860
            asm.add(where, opc_aload, 0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
        } else if (right.op == SUPER) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
            // 'super.<method>(...)', 'super(...)', or '<expr>.super(...)'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
            /*****
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
            isSuper = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
            *****/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
            right.codeValue(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
            if (idInit.equals(id)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
                // 'super(...)' or '<expr>.super(...)' only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
                ClassDefinition refc = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
                UplevelReference r = refc.getReferencesFrozen();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
                if (r != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
                    // When calling a constructor for a class with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                    // embedded uplevel references, add extra arguments.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
                    if (r.isClientOuterField()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
                        // the extra arguments are inserted after this one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                        args[i++].codeValue(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
                    r.codeArguments(env, ctx, asm, where, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
            right.codeValue(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
            /*****
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
            if (right.op == FIELD &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
                ((FieldExpression)right).id == idSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
                // '<class>.super.<method>(...)'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
                isSuper = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
            *****/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
        for ( ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
            args[i].codeValue(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
        if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
            asm.add(where, opc_invokestatic, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        } else if (field.isConstructor() || field.isPrivate() || isSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
            asm.add(where, opc_invokespecial, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
        } else if (field.getClassDefinition().isInterface()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
            asm.add(where, opc_invokeinterface, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
            asm.add(where, opc_invokevirtual, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        if (right != null && right.op == SUPER && idInit.equals(id)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
            // 'super(...)' or '<expr>.super(...)'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
            ClassDefinition refc = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
            UplevelReference r = refc.getReferencesFrozen();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
            if (r != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
                // After calling a superclass constructor in a class with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
                // embedded uplevel references, initialize uplevel fields.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
                r.codeInitialization(env, ctx, asm, where, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
     * Check if the first thing is a constructor invocation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
    public Expression firstConstructor() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
        return id.equals(idInit) ? this : null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
     * Print
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
    public void print(PrintStream out) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
        out.print("(" + opNames[op]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
        if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
            out.print(" ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
            right.print(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
        out.print(" " + ((id == null) ? idInit : id));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
        for (int i = 0 ; i < args.length ; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
            out.print(" ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
            if (args[i] != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
                args[i].print(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                out.print("<null>");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
        out.print(")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
        if (implementation != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
            out.print("/IMPL=");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
            implementation.print(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
}