/*
 * Copyright 1994-2003 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.tree;

import sun.tools.java.*;
import sun.tools.asm.Assembler;

/**
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 */
public
class Context implements Constants {
    Context prev;
    Node node;
    int varNumber;
    LocalMember locals;
    LocalMember classes;
    MemberDefinition field;
    int scopeNumber;
    int frameNumber;

    /**
     * Create the initial context for a method
     * The incoming context is inherited from
     */
    public Context(Context ctx, MemberDefinition field) {
        this.field = field;
        if (ctx == null) {
            this.frameNumber = 1;
            this.scopeNumber = 2;
            this.varNumber = 0;
        } else {
            this.prev = ctx;
            this.locals = ctx.locals;
            this.classes = ctx.classes;
            if (field != null &&
                  (field.isVariable() || field.isInitializer())) {
                // Variables and initializers are inlined into a constructor.
                // Model this by inheriting the frame number of the parent,
                // which will contain a "this" parameter.
                this.frameNumber = ctx.frameNumber;
                this.scopeNumber = ctx.scopeNumber + 1;
            } else {
                this.frameNumber = ctx.scopeNumber + 1;
                this.scopeNumber = this.frameNumber + 1;
            }
            this.varNumber = ctx.varNumber;
        }
    }

    /**
     * Create a new context, for initializing a class.
     */
    public Context(Context ctx, ClassDefinition c) {
        this(ctx, (MemberDefinition)null);
    }

    /**
     * Create a new nested context, for a block statement
     */
    Context(Context ctx, Node node) {
        if (ctx == null) {
            this.frameNumber = 1;
            this.scopeNumber = 2;
            this.varNumber = 0;
        } else {
            this.prev = ctx;
            this.locals = ctx.locals;
            // Inherit local classes from surrounding block,
            // just as for local variables.  Fixes 4074421.
            this.classes = ctx.classes;
            this.varNumber = ctx.varNumber;
            this.field = ctx.field;
            this.frameNumber = ctx.frameNumber;
            this.scopeNumber = ctx.scopeNumber + 1;
            this.node = node;
        }
    }

    public Context(Context ctx) {
        this(ctx, (Node)null);
    }

    /**
     * Declare local
     */
    public int declare(Environment env, LocalMember local) {
        //System.out.println(   "DECLARE= " + local.getName() + "=" + varNumber + ", read=" + local.readcount + ", write=" + local.writecount + ", hash=" + local.hashCode());
        local.scopeNumber = scopeNumber;
        if (this.field == null && idThis.equals(local.getName())) {
            local.scopeNumber += 1; // Anticipate variable or initializer.
        }
        if (local.isInnerClass()) {
            local.prev = classes;
            classes = local;
            return 0;
        }

        // Originally the statement:
        //
        //     local.subModifiers(M_INLINEABLE);
        //
        // was here with the comment:
        //
        //     // prevent inlining across call sites
        //
        // This statement prevented constant local variables from
        // inlining. It didn't seem to do anything useful.
        //
        // The statement has been removed and an assertion has been
        // added which mandates that the only members which are marked
        // with M_INLINEABLE are the ones for which isConstant() is true.
        // (Fix for 4106244.)
        //
        // Addition to the above comment: they might also be
        // final variables initialized with 'this', 'super', or other
        // final identifiers.  See VarDeclarationStatement.inline().
        // So I've removed the assertion.  The original subModifiers
        // call appears to have been there to fix nested class translation
        // breakage, which has been fixed in VarDeclarationStatement
        // now instead.  (Fix for 4073244.)

        local.prev = locals;
        locals = local;
        local.number = varNumber;
        varNumber += local.getType().stackSize();
        return local.number;
    }

    /**
     * Get a local variable by name
     */
    public
    LocalMember getLocalField(Identifier name) {
        for (LocalMember f = locals ; f != null ; f = f.prev) {
            if (name.equals(f.getName())) {
                return f;
            }
        }
        return null;
    }

