forked from JavaTX/JavaCompilerCore
292 lines
11 KiB
Java
Executable File
292 lines
11 KiB
Java
Executable File
|
|
package de.dhbwstuttgart.core;
|
|
|
|
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;
|
|
import de.dhbwstuttgart.logger.Logger;
|
|
import de.dhbwstuttgart.logger.LoggerConfiguration;
|
|
import de.dhbwstuttgart.logger.Section;
|
|
import de.dhbwstuttgart.parser.JavaParser;
|
|
import de.dhbwstuttgart.parser.Scanner;
|
|
import de.dhbwstuttgart.parser.JavaParser.yyException;
|
|
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;
|
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
|
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;
|
|
import de.dhbwstuttgart.typeinference.FunNInterface;
|
|
import de.dhbwstuttgart.typeinference.FunVoidNInterface;
|
|
import de.dhbwstuttgart.typeinference.Pair;
|
|
import de.dhbwstuttgart.typeinference.ResultSet;
|
|
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
|
|
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
|
|
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
|
|
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
|
|
import de.dhbwstuttgart.typeinference.exceptions.ParserError;
|
|
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
|
|
|
|
|
|
public class MyCompiler implements MyCompilerAPI{
|
|
// 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());
|
|
|
|
protected String OutputDir = "";
|
|
|
|
public Menge<Pair> testPair = null;
|
|
|
|
/**
|
|
* Author: J�rg B�uerle<br/>
|
|
* Der private Konstruktor. Es soll von au�en kein Compiler angelegt werden
|
|
* k�nnen, sondern nur eine API zur Verf�gung gestellt werden.
|
|
* @param logger Konfiguration für Debug Ausgabe TODO
|
|
*/
|
|
private MyCompiler(){
|
|
this.init();
|
|
}
|
|
|
|
/**
|
|
* Author: Jörg Bäuerle<br/>
|
|
* Stellt eine neue Instanz der CompilerAPI zur Verf�gung.
|
|
* 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();
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
* aufgerufen.
|
|
* <br/>Author: J�rg B�uerle
|
|
* @param reader
|
|
* @throws IOException
|
|
* @throws JavaParser.yyException
|
|
*/
|
|
private void parse_backup(Reader reader) throws IOException, JavaParser.yyException{
|
|
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Implementierte API-Methoden:
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* Author: J�rg B�uerle<br/>
|
|
* Initialisiert den Compiler
|
|
*/
|
|
public void init(){
|
|
TypePlaceholder.deleteRegistry();
|
|
}
|
|
/**
|
|
* Author: J�rg B�uerle<br/>
|
|
* Ruft die Parse-Methode.
|
|
* @param file Die Quellcode-Datei
|
|
* @throws FileNotFoundException Wenn die Quellcode-Datei nicht existiert.
|
|
* @throws IOException Wenn was schief l�uft.
|
|
* @throws JavaParser.yyException Wenn ein Fehler beim Parsen auftritt.
|
|
*/
|
|
public SourceFile parse(File file) throws FileNotFoundException, IOException, JavaParser.yyException{
|
|
FileReader fr = new FileReader(file);
|
|
SourceFile ret = this.parse2SyntaxTree(fr);
|
|
fr.close();
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Author: J�rg B�uerle<br/>
|
|
* Ruft den Typrekonstruktionsalgorithmus auf.
|
|
* @return Die Menge aller m�glichen Typkombinationen
|
|
* @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{
|
|
inferencelog.info("##########################################", Section.TYPEINFERENCE);
|
|
inferencelog.info("# TypeReconstruction-Algorithmus - START #", Section.TYPEINFERENCE);
|
|
inferencelog.info("##########################################\n", Section.TYPEINFERENCE);
|
|
|
|
TypeAssumptions globalAssumptions = makeFunNAssumptions();
|
|
Menge<TypeinferenceResultSet> result = new Menge<TypeinferenceResultSet>();
|
|
for(SourceFile srcFile : m_AbstractSyntaxTree){
|
|
result.addAll(srcFile.typeReconstruction(globalAssumptions));
|
|
|
|
}
|
|
|
|
inferencelog.info("#########################################", Section.TYPEINFERENCE);
|
|
inferencelog.info("# TypeReconstruction-Algorithmus - ENDE #", Section.TYPEINFERENCE);
|
|
inferencelog.info("#########################################\n", Section.TYPEINFERENCE);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Erstellt die FunN-Assumptions
|
|
* Fun0-FunN (momentan für N = 6)
|
|
* @return
|
|
*/
|
|
public static 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());
|
|
}
|
|
for(int i = 0; i<6; i++){
|
|
FunVoidNInterface funN = new FunVoidNInterface(i);
|
|
ret.add(funN.getPublicFieldAssumptions());
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Die Main-Funktion, �ber die der Compiler auch per Konsole gestartet
|
|
* werden kann.
|
|
* @param args Klassendatei
|
|
*/
|
|
public static void main(String[] args){
|
|
MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration());
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
public void setOutputDir(String dir){
|
|
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(){
|
|
return OutputDir;
|
|
}
|
|
|
|
/**
|
|
* Parst den Inhalt einer Datei zu einem Syntaxbaum.
|
|
*/
|
|
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();
|
|
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
|
|
*/
|
|
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) {
|
|
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...
|
|
}
|
|
|
|
return m_AbstractSyntaxTree;
|
|
}
|
|
|
|
@Override
|
|
public SourceFile parse(String sourceCode) {
|
|
return parse2SyntaxTree(new StringReader(sourceCode));
|
|
}
|
|
|
|
@Override
|
|
public Menge<ByteCodeResult> generateBytecode(Menge<SourceFile> m_AbstractSyntaxTree, TypeinferenceResults typeinferenceResults) {
|
|
//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(typeinferenceResults));
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|