/*
* #%~
* VDM Code Generator
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.codegen.vdm2cpp;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.definitions.AClassClassDefinition;
import org.overture.ast.definitions.SClassDefinition;
import org.overture.ast.expressions.PExp;
import org.overture.ast.intf.lex.ILexLocation;
import org.overture.ast.lex.Dialect;
import org.overture.codegen.analysis.violations.InvalidNamesResult;
import org.overture.codegen.analysis.violations.UnsupportedModelingException;
import org.overture.codegen.analysis.violations.Violation;
import org.overture.codegen.assistant.AssistantManager;
import org.overture.codegen.assistant.LocationAssistantCG;
import org.overture.codegen.ir.IRSettings;
import org.overture.codegen.ir.VdmNodeInfo;
import org.overture.codegen.logging.Logger;
import org.overture.codegen.utils.GeneralCodeGenUtils;
import org.overture.codegen.utils.Generated;
import org.overture.codegen.utils.GeneratedData;
import org.overture.codegen.utils.GeneratedModule;
import org.overture.interpreter.VDMPP;
import org.overture.interpreter.VDMRT;
import org.overture.interpreter.util.ClassListInterpreter;
import org.overture.interpreter.util.ExitStatus;
import org.overture.typechecker.util.TypeCheckerUtil.TypeCheckResult;
public class CppCodeGenUtil
{
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private static boolean generate_timing;
public static GeneratedData generateCppFromFiles(List<File> files,
IRSettings irSettings, CppSettings javaSettings, Dialect dialect, String gen_type,boolean timing)
throws AnalysisException, UnsupportedModelingException
{
generate_timing = timing;
List<SClassDefinition> mergedParseList = consMergedParseList(files, dialect);
CppCodeGen vdmCodGen = new CppCodeGen(gen_type,generate_timing);
vdmCodGen.setSettings(irSettings);
//vdmCodGen.setJavaSettings(javaSettings);
return generateCppFromVdm(mergedParseList, vdmCodGen);
}
public static List<SClassDefinition> consMergedParseList(List<File> files, Dialect dialect)
throws AnalysisException
{
VDMPP vdmrt = (dialect == Dialect.VDM_RT ? new VDMRT() : new VDMPP());
vdmrt.setQuiet(true);
ExitStatus status = vdmrt.parse(files);
if (status != ExitStatus.EXIT_OK)
{
throw new AnalysisException("Could not parse files!");
}
status = vdmrt.typeCheck();
if (status != ExitStatus.EXIT_OK)
{
throw new AnalysisException("Could not type check files!");
}
ClassListInterpreter classes;
try
{
classes = vdmrt.getInterpreter().getClasses();
} catch (Exception e)
{
throw new AnalysisException("Could not get classes from class list interpreter!");
}
List<SClassDefinition> mergedParseList = new LinkedList<SClassDefinition>();
for (SClassDefinition vdmClass : classes)
{
if (vdmClass instanceof AClassClassDefinition) {
mergedParseList.add(vdmClass);
}
}
return mergedParseList;
}
private static GeneratedData generateCppFromVdm(
List<SClassDefinition> mergedParseLists, CppCodeGen vdmCodGen)
throws AnalysisException, UnsupportedModelingException
{
return vdmCodGen.generateCppFromVdm(mergedParseLists);
}
public static Generated generateCppFromExp(String exp,
IRSettings irSettings, CppSettings javaSettings)
throws AnalysisException
{
TypeCheckResult<PExp> typeCheckResult = GeneralCodeGenUtils.validateExp(exp);
if (typeCheckResult.errors.size() > 0)
{
throw new AnalysisException("Unable to type check expression: "
+ exp);
}
CppCodeGen vdmCodGen = new CppCodeGen("",false);
vdmCodGen.setSettings(irSettings);
//vdmCodGen.setJavaSettings(javaSettings);
try
{
return vdmCodGen.generateCppFromVdmExp(typeCheckResult.result);
} catch (AnalysisException e)
{
throw new AnalysisException("Unable to generate code from expression: "
+ exp + ". Exception message: " + e.getMessage());
}
}
public static List<Violation> asSortedList(Set<Violation> violations)
{
LinkedList<Violation> list = new LinkedList<Violation>(violations);
Collections.sort(list);
return list;
}
public static String constructNameViolationsString(
InvalidNamesResult invalidNames)
{
StringBuffer buffer = new StringBuffer();
List<Violation> reservedWordViolations = asSortedList(invalidNames.getReservedWordViolations());
List<Violation> typenameViolations = asSortedList(invalidNames.getTypenameViolations());
List<Violation> tempVarViolations = asSortedList(invalidNames.getTempVarViolations());
String correctionMessage = String.format("Prefix '%s' has been added to the name"
+ LINE_SEPARATOR, invalidNames.getCorrectionPrefix());
for (Violation violation : reservedWordViolations)
{
buffer.append("Reserved name violation: " + violation + ". "
+ correctionMessage);
}
for (Violation violation : typenameViolations)
{
buffer.append("Type name violation: " + violation + ". "
+ correctionMessage);
}
for (Violation violation : tempVarViolations)
{
buffer.append("Temporary variable violation: " + violation + ". "
+ correctionMessage);
}
return buffer.toString();
}
public static String constructUnsupportedModelingString(
UnsupportedModelingException e)
{
StringBuffer buffer = new StringBuffer();
List<Violation> violations = asSortedList(e.getViolations());
for (Violation violation : violations)
{
buffer.append(violation + LINE_SEPARATOR);
}
return buffer.toString();
}
public static void generateJavaSourceFiles(File outputFolder,
List<GeneratedModule> classes)
{
CppCodeGen vdmCodGen = new CppCodeGen("",false);
vdmCodGen.generateJavaSourceFiles(outputFolder, classes);
}
public static String formatJavaCode(String code)
{
// File tempFile = null;
// StringBuffer b = new StringBuffer();
// try
// {
// tempFile = new File("target" + File.separatorChar + "temp.java");
// tempFile.getParentFile().mkdirs();
// tempFile.createNewFile();
//
// PrintWriter xwriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(tempFile, false), "UTF-8"));
// xwriter.write(code.toString());
// xwriter.flush();
//
// Jalopy jalopy = new Jalopy();
// jalopy.setFileFormat(FileFormat.DEFAULT);
// jalopy.setInput(tempFile);
// jalopy.setOutput(b);
// jalopy.format();
//
// xwriter.close();
//
// String result = null;
//
// if (jalopy.getState() == Jalopy.State.OK
// || jalopy.getState() == Jalopy.State.PARSED)
// {
// result = b.toString();
// } else if (jalopy.getState() == Jalopy.State.WARN)
// {
// result = code;// formatted with warnings
// } else if (jalopy.getState() == Jalopy.State.ERROR)
// {
// result = code; // could not be formatted
// }
//
// return result.toString();
//
// } catch (Exception e)
// {
// Logger.getLog().printErrorln("Could not format code: "
// + e.toString());
// e.printStackTrace();
// } finally
// {
// tempFile.delete();
// }
return code;
}
public static void saveCppClass(File outputFolder, String javaFileName,
String code)
{
try
{
File javaFile = new File(outputFolder, File.separator
+ javaFileName);
javaFile.getParentFile().mkdirs();
javaFile.createNewFile();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(javaFile, false), "UTF-8"));
BufferedWriter out = new BufferedWriter(writer);
out.write(code);
out.close();
} catch (IOException e)
{
Logger.getLog().printErrorln("Error when saving class file: "
+ javaFileName);
e.printStackTrace();
}
}
public static void printMergeErrors(List<Exception> mergeErrors)
{
for (Exception error : mergeErrors)
{
Logger.getLog().println(error.toString());
}
}
public static void printUnsupportedNodes(Set<VdmNodeInfo> unsupportedNodes)
{
AssistantManager assistantManager = new AssistantManager();
LocationAssistantCG locationAssistant = assistantManager.getLocationAssistant();
List<VdmNodeInfo> nodesSorted = assistantManager.getLocationAssistant().getVdmNodeInfoLocationSorted(unsupportedNodes);
Logger.getLog().println("Following constructs are not supported: ");
for (VdmNodeInfo nodeInfo : nodesSorted)
{
Logger.getLog().print(nodeInfo.getNode().toString());
ILexLocation location = locationAssistant.findLocation(nodeInfo.getNode());
Logger.getLog().print(location != null ? " at [line, pos] = ["
+ location.getStartLine() + ", " + location.getStartPos()
+ "]" : "");
String reason = nodeInfo.getReason();
if (reason != null)
{
Logger.getLog().print(". Reason: " + reason);
}
Logger.getLog().println("");
}
}
}