More work on static, references to other classes

This commit is contained in:
Daniel Holle 2023-10-24 15:17:13 +02:00
parent 124dea2e58
commit b372c6ac1c
10 changed files with 53 additions and 41 deletions

View File

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

View File

@ -1296,9 +1296,7 @@ public class Codegen {
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));
generate(state, constructor.block());
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);

View File

@ -70,8 +70,6 @@ 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();
@ -106,20 +104,22 @@ public class JavaTXCompiler {
classPath = contextPath;
for (File s : sources) {
addSourceFile(s, parse(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);
for (var sf : sourceFiles.values()) {
for (var clazz : sf.KlassenVektor) {
if (clazz.getClassName().equals(name)) return clazz;
}
}
return null;
}
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
@ -645,8 +645,12 @@ public class JavaTXCompiler {
SourceFileContext tree = JavaTXParser.parse(sourceFile);
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
SourceFile ret = generator.convert(tree, environment.packageCrawler);
return ret;
var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
addSourceFile(sourceFile, sf);
generator.convert(classes, tree, environment.packageCrawler);
sf.imports.addAll(generator.imports);
return sf;
}
/**
@ -655,10 +659,6 @@ public class JavaTXCompiler {
* @param name
*/
public boolean loadJavaTXClass(JavaClassName name) {
if (classRegistry.contains(name.getClassName())) {
return true;
}
var file = findFileForClass(name);
if (file != null) {
try {
@ -666,7 +666,10 @@ public class JavaTXCompiler {
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(this, classRegistry, new GenericsRegistry(null));
addSourceFile(file, generator.convert(tree, environment.packageCrawler));
var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
addSourceFile(file, sf);
generator.convert(classes, tree, environment.packageCrawler);
return true;
} catch (Exception e) {
throw new RuntimeException(e);

View File

@ -808,7 +808,8 @@ public class StatementGenerator {
receiver = generateLocalOrFieldVarOrClassName(part, offset);
} else {
StaticClassName cname = (StaticClassName) receiver;
isStatic = Modifier.isStatic(compiler.getClass(reg.getName(cname.getType().toString())).getField(fieldName).orElseThrow().modifier);
var javaClassName = reg.getName(cname.getType().toString());
isStatic = Modifier.isStatic(compiler.getClass(javaClassName).getField(fieldName).orElseThrow().modifier);
}
return new FieldVar(receiver, isStatic, fieldName, TypePlaceholder.fresh(offset), offset);
}

View File

@ -87,8 +87,8 @@ import javax.swing.text.html.Option;
public class SyntaxTreeGenerator {
private JavaClassRegistry reg;
private final GenericsRegistry globalGenerics;
private String pkgName = "";
Set<JavaClassName> imports = new HashSet<>();
public String pkgName = "";
public Set<JavaClassName> imports = new HashSet<>();
HashMap<String, Integer> allmodifiers = new HashMap<>();
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
// bekommen
@ -138,13 +138,12 @@ public class SyntaxTreeGenerator {
return ctx.getText();
}
public SourceFile convert(Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException, NotImplementedException {
public void convert(List<ClassOrInterface> classes, Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException, NotImplementedException {
SrcfileContext srcfile;
List<ClassOrInterface> classes = new ArrayList<>();
if (ctx instanceof Java17Parser.SrcfileContext) {
srcfile = (SrcfileContext) ctx;
} else {
return new SourceFile(this.pkgName, classes, this.imports);
return;
}
if (srcfile.packageDeclaration() != null)
this.pkgName = convert(srcfile.packageDeclaration());
@ -165,6 +164,7 @@ public class SyntaxTreeGenerator {
}
}
fieldInitializations = new ArrayList<>(); // PL 2019-10-22: muss für jede Klasse neu initilisiert werden
staticFieldInitializations = new ArrayList<>();
if (!Objects.isNull(clsoif.classDeclaration())) {
newClass = convertClass(clsoif.classDeclaration(), modifiers);
} else if (!Objects.isNull(clsoif.interfaceDeclaration())) {
@ -176,9 +176,7 @@ public class SyntaxTreeGenerator {
}
classes.add(newClass);
}
if (classes.size() > 0) {
return new SourceFile(this.pkgName, classes, this.imports);
} else {
if (classes.isEmpty()) {
throw new NotImplementedException("SourceFile enthält keine Klassen");
}
}
@ -234,7 +232,7 @@ public class SyntaxTreeGenerator {
}
}
var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset));
var staticCtor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
}
@ -290,7 +288,7 @@ public class SyntaxTreeGenerator {
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
}
var staticCtor = Optional.of(this.generatePseudoConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
}
@ -409,7 +407,7 @@ public class SyntaxTreeGenerator {
}
}
var staticCtor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
var staticCtor = Optional.of(this.generateStaticConstructor(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());
}
@ -475,6 +473,13 @@ public class SyntaxTreeGenerator {
*/);
}
private Method generateStaticConstructor(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<>(initializations), offset);
return new Method(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset);
}
private RefType convertSuperType(Java17Parser.TypeTypeContext typeType) {
ClassOrInterfaceTypeContext supertypecontext = typeType.classOrInterfaceType();
if (supertypecontext != null && supertypecontext.DOT().size() > 0) {
@ -606,8 +611,9 @@ public class SyntaxTreeGenerator {
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)
if (isStatic) {
staticFieldInitializations.add(assignment);
}
else fieldInitializations.add(assignment);
}

View File

@ -23,7 +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 Optional<Method> staticInitializer;
private List<Method> methods = new ArrayList<>();
private GenericDeclarationList genericClassParameters;
private RefType superClass;
@ -32,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, Optional<Constructor> staticInitializer, 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<Method> 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;
@ -74,7 +74,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
return fields.stream().filter(field -> field.getName().equals(name)).findFirst();
}
public Optional<Constructor> getStaticInitializer() {
public Optional<Method> getStaticInitializer() {
return staticInitializer;
}

View File

@ -13,7 +13,7 @@ import javax.swing.text.html.Option;
public class Record extends ClassOrInterface {
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) {
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> 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

@ -21,11 +21,11 @@ public class SourceFile extends SyntaxTreeNode {
*/
public SourceFile(String pkgName, List<ClassOrInterface> classDefinitions, Set<JavaClassName> imports) {
super(new NullToken());
if (classDefinitions.size() > 0) { // Enthält die Liste Klassen?
//if (classDefinitions.size() > 0) { // Enthält die Liste Klassen?
this.KlassenVektor = classDefinitions; // Klassen werden übernommen
} else {
this.KlassenVektor = null; // es handelt sich um ein "Java Module"
}
//} else {
// this.KlassenVektor = null; // es handelt sich um ein "Java Module"
//}
this.pkgName = pkgName;
this.imports = imports;
}

View File

@ -46,7 +46,7 @@ public class TYPE {
ret.addAll(getConstraintsConstructor(cl.getfieldInitializations().get(), info, cl));
}
if (cl.getStaticInitializer().isPresent()) {
ret.addAll(getConstraintsConstructor(cl.getStaticInitializer().get(), info, cl));
ret.addAll(getConstraintsMethod(cl.getStaticInitializer().get(), info, cl));
}
return ret;

View File

@ -345,7 +345,7 @@ public class TYPEStmt implements StatementVisitor {
}
}
if (numericAdditionOrStringConcatenation.size() < 1) {
throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset());
throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset());
}
constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation);
} else if (binary.operation.equals(BinaryExpr.Operator.LESSEQUAL) || binary.operation.equals(BinaryExpr.Operator.BIGGEREQUAL) || binary.operation.equals(BinaryExpr.Operator.BIGGERTHAN) || binary.operation.equals(BinaryExpr.Operator.LESSTHAN)) {