    /**
     * Get the scope number for a reference to a member of this class
     * (Larger scope numbers are more deeply nested.)
     * @see LocalMember#scopeNumber
     */
    public
    int getScopeNumber(ClassDefinition c) {
        for (Context ctx = this; ctx != null; ctx = ctx.prev) {
            if (ctx.field == null)  continue;
            if (ctx.field.getClassDefinition() == c) {
                return ctx.frameNumber;
            }
        }
        return -1;
    }

    private
    MemberDefinition getFieldCommon(Environment env, Identifier name,
                                   boolean apparentOnly) throws AmbiguousMember, ClassNotFound {
        // Note:  This is structured as a pair of parallel lookups.
        // If we were to redesign Context, we might prefer to walk
        // along a single chain of scopes.

        LocalMember lf = getLocalField(name);
        int ls = (lf == null) ? -2 : lf.scopeNumber;

        ClassDefinition thisClass = field.getClassDefinition();

        // Also look for a class member in a shallower scope.
        for (ClassDefinition c = thisClass;
             c != null;
             c = c.getOuterClass()) {
            MemberDefinition f = c.getVariable(env, name, thisClass);
            if (f != null && getScopeNumber(c) > ls) {
                if (apparentOnly && f.getClassDefinition() != c) {
                    continue;
                }
                return f;
            }
        }

        return lf;
    }

    /**
     * Assign a number to a class field.
     * (This is used to track definite assignment of some blank finals.)
     */
    public int declareFieldNumber(MemberDefinition field) {
        return declare(null, new LocalMember(field));
    }

    /**
     * Retrieve a number previously assigned by declareMember().
     * Return -1 if there was no such assignment in this context.
     */
    public int getFieldNumber(MemberDefinition field) {
        for (LocalMember f = locals ; f != null ; f = f.prev) {
            if (f.getMember() == field) {
                return f.number;
            }
        }
        return -1;
    }

    /**
     * Return the local field or member field corresponding to a number.
     * Return null if there is no such field.
     */
    public MemberDefinition getElement(int number) {
        for (LocalMember f = locals ; f != null ; f = f.prev) {
            if (f.number == number) {
                MemberDefinition field = f.getMember();
                return (field != null) ? field : f;
            }
        }
        return null;
    }

    /**
     * Get a local class by name
     */
    public
    LocalMember getLocalClass(Identifier name) {
        for (LocalMember f = classes ; f != null ; f = f.prev) {
            if (name.equals(f.getName())) {
                return f;
            }
        }
        return null;
    }

    private
    MemberDefinition getClassCommon(Environment env, Identifier name,
                                   boolean apparentOnly) throws ClassNotFound {
        LocalMember lf = getLocalClass(name);
        int ls = (lf == null) ? -2 : lf.scopeNumber;

        // Also look for a class member in a shallower scope.
        for (ClassDefinition c = field.getClassDefinition();
             c != null;
             c = c.getOuterClass()) {
            // QUERY: We may need to get the inner class from a
            // superclass of 'c'.  This call is prepared to
            // resolve the superclass if necessary.  Can we arrange
            // to assure that it is always previously resolved?
            // This is one of a small number of problematic calls that
            // requires 'getSuperClass' to resolve superclasses on demand.
            // See 'ClassDefinition.getInnerClass(env, nm)'.
            MemberDefinition f = c.getInnerClass(env, name);
            if (f != null && getScopeNumber(c) > ls) {
                if (apparentOnly && f.getClassDefinition() != c) {
                    continue;
                }
                return f;
            }
        }

        return lf;
    }

    /**
     * Get either a local variable, or a field in a current class
     */
    public final
    MemberDefinition getField(Environment env, Identifier name) throws AmbiguousMember, ClassNotFound {
        return getFieldCommon(env, name, false);
    }

