| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| /* Generated By:JJTree: Do not edit this line. ASTFunAppl.java */ |
| /* JJT: 0.3pre1 */ |
| |
| package Mini; |
| import org.apache.bcel.generic.ConstantPoolGen; |
| import org.apache.bcel.generic.INVOKESTATIC; |
| import org.apache.bcel.generic.InstructionList; |
| import org.apache.bcel.generic.MethodGen; |
| import org.apache.bcel.generic.Type; |
| |
| /** |
| * |
| * @version $Id$ |
| */ |
| public class ASTFunAppl extends ASTExpr implements MiniParserTreeConstants, |
| org.apache.bcel.Constants { |
| private ASTIdent name; |
| private Function function; // Points to Function in environment |
| |
| // Generated methods |
| ASTFunAppl(int id) { |
| super(id); |
| } |
| |
| ASTFunAppl(MiniParser p, int id) { |
| super(p, id); |
| } |
| |
| public static Node jjtCreate(MiniParser p, int id) { |
| return new ASTFunAppl(p, id); |
| } |
| |
| ASTFunAppl(ASTIdent name, Function function, ASTExpr[] exprs) { |
| this(JJTFUNAPPL); |
| |
| this.name = name; |
| this.function = function; |
| this.exprs = exprs; |
| } |
| |
| @Override |
| public String toString() { |
| return jjtNodeName[id] + " " + name.getName(); |
| } |
| |
| /** |
| * Overrides ASTExpr.closeNode() |
| */ |
| @Override |
| public void closeNode() { |
| name = (ASTIdent)children[0]; |
| |
| if(children.length > 1) { |
| exprs = new ASTExpr[children.length - 1]; |
| System.arraycopy(children, 1, exprs, 0, children.length - 1); |
| } |
| |
| children=null; // Throw away old reference |
| } |
| |
| /** |
| * Overrides ASTExpr.traverse() |
| */ |
| @Override |
| public ASTExpr traverse(Environment env) { |
| String fname = name.getName(); |
| EnvEntry entry = env.get(fname); |
| |
| this.env = env; |
| |
| if(entry == null) { |
| MiniC.addError(name.getLine(), name.getColumn(), |
| "Applying unknown function " + fname + "."); |
| } else { |
| if(!(entry instanceof Function)) { |
| MiniC.addError(name.getLine(), name.getColumn(), |
| "Applying non-function " + fname + "."); |
| } else { |
| int len = (exprs != null)? exprs.length : 0; |
| Function fun = (Function)entry; |
| |
| if(len != fun.getNoArgs()) { |
| MiniC.addError(name.getLine(), name.getColumn(), |
| "Function " + fname + " expects " + fun.getNoArgs() + |
| " arguments, you supplied " + len + "."); |
| } else { // Adjust references |
| function = fun; |
| name = fun.getName(); |
| } |
| } |
| } |
| |
| if(exprs != null) { |
| for(int i=0; i < exprs.length; i++) { |
| exprs[i] = exprs[i].traverse(env); |
| } |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Second pass |
| * Overrides AstExpr.eval() |
| * @return type of expression |
| * @param expected type |
| */ |
| @Override |
| public int eval(int expected) { |
| String fname = name.getName(); |
| Function f = function; |
| ASTIdent fun = f.getName(); |
| ASTIdent[] args = f.getArgs(); |
| int t = fun.getType(); |
| |
| is_simple = true; // Only true if all arguments are simple expressions |
| |
| // Check arguments |
| if(exprs != null) { |
| for(int i=0; i < exprs.length; i++) { // length match checked in previous pass |
| int expect = args[i].getType(); // May be T_UNKNOWN |
| int t_e = exprs[i].eval(expect); // May be T_UNKNOWN |
| |
| if((expect != T_UNKNOWN) && (t_e != expect)) { |
| MiniC.addError(exprs[i].getLine(), exprs[i].getColumn(), |
| "Argument " + (i + 1) + " in application of " + fname + |
| " is not of type " + TYPE_NAMES[expect] + " but " + |
| TYPE_NAMES[t_e]); |
| } else { |
| args[i].setType(t_e); // Update, may be identical |
| } |
| |
| is_simple = is_simple && exprs[i].isSimple(); // Check condition |
| } |
| } |
| |
| if(t == T_UNKNOWN) { |
| fun.setType(t = expected); // May be still T_UNKNOWN |
| } |
| |
| return type = t; |
| } |
| |
| /** |
| * Fourth pass, produce Java code. |
| */ |
| @Override |
| public void code(StringBuffer buf) { |
| String fname = name.getName(); |
| // Function f = function; |
| // ASTIdent[] args = f.getArgs(); |
| |
| if(fname.equals("READ")) { |
| ASTFunDecl.push(buf, "_readInt()"); |
| } else if(fname.equals("WRITE")) { |
| exprs[0].code(buf); |
| ASTFunDecl.push(buf, "_writeInt(" + ASTFunDecl.pop() + ")"); |
| } |
| else { // Normal function |
| if(exprs != null) { // Output in reverse odrder |
| for(int i = exprs.length - 1; i >= 0; i--) { |
| exprs[i].code(buf); |
| } |
| } |
| |
| StringBuffer call = new StringBuffer(fname + "("); |
| // Function call |
| |
| if(exprs != null) { |
| for(int i=0; i < exprs.length; i++) { |
| call.append(ASTFunDecl.pop()); |
| if(i < exprs.length - 1) { |
| call.append(", "); |
| } |
| } |
| } |
| call.append(")"); |
| |
| ASTFunDecl.push(buf, call.toString()); |
| } |
| } |
| |
| /** |
| * Fifth pass, produce Java byte code. |
| */ |
| @Override |
| public void byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp) { |
| String fname = name.getName(); |
| // Function f = function; |
| //ASTIdent fun = f.getName(); |
| // ASTIdent[] args = f.getArgs(); |
| String class_name = method.getClassName(); |
| |
| if(fname.equals("READ")) { |
| il.append(new INVOKESTATIC(cp.addMethodref(class_name, |
| "_readInt", |
| "()I"))); |
| } else if(fname.equals("WRITE")) { |
| exprs[0].byte_code(il, method, cp); |
| ASTFunDecl.pop(); |
| il.append(new INVOKESTATIC(cp.addMethodref(class_name, |
| "_writeInt", |
| "(I)I"))); |
| } |
| else { // Normal function |
| int size = exprs.length; |
| Type[] argv = null; |
| |
| if(exprs != null) { |
| argv = new Type[size]; |
| |
| for(int i=0; i < size; i++) { |
| argv[i] = Type.INT; |
| exprs[i].byte_code(il, method, cp); |
| } |
| |
| //ASTFunDecl.push(size); |
| } |
| |
| ASTFunDecl.pop(size); |
| |
| // Function call |
| il.append(new INVOKESTATIC(cp.addMethodref(class_name, |
| fname, |
| Type.getMethodSignature(Type.INT, |
| argv)))); |
| } |
| |
| ASTFunDecl.push(); |
| } |
| |
| // dump() inherited |
| public ASTIdent getName() { return name; } |
| public Function getFunction() { return function; } |
| } |