// Infer the type of the function.
ParseTreeTypeInference inference = new ParseTreeTypeInference();
inference.inferTypes(node, _scope);
FunctionType functionType = (FunctionType) node.getType();
ASTPtRootNode cloneTree = (ASTPtRootNode) node.getExpressionTree(); //.clone();
// ParseTreeSpecializer specializer = new ParseTreeSpecializer();
// cloneTree = specializer.specialize(node.getExpressionTree(),
// node.getArgumentNameList(), _scope);
// Generate a new Function class
SootClass functionClass = new SootClass("Function_"
+ (_functionCount++), Modifier.PUBLIC);
Scene.v().addClass(functionClass);
functionClass.setSuperclass(PtolemyUtilities.objectClass);
functionClass.setApplicationClass();
functionClass.addInterface(PtolemyUtilities.functionInterface);
// Construct the scope, starting with free variables that are
// represented by constructor arguments and stored in fields
// of the closure.
Map nameToLocal = new HashMap();
Map nameToType = new HashMap();
// A list of types corresponding to the Soot type for every
// freeVariable
List argumentSootTypes = new LinkedList();
for (Iterator freeVariables = freeVariableList.iterator(); freeVariables
.hasNext();) {
String freeVariable = (String) freeVariables.next();
ptolemy.data.type.Type type = _scope.getType(freeVariable);
Type sootType = PtolemyUtilities.getSootTypeForTokenType(type);
SootField field = new SootField(freeVariable, sootType,
Modifier.PUBLIC);
functionClass.addField(field);
argumentSootTypes.add(sootType);
nameToLocal.put(freeVariable, field);
nameToType.put(freeVariable, type);
}
// Create the constructor. The constructor takes one argument
// for every free variable of the function closure that is not
// bound to a formal argument.
SootMethod functionConstructor = new SootMethod("<init>",
argumentSootTypes, VoidType.v(), Modifier.PUBLIC);
functionClass.addMethod(functionConstructor);
{
JimpleBody body = Jimple.v().newBody(functionConstructor);
functionConstructor.setActiveBody(body);
body.insertIdentityStmts();
body.getUnits().add(
Jimple.v()
.newInvokeStmt(
Jimple.v().newSpecialInvokeExpr(
body.getThisLocal(),
PtolemyUtilities.objectConstructor
.makeRef(),
Collections.EMPTY_LIST)));
// Read the parameters to the closure constructor.
int i = 0;
for (Iterator freeVariables = freeVariableList.iterator(); freeVariables
.hasNext();) {
String freeVariable = (String) freeVariables.next();
Local local = body.getParameterLocal(i);
SootField field = (SootField) nameToLocal.get(freeVariable);
body.getUnits().add(
Jimple.v().newAssignStmt(
Jimple.v().newInstanceFieldRef(
body.getThisLocal(), field.makeRef()),
local));
i++;
}
body.getUnits().add(Jimple.v().newReturnVoidStmt());
}
// Create the apply method.
{
List argTypes = new LinkedList();
argTypes.add(ArrayType.v(PtolemyUtilities.tokenType, 1));
SootMethod functionApplyMethod = new SootMethod("apply", argTypes,
PtolemyUtilities.tokenType, Modifier.PUBLIC);
functionClass.addMethod(functionApplyMethod);
JimpleBody body = Jimple.v().newBody(functionApplyMethod);
functionApplyMethod.setActiveBody(body);
body.insertIdentityStmts();
Stmt insertPoint = Jimple.v().newNopStmt();
body.getUnits().add(insertPoint);
// Loop over all the arguments and populate the map from
// identifier to local.
List list = node.getArgumentNameList();
Local paramLocal = body.getParameterLocal(0);
int count = 0;
for (Iterator names = list.iterator(); names.hasNext(); count++) {
String name = (String) names.next();
Local argLocal = Jimple.v().newLocal("argument_" + name,
RefType.v(PtolemyUtilities.tokenClass));
body.getLocals().add(argLocal);
body.getUnits().insertBefore(
Jimple.v().newAssignStmt(
argLocal,
Jimple.v().newArrayRef(paramLocal,
IntConstant.v(count))), insertPoint);
nameToLocal.put(name, argLocal);
nameToType.put(name, node.getArgumentTypes()[count]);
}
// FIXME: bound arguments?
DataUtilities.ActorCodeGenerationScope scope = new DataUtilities.ActorCodeGenerationScope(
null, null, nameToLocal, nameToType, body, insertPoint);
ParseTreeCodeGenerator generator = new ParseTreeCodeGenerator();
Local local = generator.generateCode(cloneTree, body, insertPoint,
scope);
body.getUnits().add(Jimple.v().newReturnStmt(local));
}
// Create the getNumberOfArguments method.
{
List argTypes = new LinkedList();
SootMethod getNumberOfArgumentsMethod = new SootMethod(
"getNumberOfArguments", argTypes, IntType.v(),
Modifier.PUBLIC);
functionClass.addMethod(getNumberOfArgumentsMethod);
JimpleBody body = Jimple.v().newBody(getNumberOfArgumentsMethod);
getNumberOfArgumentsMethod.setActiveBody(body);
body.insertIdentityStmts();
body.getUnits().add(
Jimple.v().newReturnStmt(
IntConstant.v(functionType.getArgCount())));
}
// Create the isCongruent method.
{
List argTypes = new LinkedList();
argTypes.add(RefType.v(PtolemyUtilities.functionInterface));