/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package abs.backend.java.codegeneration;
import java.io.PrintStream;
import java.util.ArrayList;
import abs.backend.java.JavaBackend;
import abs.backend.java.lib.runtime.ABSInitObjectCall;
import abs.backend.java.lib.runtime.ABSObject;
import abs.backend.java.lib.runtime.ABSRunMethodCall;
import abs.backend.java.lib.runtime.ABSRuntime;
import abs.backend.java.lib.runtime.ABSThread;
import abs.backend.java.lib.runtime.COG;
import abs.backend.java.lib.runtime.Task;
import abs.backend.java.lib.types.ABSClass;
import abs.backend.java.lib.types.ABSValue;
import abs.backend.java.scheduling.UserSchedulingStrategy;
import abs.frontend.ast.ClassDecl;
import abs.frontend.ast.FieldDecl;
import abs.frontend.ast.InterfaceTypeUse;
import abs.frontend.ast.MethodImpl;
import abs.frontend.ast.ParamDecl;
import abs.frontend.typechecker.InterfaceType;
public class ClassDeclGenerator {
private final ClassDecl decl;
private final String className;
protected final PrintStream stream;
public ClassDeclGenerator(PrintStream stream, ClassDecl decl) {
this.stream = stream;
this.decl = decl;
className = JavaBackend.getClassName(decl.getName());
}
public void generate() {
JavaGeneratorHelper.generateHelpLine(decl, stream);
generateClassHeader();
generateClassBody();
}
private void generateClassBody() {
stream.println(" {");
generateFieldNamesMethod();
generateFields();
generateConstructor();
generateGetFieldValueMethod();
stream.println("public final java.lang.String getClassName() { return \"" + decl.getName() + "\"; }");
generateCreateNewCOGMethod();
generateNewObjectMethods();
generateMethods();
stream.println("}");
}
private void generateMethods() {
// methods
for (MethodImpl m : decl.getMethods()) {
m.generateJava(stream);
}
}
private void generateNewObjectMethods() {
// Convenience method for new C
stream.print("public static final <T extends " + className + "> T createNewObject");
JavaGeneratorHelper.generateParams(stream, decl.getParams());
stream.print(" { return (T)");
stream.print(className + ".__ABS_createNewObject");
JavaGeneratorHelper.generateParamArgs(stream, "null", decl.getParams());
stream.println("; }");
// static constructor method for new C
stream.print("public static final <T extends " + className + "> T __ABS_createNewObject");
JavaGeneratorHelper.generateParams(stream, ABSObject.class.getName() + " __ABS_source", decl.getParams());
stream.println(" {");
generateObjectConstruction(ABSRuntime.class.getName() + ".getCurrentRuntime()");
stream.println("__ABS_result.__ABS_init();");
if (decl.isActiveClass()) {
stream.println("final " + Task.class.getName() + " __ABS_sendingTask = " + ABSRuntime.class.getName() + ".getCurrentTask();");
stream.println(ABSRuntime.class.getName() + ".getCurrentRuntime().asyncCall(new " + ABSRunMethodCall.class.getName() + "(__ABS_sendingTask,__ABS_source,__ABS_result));");
}
stream.println("return (T)__ABS_result;");
stream.println("}");
}
private void generateCreateNewCOGMethod() {
// Convenience method for new cog C
stream.print("public static final <T extends " + className + "> T createNewCOG");
JavaGeneratorHelper.generateParams(stream, decl.getParams());
stream.print(" { ");
stream.print("return (T)");
stream.print(className + ".__ABS_createNewCOG");
// FIXME: does createNewCog() need the DC argument? Who calls this
// method?
JavaGeneratorHelper.generateParamArgs(stream, "null, null, null", decl.getParams());
stream.println("; }");
// static constructor method for new cog C
stream.print("public static final <T extends " + className + "> T __ABS_createNewCOG");
JavaGeneratorHelper.generateParams(stream,
ABSObject.class.getName() + " __ABS_source, "
+ UserSchedulingStrategy.class.getName() + " Strategy, "
+ "ABS.DC.DeploymentComponent_i DC",
decl.getParams());
stream.println(" {");
stream.println("final " + ABSRuntime.class.getName() + " __ABS_runtime = " + ABSRuntime.class.getName() + ".getCurrentRuntime();");
stream.println("final " + COG.class.getName() + " __ABS_cog = Strategy == null ? __ABS_runtime.createCOG(" + className + ".class, DC) : __ABS_runtime.createCOG(" + className + ".class, DC, Strategy);");
stream.println("final " + ABSThread.class.getName() + " __ABS_thread = " + ABSRuntime.class.getName() + ".getCurrentThread();");
stream.println("final " + COG.class.getName() + " __ABS_oldCOG = " + ABSRuntime.class.getName() + ".getCurrentCOG();");
stream.println("final " + Task.class.getName() + " __ABS_sendingTask = " + ABSRuntime.class.getName() + ".getCurrentTask();");
stream.println("__ABS_thread.setCOG(__ABS_cog);");
stream.println("try {");
generateObjectConstruction("__ABS_runtime");
stream.println(";");
stream.println("__ABS_runtime.cogCreated(__ABS_result);");
stream.println("__ABS_cog.getScheduler().addTask(new " + Task.class.getName() + "(new " +
ABSInitObjectCall.class.getName() + "(__ABS_sendingTask,__ABS_source,__ABS_result)));");
if (decl.isActiveClass()) {
stream.println("__ABS_runtime.asyncCall(new " + ABSRunMethodCall.class.getName() + "(__ABS_sendingTask,__ABS_source,__ABS_result));");
}
stream.println("return (T)__ABS_result;");
stream.println("} finally {");
stream.println("__ABS_thread.setCOG(__ABS_oldCOG);");
stream.println("}");
stream.println("}");
}
private void generateObjectConstruction(String runtime) {
stream.print(className + " __ABS_result = ");
if (decl.isForeign()) {
stream.println("(" + className + ") " + runtime + ".getForeignObject");
JavaGeneratorHelper.generateParamArgs(stream,"\"" + decl.getModuleDecl().getName() + "." + decl.getName() + "\"", decl.getParams());
stream.println(";");
stream.print("if (__ABS_result == null) __ABS_result = ");
}
stream.print("new " + className);
JavaGeneratorHelper.generateParamArgs(stream,decl.getParams());
stream.println(";");
}
private void generateGetFieldValueMethod() {
stream.println("protected final " + ABSValue.class.getName() + " getFieldValue(java.lang.String __ABS_fieldName) throws java.lang.NoSuchFieldException {");
for (ParamDecl p : decl.getParams()) {
stream.println("if (\"" + p.getName() + "\".equals(__ABS_fieldName)) return " + JavaBackend.getVariableName(p.getName()) + ";");
}
for (FieldDecl f : decl.getFields()) {
stream.println("if (\"" + f.getName() + "\".equals(__ABS_fieldName)) return " + JavaBackend.getVariableName(f.getName()) + ";");
}
stream.println("return super.getFieldValue(__ABS_fieldName);");
stream.println("}");
}
private void generateConstructor() {
// constructor
stream.print("public " + className);
JavaGeneratorHelper.generateParams(stream, decl.getParams());
stream.println(" {");
for (ParamDecl p : decl.getParams()) {
stream.println("this." + JavaBackend.getVariableName(p.getName()) + " = " + JavaBackend.getVariableName(p.getName()) + ";");
}
stream.println("getCOG().objectCreated(this);");
stream.println("}");
stream.println("protected final void __ABS_init() {");
for (FieldDecl f : decl.getFields()) {
if (f.hasInitExp()) {
stream.print("this.");
stream.print(JavaBackend.getVariableName(f.getName()));
stream.print(" = ");
f.getInitExp().generateJava(stream);
stream.print(";");
}
}
if (decl.hasInitBlock()) {
decl.getInitBlock().generateJava(stream);
}
stream.println("getCOG().objectInitialized(this);");
stream.println("}");
}
private void generateFields() {
for (ParamDecl p : decl.getParams()) {
stream.print("private ");
p.generateJava(stream);
stream.println(";");
}
for (FieldDecl f : decl.getFields()) {
f.generateJava(stream);
}
}
private void generateFieldNamesMethod() {
java.util.List<String> fieldNames = getFieldNames();
stream.print("private static final java.lang.String[] __fieldNames = new java.lang.String[] { ");
boolean first = true;
for (String fieldName : fieldNames) {
if (first) first = false;
else stream.print(", ");
stream.print("\"" + fieldName + "\"");
}
stream.println(" };");
stream.println("public final java.util.List<java.lang.String> getFieldNames() { return java.util.Arrays.asList(__fieldNames); }");
}
private java.util.List<String> getFieldNames() {
java.util.List<String> fieldNames = new ArrayList<String>();
for (ParamDecl p : decl.getParams()) {
fieldNames.add(p.getName());
}
for (FieldDecl f : decl.getFields()) {
fieldNames.add(f.getName());
}
return fieldNames;
}
private void generateClassHeader() {
stream.print("public ");
if (!decl.isForeign())
stream.print("final ");
stream.print("class " + className + " extends " + ABSObject.class.getName() + " implements " + ABSClass.class.getName());
for (InterfaceTypeUse use : decl.getImplementedInterfaceUses()) {
String iname = JavaBackend.getQualifiedString(((InterfaceType)use.getType()).getDecl());
stream.print(", " + iname);
}
}
}