    /**
     * Like getField, except that it skips over inherited fields.
     * Used for error checking.
     */
    public final
    MemberDefinition getApparentField(Environment env, Identifier name) throws AmbiguousMember, ClassNotFound {
        return getFieldCommon(env, name, true);
    }

    /**
     * Check if the given field is active in this context.
     */
    public boolean isInScope(LocalMember field) {
        for (LocalMember f = locals ; f != null ; f = f.prev) {
            if (field == f) {
                return true;
            }
        }
        return false;
    }

    /**
     * Notice a reference (usually an uplevel one).
     * Update the references list of every enclosing class
     * which is enclosed by the scope of the target.
     * Update decisions about which uplevels to make into fields.
     * Return the uplevel reference descriptor, or null if it's local.
     * <p>
     * The target must be in scope in this context.
     * So, call this method only from the check phase.
     * (In other phases, the context may be less complete.)
     * <p>
     * This can and should be called both before and after classes are frozen.
     * It should be a no-op, and will raise a compiler error if not.
     */
    public UplevelReference noteReference(Environment env, LocalMember target) {
        int targetScopeNumber = !isInScope(target) ? -1 : target.scopeNumber;

        // Walk outward visiting each scope.
        // Note each distinct frame (i.e., enclosing method).
        // For each frame in which the variable is uplevel,
        // record the event in the references list of the enclosing class.
        UplevelReference res = null;
        int currentFrameNumber = -1;
        for (Context refctx = this; refctx != null; refctx = refctx.prev) {
            if (currentFrameNumber == refctx.frameNumber) {
                continue;       // we're processing frames, not contexts
            }
            currentFrameNumber = refctx.frameNumber;
            if (targetScopeNumber >= currentFrameNumber) {
                break;          // the target is native to this frame
            }

            // process a frame which is using this variable as an uplevel
            ClassDefinition refc = refctx.field.getClassDefinition();
            UplevelReference r = refc.getReference(target);
            r.noteReference(env, refctx);

            // remember the reference pertaining to the innermost frame
            if (res == null) {
                res = r;
            }
        }
        return res;
    }

    /**
     * Implement a reference (usually an uplevel one).
     * Call noteReference() first, to make sure the reference
     * lists are up to date.
     * <p>
     * The resulting expression tree does not need checking;
     * it can be code-generated right away.
     * If the reference is not uplevel, the result is an IDENT or THIS.
     */
    public Expression makeReference(Environment env, LocalMember target) {
        UplevelReference r = noteReference(env, target);

        // Now create a referencing expression.
        if (r != null) {
            return r.makeLocalReference(env, this);
        } else if (idThis.equals(target.getName())) {
            return new ThisExpression(0, target);
        } else {
            return new IdentifierExpression(0, target);
        }
    }

    /**
     * Return a local expression which can serve as the base reference
     * for the given field.  If the field is a constructor, return an
     * expression for the implicit enclosing instance argument.
     * <p>
     * Return null if there is no need for such an argument,
     * or if there was an error.
     */
    public Expression findOuterLink(Environment env, long where,
                                    MemberDefinition f) {
        // reqc is the base pointer type required to use f
        ClassDefinition fc = f.getClassDefinition();
        ClassDefinition reqc = f.isStatic() ? null
                             : !f.isConstructor() ? fc
                             : fc.isTopLevel() ? null
                             : fc.getOuterClass();
        if (reqc == null) {
            return null;
        }
        return findOuterLink(env, where, reqc, f, false);
    }

    private static boolean match(Environment env,
                                 ClassDefinition thisc, ClassDefinition reqc) {
        try {
            return thisc == reqc
                || reqc.implementedBy(env, thisc.getClassDeclaration());
        } catch (ClassNotFound ee) {
            return false;
        }
    }

