Compare commits
48 Commits
5d75c23f49
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22d925810f | ||
|
|
b4f59ce5c3 | ||
|
|
5239e608bc | ||
|
|
079668b9f8 | ||
|
|
58f6dc74e4 | ||
|
|
88ce2a985c | ||
|
|
a2fa6f55d4 | ||
|
|
8d4e8a9269 | ||
| c2c0c0b442 | |||
|
|
ec400479bb | ||
| 167b8e80b5 | |||
|
|
0baac36f35 | ||
|
|
da53e5d6dc | ||
|
|
0593d988b4 | ||
|
|
8e55eaca93 | ||
|
|
31ac237ffd | ||
|
|
e56139080f | ||
|
|
f807721293 | ||
|
|
271bbf4b4b | ||
|
|
5b4d08ba01 | ||
|
|
3b5f157bb5 | ||
|
|
59183f5b44 | ||
|
|
302b907d36 | ||
|
|
32353b9a37 | ||
|
|
3e908293ee | ||
|
|
aed7af7c68 | ||
|
|
3a8b9ea9cd | ||
|
|
aa8a647fa1 | ||
|
|
51240806b9 | ||
|
|
8f55a15aef | ||
| edfaa93980 | |||
|
|
4b36453ff3 | ||
|
|
78d6d402a2 | ||
|
|
0533ddbc5d | ||
|
|
920fa2fa48 | ||
|
|
dbb61e2a81 | ||
|
|
7fb7cea2f7 | ||
|
|
7e8c297d9a | ||
|
|
c9ce9e02db | ||
|
|
4dfea0d69d | ||
|
|
e801717444 | ||
|
|
6a56f51050 | ||
| 403b31c550 | |||
|
|
82384886c6 | ||
|
|
1dd405a00f | ||
| 6948797001 | |||
|
|
d7016df1ba | ||
|
|
384a5e9066 |
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -24,7 +24,11 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<component name="PWA">
|
||||
<option name="enabled" value="true" />
|
||||
<option name="wasEnabledAtLeastOnce" value="true" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/target" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
Binary file not shown.
BIN
ClassOne.class
BIN
ClassOne.class
Binary file not shown.
BIN
ClassTwo.class
BIN
ClassTwo.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
DivMethod.class
BIN
DivMethod.class
Binary file not shown.
BIN
Documentation/DokumentationNichtHaskell.pdf
Normal file
BIN
Documentation/DokumentationNichtHaskell.pdf
Normal file
Binary file not shown.
BIN
Documentation/KlassendiagrammFields.jpg
Normal file
BIN
Documentation/KlassendiagrammFields.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 766 KiB |
BIN
Documentation/KlassendiagrammUML.jpg
Normal file
BIN
Documentation/KlassendiagrammUML.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
BIN
Documentation/PraesentationNichtHaskell.pdf
Normal file
BIN
Documentation/PraesentationNichtHaskell.pdf
Normal file
Binary file not shown.
20
Examples/Fakultaet.java
Normal file
20
Examples/Fakultaet.java
Normal file
@@ -0,0 +1,20 @@
|
||||
class Fakultaet {
|
||||
public int fak(int number) {
|
||||
if (number < 0) {
|
||||
return 1;
|
||||
}
|
||||
int factorial = 1;
|
||||
int i = 1;
|
||||
while(i <= number){
|
||||
factorial = factorial * i;
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
return factorial;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
Fakultaet f = new Fakultaet();
|
||||
int result = f.fak(5);
|
||||
print(result);
|
||||
}
|
||||
}
|
||||
40
Examples/FieldAccessAndMethodCalls.java
Normal file
40
Examples/FieldAccessAndMethodCalls.java
Normal file
@@ -0,0 +1,40 @@
|
||||
class FieldAccessAndMethodCalls {
|
||||
public static void main(String[] args) {
|
||||
Class1 c1 = new Class1();
|
||||
int i = c1.c2.c3.m3(1).m2().m1();
|
||||
print(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Class1{
|
||||
int i1;
|
||||
Class2 c2;
|
||||
public Class1() {
|
||||
this.c2 = new Class2();
|
||||
}
|
||||
public int m1(){
|
||||
return i1;
|
||||
}
|
||||
}
|
||||
|
||||
class Class2{
|
||||
int i2;
|
||||
Class3 c3;
|
||||
public Class2(){
|
||||
this.c3 = new Class3();
|
||||
}
|
||||
public Class1 m2(){
|
||||
Class1 c1 = new Class1();
|
||||
c1.i1 = i2;
|
||||
return c1;
|
||||
}
|
||||
}
|
||||
|
||||
class Class3{
|
||||
int i3;
|
||||
public Class2 m3(int i){
|
||||
Class2 c2 = new Class2();
|
||||
c2.i2 = i;
|
||||
return c2;
|
||||
}
|
||||
}
|
||||
BIN
Fakultaet.class
BIN
Fakultaet.class
Binary file not shown.
BIN
FieldVar.class
BIN
FieldVar.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
166
Grammatik.txt
166
Grammatik.txt
@@ -1,166 +0,0 @@
|
||||
Grammatik:
|
||||
|
||||
1. Ausdrücke
|
||||
|
||||
Primary:
|
||||
Literal
|
||||
Variable
|
||||
IncDecExpression
|
||||
( Expression )
|
||||
MethodInvocation
|
||||
|
||||
Variable:
|
||||
Identifier { [ Expression ] }
|
||||
|
||||
Identifier:
|
||||
[ Identifier . ] Name
|
||||
|
||||
IncDecExpression:
|
||||
Variable IncDec
|
||||
IncDec Variable
|
||||
|
||||
IncDec:
|
||||
++ | --
|
||||
|
||||
Expression:
|
||||
UnaryExpression
|
||||
BinaryExpression
|
||||
AssignmentExpression
|
||||
MethodInvocation
|
||||
CreationExpression
|
||||
|
||||
UnaryExpression:
|
||||
Primary
|
||||
UnaryExpression
|
||||
UnaryOperator
|
||||
+ | - | ! | ...
|
||||
|
||||
BinaryExpression:
|
||||
Expression BinaryOperator Expression
|
||||
|
||||
BinaryOperator:
|
||||
== | + | - | * | / | & | && | | | || |
|
||||
|
||||
|
||||
AssignmentExpression:
|
||||
Variable = Expression
|
||||
|
||||
MethodInvocation:
|
||||
Method ( [ ActualArguments ] )
|
||||
|
||||
Method:
|
||||
Identifier
|
||||
|
||||
ActualArguments:
|
||||
Expression { , Expression }
|
||||
|
||||
CreationExpression:
|
||||
new ClassIdentifier ( [ ActualArguments ] )
|
||||
|
||||
|
||||
|
||||
2. Anweisungen
|
||||
|
||||
Statement:
|
||||
SimpleStatement
|
||||
CompositeStatement
|
||||
Label : Statement
|
||||
|
||||
SimpleStatement:
|
||||
EmptyStatement
|
||||
StatementExpression
|
||||
EmptyStatement ;
|
||||
ReturnStatement
|
||||
|
||||
StatementExpression:
|
||||
AssignmentExpression
|
||||
IncDecExpression
|
||||
MethodInvocation
|
||||
CreationExpression
|
||||
|
||||
ContinueStatement:
|
||||
continue [ Name ] ;
|
||||
|
||||
ReturnStatement.
|
||||
return [ Expression ] ;
|
||||
|
||||
|
||||
CompositeStatement:
|
||||
Block
|
||||
CaseStatement
|
||||
|
||||
Block:
|
||||
"{" { VariableDeclaration | Statement } "}"
|
||||
|
||||
VariableDeclaration:
|
||||
Type VariableDeclarator ;
|
||||
|
||||
VariableDeclarator:
|
||||
Name [ = Expression ]
|
||||
|
||||
Type:
|
||||
Name # konkrete Typen hinzufügen
|
||||
Identifier
|
||||
|
||||
CaseStatement: # Andere CaseStatements heraussuchen. Assign, MethodCall,
|
||||
ConditionalStatement
|
||||
WhileStatement
|
||||
|
||||
|
||||
ConditionalStatement:
|
||||
if ( Expression ) Statement [ else Statement ]
|
||||
|
||||
ConstantExpression:
|
||||
Expression
|
||||
|
||||
WhileStatement:
|
||||
while ( Expression ) Statement
|
||||
|
||||
Initialization:
|
||||
StatementExpression { , StatementExpression }
|
||||
VariableDeclaration
|
||||
|
||||
|
||||
3. Methoden
|
||||
|
||||
MethodDeclaration:
|
||||
MethodHeader Block
|
||||
|
||||
MethodHeader:
|
||||
{ Modifier } ResultType MethodDeclarator
|
||||
|
||||
Modifier:
|
||||
public | static | ...
|
||||
|
||||
ResultType:
|
||||
Type | void
|
||||
|
||||
MethodDeclarator:
|
||||
Identifier "(" [ FormalArguments ] ")"
|
||||
|
||||
FormalArguments:
|
||||
FormalArgument { , FormalArgument }
|
||||
|
||||
FormalArgument:
|
||||
Type Name
|
||||
|
||||
|
||||
|
||||
4. Klassen
|
||||
|
||||
Start:
|
||||
ClassDeclaration {ClassDeclaration}
|
||||
|
||||
ClassDeclaration:
|
||||
[ public ] class Name ClassBody
|
||||
|
||||
ClassBody:
|
||||
"{" { { Modifier } Declaration } "}"
|
||||
|
||||
Declaration:
|
||||
VariableDeclaration
|
||||
MethodDeclaration
|
||||
ConstructorDeclaration
|
||||
|
||||
ConstructorDeclaration:
|
||||
[ public ] Name ( [ FormalArguments ] ) Block
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="AdditionalModuleElements">
|
||||
<content url="file://$MODULE_DIR$" dumb="true">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
</component>
|
||||
</module>
|
||||
@@ -1 +1,3 @@
|
||||
Please move your stuff from "Source" to "src".
|
||||
Dies ist das Repository des Mini-Java-Compiler-Bauprojekt der Gruppe NichtHaskell für das 4. Semester Informatik der Dualen Hochschule Baden-Württemberg in Stuttgart (Horb).
|
||||
|
||||
Alles weitere ist in der Dokumentation DokumentationNichtHaskell.pdf unter `/Documentation/DokumentationNichtHaskell.pdf` zu finden.
|
||||
Binary file not shown.
BIN
emptyClass.class
BIN
emptyClass.class
Binary file not shown.
BIN
getI.class
BIN
getI.class
Binary file not shown.
BIN
jar/NichtHaskell.jar
Normal file
BIN
jar/NichtHaskell.jar
Normal file
Binary file not shown.
BIN
jar/NichtHaskellCompiler-jar-with-dependencies.jar
Normal file
BIN
jar/NichtHaskellCompiler-jar-with-dependencies.jar
Normal file
Binary file not shown.
1
pom.xml
1
pom.xml
@@ -26,6 +26,7 @@
|
||||
<mainClass>Compiler</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<finalName>NichtHaskellCompiler</finalName>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
|
||||
33
src/main/java/CodeGen/CodeGenHelper.java
Normal file
33
src/main/java/CodeGen/CodeGenHelper.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package CodeGen;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class CodeGenHelper {
|
||||
|
||||
public static String getFieldDescriptor(String type) {
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default:
|
||||
return "L" + type + ";";
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetLocalVarIndex(LinkedHashMap<String, String> localVars, String varToSearchFor) {
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()) {
|
||||
if (key.equals(varToSearchFor)) {
|
||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -18,16 +19,15 @@ public class Compiler {
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
|
||||
// todo code für jar
|
||||
// if (args.length < 1) {
|
||||
// System.out.println("Usage: java -jar Compiler.jar <file_path> [--suppress-details]");
|
||||
// return;
|
||||
// }
|
||||
|
||||
//String filePath = args[0];
|
||||
String filePath = "src/main/java/TestClass.java";
|
||||
// TODO false setzen für jar-Build
|
||||
boolean suppressDetails = true;
|
||||
if (args.length < 1) {
|
||||
System.out.println("Usage: java -jar Compiler.jar <file_path> [--suppress-details]");
|
||||
return;
|
||||
}
|
||||
|
||||
String filePath = args[0];
|
||||
|
||||
boolean suppressDetails = false;
|
||||
|
||||
if (args.length > 1 && args[1].equals("--suppress-details")) {
|
||||
suppressDetails = true;
|
||||
@@ -64,7 +64,7 @@ public class Compiler {
|
||||
}
|
||||
String readableTokens = stringBuilder.toString().trim();
|
||||
|
||||
System.out.println("The tokens of your input are: \n" + readableTokens);
|
||||
System.out.println("The tokens of your input are: \n" + readableTokens + "\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -80,26 +80,40 @@ public class Compiler {
|
||||
if(!suppressDetails) {
|
||||
System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes: ");
|
||||
abstractSyntaxTree.classes.forEach(refType -> {
|
||||
System.out.print(refType.name);
|
||||
if (abstractSyntaxTree.classes.indexOf(refType) < abstractSyntaxTree.classes.size() - 1) {
|
||||
System.out.print(", ");
|
||||
} else {
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println("\t" + refType.name);
|
||||
});
|
||||
System.out.println();
|
||||
}
|
||||
// try {
|
||||
// abstractSyntaxTree.typeCheck();
|
||||
// }catch(TypeCheckException e){
|
||||
// System.out.println("A TypeCheck error occurred. The compilation was stopped.");
|
||||
// System.out.println(e);
|
||||
// return;
|
||||
// }
|
||||
abstractSyntaxTree.typeCheck();
|
||||
|
||||
try {
|
||||
abstractSyntaxTree.typeCheck();
|
||||
}catch(TypeCheckException e){
|
||||
System.out.println("A TypeCheck error was found in you input. Your input was not compiled.");
|
||||
System.out.println(e);
|
||||
return;
|
||||
}catch (Exception e){
|
||||
System.out.println("A unexpected error occurred in TypeCheck.");
|
||||
System.out.println(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!suppressDetails)
|
||||
System.out.println("No TypeCheck errors found.");
|
||||
|
||||
abstractSyntaxTree.codeGen();
|
||||
System.out.println("Your input was compiled. You can find the output at ???");// todo wo output? überhaupt hinschreiben?
|
||||
abstractSyntaxTree.codeGen();//todo remove
|
||||
|
||||
try {
|
||||
abstractSyntaxTree.codeGen();
|
||||
}catch (Exception e){
|
||||
System.out.println("A error occurred during code generation. Your input was not compiled.");
|
||||
System.out.println(e);
|
||||
return;
|
||||
}
|
||||
|
||||
File outputJarFile = new File("output.jar");
|
||||
if (outputJarFile.exists())
|
||||
outputJarFile.delete();
|
||||
|
||||
System.out.println("Your input was compiled. You can find the output in your current working directory.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ New : 'new';
|
||||
|
||||
|
||||
//Values
|
||||
IntValue : ('+'|'-')*[0-9]+;
|
||||
IntValue : ('+'|'-')?[0-9]+;
|
||||
CharValue: '\''~[\r\n]?'\'';
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
class EmptyClass {
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
class Example1b {
|
||||
public int fak(int number){
|
||||
if(number < 0){
|
||||
return 1;
|
||||
}
|
||||
int factorial = 1;
|
||||
int i = 0;
|
||||
while(i < number){
|
||||
factorial = factorial * i;
|
||||
}
|
||||
return factorial;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,27 @@
|
||||
package TypeCheck;
|
||||
|
||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class TypeCheckResult {
|
||||
|
||||
public TypeCheckResult(){}
|
||||
public TypeCheckResult(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String type;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TypeCheckResult typeCheckResult = (TypeCheckResult) o;
|
||||
boolean result = (Objects.equals(type, typeCheckResult.type)
|
||||
);
|
||||
System.out.println("In TypeCheckResult: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Program;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -18,9 +18,9 @@ import java.util.Objects;
|
||||
|
||||
public class FieldDecl extends AbstractType implements Node {
|
||||
|
||||
public String type; // from parser
|
||||
public String identifier;// from parser
|
||||
public IExpression expression; // value of the field
|
||||
public String type;
|
||||
public String identifier;
|
||||
public IExpression expression;
|
||||
|
||||
public FieldDecl(String type, String identifier, IExpression expression){
|
||||
this.type = type;
|
||||
@@ -44,28 +44,14 @@ public class FieldDecl extends AbstractType implements Node {
|
||||
setTypeCheckResult(result);
|
||||
|
||||
return result;
|
||||
|
||||
//write field table
|
||||
}
|
||||
|
||||
public void codeGen(ClassWriter cw) {
|
||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
||||
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, descriptor, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
private String getFieldDescriptor() {
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default:
|
||||
return "L" + type + ";";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.*;
|
||||
@@ -35,7 +34,6 @@ public class MethodDecl implements Node {
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
// jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben
|
||||
List<Parameter> parametersList = parameters.parameterList;
|
||||
for(Parameter parameter : parametersList){
|
||||
localVars.put(parameter.identifier, parameter.type);
|
||||
@@ -92,7 +90,7 @@ public class MethodDecl implements Node {
|
||||
default -> mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
}
|
||||
}
|
||||
descriptor = getFieldDescriptor(field.type);
|
||||
descriptor = CodeGenHelper.getFieldDescriptor(field.type);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
||||
fieldFound = true;
|
||||
break;
|
||||
@@ -216,19 +214,6 @@ public class MethodDecl implements Node {
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
private String getFieldDescriptor(String type) {
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default:
|
||||
return "L" + type + ";";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -3,7 +3,6 @@ package abstractSyntaxTree.Class;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
@@ -68,7 +67,6 @@ public class RefType extends AbstractType implements Node {
|
||||
|
||||
// type check each method
|
||||
for (MethodDecl methodDecl : methodDecls) {
|
||||
// methodDecl.classThatContainsMethod = this.name;
|
||||
methodDecl.typeCheck(methodContext, typeContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -3,6 +3,7 @@ package abstractSyntaxTree.Datatype;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,11 +22,13 @@ public class CharDatatype extends AbstractType implements IDatatype{
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
// Possible use of BIPUSH and SIPUSH if the value is small enough
|
||||
//This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway
|
||||
|
||||
mv.visitLdcInsn((int)value);
|
||||
if (value <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||
} else if (value <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
} else {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
@@ -5,14 +5,9 @@ import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IDatatype {
|
||||
// typeCheck method
|
||||
TypeCheckResult typeCheck() throws TypeCheckException;
|
||||
|
||||
// visit method for code generation
|
||||
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
|
||||
TypeCheckResult getTypeCheckResult();
|
||||
}
|
||||
|
||||
//TODO: Check if we need to differentiate between primitive types and reference types --> for example in "=="
|
||||
@@ -21,8 +21,6 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
//Example of using BIPUSH and SIPUSH for optimizing bytecode size
|
||||
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||
|
||||
@@ -7,7 +7,6 @@ import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.beans.Expression;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
@@ -17,6 +16,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
public String operator;
|
||||
public IExpression left;
|
||||
public IExpression right;
|
||||
public String thisClass;
|
||||
|
||||
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
||||
this.operator = operator;
|
||||
@@ -28,6 +28,10 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
if(left instanceof LocalVarIdentifier localVarIdentifier)
|
||||
localVarIdentifier.thisClass = this.thisClass;
|
||||
if(right instanceof LocalVarIdentifier localVarIdentifier)
|
||||
localVarIdentifier.thisClass = this.thisClass;
|
||||
TypeCheckResult leftType = left.typeCheck(methodContext, typeContext, localVars);
|
||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
@@ -58,9 +62,6 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
result.type = "int";
|
||||
}
|
||||
break;
|
||||
|
||||
//case "&" ist für logisches und auf bit level
|
||||
//case "|" ist für logisches oder auf bit level
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
@@ -178,6 +179,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
boolean result = (Objects.equals(operator, binaryExpression.operator)
|
||||
&& Objects.equals(left, binaryExpression.left)
|
||||
&& Objects.equals(right, binaryExpression.right)
|
||||
&& Objects.equals(left.getTypeCheckResult(), binaryExpression.left.getTypeCheckResult())
|
||||
);
|
||||
System.out.println("In BinaryExpression: " + result);
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.BoolDatatype;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -27,7 +27,13 @@ public class CharConstantExpression extends AbstractType implements IExpression{
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
|
||||
if (value <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||
} else if (value <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
} else {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,11 +10,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public interface IExpression extends Node {
|
||||
// typeCheck method
|
||||
//TypeCheckResult typeCheck() throws Exception;
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
|
||||
|
||||
// visit method for code generation
|
||||
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception;
|
||||
|
||||
TypeCheckResult getTypeCheckResult();
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||
import gen.DecafParser;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -16,14 +14,14 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class InstVarExpression extends AbstractType implements IExpression{
|
||||
public class InstVarExpression extends AbstractType implements IExpression {
|
||||
|
||||
public String thisClass;
|
||||
public List<SubReceiver> receivers;
|
||||
public List<ReceivingMethod> receivingMethods;
|
||||
public String fieldName;
|
||||
|
||||
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName){
|
||||
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName) {
|
||||
this.receivers = receivers;
|
||||
this.receivingMethods = receivingMethods;
|
||||
this.fieldName = fieldName;
|
||||
@@ -32,7 +30,7 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
String typeOfSubreceiver = "";
|
||||
if(receivers.get(0).identifier != null) {
|
||||
if (receivers.get(0).identifier != null) {
|
||||
String subreceiver = receivers.get(0).identifier;
|
||||
typeOfSubreceiver = localVars.get(subreceiver);
|
||||
if (typeOfSubreceiver == null)
|
||||
@@ -45,7 +43,7 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
||||
|
||||
}
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
typeOfSubreceiver = thisClass;
|
||||
}
|
||||
|
||||
@@ -63,34 +61,123 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
||||
// typeContext: (ClassName, (FieldName, FieldType))
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
// Load "this" onto the stack
|
||||
String typeOfReciever = "";
|
||||
String descriptor = "";
|
||||
String classOfField = "";
|
||||
|
||||
// Determine if the reference is this or not
|
||||
if (this.receivers.get(0).identifier != null) {
|
||||
|
||||
// Load the local variable onto the stack
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()){
|
||||
if (key.equals(this.receivers.get(0).identifier)){
|
||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
break;
|
||||
for (int i = 0; i < receivers.size(); i++) {
|
||||
|
||||
if (i == 0) {
|
||||
// Load the local variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, this.receivers.get(i).identifier);
|
||||
|
||||
if (index == -1) {
|
||||
if (typeContext.get(thisClass).get(this.receivers.get(i).identifier) != null) {
|
||||
|
||||
classOfField = typeOfReciever;
|
||||
|
||||
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||
continue;
|
||||
|
||||
} else {
|
||||
throw new Exception("Variable " + this.receivers.get(i).identifier + " not found");
|
||||
}
|
||||
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
|
||||
|
||||
// Get the class of the receiver
|
||||
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||
}
|
||||
}
|
||||
counter++;
|
||||
// Not the first receiver
|
||||
else {
|
||||
|
||||
// Load the local variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, this.receivers.get(i).identifier);
|
||||
|
||||
if (index == -1) {
|
||||
if (typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier) != null) {
|
||||
|
||||
classOfField = typeOfReciever;
|
||||
|
||||
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||
continue;
|
||||
|
||||
} else {
|
||||
throw new Exception("Variable " + this.receivers.get(i).identifier + " not found");
|
||||
}
|
||||
} else {
|
||||
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load the field in fieldName
|
||||
|
||||
// Load the local variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, fieldName);
|
||||
|
||||
if (index == -1) {
|
||||
if (typeContext.get(typeOfReciever).get(fieldName) != null) {
|
||||
|
||||
classOfField = typeOfReciever;
|
||||
|
||||
typeOfReciever = typeContext.get(typeOfReciever).get(fieldName);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, fieldName, descriptor);
|
||||
|
||||
} else {
|
||||
throw new Exception("Variable " + fieldName + " not found");
|
||||
}
|
||||
|
||||
} else {
|
||||
typeOfReciever = localVars.get(fieldName);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||
}
|
||||
} else if (receivers.get(0).thisExpression) {
|
||||
// Load the local variable or instVar of this onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, fieldName);
|
||||
|
||||
if (index == -1) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
}
|
||||
|
||||
if (index == -1){
|
||||
throw new Exception("Variable " + this.receivers.get(0).identifier + " not found");
|
||||
}
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
||||
descriptor = getFieldDescriptor(fieldType);
|
||||
|
||||
} else {
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
//Load the field onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
//Get the field information
|
||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
||||
|
||||
private String getFieldDescriptor(String fieldType) {
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
|
||||
|
||||
@@ -105,16 +192,13 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
||||
descriptor.append("C");
|
||||
break;
|
||||
default:
|
||||
String fullReturnType = typeContext.get(thisClass).get(fieldName);
|
||||
|
||||
String fullReturnType = fieldType;
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||
break;
|
||||
}
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor.toString());
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,8 +206,10 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
InstVarExpression instVarExpression = (InstVarExpression) o;
|
||||
boolean result = (Objects.equals(thisClass, instVarExpression.thisClass)
|
||||
boolean result = (Objects.equals(receivers, instVarExpression.receivers)
|
||||
&& Objects.equals(fieldName, instVarExpression.fieldName)
|
||||
&& Objects.equals(receivingMethods, instVarExpression.receivingMethods)
|
||||
&& Objects.equals(thisClass, instVarExpression.thisClass)
|
||||
);
|
||||
System.out.println("In InstVarExpression: " + result);
|
||||
|
||||
@@ -134,4 +220,4 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,15 @@ public class IntConstantExpression extends AbstractType implements IExpression{
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
//TODO: When we are finished this can be done more efficiently
|
||||
mv.visitLdcInsn(value);
|
||||
if (value >= -1 && value <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||
} else {
|
||||
mv.visitLdcInsn(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
@@ -11,7 +11,6 @@ import java.util.LinkedHashMap;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||
@@ -52,15 +51,7 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||
if (localVars.containsKey(identifier)) {
|
||||
type = localVars.get(identifier);
|
||||
// Find the index of the variable
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()) {
|
||||
if (key.equals(identifier)) {
|
||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
@@ -84,25 +75,13 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
// Get the field from "this"
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, identifier, getFieldDescriptor(type));
|
||||
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, identifier, descriptor);
|
||||
} else
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
|
||||
//TODO move this to a helper class and remove the doubled code in MethodDecl and in other places
|
||||
private String getFieldDescriptor(String type) {
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default:
|
||||
return "L" + type + ";";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
|
||||
@@ -6,7 +6,7 @@ import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SubReceiver implements Node {
|
||||
boolean thisExpression;
|
||||
public boolean thisExpression;
|
||||
public NewStatementExpression newStatementExpression;
|
||||
public String identifier;
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.IDatatype;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -87,7 +87,6 @@ public class Program implements Node {
|
||||
typeContext.put(oneClass.name, classVars);
|
||||
|
||||
// build method context
|
||||
|
||||
HashMap<String, HashMap<String, ParameterList>> identifierAndMethod = new HashMap<>();
|
||||
for (MethodDecl methodDecl : oneClass.methodDecls){
|
||||
if(methodDecl.returnType == null) continue;
|
||||
@@ -98,8 +97,8 @@ public class Program implements Node {
|
||||
methodContext.put(oneClass.name, identifierAndMethod);
|
||||
}
|
||||
|
||||
int mainCounter = 0;
|
||||
// check if main exists
|
||||
int mainCounter = 0;
|
||||
for(RefType oneClass : classes){
|
||||
if(oneClass.hasMain)
|
||||
mainCounter++;
|
||||
|
||||
@@ -3,11 +3,10 @@ package abstractSyntaxTree.Statement;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -16,13 +15,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockStatement extends AbstractType implements IStatement {
|
||||
|
||||
//We will need a parameter which holds the symbol table
|
||||
HashMap<String, String> localVars;
|
||||
public String returnType; // "not" --> not void
|
||||
public String returnType;
|
||||
public List<IStatement> statements;
|
||||
public String thisClass;
|
||||
// do we need expression, statementexpression
|
||||
|
||||
public BlockStatement(List<IStatement> statements, String returnType) {
|
||||
this.statements = statements;
|
||||
@@ -66,6 +62,9 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
if (statement instanceof ReturnStatement returnStatement) {
|
||||
returnStatement.thisClass = thisClass;
|
||||
}
|
||||
if (statement instanceof NewStatementExpression newStatementExpression) {
|
||||
newStatementExpression.thisClass = thisClass;
|
||||
}
|
||||
|
||||
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
||||
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||
@@ -76,7 +75,7 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
}
|
||||
|
||||
if (typeOfCurrentStatement.type.contains(",")) {
|
||||
// else if has 2 returns, all code paths must retrun a value.
|
||||
// else if has 2 returns, all code paths must return a value.
|
||||
String[] substrings = typeOfCurrentStatement.type.split(",");
|
||||
|
||||
String firstType = substrings[0];
|
||||
@@ -139,7 +138,7 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
&& Objects.equals(statements, blockStatement.statements
|
||||
/*&& (Objects.equals(localVars, blockStatement.localVars)*/
|
||||
);
|
||||
System.out.println("In ParameterList: " + result);
|
||||
System.out.println("In BlockStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class EmptyStatement extends AbstractType implements IStatement{
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IfElseStatement extends AbstractType implements IStatement{
|
||||
@@ -54,9 +53,6 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
|
||||
//TODO: There are 2 NOPs and one athrow on the stack between the if-Block and else-Block execution --> I have no idea why
|
||||
// I think they are generated because of the jump operations below and can not be eliminated
|
||||
// as they do not negatively impact the execution of the code logic wise we can ignore them
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
|
||||
@@ -9,13 +9,10 @@ import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IfStatement extends AbstractType implements IStatement{
|
||||
public IExpression condition;
|
||||
|
||||
//Do we need a block statement here?
|
||||
IStatement ifStatement;
|
||||
public String thisClass;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
@@ -7,8 +8,8 @@ import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -36,11 +37,14 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
||||
if(expression instanceof MethodCallStatementExpression){
|
||||
MethodCallStatementExpression methodCall = (MethodCallStatementExpression) expression;
|
||||
methodCall.thisClass = this.thisClass;
|
||||
|
||||
}
|
||||
if(expression instanceof LocalVarIdentifier localVarIdentifier){
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
}
|
||||
if (expression instanceof NewStatementExpression newStatementExpression){
|
||||
newStatementExpression.thisClass = thisClass;
|
||||
}
|
||||
|
||||
expression.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
|
||||
@@ -55,15 +59,8 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
localVars.put(identifier, type);
|
||||
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()){
|
||||
if (key.equals(identifier)){
|
||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||
|
||||
if (index == -1){
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
@@ -82,7 +79,7 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
||||
}
|
||||
} else {
|
||||
|
||||
// Set a default value for the variable --> less problems
|
||||
// Set a default value for the variable --> fewer problems
|
||||
switch (type) {
|
||||
case "int", "boolean", "char":
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
@@ -51,18 +52,15 @@ public class PrintStatement extends AbstractType implements IStatement {
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||
|
||||
// Load the value of the variable onto the stack
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()){
|
||||
if (key.equals(variableName)){
|
||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, variableName);
|
||||
|
||||
// If not a localVar, maybe a class field of this class
|
||||
if (index == -1){
|
||||
throw new Exception("Variable " + variableName + " not found");
|
||||
String typeOfField = typeContext.get(thisClass).get(variableName);
|
||||
if (typeOfField == null){
|
||||
throw new Exception("Variable " + variableName + " not found in local variables or class fields.");
|
||||
}
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, thisClass, variableName, "I");
|
||||
}
|
||||
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
|
||||
@@ -5,17 +5,17 @@ import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ReturnStatement extends AbstractType implements IStatement{
|
||||
IExpression expression;
|
||||
IExpression expression; // Needs typeCheckResult
|
||||
public String thisClass;
|
||||
|
||||
public ReturnStatement(IExpression expression) {
|
||||
@@ -33,6 +33,8 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
||||
methodCallStatementExpression.thisClass = this.thisClass;
|
||||
else if(expression instanceof InstVarExpression instVarExpression)
|
||||
instVarExpression.thisClass = this.thisClass;
|
||||
else if(expression instanceof LocalVarIdentifier localVarIdentifier)
|
||||
localVarIdentifier.thisClass = this.thisClass;
|
||||
TypeCheckResult typedExpression = expression.typeCheck(methodContext, typeContext, localVars);
|
||||
result.type = typedExpression.type;
|
||||
}
|
||||
@@ -66,8 +68,9 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ReturnStatement returnStatement = (ReturnStatement) o;
|
||||
boolean result = (Objects.equals(expression, returnStatement.expression)
|
||||
&& Objects.equals(expression.getTypeCheckResult(), returnStatement.expression.getTypeCheckResult())
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
System.out.println("In ReturnStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WhileStatement extends AbstractType implements IStatement {
|
||||
@@ -29,7 +28,7 @@ public class WhileStatement extends AbstractType implements IStatement {
|
||||
// check condition
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new IllegalArgumentException("Expected boolean");
|
||||
throw new TypeCheckException("Condition of while-statement is of type " + conditionType.type + " but should be boolean.");
|
||||
}
|
||||
|
||||
// check code block
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.WhileStatement;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -36,11 +37,12 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
TypeCheckResult leftType;
|
||||
|
||||
if (left instanceof LocalVarIdentifier localVarIdentifier) {
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
leftType = new TypeCheckResult();
|
||||
String identifier = localVarIdentifier.getIdentifier();
|
||||
leftType.type = localVars.get(identifier);
|
||||
|
||||
// local var may be actually instvar of this
|
||||
// local var may be actually instVar of this
|
||||
if(leftType.type == null){
|
||||
leftType.type = typeContext.get(thisClass).get(identifier);
|
||||
}
|
||||
@@ -51,6 +53,10 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
}
|
||||
if(right instanceof MethodCallStatementExpression methodCallStatementExpression)
|
||||
methodCallStatementExpression.thisClass = this.thisClass;
|
||||
if(right instanceof LocalVarIdentifier localVarIdentifierRight)
|
||||
localVarIdentifierRight.thisClass = this.thisClass;
|
||||
if(right instanceof BinaryExpression binaryExpression)
|
||||
binaryExpression.thisClass = this.thisClass;
|
||||
|
||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
@@ -78,15 +84,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
String varName = localVar.getIdentifier();
|
||||
|
||||
//Get the index of the local variable
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()) {
|
||||
if (key.equals(varName)) {
|
||||
index = counter+1;
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, varName);
|
||||
|
||||
if (index == -1) {
|
||||
String fieldType = typeContext.get(thisClass).get(varName);
|
||||
@@ -120,39 +118,105 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
} else if (left instanceof InstVarExpression) {
|
||||
instVar = (InstVarExpression) left;
|
||||
|
||||
boolean isLocal = false;
|
||||
|
||||
// Load the reference onto the stack
|
||||
// Determine if the reference is this or another object
|
||||
if (instVar.receivers.get(0).identifier != null) {
|
||||
// Load the local variable (another object) onto the stack
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()) {
|
||||
if (key.equals(instVar.receivers.get(0).identifier)) {
|
||||
index = counter + 1; // Local variables start at index 1, 0 is "this"
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, instVar.receivers.get(0).identifier);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
|
||||
}
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
isLocal = true;
|
||||
} else {
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
}
|
||||
|
||||
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
//Now that the base ref is on the stack, I need to get the next field(s) and store the value in the last field
|
||||
|
||||
// Get the field information
|
||||
String fieldType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
||||
String typeOfPrevious = "";
|
||||
String currentType = "";
|
||||
if (instVar.receivers.size() > 0) {
|
||||
for (int i = 0; i < instVar.receivers.size(); i++) {
|
||||
|
||||
// Get the field descriptor
|
||||
String descriptor = getFieldDescriptor(fieldType, typeContext, instVar.fieldName, instVar.thisClass);
|
||||
if (i == 0) {
|
||||
|
||||
// Store the value in the field
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor);
|
||||
//Check if the chain is longer than 1
|
||||
// If it is not, then we can directly store the value in the field
|
||||
// If not we have to load the reference of the field on the stack
|
||||
if (instVar.receivers.size() < 2) {
|
||||
// Chain is only 1 long, so we can call PUTFIELD directly
|
||||
|
||||
//Load the value of the right expression on the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
if (isLocal) {
|
||||
typeOfPrevious = localVars.get(instVar.receivers.get(i).identifier);
|
||||
} else {
|
||||
typeOfPrevious = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
||||
if (typeOfPrevious == null) {
|
||||
typeOfPrevious = thisClass;
|
||||
}
|
||||
}
|
||||
|
||||
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||
continue;
|
||||
} else {
|
||||
|
||||
if (isLocal) {
|
||||
currentType = localVars.get(instVar.receivers.get(i).identifier);
|
||||
} else {
|
||||
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
||||
}
|
||||
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, thisClass);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.receivers.get(i).identifier, descriptor);
|
||||
typeOfPrevious = currentType;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//Now we have to implement the logic for the following fields in the chain as the above code
|
||||
// only handles the first field in the chain
|
||||
|
||||
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
|
||||
typeOfPrevious = currentType;
|
||||
}
|
||||
|
||||
// Now we have the reference of the last field in the chain on the stack
|
||||
if (instVar.receivers.size() > 1) {
|
||||
// We can store the value of the right expression in this field
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||
}
|
||||
|
||||
} else {
|
||||
// When a field is accessed directly and without a "this."
|
||||
|
||||
//Load the value of the right expression on the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
// Get the field information
|
||||
String fieldType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
||||
|
||||
// Get the field descriptor
|
||||
String descriptor = getFieldDescriptor(fieldType, typeContext, instVar.fieldName, instVar.thisClass);
|
||||
|
||||
// Store the value in the field
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,10 @@ package abstractSyntaxTree.StatementExpression;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -34,7 +31,6 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
|
||||
String classToSearchMethodIn = thisClass;
|
||||
|
||||
//method is called on something that is not this ???
|
||||
if (this.receiver != null) {
|
||||
if (!receiver.thisExpression) {
|
||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
@@ -45,17 +41,13 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
|
||||
String currentType = "";
|
||||
|
||||
// receiver is instvar
|
||||
// receiver is instVar
|
||||
if (receiver != null) {
|
||||
if (receiver.instVarExpression != null) {
|
||||
receiver.instVarExpression.thisClass = this.thisClass;
|
||||
String typeOfSubreceiver = receiver.instVarExpression.typeCheck(methodContext, typeContext, localVars).type;
|
||||
|
||||
String lastField = receiver.instVarExpression.fieldName;
|
||||
|
||||
currentType = typeOfSubreceiver;
|
||||
|
||||
//currentType = typeContext.get(receiver.instVarExpression.getTypeCheckResult().type).get(mostLeftField);
|
||||
} else {
|
||||
currentType = classToSearchMethodIn;
|
||||
}
|
||||
@@ -63,16 +55,11 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
currentType = thisClass;
|
||||
}
|
||||
|
||||
//if classToSearchMethodIn does not contain method, throw exception. go through list and check each
|
||||
|
||||
for (int i = 0; i < receivingMethods.size(); i++) {
|
||||
currentType = (String) methodContext.get(currentType).get(receivingMethods.get(i).methodName).keySet().toArray()[0];
|
||||
if (currentType == null)
|
||||
throw new TypeCheckException("The method " + methodName + " was not found in " + classToSearchMethodIn + ".");
|
||||
receivingMethods.get(i).thisClass = this.thisClass;
|
||||
|
||||
// currentType = return type
|
||||
// ThisClass = class von methode
|
||||
receivingMethods.get(i).checkParameters(methodContext, typeContext, localVars);
|
||||
}
|
||||
currentType = (String) methodContext.get(currentType).get(methodName).keySet().toArray()[0];
|
||||
@@ -139,7 +126,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
}
|
||||
|
||||
// Invoke the current method
|
||||
String descriptor = getMethodDescriptor(receivingMethod.methodName, localVars, methodContext, receivingMethod.arguments, returnOfPreviousMethod);
|
||||
String descriptor = getMethodDescriptor(receivingMethod.methodName, localVars, methodContext, receivingMethod.arguments, returnOfPreviousMethod, owner);
|
||||
returnOfPreviousMethod = methodContext.get(owner).get(receivingMethod.methodName).keySet().toArray()[0].toString();
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, receivingMethod.methodName, descriptor, false);
|
||||
}
|
||||
@@ -151,13 +138,16 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
|
||||
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod);
|
||||
if (returnOfPreviousMethod != null) {
|
||||
owner = returnOfPreviousMethod;
|
||||
}
|
||||
|
||||
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
||||
|
||||
}
|
||||
|
||||
// ()I
|
||||
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod) {
|
||||
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod, String owner) {
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
@@ -189,12 +179,20 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
String classToSearchMethodIn;
|
||||
//Return Type
|
||||
if (receiver != null) {
|
||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
if (classToSearchMethodIn == null) {
|
||||
classToSearchMethodIn = returnOfPreviousMethod;
|
||||
}
|
||||
if (classToSearchMethodIn == null) {
|
||||
classToSearchMethodIn = thisClass;
|
||||
if (receiver.identifier != null) {
|
||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
if (classToSearchMethodIn == null) {
|
||||
classToSearchMethodIn = returnOfPreviousMethod;
|
||||
}
|
||||
if (classToSearchMethodIn == null) {
|
||||
classToSearchMethodIn = thisClass;
|
||||
}
|
||||
} else {
|
||||
if (receiver.instVarExpression != null && returnOfPreviousMethod != null) {
|
||||
classToSearchMethodIn = returnOfPreviousMethod;
|
||||
} else {
|
||||
classToSearchMethodIn = owner;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
classToSearchMethodIn = thisClass;
|
||||
@@ -231,9 +229,80 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MethodCallStatementExpression methodCallStatementExpression = (MethodCallStatementExpression) o;
|
||||
return (Objects.equals(methodName, methodCallStatementExpression.methodName)
|
||||
boolean typeCheckResults = testTypeChecks(this, methodCallStatementExpression);
|
||||
|
||||
boolean result = (Objects.equals(methodName, methodCallStatementExpression.methodName)
|
||||
&& Objects.equals(arguments, methodCallStatementExpression.arguments)
|
||||
);
|
||||
&& Objects.equals(thisClass, methodCallStatementExpression.thisClass));
|
||||
return result && typeCheckResults;
|
||||
|
||||
}
|
||||
|
||||
public boolean testTypeChecks(MethodCallStatementExpression class1, MethodCallStatementExpression class2) {
|
||||
|
||||
boolean resultArguments = true;
|
||||
|
||||
for (int i = 0; i < class1.arguments.size(); i++){
|
||||
resultArguments = resultArguments && Objects.equals(class1.arguments.get(i).getTypeCheckResult(), class2.arguments.get(i).getTypeCheckResult());
|
||||
}
|
||||
|
||||
boolean exception1 = false;
|
||||
boolean exception2 = false;
|
||||
|
||||
try {
|
||||
class1.receiver.instVarExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception1 = true;
|
||||
}
|
||||
|
||||
try {
|
||||
class2.receiver.instVarExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception2 = true;
|
||||
}
|
||||
|
||||
if(exception1 != exception2) {
|
||||
System.out.println("Only one of the InstVarTypeChecks is null in MethodCallStatementExpression");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!exception1) {
|
||||
boolean resultInstVar = Objects.equals(receiver.instVarExpression.getTypeCheckResult(), class2.receiver.instVarExpression.getTypeCheckResult());
|
||||
if(!resultInstVar) {
|
||||
System.out.println("TypeCheckResult of receiver.instVarExpression.getTypeCheckResult() in MethodCallStatementExpression do not match");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
class1.receiver.newStatementExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception1 = true;
|
||||
}
|
||||
|
||||
try {
|
||||
class2.receiver.newStatementExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception2 = true;
|
||||
}
|
||||
|
||||
if(exception1 != exception2) {
|
||||
System.out.println("Only one of the newStatementExpression Typechecks is null in MethodCallStatementExpression");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!exception1) {
|
||||
boolean resultNewStatementExpression = Objects.equals(receiver.newStatementExpression.getTypeCheckResult().type, class2.receiver.newStatementExpression.getTypeCheckResult().type);
|
||||
if(!resultNewStatementExpression) {
|
||||
System.out.println("TypeCheckResult of receiver.newStatementExpression.getTypeCheckResult().type in MethodCallStatementExpression do not match");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,19 +5,17 @@ import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
|
||||
public String thisClass;
|
||||
private String className;
|
||||
private List<IExpression> arguments;
|
||||
|
||||
@@ -26,11 +24,36 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
NewStatementExpression newStatementExpression = (NewStatementExpression) o;
|
||||
boolean resultTypeCheckArguments = true;
|
||||
for (int i = 0; i < newStatementExpression.arguments.size(); i++){
|
||||
resultTypeCheckArguments = resultTypeCheckArguments && Objects.equals(this.arguments.get(i).getTypeCheckResult(), newStatementExpression.arguments.get(i).getTypeCheckResult());
|
||||
}
|
||||
boolean result = (Objects.equals(className, newStatementExpression.className)
|
||||
&& Objects.equals(arguments, newStatementExpression.arguments)
|
||||
);
|
||||
System.out.println("In newStatementExpression: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
|
||||
throw new TypeCheckException("An instance of " + className + " is created, but the type does not exist.");
|
||||
}
|
||||
for (IExpression argument : arguments) {
|
||||
if (argument instanceof InstVarExpression instVarExpression) {
|
||||
instVarExpression.thisClass = this.thisClass;
|
||||
}
|
||||
argument.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = className;
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Receiver implements Node {
|
||||
boolean thisExpression;
|
||||
@@ -18,6 +12,22 @@ public class Receiver implements Node {
|
||||
NewStatementExpression newStatementExpression;
|
||||
String identifier;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Receiver receiver = (Receiver) o;
|
||||
boolean result = (Objects.equals(thisExpression, receiver.thisExpression)
|
||||
&& Objects.equals(instVarExpression, receiver.instVarExpression)
|
||||
&& Objects.equals(newStatementExpression, receiver.newStatementExpression)
|
||||
&& Objects.equals(identifier, receiver.identifier)
|
||||
);
|
||||
System.out.println("In receiver: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public Receiver(boolean thisExpression) {
|
||||
this.thisExpression = thisExpression;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,29 @@ import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ReceivingMethod implements Node {
|
||||
public String methodName;
|
||||
public List<IExpression> arguments;
|
||||
public String thisClass;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ReceivingMethod receivingMethod = (ReceivingMethod) o;
|
||||
boolean result = (Objects.equals(methodName, receivingMethod.methodName)
|
||||
&& Objects.equals(arguments, receivingMethod.arguments)
|
||||
);
|
||||
System.out.println("In ReceivingMethod: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ReceivingMethod(String methodName, List<IExpression> arguments) {
|
||||
this.methodName = methodName;
|
||||
this.arguments = arguments;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import java.util.List;
|
||||
|
||||
public class SuperStatementExpression extends MethodCallStatementExpression{
|
||||
public SuperStatementExpression(String methodName, List<IExpression> arguments, List<ReceivingMethod> receivingMethods, Receiver receiver) {
|
||||
super(methodName, receiver, receivingMethods, arguments);
|
||||
}
|
||||
}
|
||||
@@ -32,27 +32,27 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
List<FieldDecl> fieldDecls = new ArrayList<>();
|
||||
List<MethodDecl> methodDecls = new ArrayList<>();
|
||||
boolean hasMain;
|
||||
if(ctx.MainMethodDecl() != null) {
|
||||
if (ctx.MainMethodDecl() != null) {
|
||||
hasMain = true;
|
||||
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()),(BlockStatement) visitBlock(ctx.block()));
|
||||
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()), (BlockStatement) visitBlock(ctx.block()));
|
||||
methodDecls.add(mainMethod);
|
||||
} else {
|
||||
hasMain = false;
|
||||
}
|
||||
for (DecafParser.LocalVarDeclContext fieldDecl: ctx.localVarDecl()) {
|
||||
for (DecafParser.LocalVarDeclContext fieldDecl : ctx.localVarDecl()) {
|
||||
fieldDecls.add((FieldDecl) generateFieldDecl(fieldDecl));
|
||||
}
|
||||
for (DecafParser.ConstuctorDeclContext constDecl: ctx.constuctorDecl()) {
|
||||
for (DecafParser.ConstuctorDeclContext constDecl : ctx.constuctorDecl()) {
|
||||
MethodDecl constructor = ((MethodDecl) visit(constDecl));
|
||||
constructor.classThatContainsMethod = name;
|
||||
methodDecls.add(constructor);
|
||||
}
|
||||
for (DecafParser.MethodDeclContext methodDecl: ctx.methodDecl()) {
|
||||
for (DecafParser.MethodDeclContext methodDecl : ctx.methodDecl()) {
|
||||
MethodDecl method = (MethodDecl) visit(methodDecl);
|
||||
method.classThatContainsMethod = name;
|
||||
methodDecls.add(method);
|
||||
}
|
||||
return new RefType(name,fieldDecls, methodDecls, hasMain);
|
||||
return new RefType(name, fieldDecls, methodDecls, hasMain);
|
||||
}
|
||||
|
||||
public Node generateFieldDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||
@@ -68,10 +68,10 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
IExpression expression = (IExpression) visit(ctx.expression());
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||
} else {
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||
}
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +99,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
} else {
|
||||
type = ctx.type().getText();
|
||||
}
|
||||
return new MethodDecl("", type , name, parameterList, block);
|
||||
return new MethodDecl("", type, name, parameterList, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,7 +110,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
@Override
|
||||
public Node visitParameterList(DecafParser.ParameterListContext ctx) {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
for (DecafParser.ParameterContext parameter: ctx.parameter()) {
|
||||
for (DecafParser.ParameterContext parameter : ctx.parameter()) {
|
||||
parameters.add((Parameter) visit(parameter));
|
||||
}
|
||||
return new ParameterList(parameters);
|
||||
@@ -140,14 +140,18 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
|
||||
@Override
|
||||
public Node visitReturnStmt(DecafParser.ReturnStmtContext ctx) {
|
||||
Node expression = visitExpression(ctx.expression());
|
||||
return new ReturnStatement((IExpression) expression);
|
||||
if (ctx.expression() != null) {
|
||||
Node expression = visitExpression(ctx.expression());
|
||||
return new ReturnStatement((IExpression) expression);
|
||||
} else {
|
||||
return new ReturnStatement(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitBlock(DecafParser.BlockContext ctx) {
|
||||
List<IStatement> stmts = new ArrayList<>();
|
||||
for (DecafParser.StatementContext stmt: ctx.statement()) {
|
||||
for (DecafParser.StatementContext stmt : ctx.statement()) {
|
||||
Node statement = visitStatement(stmt);
|
||||
stmts.add((IStatement) statement);
|
||||
}
|
||||
@@ -195,7 +199,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
} else if (ctx.newDecl() != null) {
|
||||
return visitNewDecl(ctx.newDecl());
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,7 +211,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
public Node visitAssign(DecafParser.AssignContext ctx) {
|
||||
Node right = visitExpression(ctx.expression());
|
||||
Node left = visitAssignableExpr(ctx.assignableExpr());
|
||||
return new AssignStatementExpression(ctx.Assign().getText(),(IExpression) left, (IExpression) right);
|
||||
return new AssignStatementExpression(ctx.Assign().getText(), (IExpression) left, (IExpression) right);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -215,7 +219,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
String methodName = ctx.Identifier().getText();
|
||||
List<IExpression> arguments = generateExpressions(ctx.argumentList());
|
||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||
for(DecafParser.ReceivingMethodContext receivingMethod: ctx.receivingMethod()) {
|
||||
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||
}
|
||||
if (ctx.receiver() != null) {
|
||||
@@ -316,14 +320,14 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
if (ctx.IntValue() != null) {
|
||||
int value = Integer.parseInt(ctx.IntValue().getText());
|
||||
return new IntConstantExpression(value);
|
||||
} else if(ctx.Identifier() != null) {
|
||||
} else if (ctx.Identifier() != null) {
|
||||
String identifier = ctx.Identifier().getText();
|
||||
return new LocalVarIdentifier(identifier);
|
||||
} else if(ctx.instVar() != null) {
|
||||
} else if (ctx.instVar() != null) {
|
||||
return visitInstVar(ctx.instVar());
|
||||
} else if(ctx.methodCall() != null) {
|
||||
} else if (ctx.methodCall() != null) {
|
||||
return visitMethodCall(ctx.methodCall());
|
||||
} else if(ctx.calcExpr() != null) {
|
||||
} else if (ctx.calcExpr() != null) {
|
||||
return visitCalcExpr(ctx.calcExpr());
|
||||
}
|
||||
return null;
|
||||
@@ -332,7 +336,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
@Override
|
||||
public Node visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) {
|
||||
String operator;
|
||||
if(ctx.nonCalcOperator().LogicalOpertor() != null) {
|
||||
if (ctx.nonCalcOperator().LogicalOpertor() != null) {
|
||||
operator = ctx.nonCalcOperator().LogicalOpertor().getText();
|
||||
} else {
|
||||
operator = ctx.nonCalcOperator().ComparisonOperator().getText();
|
||||
@@ -369,10 +373,10 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
List<SubReceiver> receivers = new ArrayList<>();
|
||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||
String fieldName = ctx.Identifier().getText();
|
||||
for(DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
||||
for (DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
||||
receivers.add((SubReceiver) visit(subReceiver));
|
||||
}
|
||||
for(DecafParser.ReceivingMethodContext receivingMethod: ctx.receivingMethod()) {
|
||||
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||
}
|
||||
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
||||
|
||||
@@ -12,12 +12,47 @@ public class testAll {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAssignWrongType(){
|
||||
Program ast = AssignWrongTypeAST.getProgram();
|
||||
String pathToCode = "failTests/AssignWrongType.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharArgument(){
|
||||
Program ast = CharArgumentAST.getProgram();
|
||||
String pathToCode = "SimpleTests/CharArgument.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassWithMain(){
|
||||
Program ast = ClassWithMainAST.getProgram();
|
||||
String pathToCode = "basicClasses/classWithMain.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorThisDot(){
|
||||
Program ast = ConstructorThisDotAST.getProgram();
|
||||
String pathToCode = "SimpleTests/ConstructorThisDot.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorParams(){
|
||||
Program ast = ConstructorParamsAST.getProgram();
|
||||
String pathToCode = "SimpleTests/ConstructorParams.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivideByZero(){
|
||||
Program ast = DivideByZeroAST.getProgram();
|
||||
String pathToCode = "failTests/DivideByzero.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
@Test
|
||||
public void testEmptyClass(){
|
||||
Program ast = emptyClassAST.getEmptyProgramm();
|
||||
@@ -40,24 +75,16 @@ public class testAll {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignWrongType(){
|
||||
Program ast = AssignWrongTypeAST.getProgram();
|
||||
String pathToCode = "failTests/AssignWrongType.java";
|
||||
public void testFieldVariable(){
|
||||
Program ast = FieldVarAST.getProgram();
|
||||
String pathToCode = "SimpleTests/FieldVar.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testDivideByZero(){
|
||||
Program ast = AssignWrongTypeAST.getProgram();
|
||||
String pathToCode = "failTests/DivideByzero.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
*/
|
||||
@Test
|
||||
public void testcharArgument(){
|
||||
Program ast = CharArgumentAST.getProgram();
|
||||
String pathToCode = "SimpleTests/CharArgument.java";
|
||||
public void testIfElseIfStatementWithOneReturne(){
|
||||
Program ast = IfElseIfStatementWithOneReturnAST.getProgram();
|
||||
String pathToCode = "SimpleTests/IfElseIfStatementWithOneReturn.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ASTs;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
@@ -24,6 +25,8 @@ public class CharArgumentASTTyped {
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(getRefType());
|
||||
Program program = new Program(classes);
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
@@ -44,14 +47,17 @@ public class CharArgumentASTTyped {
|
||||
List<SubReceiver> subReceiverList0 = new ArrayList<>();
|
||||
subReceiverList0.add(subReceiver0);
|
||||
InstVarExpression instVarExpression0 = new InstVarExpression(subReceiverList0, new ArrayList<>(), "c");
|
||||
instVarExpression0.thisClass = "CharArgument";
|
||||
CharConstantExpression charConstantExpression0 = new CharConstantExpression('a');
|
||||
List<IExpression> argumentList0 = new ArrayList<>();
|
||||
charConstantExpression0.setTypeCheckResult(new TypeCheckResult("char"));
|
||||
argumentList0.add(charConstantExpression0);
|
||||
MethodCallStatementExpression methodCallStatementExpression0 = new MethodCallStatementExpression("foo", null, new ArrayList<>(), argumentList0);
|
||||
methodCallStatementExpression0.thisClass = "CharArgument";
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", instVarExpression0,methodCallStatementExpression0);
|
||||
List<IStatement> iStatementList0 = new ArrayList<>();
|
||||
iStatementList0.add(assignStatementExpression0);
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList0, null);
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList0, "void");
|
||||
MethodDecl methodDecl0 =new MethodDecl("CharArgument", null,
|
||||
"CharArgument", new ParameterList(new ArrayList<>()), blockStatement0);
|
||||
|
||||
@@ -59,10 +65,12 @@ public class CharArgumentASTTyped {
|
||||
}
|
||||
|
||||
public static MethodDecl method1(){
|
||||
ReturnStatement returnStatement0 =new ReturnStatement(new LocalVarIdentifier("c"));
|
||||
LocalVarIdentifier localVarIdentifierC = new LocalVarIdentifier("c");
|
||||
localVarIdentifierC.setTypeCheckResult(new TypeCheckResult("char"));
|
||||
ReturnStatement returnStatement0 =new ReturnStatement(localVarIdentifierC);
|
||||
List<IStatement> iStatementList0 =new ArrayList<>();
|
||||
iStatementList0.add(returnStatement0);
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList0, null);
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList0, "char");
|
||||
Parameter parameter00 = new Parameter("char", "c");
|
||||
List<Parameter> parameterList0 = new ArrayList<>();
|
||||
parameterList0.add(parameter00);
|
||||
@@ -75,13 +83,18 @@ public class CharArgumentASTTyped {
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
TypingHelper.addTypeContext(program, "EmptyClassWithConstructor", new HashMap<>());
|
||||
HashMap<String, String> charArgumentMap0 = new HashMap<>();
|
||||
charArgumentMap0.put("c", "char");
|
||||
TypingHelper.addTypeContext(program, "CharArgument", charArgumentMap0);
|
||||
|
||||
// MethodContext
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
//method0.put("void", new ParameterList(new ArrayList<>()));
|
||||
List<Parameter> parameterList0 = new ArrayList<>();
|
||||
parameterList0.add(new Parameter("char", "c"));
|
||||
ParameterList parameterListObj0 = new ParameterList(parameterList0);
|
||||
method0.put("char", parameterListObj0);
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
//methods.put("main", method0);
|
||||
TypingHelper.addMethodContext(program, "EmptyClassWithConstructor", methods);
|
||||
methods.put("foo", method0);
|
||||
TypingHelper.addMethodContext(program, "CharArgument", methods);
|
||||
}
|
||||
}
|
||||
|
||||
45
src/test/java/ASTs/ConstructorParamsAST.java
Normal file
45
src/test/java/ASTs/ConstructorParamsAST.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorParamsAST {
|
||||
|
||||
public static Program getProgram() {
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("ConstructorParams", fieldDeclList, methodDeclList, false);
|
||||
return refType;
|
||||
}
|
||||
|
||||
public static MethodDecl method0() {
|
||||
|
||||
Parameter parameter0 = new Parameter("int", "i");
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
parameterList.add(parameter0);
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
BlockStatement blockStatement = new BlockStatement(new ArrayList<>(), null);
|
||||
MethodDecl methodDecl = new MethodDecl("ConstructorParams", null, "ConstructorParams",
|
||||
parameterListObj, blockStatement);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
}
|
||||
59
src/test/java/ASTs/ConstructorParamsASTTyped.java
Normal file
59
src/test/java/ASTs/ConstructorParamsASTTyped.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package ASTs;
|
||||
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorParamsASTTyped {
|
||||
public static Program getProgram() {
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("ConstructorParams", fieldDeclList, methodDeclList, false);
|
||||
return refType;
|
||||
}
|
||||
|
||||
public static MethodDecl method0() {
|
||||
|
||||
Parameter parameter0 = new Parameter("int", "i");
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
parameterList.add(parameter0);
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
BlockStatement blockStatement = new BlockStatement(new ArrayList<>(), "void");
|
||||
MethodDecl methodDecl = new MethodDecl("ConstructorParams", null, "ConstructorParams",
|
||||
parameterListObj, blockStatement);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
TypingHelper.addTypeContext(program, "ConstructorParams", new HashMap<>());
|
||||
|
||||
// MethodContext
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
//method0.put("void", new ParameterList(new ArrayList<>()));
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
//methods.put("main", method0);
|
||||
TypingHelper.addMethodContext(program, "ConstructorParams", methods);
|
||||
}
|
||||
}
|
||||
60
src/test/java/ASTs/ConstructorThisDotAST.java
Normal file
60
src/test/java/ASTs/ConstructorThisDotAST.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Expression.SubReceiver;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorThisDotAST {
|
||||
public static Program getProgram() {
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(new FieldDecl("int", "i", null));
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("ConstructorThisDot", fieldDeclList, methodDeclList, false);
|
||||
return refType;
|
||||
}
|
||||
|
||||
public static MethodDecl method0() {
|
||||
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
|
||||
SubReceiver subReceiver = new SubReceiver(true);
|
||||
List<SubReceiver> subReceiverList = new ArrayList<>();
|
||||
subReceiverList.add(subReceiver);
|
||||
InstVarExpression instVarExpressionLeft = new InstVarExpression(subReceiverList, new ArrayList<>(), "i");
|
||||
|
||||
|
||||
IntConstantExpression intConstantExpression = new IntConstantExpression(5);
|
||||
AssignStatementExpression assignStatementExpression = new AssignStatementExpression("=", instVarExpressionLeft, intConstantExpression);
|
||||
|
||||
iStatementList.add(assignStatementExpression);
|
||||
BlockStatement blockStatement = new BlockStatement(iStatementList, null);
|
||||
MethodDecl methodDecl = new MethodDecl("ConstructorThisDot", null, "ConstructorThisDot",
|
||||
parameterListObj, blockStatement);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
}
|
||||
77
src/test/java/ASTs/ConstructorThisDotASTTyped.java
Normal file
77
src/test/java/ASTs/ConstructorThisDotASTTyped.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package ASTs;
|
||||
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Expression.SubReceiver;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorThisDotASTTyped {
|
||||
public static Program getProgram() {
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(new FieldDecl("int", "i", null));
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("ConstructorThisDot", fieldDeclList, methodDeclList, false);
|
||||
return refType;
|
||||
}
|
||||
|
||||
public static MethodDecl method0() {
|
||||
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
|
||||
SubReceiver subReceiver = new SubReceiver(true);
|
||||
List<SubReceiver> subReceiverList = new ArrayList<>();
|
||||
subReceiverList.add(subReceiver);
|
||||
InstVarExpression instVarExpressionLeft = new InstVarExpression(subReceiverList, new ArrayList<>(), "i");
|
||||
instVarExpressionLeft.thisClass = "ConstructorThisDot";
|
||||
|
||||
IntConstantExpression intConstantExpression = new IntConstantExpression(5);
|
||||
AssignStatementExpression assignStatementExpression = new AssignStatementExpression("=", instVarExpressionLeft, intConstantExpression);
|
||||
|
||||
iStatementList.add(assignStatementExpression);
|
||||
BlockStatement blockStatement = new BlockStatement(iStatementList, "void");
|
||||
MethodDecl methodDecl = new MethodDecl("ConstructorThisDot", null, "ConstructorThisDot",
|
||||
parameterListObj, blockStatement);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
HashMap<String, String> typeContextMap = new HashMap<>();
|
||||
typeContextMap.put("i", "int");
|
||||
TypingHelper.addTypeContext(program, "ConstructorThisDot", typeContextMap);
|
||||
|
||||
// MethodContext
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
//method0.put("void", new ParameterList(new ArrayList<>()));
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
//methods.put("main", method0);
|
||||
TypingHelper.addMethodContext(program, "ConstructorThisDot", methods);
|
||||
}
|
||||
}
|
||||
@@ -3,28 +3,48 @@ package ASTs;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DivideByZeroAST {
|
||||
/*
|
||||
|
||||
public static Program getProgram() {
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType(){
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, false);
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, true);
|
||||
|
||||
return refType;
|
||||
}
|
||||
public static MethodDecl method0(){
|
||||
|
||||
BlockStatement blockStatement = new BlockStatement();
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
MethodDecl methodDecl = new MethodDecl("DivideByZero", "int", "test",
|
||||
BinaryExpression binaryExpression00 = new BinaryExpression("/", new IntConstantExpression(1), new IntConstantExpression(0));
|
||||
LocalVarDecl localVarDecl00 = new LocalVarDecl("int", "a", binaryExpression00);
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
iStatementList.add(localVarDecl00);
|
||||
BlockStatement blockStatement = new BlockStatement(iStatementList, null);
|
||||
|
||||
MethodDecl methodDecl = new MethodDecl("DivideByZero", "void", "main",
|
||||
new ParameterList(new ArrayList<>()), blockStatement
|
||||
);
|
||||
}*/
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,69 @@
|
||||
package ASTs;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class DivideByZeroASTTyped {
|
||||
|
||||
public static Program getProgram() {
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType(){
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, true);
|
||||
|
||||
return refType;
|
||||
}
|
||||
public static MethodDecl method0(){
|
||||
|
||||
IntConstantExpression intConstantExpression0 = new IntConstantExpression(1);
|
||||
intConstantExpression0.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
BinaryExpression binaryExpression00 = new BinaryExpression("/", intConstantExpression0, new IntConstantExpression(0));
|
||||
LocalVarDecl localVarDecl00 = new LocalVarDecl("int", "a", binaryExpression00);
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
iStatementList.add(localVarDecl00);
|
||||
BlockStatement blockStatement = new BlockStatement(iStatementList, "void");
|
||||
|
||||
MethodDecl methodDecl = new MethodDecl("DivideByZero", "void", "main",
|
||||
new ParameterList(new ArrayList<>()), blockStatement
|
||||
);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program) {
|
||||
//Type Context
|
||||
TypingHelper.addTypeContext(program, "DivideByZero", new HashMap<>());
|
||||
|
||||
|
||||
//Method Context
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
method0.put("void", new ParameterList(new ArrayList<>()));
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
methods.put("main", method0);
|
||||
TypingHelper.addMethodContext(program, "DivideByZero", methods);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,18 +76,24 @@ public class FakultaetAST {
|
||||
|
||||
iStmtList0.add(localVarExpr0);
|
||||
// Expression 2
|
||||
IntConstantExpression intConst1 = new IntConstantExpression(0);
|
||||
IntConstantExpression intConst1 = new IntConstantExpression(1);
|
||||
LocalVarDecl localVarExpr1 = new LocalVarDecl("int", "i", intConst1);
|
||||
|
||||
iStmtList0.add(localVarExpr1);
|
||||
|
||||
//While Statement
|
||||
BinaryExpression whileCondition = new BinaryExpression("<", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
||||
BinaryExpression whileCondition = new BinaryExpression("<=", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
||||
|
||||
BinaryExpression whileBinExpr = new BinaryExpression("*", new LocalVarIdentifier("factorial"), new LocalVarIdentifier("i"));
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", new LocalVarIdentifier("factorial"), whileBinExpr);
|
||||
List<IStatement> whileBlockStmts = new ArrayList<>();
|
||||
|
||||
LocalVarIdentifier identifierI = new LocalVarIdentifier("i");
|
||||
BinaryExpression rightAssign1 = new BinaryExpression("+", identifierI, new IntConstantExpression(1));
|
||||
AssignStatementExpression assignStatementExpression1 = new AssignStatementExpression("=", identifierI, rightAssign1);
|
||||
|
||||
whileBlockStmts.add(assignStatementExpression0);
|
||||
whileBlockStmts.add(assignStatementExpression1);
|
||||
BlockStatement whileBlock = new BlockStatement( whileBlockStmts, null);
|
||||
|
||||
WhileStatement whileStatement0 = new WhileStatement(whileCondition, whileBlock);
|
||||
|
||||
@@ -61,8 +61,14 @@ public class FakultaetASTTyped {
|
||||
// If Statament
|
||||
//condition
|
||||
LocalVarIdentifier binExprIdentifier = new LocalVarIdentifier("number");
|
||||
TypeCheckResult typeCheckResultbinExprIdentifier = new TypeCheckResult();
|
||||
typeCheckResultbinExprIdentifier.type = "int";
|
||||
binExprIdentifier.setTypeCheckResult(typeCheckResultbinExprIdentifier);
|
||||
IntConstantExpression binExprIntConst = new IntConstantExpression(0);
|
||||
BinaryExpression binExpr = new BinaryExpression("<", binExprIdentifier, binExprIntConst);
|
||||
TypeCheckResult typeCheckResultbinExpr = new TypeCheckResult();
|
||||
typeCheckResultbinExpr.type = "boolean";
|
||||
binExpr.setTypeCheckResult(typeCheckResultbinExpr);
|
||||
|
||||
IntConstantExpression return0Expr0 = new IntConstantExpression(1);
|
||||
TypeCheckResult typeCheckResult1 = new TypeCheckResult();
|
||||
@@ -88,12 +94,23 @@ public class FakultaetASTTyped {
|
||||
iStmtList0.add(localVarExpr1);
|
||||
|
||||
//While Statement
|
||||
BinaryExpression whileCondition = new BinaryExpression("<", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
||||
LocalVarIdentifier identifierI = new LocalVarIdentifier("i");
|
||||
identifierI.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
BinaryExpression whileCondition = new BinaryExpression("<=", identifierI, new LocalVarIdentifier("number"));
|
||||
whileCondition.setTypeCheckResult(new TypeCheckResult("void"));
|
||||
|
||||
BinaryExpression whileBinExpr = new BinaryExpression("*", new LocalVarIdentifier("factorial"), new LocalVarIdentifier("i"));
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", new LocalVarIdentifier("factorial"), whileBinExpr);
|
||||
LocalVarIdentifier localVarIdentifierFactorial = new LocalVarIdentifier("factorial");
|
||||
localVarIdentifierFactorial.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
BinaryExpression whileBinExpr = new BinaryExpression("*", localVarIdentifierFactorial, identifierI);
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", localVarIdentifierFactorial, whileBinExpr);
|
||||
List<IStatement> whileBlockStmts = new ArrayList<>();
|
||||
|
||||
|
||||
BinaryExpression rightAssign1 = new BinaryExpression("+", identifierI, new IntConstantExpression(1));
|
||||
AssignStatementExpression assignStatementExpression1 = new AssignStatementExpression("=", identifierI, rightAssign1);
|
||||
|
||||
whileBlockStmts.add(assignStatementExpression0);
|
||||
whileBlockStmts.add(assignStatementExpression1);
|
||||
BlockStatement whileBlock = new BlockStatement( whileBlockStmts, "void");
|
||||
|
||||
WhileStatement whileStatement0 = new WhileStatement(whileCondition, whileBlock);
|
||||
|
||||
24
src/test/java/ASTs/FieldVarAST.java
Normal file
24
src/test/java/ASTs/FieldVarAST.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Program;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FieldVarAST {
|
||||
public static Program getProgram() {
|
||||
// int variable
|
||||
FieldDecl fieldDecl = new FieldDecl("int", "variable", null);
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(fieldDecl);
|
||||
RefType class0 = new RefType("FieldVar", fieldDeclList, methodDeclList, false);
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(class0);
|
||||
return new Program(refTypeList);
|
||||
}
|
||||
}
|
||||
43
src/test/java/ASTs/FieldVarASTTyped.java
Normal file
43
src/test/java/ASTs/FieldVarASTTyped.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package ASTs;
|
||||
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class FieldVarASTTyped {
|
||||
public static Program getProgram() {
|
||||
// int variable
|
||||
FieldDecl fieldDecl = new FieldDecl("int", "variable", null);
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(fieldDecl);
|
||||
RefType class0 = new RefType("FieldVar", fieldDeclList, methodDeclList, false);
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(class0);
|
||||
Program program = new Program(refTypeList);
|
||||
addTyping(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
HashMap<String, String> typeContextMap = new HashMap<>();
|
||||
typeContextMap.put("variable", "int");
|
||||
TypingHelper.addTypeContext(program, "FieldVar", typeContextMap);
|
||||
|
||||
// MethodContext
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
//method0.put("void", new ParameterList(new ArrayList<>()));
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
//methods.put("main", method0);
|
||||
TypingHelper.addMethodContext(program, "FieldVar", methods);
|
||||
}
|
||||
}
|
||||
104
src/test/java/ASTs/IfElseIfStatementWithOneReturnAST.java
Normal file
104
src/test/java/ASTs/IfElseIfStatementWithOneReturnAST.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.*;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IfElseIfStatementWithOneReturnAST {
|
||||
public static Program getProgram() {
|
||||
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("IfElseIfStatementWithOneReturn", fieldDeclList, methodDeclList, false);
|
||||
|
||||
return refType;
|
||||
}
|
||||
|
||||
public static MethodDecl method0() {
|
||||
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
parameterList.add(new Parameter("int", "i"));
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
iStatementList.add(statement00());
|
||||
iStatementList.add(statement01());
|
||||
iStatementList.add(statement02());
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList, null);
|
||||
MethodDecl methodDecl = new MethodDecl("IfElseIfStatementWithOneReturn", "int", "foo", parameterListObj, blockStatement0);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static LocalVarDecl statement00() {
|
||||
LocalVarDecl localVarDecl = new LocalVarDecl("int", "result", null);
|
||||
return localVarDecl;
|
||||
}
|
||||
|
||||
public static IfElseStatement statement01() {
|
||||
|
||||
LocalVarIdentifier conditionLeft = new LocalVarIdentifier("i");
|
||||
BinaryExpression condition = new BinaryExpression("==", conditionLeft, new IntConstantExpression(1));
|
||||
|
||||
LocalVarIdentifier identifierResult = new LocalVarIdentifier("result");
|
||||
List<IStatement> ifStatementList = new ArrayList<>();
|
||||
ifStatementList.add(new AssignStatementExpression("=", identifierResult, new IntConstantExpression(10)));
|
||||
BlockStatement ifStatement = new BlockStatement(ifStatementList, null);
|
||||
|
||||
IfElseStatement elseStatement = statement010();
|
||||
|
||||
IfElseStatement ifElseStatement = new IfElseStatement(condition, ifStatement, elseStatement);
|
||||
|
||||
return ifElseStatement;
|
||||
}
|
||||
|
||||
public static IfElseStatement statement010() {
|
||||
LocalVarIdentifier identifieri = new LocalVarIdentifier("i");
|
||||
BinaryExpression condition0 = new BinaryExpression("==", identifieri, new IntConstantExpression(2));
|
||||
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
LocalVarIdentifier identifierResult = new LocalVarIdentifier("result");
|
||||
AssignStatementExpression assignStatementExpression = new AssignStatementExpression("=", identifierResult, new IntConstantExpression(10));
|
||||
iStatementList.add(assignStatementExpression);
|
||||
BlockStatement ifStatement = new BlockStatement(iStatementList, null);
|
||||
|
||||
BinaryExpression condition1 = new BinaryExpression("==", identifieri, new IntConstantExpression(2));
|
||||
List<IStatement> iStatementList1 = new ArrayList<>();
|
||||
iStatementList1.add(new ReturnStatement(new IntConstantExpression(20)));
|
||||
BlockStatement blockStatementIf = new BlockStatement(iStatementList1, null);
|
||||
List<IStatement> iStatementList2 = new ArrayList<>();
|
||||
AssignStatementExpression assignStatementExpression1 = new AssignStatementExpression("=", identifierResult, new IntConstantExpression(30));
|
||||
iStatementList2.add(assignStatementExpression1);
|
||||
BlockStatement blockStatementElse = new BlockStatement(iStatementList2, null);
|
||||
IfElseStatement ifElseStatement = new IfElseStatement(condition1, blockStatementIf, blockStatementElse);
|
||||
|
||||
return new IfElseStatement(condition1, blockStatementIf, blockStatementElse);
|
||||
}
|
||||
|
||||
public static ReturnStatement statement02() {
|
||||
LocalVarIdentifier identifierResult = new LocalVarIdentifier("result");
|
||||
return new ReturnStatement(identifierResult);
|
||||
}
|
||||
|
||||
}
|
||||
135
src/test/java/ASTs/IfElseIfStatementWithOneReturnASTTyped.java
Normal file
135
src/test/java/ASTs/IfElseIfStatementWithOneReturnASTTyped.java
Normal file
@@ -0,0 +1,135 @@
|
||||
package ASTs;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.*;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class IfElseIfStatementWithOneReturnASTTyped {
|
||||
|
||||
public static Program getProgram() {
|
||||
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(getRefType());
|
||||
Program program = new Program(refTypeList);
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("IfElseIfStatementWithOneReturn", fieldDeclList, methodDeclList, false);
|
||||
|
||||
return refType;
|
||||
}
|
||||
|
||||
public static MethodDecl method0() {
|
||||
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
parameterList.add(new Parameter("int", "i"));
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
iStatementList.add(statement00());
|
||||
iStatementList.add(statement01());
|
||||
iStatementList.add(statement02());
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList, "int");
|
||||
MethodDecl methodDecl = new MethodDecl("IfElseIfStatementWithOneReturn", "int", "foo", parameterListObj, blockStatement0);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static LocalVarDecl statement00() {
|
||||
LocalVarDecl localVarDecl = new LocalVarDecl("int", "result", null);
|
||||
return localVarDecl;
|
||||
}
|
||||
|
||||
public static IfElseStatement statement01() {
|
||||
|
||||
LocalVarIdentifier conditionLeft = new LocalVarIdentifier("i");
|
||||
conditionLeft.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
BinaryExpression condition = new BinaryExpression("==", conditionLeft, new IntConstantExpression(1));
|
||||
condition.setTypeCheckResult(new TypeCheckResult("boolean"));
|
||||
|
||||
LocalVarIdentifier identifierResult = new LocalVarIdentifier("result");
|
||||
identifierResult.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
List<IStatement> ifStatementList = new ArrayList<>();
|
||||
ifStatementList.add(new AssignStatementExpression("=", identifierResult, new IntConstantExpression(10)));
|
||||
BlockStatement ifStatement = new BlockStatement(ifStatementList, "void");
|
||||
|
||||
IfElseStatement elseStatement = statement010();
|
||||
|
||||
IfElseStatement ifElseStatement = new IfElseStatement(condition, ifStatement, elseStatement);
|
||||
|
||||
return ifElseStatement;
|
||||
}
|
||||
|
||||
public static IfElseStatement statement010() {
|
||||
LocalVarIdentifier identifieri = new LocalVarIdentifier("i");
|
||||
identifieri.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
BinaryExpression condition0 = new BinaryExpression("==", identifieri, new IntConstantExpression(2));
|
||||
condition0.setTypeCheckResult(new TypeCheckResult("boolean"));
|
||||
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
LocalVarIdentifier identifierResult = new LocalVarIdentifier("result");
|
||||
identifierResult.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
AssignStatementExpression assignStatementExpression = new AssignStatementExpression("=", identifierResult, new IntConstantExpression(10));
|
||||
iStatementList.add(assignStatementExpression);
|
||||
BlockStatement ifStatement = new BlockStatement(iStatementList, "void");
|
||||
|
||||
BinaryExpression condition1 = new BinaryExpression("==", identifieri, new IntConstantExpression(2));
|
||||
condition1.setTypeCheckResult(new TypeCheckResult("boolean"));
|
||||
List<IStatement> iStatementList1 = new ArrayList<>();
|
||||
IntConstantExpression intConstantExpression20 = new IntConstantExpression(20);
|
||||
intConstantExpression20.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
ReturnStatement return20 = new ReturnStatement(intConstantExpression20);
|
||||
return20.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
iStatementList1.add(return20);
|
||||
BlockStatement blockStatementIf = new BlockStatement(iStatementList1, "int");
|
||||
List<IStatement> iStatementList2 = new ArrayList<>();
|
||||
AssignStatementExpression assignStatementExpression1 = new AssignStatementExpression("=", identifierResult, new IntConstantExpression(30));
|
||||
iStatementList2.add(assignStatementExpression1);
|
||||
BlockStatement blockStatementElse = new BlockStatement(iStatementList2, "void");
|
||||
IfElseStatement ifElseStatement = new IfElseStatement(condition1, blockStatementIf, blockStatementElse);
|
||||
|
||||
return new IfElseStatement(condition1, blockStatementIf, blockStatementElse);
|
||||
}
|
||||
|
||||
public static ReturnStatement statement02() {
|
||||
LocalVarIdentifier identifierResult = new LocalVarIdentifier("result");
|
||||
identifierResult.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
return new ReturnStatement(identifierResult);
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
TypingHelper.addTypeContext(program, "IfElseIfStatementWithOneReturn", new HashMap<>());
|
||||
|
||||
// MethodContext
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
parameterList.add(new Parameter("int", "i"));
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
method0.put("int", parameterListObj);
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
methods.put("foo", method0);
|
||||
TypingHelper.addMethodContext(program, "IfElseIfStatementWithOneReturn", methods);
|
||||
}
|
||||
}
|
||||
@@ -23,49 +23,32 @@ public class ByteCodeTester {
|
||||
}
|
||||
|
||||
public void testByteCodeFromAst(String correctClassFilePath, Program abstractSyntaxTree, String className) {
|
||||
testClassFile(false, className, abstractSyntaxTree, correctClassFilePath, null);
|
||||
typeCheckWithoutmain(abstractSyntaxTree);
|
||||
generateCode(abstractSyntaxTree);
|
||||
testAST(correctClassFilePath, className);
|
||||
}
|
||||
|
||||
public void testByteCodeFromTypedAst(String correctClassFilePath, Program abstractSyntaxTree, String className) {
|
||||
generateCode(abstractSyntaxTree);
|
||||
testAST(correctClassFilePath, className);
|
||||
}
|
||||
|
||||
public void testClassFileFromScratch(String correctClassFilePath, String fileToComparePath, String className) {
|
||||
testClassFile(true, className, null, correctClassFilePath, fileToComparePath);
|
||||
Program abstractSyntaxTree = generateAST(fileToComparePath);
|
||||
typeCheckWithoutmain(abstractSyntaxTree);
|
||||
generateCode(abstractSyntaxTree);
|
||||
testAST(correctClassFilePath, className);
|
||||
}
|
||||
public void testClassFile(boolean generateAST, String className, Program abstractSyntaxTree,
|
||||
String correctClassFilePath, String fileToComparePath) {
|
||||
|
||||
if(generateAST){
|
||||
String content = "";
|
||||
try {
|
||||
System.out.println("Classpath: " + Path.of(fileToComparePath));
|
||||
content = Files.readString(Path.of(fileToComparePath));
|
||||
} catch (IOException e) {
|
||||
System.out.println("File not found!");
|
||||
fail();
|
||||
}
|
||||
|
||||
CharStream codeCharStream = CharStreams.fromString(content);
|
||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
|
||||
tokens.fill();
|
||||
|
||||
DecafParser parser = new DecafParser(tokens);
|
||||
|
||||
ParseTree tree = parser.program();
|
||||
|
||||
ASTGenerator generator = new ASTGenerator();
|
||||
abstractSyntaxTree = (Program) generator.visit(tree);
|
||||
private void typeCheckWithoutmain(Program abstractSyntaxTree){
|
||||
try {
|
||||
abstractSyntaxTree.typeCheckWithoutMain();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le type-check");
|
||||
}
|
||||
}
|
||||
|
||||
if(generateAST){
|
||||
try {
|
||||
abstractSyntaxTree.typeCheckWithoutMain();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le type-check");
|
||||
//fail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void generateCode(Program abstractSyntaxTree){
|
||||
try {
|
||||
abstractSyntaxTree.codeGen();
|
||||
} catch (Exception e){
|
||||
@@ -73,7 +56,9 @@ public class ByteCodeTester {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
private void testAST(String correctClassFilePath, String className) {
|
||||
try {
|
||||
ClassFileLoader classLoader1 = new ClassFileLoader(correctClassFilePath);
|
||||
ClassFileLoader classLoader2 = new ClassFileLoader(className+ ".class");
|
||||
@@ -89,6 +74,30 @@ public class ByteCodeTester {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
private Program generateAST(String pathToJavaFile){
|
||||
String content = "";
|
||||
try {
|
||||
content = Files.readString(Path.of(pathToJavaFile));
|
||||
} catch (IOException e) {
|
||||
System.out.println("File not found!");
|
||||
fail();
|
||||
}
|
||||
|
||||
CharStream codeCharStream = CharStreams.fromString(content);
|
||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
|
||||
tokens.fill();
|
||||
|
||||
DecafParser parser = new DecafParser(tokens);
|
||||
|
||||
ParseTree tree = parser.program();
|
||||
|
||||
ASTGenerator generator = new ASTGenerator();
|
||||
Program abstractSyntaxTree = (Program) generator.visit(tree);
|
||||
|
||||
return abstractSyntaxTree;
|
||||
}
|
||||
|
||||
public void compareJarFilesFromAST(Program abstractSyntaxTree, String jarPath, String[] classNames){
|
||||
try {
|
||||
@@ -105,7 +114,6 @@ public class ByteCodeTester {
|
||||
public void compareJarFilesFromScratch(String javaCodePath, String jarPath, String[] classNames){
|
||||
String content = "";
|
||||
try {
|
||||
System.out.println("Classpath: " + Path.of(javaCodePath));
|
||||
content = Files.readString(Path.of(javaCodePath));
|
||||
} catch (IOException e) {
|
||||
System.out.println("File not found!");
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Random;
|
||||
|
||||
import static ByteCode.CompareByteCodeSyntax.compareMethod;
|
||||
|
||||
@@ -38,6 +39,14 @@ public class CompareByteCodeBehaviour {
|
||||
Method[] methods1 = class1.getDeclaredMethods();
|
||||
Method[] methods2 = class2.getDeclaredMethods();
|
||||
|
||||
/*
|
||||
for(int i = 0; i < methods1.length; i++) {
|
||||
System.out.println("Method1[" + i + "]: " + methods1[i]);
|
||||
System.out.println("Method2[" + i + "]: " + methods2[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
for (Method method1 : methods1) {
|
||||
for (Method method2 : methods2) {
|
||||
if (compareMethod(method1, method2)) {
|
||||
@@ -49,6 +58,12 @@ public class CompareByteCodeBehaviour {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
for(int i = 0; i < this.methodArray1.size(); i++){
|
||||
System.out.println("Method1[" + i + "]: " + methodArray1.get(i));
|
||||
System.out.println("Method2[" + i + "]: " + methodArray2.get(i));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public boolean compareMethodBehaviour(Class<?> class1, Class<?> class2){
|
||||
@@ -61,10 +76,9 @@ public class CompareByteCodeBehaviour {
|
||||
Constructor<?> constructor2 = constructors2[0];
|
||||
constructor1.setAccessible(true);
|
||||
constructor2.setAccessible(true);
|
||||
Object[] constructorArgs1 = getDefaultArguments(constructor1.getParameters());
|
||||
Object[] constructorArgs2 = getDefaultArguments(constructor2.getParameters());
|
||||
Object obj1 = constructor1.newInstance(constructorArgs1);
|
||||
Object obj2 = constructor2.newInstance(constructorArgs2);
|
||||
Object[] constructorArgs = getDefaultArguments(constructor1.getParameters());
|
||||
Object obj1 = constructor1.newInstance(constructorArgs);
|
||||
Object obj2 = constructor2.newInstance(constructorArgs);
|
||||
|
||||
// Get methods
|
||||
Method[] methods1 = new Method[this.methodArray1.size()];
|
||||
@@ -72,32 +86,47 @@ public class CompareByteCodeBehaviour {
|
||||
Method[] methods2 = new Method[this.methodArray2.size()];
|
||||
methods2 = this.methodArray2.toArray(methods2);
|
||||
|
||||
/*
|
||||
for(int i = 0; i < methods1.length; i++) {
|
||||
System.out.println("MethodArray1 [" + i + "]: " + methods1[i]);
|
||||
System.out.println("MethodArray2 [" + i + "]: " + methods2[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
// Compare methods
|
||||
for (int i = 0; i < methods1.length; i++) {
|
||||
Method method1 = methods1[i];
|
||||
Method method2 = methods2[i];
|
||||
|
||||
System.out.println("\n" + method1);
|
||||
System.out.println(method2);
|
||||
|
||||
method1.setAccessible(true);
|
||||
method2.setAccessible(true);
|
||||
|
||||
|
||||
// Test with some sample inputs
|
||||
Object[] testInputs = getTestInputs(method1.getParameterTypes());
|
||||
for(int j = 0; j < testInputs.length; j++){
|
||||
System.out.println("Parameter[" + i + "]: " + testInputs[j]);
|
||||
}
|
||||
|
||||
Object result1 = method1.invoke(obj1, testInputs);
|
||||
Object result2 = method2.invoke(obj2, testInputs);
|
||||
|
||||
if( (result1 == null) && (result2 == null)) {
|
||||
return true;
|
||||
}
|
||||
if(( result1 == null) || (result2 == null) ) {
|
||||
return false;
|
||||
System.out.println("Result method 1: " + result1);
|
||||
System.out.println("Result method 2: " + result2);
|
||||
|
||||
if( !((result1 == null) && (result2 == null))) {
|
||||
if(( result1 == null) || (result2 == null) ) {
|
||||
return false;
|
||||
}
|
||||
if (!result1.equals(result2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result1.equals(result2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException |
|
||||
@@ -111,15 +140,16 @@ public class CompareByteCodeBehaviour {
|
||||
private static Object[] getTestInputs(Class<?>[] parameterTypes) {
|
||||
// Create test inputs based on parameter types
|
||||
Object[] inputs = new Object[parameterTypes.length];
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (parameterTypes[i] == int.class) {
|
||||
inputs[i] = 1; // example value
|
||||
inputs[i] = random.nextInt(10); // example value
|
||||
} else if (parameterTypes[i] == String.class) {
|
||||
inputs[i] = "test"; // example value
|
||||
inputs[i] = "baguette"; // example value
|
||||
} else if (parameterTypes[i] == char.class) {
|
||||
inputs[i] = 'a';
|
||||
} else if (parameterTypes[i] == boolean.class) {
|
||||
inputs[i] = false;
|
||||
inputs[i] = random.nextBoolean();
|
||||
}
|
||||
// Add more cases as needed for different parameter types
|
||||
}
|
||||
@@ -128,13 +158,14 @@ public class CompareByteCodeBehaviour {
|
||||
|
||||
private Object[] getDefaultArguments(Parameter[] parameters) {
|
||||
Object[] defaultArgs = new Object[parameters.length];
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Class<?> paramType = parameters[i].getType();
|
||||
if (paramType.isPrimitive()) {
|
||||
if (paramType == boolean.class) {
|
||||
defaultArgs[i] = false;
|
||||
defaultArgs[i] = random.nextBoolean();
|
||||
} else if (paramType == int.class) {
|
||||
defaultArgs[i] = 1;
|
||||
defaultArgs[i] = random.nextInt(10);
|
||||
} else if (paramType == char.class) {
|
||||
defaultArgs[i] = '\u0000';
|
||||
} else if (paramType == String.class) {
|
||||
|
||||
@@ -8,19 +8,15 @@ import java.util.Arrays;
|
||||
public class CompareByteCodeSyntax {
|
||||
|
||||
public static boolean haveSameBehavior(Class<?> class1, Class<?> class2) {
|
||||
System.out.println("Comparing class signatures of " + class1.getName() + " and " + class2.getName());
|
||||
if (!compareClassSignatures(class1, class2)) {
|
||||
return false;
|
||||
}
|
||||
System.out.println("Comparing methods of " + class1.getName() + " and " + class2.getName());
|
||||
if (!compareMethods(class1, class2)) {
|
||||
return false;
|
||||
}
|
||||
System.out.println("Comparing fields of " + class1.getName() + " and " + class2.getName());
|
||||
if (!compareFields(class1, class2)) {
|
||||
return false;
|
||||
}
|
||||
System.out.println("Comparing annotations of " + class1.getName() + " and " + class2.getName());
|
||||
if (!compareAnnotations(class1.getAnnotations(), class2.getAnnotations())) {
|
||||
return false;
|
||||
}
|
||||
@@ -81,6 +77,7 @@ public class CompareByteCodeSyntax {
|
||||
System.out.println("Annotations do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,18 +18,28 @@ public class TestAll {
|
||||
Program ast = emptyClassASTTyped.getEmptyProgramm();
|
||||
String className = "emptyClass";
|
||||
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
||||
//byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyClassWithConstructor() {
|
||||
String classPath = "src/test/resources/basicClasses/EmptyClassWithConstructor.class";
|
||||
Program ast = EmptyClassWithConstructorASTTyped.getProgram();
|
||||
String className = "EmptyClassWithConstructor";
|
||||
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
||||
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFakultaet() {
|
||||
String classPath = "src/test/resources/basicClasses/Fakultaet.class";
|
||||
Program ast = FakultaetASTTyped.getProgram();
|
||||
Program ast = FakultaetAST.getProgram();
|
||||
String className = "Fakultaet";
|
||||
String javacode = "src/test/resources/basicClasses/Fakultaet.java";
|
||||
//byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -38,17 +48,17 @@ public class TestAll {
|
||||
Program ast = ClassWithMainASTTyped.getProgram();
|
||||
String className = "classWithMain";
|
||||
String javacode = "src/test/resources/basicClasses/classWithMain.java";
|
||||
//testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharArgument() {
|
||||
String classPath = "src/test/resources/SimpleTests/CharArgument.class";
|
||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||
Program ast = CharArgumentASTTyped.getProgram();
|
||||
String className = "CharArgument";
|
||||
String javacode = "src/test/resources/SimpleTests/CharArgument.java";
|
||||
//testByteCodeFromAst(classPath, ast ,className);
|
||||
//byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@@ -82,15 +92,6 @@ public class TestAll {
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivMethod() {
|
||||
String classPath = "src/test/resources/SimpleTests/DivMethod.class";
|
||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||
String className = "DivMethod";
|
||||
String javacode = "src/test/resources/SimpleTests/DivMethod.java";
|
||||
//testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
// We dont do null assignments
|
||||
/*
|
||||
@@ -108,10 +109,10 @@ public class TestAll {
|
||||
@Test
|
||||
public void testFieldVar() {
|
||||
String classPath = "src/test/resources/SimpleTests/FieldVar.class";
|
||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||
Program ast = FieldVarASTTyped.getProgram();
|
||||
String className = "FieldVar";
|
||||
String javacode = "src/test/resources/SimpleTests/FieldVar.java";
|
||||
//testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@@ -125,6 +126,7 @@ public class TestAll {
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetterFunction() {
|
||||
String classPath = "src/test/resources/SimpleTests/GetterFunction.class";
|
||||
@@ -135,6 +137,16 @@ public class TestAll {
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivMethod() {
|
||||
String classPath = "src/test/resources/SimpleTests/DivMethod.class";
|
||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||
String className = "DivMethod";
|
||||
String javacode = "src/test/resources/SimpleTests/DivMethod.java";
|
||||
//byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfElseIfStatement() {
|
||||
String classPath = "src/test/resources/SimpleTests/IfElseIfStatement.class";
|
||||
@@ -148,16 +160,14 @@ public class TestAll {
|
||||
@Test
|
||||
public void testIfElseIfStatementWithOneReturn() {
|
||||
String classPath = "src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.class";
|
||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||
Program ast = IfElseIfStatementWithOneReturnAST.getProgram();
|
||||
String className = "IfElseIfStatementWithOneReturn";
|
||||
String javacode = "src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.java";
|
||||
//testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testTwoClasses() {
|
||||
String jarPath = "src/test/resources/basicClasses/TwoClasses.jar";
|
||||
@@ -177,15 +187,6 @@ public class TestAll {
|
||||
byteCodeTester.compareJarFilesFromScratch(javacode, jarPath, classNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDijkstra() {
|
||||
String jarPath = "src/test/resources/Integration/Dijkstra.jar";
|
||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||
String[] classNames = {"FourClasses", "Test", "Test2", "Test3"};
|
||||
String javacode = "src/test/resources/Integration/Dijkstra.java";
|
||||
byteCodeTester.compareJarFilesFromScratch(javacode, jarPath, classNames);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,44 +21,44 @@ public class TestAll {
|
||||
|
||||
@Test
|
||||
public void testClassWithMain() {
|
||||
Program emptyClassAst = ClassWithMainAST.getProgram();
|
||||
Program astToBeTested = ClassWithMainAST.getProgram();
|
||||
Program correctAST = ClassWithMainASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheck(emptyClassAst, correctAST, expectedResult);
|
||||
testTypeCheck(astToBeTested, correctAST, expectedResult);
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testEmptyClass() {
|
||||
Program emptyClassAst = emptyClassAST.getEmptyProgramm();
|
||||
Program astToBeTested = emptyClassAST.getEmptyProgramm();
|
||||
Program correctAST = emptyClassASTTyped.getEmptyProgramm();
|
||||
boolean expectedResult = false;
|
||||
testTypeCheck(emptyClassAst, correctAST, expectedResult);
|
||||
testTypeCheck(astToBeTested, correctAST, expectedResult);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyClassWM() {
|
||||
Program emptyClassAst = emptyClassAST.getEmptyProgramm();
|
||||
Program astToBeTested = emptyClassAST.getEmptyProgramm();
|
||||
Program correctAST = emptyClassASTTyped.getEmptyProgramm();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWM(emptyClassAst, correctAST, expectedResult);
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyClassWithConstructor(){
|
||||
Program abstractSyntaxTree = EmptyClassWithConstructorAST.getProgram();
|
||||
Program astToBeTested = EmptyClassWithConstructorAST.getProgram();
|
||||
Program correctAST = EmptyClassWithConstructorASTTyped.getProgram();
|
||||
boolean expectedResult = false;
|
||||
testTypeCheck(abstractSyntaxTree, correctAST, expectedResult);
|
||||
testTypeCheck(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyClassWithConstructorWM(){
|
||||
Program abstractSyntaxTree = EmptyClassWithConstructorAST.getProgram();
|
||||
Program astToBeTested = EmptyClassWithConstructorAST.getProgram();
|
||||
Program correctAST = EmptyClassWithConstructorASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWM(abstractSyntaxTree, correctAST, expectedResult);
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -79,29 +79,86 @@ public class TestAll {
|
||||
|
||||
@Test
|
||||
public void testAssignWrongType(){
|
||||
Program assignWrongType = AssignWrongTypeAST.getProgram();
|
||||
Program astToBeTested = AssignWrongTypeAST.getProgram();
|
||||
Program correctAST = AssignWrongTypeASTTyped.getProgram();
|
||||
boolean expectedResult = false;
|
||||
testTypeCheck(assignWrongType, correctAST,expectedResult);
|
||||
testTypeCheck(astToBeTested, correctAST,expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignWrongTypeWM(){
|
||||
Program assignWrongType = AssignWrongTypeAST.getProgram();
|
||||
Program astToBeTested = AssignWrongTypeAST.getProgram();
|
||||
Program correctAST = AssignWrongTypeASTTyped.getProgram();
|
||||
boolean expectedResult = false;
|
||||
testTypeCheckWM(assignWrongType, correctAST, expectedResult);
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFakultaet(){
|
||||
Program fakultaet = FakultaetAST.getProgram();
|
||||
Program astToBeTested = FakultaetAST.getProgram();
|
||||
Program correctAST = FakultaetASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheck(fakultaet, correctAST, expectedResult);
|
||||
testTypeCheck(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivideByZero(){
|
||||
Program astToBeTested = DivideByZeroAST.getProgram();
|
||||
Program correctAST = DivideByZeroASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheck(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharArgument(){
|
||||
Program astToBeTested = CharArgumentAST.getProgram();
|
||||
Program correctAST = CharArgumentASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldVar(){
|
||||
Program astToBeTested = FieldVarAST.getProgram();
|
||||
Program correctAST = FieldVarASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorParams(){
|
||||
Program astToBeTested = ConstructorParamsAST.getProgram();
|
||||
Program correctAST = ConstructorParamsASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorThisDot(){
|
||||
Program astToBeTested = ConstructorThisDotAST.getProgram();
|
||||
Program correctAST = ConstructorThisDotASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfElseIfStatementWithOneReturn(){
|
||||
Program astToBeTested = IfElseIfStatementWithOneReturnAST.getProgram();
|
||||
Program correctAST = IfElseIfStatementWithOneReturnASTTyped.getProgram();
|
||||
boolean expectedResult = true;
|
||||
testTypeCheckWOM(astToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void testTypeCheckWOM(Program abstractSyntaxTree, Program correctAST, boolean expectedResult) {
|
||||
try {
|
||||
TypeChecker.assertTypeCheckResultNoMain(abstractSyntaxTree , correctAST,expectedResult);
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
public void testTypeCheckWM(Program abstractSyntaxTree, Program correctAST, boolean expectedResult){
|
||||
abstractSyntaxTree.classes.add(ClassWithMainASTTyped.getRefType());
|
||||
correctAST.classes.add(ClassWithMainASTTyped.getRefType());
|
||||
|
||||
@@ -8,7 +8,7 @@ import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TypeChecker {
|
||||
// Method to test if the TypeCheck returns the expected Result
|
||||
static public void assertTypeCheckResultNoMain(boolean testForMain, Program programmToBeTested, Program correctAST, boolean expectedResult) {
|
||||
static public void assertTypeCheckResultNoMain(Program programmToBeTested, Program correctAST, boolean expectedResult) {
|
||||
assertTypeCheckResult(false, programmToBeTested, correctAST, expectedResult);
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ public class TypeChecker {
|
||||
} catch (Exception e) {
|
||||
actualResult = false;
|
||||
}
|
||||
assertEquals(expectedResult, actualResult);
|
||||
assertEquals(programmToBeTested.typeContext, correctAST.typeContext);
|
||||
assertEquals(programmToBeTested.methodContext, correctAST.methodContext);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
if(expectedResult){
|
||||
assertEquals(programmToBeTested, correctAST);
|
||||
}
|
||||
|
||||
7
src/test/resources/FailTests/AddIntBool.java
Normal file
7
src/test/resources/FailTests/AddIntBool.java
Normal file
@@ -0,0 +1,7 @@
|
||||
class AddIntBool {
|
||||
|
||||
public int add(int myInt, bool myBool) {
|
||||
int result = myInt + myBool;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
class Dijkstra {
|
||||
|
||||
void main() {
|
||||
public static void main(String[] args) {
|
||||
Vertex v1 = new Vertex(1);
|
||||
Graph g = new Graph(v1);
|
||||
Vertex v2 = new Vertex(2);
|
||||
@@ -91,7 +91,7 @@ class Graph {
|
||||
}
|
||||
|
||||
public void getShortestPath(Vertex source, Vertex destination) {
|
||||
VertexSet calcList = vertexList.copy();
|
||||
VertexSet calcList = vertexList.copy(vertexList);
|
||||
calcList.get(source.id).setDistance(0);
|
||||
calcList.get(source.id).setPrevious(null);
|
||||
Vertex current = calcList.get(source.id);
|
||||
@@ -100,7 +100,6 @@ class Graph {
|
||||
current.setVisited(true);
|
||||
VertexSet currentAdjanceyList = current.getAdjanceyList();
|
||||
if (currentAdjanceyList != null) {
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
while (i < currentAdjanceyList.size()) {
|
||||
Vertex adjancey = currentAdjanceyList.getFromIndex(i);
|
||||
@@ -118,7 +117,7 @@ class Graph {
|
||||
}
|
||||
} else {
|
||||
}
|
||||
current = calcList.getNextSmallestUnvisited();
|
||||
current = calcList.getNextSmallestUnvisited(calcList);
|
||||
}
|
||||
Vertex previous = calcList.get(destination.id);
|
||||
if (previous == null) {
|
||||
@@ -190,8 +189,8 @@ class Vertex {
|
||||
}
|
||||
}
|
||||
|
||||
public Vertex copy() {
|
||||
return new Vertex(this);
|
||||
public Vertex copy(Vertex vertex) {
|
||||
return new Vertex(vertex);
|
||||
}
|
||||
|
||||
public boolean isDirect(Vertex v) {
|
||||
@@ -221,16 +220,16 @@ class VertexSet {
|
||||
}
|
||||
|
||||
public VertexSet(VertexSet vertexList) {
|
||||
this.vertex = vertexList.vertex.copy();
|
||||
this.vertex = vertexList.vertex.copy(vertexList.vertex);
|
||||
if (vertexList.next != null) {
|
||||
this.next = vertexList.next.copy();
|
||||
this.next = new VertexSet(vertexList.next);
|
||||
} else {
|
||||
this.next = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Vertex getNextSmallestUnvisited() {
|
||||
VertexSet v = this.getUnvisited();
|
||||
public Vertex getNextSmallestUnvisited(VertexSet currenVertexSet) {
|
||||
VertexSet v = this.getUnvisited(currenVertexSet);
|
||||
if (v == null) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -250,10 +249,10 @@ class VertexSet {
|
||||
return smallest;
|
||||
}
|
||||
|
||||
public VertexSet getUnvisited() {
|
||||
public VertexSet getUnvisited(VertexSet currenVertexSet) {
|
||||
VertexSet unvisited = null;
|
||||
|
||||
VertexSet current = this;
|
||||
VertexSet current = currenVertexSet;
|
||||
while (current != null) {
|
||||
if (!current.vertex.isVisited()) {
|
||||
if (unvisited == null) {
|
||||
@@ -295,8 +294,8 @@ class VertexSet {
|
||||
}
|
||||
}
|
||||
|
||||
public VertexSet copy() {
|
||||
return new VertexSet(this);
|
||||
public VertexSet copy(VertexSet currenVertexSet) {
|
||||
return new VertexSet(currenVertexSet);
|
||||
}
|
||||
|
||||
public boolean contains(Vertex v) {
|
||||
@@ -328,7 +327,6 @@ class VertexSet {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class IntStack {
|
||||
|
||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
||||
class CharArgument {
|
||||
|
||||
char c;
|
||||
public char c;
|
||||
|
||||
public CharArgument() {
|
||||
this.c = foo('a');
|
||||
}
|
||||
|
||||
char foo(char c) {
|
||||
public char foo(char c) {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class FieldVar {
|
||||
|
||||
int field;
|
||||
int variable;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ Class: "class"
|
||||
Identifier: "FieldVar"
|
||||
OpenCurlyBracket: "{"
|
||||
Int: "int"
|
||||
Identifier: "field"
|
||||
Identifier: "variable"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
EOF: "<EOF>"
|
||||
@@ -5,10 +5,48 @@ Int: "int"
|
||||
Identifier: "foo"
|
||||
OpenRoundBracket: "("
|
||||
Int: "int"
|
||||
Identifier: "i"
|
||||
ClosedRoundBracket: ")"
|
||||
OpenCurlyBracket: "{"
|
||||
Int: "int"
|
||||
Identifier: "result"
|
||||
Assign: "="
|
||||
IntValue: "0"
|
||||
Semicolon: ";"
|
||||
Semicolon: ";"
|
||||
If: "if"
|
||||
OpenRoundBracket: "("
|
||||
Identifier: "i"
|
||||
ComparisonOperator: "=="
|
||||
IntValue: "1"
|
||||
ClosedRoundBracket: ")"
|
||||
OpenCurlyBracket: "{"
|
||||
Identifier: "result"
|
||||
Assign: "="
|
||||
IntValue: "10"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
Else: "else"
|
||||
If: "if"
|
||||
OpenRoundBracket: "("
|
||||
Identifier: "i"
|
||||
ComparisonOperator: "=="
|
||||
IntValue: "2"
|
||||
ClosedRoundBracket: ")"
|
||||
OpenCurlyBracket: "{"
|
||||
Return: "return"
|
||||
IntValue: "20"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
Else: "else"
|
||||
OpenCurlyBracket: "{"
|
||||
Identifier: "result"
|
||||
Assign: "="
|
||||
IntValue: "30"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
Return: "return"
|
||||
Identifier: "result"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
ClosedCurlyBracket: "}"
|
||||
EOF: "<EOF>"
|
||||
BIN
src/test/resources/basicClasses/EmptyClassWithConstructor.class
Normal file
BIN
src/test/resources/basicClasses/EmptyClassWithConstructor.class
Normal file
Binary file not shown.
Binary file not shown.
@@ -4,9 +4,10 @@ class Fakultaet {
|
||||
return 1;
|
||||
}
|
||||
int factorial = 1;
|
||||
int i = 0;
|
||||
while(i < number){
|
||||
int i = 1;
|
||||
while(i <= number){
|
||||
factorial = factorial * i;
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
return factorial;
|
||||
|
||||
@@ -28,12 +28,12 @@ Semicolon: ";"
|
||||
Int: "int"
|
||||
Identifier: "i"
|
||||
Assign: "="
|
||||
IntValue: "0"
|
||||
IntValue: "1"
|
||||
Semicolon: ";"
|
||||
While: "while"
|
||||
OpenRoundBracket: "("
|
||||
Identifier: "i"
|
||||
ComparisonOperator: "<"
|
||||
ComparisonOperator: "<="
|
||||
Identifier: "number"
|
||||
ClosedRoundBracket: ")"
|
||||
OpenCurlyBracket: "{"
|
||||
@@ -43,6 +43,12 @@ Identifier: "factorial"
|
||||
DotOperator: "*"
|
||||
Identifier: "i"
|
||||
Semicolon: ";"
|
||||
Identifier: "i"
|
||||
Assign: "="
|
||||
Identifier: "i"
|
||||
LineOperator: "+"
|
||||
IntValue: "1"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
Return: "return"
|
||||
Identifier: "factorial"
|
||||
|
||||
@@ -3,7 +3,7 @@ Identifier: "FourClasses"
|
||||
OpenCurlyBracket: "{"
|
||||
AccessModifierPublic: "public"
|
||||
Int: "int"
|
||||
Identifier: "main"
|
||||
Identifier: "method"
|
||||
OpenRoundBracket: "("
|
||||
Int: "int"
|
||||
Identifier: "i"
|
||||
@@ -41,6 +41,24 @@ OpenRoundBracket: "("
|
||||
ClosedRoundBracket: ")"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
MainMethodDecl: "public static void main(String[] args)"
|
||||
OpenCurlyBracket: "{"
|
||||
Identifier: "FourClasses"
|
||||
Identifier: "fourClasses"
|
||||
Assign: "="
|
||||
New: "new"
|
||||
Identifier: "FourClasses"
|
||||
OpenRoundBracket: "("
|
||||
ClosedRoundBracket: ")"
|
||||
Semicolon: ";"
|
||||
Identifier: "fourClasses"
|
||||
Dot: "."
|
||||
Identifier: "method"
|
||||
OpenRoundBracket: "("
|
||||
IntValue: "1"
|
||||
ClosedRoundBracket: ")"
|
||||
Semicolon: ";"
|
||||
ClosedCurlyBracket: "}"
|
||||
ClosedCurlyBracket: "}"
|
||||
Class: "class"
|
||||
Identifier: "Test"
|
||||
|
||||
Reference in New Issue
Block a user