Static but no static blocks yet
This commit is contained in:
parent
892ba5fff0
commit
eaef00ff54
9
resources/bytecode/javFiles/Static.jav
Normal file
9
resources/bytecode/javFiles/Static.jav
Normal file
@ -0,0 +1,9 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Static {
|
||||
static i = 20;
|
||||
|
||||
static m() {
|
||||
return i;
|
||||
}
|
||||
}
|
@ -599,7 +599,7 @@ public class Codegen {
|
||||
switch (op) {
|
||||
case TargetUnaryOp.Add add ->
|
||||
// This literally does nothing
|
||||
generate(state, add.expr());
|
||||
generate(state, add.expr());
|
||||
case TargetUnaryOp.Negate negate -> {
|
||||
generate(state, negate.expr());
|
||||
if (negate.type().equals(TargetType.Double))
|
||||
@ -834,7 +834,8 @@ public class Codegen {
|
||||
}
|
||||
case TargetFieldVar dot -> {
|
||||
var fieldType = dot.type();
|
||||
generate(state, dot.left());
|
||||
if (!(dot.left() instanceof TargetThis && dot.isStatic()))
|
||||
generate(state, dot.left());
|
||||
generate(state, assign.right());
|
||||
convertTo(state, assign.right().type(), fieldType);
|
||||
boxPrimitive(state, fieldType);
|
||||
@ -1290,6 +1291,20 @@ public class Codegen {
|
||||
cw.visitField(access, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
|
||||
}
|
||||
|
||||
private void generateStaticConstructor(TargetMethod constructor) {
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
var state = new State(null, mv, 0);
|
||||
var stmts = constructor.block().statements();
|
||||
for (var i = 1; i < stmts.size(); i++)
|
||||
generate(state, stmts.get(i));
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateConstructor(TargetConstructor constructor) {
|
||||
MethodVisitor mv = cw.visitMethod(constructor.access() | ACC_PUBLIC, "<init>", constructor.getDescriptor(), constructor.getSignature(), null);
|
||||
if (constructor.txGenerics() != null)
|
||||
@ -1407,6 +1422,9 @@ public class Codegen {
|
||||
clazz.constructors().forEach(this::generateConstructor);
|
||||
clazz.methods().forEach(this::generateMethod);
|
||||
|
||||
if (clazz.staticConstructor() != null)
|
||||
generateStaticConstructor(clazz.staticConstructor());
|
||||
|
||||
if (clazz instanceof TargetRecord)
|
||||
generateRecordMethods();
|
||||
|
||||
|
@ -70,6 +70,9 @@ public class JavaTXCompiler {
|
||||
final CompilationEnvironment environment;
|
||||
Boolean resultmodel = false;
|
||||
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
|
||||
// TODO We might want to incorporate this into the class registry instead
|
||||
public final Map<JavaClassName, ClassOrInterface> classes = new HashMap<>();
|
||||
|
||||
Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||
private final DirectoryClassLoader classLoader;
|
||||
@ -103,11 +106,22 @@ public class JavaTXCompiler {
|
||||
classPath = contextPath;
|
||||
|
||||
for (File s : sources) {
|
||||
sourceFiles.put(s, parse(s));
|
||||
addSourceFile(s, parse(s));
|
||||
}
|
||||
// INSTANCE = this;
|
||||
}
|
||||
|
||||
private void addSourceFile(File file, SourceFile sf) {
|
||||
sourceFiles.put(file, sf);
|
||||
for (var clazz : sf.KlassenVektor) {
|
||||
classes.put(clazz.getClassName(), clazz);
|
||||
}
|
||||
}
|
||||
|
||||
public ClassOrInterface getClass(JavaClassName name) {
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
||||
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
|
||||
List<ClassOrInterface> importedClasses = new ArrayList<>();
|
||||
@ -630,8 +644,8 @@ public class JavaTXCompiler {
|
||||
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
||||
SourceFileContext tree = JavaTXParser.parse(sourceFile);
|
||||
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(classRegistry, new GenericsRegistry(null));
|
||||
SourceFile ret = generator.convert(tree, environment.packageCrawler, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
|
||||
SourceFile ret = generator.convert(tree, environment.packageCrawler);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -651,8 +665,8 @@ public class JavaTXCompiler {
|
||||
var tree = JavaTXParser.parse(file);
|
||||
classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away?
|
||||
environment.addClassesToRegistry(classRegistry, tree, file, this);
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(classRegistry, new GenericsRegistry(null));
|
||||
sourceFiles.put(file, generator.convert(tree, environment.packageCrawler, this));
|
||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
|
||||
addSourceFile(file, generator.convert(tree, environment.packageCrawler));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -0,0 +1,6 @@
|
||||
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
|
||||
public record FieldEntry(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifiers) {
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -8,6 +9,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
@ -134,17 +136,24 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
|
||||
public class StatementGenerator {
|
||||
|
||||
private JavaClassRegistry reg;
|
||||
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields; // PL 2018-11-01 fields eingefuegt, damit die fields
|
||||
// immer die gleiche TPH bekommen
|
||||
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars;
|
||||
private GenericsRegistry generics;
|
||||
private final JavaClassRegistry reg;
|
||||
|
||||
public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields, Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars) {
|
||||
private final Map<String, FieldEntry> fields; // PL 2018-11-01 fields eingefuegt, damit die fields
|
||||
// immer die gleiche TPH bekommen
|
||||
private final Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars;
|
||||
private final GenericsRegistry generics;
|
||||
private final JavaTXCompiler compiler;
|
||||
|
||||
private final RefType superClass;
|
||||
|
||||
// TODO How about instead of passing all of these types we just pass an instance of the SyntaxTreeGenerator?
|
||||
public StatementGenerator(RefType superType, JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry generics, Map<String, FieldEntry> fields, Map<String, RefTypeOrTPHOrWildcardOrGeneric> localVars) {
|
||||
this.reg = reg;
|
||||
this.generics = generics;
|
||||
this.fields = fields;
|
||||
this.localVars = localVars;
|
||||
this.compiler = compiler;
|
||||
this.superClass = superType;
|
||||
}
|
||||
|
||||
public ParameterList convert(Java17Parser.FormalParameterListContext formalParameterListContext) {
|
||||
@ -574,7 +583,8 @@ public class StatementGenerator {
|
||||
} else {
|
||||
initValue = convert(varDecl.variableInitializer().expression());
|
||||
}
|
||||
return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), name.getText(), type, varDecl.getStart())), initValue, name.getStart()));
|
||||
var fieldEntry = fields.get(name.getText());
|
||||
return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), (fieldEntry.modifiers() & Modifier.STATIC) != 0, name.getText(), type, varDecl.getStart())), initValue, name.getStart()));
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.BreakstmtContext stmt) {
|
||||
@ -760,7 +770,8 @@ public class StatementGenerator {
|
||||
return new LocalVar(expression, localVars.get(expression), offset);
|
||||
} else if (fields.get(expression) != null) {// PL 2018-11-01 fields eingefuegt, damit die fields immer die
|
||||
// gleiche TPH bekommen
|
||||
return new FieldVar(new This(offset), expression, fields.get(expression), offset);
|
||||
var field = fields.get(expression);
|
||||
return new FieldVar(new This(offset), Modifier.isStatic(field.modifiers()), expression, fields.get(expression).type(), offset);
|
||||
|
||||
} else {
|
||||
// lokale Variable wurde ohne "var"-Keyword deklariert und direkt mit Wert versehen
|
||||
@ -783,16 +794,23 @@ public class StatementGenerator {
|
||||
}
|
||||
whole += ".";
|
||||
}
|
||||
var fieldName = parts[parts.length - 1];
|
||||
|
||||
var isStatic = false;
|
||||
if (parts.length < 2 || parts[0].contentEquals("this")) {
|
||||
receiver = new This(offset);
|
||||
isStatic = Modifier.isStatic(fields.get(fieldName).modifiers());
|
||||
} else if (parts[0].contentEquals("super")) {
|
||||
receiver = new Super(offset);
|
||||
isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier);
|
||||
} else if (receiver == null) { // Handelt es sich um keinen Statischen Klassennamen:
|
||||
String part = expression.substring(0, expression.length() - (1 + parts[parts.length - 1].length()));
|
||||
receiver = generateLocalOrFieldVarOrClassName(part, offset);
|
||||
} else {
|
||||
StaticClassName cname = (StaticClassName) receiver;
|
||||
isStatic = Modifier.isStatic(compiler.getClass(reg.getName(cname.getType().toString())).getField(fieldName).orElseThrow().modifier);
|
||||
}
|
||||
return new FieldVar(receiver, parts[parts.length - 1], TypePlaceholder.fresh(offset), offset);
|
||||
return new FieldVar(receiver, isStatic, fieldName, TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.ArrayaccessexpressionContext arrayaccess) {
|
||||
@ -1063,7 +1081,7 @@ public class StatementGenerator {
|
||||
if (!(param instanceof FormalParameter fp)) throw new IllegalArgumentException();
|
||||
lambdaLocals.put(fp.getName(), fp.getType());
|
||||
}
|
||||
StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, fields, lambdaLocals);
|
||||
StatementGenerator lambdaGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, lambdaLocals);
|
||||
|
||||
Block block;
|
||||
if (expression.lambdaBody().expression() != null) {
|
||||
|
@ -13,6 +13,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.Record;
|
||||
import org.antlr.v4.runtime.CommonToken;
|
||||
@ -91,11 +92,15 @@ public class SyntaxTreeGenerator {
|
||||
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
||||
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
||||
// bekommen
|
||||
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields = new HashMap<>();
|
||||
private final Map<String, FieldEntry> fields = new HashMap<>();
|
||||
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
||||
List<Statement> fieldInitializations = new ArrayList<>();
|
||||
List<Statement> staticFieldInitializations = new ArrayList<>();
|
||||
|
||||
public SyntaxTreeGenerator(JavaClassRegistry reg, GenericsRegistry globalGenerics) {
|
||||
private final JavaTXCompiler compiler;
|
||||
private RefType superClass;
|
||||
|
||||
public SyntaxTreeGenerator(JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry globalGenerics) {
|
||||
// Die Generics müssen während des Bauens des AST erstellt werden,
|
||||
// da diese mit der Methode oder Klasse, in welcher sie deklariert werden
|
||||
// verknüpft sein müssen. Dennoch werden die Namen aller Generics in einer
|
||||
@ -118,6 +123,8 @@ public class SyntaxTreeGenerator {
|
||||
this.allmodifiers.put("non-sealed", 8192);
|
||||
this.allmodifiers.put("default", 16384);
|
||||
this.allmodifiers.put("strictfp", 32768);
|
||||
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
public JavaClassRegistry getReg() {
|
||||
@ -131,7 +138,7 @@ public class SyntaxTreeGenerator {
|
||||
return ctx.getText();
|
||||
}
|
||||
|
||||
public SourceFile convert(Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler, JavaTXCompiler compiler) throws ClassNotFoundException, NotImplementedException {
|
||||
public SourceFile convert(Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException, NotImplementedException {
|
||||
SrcfileContext srcfile;
|
||||
List<ClassOrInterface> classes = new ArrayList<>();
|
||||
if (ctx instanceof Java17Parser.SrcfileContext) {
|
||||
@ -200,6 +207,7 @@ public class SyntaxTreeGenerator {
|
||||
} else {
|
||||
superClass = new RefType(ASTFactory.createObjectClass().getClassName(), ctx.getStart());
|
||||
}
|
||||
this.superClass = superClass;
|
||||
List<Field> fielddecl = new ArrayList<>();
|
||||
List<Method> methods = new ArrayList<>();
|
||||
List<Constructor> constructors = new ArrayList<>();
|
||||
@ -225,11 +233,14 @@ public class SyntaxTreeGenerator {
|
||||
throw new NotImplementedException("Invalid sealed class declaration");
|
||||
}
|
||||
}
|
||||
return new ClassOrInterface(modifiers, name, fielddecl, Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset)), methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||
var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset));
|
||||
var staticCtor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
|
||||
return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||
|
||||
}
|
||||
|
||||
private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
|
||||
this.superClass = new RefType(new JavaClassName("java.lang.Record"), new NullToken());
|
||||
String identifier = recordDeclaration.identifier().getText();
|
||||
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + identifier;
|
||||
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
||||
@ -264,7 +275,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
||||
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
|
||||
FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset);
|
||||
FieldVar fieldvar = new FieldVar(new This(offset), false, fieldname, fieldtype, fieldoffset);
|
||||
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
||||
Statement returnStatement = new Return(fieldvar, offset);
|
||||
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
|
||||
@ -279,7 +290,8 @@ public class SyntaxTreeGenerator {
|
||||
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
||||
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
||||
}
|
||||
return new Record(modifiers, name, fielddecl, initializations, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||
var staticCtor = Optional.of(this.generatePseudoConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
|
||||
return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||
}
|
||||
|
||||
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
|
||||
@ -319,6 +331,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
|
||||
private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) {
|
||||
this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken());
|
||||
String className = this.pkgName.length() > 0 ? this.pkgName + "." : "" + ctx.identifier().getText();
|
||||
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
||||
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
|
||||
@ -391,7 +404,9 @@ public class SyntaxTreeGenerator {
|
||||
throw new NotImplementedException("Invalid sealed class declaration");
|
||||
}
|
||||
}
|
||||
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, permittedSubtypes, ctx.getStart());
|
||||
|
||||
var staticCtor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
|
||||
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, permittedSubtypes, ctx.getStart());
|
||||
}
|
||||
|
||||
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {
|
||||
@ -419,7 +434,7 @@ public class SyntaxTreeGenerator {
|
||||
retType = new Void(bodydeclaration.refType().getStart());
|
||||
}
|
||||
}
|
||||
StatementGenerator stmtgen = new StatementGenerator(reg, generics, fields, new HashMap<>());
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList());
|
||||
MethodBodyContext body = bodydeclaration.methodBody();
|
||||
Block block = null;
|
||||
@ -447,10 +462,10 @@ public class SyntaxTreeGenerator {
|
||||
/*
|
||||
* fieldInitializations werden in einem Psedokonstruktor in der abstrakten Syntax gespeichert
|
||||
*/
|
||||
private Constructor generatePseudoConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) {
|
||||
private Constructor generatePseudoConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
|
||||
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
|
||||
ParameterList params = new ParameterList(new ArrayList<>(), offset);
|
||||
Block block = new Block(new ArrayList<>(fieldInitializations), offset);
|
||||
Block block = new Block(new ArrayList<>(initializations), offset);
|
||||
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*
|
||||
* fieldInitializations geloescht PL 2018-11-24
|
||||
*/);
|
||||
@ -512,7 +527,7 @@ public class SyntaxTreeGenerator {
|
||||
retType = new Void(header.refType().getStart());
|
||||
}
|
||||
}
|
||||
StatementGenerator stmtgen = new StatementGenerator(reg, localgenerics, fields, new HashMap<>());
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList());
|
||||
MethodBodyContext body = methoddeclaration.methodBody();
|
||||
Block block = null;
|
||||
@ -552,13 +567,13 @@ public class SyntaxTreeGenerator {
|
||||
gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), constructordeclaration.getStart());
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics);
|
||||
StatementGenerator stmtgen = new StatementGenerator(reg, localgenerics, fields, new HashMap<>());
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList());
|
||||
Block block = stmtgen.convert(constructordeclaration.constructorBody, true);
|
||||
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
||||
}
|
||||
|
||||
private List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
||||
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
||||
List<Field> ret = new ArrayList<>();
|
||||
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
||||
if (fieldDeclContext.typeType() != null) {
|
||||
@ -570,9 +585,9 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
||||
String fieldName = varDecl.variableDeclaratorId().getText();
|
||||
this.fields.put(fieldName, fieldType);
|
||||
this.fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
||||
if (varDecl.variableInitializer() != null) {
|
||||
initializeField(varDecl, fieldType, generics);
|
||||
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics);
|
||||
}
|
||||
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
||||
}
|
||||
@ -584,9 +599,12 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
|
||||
// Initialize a field by creating implicit constructor.
|
||||
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
||||
StatementGenerator statementGenerator = new StatementGenerator(reg, generics, fields, new HashMap<>());
|
||||
fieldInitializations.add(statementGenerator.generateFieldAssignment(ctx, typeOfField));
|
||||
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
||||
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
||||
if (isStatic)
|
||||
staticFieldInitializations.add(assignment);
|
||||
else fieldInitializations.add(assignment);
|
||||
}
|
||||
|
||||
public int convertModifier(String modifier) {
|
||||
|
@ -1,18 +1,11 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
import de.dhbwstuttgart.core.IItemWithOffset;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
@ -30,6 +23,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
protected JavaClassName name;
|
||||
private List<Field> fields = new ArrayList<>();
|
||||
private Optional<Constructor> fieldInitializations; // PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen
|
||||
private Optional<Constructor> staticInitializer;
|
||||
private List<Method> methods = new ArrayList<>();
|
||||
private GenericDeclarationList genericClassParameters;
|
||||
private RefType superClass;
|
||||
@ -38,7 +32,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
private List<RefType> permittedSubtypes;
|
||||
private List<Constructor> constructors;
|
||||
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Constructor> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
|
||||
super(offset);
|
||||
if (isInterface) {
|
||||
modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT;
|
||||
@ -47,6 +41,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
this.name = name;
|
||||
this.fields = fielddecl;
|
||||
this.fieldInitializations = fieldInitializations;
|
||||
this.staticInitializer = staticInitializer;
|
||||
this.genericClassParameters = genericClassParameters;
|
||||
this.superClass = superClass;
|
||||
this.isInterface = isInterface;
|
||||
@ -65,6 +60,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
this.name = cl.name;
|
||||
this.fields = new ArrayList<>(cl.fields);
|
||||
this.fieldInitializations = cl.fieldInitializations;
|
||||
this.staticInitializer = cl.staticInitializer;
|
||||
this.genericClassParameters = cl.genericClassParameters;
|
||||
this.superClass = cl.superClass;
|
||||
this.isInterface = cl.isInterface;
|
||||
@ -73,6 +69,15 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
this.constructors = new ArrayList<>(cl.constructors);
|
||||
}
|
||||
|
||||
public Optional<Field> getField(String name) {
|
||||
// TODO This should be a map
|
||||
return fields.stream().filter(field -> field.getName().equals(name)).findFirst();
|
||||
}
|
||||
|
||||
public Optional<Constructor> getStaticInitializer() {
|
||||
return staticInitializer;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return (Modifier.INTERFACE & this.getModifiers()) != 0;
|
||||
}
|
||||
|
@ -9,9 +9,11 @@ import org.antlr.v4.runtime.Token;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
|
||||
public class Record extends ClassOrInterface {
|
||||
|
||||
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
|
||||
super(modifiers, name, fielddecl, fieldInitializations, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, new ArrayList<>(), offset);
|
||||
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Constructor> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
|
||||
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, new ArrayList<>(), offset);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public class ASTFactory {
|
||||
|
||||
Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
|
||||
|
||||
var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, methoden, konstruktoren, genericDeclarationList, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||
var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||
cache.put(jreClass, cinf);
|
||||
return cinf;
|
||||
}
|
||||
|
@ -17,11 +17,13 @@ public class FieldVar extends Expression {
|
||||
|
||||
public final String fieldVarName;
|
||||
public final Expression receiver;
|
||||
public final boolean isStatic;
|
||||
|
||||
public FieldVar(Expression receiver, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
public FieldVar(Expression receiver, boolean isStatic, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(type, offset);
|
||||
this.fieldVarName = fieldVarName;
|
||||
this.receiver = receiver;
|
||||
this.isStatic = isStatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,11 +144,15 @@ public class ASTToTargetAST {
|
||||
var fields = input.getFieldDecl().stream().map(this::convert).toList();
|
||||
var methods = groupOverloads(input.getMethods()).stream().map(this::convert).flatMap(List::stream).toList();
|
||||
|
||||
TargetMethod staticConstructor = null;
|
||||
if (input.getStaticInitializer().isPresent())
|
||||
staticConstructor = this.convert(input.getStaticInitializer().get()).get(0);
|
||||
|
||||
if (input instanceof Record)
|
||||
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
|
||||
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||
else if (input.isInterface())
|
||||
return new TargetInterface(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, methods, superInterfaces);
|
||||
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
|
||||
return new TargetInterface(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, methods, superInterfaces, staticConstructor);
|
||||
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||
}
|
||||
|
||||
private List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
|
||||
|
@ -134,7 +134,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(FieldVar fieldVar) {
|
||||
result = new TargetFieldVar(converter.convert(fieldVar.getType()), converter.convert(fieldVar.receiver.getType()), false, converter.convert(fieldVar.receiver), fieldVar.fieldVarName);
|
||||
result = new TargetFieldVar(converter.convert(fieldVar.getType()), converter.convert(fieldVar.receiver.getType()), fieldVar.isStatic, converter.convert(fieldVar.receiver), fieldVar.fieldVarName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -11,13 +11,13 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public record TargetClass(int modifiers, JavaClassName qualifiedName, TargetType superType, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces,
|
||||
List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
|
||||
List<TargetConstructor> constructors, TargetMethod staticConstructor, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
|
||||
|
||||
public TargetClass(int modifiers, JavaClassName qualifiedName) {
|
||||
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new HashSet<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
||||
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new HashSet<>(), new ArrayList<>(), new ArrayList<>(), null, new ArrayList<>(), new ArrayList<>());
|
||||
}
|
||||
public TargetClass(int modifiers, JavaClassName qualifiedName, List<TargetType> implementingInterfaces) {
|
||||
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new HashSet<>(), implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
||||
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new HashSet<>(), implementingInterfaces, new ArrayList<>(), null, new ArrayList<>(), new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addField(int access, TargetRefType type, String name) {
|
||||
|
@ -6,7 +6,7 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces) implements TargetStructure {
|
||||
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces, TargetMethod staticConstructor) implements TargetStructure {
|
||||
@Override
|
||||
public TargetType superType() {
|
||||
return null;
|
||||
|
@ -7,7 +7,7 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public record TargetRecord(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces, List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
|
||||
public record TargetRecord(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces, List<TargetConstructor> constructors, TargetMethod staticConstructor, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
|
||||
|
||||
public static final TargetType RECORD = new TargetRefType("java.lang.Record");
|
||||
public TargetType superType() {
|
||||
|
@ -15,6 +15,9 @@ public interface TargetStructure {
|
||||
Set<TargetGeneric> txGenerics();
|
||||
List<TargetType> implementingInterfaces();
|
||||
List<TargetConstructor> constructors();
|
||||
|
||||
TargetMethod staticConstructor();
|
||||
|
||||
List<TargetField> fields();
|
||||
List<TargetMethod> methods();
|
||||
|
||||
|
@ -15,13 +15,14 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FunNClass extends ClassOrInterface {
|
||||
public FunNClass(List<GenericRefType> funNParams) {
|
||||
super(0, new JavaClassName("Fun" + (funNParams.size() - 1)), new ArrayList<>(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, new ArrayList<>(), new ArrayList<>(), new NullToken());
|
||||
super(0, new JavaClassName("Fun" + (funNParams.size() - 1)), new ArrayList<>(), Optional.empty(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, new ArrayList<>(), new ArrayList<>(), new NullToken());
|
||||
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,10 @@ public class TYPE {
|
||||
if (cl.getfieldInitializations().isPresent()) {
|
||||
ret.addAll(getConstraintsConstructor(cl.getfieldInitializations().get(), info, cl));
|
||||
}
|
||||
if (cl.getStaticInitializer().isPresent()) {
|
||||
ret.addAll(getConstraintsConstructor(cl.getStaticInitializer().get(), info, cl));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
|
@ -719,6 +719,12 @@ public class TestComplete {
|
||||
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Interfaces.jav");
|
||||
var clazz = classFiles.get("Interfaces");
|
||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||
System.out.println(Arrays.toString(clazz.getInterfaces()));
|
||||
}
|
||||
@Test
|
||||
public void testStatic() throws Exception {
|
||||
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Static.jav");
|
||||
var clazz = classFiles.get("Static");
|
||||
var m = clazz.getDeclaredMethod("m");
|
||||
assertEquals(m.invoke(null), 20);
|
||||
}
|
||||
}
|
||||
|
@ -8,17 +8,13 @@ import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.target.tree.TargetClass;
|
||||
import de.dhbwstuttgart.target.tree.TargetStructure;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -26,7 +22,7 @@ public class ASTToTypedTargetAST {
|
||||
|
||||
@Test
|
||||
public void emptyClass() {
|
||||
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new ArrayList<>(), new NullToken());
|
||||
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), Optional.empty(), Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new ArrayList<>(), new NullToken());
|
||||
ResultSet emptyResultSet = new ResultSet(new HashSet<>());
|
||||
TargetStructure emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
|
||||
assert emptyTargetClass.getName().equals("EmptyClass");
|
||||
|
Loading…
Reference in New Issue
Block a user