JavaPatternMatching/src/de/dhbwstuttgart/core/MyCompiler.java

330 lines
12 KiB
Java
Raw Normal View History

2013-10-18 11:33:46 +00:00
package de.dhbwstuttgart.core;
2013-10-18 11:33:46 +00:00
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import de.dhbwstuttgart.typeinference.Menge;
2014-10-09 10:01:16 +00:00
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.LoggerConfiguration;
2014-11-04 12:47:05 +00:00
import de.dhbwstuttgart.logger.Section;
2014-09-04 14:35:44 +00:00
import de.dhbwstuttgart.myexception.CTypeReconstructionException;
import de.dhbwstuttgart.myexception.JVMCodeException;
import de.dhbwstuttgart.parser.JavaParser;
import de.dhbwstuttgart.parser.Scanner;
import de.dhbwstuttgart.parser.JavaParser.yyException;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.ClassBody;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.ImportDeclarations;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
2014-09-04 14:35:44 +00:00
import de.dhbwstuttgart.syntaxtree.SourceFile;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.misc.DeclId;
import de.dhbwstuttgart.syntaxtree.misc.UsedId;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.IMatchable;
import de.dhbwstuttgart.syntaxtree.type.ITypeContainer;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ByteCodeResult;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.typeinference.FunNInterface;
2015-07-08 15:46:54 +00:00
import de.dhbwstuttgart.typeinference.FunVoidNInterface;
2014-09-08 13:12:47 +00:00
import de.dhbwstuttgart.typeinference.Pair;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.ParserError;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
2013-10-18 11:33:46 +00:00
public class MyCompiler implements MyCompilerAPI{
2013-10-18 11:33:46 +00:00
// PL: Der Zusammenhang zwischen paralist und vParaOrg muesste
// noch geklaert werden 05-01-07
public static final int NO_LINENUMBER = -1;
protected static Logger inferencelog = Logger.getLogger(MyCompiler.class.getName());
2013-10-18 11:33:46 +00:00
protected String OutputDir = "";
public Menge<Pair> testPair = null;
2013-10-18 11:33:46 +00:00
/**
* Author: ¯Â¿Â½rg ¯Â¿Â½uerle<br/>
* Der private Konstruktor. Es soll von au�en kein Compiler angelegt werden
* ¯Â¿Â½nnen, sondern nur eine API zur Verf�gung gestellt werden.
* @param logger Konfiguration ¼r Debug Ausgabe TODO
2013-10-18 11:33:46 +00:00
*/
private MyCompiler(){
2013-10-18 11:33:46 +00:00
this.init();
}
2013-10-18 11:33:46 +00:00
/**
* Author: rg ¤uerle<br/>
* Stellt eine neue Instanz der CompilerAPI zur Verf�gung.
2013-10-18 11:33:46 +00:00
* Diese Methode sollte von der IDE aus aufgerufen werden,
* um eine Quellcode-Datei zu kompilieren.
* @return Die Compiler-API
*/
public static MyCompilerAPI getAPI(LoggerConfiguration loggerConfig){
Logger.setStandardConfiguration(loggerConfig);
return new MyCompiler();
2013-10-18 11:33:46 +00:00
}
/**
* Parst den Quellcode und baut den abstrakten Syntaxbaum auf. Danach wird
* automatisch der von Thomas Ott implementierte Algorithmus
* <code>NewTVar(jclass)</code> (siehe Algorithmus 5.17 TRProg, Martin Pl�micke)
2013-10-18 11:33:46 +00:00
* aufgerufen.
* <br/>Author: ¯Â¿Â½rg ¯Â¿Â½uerle
2013-10-18 11:33:46 +00:00
* @param reader
* @throws IOException
* @throws JavaParser.yyException
*/
private void parse_backup(Reader reader) throws IOException, JavaParser.yyException{
}
2013-10-18 11:33:46 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////
// Implementierte API-Methoden:
/////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Author: ¯Â¿Â½rg ¯Â¿Â½uerle<br/>
2013-10-18 11:33:46 +00:00
* Initialisiert den Compiler
*/
public void init(){
2013-10-18 11:33:46 +00:00
TypePlaceholder.deleteRegistry();
}
/**
* Author: ¯Â¿Â½rg ¯Â¿Â½uerle<br/>
2013-10-18 11:33:46 +00:00
* Ruft die Parse-Methode.
* @param file Die Quellcode-Datei
* @throws FileNotFoundException Wenn die Quellcode-Datei nicht existiert.
* @throws IOException Wenn was schief ¯Â¿Â½uft.
2013-10-18 11:33:46 +00:00
* @throws JavaParser.yyException Wenn ein Fehler beim Parsen auftritt.
*/
public SourceFile parse(File file) throws FileNotFoundException, IOException, JavaParser.yyException{
2013-10-18 11:33:46 +00:00
FileReader fr = new FileReader(file);
2014-03-14 15:34:25 +00:00
SourceFile ret = this.parse2SyntaxTree(fr);
2013-10-18 11:33:46 +00:00
fr.close();
2014-03-14 15:34:25 +00:00
return ret;
2013-10-18 11:33:46 +00:00
}
2013-10-18 11:33:46 +00:00
/**
* Author: ¯Â¿Â½rg ¯Â¿Â½uerle<br/>
2013-10-18 11:33:46 +00:00
* Ruft den Typrekonstruktionsalgorithmus auf.
* @return Die Menge aller ¯Â¿Â½glichen Typkombinationen
2013-10-18 11:33:46 +00:00
* @throws NullPointerException Wenn noch kein abstrakter Syntaxbaum vorhanden
* ist. @throws CTypeReconstructionException Wenn ein Fehler bei der
* Typrekonstruktion auftritt.
*/
public Menge<TypeinferenceResultSet> typeReconstruction(Menge<SourceFile> m_AbstractSyntaxTree) throws NullPointerException, CTypeReconstructionException{
2014-11-04 12:47:05 +00:00
inferencelog.info("##########################################", Section.TYPEINFERENCE);
inferencelog.info("# TypeReconstruction-Algorithmus - START #", Section.TYPEINFERENCE);
inferencelog.info("##########################################\n", Section.TYPEINFERENCE);
2014-02-11 01:47:39 +00:00
TypeAssumptions globalAssumptions = makeFunNAssumptions();
Menge<TypeinferenceResultSet> result = new Menge<TypeinferenceResultSet>();
for(SourceFile srcFile : m_AbstractSyntaxTree){
result.addAll(srcFile.typeReconstruction(globalAssumptions));
}
2014-02-11 01:47:39 +00:00
2014-11-04 12:47:05 +00:00
inferencelog.info("#########################################", Section.TYPEINFERENCE);
inferencelog.info("# TypeReconstruction-Algorithmus - ENDE #", Section.TYPEINFERENCE);
inferencelog.info("#########################################\n", Section.TYPEINFERENCE);
2013-10-18 11:33:46 +00:00
return result;
}
/**
* Erstellt die FunN-Assumptions
* Fun0-FunN (momentan ¼r N = 6)
* @return
*/
private TypeAssumptions makeFunNAssumptions(){
TypeAssumptions ret = new TypeAssumptions();
//Basic Assumptions für die FunN Interfaces:
//TODO: Hier mehr als Fun1-Fun5 implementieren
for(int i = 0; i<6; i++){
FunNInterface funN = new FunNInterface(i);
ret.add(funN.getPublicFieldAssumptions());
}
2015-07-08 15:46:54 +00:00
for(int i = 0; i<6; i++){
FunVoidNInterface funN = new FunVoidNInterface(i);
ret.add(funN.getPublicFieldAssumptions());
}
return ret;
}
2013-10-18 11:33:46 +00:00
/**
* Die Main-Funktion, �ber die der Compiler auch per Konsole gestartet
2013-10-18 11:33:46 +00:00
* werden kann.
* @param args Klassendatei
*/
public static void main(String[] args){
MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration());
2013-10-18 11:33:46 +00:00
// Hier koennten ggf. Aenderungen der Ausgabeeinstellungen
// (Debuginfos) vorgenommen werden -> LOG4J
try {
compiler.parse(new File(args[0]));
} catch (FileNotFoundException e) {
System.err.println("Die Datei \""+args[0]+"\" konnte nicht gefunden werden.");
System.exit(0);
} catch (IOException e) {
System.err.println("Fehler beim Parsen:");
System.err.println(e);
System.exit(0);
} catch (yyException e) {
System.err.println("Fehler beim Parsen:");
System.err.println(e);
System.exit(0);
}
}
2013-10-18 11:33:46 +00:00
public void setOutputDir(String dir){
2013-10-18 11:33:46 +00:00
char c = dir.charAt(dir.length()-1);
if (c != '/' & c != '\\') dir = dir + "/";
OutputDir = dir;
// Verzeichnis(se) ggf. anlegen
File f = new File(dir);
f.mkdirs();
}
public String getOutputDir(){
2013-10-18 11:33:46 +00:00
return OutputDir;
}
/**
* @author Arne ¼dtke
2013-10-18 11:33:46 +00:00
* Ersetzt alle GTVs durch TPHs mit gleichem Namen. Arbeitet Rekursiv.
* ACHTUNG: BACKDOOR CREATE!!! Nur ¼r Testzwecke verwenden.
2013-10-18 11:33:46 +00:00
* @param T - Typ, bei welchem die GTVs ersetzt werden sollen.
*/
public static Type makeGenericTypeVars2TypePlaceHolders(Type T)
{
if(T instanceof RefType)
{
RefType refT = (RefType)T;
if(refT.get_ParaList() != null)
{
Menge<Type> paras = refT.get_ParaList();
2013-10-18 11:33:46 +00:00
for(int i = 0; i<paras.size();i++)
{
Type tt = paras.elementAt(i);
if(tt instanceof GenericTypeVar)
{
GenericTypeVar gtv = (GenericTypeVar)tt;
2014-09-02 16:49:19 +00:00
paras.set(i,TypePlaceholder.backdoorCreate(gtv.getName().toString()));
2013-10-18 11:33:46 +00:00
}
else
{
makeGenericTypeVars2TypePlaceHolders(tt);
}
}
}
}
else if(T instanceof IMatchable)
{
Type TT = ((IMatchable)T).getMatchType();
makeGenericTypeVars2TypePlaceHolders(TT);
}
return T;
}
/**
* Parst den Inhalt einer Datei zu einem Syntaxbaum.
*/
2014-04-15 12:56:20 +00:00
private SourceFile parse2SyntaxTree(Reader fileContent) throws ParserError{
//StringReader reader = new StringReader(fileContent);
//////////////////////////////////////
// Scanner und Parser erzeugen:
//////////////////////////////////////
Scanner scanner = new Scanner(fileContent);
JavaParser parser = new JavaParser();
//////////////////////////////////////
// Parsen ==> Ergebnis: srcFile
//////////////////////////////////////
SourceFile srcFile = null;
try {
srcFile = (SourceFile) parser.yyparse( scanner );
} catch (IOException | yyException e) {
e.printStackTrace();
2014-04-15 12:56:20 +00:00
if(e instanceof yyException)throw new ParserError((yyException)e);
}
//////////////////////////////////////
// Postprocessing:
//////////////////////////////////////
srcFile.parserPostProcessing(null); //Muss mit null aufgerufen werden.
//Fertig:
return srcFile;
}
/**
* Diese Funktion nimmt einen Menge von Dateinamen. Alle diese Dateien werden zu einem SyntaxBaum geparst.
* @return
2013-10-18 11:33:46 +00:00
*/
public Menge<SourceFile> parse(Menge<String> filenames) throws ParserError {
Menge<SourceFile> m_AbstractSyntaxTree = new Menge<SourceFile>();
for(String filename : filenames){
StringBuffer fileData = new StringBuffer();
BufferedReader reader;
try {
reader = new BufferedReader(
new FileReader(filename));
} catch (FileNotFoundException e) {
2014-04-15 12:56:20 +00:00
throw new DebugException("Die Datei "+ filename+" konnte nicht gelesen werden.");
}
char[] buf = new char[1024];
int numRead=0;
try {
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
StringReader srcreader = new StringReader(fileData.toString());
//Den aus der Datei ausgelesenen Quellcode zu einem Syntaxbaum parsen:
m_AbstractSyntaxTree.add(parse2SyntaxTree(srcreader)); // Alle Dateien nacheinander hintereinander anhängen...
2013-10-18 11:33:46 +00:00
}
return m_AbstractSyntaxTree;
2013-10-18 11:33:46 +00:00
}
@Override
public SourceFile parse(String sourceCode) {
return parse2SyntaxTree(new StringReader(sourceCode));
}
@Override
public Menge<ByteCodeResult> generateBytecode(Menge<SourceFile> m_AbstractSyntaxTree, TypeinferenceResultSet typeinferenceResult) {
2015-08-27 11:36:14 +00:00
//SourceFile parsedFile = this.m_AbstractSyntaxTree.firstElement();
//Class parsedClass = parsedFile.KlassenVektor.firstElement();
Menge<ByteCodeResult> ret = new Menge<>();
for(SourceFile sf : m_AbstractSyntaxTree){
ret.addAll(sf.generateBytecode(typeinferenceResult));
}
2015-08-27 11:36:14 +00:00
return ret;
}
2013-10-18 11:33:46 +00:00
}