    public Expression findOuterLink(Environment env, long where,
                                    ClassDefinition reqc,
                                    MemberDefinition f,
                                    boolean needExactMatch) {
        if (field.isStatic()) {
            if (f == null) {
                // say something like: undefined variable A.this
                Identifier nm = reqc.getName().getFlatName().getName();
                env.error(where, "undef.var", Identifier.lookup(nm,idThis));
            } else if (f.isConstructor()) {
                env.error(where, "no.outer.arg", reqc, f.getClassDeclaration());
            } else if (f.isMethod()) {
                env.error(where, "no.static.meth.access",
                          f, f.getClassDeclaration());
            } else {
                env.error(where, "no.static.field.access", f.getName(),
                          f.getClassDeclaration());
            }
            // This is an attempt at error recovery.
            // Unfortunately, the constructor may throw
            // a null pointer exception after failing to resolve
            // 'idThis'.  Since an error message has already been
            // issued previously, this exception is caught and
            // silently ignored.  Ideally, we should avoid throwing
            // the exception.
            Expression e = new ThisExpression(where, this);
            e.type = reqc.getType();
            return e;
        }

        // use lp to scan for current instances (locals named "this")
        LocalMember lp = locals;

        // thise is a link expression being built up
        Expression thise = null;

        // root is the local variable (idThis) at the far left of thise
        LocalMember root = null;

        // thisc is the class of the link expression thise
        ClassDefinition thisc = null;

        // conCls is the class of the "this", in a constructor
        ClassDefinition conCls = null;
        if (field.isConstructor()) {
            conCls = field.getClassDefinition();
        }

        if (!field.isMethod()) {
            thisc = field.getClassDefinition();
            thise = new ThisExpression(where, this);
        }

        while (true) {
            if (thise == null) {
                // start fresh from lp
                while (lp != null && !idThis.equals(lp.getName())) {
                    lp = lp.prev;
                }
                if (lp == null) {
                    break;
                }
                thise = new ThisExpression(where, lp);
                thisc = lp.getClassDefinition();
                root = lp;
                lp = lp.prev;
            }

            // Require exact class identity when called with
            // 'needExactMatch' true.  This is done when checking
            // the '<class>.this' syntax.  Fixes 4102393 and 4133457.
            if (thisc == reqc ||
                (!needExactMatch && match(env, thisc, reqc))) {
                break;
            }

            // move out one step, if the current instance has an outer link

            MemberDefinition outerMember = thisc.findOuterMember();
            if (outerMember == null) {
                thise = null;
                continue;       // try to find more help in lp
            }
            ClassDefinition prevc = thisc;
            thisc = prevc.getOuterClass();

            if (prevc == conCls) {
                // Must pick up "this$C" from the constructor argument,
                // not from "this.this$C", since the latter may not be
                // initialized properly.  (This way is cheaper too.)
                Identifier nm = outerMember.getName();
                IdentifierExpression arg = new IdentifierExpression(where, nm);
                arg.bind(env, this);
                thise = arg;
            } else {
                thise = new FieldExpression(where, thise, outerMember);
            }
        }
        if (thise != null) {
            // mark crossed scopes
            // ?????
            //ensureAvailable(root);
            return thise;
        }

        if (f == null) {
            // say something like: undefined variable A.this
            Identifier nm = reqc.getName().getFlatName().getName();
            env.error(where, "undef.var", Identifier.lookup(nm,idThis));
        } else if (f.isConstructor()) {
            env.error(where, "no.outer.arg", reqc, f.getClassDefinition());
        } else {
            env.error(where, "no.static.field.access", f, field);
        }

        // avoid floodgating:
        Expression e = new ThisExpression(where, this);
        e.type = reqc.getType();
        return e;
    }

    /**
     * Is there a "this" of type reqc in scope?
     */
    public static boolean outerLinkExists(Environment env,
                                          ClassDefinition reqc,
                                          ClassDefinition thisc) {
        while (!match(env, thisc, reqc)) {
            if (thisc.isTopLevel()) {
                return false;
            }
            thisc = thisc.getOuterClass();
        }
        return true;
    }

