blob: eadb1cb4a2c79b6435893ff9d3207fd3dbc8f931 [file] [log] [blame]
/*
* 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; }
}