package org.overture.codegen.vdm2jml;
import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.lex.Dialect;
import org.overture.ast.modules.AModuleModules;
import org.overture.codegen.printer.MsgPrinter;
import org.overture.codegen.utils.GeneralCodeGenUtils;
import org.overture.codegen.utils.GeneralUtils;
import org.overture.codegen.utils.GeneratedData;
import org.overture.codegen.vdm2java.JavaCodeGenMain;
import org.overture.codegen.vdm2java.JavaCodeGenUtil;
import org.overture.config.Release;
import org.overture.config.Settings;
import org.overture.typechecker.util.TypeCheckerUtil;
import org.overture.typechecker.util.TypeCheckerUtil.TypeCheckResult;
public class JmlGenMain
{
public static final String OUTPUT_ARG = "-output";
public static final String PRINT_ARG = "-print";
public static final String FOLDER_ARG = "-folder";
public static final String INVARIANT_FOR = "-invariant_for";
public static final String NO_TRACE = "-notrace";
public static final String NO_CLONING = "-nocloning";
public static final String PACKAGE_ARG = "-package";
public static void main(String[] args)
{
if (args == null || args.length < 1)
{
usage("Expected one or more arguments");
return;
}
Settings.release = Release.VDM_10;
Settings.dialect = Dialect.VDM_SL;
List<String> listArgs = Arrays.asList(args);
List<File> files = new LinkedList<File>();
File outputDir = null;
boolean print = false;
JmlGenerator jmlGen = new JmlGenerator();
jmlGen.getIrSettings().setCharSeqAsString(true);
for (Iterator<String> i = listArgs.iterator(); i.hasNext();)
{
String arg = i.next();
if (arg.equals(OUTPUT_ARG))
{
if (i.hasNext())
{
outputDir = new File(i.next());
outputDir.mkdirs();
if (!outputDir.isDirectory())
{
usage(outputDir + " is not a directory");
}
} else
{
usage(OUTPUT_ARG + " requires a directory");
}
} else if (arg.equals(PRINT_ARG))
{
print = true;
} else if (arg.equals(PACKAGE_ARG))
{
if (i.hasNext())
{
String javaPackage = i.next();
if (JavaCodeGenUtil.isValidJavaPackage(javaPackage))
{
jmlGen.getJavaSettings().setJavaRootPackage(javaPackage);
} else
{
MsgPrinter.getPrinter().errorln("Not a valid java package. Using the default java package instead..\n");
}
}
} else if (arg.equals(FOLDER_ARG))
{
if (i.hasNext())
{
File path = new File(i.next());
if (path.isDirectory())
{
files.addAll(JavaCodeGenMain.filterFiles(GeneralUtils.getFiles(path)));
} else
{
usage("Could not find path: " + path);
}
} else
{
usage(FOLDER_ARG + " requires a directory");
}
} else if (arg.equals(INVARIANT_FOR))
{
jmlGen.getJmlSettings().setGenInvariantFor(true);
} else if (arg.equals(NO_TRACE))
{
jmlGen.getIrSettings().setGenerateTraces(false);
jmlGen.getJavaSettings().setMakeClassesSerializable(false);
} else if (arg.equals(NO_CLONING))
{
jmlGen.getJavaSettings().setDisableCloning(true);
} else
{
// It's a file or a directory
File file = new File(arg);
if (file.isFile())
{
if (GeneralCodeGenUtils.isVdmSourceFile(file))
{
files.add(file);
}
} else
{
usage("Not a file: " + file);
}
}
}
try
{
MsgPrinter.getPrinter().println("Starting the VDM to JML generator...");
TypeCheckResult<List<AModuleModules>> tcResult = TypeCheckerUtil.typeCheckSl(files);
if (!GeneralCodeGenUtils.hasErrors(tcResult))
{
GeneratedData data = jmlGen.generateJml(tcResult.result);
JavaCodeGenMain.processData(print, outputDir, jmlGen.getJavaGen(), data, false);
} else
{
MsgPrinter.getPrinter().errorln("Could not parse/type check VDM model:\n"
+ GeneralCodeGenUtils.errorStr(tcResult));
}
} catch (AnalysisException e)
{
MsgPrinter.getPrinter().println("Could not code generate model: "
+ e.getMessage());
}
}
private static void usage(String msg)
{
MsgPrinter.getPrinter().errorln("VDMSL to JML/Java generator: " + msg
+ "\n");
MsgPrinter.getPrinter().errorln("Usage: vdm2jml [<options>] [<VDM SL files>]");
MsgPrinter.getPrinter().errorln(PRINT_ARG
+ ": print the generated code to the console");
MsgPrinter.getPrinter().errorln(OUTPUT_ARG
+ " <folder path>: the output folder of the generated code");
MsgPrinter.getPrinter().errorln(FOLDER_ARG
+ " <folder path>: a folder containing input .vdmsl files");
MsgPrinter.getPrinter().errorln(INVARIANT_FOR
+ ": to check record invariants explicitly using JML's invariant_for");
MsgPrinter.getPrinter().errorln(NO_CLONING
+ ": To disable deep cloning of value types");
System.exit(1);
}
}