Compare commits

...

3 Commits

23 changed files with 150 additions and 46 deletions

Binary file not shown.

View File

@ -26,7 +26,8 @@ import java.lang.Boolean;
public class FunNClass extends ClassOrInterface {
public FunNClass(List<GenericRefType> funNParams) {
JavaClassName a = new JavaClassName("Fun" + (funNParams.size() - 1);
String a_param = "Fun" + (funNParams.size() - 1);
JavaClassName a = new JavaClassName(a_param);
super(0, a, new ArrayList<>(), Optional.empty(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, false, new ArrayList<>(), new ArrayList<>(), new NullToken());
}

View File

@ -1,7 +1,7 @@
JFLAGS = -g:none
JC = javac
JTX = JavaTXcompiler-0.4-jar-with-dependencies.jar
JTX = JavaTXcompiler-0.5-jar-with-dependencies.jar
SRCDIR = javatx-src/main/java
DESTDIR = out
@ -14,22 +14,19 @@ JAVSOURCES := $(shell find $(SRCDIR) -name '*.jav')
JAVACLASSES := $(patsubst $(SRCDIR)/%.java,$(DESTDIR)/%.class,$(JAVASOURCES))
JAVCLASSES := $(patsubst $(SRCDIR)/%.jav,$(DESTDIR)/%.class,$(JAVSOURCES))
# Create a list of directories that need to be created in the destination directory
DIRS := $(sort $(dir $(JAVACLASSES))) $(sort $(dir $(JAVCLASSES)))
default: classes
# Rule for creating directories
#$(DIRS):
# @mkdir -p $@
$(DESTDIR):
mkdir -p $(DESTDIR)
# Rule for creating directories
# Rule for compiling .jav files
$(DESTDIR)/%.class: $(SRCDIR)/%.jav #| $(DIRS)
$(DESTDIR)/%.class: $(SRCDIR)/%.jav | $(DESTDIR)
java -jar $(JTX) -d "$(dir $@)" -cp "src/main/java:out:target/dependencies/" $<
# Rule for compiling .java files
$(DESTDIR)/%.class: $(SRCDIR)/%.java #| $(DIRS)
$(DESTDIR)/%.class: $(SRCDIR)/%.java | $(DESTDIR)
$(JC) -nowarn -d "$(dir $@)" -cp "src/main/java:out:target/dependencies/*" $(JFLAGS) $<

View File

@ -806,6 +806,7 @@ public class Codegen {
case StringLiteral stringLiteral -> mv.visitLdcInsn(stringLiteral.value());
case CharLiteral charLiteral -> mv.visitIntInsn(BIPUSH, charLiteral.value());
case DoubleLiteral doubleLiteral -> mv.visitLdcInsn(doubleLiteral.value());
case Null ignored -> mv.visitInsn(ACONST_NULL);
case BooleanLiteral booleanLiteral -> {
if (booleanLiteral.value()) {
mv.visitInsn(ICONST_1);
@ -1040,6 +1041,11 @@ public class Codegen {
mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "<init>", _new.getDescriptor(), false);
break;
}
case TargetThrow _throw: {
generate(state, _throw.expr());
mv.visitInsn(ATHROW);
break;
}
default:
throw new CodeGenException("Unexpected value: " + expr);
}

View File

@ -648,7 +648,7 @@ public class JavaTXCompiler {
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
private SourceFile parse(File sourceFile) throws IOException, ClassNotFoundException {
SourceFileContext tree = JavaTXParser.parse(sourceFile);
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));

View File

@ -11,11 +11,11 @@ import java.util.List;
import java.util.stream.Collectors;
public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader {
public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
public DirectoryClassLoader(File directory, ClassLoader parent) {
super(generateURLArray(dirToURL(directory)), parent);
}
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
public DirectoryClassLoader(List<File> directory, ClassLoader parent) {
super(directory.stream().map(DirectoryClassLoader::dirToURL).collect(Collectors.toList()).toArray(new URL[0]), parent);
}

View File

@ -17,7 +17,7 @@ import java.util.ArrayList;
import java.util.List;
public class JavaTXParser {
public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException {
public static Java17Parser.SourceFileContext parse(File source) throws IOException, ClassNotFoundException {
InputStream stream = new FileInputStream(source);
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);
CharStream input = CharStreams.fromStream(stream);

View File

@ -611,8 +611,7 @@ public class StatementGenerator {
}
private Statement convert(Java17Parser.ThrowstmtContext stmt) {
// TODO
throw new NotImplementedException();
return new Throw(convert(stmt.expression()), stmt.getStart());
}
private Statement convert(Java17Parser.SynchronizedstmtContext stmt) {
@ -1033,8 +1032,7 @@ public class StatementGenerator {
switch (literal) {
case IntLiteralContext intliteral:
Number value = Integer.parseInt(intliteral.getText());
Literal a = new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
return a;
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
case FltLiteralContext floatliteral:
value = Double.parseDouble(floatliteral.getText());
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, floatliteral.getStart());
@ -1043,7 +1041,6 @@ public class StatementGenerator {
return new Literal(type, charliteral.getText().charAt(1), charliteral.getStart());
case StringLiteralContext stringliteral:
type = new RefType(reg.getName("java.lang.String"), stringliteral.getStart());
Literal b = new Literal(type, stringliteral.getText().substring(1, stringliteral.getText().length() - 1), stringliteral.getStart());
return new Literal(type, stringliteral.getText().substring(1, stringliteral.getText().length() - 1), stringliteral.getStart());
case BoolLiteralContext boolliteral:
type = new RefType(reg.getName("java.lang.Boolean"), boolliteral.getStart());

View File

@ -230,7 +230,7 @@ public class SyntaxTreeGenerator {
}
private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
private 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;

View File

@ -68,7 +68,7 @@ public class TypeGenerator {
case "double":
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
default:
throw new NotImplementedException("only primitive types boolean, int and double are supported");
throw new NotImplementedException();
}
} else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen
// System.out.println(unannTypeContext.getText());

View File

@ -266,6 +266,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
}
@Override
public void visit(Throw aThrow) {
}
@Override
public void visit(AssignToField assignLeftSide) {
assignLeftSide.field.accept(this);

View File

@ -76,4 +76,6 @@ public interface StatementVisitor {
void visit(UnaryExpr unaryExpr);
void visit(Literal literal);
void visit(Throw aThrow);
}

View File

@ -31,9 +31,9 @@ import org.objectweb.asm.signature.SignatureVisitor;
*/
public class ASTFactory {
private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>();
private static final HashMap<Class, ClassOrInterface> cache = new HashMap<>();
public static ClassOrInterface createClass(java.lang.Class jreClass) {
public static ClassOrInterface createClass(Class jreClass) {
if (cache.containsKey(jreClass))
return cache.get(jreClass);
@ -91,7 +91,7 @@ public class ASTFactory {
JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = new ArrayList<>();
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
for (java.lang.reflect.Constructor constructor : jreClass.getConstructors()) {
for (Constructor constructor : jreClass.getConstructors()) {
var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor)));
createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c));
}
@ -124,14 +124,14 @@ public class ASTFactory {
Type tempSuperClass = jreClass.getGenericSuperclass();
if (tempSuperClass != null && tempSuperClass instanceof ParameterizedType)
parameterSuperClass = (ParameterizedType) tempSuperClass;
java.lang.Class superjreClass = jreClass.getSuperclass();
Class superjreClass = jreClass.getSuperclass();
RefType superClass;
if (parameterSuperClass != null) {
superClass = (RefType) createType(parameterSuperClass);
} else if (superjreClass != null) {
superClass = (RefType) createType(superjreClass);
} else {// Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!)
superClass = (RefType) createType(java.lang.Object.class);
superClass = (RefType) createType(Object.class);
}
List<RefType> implementedInterfaces = new ArrayList<>();
for (Type jreInterface : jreClass.getGenericInterfaces()) {
@ -181,14 +181,14 @@ public class ASTFactory {
Token offset = new NullToken();
int modifier = constructor.getModifiers();
if (inClass.equals(java.lang.Object.class)) {
if (inClass.equals(Object.class)) {
return Optional.empty();
}
return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */));
}
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited) {
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, Class inClass, Boolean isInherited) {
String name = jreMethod.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType;
@ -219,9 +219,9 @@ public class ASTFactory {
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
if (signature == null) {
List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
List<GenericTypeVar> gtvs = new ArrayList<>();
for (TypeVariable jreTV : typeParameters) {
de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
gtvs.add(gtv);
}
return new GenericDeclarationList(gtvs, new NullToken());
@ -351,7 +351,7 @@ public class ASTFactory {
return new GenericDeclarationList(gtvs, new NullToken());
}
private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type) {
private static RefTypeOrTPHOrWildcardOrGeneric createType(Type type) {
if (type == null || type.getTypeName().equals("void")) {
return new Void(new NullToken());
} else if (type.getTypeName().equals("int")) {
@ -400,16 +400,16 @@ public class ASTFactory {
}
}
public static de.dhbwstuttgart.syntaxtree.GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod) {
public static GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod) {
JavaClassName parentClass = new JavaClassName(context.getName());
List<RefTypeOrTPHOrWildcardOrGeneric> genericBounds = new ArrayList<>();
java.lang.reflect.Type[] bounds = jreTypeVar.getBounds();
Type[] bounds = jreTypeVar.getBounds();
if (bounds.length > 0) {
for (java.lang.reflect.Type bound : bounds) {
for (Type bound : bounds) {
genericBounds.add(createType(bound));
}
}
return new de.dhbwstuttgart.syntaxtree.GenericTypeVar(jreTVName, genericBounds, new NullToken(), new NullToken());
return new GenericTypeVar(jreTVName, genericBounds, new NullToken(), new NullToken());
}
public static ClassOrInterface createObjectClass() {

View File

@ -0,0 +1,21 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token;
public class Throw extends Statement {
public final Expression expr;
public Throw(Expression expr, Token offset) {
super(new Void(offset), offset);
this.expr = expr;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -403,10 +403,15 @@ public class OutputGenerator implements ASTVisitor {
}
@Override
public void visit(de.dhbwstuttgart.syntaxtree.statement.Literal literal) {
public void visit(Literal literal) {
out.append(literal.value);
}
@Override
public void visit(Throw aThrow) {
// TODO implement
}
@Override
public void visit(Switch switchStmt) {
out.append("switch(");

View File

@ -265,7 +265,7 @@ public abstract class GenerateGenerics {
if (method.block != null)
method.block.accept(new TracingStatementVisitor() {
private RefTypeOrTPHOrWildcardOrGeneric superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
private RefTypeOrTPHOrWildcardOrGeneric superType = new Void(new NullToken());
@Override
public void visit(MethodCall methodCall) {
@ -372,7 +372,7 @@ public abstract class GenerateGenerics {
@Override
public void visit(Block block) {
for (var expr : block.statements) {
superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
superType = new Void(new NullToken());
expr.accept(this);
}
}

View File

@ -320,9 +320,16 @@ public class StatementToTargetExpression implements ASTVisitor {
result = new TargetLiteral.StringLiteral((String) literal.value);
} else if (literal.value instanceof Boolean) {
result = new TargetLiteral.BooleanLiteral((boolean) literal.value);
} else if (literal.value == null) {
result = new TargetLiteral.Null();
}
}
@Override
public void visit(Throw aThrow) {
result = new TargetThrow(converter.convert(aThrow.expr));
}
@Override
public void visit(Switch switchStmt) {
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();
@ -370,7 +377,7 @@ public class StatementToTargetExpression implements ASTVisitor {
}
@Override
public void visit(de.dhbwstuttgart.syntaxtree.Method field) {
public void visit(Method field) {
}

View File

@ -173,6 +173,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
}
@Override
public void visit(Throw aThrow) {
}
@Override
public void visit(Switch switchStmt) {

View File

@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.*;
public sealed interface TargetExpression
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetPattern, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
default TargetType type() {
return null;

View File

@ -53,4 +53,16 @@ public sealed interface TargetLiteral extends TargetExpression {
return TargetType.String;
}
}
record Null() implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Object;
}
@Override
public Object value() {
return null;
}
}
}

View File

@ -0,0 +1,4 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetThrow(TargetExpression expr) implements TargetExpression {
}

View File

@ -130,7 +130,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(ForEachStmt forEachStmt) {
var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(forEachStmt.statement.getType()), new NullToken());
var iterableType = new RefType(ASTFactory.createClass(Iterable.class).getClassName(), Arrays.asList(forEachStmt.statement.getType()), new NullToken());
constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT));
forEachStmt.statement.accept(this);
forEachStmt.expression.accept(this);
@ -139,7 +139,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(IfStmt ifStmt) {
RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken());
RefType booleanType = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken());
// Expression inferieren:
ifStmt.expr.accept(this);
// Expression muss boolean sein:
@ -451,11 +451,17 @@ public class TYPEStmt implements StatementVisitor {
if (literal.value instanceof Boolean) {
constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT));
return;
} else {
}
if (literal.value != null) {
throw new NotImplementedException();
}
}
@Override
public void visit(Throw aThrow) {
aThrow.expr.accept(this);
}
@Override
public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this);
@ -510,7 +516,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(WhileStmt whileStmt) {
RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken());
RefType booleanType = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken());
// Expression inferieren:
whileStmt.expr.accept(this);
// Expression muss boolean sein:
@ -542,7 +548,9 @@ public class TYPEStmt implements StatementVisitor {
for (var clazz : info.getAvailableClasses()) {
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) {
for (var ctor : clazz.getConstructors()) {
var assumption = new MethodAssumption(null, new Void(new NullToken()), convertParams(ctor.getParameterList(), info), createTypeScope(clazz, ctor), ctor.isInherited);
var params = convertParams(ctor.getParameterList(), info);
if (params.size() != superCall.arglist.getArguments().size()) continue;
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);

View File

@ -1,9 +1,9 @@
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import org.junit.Ignore;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
@ -799,4 +799,38 @@ public class TestComplete {
assertTrue((Boolean) clazz.getDeclaredMethod("test2").invoke(instance));
assertFalse((Boolean) clazz.getDeclaredMethod("test3").invoke(instance));
}
@Test
public void testExceptions() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Exceptions.jav");
var clazz = classFiles.get("Exceptions");
var instance = clazz.getDeclaredConstructor().newInstance();
try {
clazz.getDeclaredMethod("m").invoke(instance);
fail("No exception thrown!");
} catch (InvocationTargetException exception) {
var exc = exception.getTargetException();
if (!(exc instanceof RuntimeException rexp) || !rexp.getMessage().equals("Some Exception")) {
fail("Wrong exception thrown!");
}
}
}
@Test
public void testLiteral() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Literal.jav");
var clazz = classFiles.get("Literal");
var instance = clazz.getDeclaredConstructor().newInstance();
assertNull(clazz.getDeclaredMethod("m").invoke(instance));
}
@Test
public void testOLConstructor() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OLConstructor.jav");
var clazz = classFiles.get("Child");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getSuperclass().getDeclaredField("x").get(instance), 3);
}
}