alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (IdentifierExpression.java)

This example Java source code file (IdentifierExpression.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

ambiguousmember, assembler, classdefinition, classnotfound, context, expression, fieldexpression, fieldupdater, hashtable, identifierexpression, localmember, memberdefinition, typeexpression, util, vset

The IdentifierExpression.java Java example source code

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

package sun.tools.tree;

import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.LocalVariable;
import java.io.PrintStream;
import java.util.Hashtable;

/**
 * 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 IdentifierExpression extends Expression {
    Identifier id;
    MemberDefinition field;
    Expression implementation;

    /**
     * Constructor
     */
    public IdentifierExpression(long where, Identifier id) {
        super(IDENT, where, Type.tError);
        this.id = id;
    }
    public IdentifierExpression(IdentifierToken id) {
        this(id.getWhere(), id.getName());
    }
    public IdentifierExpression(long where, MemberDefinition field) {
        super(IDENT, where, field.getType());
        this.id = field.getName();
        this.field = field;
    }

    public Expression getImplementation() {
        if (implementation != null)
            return implementation;
        return this;
    }

    /**
     * Check if the expression is equal to a value
     */
    public boolean equals(Identifier id) {
        return this.id.equals(id);
    }


    /**
     * Assign a value to this identifier.  [It must already be "bound"]
     */
    private Vset assign(Environment env, Context ctx, Vset vset) {
        if (field.isLocal()) {
            LocalMember local = (LocalMember)field;
            if (local.scopeNumber < ctx.frameNumber) {
                env.error(where, "assign.to.uplevel", id);
            }
            if (local.isFinal()) {
                // allow definite single assignment of blank finals
                if (!local.isBlankFinal()) {
                    env.error(where, "assign.to.final", id);
                } else if (!vset.testVarUnassigned(local.number)) {
                    env.error(where, "assign.to.blank.final", id);
                }
            }
            vset.addVar(local.number);
            local.writecount++;
        } else if (field.isFinal()) {
            vset = FieldExpression.checkFinalAssign(env, ctx, vset,
                                                    where, field);
        }
        return vset;
    }

    /**
     * Get the value of this identifier.  [ It must already be "bound"]
     */
    private Vset get(Environment env, Context ctx, Vset vset) {
        if (field.isLocal()) {
            LocalMember local = (LocalMember)field;
            if (local.scopeNumber < ctx.frameNumber && !local.isFinal()) {
                env.error(where, "invalid.uplevel", id);
            }
            if (!vset.testVar(local.number)) {
                env.error(where, "var.not.initialized", id);
                vset.addVar(local.number);
            }
            local.readcount++;
        } else {
            if (!field.isStatic()) {
                if (!vset.testVar(ctx.getThisNumber())) {
                    env.error(where, "access.inst.before.super", id);
                    implementation = null;
                }
            }
            if (field.isBlankFinal()) {
                int number = ctx.getFieldNumber(field);
                if (number >= 0 && !vset.testVar(number)) {
                    env.error(where, "var.not.initialized", id);
                }
            }
        }
        return vset;
    }

    /**
     * Bind to a field
     */
    boolean bind(Environment env, Context ctx) {
        try {
            field = ctx.getField(env, id);
            if (field == null) {
                for (ClassDefinition cdef = ctx.field.getClassDefinition();
                     cdef != null; cdef = cdef.getOuterClass()) {
                    if (cdef.findAnyMethod(env, id) != null) {
                        env.error(where, "invalid.var", id,
                                  ctx.field.getClassDeclaration());
                        return false;
                    }
                }
                env.error(where, "undef.var", id);
                return false;
            }

            type = field.getType();

            // Check access permission
            if (!ctx.field.getClassDefinition().canAccess(env, field)) {
                env.error(where, "no.field.access",
                          id, field.getClassDeclaration(),
                          ctx.field.getClassDeclaration());
                return false;
            }

            // Find out how to access this variable.
            if (field.isLocal()) {
                LocalMember local = (LocalMember)field;
                if (local.scopeNumber < ctx.frameNumber) {
                    // get a "val$x" copy via the current object
                    implementation = ctx.makeReference(env, local);
                }
            } else {
                MemberDefinition f = field;

                if (f.reportDeprecated(env)) {
                    env.error(where, "warn.field.is.deprecated",
                              id, f.getClassDefinition());
                }

                ClassDefinition fclass = f.getClassDefinition();
                if (fclass != ctx.field.getClassDefinition()) {
                    // Maybe an inherited field hides an apparent variable.
                    MemberDefinition f2 = ctx.getApparentField(env, id);
                    if (f2 != null && f2 != f) {
                        ClassDefinition c = ctx.findScope(env, fclass);
                        if (c == null)  c = f.getClassDefinition();
                        if (f2.isLocal()) {
                            env.error(where, "inherited.hides.local",
                                      id, c.getClassDeclaration());
                        } else {
                            env.error(where, "inherited.hides.field",
                                      id, c.getClassDeclaration(),
                                      f2.getClassDeclaration());
                        }
                    }
                }

                // Rewrite as a FieldExpression.
                // Access methods for private fields, if needed, will be added
                // during subsequent processing of the FieldExpression.  See
                // method 'FieldExpression.checkCommon'. This division of labor
                // is somewhat awkward, as most further processing of a
                // FieldExpression during the checking phase is suppressed when
                // the referenced field is pre-set as it is here.

                if (f.isStatic()) {
                    Expression base = new TypeExpression(where,
                                        f.getClassDeclaration().getType());
                    implementation = new FieldExpression(where, null, f);
                } else {
                    Expression base = ctx.findOuterLink(env, where, f);
                    if (base != null) {
                        implementation = new FieldExpression(where, base, f);
                    }
                }
            }

            // Check forward reference
            if (!ctx.canReach(env, field)) {
                env.error(where, "forward.ref",
                          id, field.getClassDeclaration());
                return false;
            }
            return true;
        } catch (ClassNotFound e) {
            env.error(where, "class.not.found", e.name, ctx.field);
        } catch (AmbiguousMember e) {
            env.error(where, "ambig.field", id,
                      e.field1.getClassDeclaration(),
                      e.field2.getClassDeclaration());
        }
        return false;
    }

    /**
     * Check expression
     */
    public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
        if (field != null) {
            // An internally pre-set field, such as an argument copying
            // an uplevel value.  Do not re-check it.
            return vset;
        }
        if (bind(env, ctx)) {
            vset = get(env, ctx, vset);
            ctx.field.getClassDefinition().addDependency(field.getClassDeclaration());
            if (implementation != null)
                vset = implementation.checkValue(env, ctx, vset, exp);
        }
        return vset;
    }

    /**
     * Check the expression if it appears on the LHS of an assignment
     */
    public Vset checkLHS(Environment env, Context ctx,
                         Vset vset, Hashtable exp) {
        if (!bind(env, ctx))
            return vset;
        vset = assign(env, ctx, vset);
        if (implementation != null)
            vset = implementation.checkValue(env, ctx, vset, exp);
        return vset;
    }

    /**
     * Check the expression if it appears on the LHS of an op= expression
     */
    public Vset checkAssignOp(Environment env, Context ctx,
                              Vset vset, Hashtable exp, Expression outside) {
        if (!bind(env, ctx))
            return vset;
        vset = assign(env, ctx, get(env, ctx, vset));
        if (implementation != null)
            vset = implementation.checkValue(env, ctx, vset, exp);
        return vset;
    }

    /**
     * Return an accessor if one is needed for assignments to this expression.
     */
    public FieldUpdater getAssigner(Environment env, Context ctx) {
        if (implementation != null)
            return implementation.getAssigner(env, ctx);
        return null;
    }

    /**
     * Return an updater if one is needed for assignments to this expression.
     */
    public FieldUpdater getUpdater(Environment env, Context ctx) {
        if (implementation != null)
            return implementation.getUpdater(env, ctx);
        return null;
    }

    /**
     * Check if the present name is part of a scoping prefix.
     */
    public Vset checkAmbigName(Environment env, Context ctx, Vset vset, Hashtable exp,
                               UnaryExpression loc) {
        try {
            if (ctx.getField(env, id) != null) {
                // if this is a local field, there's nothing more to do.
                return checkValue(env, ctx, vset, exp);
            }
        } catch (ClassNotFound ee) {
        } catch (AmbiguousMember ee) {
        }
        // Can this be interpreted as a type?
        ClassDefinition c = toResolvedType(env, ctx, true);
        // Is it a real type??
        if (c != null) {
            loc.right = new TypeExpression(where, c.getType());
            return vset;
        }
        // We hope it is a package prefix.  Let the caller decide.
        type = Type.tPackage;
        return vset;
    }

    /**
     * Convert an identifier to a known type, or null.
     */
    private ClassDefinition toResolvedType(Environment env, Context ctx,
                                           boolean pkgOK) {
        Identifier rid = ctx.resolveName(env, id);
        Type t = Type.tClass(rid);
        if (pkgOK && !env.classExists(t)) {
            return null;
        }
        if (env.resolve(where, ctx.field.getClassDefinition(), t)) {
            try {
                ClassDefinition c = env.getClassDefinition(t);

                // Maybe an inherited class hides an apparent class.
                if (c.isMember()) {
                    ClassDefinition sc = ctx.findScope(env, c.getOuterClass());
                    if (sc != c.getOuterClass()) {
                        Identifier rid2 = ctx.getApparentClassName(env, id);
                        if (!rid2.equals(idNull) && !rid2.equals(rid)) {
                            env.error(where, "inherited.hides.type",
                                      id, sc.getClassDeclaration());
                        }
                    }
                }

                if (!c.getLocalName().equals(id.getFlatName().getName())) {
                    env.error(where, "illegal.mangled.name", id, c);
                }

                return c;
            } catch (ClassNotFound ee) {
            }
        }
        return null;
    }

    /**
     * Convert an identifier to a type.
     * If one is not known, use the current package as a qualifier.
     */
    Type toType(Environment env, Context ctx) {
        ClassDefinition c = toResolvedType(env, ctx, false);
        if (c != null) {
            return c.getType();
        }
        return Type.tError;
    }

    /**
     * Convert an expresion to a type in a context where a qualified
     * type name is expected, e.g., in the prefix of a qualified type
     * name. We do not necessarily know where the package prefix ends,
     * so we operate similarly to 'checkAmbiguousName'.  This is the
     * base case -- the first component of the qualified name.
     */
    /*-------------------------------------------------------*
    Type toQualifiedType(Environment env, Context ctx) {
        // We do not look for non-type fields.  Is this correct?
        ClassDefinition c = toResolvedType(env, ctx, true);
        // Is it a real type?
        if (c != null) {
            return c.getType();
        }
        // We hope it is a package prefix.  Let the caller decide.
        return Type.tPackage;
    }
    *-------------------------------------------------------*/

    /**
     * Check if constant:  Will it inline away?
     */
    public boolean isConstant() {
        if (implementation != null)
            return implementation.isConstant();
        if (field != null) {
            return field.isConstant();
        }
        return false;
    }

    /**
     * Inline
     */
    public Expression inline(Environment env, Context ctx) {
        return null;
    }
    public Expression inlineValue(Environment env, Context ctx) {
        if (implementation != null)
            return implementation.inlineValue(env, ctx);
        if (field == null) {
            return this;
        }
        try {
            if (field.isLocal()) {
                if (field.isInlineable(env, false)) {
                    Expression e = (Expression)field.getValue(env);
                    return (e == null) ? this : e.inlineValue(env, ctx);
                }
                return this;
            }
            return this;
        } catch (ClassNotFound e) {
            throw new CompilerError(e);
        }
    }
    public Expression inlineLHS(Environment env, Context ctx) {
        if (implementation != null)
            return implementation.inlineLHS(env, ctx);
        return this;
    }

    public Expression copyInline(Context ctx) {
        if (implementation != null)
            return implementation.copyInline(ctx);
        IdentifierExpression e =
            (IdentifierExpression)super.copyInline(ctx);
        if (field != null && field.isLocal()) {
            e.field = ((LocalMember)field).getCurrentInlineCopy(ctx);
        }
        return e;
    }

    public int costInline(int thresh, Environment env, Context ctx) {
        if (implementation != null)
            return implementation.costInline(thresh, env, ctx);
        return super.costInline(thresh, env, ctx);
    }

    /**
     * Code local vars (object fields have been inlined away)
     */
    int codeLValue(Environment env, Context ctx, Assembler asm) {
        return 0;
    }
    void codeLoad(Environment env, Context ctx, Assembler asm) {
        asm.add(where, opc_iload + type.getTypeCodeOffset(),
                new Integer(((LocalMember)field).number));
    }
    void codeStore(Environment env, Context ctx, Assembler asm) {
        LocalMember local = (LocalMember)field;
        asm.add(where, opc_istore + type.getTypeCodeOffset(),
                new LocalVariable(local, local.number));
    }
    public void codeValue(Environment env, Context ctx, Assembler asm) {
        codeLValue(env, ctx, asm);
        codeLoad(env, ctx, asm);
    }

    /**
     * Print
     */
    public void print(PrintStream out) {
        out.print(id + "#" + ((field != null) ? field.hashCode() : 0));
        if (implementation != null) {
            out.print("/IMPL=");
            implementation.print(out);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java IdentifierExpression.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.