Static but no static blocks yet

This commit is contained in:
Daniel Holle 2023-10-23 16:44:12 +02:00
parent 892ba5fff0
commit eaef00ff54
20 changed files with 170 additions and 64 deletions

View File

@ -0,0 +1,9 @@
import java.lang.Integer;
public class Static {
static i = 20;
static m() {
return i;
}
}

View File

@ -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();

View File

@ -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);

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public record FieldEntry(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifiers) {
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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() {

View File

@ -15,6 +15,9 @@ public interface TargetStructure {
Set<TargetGeneric> txGenerics();
List<TargetType> implementingInterfaces();
List<TargetConstructor> constructors();
TargetMethod staticConstructor();
List<TargetField> fields();
List<TargetMethod> methods();

View File

@ -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());
}

View File

@ -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;
}
/*

View File

@ -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);
}
}

View File

@ -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");