1/*
2 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.tools.tree;
27
28import sun.tools.java.*;
29import sun.tools.asm.Assembler;
30import sun.tools.asm.Label;
31import java.io.PrintStream;
32import java.util.Hashtable;
33
34/**
35 * WARNING: The contents of this source file are not part of any
36 * supported API.  Code that depends on them does so at its own risk:
37 * they are subject to change or removal without notice.
38 */
39public
40class CompoundStatement extends Statement {
41    Statement args[];
42
43    /**
44     * Constructor
45     */
46    public CompoundStatement(long where, Statement args[]) {
47        super(STAT, where);
48        this.args = args;
49        // To avoid the need for subsequent null checks:
50        for (int i = 0 ; i < args.length ; i++) {
51            if (args[i] == null) {
52                args[i] = new CompoundStatement(where, new Statement[0]);
53            }
54        }
55    }
56
57    /**
58     * Insert a new statement at the front.
59     * This is used to introduce an implicit super-class constructor call.
60     */
61    public void insertStatement(Statement s) {
62        Statement newargs[] = new Statement[1+args.length];
63        newargs[0] = s;
64        for (int i = 0 ; i < args.length ; i++) {
65            newargs[i+1] = args[i];
66        }
67        this.args = newargs;
68    }
69
70    /**
71     * Check statement
72     */
73    Vset check(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp) {
74        checkLabel(env, ctx);
75        if (args.length > 0) {
76            vset = reach(env, vset);
77            CheckContext newctx = new CheckContext(ctx, this);
78            // In this environment, 'resolveName' will look for local classes.
79            Environment newenv = Context.newEnvironment(env, newctx);
80            for (int i = 0 ; i < args.length ; i++) {
81                vset = args[i].checkBlockStatement(newenv, newctx, vset, exp);
82            }
83            vset = vset.join(newctx.vsBreak);
84        }
85        return ctx.removeAdditionalVars(vset);
86    }
87
88    /**
89     * Inline
90     */
91    public Statement inline(Environment env, Context ctx) {
92        ctx = new Context(ctx, this);
93        boolean expand = false;
94        int count = 0;
95        for (int i = 0 ; i < args.length ; i++) {
96            Statement s = args[i];
97            if (s != null) {
98                if ((s = s.inline(env, ctx)) != null) {
99                    if ((s.op == STAT) && (s.labels == null)) {
100                        count += ((CompoundStatement)s).args.length;
101                    } else {
102                        count++;
103                    }
104                    expand = true;
105                }
106                args[i] = s;
107            }
108        }
109        switch (count) {
110          case 0:
111            return null;
112
113          case 1:
114            for (int i = args.length ; i-- > 0 ;) {
115                if (args[i] != null) {
116                    return eliminate(env, args[i]);
117                }
118            }
119            break;
120        }
121        if (expand || (count != args.length)) {
122            Statement newArgs[] = new Statement[count];
123            for (int i = args.length ; i-- > 0 ;) {
124                Statement s = args[i];
125                if (s != null) {
126                    if ((s.op == STAT) && (s.labels == null)) {
127                        Statement a[] = ((CompoundStatement)s).args;
128                        for (int j = a.length ; j-- > 0 ; ) {
129                            newArgs[--count] = a[j];
130                        }
131                    } else {
132                        newArgs[--count] = s;
133                    }
134                }
135            }
136            args = newArgs;
137        }
138        return this;
139    }
140
141    /**
142     * Create a copy of the statement for method inlining
143     */
144    public Statement copyInline(Context ctx, boolean valNeeded) {
145        CompoundStatement s = (CompoundStatement)clone();
146        s.args = new Statement[args.length];
147        for (int i = 0 ; i < args.length ; i++) {
148            s.args[i] = args[i].copyInline(ctx, valNeeded);
149        }
150        return s;
151    }
152
153    /**
154     * The cost of inlining this statement
155     */
156    public int costInline(int thresh, Environment env, Context ctx) {
157        int cost = 0;
158        for (int i = 0 ; (i < args.length) && (cost < thresh) ; i++) {
159            cost += args[i].costInline(thresh, env, ctx);
160        }
161        return cost;
162    }
163
164    /**
165     * Code
166     */
167    public void code(Environment env, Context ctx, Assembler asm) {
168        CodeContext newctx = new CodeContext(ctx, this);
169        for (int i = 0 ; i < args.length ; i++) {
170            args[i].code(env, newctx, asm);
171        }
172        asm.add(newctx.breakLabel);
173    }
174
175    /**
176     * Check if the first thing is a constructor invocation
177     */
178    public Expression firstConstructor() {
179        return (args.length > 0) ? args[0].firstConstructor() : null;
180    }
181
182    /**
183     * Print
184     */
185    public void print(PrintStream out, int indent) {
186        super.print(out, indent);
187        out.print("{\n");
188        for (int i = 0 ; i < args.length ; i++) {
189            printIndent(out, indent+1);
190            if (args[i] != null) {
191                args[i].print(out, indent + 1);
192            } else {
193                out.print("<empty>");
194            }
195            out.print("\n");
196        }
197        printIndent(out, indent);
198        out.print("}");
199    }
200}
201