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. ASTFunAppl.java */ 19 /* JJT: 0.3pre1 */ 20 21 package Mini; 22 import org.apache.bcel.generic.ConstantPoolGen; 23 import org.apache.bcel.generic.INVOKESTATIC; 24 import org.apache.bcel.generic.InstructionList; 25 import org.apache.bcel.generic.MethodGen; 26 import org.apache.bcel.generic.Type; 27 28 /** 29 * 30 * @version $Id$ 31 */ 32 public class ASTFunAppl extends ASTExpr implements MiniParserTreeConstants, 33 org.apache.bcel.Constants { 34 private ASTIdent name; 35 private Function function; // Points to Function in environment 36 37 // Generated methods ASTFunAppl(int id)38 ASTFunAppl(int id) { 39 super(id); 40 } 41 ASTFunAppl(MiniParser p, int id)42 ASTFunAppl(MiniParser p, int id) { 43 super(p, id); 44 } 45 jjtCreate(MiniParser p, int id)46 public static Node jjtCreate(MiniParser p, int id) { 47 return new ASTFunAppl(p, id); 48 } 49 ASTFunAppl(ASTIdent name, Function function, ASTExpr[] exprs)50 ASTFunAppl(ASTIdent name, Function function, ASTExpr[] exprs) { 51 this(JJTFUNAPPL); 52 53 this.name = name; 54 this.function = function; 55 this.exprs = exprs; 56 } 57 58 @Override toString()59 public String toString() { 60 return jjtNodeName[id] + " " + name.getName(); 61 } 62 63 /** 64 * Overrides ASTExpr.closeNode() 65 */ 66 @Override closeNode()67 public void closeNode() { 68 name = (ASTIdent)children[0]; 69 70 if(children.length > 1) { 71 exprs = new ASTExpr[children.length - 1]; 72 System.arraycopy(children, 1, exprs, 0, children.length - 1); 73 } 74 75 children=null; // Throw away old reference 76 } 77 78 /** 79 * Overrides ASTExpr.traverse() 80 */ 81 @Override traverse(Environment env)82 public ASTExpr traverse(Environment env) { 83 String fname = name.getName(); 84 EnvEntry entry = env.get(fname); 85 86 this.env = env; 87 88 if(entry == null) { 89 MiniC.addError(name.getLine(), name.getColumn(), 90 "Applying unknown function " + fname + "."); 91 } else { 92 if(!(entry instanceof Function)) { 93 MiniC.addError(name.getLine(), name.getColumn(), 94 "Applying non-function " + fname + "."); 95 } else { 96 int len = (exprs != null)? exprs.length : 0; 97 Function fun = (Function)entry; 98 99 if(len != fun.getNoArgs()) { 100 MiniC.addError(name.getLine(), name.getColumn(), 101 "Function " + fname + " expects " + fun.getNoArgs() + 102 " arguments, you supplied " + len + "."); 103 } else { // Adjust references 104 function = fun; 105 name = fun.getName(); 106 } 107 } 108 } 109 110 if(exprs != null) { 111 for(int i=0; i < exprs.length; i++) { 112 exprs[i] = exprs[i].traverse(env); 113 } 114 } 115 116 return this; 117 } 118 119 /** 120 * Second pass 121 * Overrides AstExpr.eval() 122 * @return type of expression 123 * @param expected type 124 */ 125 @Override eval(int expected)126 public int eval(int expected) { 127 String fname = name.getName(); 128 Function f = function; 129 ASTIdent fun = f.getName(); 130 ASTIdent[] args = f.getArgs(); 131 int t = fun.getType(); 132 133 is_simple = true; // Only true if all arguments are simple expressions 134 135 // Check arguments 136 if(exprs != null) { 137 for(int i=0; i < exprs.length; i++) { // length match checked in previous pass 138 int expect = args[i].getType(); // May be T_UNKNOWN 139 int t_e = exprs[i].eval(expect); // May be T_UNKNOWN 140 141 if((expect != T_UNKNOWN) && (t_e != expect)) { 142 MiniC.addError(exprs[i].getLine(), exprs[i].getColumn(), 143 "Argument " + (i + 1) + " in application of " + fname + 144 " is not of type " + TYPE_NAMES[expect] + " but " + 145 TYPE_NAMES[t_e]); 146 } else { 147 args[i].setType(t_e); // Update, may be identical 148 } 149 150 is_simple = is_simple && exprs[i].isSimple(); // Check condition 151 } 152 } 153 154 if(t == T_UNKNOWN) { 155 fun.setType(t = expected); // May be still T_UNKNOWN 156 } 157 158 return type = t; 159 } 160 161 /** 162 * Fourth pass, produce Java code. 163 */ 164 @Override code(StringBuffer buf)165 public void code(StringBuffer buf) { 166 String fname = name.getName(); 167 // Function f = function; 168 // ASTIdent[] args = f.getArgs(); 169 170 if(fname.equals("READ")) { 171 ASTFunDecl.push(buf, "_readInt()"); 172 } else if(fname.equals("WRITE")) { 173 exprs[0].code(buf); 174 ASTFunDecl.push(buf, "_writeInt(" + ASTFunDecl.pop() + ")"); 175 } 176 else { // Normal function 177 if(exprs != null) { // Output in reverse odrder 178 for(int i = exprs.length - 1; i >= 0; i--) { 179 exprs[i].code(buf); 180 } 181 } 182 183 StringBuffer call = new StringBuffer(fname + "("); 184 // Function call 185 186 if(exprs != null) { 187 for(int i=0; i < exprs.length; i++) { 188 call.append(ASTFunDecl.pop()); 189 if(i < exprs.length - 1) { 190 call.append(", "); 191 } 192 } 193 } 194 call.append(")"); 195 196 ASTFunDecl.push(buf, call.toString()); 197 } 198 } 199 200 /** 201 * Fifth pass, produce Java byte code. 202 */ 203 @Override byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp)204 public void byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp) { 205 String fname = name.getName(); 206 // Function f = function; 207 //ASTIdent fun = f.getName(); 208 // ASTIdent[] args = f.getArgs(); 209 String class_name = method.getClassName(); 210 211 if(fname.equals("READ")) { 212 il.append(new INVOKESTATIC(cp.addMethodref(class_name, 213 "_readInt", 214 "()I"))); 215 } else if(fname.equals("WRITE")) { 216 exprs[0].byte_code(il, method, cp); 217 ASTFunDecl.pop(); 218 il.append(new INVOKESTATIC(cp.addMethodref(class_name, 219 "_writeInt", 220 "(I)I"))); 221 } 222 else { // Normal function 223 int size = exprs.length; 224 Type[] argv = null; 225 226 if(exprs != null) { 227 argv = new Type[size]; 228 229 for(int i=0; i < size; i++) { 230 argv[i] = Type.INT; 231 exprs[i].byte_code(il, method, cp); 232 } 233 234 //ASTFunDecl.push(size); 235 } 236 237 ASTFunDecl.pop(size); 238 239 // Function call 240 il.append(new INVOKESTATIC(cp.addMethodref(class_name, 241 fname, 242 Type.getMethodSignature(Type.INT, 243 argv)))); 244 } 245 246 ASTFunDecl.push(); 247 } 248 249 // dump() inherited getName()250 public ASTIdent getName() { return name; } getFunction()251 public Function getFunction() { return function; } 252 } 253