*/
private static JavaClassRep makeMainClass(final JavaTypeName mainClassName, final QualifiedName entryPointName, final ProgramModelManager programModelManager) {
final LECCModule module = (LECCModule)programModelManager.getModule(entryPointName.getModuleName());
final JavaClassRep classRep = new JavaClassRep(mainClassName, JavaTypeName.OBJECT, Modifier.PUBLIC|Modifier.FINAL, new JavaTypeName[0]);
// Code fragment:
//
// private {MainClassConstructorName} {}
//
classRep.addConstructor(makePrivateConstructor(mainClassName));
// Code fragment:
//
// public static void main(final String[] args) throws CALExecutorException
//
final JavaMethod mainMethod = new JavaMethod(Modifier.PUBLIC|Modifier.STATIC, JavaTypeName.VOID, ARGS_PARAMETER_NAME, JavaTypeName.STRING_ARRAY, true, "main");
mainMethod.addThrows(JavaTypeName.CAL_EXECUTOR_EXCEPTION);
////
/// The classes in the standalone JAR are generated with the machine configuration at "build time".
/// We capture this configuration into a StandaloneJarGeneratedCodeInfo, to be checked at runtime
/// against the machine configuration then.
//
final JavaStatement.LocalVariableDeclaration generatedCodeInfoDecl = makeGeneratedCodeInfoDecl();
final JavaExpression.LocalVariable generatedCodeInfoLocalVar = generatedCodeInfoDecl.getLocalVariable();
mainMethod.addStatement(generatedCodeInfoDecl);
//
// Code fragment:
//
// if (!generatedCodeInfo.isCompatibleWithCurrentConfiguration()) {
// System.err.println(generatedCodeInfo.getConfigurationHints());
// return;
// }
//
final JavaStatement.Block configCheckFailureBody = new JavaStatement.Block();
configCheckFailureBody.addStatement(
new JavaStatement.ExpressionStatement(
new JavaExpression.MethodInvocation.Instance(
new JavaExpression.JavaField.Static(JavaTypeName.SYSTEM, "err", JavaTypeName.PRINT_STREAM),
"println",
new JavaExpression.MethodInvocation.Instance(
generatedCodeInfoLocalVar,
"getConfigurationHints",
JavaTypeName.STRING,
JavaExpression.MethodInvocation.InvocationType.VIRTUAL),
JavaTypeName.STRING,
JavaTypeName.VOID,
JavaExpression.MethodInvocation.InvocationType.VIRTUAL)));
configCheckFailureBody.addStatement(new JavaStatement.ReturnStatement());
final JavaStatement configCheck =
new JavaStatement.IfThenElseStatement(
new JavaExpression.OperatorExpression.Unary(
JavaOperator.LOGICAL_NEGATE,
new JavaExpression.MethodInvocation.Instance(
generatedCodeInfoLocalVar,
"isCompatibleWithCurrentConfiguration",
JavaTypeName.BOOLEAN,
JavaExpression.MethodInvocation.InvocationType.VIRTUAL)),
configCheckFailureBody);
mainMethod.addStatement(configCheck);
////
/// Generate code to obtain the class loader which loaded this main class.
///
/// It is necessary to obtain this class loader and pass it into the execution context and the resource access
/// because the class loader which loaded the CAL Platform classes may be an *ancestor* of the one which loaded
/// the standalone JAR (e.g. the bootstrap class loader), and thus may not have access to the foreign classes
/// and localized resources necessary for the standalone JAR to run.
//
// Code fragment:
//
// ClassLoader classloader = {MainClassName}.class.getClassLoader();
//
final JavaTypeName javaTypeName_ClassLoader = JavaTypeName.make(ClassLoader.class);
final JavaExpression classloaderInit =
new JavaExpression.MethodInvocation.Instance(
new JavaExpression.ClassLiteral(mainClassName),
"getClassLoader",
javaTypeName_ClassLoader,
JavaExpression.MethodInvocation.InvocationType.VIRTUAL);
final JavaExpression.LocalVariable classloaderLocalVar = new JavaExpression.LocalVariable("classloader", javaTypeName_ClassLoader);
final JavaStatement classloaderDecl = new JavaStatement.LocalVariableDeclaration(classloaderLocalVar, classloaderInit);
mainMethod.addStatement(classloaderDecl);
////
/// Generate code to set up the execution context to have access to a standalone-JAR-specific
/// ResourceAccess implementation.
//
// Code fragment:
//
// RTExecutionContext executionContext = new RTExecutionContext(
// new ExecutionContextProperties.Builder().toProperties(),
// new StandaloneRuntimeEnvironment(
// classloader,
// new StandaloneJarResourceAccess(classloader)));
//
final JavaTypeName javaTypeName_ExecutionContextProperties = JavaTypeName.make(ExecutionContextProperties.class);
final JavaTypeName javaTypeName_ResourceAccess = JavaTypeName.make(ResourceAccess.class);
final JavaExpression newRuntimeEnvironment =
new JavaExpression.ClassInstanceCreationExpression(
JavaTypeNames.STANDALONE_RUNTIME_ENVIRONMENT,
new JavaExpression[] {
classloaderLocalVar,
new JavaExpression.ClassInstanceCreationExpression(
JavaTypeName.make(StandaloneJarResourceAccess.class),
classloaderLocalVar,
javaTypeName_ClassLoader)},
new JavaTypeName[] {
javaTypeName_ClassLoader,
javaTypeName_ResourceAccess}
);
final JavaExpression executionContextInit =
new JavaExpression.ClassInstanceCreationExpression(
JavaTypeNames.RTEXECUTION_CONTEXT,
new JavaExpression[] {
new JavaExpression.MethodInvocation.Instance(
new JavaExpression.ClassInstanceCreationExpression(JavaTypeName.make(ExecutionContextProperties.Builder.class)),
"toProperties",
javaTypeName_ExecutionContextProperties,
JavaExpression.MethodInvocation.InvocationType.VIRTUAL),
newRuntimeEnvironment
},
new JavaTypeName[] {
javaTypeName_ExecutionContextProperties,
JavaTypeNames.RUNTIME_ENIVONMENT
});
final JavaExpression.LocalVariable executionContextLocalVar = new JavaExpression.LocalVariable(EXECUTION_CONTEXT_USER_FRIENDLY_NAME, JavaTypeNames.RTEXECUTION_CONTEXT);
final JavaStatement executionContextDecl = new JavaStatement.LocalVariableDeclaration(executionContextLocalVar, executionContextInit, true);
mainMethod.addStatement(executionContextDecl);
////
/// Generate code to run the entry point.
//
// Code fragment:
//
// {EntryPointClass's instance}
// .apply(Input_String_List.$instance.apply(new RTData.CAL_Opaque(args))
// .evaluate(executionContext);
//
final MachineFunction entryPointMachineFunction = module.getFunction(entryPointName);
final MachineFunction inputStringListMachineFunction = module.getFunction(CAL_Prelude_internal.Functions.inputStringList);
final JavaExpression runExpr =
makeEvaluateInvocationExpr(
makeApplyInvocationExpr(
getInstanceOfGeneratedClassJavaExpression(entryPointMachineFunction, module, executionContextLocalVar),
makeApplyInvocationExpr(
getInstanceOfGeneratedClassJavaExpression(inputStringListMachineFunction, module, executionContextLocalVar),
new JavaExpression.ClassInstanceCreationExpression(
JavaTypeNames.RTDATA_OPAQUE, new JavaExpression.MethodVariable(ARGS_PARAMETER_NAME), JavaTypeName.OBJECT))), executionContextLocalVar);
mainMethod.addStatement(new JavaStatement.ExpressionStatement(runExpr));
classRep.addMethod(mainMethod);
// We are finished with building the class.
return classRep;
}