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

Java example source code file (Statement.java)

This example Java source code file (Statement.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

assembler, checkcontext, compilererror, compoundstatement, context, expression, finally, finallystatement, hashtable, identifier, statement, synchronized, type, util, vset

The Statement.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.Label;
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 Statement extends Node {
    public static final Vset DEAD_END = Vset.DEAD_END;
    Identifier labels[] = null;

    /**
     * Constructor
     */
    Statement(int op, long where) {
        super(op, where);
    }

    /**
     * An empty statement.  Its costInline is infinite.
     */
    public static final Statement empty = new Statement(STAT, 0);

    /**
     * The largest possible interesting inline cost value.
     */
    public static final int MAXINLINECOST =
                      Integer.getInteger("javac.maxinlinecost",
                                         30).intValue();

    /**
     * Insert a bit of code at the front of a statement.
     * Side-effect s2, if it is a CompoundStatement.
     */
    public static Statement insertStatement(Statement s1, Statement s2) {
        if (s2 == null) {
            s2 = s1;
        } else if (s2 instanceof CompoundStatement) {
            // Do not add another level of block nesting.
            ((CompoundStatement)s2).insertStatement(s1);
        } else {
            Statement body[] = { s1, s2 };
            s2 = new CompoundStatement(s1.getWhere(), body);
        }
        return s2;
    }

    /**
     * Set the label of a statement
     */
    public void setLabel(Environment env, Expression e) {
        if (e.op == IDENT) {
            if (labels == null) {
                labels = new Identifier[1];
            } else {
                // this should almost never happen.  Multiple labels on
                // the same statement.  But handle it gracefully.
                Identifier newLabels[] = new Identifier[labels.length + 1];
                System.arraycopy(labels, 0, newLabels, 1, labels.length);
                labels = newLabels;
            }
            labels[0] = ((IdentifierExpression)e).id;
        } else {
            env.error(e.where, "invalid.label");
        }
    }

    /**
     * Check a statement
     */
    public Vset checkMethod(Environment env, Context ctx, Vset vset, Hashtable exp) {
        // Set up ctx.getReturnContext() for the sake of ReturnStatement.check().
        CheckContext mctx = new CheckContext(ctx, new Statement(METHOD, 0));
        ctx = mctx;

        vset = check(env, ctx, vset, exp);

        // Check for return
        if (!ctx.field.getType().getReturnType().isType(TC_VOID)) {
            // In general, we suppress further error messages due to
            // unreachable statements after reporting the first error
            // along a flow path (using 'clearDeadEnd').   Here, we
            // report an error anyway, because the end of the method
            // should be unreachable despite the earlier error.  The
            // difference in treatment is due to the fact that, in this
            // case, the error is reachability, not unreachability.
            // NOTE: In addition to this subtle difference in the quality
            // of the error diagnostics, this treatment is essential to
            // preserve the correctness of using 'clearDeadEnd' to implement
            // the special-case reachability rules for if-then and if-then-else.
            if (!vset.isDeadEnd()) {
                env.error(ctx.field.getWhere(), "return.required.at.end", ctx.field);
            }
        }

        // Simulate a return at the end.
        vset = vset.join(mctx.vsBreak);

        return vset;
    }
    Vset checkDeclaration(Environment env, Context ctx, Vset vset, int mod, Type t, Hashtable exp) {
        throw new CompilerError("checkDeclaration");
    }

    /**
     * Make sure the labels on this statement do not duplicate the
     * labels on any enclosing statement.  Provided as a convenience
     * for subclasses.
     */
    protected void checkLabel(Environment env, Context ctx) {
        if (labels != null) {
            loop: for (int i = 0; i < labels.length; i++) {
                // Make sure there is not a double label on this statement.
                for (int j = i+1; j < labels.length; j++) {
                    if (labels[i] == labels[j]) {
                        env.error(where, "nested.duplicate.label", labels[i]);
                        continue loop;
                    }
                }

                // Make sure no enclosing statement has the same label.
                CheckContext destCtx =
                    (CheckContext) ctx.getLabelContext(labels[i]);

                if (destCtx != null) {
                    // Check to make sure the label is in not uplevel.
                    if (destCtx.frameNumber == ctx.frameNumber) {
                        env.error(where, "nested.duplicate.label", labels[i]);
                    }
                }
            } // end loop
        }
    }

    Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
        throw new CompilerError("check");
    }

    /** This is called in contexts where declarations are valid. */
    Vset checkBlockStatement(Environment env, Context ctx, Vset vset, Hashtable exp) {
        return check(env, ctx, vset, exp);
    }

    Vset reach(Environment env, Vset vset) {
        if (vset.isDeadEnd()) {
            env.error(where, "stat.not.reached");
            vset = vset.clearDeadEnd();
        }
        return vset;
    }

    /**
     * Inline
     */
    public Statement inline(Environment env, Context ctx) {
        return this;
    }

    /**
     * Eliminate this statement, which is only possible if it has no label.
     */
    public Statement eliminate(Environment env, Statement s) {
        if ((s != null) && (labels != null)) {
            Statement args[] = {s};
            s = new CompoundStatement(where, args);
            s.labels = labels;
        }
        return s;
    }


    /**
     * Code
     */
    public void code(Environment env, Context ctx, Assembler asm) {
        throw new CompilerError("code");
    }

    /**
     * Generate the code to call all finally's for a break, continue, or
     * return statement.  We must call "jsr" on all the cleanup code between
     * the current context "ctx", and the destination context "stopctx".
     * If 'save' isn't null, there is also a value on the top of the stack
     */
    void codeFinally(Environment env, Context ctx, Assembler asm,
                        Context stopctx, Type save) {
        Integer num = null;
        boolean haveCleanup = false; // there is a finally or synchronize;
        boolean haveNonLocalFinally = false; // some finally doesn't return;

        for (Context c = ctx; (c != null) && (c != stopctx); c = c.prev) {
            if (c.node == null)
                continue;
            if (c.node.op == SYNCHRONIZED) {
                haveCleanup = true;
            } else if (c.node.op == FINALLY
                          && ((CodeContext)c).contLabel != null) {
                // c.contLabel == null indicates we're in the "finally" part
                haveCleanup = true;
                FinallyStatement st = ((FinallyStatement)(c.node));
                if (!st.finallyCanFinish) {
                    haveNonLocalFinally = true;
                    // after hitting a non-local finally, no need generating
                    // further code, because it won't get executed.
                    break;
                }
            }
        }
        if (!haveCleanup) {
            // there is no cleanup that needs to be done.  Just quit.
            return;
        }
        if (save != null) {
            // This statement has a return value on the stack.
            ClassDefinition def = ctx.field.getClassDefinition();
            if (!haveNonLocalFinally) {
                // Save the return value in the register which should have
                // been reserved.
                LocalMember lf = ctx.getLocalField(idFinallyReturnValue);
                num = new Integer(lf.number);
                asm.add(where, opc_istore + save.getTypeCodeOffset(), num);
            } else {
                // Pop the return value.
                switch(ctx.field.getType().getReturnType().getTypeCode()) {
                    case TC_VOID:
                        break;
                    case TC_DOUBLE: case TC_LONG:
                        asm.add(where, opc_pop2); break;
                    default:
                        asm.add(where, opc_pop); break;
                }
            }
        }
        // Call each of the cleanup functions, as necessary.
        for (Context c = ctx ; (c != null)  && (c != stopctx) ; c = c.prev) {
            if (c.node == null)
                continue;
            if (c.node.op == SYNCHRONIZED) {
                asm.add(where, opc_jsr, ((CodeContext)c).contLabel);
            } else if (c.node.op == FINALLY
                          && ((CodeContext)c).contLabel != null) {
                FinallyStatement st = ((FinallyStatement)(c.node));
                Label label = ((CodeContext)c).contLabel;
                if (st.finallyCanFinish) {
                    asm.add(where, opc_jsr, label);
                } else {
                    // the code never returns, so we're done.
                    asm.add(where, opc_goto, label);
                    break;
                }
            }
        }
        // Move the return value from the register back to the stack.
        if (num != null) {
            asm.add(where, opc_iload + save.getTypeCodeOffset(), num);
        }
    }

    /*
     * Return true if the statement has the given label
     */
    public boolean hasLabel (Identifier lbl) {
        Identifier labels[] = this.labels;
        if (labels != null) {
            for (int i = labels.length; --i >= 0; ) {
                if (labels[i].equals(lbl)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Check if the first thing is a constructor invocation
     */
    public Expression firstConstructor() {
        return null;
    }

    /**
     * Create a copy of the statement for method inlining
     */
    public Statement copyInline(Context ctx, boolean valNeeded) {
        return (Statement)clone();
    }

    public int costInline(int thresh, Environment env, Context ctx) {
        return thresh;
    }


    /**
     * Print
     */
    void printIndent(PrintStream out, int indent) {
        for (int i = 0 ; i < indent ; i++) {
            out.print("    ");
        }
    }
    public void print(PrintStream out, int indent) {
        if (labels != null) {
            for (int i = labels.length; --i >= 0; )
                out.print(labels[i] + ": ");
        }
    }
    public void print(PrintStream out) {
        print(out, 0);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Statement.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.