    /**
     * From which enclosing class do members of this type come?
     */
    public ClassDefinition findScope(Environment env, ClassDefinition reqc) {
        ClassDefinition thisc = field.getClassDefinition();
        while (thisc != null && !match(env, thisc, reqc)) {
            thisc = thisc.getOuterClass();
        }
        return thisc;
    }

    /**
     * Resolve a type name from within a local scope.
     * @see Environment#resolveName
     */
    Identifier resolveName(Environment env, Identifier name) {
        // This logic is pretty much exactly parallel to that of
        // Environment.resolveName().
        if (name.isQualified()) {
            // Try to resolve the first identifier component,
            // because inner class names take precedence over
            // package prefixes.  (Cf. Environment.resolveName.)
            Identifier rhead = resolveName(env, name.getHead());

            if (rhead.hasAmbigPrefix()) {
                // The first identifier component refers to an
                // ambiguous class.  Limp on.  We throw away the
                // rest of the classname as it is irrelevant.
                // (part of solution for 4059855).
                return rhead;
            }

            if (!env.classExists(rhead)) {
                return env.resolvePackageQualifiedName(name);
            }
            try {
                return env.getClassDefinition(rhead).
                    resolveInnerClass(env, name.getTail());
            } catch (ClassNotFound ee) {
                // return partially-resolved name someone else can fail on
                return Identifier.lookupInner(rhead, name.getTail());
            }
        }

        // Look for an unqualified name in enclosing scopes.
        try {
            MemberDefinition f = getClassCommon(env, name, false);
            if (f != null) {
                return f.getInnerClass().getName();
            }
        } catch (ClassNotFound ee) {
            // a missing superclass, or something catastrophic
        }

        // look in imports, etc.
        return env.resolveName(name);
    }

    /**
     * Return the name of a lexically apparent type,
     * skipping inherited members, and ignoring
     * the current pacakge and imports.
     * This is used for error checking.
     */
    public
    Identifier getApparentClassName(Environment env, Identifier name) {
        if (name.isQualified()) {
            // Try to resolve the first identifier component,
            // because inner class names take precedence over
            // package prefixes.  (Cf. Environment.resolveName.)
            Identifier rhead = getApparentClassName(env, name.getHead());
            return (rhead == null) ? idNull
                : Identifier.lookup(rhead,
                                    name.getTail());
        }

        // Look for an unqualified name in enclosing scopes.
        try {
            MemberDefinition f = getClassCommon(env, name, true);
            if (f != null) {
                return f.getInnerClass().getName();
            }
        } catch (ClassNotFound ee) {
            // a missing superclass, or something catastrophic
        }

        // the enclosing class name is the only apparent package member:
        Identifier topnm = field.getClassDefinition().getTopClass().getName();
        if (topnm.getName().equals(name)) {
            return topnm;
        }
        return idNull;
    }

    /**
     * Raise an error if a blank final was definitely unassigned
     * on entry to a loop, but has possibly been assigned on the
     * back-branch.  If this is the case, the loop may be assigning
     * it multiple times.
     */
    public void checkBackBranch(Environment env, Statement loop,
                                Vset vsEntry, Vset vsBack) {
        for (LocalMember f = locals ; f != null ; f = f.prev) {
            if (f.isBlankFinal()
                && vsEntry.testVarUnassigned(f.number)
                && !vsBack.testVarUnassigned(f.number)) {
                env.error(loop.where, "assign.to.blank.final.in.loop",
                          f.getName());
            }
        }
    }

    /**
     * Check if a field can reach another field (only considers
     * forward references, not the access modifiers).
     */
    public boolean canReach(Environment env, MemberDefinition f) {
        return field.canReach(env, f);
    }

