Compare commits
6 Commits
code-gener
...
Tests
Author | SHA1 | Date | |
---|---|---|---|
|
729f4f23d6 | ||
|
a1a9cce511 | ||
|
f7a4e65093 | ||
|
2934872457 | ||
|
1c327705d8 | ||
|
49195c754c |
19
readme.md
19
readme.md
@@ -43,10 +43,21 @@ src/
|
|||||||
└── resources/
|
└── resources/
|
||||||
test/
|
test/
|
||||||
└── java/
|
└── java/
|
||||||
│ ├── main/ -> MainTest, E2ETests, UtilityTests
|
│ ├── main/
|
||||||
│ ├── parser/ -> Performs tests on the parser
|
│ ├── parser/ -> Performs tests on the parser
|
||||||
│ └── semantic/ -> Performs tests on the semantic check
|
│ └── semantic/
|
||||||
└── resources/ -> Ressources for running the Tests
|
└── resources/ -> Ressources for running the Tests
|
||||||
|
├──input
|
||||||
|
│ ├── combinedFeatureTests
|
||||||
|
│ ├── endabgabeTests
|
||||||
|
│ ├── failureTests
|
||||||
|
│ ├── singleFeatureSemanticTests
|
||||||
|
│ ├── singleFeatureTests
|
||||||
|
│ ├── typedAstExceptionsTests
|
||||||
|
│ └── typedAstFeatureTests
|
||||||
|
└──output
|
||||||
|
├── javac
|
||||||
|
└── raupenpiler
|
||||||
```
|
```
|
||||||
|
|
||||||
## Class-Diagramm AST
|
## Class-Diagramm AST
|
||||||
@@ -62,7 +73,5 @@ test/
|
|||||||
|
|
||||||
|
|
||||||
## How to run the compiler
|
## How to run the compiler
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
```bash
|
```bash
|
@@ -7,7 +7,7 @@ import semantic.SemanticVisitor;
|
|||||||
import typechecker.TypeCheckResult;
|
import typechecker.TypeCheckResult;
|
||||||
import visitor.Visitable;
|
import visitor.Visitable;
|
||||||
|
|
||||||
public class DecrementNode implements IStatementExpressionNode, Visitable {
|
public class DecrementNode implements IStatementExpressionNode {
|
||||||
public CrementType crementType;
|
public CrementType crementType;
|
||||||
public AssignableNode assignableExpression;
|
public AssignableNode assignableExpression;
|
||||||
|
|
||||||
@@ -20,9 +20,4 @@ public class DecrementNode implements IStatementExpressionNode, Visitable {
|
|||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(MethodVisitor methodVisitor) {
|
|
||||||
methodVisitor.visit(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -5,9 +5,8 @@ import ast.statementexpressions.IStatementExpressionNode;
|
|||||||
import bytecode.visitor.MethodVisitor;
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import typechecker.TypeCheckResult;
|
import typechecker.TypeCheckResult;
|
||||||
import visitor.Visitable;
|
|
||||||
|
|
||||||
public class IncrementNode implements IStatementExpressionNode, Visitable {
|
public class IncrementNode implements IStatementExpressionNode {
|
||||||
public CrementType crementType;
|
public CrementType crementType;
|
||||||
public AssignableNode assignableExpression;
|
public AssignableNode assignableExpression;
|
||||||
|
|
||||||
@@ -20,9 +19,4 @@ public class IncrementNode implements IStatementExpressionNode, Visitable {
|
|||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(MethodVisitor methodVisitor) {
|
|
||||||
methodVisitor.visit(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,11 @@ public class ChainedMethodNode implements ASTNode, Visitable {
|
|||||||
expressions.add(expression);
|
expressions.add(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(MethodVisitor methodVisitor) {
|
||||||
|
methodVisitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return null;
|
return null;
|
||||||
|
@@ -27,7 +27,7 @@ public class ClassCodeGen implements ClassVisitor {
|
|||||||
private boolean generateClassFiles;
|
private boolean generateClassFiles;
|
||||||
|
|
||||||
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||||
this.mapper = new Mapper();
|
mapper = new Mapper();
|
||||||
this.jarOutputStream = jarOutputStream;
|
this.jarOutputStream = jarOutputStream;
|
||||||
this.outputDirectory = outputDirectory;
|
this.outputDirectory = outputDirectory;
|
||||||
this.generateJar = generateJar;
|
this.generateJar = generateJar;
|
||||||
|
@@ -3,7 +3,6 @@ package bytecode;
|
|||||||
import ast.parameters.ParameterNode;
|
import ast.parameters.ParameterNode;
|
||||||
import ast.type.*;
|
import ast.type.*;
|
||||||
import ast.type.type.BaseType;
|
import ast.type.type.BaseType;
|
||||||
import ast.type.type.ITypeNode;
|
|
||||||
import ast.type.type.ReferenceType;
|
import ast.type.type.ReferenceType;
|
||||||
import ast.type.type.TypeEnum;
|
import ast.type.type.TypeEnum;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -25,7 +24,7 @@ public class Mapper {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateMethodDescriptor(ITypeNode type, List<ParameterNode> parameters) {
|
public String generateMethodDescriptor(BaseType type, List<ParameterNode> parameters) {
|
||||||
String descriptor = "(";
|
String descriptor = "(";
|
||||||
for (ParameterNode parameterNode : parameters) {
|
for (ParameterNode parameterNode : parameters) {
|
||||||
if(parameterNode.type instanceof BaseType) {
|
if(parameterNode.type instanceof BaseType) {
|
||||||
@@ -36,11 +35,7 @@ public class Mapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor += ")";
|
descriptor += ")";
|
||||||
if(type instanceof BaseType) {
|
descriptor += getTypeChar(type);
|
||||||
descriptor += getTypeChar((BaseType) type);
|
|
||||||
} else if(type instanceof ReferenceType) {
|
|
||||||
descriptor += "L" + ((ReferenceType) type).getIdentifier() +";";
|
|
||||||
}
|
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,7 +14,9 @@ import ast.statementexpressions.NewDeclarationNode;
|
|||||||
import ast.statementexpressions.crementexpressions.CrementType;
|
import ast.statementexpressions.crementexpressions.CrementType;
|
||||||
import ast.statementexpressions.crementexpressions.DecrementNode;
|
import ast.statementexpressions.crementexpressions.DecrementNode;
|
||||||
import ast.statementexpressions.crementexpressions.IncrementNode;
|
import ast.statementexpressions.crementexpressions.IncrementNode;
|
||||||
|
import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode;
|
||||||
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
||||||
|
import ast.statementexpressions.methodcallstatementnexpressions.TargetNode;
|
||||||
import ast.statements.*;
|
import ast.statements.*;
|
||||||
import ast.type.ValueNode;
|
import ast.type.ValueNode;
|
||||||
import ast.type.type.BaseType;
|
import ast.type.type.BaseType;
|
||||||
@@ -69,7 +71,9 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
|
|
||||||
// Visit all statements
|
// Visit all statements
|
||||||
for (IStatementNode statementNode : constructorNode.block.statements) {
|
for (IStatementNode statementNode : constructorNode.block.statements) {
|
||||||
statementNode.accept(this);
|
if (statementNode != null) {
|
||||||
|
statementNode.accept(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
methodVisitor.visitMaxs(0, 0);
|
methodVisitor.visitMaxs(0, 0);
|
||||||
@@ -101,7 +105,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
public void visit(MethodNode methodNode) {
|
public void visit(MethodNode methodNode) {
|
||||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
||||||
methodNode.getIdentifier(),
|
methodNode.getIdentifier(),
|
||||||
mapper.generateMethodDescriptor(methodNode.getType(), methodNode.parameters),
|
mapper.generateMethodDescriptor((BaseType) methodNode.getType(), methodNode.parameters),
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
@@ -237,7 +241,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
nonCalculationNode.unaryExpression.accept(this);
|
nonCalculationNode.unaryExpression.accept(this);
|
||||||
nonCalculationNode.expression.accept(this);
|
nonCalculationNode.expression.accept(this);
|
||||||
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
||||||
methodVisitor.visitJumpInsn(IF_ICMPEQ, labelFalse);
|
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||||
} else {
|
} else {
|
||||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||||
}
|
}
|
||||||
@@ -262,17 +266,9 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(MemberAccessNode memberAccessNode) {
|
public void visit(MemberAccessNode memberAccessNode) {
|
||||||
// Only used to get, not to put
|
// Only used to get, not to put
|
||||||
int localVarIndex = localVariables.indexOf("memberAccessNode.identifier"); // TODO
|
if (memberAccessNode.thisExpr) { // Field
|
||||||
if (localVarIndex >= 0) { // local var object
|
// methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), );
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
} else { // Object Attribut
|
||||||
} else { // this field
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memberAccessNode.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), mapper.getTypeChar((BaseType) memberAccessNode.getTypeNode()));
|
|
||||||
} else if (memberAccessNode.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), "L" + ((ReferenceType) memberAccessNode.getTypeNode()).getIdentifier() + ";");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +331,6 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
// else if statements
|
// else if statements
|
||||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[0]);
|
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ifElseNode.ifStatement.block.accept(this); // accept if block
|
ifElseNode.ifStatement.block.accept(this); // accept if block
|
||||||
|
|
||||||
Label endLabel = new Label();
|
Label endLabel = new Label();
|
||||||
@@ -367,17 +362,22 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
if (localVariableDeclarationNode.expression != null) {
|
if (localVariableDeclarationNode.expression != null) {
|
||||||
// Process expression
|
// Process expression
|
||||||
localVariableDeclarationNode.expression.accept(this);
|
localVariableDeclarationNode.expression.accept(this);
|
||||||
// add local var to list if not in list
|
// Store result of expression in variable
|
||||||
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
if (localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||||
|
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||||
|
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||||
|
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
localVariables.add(localVariableDeclarationNode.identifier);
|
localVariables.add(localVariableDeclarationNode.identifier);
|
||||||
}
|
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Local var declaration
|
|
||||||
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||||
localVariables.add(localVariableDeclarationNode.identifier);
|
localVariables.add(localVariableDeclarationNode.identifier);
|
||||||
}
|
}
|
||||||
@@ -386,106 +386,40 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignNode assignNode) {
|
public void visit(AssignNode assignNode) {
|
||||||
if (assignNode.assignable.memberAccess != null) { // this / object
|
// Process expression
|
||||||
if (assignNode.expression instanceof IncrementNode) {
|
|
||||||
if (((IncrementNode) assignNode.expression).crementType.equals(CrementType.PREFIX)) { // ++i
|
|
||||||
fieldOrObjectVarPrefixCrementAssign(assignNode);
|
|
||||||
} else { // i++
|
|
||||||
fieldOrObjectVarSuffixCrementAssign(assignNode);
|
|
||||||
}
|
|
||||||
} else if (assignNode.expression instanceof DecrementNode) {
|
|
||||||
if (((DecrementNode) assignNode.expression).crementType.equals(CrementType.PREFIX)) {
|
|
||||||
fieldOrObjectVarPrefixCrementAssign(assignNode);
|
|
||||||
} else {
|
|
||||||
fieldOrObjectVarSuffixCrementAssign(assignNode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assignFieldOrObjectVar(assignNode);
|
|
||||||
}
|
|
||||||
} else { // local var
|
|
||||||
if (assignNode.expression instanceof IncrementNode || assignNode.expression instanceof DecrementNode) {
|
|
||||||
localVarCrementAssign(assignNode);
|
|
||||||
} else {
|
|
||||||
assignNode.expression.accept(this);
|
|
||||||
assignLocalVar(assignNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void localVarCrementAssign(AssignNode assignNode) {
|
|
||||||
if (assignNode.expression instanceof IncrementNode) {
|
if (assignNode.expression instanceof IncrementNode) {
|
||||||
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
||||||
if (incrementNode.crementType.equals(CrementType.PREFIX)) { // ++i
|
if (incrementNode.crementType.equals(CrementType.PREFIX)) { // ++i
|
||||||
incrementNode.accept(this);
|
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||||
assignLocalVar(assignNode);
|
assign(assignNode);
|
||||||
} else { // i++
|
} else if (incrementNode.crementType.equals(CrementType.SUFFIX)) { // Suffix: i++
|
||||||
loadBeforeCrement(assignNode);
|
assign(assignNode);
|
||||||
assignLocalVar(assignNode);
|
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||||
incrementNode.accept(this);
|
|
||||||
}
|
}
|
||||||
} else if (assignNode.expression instanceof DecrementNode) {
|
} else if (assignNode.expression instanceof DecrementNode) {
|
||||||
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
||||||
if (decrementNode.crementType.equals(CrementType.PREFIX)) {
|
if (decrementNode.crementType.equals(CrementType.PREFIX)) {
|
||||||
decrementNode.accept(this);
|
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||||
assignLocalVar(assignNode);
|
assign(assignNode);
|
||||||
} else {
|
} else if (decrementNode.crementType.equals(CrementType.SUFFIX)) {
|
||||||
loadBeforeCrement(assignNode);
|
assign(assignNode);
|
||||||
assignLocalVar(assignNode);
|
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), 1);
|
||||||
decrementNode.accept(this);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
assignNode.expression.accept(this);
|
||||||
|
assign(assignNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fieldOrObjectVarPrefixCrementAssign(AssignNode assignNode) {
|
private void assign(AssignNode assignNode) {
|
||||||
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
if (assignNode.assignable.memberAccess.thisExpr) {
|
||||||
if(localVarIndex >= 0) { // object
|
assignField(assignNode);
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
|
||||||
} else if(assignNode.assignable.memberAccess.thisExpr) { // field
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
|
||||||
} else {
|
} else {
|
||||||
localVariables.add(assignNode.assignable.identifier);
|
assignLocalVar(assignNode);
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assignNode.expression.accept(this);
|
|
||||||
methodVisitor.visitInsn(DUP_X1);
|
|
||||||
|
|
||||||
if (assignNode.expression instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
|
||||||
} else if (assignNode.expression instanceof ReferenceType) {
|
|
||||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fieldOrObjectVarSuffixCrementAssign(AssignNode assignNode) {
|
|
||||||
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
|
||||||
if(localVarIndex >= 0) { // object
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
|
||||||
} else if(assignNode.assignable.memberAccess.thisExpr) { // field
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
|
||||||
} else {
|
|
||||||
localVariables.add(assignNode.assignable.identifier);
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
loadBeforeCrement(assignNode);
|
|
||||||
|
|
||||||
if (assignNode.expression instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
|
||||||
} else if (assignNode.expression instanceof ReferenceType) {
|
|
||||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
assignNode.expression.accept(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignLocalVar(AssignNode assignNode) {
|
private void assignLocalVar(AssignNode assignNode) {
|
||||||
methodVisitor.visitInsn(DUP);
|
|
||||||
if (!localVariables.contains(assignNode.assignable.identifier)) {
|
|
||||||
localVariables.add(assignNode.assignable.identifier);
|
|
||||||
}
|
|
||||||
if (assignNode.expression instanceof BaseType) {
|
if (assignNode.expression instanceof BaseType) {
|
||||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
} else if (assignNode.expression instanceof ReferenceType) {
|
} else if (assignNode.expression instanceof ReferenceType) {
|
||||||
@@ -493,105 +427,12 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignFieldOrObjectVar(AssignNode assignNode) {
|
private void assignField(AssignNode assignNode) {
|
||||||
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
|
||||||
if (localVarIndex >= 0) { // object
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
|
||||||
} else if (assignNode.assignable.memberAccess.thisExpr) { // this
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
|
||||||
} else {
|
|
||||||
localVariables.add(assignNode.assignable.identifier);
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
assignNode.expression.accept(this);
|
|
||||||
methodVisitor.visitInsn(DUP_X1);
|
|
||||||
|
|
||||||
if (assignNode.expression instanceof BaseType) {
|
if (assignNode.expression instanceof BaseType) {
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||||
} else if (assignNode.expression instanceof ReferenceType) {
|
} else if (assignNode.expression instanceof ReferenceType) {
|
||||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L"+referenceType.getIdentifier()+";");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadBeforeCrement(AssignNode assignNode) {
|
|
||||||
if(assignNode.expression instanceof IncrementNode) {
|
|
||||||
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
|
||||||
if(incrementNode.assignableExpression.memberAccess != null) {
|
|
||||||
incrementNode.assignableExpression.memberAccess.accept(this);
|
|
||||||
} else {
|
|
||||||
if(assignNode.assignable.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
} else if(assignNode.assignable.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(assignNode.expression instanceof DecrementNode) {
|
|
||||||
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
|
||||||
if(decrementNode.assignableExpression.memberAccess != null) {
|
|
||||||
decrementNode.assignableExpression.memberAccess.accept(this);
|
|
||||||
} else {
|
|
||||||
if(assignNode.assignable.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
} else if(assignNode.assignable.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(IncrementNode incrementNode) {
|
|
||||||
if (incrementNode.assignableExpression.memberAccess != null) { // Object var / field
|
|
||||||
int localVarIndex = localVariables.indexOf(incrementNode.assignableExpression.identifier);
|
|
||||||
if (localVarIndex >= 0) { // object
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
|
||||||
} else { // this
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
|
||||||
}
|
|
||||||
if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(GETFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) incrementNode.assignableExpression.memberAccess.getTypeNode()));
|
|
||||||
} else if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitFieldInsn(GETFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) incrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
|
||||||
}
|
|
||||||
methodVisitor.visitInsn(DUP);
|
|
||||||
methodVisitor.visitInsn(ICONST_1);
|
|
||||||
methodVisitor.visitInsn(IADD);
|
|
||||||
if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) incrementNode.assignableExpression.memberAccess.getTypeNode()));
|
|
||||||
} else if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) incrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
|
||||||
}
|
|
||||||
} else { // local var
|
|
||||||
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(DecrementNode decrementNode) {
|
|
||||||
if (decrementNode.assignableExpression.memberAccess != null) { // Object var / field
|
|
||||||
int localVarIndex = localVariables.indexOf(decrementNode.assignableExpression.identifier);
|
|
||||||
if (localVarIndex >= 0) { // object
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
|
||||||
} else { // this
|
|
||||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
|
||||||
}
|
|
||||||
methodVisitor.visitInsn(DUP);
|
|
||||||
if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(GETFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) decrementNode.assignableExpression.memberAccess.getTypeNode()));
|
|
||||||
} else if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitFieldInsn(GETFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) decrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
|
||||||
}
|
|
||||||
methodVisitor.visitInsn(ICONST_1);
|
|
||||||
methodVisitor.visitInsn(ISUB);
|
|
||||||
if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) decrementNode.assignableExpression.memberAccess.getTypeNode()));
|
|
||||||
} else if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) decrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
|
||||||
}
|
|
||||||
} else { // local var
|
|
||||||
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,7 +445,8 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
expressionNode.accept(this);
|
expressionNode.accept(this);
|
||||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||||
}
|
}
|
||||||
methodVisitor.visitMethodInsn(INVOKESPECIAL, newDeclarationNode.identifier, "<init>", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID), parameterNodes), false);
|
methodVisitor.visitMethodInsn(INVOKESPECIAL, newDeclarationNode.identifier, "<init>", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID),parameterNodes), false);
|
||||||
|
localVariables.add(newDeclarationNode.identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -676,13 +518,19 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
methodVisitor.visitLabel(endOfLoopLabel);
|
methodVisitor.visitLabel(endOfLoopLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ChainedMethodNode chainedMethodNode) {
|
||||||
|
// TODO: Erstmal abwarten
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MethodCallNode methodCallNode) {
|
public void visit(MethodCallNode methodCallNode) {
|
||||||
List<ParameterNode> parameterNodes = new ArrayList<>();
|
List<ParameterNode> parameterNodes = new ArrayList<>();
|
||||||
for (IExpressionNode expressionNode : methodCallNode.parameters) {
|
for(IExpressionNode expressionNode : methodCallNode.parameters) {
|
||||||
expressionNode.accept(this);
|
expressionNode.accept(this);
|
||||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||||
}
|
}
|
||||||
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, methodCallNode.target.memberAccess.identifiers.get(0), methodCallNode.identifier, mapper.generateMethodDescriptor(methodCallNode.type, parameterNodes), false);
|
// TODO: Klassenname und Returntype
|
||||||
|
//methodVisitor.visitMethodInsn(INVOKEVIRTUAL, classname, methodCallNode.identifier, mapper.generateMethodDescriptor(returntype, parameterNodes), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,5 +5,6 @@ import ast.members.FieldNode;
|
|||||||
|
|
||||||
public interface ClassVisitor {
|
public interface ClassVisitor {
|
||||||
void visit(ClassNode classNode);
|
void visit(ClassNode classNode);
|
||||||
|
|
||||||
void visit(FieldNode fieldNode);
|
void visit(FieldNode fieldNode);
|
||||||
}
|
}
|
||||||
|
@@ -39,14 +39,12 @@ public interface MethodVisitor {
|
|||||||
// statements
|
// statements
|
||||||
void visit(IfElseNode ifElseNode);
|
void visit(IfElseNode ifElseNode);
|
||||||
|
|
||||||
void visit(IncrementNode incrementNode);
|
|
||||||
void visit(DecrementNode decrementNode);
|
|
||||||
|
|
||||||
void visit(LocalVariableDeclarationNode localVariableDeclarationNode);
|
void visit(LocalVariableDeclarationNode localVariableDeclarationNode);
|
||||||
void visit(ReturnNode returnNode);
|
void visit(ReturnNode returnNode);
|
||||||
void visit(WhileNode whileNode);
|
void visit(WhileNode whileNode);
|
||||||
|
|
||||||
// statement expression
|
// statement expression
|
||||||
|
void visit(ChainedMethodNode chainedMethodNode);
|
||||||
void visit(MethodCallNode methodCallNode);
|
void visit(MethodCallNode methodCallNode);
|
||||||
|
|
||||||
void visit(AssignNode assignNode);
|
void visit(AssignNode assignNode);
|
||||||
|
@@ -253,7 +253,6 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
|
|
||||||
if (toCheck.memberAccess != null) {
|
if (toCheck.memberAccess != null) {
|
||||||
var result = toCheck.memberAccess.accept(this);
|
var result = toCheck.memberAccess.accept(this);
|
||||||
toCheck.identifier = toCheck.memberAccess.identifiers.getLast();
|
|
||||||
toCheck.setTypeNode(result.getType());
|
toCheck.setTypeNode(result.getType());
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -317,13 +316,9 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(IfElseNode toCheck) {
|
public TypeCheckResult analyze(IfElseNode toCheck) {
|
||||||
var resultIf = toCheck.ifStatement.accept(this);
|
var resultIf = toCheck.ifStatement.accept(this);
|
||||||
if(toCheck.elseStatement != null){
|
var resultElse = toCheck.elseStatement.accept(this);
|
||||||
var resultElse = toCheck.elseStatement.accept(this);
|
|
||||||
return new TypeCheckResult(resultIf.isValid() && resultElse.isValid(), new BaseType(TypeEnum.VOID));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return new TypeCheckResult(resultIf.isValid() && resultElse.isValid(), new BaseType(TypeEnum.VOID));
|
||||||
return new TypeCheckResult(resultIf.isValid(), new BaseType(TypeEnum.VOID));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -609,15 +604,11 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
ITypeNode currentType = null;
|
ITypeNode currentType = null;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
if(!memberAccessNode.identifiers.isEmpty()){
|
if(!memberAccessNode.identifiers.isEmpty()){
|
||||||
if(currentFields.get(memberAccessNode.identifiers.getFirst()) != null){
|
if(currentFields.get(memberAccessNode.identifiers.get(0)) != null){
|
||||||
memberAccessNode.identifiers.addFirst(currentClass.identifier);
|
memberAccessNode.identifiers.add(0, currentClass.identifier);
|
||||||
start++;
|
start = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(context.getClasses().get(memberAccessNode.identifiers.getFirst()) == null){
|
|
||||||
memberAccessNode.identifiers.addFirst(currentClass.identifier);
|
|
||||||
start++;
|
|
||||||
}
|
|
||||||
for (int i = start; i < memberAccessNode.identifiers.size(); i++) {
|
for (int i = start; i < memberAccessNode.identifiers.size(); i++) {
|
||||||
|
|
||||||
String s = memberAccessNode.identifiers.get(i);
|
String s = memberAccessNode.identifiers.get(i);
|
||||||
@@ -635,8 +626,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
} else {
|
} else {
|
||||||
if (currentType instanceof ReferenceType reference) {
|
if (currentType instanceof ReferenceType reference) {
|
||||||
var currentTypeClass = context.getClass(reference.getIdentifier());
|
var currentTypeClass = context.getClass(reference.getIdentifier());
|
||||||
memberAccessNode.identifiers.add(i, reference.getIdentifier());
|
|
||||||
i++;
|
|
||||||
var currentField = currentTypeClass.getField(s);
|
var currentField = currentTypeClass.getField(s);
|
||||||
if (currentField.getAccessModifier().accessType == EnumAccessModifierNode.PUBLIC) {
|
if (currentField.getAccessModifier().accessType == EnumAccessModifierNode.PUBLIC) {
|
||||||
currentType = currentField.getType();
|
currentType = currentField.getType();
|
||||||
|
@@ -12,6 +12,12 @@ compile-raupenpiler:
|
|||||||
cd ../.. ; mvn exec:java -DgenJar=true -DgenClass=true -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output'"
|
cd ../.. ; mvn exec:java -DgenJar=true -DgenClass=true -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output'"
|
||||||
# cp ../main/resources/output/CompilerInput.class .java/resources/output/raupenpiler
|
# cp ../main/resources/output/CompilerInput.class .java/resources/output/raupenpiler
|
||||||
|
|
||||||
|
test: compile-javac compile-raupenpiler test-javac test-raupenpiler
|
||||||
|
|
||||||
|
test-javac:
|
||||||
|
# gleich wie bei raupenpiler, kann ich ohne funktionierenden Compiler nicht testen
|
||||||
|
|
||||||
|
|
||||||
test-raupenpiler:
|
test-raupenpiler:
|
||||||
# move the compiled class to the test/main folder
|
# move the compiled class to the test/main folder
|
||||||
mv ../main/resources/output/CompilerInput.class .java/main/
|
mv ../main/resources/output/CompilerInput.class .java/main/
|
||||||
|
@@ -88,7 +88,7 @@ public class E2EReflectionsTest {
|
|||||||
for (Field raupenpilerField : raupenpilerLoadedClassDeclaredFields) {
|
for (Field raupenpilerField : raupenpilerLoadedClassDeclaredFields) {
|
||||||
if (field.getName().equals(raupenpilerField.getName())) {
|
if (field.getName().equals(raupenpilerField.getName())) {
|
||||||
assertEquals(field.getType(), raupenpilerField.getType());
|
assertEquals(field.getType(), raupenpilerField.getType());
|
||||||
// assertEquals(field.getModifiers(), raupenpilerField.getModifiers());
|
// assertEquals(field.getModifiers(), raupenpilerField.getModifiers());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -338,17 +338,6 @@ public class EndToTypedAstTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void Expression(){
|
|
||||||
|
|
||||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/Expression.java");
|
|
||||||
|
|
||||||
SemanticAnalyzer.generateTast(tast);
|
|
||||||
|
|
||||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------ Helpers ------------------
|
// ------------------ Helpers ------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
class VariableCompare{
|
|
||||||
|
|
||||||
void trueMethod(boolean a, int c) {
|
|
||||||
if(a && c == 10){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -1,16 +1,13 @@
|
|||||||
public class Compiler {
|
public class Klasse1 {
|
||||||
Node node;
|
public int test;
|
||||||
public int add(int i, int j) {
|
|
||||||
node = new Node();
|
|
||||||
node.x = 1;
|
|
||||||
return i+j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Node {
|
public int test1() {
|
||||||
public int x;
|
test = 5;
|
||||||
public void main() {
|
return 1;
|
||||||
Compiler compiler = new Compiler();
|
}
|
||||||
int i = compiler.add(5, 8);
|
|
||||||
|
public void test2() {
|
||||||
|
int testInt;
|
||||||
|
testInt = this.test1();
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user