/**
* Copyright (C) 2015 the original author or authors.
*
* Licensed 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.
*/
package mujava.openjava.extension;
import openjava.mop.Environment;
import openjava.mop.OJClass;
import openjava.mop.OJClassNotFoundException;
import openjava.mop.Toolbox;
import openjava.ptree.EnumConstant;
import openjava.ptree.ForStatement;
import openjava.ptree.MemberDeclaration;
import openjava.ptree.Parameter;
import openjava.ptree.ParseTreeException;
import openjava.ptree.Statement;
import openjava.ptree.TypeName;
import openjava.ptree.TypeParameter;
import openjava.ptree.TypeParameterList;
import openjava.ptree.VariableDeclaration;
import openjava.ptree.VariableDeclarator;
import openjava.tools.DebugOut;
import openjava.ptree.MethodDeclaration;;
/**
* The class <code>VariableBinder</code>
* <p>
* For example
* <pre>
* </pre>
* <p>
*
* @author Michiaki Tatsubori
* @version 1.0
* @since $Id: VariableBinder.java,v 1.2 2003/02/19 02:55:00 tatsubori Exp $
* @see java.lang.Object
*
* @update by Nan Li on 09/29/2012
* evaluateDown(typeParameter) and record(Environment, String type, String name) are added
* if a method has type parameters in which identifiers extends from some types, the identifiers and the corresponding types need to be recorded in the closedEnvironment of this method.
* e.g. <T extends Comparable<T>> is a type parameter, T and its type Comparable should be recorded such that T could be recognized as a variable of Comparable in this method
*/
public class VariableBinder extends ScopeHandler {
public VariableBinder(Environment env) {
super(env);
}
public Statement evaluateDown(VariableDeclaration ptree)
throws ParseTreeException {
super.evaluateDown(ptree);
bindLocalVariable(ptree, getEnvironment());
return ptree;
}
public Statement evaluateDown(ForStatement ptree)
throws ParseTreeException {
super.evaluateDown(ptree);
TypeName tspec = ptree.getInitDeclType();
if (tspec == null)
return ptree;
VariableDeclarator[] vdecls = ptree.getInitDecls();
if(vdecls != null)
bindForInit(tspec, vdecls, getEnvironment());
else{
String identifier = ptree.getIdentifier();
bindName(getEnvironment(), Toolbox.nameToJavaClassName(tspec.toString()), identifier);
}
return ptree;
}
/*
public MemberDeclaration evaluateDown(MethodDeclaration ptree)
throws ParseTreeException {
System.out.println("VariableBinder: down" + ptree.getName()+ "; " + ptree.getGenericsTypeParameters() + ptree.getReturnType());
return ptree;
}
public MemberDeclaration evaluateUp(MethodDeclaration ptree)
throws ParseTreeException {
System.out.println("VariableBinder: up" + ptree.getName()+ "; " + ptree.getGenericsTypeParameters() + ptree.getReturnType());
return ptree;
}
*/
public Parameter evaluateDown(Parameter ptree) throws ParseTreeException {
super.evaluateDown(ptree);
bindParameter(ptree, getEnvironment());
return ptree;
}
public TypeParameter evaluateDown(TypeParameter ptree) throws ParseTreeException {
super.evaluateDown(ptree);
String identifier = ptree.getName();
if(ptree.getTypeBound() != ""){
String[] types = ptree.getTypeBound().split("&");
//System.out.println("identifier: " + identifier);
//System.out.println("type: " + type);
for(String type: types)
record(env, type, identifier);
}
else{
OJClass OBJECT = OJClass.forClass(Object.class);
//env.record(identifier, OBJECT);
getEnvironment().recordGenerics(identifier, OBJECT);
//System.out.println("env: " + env.toString());
}
return ptree;
}
/*
public TypeParameterList evaluateDown(TypeParameterList ptree) throws ParseTreeException {
super.evaluateDown(ptree);
System.out.println("VariableBinder: TypeParameterList: down " + ptree.toString());
return ptree;
}*/
private static void bindLocalVariable(
VariableDeclaration var_decl,
Environment env) {
String type = var_decl.getTypeSpecifier().toString();
String name = var_decl.getVariable();
bindName(env, type, name);
}
private static void bindForInit(
TypeName tspec,
VariableDeclarator[] vdecls,
Environment env) {
//If the for statement is a enhanced one, variable declarator will be null
//so the statements below will only be executed for the traditional for statements
if(vdecls != null){
for (int i = 0; i < vdecls.length; ++i) {
String type = tspec.toString() + vdecls[i].dimensionString();
String name = vdecls[i].getVariable();
bindName(env, type, name);
}
}
}
private static void bindParameter(Parameter param, Environment env) {
String type = "";
String name = param.getVariable();
if(param.isVarargs() == false){
type = param.getTypeSpecifier().toString();
}
else{
type = param.getTypeSpecifier().toString() + "[]";
}
//System.out.println("VariableBinder: Parameter " + type + " " + name);
bindName(env, type, name);
}
private static void record(Environment env, String type, String name) {
String qtypename = env.toQualifiedName(type);
//System.out.println("qtypename: " + type);
try {
OJClass clazz = env.lookupClass(qtypename);
if (clazz == null)
clazz = OJClass.forName(qtypename);
//System.out.println("OJClass: " + name + " " + clazz);
env.record(name, clazz);
//System.out.println("env: " + env.toString());
DebugOut.println("record\t" + name + "\t: " + qtypename);
} catch (OJClassNotFoundException e) {
System.err.println(
"VariableBinder.record() "
+ e.toString()
+ " : "
+ qtypename);
System.err.println(env);
}
}
private static void bindName(Environment env, String type, String name) {
String qtypename = env.toQualifiedName(type);
//System.out.println("qtypename: " + type);
try {
OJClass clazz = env.lookupClass(qtypename);
if (clazz == null)
clazz = OJClass.forName(qtypename);
//System.out.println("OJClass: " + name + " " + clazz);
env.bindVariable(name, clazz);
//System.out.println("env: " + env.toString());
DebugOut.println("binds variable\t" + name + "\t: " + qtypename);
} catch (OJClassNotFoundException e) {
System.err.println(
"VariableBinder.bindName() "
+ e.toString()
+ " : "
+ qtypename);
System.err.println(env);
}
}
}