    /**
     * Get the context that corresponds to a label, return null if
     * not found.
     */
    public
    Context getLabelContext(Identifier lbl) {
        for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
            if ((ctx.node != null) && (ctx.node instanceof Statement)) {
                if (((Statement)(ctx.node)).hasLabel(lbl))
                    return ctx;
            }
        }
        return null;
    }

    /**
     * Get the destination context of a break
     */
    public
    Context getBreakContext(Identifier lbl) {
        if (lbl != null) {
            return getLabelContext(lbl);
        }
        for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
            if (ctx.node != null) {
                switch (ctx.node.op) {
                  case SWITCH:
                  case FOR:
                  case DO:
                  case WHILE:
                    return ctx;
                }
            }
        }
        return null;
    }

    /**
     * Get the destination context of a continue
     */
    public
    Context getContinueContext(Identifier lbl) {
        if (lbl != null) {
            return getLabelContext(lbl);
        }
        for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
            if (ctx.node != null) {
                switch (ctx.node.op) {
                  case FOR:
                  case DO:
                  case WHILE:
                    return ctx;
                }
            }
        }
        return null;
    }

    /**
     * Get the destination context of a return (the method body)
     */
    public
    CheckContext getReturnContext() {
        for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
            // The METHOD node is set up by Statement.checkMethod().
            if (ctx.node != null && ctx.node.op == METHOD) {
                return (CheckContext)ctx;
            }
        }
        return null;
    }

    /**
     * Get the context of the innermost surrounding try-block.
     * Consider only try-blocks contained within the same method.
     * (There could be others when searching from within a method
     * of a local class, but they are irrelevant to our purpose.)
     * This is used for recording DA/DU information preceding
     * all abnormal transfers of control: break, continue, return,
     * and throw.
     */
    public
    CheckContext getTryExitContext() {
        for (Context ctx = this;
             ctx != null && ctx.node != null && ctx.node.op != METHOD;
             ctx = ctx.prev) {
            if (ctx.node.op == TRY) {
                return (CheckContext)ctx;
            }
        }
        return null;
    }

    /**
     * Get the nearest inlined context
     */
    Context getInlineContext() {
        for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
            if (ctx.node != null) {
                switch (ctx.node.op) {
                  case INLINEMETHOD:
                  case INLINENEWINSTANCE:
                    return ctx;
                }
            }
        }
        return null;
    }

    /**
     * Get the context of a field that is being inlined
     */
    Context getInlineMemberContext(MemberDefinition field) {
        for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
            if (ctx.node != null) {
                switch (ctx.node.op) {
                  case INLINEMETHOD:
                    if (((InlineMethodExpression)ctx.node).field.equals(field)) {
                        return ctx;
                    }
                    break;
                  case INLINENEWINSTANCE:
                    if (((InlineNewInstanceExpression)ctx.node).field.equals(field)) {
                        return ctx;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Remove variables from the vset set  that are no longer part of
     * this context.
     */
    public final Vset removeAdditionalVars(Vset vset) {
        return vset.removeAdditionalVars(varNumber);
    }

    public final int getVarNumber() {
        return varNumber;
    }

    /**
     * Return the number of the innermost current instance reference.
     */
    public int getThisNumber() {
        LocalMember thisf = getLocalField(idThis);
        if (thisf != null
            && thisf.getClassDefinition() == field.getClassDefinition()) {
            return thisf.number;
        }
        // this is a variable; there is no "this" (should not happen)
        return varNumber;
    }

    /**
     * Return the field containing the present context.
     */
    public final MemberDefinition getField() {
        return field;
    }

    /**
     * Extend an environment with the given context.
     * The resulting environment behaves the same as
     * the given one, except that resolveName() takes
     * into account local class names in this context.
     */
    public static Environment newEnvironment(Environment env, Context ctx) {
        return new ContextEnvironment(env, ctx);
    }
}

final
class ContextEnvironment extends Environment {
    Context ctx;
    Environment innerEnv;

    ContextEnvironment(Environment env, Context ctx) {
        super(env, env.getSource());
        this.ctx = ctx;
        this.innerEnv = env;
    }

    public Identifier resolveName(Identifier name) {
        return ctx.resolveName(innerEnv, name);
    }
}
