1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 /* Generated By:JJTree: Do not edit this line. ASTLetExpr.java */
19 /* JJT: 0.3pre1 */
20 
21 package Mini;
22 import org.apache.bcel.generic.BasicType;
23 import org.apache.bcel.generic.ConstantPoolGen;
24 import org.apache.bcel.generic.ISTORE;
25 import org.apache.bcel.generic.InstructionHandle;
26 import org.apache.bcel.generic.InstructionList;
27 import org.apache.bcel.generic.LocalVariableGen;
28 import org.apache.bcel.generic.MethodGen;
29 import org.apache.bcel.generic.Type;
30 
31 /**
32  *
33  * @version $Id$
34  */
35 public class ASTLetExpr extends ASTExpr implements org.apache.bcel.Constants {
36   private ASTIdent[]  idents;
37   private ASTExpr[]   exprs;
38   private ASTExpr     body;
39 
40   // Generated methods
ASTLetExpr(int id)41   ASTLetExpr(int id) {
42     super(id);
43   }
44 
ASTLetExpr(MiniParser p, int id)45   ASTLetExpr(MiniParser p, int id) {
46     super(p, id);
47   }
48 
jjtCreate(MiniParser p, int id)49   public static Node jjtCreate(MiniParser p, int id) {
50     return new ASTLetExpr(p, id);
51   }
52 
53 
54   /**
55    * Overrides ASTExpr.closeNode()
56    * Cast children nodes to appropiate types.
57    */
58   @Override
closeNode()59   public void closeNode() {
60     int i, len_2 = children.length / 2; /* length must be a multiple of
61                                          * two (ident = expr) + 1 (body expr) */
62     idents = new ASTIdent[len_2];
63     exprs  = new ASTExpr[len_2];
64 
65     // At least one assignment is enforced by the grammar
66     for(i=0; i < len_2; i++) {
67       idents[i] = (ASTIdent)children[i * 2];
68       exprs[i]  = (ASTExpr)children[i * 2 + 1];
69     }
70 
71     body = (ASTExpr)children[children.length - 1]; // Last expr is the body
72     children=null; // Throw away old reference
73   }
74 
75   /**
76    * Overrides ASTExpr.traverse()
77    */
78   @Override
traverse(Environment env)79   public ASTExpr traverse(Environment env) {
80     this.env = env;
81 
82     // Traverse RHS exprs first, so no references to LHS vars are allowed
83     for(int i=0; i < exprs.length; i++) {
84         exprs[i] = exprs[i].traverse((Environment)env.clone());
85     }
86 
87     // Put argument names into hash table aka. environment
88     for(int i=0; i < idents.length; i++) {
89       ASTIdent id    = idents[i];
90       String   name  = id.getName();
91       EnvEntry entry = env.get(name);
92 
93       if(entry != null) {
94         MiniC.addError(id.getLine(), id.getColumn(),
95                        "Redeclaration of " + entry + ".");
96     } else {
97         env.put(new Variable(id));
98     }
99     }
100 
101     body = body.traverse(env);
102 
103     return this;
104   }
105 
106   /**
107    * Second pass
108    * Overrides AstExpr.eval()
109    * @return type of expression
110    * @param expected type
111    */
112   @Override
eval(int expected)113   public int eval(int expected) {
114     //is_simple = true;
115 
116     for(int i=0; i < idents.length; i++) {
117       int t = exprs[i].eval(T_UNKNOWN);
118 
119       idents[i].setType(t);
120       //      is_simple = is_simple && exprs[i].isSimple();
121     }
122 
123     return type = body.eval(expected);
124   }
125 
126   /**
127    * Fifth pass, produce Java code.
128    */
129   @Override
code(StringBuffer buf)130   public void code(StringBuffer buf) {
131     for(int i = 0; i < idents.length; i++) {
132       String ident = idents[i].getName();
133       int    t     = idents[i].getType(); // can only be int
134 
135       /* Idents have to be declared at start of function for later use.
136        * Each name is unique, so there shouldn't be a problem in application.
137        */
138       exprs[i].code(buf);
139 
140       buf.append("    " + TYPE_NAMES[t] + " " + ident + " = " +
141                  ASTFunDecl.pop() + ";\n");
142     }
143 
144     body.code(buf);
145   }
146 
147   /**
148    * Fifth pass, produce Java byte code.
149    */
150   @Override
byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp)151   public void byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp) {
152     int size = idents.length;
153     LocalVariableGen[] l = new LocalVariableGen[size];
154 
155     for(int i=0; i < size; i++) {
156       String           ident = idents[i].getName();
157       Variable         entry = (Variable)env.get(ident);
158       Type             t     = BasicType.getType((byte)idents[i].getType());
159       LocalVariableGen lg    = method.addLocalVariable(ident, t, null, null);
160       int              slot  = lg.getIndex();
161 
162       entry.setLocalVariable(lg);
163       InstructionHandle start = il.getEnd();
164       exprs[i].byte_code(il, method, cp);
165       start = (start == null)? il.getStart() : start.getNext();
166       lg.setStart(start);
167       il.append(new ISTORE(slot));     ASTFunDecl.pop();
168       l[i] = lg;
169     }
170 
171     body.byte_code(il, method, cp);
172     InstructionHandle end = il.getEnd();
173     for(int i=0; i < size; i++) {
174         l[i].setEnd(end);
175     }
176   }
177 
178   @Override
dump(String prefix)179   public void dump(String prefix) {
180     System.out.println(toString(prefix));
181 
182     for(int i=0; i < idents.length; i++) {
183       idents[i].dump(prefix + " ");
184       exprs[i].dump(prefix + " ");
185     }
186 
187     body.dump(prefix + " ");
188   }
189 
190 }
191