Compare commits
154 Commits
d8397753ca
...
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 | ||
|
|
5d75c23f49 | ||
|
|
ba9760fe43 | ||
|
|
888534955a | ||
|
|
f6358867f0 | ||
|
|
0711028dc3 | ||
|
|
97ab66122e | ||
|
|
1100cef668 | ||
|
|
3c863aafde | ||
|
|
41d5cd428c | ||
|
|
5dd3821ecb | ||
|
|
c5752df15e | ||
|
|
88bcfa5fa3 | ||
|
|
5dae167443 | ||
|
|
47a8d50185 | ||
|
|
94b3830561 | ||
|
|
3dcaad62f9 | ||
|
|
62060462a9 | ||
|
|
d5b526b8fc | ||
|
|
10f5dc692d | ||
|
|
e46cede8d5 | ||
|
|
38aeaa657d | ||
|
|
cabbbdcaf3 | ||
|
|
192dfae94b | ||
|
|
c24a483880 | ||
|
|
aa7d82b9ac | ||
|
|
94ea539fab | ||
|
|
6bf2c75e02 | ||
|
|
d2b307f86f | ||
|
|
5b0dc04bd7 | ||
| 6c015e72d5 | |||
|
|
cd9fc46a1f | ||
|
|
9b0d8147db | ||
|
|
21ece58cc9 | ||
| 8e0b215140 | |||
| 3fa8400b72 | |||
|
|
07552e704e | ||
|
|
194ff3fcf7 | ||
|
|
f5dcd4d79f | ||
| 492bab5477 | |||
|
|
99d23e89fa | ||
|
|
16cf78521b | ||
| 0c9acb2bc9 | |||
|
|
2c7748e6a3 | ||
|
|
4b2edaa6ff | ||
|
|
dd2842138f | ||
|
|
942597d535 | ||
|
|
392fea7d23 | ||
|
|
d1da1c6eee | ||
|
|
b787b333fb | ||
|
|
27ca4a978f | ||
|
|
289231030a | ||
| 3b2a328182 | |||
|
|
127726d342 | ||
|
|
4bc38c0ff9 | ||
|
|
34f4f307f3 | ||
|
|
c30dcdb773 | ||
|
|
f6bb836ee0 | ||
|
|
7498ca6e4d | ||
|
|
66c7722728 | ||
| 4b7cb0b150 | |||
|
|
1358e3372f | ||
|
|
5c81b88ca5 | ||
|
|
a3000d0ba1 | ||
|
|
d4f98693d6 | ||
|
|
6365e994d2 | ||
|
|
377e9b3193 | ||
|
|
eac4eb1db8 | ||
|
|
d8602ddd18 | ||
| b84ad2ef6b | |||
| 60958538d8 | |||
|
|
ed2f64eff9 | ||
|
|
77a6dae94f | ||
|
|
30334dc393 | ||
|
|
2a2e14ae21 | ||
| 9cf2ff6f37 | |||
| b402857713 | |||
|
|
8182e1ee7a | ||
|
|
ae260f6feb | ||
|
|
7daece9b8f | ||
|
|
b95bc75a1e | ||
|
|
1dac9245f2 | ||
|
|
90936affb9 | ||
|
|
9ff069827a | ||
|
|
87e863e773 | ||
|
|
c764b710ea | ||
|
|
e7d4a83a1d | ||
|
|
dcb564bd0d | ||
| c8c12e4d9a | |||
|
|
e23d84cd09 | ||
|
|
8a26f700b5 | ||
| 621ce16615 | |||
|
|
5a66ce97ca | ||
|
|
fdae734452 | ||
| ebd4f7ca4e | |||
|
|
719e19e7f8 | ||
|
|
5220a65a92 | ||
|
|
6585e67273 | ||
|
|
6915a97432 | ||
| c96d9fc1a1 | |||
| b00979c1a8 | |||
| 112c5f2c1b | |||
|
|
46ac49576e | ||
|
|
eaac9898f4 | ||
|
|
e70580ac86 | ||
| afd2319d78 | |||
| 821908f060 |
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/misc.xml
generated
8
.idea/misc.xml
generated
@@ -24,7 +24,11 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
<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>
|
||||
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -3,7 +3,6 @@
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/NichtHaskell.iml" filepath="$PROJECT_DIR$/NichtHaskell.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/src/NichtHaskell1.iml" filepath="$PROJECT_DIR$/src/NichtHaskell1.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
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/KlassendiagrammVereinfacht.pdf
Normal file
BIN
Documentation/KlassendiagrammVereinfacht.pdf
Normal file
Binary file not shown.
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -1,8 +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$/Source" isTestSource="false" />
|
||||
</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.
|
||||
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.
43
pom.xml
43
pom.xml
@@ -4,37 +4,52 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>Clippit.org</groupId>
|
||||
<artifactId>NichtHaskell</artifactId>
|
||||
<version>1</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>20</maven.compiler.source>
|
||||
<maven.compiler.target>20</maven.compiler.target>
|
||||
<java.version>22</java.version>
|
||||
<maven.compiler.source>22</maven.compiler.source>
|
||||
<maven.compiler.target>22</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>Compiler</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<finalName>NichtHaskellCompiler</finalName>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.7.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>compile</scope>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
|
||||
@@ -8,5 +8,17 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.antlr:antlr4-runtime:4.13.1" level="project" />
|
||||
<orderEntry type="module" module-name="NichtHaskell" scope="TEST" />
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library name="JUnit4">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,5 @@
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Datatype.BoolDatatype;
|
||||
import abstractSyntaxTree.Datatype.IntDatatype;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Expression.UnaryExpression;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import astGenerator.ASTGenerator;
|
||||
import gen.DecafLexer;
|
||||
import gen.DecafParser;
|
||||
@@ -18,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;
|
||||
@@ -27,41 +19,53 @@ public class Compiler {
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
|
||||
Path filePath = Paths.get("src/main/java/Input.java");
|
||||
|
||||
if (args.length < 1) {
|
||||
System.out.println("Usage: java -jar Compiler.jar <file_path> [--suppress-details]");
|
||||
return;
|
||||
}
|
||||
|
||||
// todo remove this debug info
|
||||
Path absolutePath = filePath.toAbsolutePath();
|
||||
System.out.println("Full path: " + absolutePath);
|
||||
String filePath = args[0];
|
||||
|
||||
String content;
|
||||
try {
|
||||
content = Files.readString(filePath);
|
||||
}catch (java.nio.file.NoSuchFileException e){
|
||||
System.out.println("File not found");
|
||||
boolean suppressDetails = false;
|
||||
|
||||
if (args.length > 1 && args[1].equals("--suppress-details")) {
|
||||
suppressDetails = true;
|
||||
}
|
||||
|
||||
Path path = Paths.get(filePath);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
System.out.println("Your input file was not found: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!suppressDetails)
|
||||
System.out.println("Processing input: " + path);
|
||||
|
||||
System.out.println("--- print content ---");
|
||||
System.out.println(content);
|
||||
String content = Files.readString(path);
|
||||
|
||||
if(!suppressDetails)
|
||||
System.out.println("The content of your input file is: \n" + content);
|
||||
|
||||
CharStream codeCharStream = CharStreams.fromString(content);
|
||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
|
||||
System.out.println("--- print tokens ---");
|
||||
tokens.fill();
|
||||
|
||||
List<Token> tokenList = tokens.getTokens();
|
||||
if(!suppressDetails) {
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Token token : tokenList) {
|
||||
stringBuilder.append(token.getText()).append(" ");
|
||||
List<Token> tokenList = tokens.getTokens();
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Token token : tokenList) {
|
||||
stringBuilder.append(token.getText()).append(" ");
|
||||
}
|
||||
String readableTokens = stringBuilder.toString().trim();
|
||||
|
||||
System.out.println("The tokens of your input are: \n" + readableTokens + "\n");
|
||||
}
|
||||
String readableTokens = stringBuilder.toString().trim();
|
||||
|
||||
System.out.println(readableTokens);
|
||||
|
||||
|
||||
DecafParser parser = new DecafParser(tokens);
|
||||
@@ -72,41 +76,44 @@ public class Compiler {
|
||||
Program abstractSyntaxTree =(Program) generator.visit(tree);
|
||||
|
||||
|
||||
System.out.println("--- AST generator ---");
|
||||
System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes with names:");
|
||||
for (RefType refType : abstractSyntaxTree.classes) {
|
||||
System.out.println(refType.name);
|
||||
|
||||
if(!suppressDetails) {
|
||||
System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes: ");
|
||||
abstractSyntaxTree.classes.forEach(refType -> {
|
||||
System.out.println("\t" + refType.name);
|
||||
});
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
//
|
||||
// List<FieldDecl> fieldDecls = new ArrayList<>();
|
||||
//
|
||||
// FieldDecl fieldDecl = new FieldDecl("int", "i");
|
||||
// fieldDecls.add(fieldDecl);
|
||||
//
|
||||
//// FieldDecl fieldDecl2 = new FieldDecl("char", "i");
|
||||
//// fieldDecls.add(fieldDecl2);
|
||||
//
|
||||
// List<MethodDecl> methodDecls = new ArrayList<>();
|
||||
//
|
||||
//
|
||||
// MethodDecl methodDecl = new MethodDecl("ClassA", "int", "m", new ParameterList(new ArrayList<>()), new BlockStatement(new ArrayList<>(), "void"));
|
||||
// methodDecls.add(methodDecl);
|
||||
//
|
||||
//// MethodDecl methodDecl2 = new MethodDecl("ClassA", "int", "m", new ArrayList<>(), new ArrayList<>());
|
||||
//// methodDecls.add(methodDecl2);
|
||||
//
|
||||
// abstractSyntaxTree.classes.add(new RefType("MyClass", fieldDecls, methodDecls, false));
|
||||
//
|
||||
// System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes with identifiers/names:");
|
||||
// for (RefType refType : abstractSyntaxTree.classes) {
|
||||
// System.out.println(refType.name);
|
||||
// }
|
||||
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.classes.get(0).methodDecls.get(0).codeBlock.returnType = "char";
|
||||
abstractSyntaxTree.typeCheck();
|
||||
abstractSyntaxTree.codeGen();//todo remove
|
||||
|
||||
abstractSyntaxTree.codeGen();
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ subExpression: This | assignableExpr | stmtExpr | OpenRoundBracket subExpression
|
||||
//.trim().toLength().toLowerCase().count ...
|
||||
methodCall: receiver? receivingMethod* Identifier OpenRoundBracket argumentList ClosedRoundBracket;
|
||||
|
||||
statement: returnStmt Semicolon | localVarDecl | block | whileStmt | ifElseStmt | stmtExpr Semicolon | emptyStatement;
|
||||
statement: returnStmt Semicolon | localVarDecl | block | whileStmt | ifElseStmt | print | stmtExpr Semicolon | emptyStatement;
|
||||
|
||||
stmtExpr: assign | newDecl | methodCall;
|
||||
|
||||
@@ -62,6 +62,9 @@ value: IntValue | BooleanValue | CharValue | NullValue;
|
||||
AccessModifierPublic : 'public' ;
|
||||
MainMethodDecl : 'public static void main(String[] args)';
|
||||
|
||||
//Print Statement print(VariableA);
|
||||
print: 'print' OpenRoundBracket Identifier ClosedRoundBracket Semicolon;
|
||||
|
||||
//Types
|
||||
Void : 'void';
|
||||
Int : 'int';
|
||||
@@ -111,7 +114,7 @@ New : 'new';
|
||||
|
||||
|
||||
//Values
|
||||
IntValue : ('+'|'-')*[0-9]+;
|
||||
IntValue : ('+'|'-')?[0-9]+;
|
||||
CharValue: '\''~[\r\n]?'\'';
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
class EmptyClass {
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
class ExampleEmpty {
|
||||
|
||||
}
|
||||
|
||||
class Example {
|
||||
int i;
|
||||
boolean b;
|
||||
char c;
|
||||
|
||||
}
|
||||
class Example2 {
|
||||
boolean instVarBool;
|
||||
int m(int n){
|
||||
int localA;
|
||||
int localB;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
class Example3 {
|
||||
char isNice;
|
||||
char m(int n) {
|
||||
int test = 12;
|
||||
this.m(test);
|
||||
boolean l;
|
||||
l = false;
|
||||
return 't';
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,65 @@
|
||||
public class TestClass {
|
||||
class FourClasses {
|
||||
|
||||
public int notmain(int i) {
|
||||
Test t = new Test(i);
|
||||
Test2 t2 = new Test2(t.y);
|
||||
return t2.test.test3.getX();
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
// new Example();
|
||||
// new Example2();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int x;
|
||||
public int y;
|
||||
public Test3 test3;
|
||||
|
||||
public Test(int i) {
|
||||
this.x = i;
|
||||
this.y = 10;
|
||||
this.test3 = new Test3(i * 2);
|
||||
}
|
||||
|
||||
public Test3 getTest3() {
|
||||
return this.test3;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public Test test;
|
||||
|
||||
public Test2(int i) {
|
||||
this.test = new Test(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
public int x;
|
||||
|
||||
public int y;
|
||||
|
||||
public Test3(int i) {
|
||||
this.x = i;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
7
src/main/java/TypeCheck/TypeCheckException.java
Normal file
7
src/main/java/TypeCheck/TypeCheckException.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package TypeCheck;
|
||||
|
||||
public class TypeCheckException extends Exception {
|
||||
public TypeCheckException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -4,31 +4,28 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TypeCheckHelper {
|
||||
public String upperBound(String type1, String type2) throws Exception{
|
||||
if(Objects.equals(type1, "boolean"))
|
||||
type1 = "bool";
|
||||
if (Objects.equals(type2, "boolean"))
|
||||
type2 = "bool";
|
||||
boolean type1Primitiv = Objects.equals(type1, "bool") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
|
||||
boolean type2Primitiv = Objects.equals(type2, "bool") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
|
||||
public static String upperBound(String type1, String type2) throws TypeCheckException{
|
||||
boolean type1Primitiv = Objects.equals(type1, "boolean") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
|
||||
boolean type2Primitiv = Objects.equals(type2, "boolean") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
|
||||
|
||||
String result;
|
||||
String result = "class";
|
||||
if(type1Primitiv && type2Primitiv){
|
||||
if(Objects.equals(type1, type2)){
|
||||
result = type1;
|
||||
}else{
|
||||
throw new Exception("no upper bound");
|
||||
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
||||
}
|
||||
}else if(type1Primitiv || type2Primitiv){
|
||||
throw new Exception("no upper bound");
|
||||
}else if(type1Primitiv ^ type2Primitiv){
|
||||
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
||||
}else{
|
||||
result = "class";
|
||||
if(Objects.equals(type1, type2))
|
||||
result = type1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static boolean typeExists(String type, List<String> customTypeslist) {
|
||||
|
||||
if(type.equals("int") || type.equals("bool") || type.equals("char")){
|
||||
if(type.equals("int") || type.equals("boolean") || type.equals("char")){
|
||||
return true;
|
||||
}
|
||||
return customTypeslist.contains(type);
|
||||
|
||||
@@ -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,10 +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;
|
||||
@@ -16,14 +18,16 @@ import java.util.Objects;
|
||||
|
||||
public class FieldDecl extends AbstractType implements Node {
|
||||
|
||||
public String type; // from parser
|
||||
public String identifier; // from parser
|
||||
public String type;
|
||||
public String identifier;
|
||||
public IExpression expression;
|
||||
|
||||
public FieldDecl(String type, String identifier){
|
||||
public FieldDecl(String type, String identifier, IExpression expression){
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
@@ -40,35 +44,24 @@ public class FieldDecl extends AbstractType implements Node {
|
||||
setTypeCheckResult(result);
|
||||
|
||||
return result;
|
||||
|
||||
//write field table
|
||||
}
|
||||
|
||||
public void codeGen(ClassWriter cw) {
|
||||
//TODO: Do we have fields with initial values? --> No dont think so --> assign
|
||||
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;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
FieldDecl fieldDecl = (FieldDecl) o;
|
||||
return ( Objects.equals(type, fieldDecl.type)
|
||||
&& Objects.equals(identifier, fieldDecl.identifier));
|
||||
boolean result = Objects.equals(type, fieldDecl.type)
|
||||
&& Objects.equals(identifier, fieldDecl.identifier)
|
||||
&& Objects.equals(expression, fieldDecl.expression);
|
||||
|
||||
System.out.println("In FieldDecl: " + result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +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.*;
|
||||
@@ -33,24 +33,29 @@ public class MethodDecl implements Node {
|
||||
this.localVars = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
// jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
List<Parameter> parametersList = parameters.parameterList;
|
||||
for(Parameter parameter : parametersList){
|
||||
localVars.put(parameter.identifier, parameter.type);
|
||||
}
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
String CodeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type;
|
||||
if(!Objects.equals(this.returnType, CodeBlockType))
|
||||
throw new Exception("TypeCheck Exception: Method retruns wrong type");
|
||||
codeBlock.thisClass = classThatContainsMethod;
|
||||
String codeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type;
|
||||
if(Objects.equals(this.name, classThatContainsMethod))
|
||||
codeBlockType = null;
|
||||
|
||||
if(!Objects.equals(this.returnType, codeBlockType))
|
||||
throw new TypeCheckException("Method returns " + codeBlockType + ", but should return " + this.returnType + ". ");
|
||||
|
||||
result.type = codeBlock.returnType;
|
||||
return result;
|
||||
}
|
||||
|
||||
//Need to get the returnType of the method if it is an object
|
||||
// methodContext (class, (returnType, (identifier, parameter)))
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
// methodContext (class, (identifier, (returnType, parameter)))
|
||||
// typeContext (class, (identifier, type))
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, List<FieldDecl> fieldDecls) throws Exception {
|
||||
|
||||
localVars.put("this", classThatContainsMethod);
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
@@ -59,27 +64,63 @@ public class MethodDecl implements Node {
|
||||
|
||||
// check if the method is a constructor
|
||||
if (classThatContainsMethod.equals(name) && returnType == null) {
|
||||
String descriptor = getMethodDescriptor(methodContext);
|
||||
String descriptor = getMethodDescriptor(methodContext, typeContext);
|
||||
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
|
||||
|
||||
//Call the superclass constructor
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
|
||||
HashMap<String, String> classFields = typeContext.get(classThatContainsMethod);
|
||||
|
||||
//Set the fields of the class
|
||||
boolean fieldFound = false;
|
||||
for (Map.Entry<String, String> entry : classFields.entrySet()) {
|
||||
String fieldName = entry.getKey();
|
||||
for (FieldDecl field : fieldDecls) {
|
||||
if (field.identifier.equals(fieldName)) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
if (field.expression != null) {
|
||||
field.expression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
} else {
|
||||
// If the field is not initialized, we need to load a default value onto the stack
|
||||
switch (field.type) {
|
||||
case "int", "boolean", "char" -> mv.visitInsn(Opcodes.ICONST_0);
|
||||
default -> mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
}
|
||||
}
|
||||
descriptor = CodeGenHelper.getFieldDescriptor(field.type);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
||||
fieldFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fieldFound){
|
||||
throw new Exception("Field " + fieldName + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
//Load the parameters onto the stack
|
||||
int localVarIndex = 1;
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
String paramType = param.type;
|
||||
switch(paramType) {
|
||||
case "int", "boolean", "char" -> mv.visitVarInsn(Opcodes.ILOAD, localVarIndex);
|
||||
default -> mv.visitVarInsn(Opcodes.ALOAD, localVarIndex);
|
||||
case "int", "boolean", "char" -> {
|
||||
mv.visitVarInsn(Opcodes.ILOAD, localVarIndex);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, localVarIndex);
|
||||
}
|
||||
default -> {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, localVarIndex);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, localVarIndex);
|
||||
}
|
||||
}
|
||||
localVarIndex++;
|
||||
}
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", descriptor, false);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars, typeContext);
|
||||
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
//automatically computed max stack and max locals
|
||||
@@ -91,17 +132,17 @@ public class MethodDecl implements Node {
|
||||
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars, typeContext);
|
||||
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
} else {
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext), null, null);
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext, typeContext), null, null);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars, typeContext);
|
||||
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
// We have to check the return type to get the return opcode
|
||||
// For methods which return an actual value, the return opcode is created in the method body to ensure the
|
||||
@@ -113,7 +154,7 @@ public class MethodDecl implements Node {
|
||||
}
|
||||
}
|
||||
|
||||
private String getMethodDescriptor(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) {
|
||||
private String getMethodDescriptor(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) {
|
||||
// get the method descriptor
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
@@ -121,13 +162,23 @@ public class MethodDecl implements Node {
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
switch (param.type) {
|
||||
case "int" -> descriptor.append("I");
|
||||
case "bool" -> descriptor.append("Z");
|
||||
case "boolean" -> descriptor.append("Z");
|
||||
case "char" -> descriptor.append("C");
|
||||
case "void" -> descriptor.append("V");
|
||||
default -> {
|
||||
// object
|
||||
//TODO: This is not finished for objects --> classes and methods
|
||||
if (returnType != null) descriptor.append("L").append(returnType).append(";");
|
||||
if (param.type != null) {
|
||||
String paramType = param.type;
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
HashMap<String, String> classTypes = typeContext.get(classThatContainsMethod);
|
||||
if (classTypes != null) {
|
||||
if (classTypes.containsKey(paramType)) {
|
||||
paramType = classTypes.get(paramType);
|
||||
paramType.replaceAll("\\.", "/");
|
||||
}
|
||||
}
|
||||
descriptor.append("L").append(paramType).append(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,11 +191,12 @@ public class MethodDecl implements Node {
|
||||
} else {
|
||||
switch (returnType) {
|
||||
case "int" -> descriptor.append("I");
|
||||
case "bool" -> descriptor.append("Z");
|
||||
case "boolean" -> descriptor.append("Z");
|
||||
case "char" -> descriptor.append("C");
|
||||
case "void" -> descriptor.append("V");
|
||||
default -> {
|
||||
// object
|
||||
// methodContext (class, (returnType, (identifier, parameter)))
|
||||
HashMap<String, HashMap<String, ParameterList>> classMethods = methodContext.get(classThatContainsMethod);
|
||||
HashMap<String, ParameterList> methodDetails = classMethods.get(name);
|
||||
|
||||
@@ -167,10 +219,12 @@ public class MethodDecl implements Node {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MethodDecl methodDecl = (MethodDecl) o;
|
||||
return (Objects.equals(name, methodDecl.name)
|
||||
boolean result = (Objects.equals(name, methodDecl.name)
|
||||
&& Objects.equals(parameters, methodDecl.parameters)
|
||||
&& Objects.equals(returnType, methodDecl.returnType)
|
||||
&& Objects.equals(codeBlock, methodDecl.codeBlock));
|
||||
System.out.println("In MethodDecl: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
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;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -19,7 +20,7 @@ public class RefType extends AbstractType implements Node {
|
||||
public String name; // Class Name
|
||||
public List<FieldDecl> fieldDecls;
|
||||
public List<MethodDecl> methodDecls;
|
||||
boolean hasMain;
|
||||
public boolean hasMain;
|
||||
|
||||
public RefType(String name,
|
||||
List<FieldDecl> fieldDecls,
|
||||
@@ -34,14 +35,14 @@ public class RefType extends AbstractType implements Node {
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
|
||||
HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
// check if field with the same identifier is defined more than once
|
||||
List<String> discoveredFieldIdentifiers = new ArrayList<>();
|
||||
for (FieldDecl fieldDecl : fieldDecls) {
|
||||
if(discoveredFieldIdentifiers.contains(fieldDecl.identifier)){
|
||||
throw new Exception("A field with the identifier " + fieldDecl.identifier + " was defined more than once in the same class.");
|
||||
throw new TypeCheckException("A field with the identifier " + fieldDecl.identifier + " was defined more than once in the class " + this.name + ". ");
|
||||
}
|
||||
discoveredFieldIdentifiers.add(fieldDecl.identifier);
|
||||
}
|
||||
@@ -58,7 +59,7 @@ public class RefType extends AbstractType implements Node {
|
||||
|
||||
if (discoveredMethods.containsKey(methodDecl.returnType)) {
|
||||
if(discoveredMethods.get(methodDecl.returnType).equals(methodDecl.name)){
|
||||
throw new Exception("A method with the name " + methodDecl.name + " and return type " + methodDecl.returnType + " was defined more than once in the same class.");
|
||||
throw new TypeCheckException("A method with the name " + methodDecl.name + " and return type " + methodDecl.returnType + " was defined more than once in the same class.");
|
||||
}
|
||||
}
|
||||
discoveredMethods.put(methodDecl.returnType, methodDecl.name);
|
||||
@@ -77,7 +78,7 @@ public class RefType extends AbstractType implements Node {
|
||||
// Method for code generation which iterates over all the field declarations
|
||||
// and method declarations and calls their CodeGen methods
|
||||
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null,
|
||||
"java/lang/Object", null);
|
||||
@@ -86,22 +87,37 @@ public class RefType extends AbstractType implements Node {
|
||||
field.codeGen(cw);
|
||||
}
|
||||
|
||||
boolean hasCustomConstructor = false;
|
||||
for (MethodDecl method : methodDecls) {
|
||||
method.codeGen(cw, methodContext, typeContext);
|
||||
if (method.name.equals(name) && method.returnType == null) {
|
||||
hasCustomConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasCustomConstructor) {
|
||||
MethodDecl standardConstructor = new MethodDecl(name, null, name, new ParameterList(new ArrayList<>()), new BlockStatement(new ArrayList<>(), "void"));
|
||||
standardConstructor.codeGen(cw, methodContext, typeContext, fieldDecls);
|
||||
}
|
||||
|
||||
for (MethodDecl method : methodDecls) {
|
||||
method.codeGen(cw, methodContext, typeContext, fieldDecls);
|
||||
}
|
||||
cw.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
System.out.println("Dont forget me ;)");
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RefType refType = (RefType) o;
|
||||
return ( Objects.equals(name, refType.name)
|
||||
boolean result = ( Objects.equals(name, refType.name)
|
||||
&& Objects.equals(fieldDecls, refType.fieldDecls)
|
||||
&& Objects.equals(methodDecls, refType.methodDecls)
|
||||
&& Objects.equals(hasMain, refType.hasMain));
|
||||
System.out.println("In RefType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -14,13 +13,16 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BoolDatatype boolDatatype = (BoolDatatype) o;
|
||||
return (Objects.equals(value, boolDatatype.value));
|
||||
boolean result = Objects.equals(value, boolDatatype.value);
|
||||
System.out.println("In BoolDataType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
public TypeCheckResult typeCheck() {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "bool";
|
||||
result.type = "boolean";
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
@@ -37,6 +39,8 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -10,7 +11,7 @@ public class CharDatatype extends AbstractType implements IDatatype{
|
||||
char value;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
public TypeCheckResult typeCheck() {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "char";
|
||||
@@ -21,22 +22,27 @@ 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) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CharDatatype charDatatype = (CharDatatype) o;
|
||||
return (Objects.equals(value, charDatatype.value));
|
||||
boolean result = Objects.equals(value, charDatatype.value);
|
||||
System.out.println("In CharDataType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IDatatype {
|
||||
// typeCheck method
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
// visit method for code generation
|
||||
TypeCheckResult typeCheck() throws TypeCheckException;
|
||||
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
|
||||
TypeCheckResult getTypeCheckResult();
|
||||
}
|
||||
|
||||
//TODO: Check if we need to differentiate between primitive types and reference types --> for example in "=="
|
||||
@@ -10,7 +10,7 @@ import java.util.Objects;
|
||||
public class IntDatatype extends AbstractType implements IDatatype{
|
||||
int value;
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
public TypeCheckResult typeCheck() {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "int";
|
||||
@@ -19,13 +19,8 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
||||
return result;
|
||||
}
|
||||
|
||||
// visit method for code generation
|
||||
|
||||
|
||||
@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)
|
||||
@@ -39,11 +34,14 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IntDatatype intDatatype = (IntDatatype) o;
|
||||
return (Objects.equals(value, intDatatype.value));
|
||||
boolean result = (Objects.equals(value, intDatatype.value));
|
||||
System.out.println("In IntDataType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
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;
|
||||
@@ -16,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;
|
||||
@@ -24,10 +25,13 @@ public class BinaryExpression 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 Exception {
|
||||
TypeCheckHelper helper = new TypeCheckHelper();
|
||||
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);
|
||||
|
||||
@@ -35,8 +39,8 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
|
||||
case "&&":
|
||||
case "||" :{
|
||||
if (Objects.equals(helper.upperBound(leftType.type, rightType.type), "bool")){
|
||||
result.type = "bool";
|
||||
if (Objects.equals(TypeCheckHelper.upperBound(leftType.type, rightType.type), "boolean")){
|
||||
result.type = "boolean";
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -46,20 +50,18 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
case "<=":
|
||||
case ">=":
|
||||
case "!=":
|
||||
result.type = helper.upperBound(leftType.type, rightType.type);
|
||||
TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||
result.type = "boolean";
|
||||
break;
|
||||
|
||||
case "-":
|
||||
case "+":
|
||||
case "*":
|
||||
case "/":
|
||||
if (Objects.equals(helper.upperBound(leftType.type, rightType.type), "int")){
|
||||
if (Objects.equals(TypeCheckHelper.upperBound(leftType.type, rightType.type), "int")){
|
||||
result.type = "int";
|
||||
}
|
||||
break;
|
||||
|
||||
//case "&" ist für logisches und auf bit level
|
||||
//case "|" ist für logisches oder auf bit level
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
@@ -67,7 +69,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
// Label for the jump instruction
|
||||
Label operationFalse = new Label(); //Operation is false
|
||||
Label operationTrue = new Label(); //Operation is true
|
||||
@@ -75,105 +77,98 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
Label expressionEnd = new Label(); //End of the whole expression
|
||||
|
||||
// Bytecode for the binary operation
|
||||
switch (operator) {
|
||||
case "&&":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||
if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
|
||||
switch (operator) {
|
||||
case "+" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.IADD);
|
||||
}
|
||||
case "-" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.ISUB);
|
||||
}
|
||||
case "*" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.IMUL);
|
||||
}
|
||||
case "/" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.IDIV);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (operator) {
|
||||
case "&&" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||
break;
|
||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||
}
|
||||
case "||" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||
|
||||
case "||":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||
}
|
||||
case "==" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||
break;
|
||||
switch (left.getTypeCheckResult().type) {
|
||||
case "int", "boolean", "char" -> mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue);
|
||||
|
||||
case "==":
|
||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||
default -> mv.visitJumpInsn(Opcodes.IF_ACMPEQ, operationTrue);
|
||||
}
|
||||
}
|
||||
case "<" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||
}
|
||||
case ">" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
||||
break;
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||
}
|
||||
case "<=" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
case "<":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||
}
|
||||
case ">=" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||
break;
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||
}
|
||||
case "!=" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
case ">":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||
}
|
||||
default -> throw new TypeCheckException("The operator " + operator + " is not known.");
|
||||
}
|
||||
mv.visitLabel(operationFalse);
|
||||
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
|
||||
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||
break;
|
||||
mv.visitLabel(operationTrue);
|
||||
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||
|
||||
case "<=":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||
break;
|
||||
|
||||
case ">=":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||
break;
|
||||
|
||||
case "!=":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||
break;
|
||||
|
||||
case "+":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitInsn(Opcodes.IADD);
|
||||
break;
|
||||
|
||||
case "-":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitInsn(Opcodes.ISUB);
|
||||
break;
|
||||
|
||||
case "*":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitInsn(Opcodes.IMUL);
|
||||
break;
|
||||
|
||||
case "/":
|
||||
left.codeGen(mv, localVars, typeContext);
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
mv.visitInsn(Opcodes.IDIV);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("Unknown operator: " + operator);
|
||||
mv.visitLabel(expressionEnd);
|
||||
}
|
||||
|
||||
mv.visitLabel(operationFalse);
|
||||
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
|
||||
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
|
||||
|
||||
mv.visitLabel(operationTrue);
|
||||
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||
|
||||
mv.visitLabel(expressionEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -181,14 +176,17 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BinaryExpression binaryExpression = (BinaryExpression) o;
|
||||
return (Objects.equals(operator, binaryExpression.operator)
|
||||
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);
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,11 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BooleanConstantExpression extends AbstractType implements IExpression{
|
||||
public boolean value;
|
||||
@@ -16,15 +18,34 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "bool";
|
||||
result.type = "boolean";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
if (value){
|
||||
mv.visitInsn(Opcodes.ICONST_1);
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BooleanConstantExpression boolDatatype = (BooleanConstantExpression) o;
|
||||
boolean result = Objects.equals(value, boolDatatype.value);
|
||||
System.out.println("In BooleanConstantExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CharConstantExpression extends AbstractType implements IExpression{
|
||||
public char value;
|
||||
@@ -16,7 +18,7 @@ public class CharConstantExpression 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 Exception {
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "char";
|
||||
setTypeCheckResult(result);
|
||||
@@ -24,7 +26,29 @@ public class CharConstantExpression extends AbstractType implements IExpression{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
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 TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CharConstantExpression boolDatatype = (CharConstantExpression) o;
|
||||
boolean result = Objects.equals(value, boolDatatype.value);
|
||||
System.out.println("In CharConstantExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
@@ -9,12 +10,8 @@ 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 Exception;
|
||||
|
||||
// visit method for code generation
|
||||
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
|
||||
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,46 +1,183 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import gen.DecafParser;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class InstVarExpression implements IExpression{
|
||||
public class InstVarExpression extends AbstractType implements IExpression {
|
||||
|
||||
public RefType classRef;
|
||||
public String thisClass;
|
||||
public List<SubReceiver> receivers;
|
||||
public List<ReceivingMethod> receivingMethods;
|
||||
public String fieldName;
|
||||
|
||||
public InstVarExpression(RefType classRef, String fieldName){
|
||||
this.classRef = classRef;
|
||||
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName) {
|
||||
this.receivers = receivers;
|
||||
this.receivingMethods = receivingMethods;
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
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) {
|
||||
String subreceiver = receivers.get(0).identifier;
|
||||
typeOfSubreceiver = localVars.get(subreceiver);
|
||||
if (typeOfSubreceiver == null)
|
||||
typeContext.get(thisClass).get(subreceiver);
|
||||
|
||||
//todo ///////////////////
|
||||
String varType = typeContext.get(classRef.name).get(fieldName);
|
||||
if (receivers.size() > 1) {
|
||||
for (int i = 1; i < receivers.size(); i++) {
|
||||
subreceiver = receivers.get(i).identifier;
|
||||
typeOfSubreceiver = typeContext.get(typeOfSubreceiver).get(subreceiver);
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
typeOfSubreceiver = thisClass;
|
||||
}
|
||||
|
||||
String varType = typeContext.get(typeOfSubreceiver).get(fieldName);
|
||||
if (varType == null) {
|
||||
throw new TypeCheckException("Field " + fieldName + " was not found in class " + thisClass + ".");
|
||||
}
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = varType;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
// typeContext: (ClassName, (FieldName, FieldType))
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
String typeOfReciever = "";
|
||||
String descriptor = "";
|
||||
String classOfField = "";
|
||||
|
||||
//Get the field information
|
||||
String fieldType = typeContext.get(classRef.name).get(fieldName);
|
||||
// Determine if the reference is this or not
|
||||
if (this.receivers.get(0).identifier != null) {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
||||
descriptor = getFieldDescriptor(fieldType);
|
||||
|
||||
//Load the field onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private String getFieldDescriptor(String fieldType) {
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
|
||||
|
||||
@@ -55,16 +192,13 @@ public class InstVarExpression implements IExpression{
|
||||
descriptor.append("C");
|
||||
break;
|
||||
default:
|
||||
String fullReturnType = typeContext.get(classRef.name).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, classRef.name, fieldName, descriptor.toString());
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,13 +206,18 @@ public class InstVarExpression implements IExpression{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
InstVarExpression instVarExpression = (InstVarExpression) o;
|
||||
return (Objects.equals(classRef, instVarExpression.classRef)
|
||||
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);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -18,13 +19,24 @@ public class IntConstantExpression 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 Exception {
|
||||
return null;
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "int";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
|
||||
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 {
|
||||
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
|
||||
@@ -32,12 +44,15 @@ public class IntConstantExpression extends AbstractType implements IExpression{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IntConstantExpression intConstantExpression = (IntConstantExpression) o;
|
||||
return (Objects.equals(value, intConstantExpression.value)
|
||||
boolean result = (Objects.equals(value, intConstantExpression.value)
|
||||
);
|
||||
System.out.println("In intConstantExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
@@ -9,12 +11,12 @@ import java.util.LinkedHashMap;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class LocalVarIdentifier implements IExpression{
|
||||
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||
|
||||
String identifier;
|
||||
public String thisClass;
|
||||
public LocalVarIdentifier(String identifier){
|
||||
this.identifier = identifier;
|
||||
}
|
||||
@@ -24,53 +26,65 @@ public class LocalVarIdentifier 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 Exception {
|
||||
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 (localVars.containsKey(identifier)) {
|
||||
result.type = localVars.get(identifier);
|
||||
} else {
|
||||
throw new Exception("TypeCheck Exception: Local var " + identifier + " does not exist.");
|
||||
// check if instvar
|
||||
result.type = typeContext.get(thisClass).get(identifier);
|
||||
if(result.type != null){
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
throw new TypeCheckException("Local var " + identifier + " does not exist.");
|
||||
}
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
// Check if the variable is in the list of local variables
|
||||
String type = localVars.get(identifier);
|
||||
if (type == null){
|
||||
throw new Exception("Variable " + identifier + " not declared");
|
||||
}
|
||||
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 {
|
||||
String type = null;
|
||||
|
||||
// Load the variable onto the stack
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()){
|
||||
if (key.equals(identifier)){
|
||||
index = counter;
|
||||
break;
|
||||
// if it's a local variable
|
||||
if (localVars.containsKey(identifier)) {
|
||||
type = localVars.get(identifier);
|
||||
// Find the index of the variable
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (index == -1){
|
||||
// Load the variable onto the stack
|
||||
switch (type) {
|
||||
case "int", "boolean", "char":
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
default:
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
break;
|
||||
}
|
||||
// If it's a field
|
||||
} else if (typeContext.get(thisClass).get(identifier) != null){
|
||||
type = typeContext.get(thisClass).get(identifier);
|
||||
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
// Get the field from "this"
|
||||
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, identifier, descriptor);
|
||||
} else
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
// Load the variable onto the stack
|
||||
switch (type){
|
||||
case "int":
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
break;
|
||||
case "bool":
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
default:
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
break;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,12 +92,10 @@ public class LocalVarIdentifier implements IExpression{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
LocalVarIdentifier localVarIdentifier = (LocalVarIdentifier) o;
|
||||
return (Objects.equals(identifier, localVarIdentifier.identifier)
|
||||
boolean result = (Objects.equals(identifier, localVarIdentifier.identifier)
|
||||
);
|
||||
}
|
||||
System.out.println("In localVarIdentifier: " + result);
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
36
src/main/java/abstractSyntaxTree/Expression/SubReceiver.java
Normal file
36
src/main/java/abstractSyntaxTree/Expression/SubReceiver.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SubReceiver implements Node {
|
||||
public boolean thisExpression;
|
||||
public NewStatementExpression newStatementExpression;
|
||||
public String identifier;
|
||||
|
||||
public SubReceiver(boolean thisExpression) {
|
||||
this.thisExpression = thisExpression;
|
||||
}
|
||||
|
||||
public SubReceiver(NewStatementExpression newStatementExpression) {
|
||||
this.newStatementExpression = newStatementExpression;
|
||||
}
|
||||
|
||||
public SubReceiver(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SubReceiver subReceiver = (SubReceiver) o;
|
||||
boolean result = (Objects.equals(thisExpression, subReceiver.thisExpression)
|
||||
);
|
||||
System.out.println("In SubReceiver: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.IDatatype;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -14,23 +13,23 @@ import java.util.Objects;
|
||||
|
||||
public class UnaryExpression extends AbstractType implements IExpression{
|
||||
public String operator;
|
||||
public IDatatype operand;
|
||||
public UnaryExpression(String operator, IDatatype operand){
|
||||
public IExpression operand;
|
||||
public UnaryExpression(String operator, IExpression operand){
|
||||
this.operator = operator;
|
||||
this.operand = operand;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
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();
|
||||
|
||||
TypeCheckResult operandTypeCheckResult = operand.typeCheck();
|
||||
TypeCheckResult operandTypeCheckResult = operand.typeCheck(methodContext, typeContext, localVars);
|
||||
String operandType = operandTypeCheckResult.type;
|
||||
|
||||
switch (operator) {
|
||||
|
||||
case "!" :{
|
||||
if (Objects.equals(operandType, "bool")){
|
||||
result.type = "bool";
|
||||
if (Objects.equals(operandType, "boolean")){
|
||||
result.type = "boolean";
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -50,9 +49,9 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
|
||||
operand.codeGen(mv);
|
||||
operand.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
switch (operator) {
|
||||
case "!":
|
||||
@@ -76,13 +75,16 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
UnaryExpression unaryExpression = (UnaryExpression) o;
|
||||
return (Objects.equals(operator, unaryExpression.operator)
|
||||
boolean result = (Objects.equals(operator, unaryExpression.operator)
|
||||
&& Objects.equals(operand, unaryExpression.operand)
|
||||
);
|
||||
System.out.println("In UnaryExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,11 @@ public class Parameter implements Node {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Parameter parameter = (Parameter) o;
|
||||
return (Objects.equals(type, parameter.type)
|
||||
boolean result = (Objects.equals(type, parameter.type)
|
||||
&& Objects.equals(identifier, parameter.identifier)
|
||||
);
|
||||
System.out.println("In Parameter: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@ public class ParameterList implements Node {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ParameterList parameterListObj = (ParameterList) o;
|
||||
return (Objects.equals(parameterList, parameterListObj.parameterList)
|
||||
boolean result = (Objects.equals(parameterList, parameterListObj.parameterList)
|
||||
);
|
||||
System.out.println("In ParameterList: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
@@ -9,6 +10,8 @@ import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.*;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -26,8 +29,7 @@ public class Program implements Node {
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
|
||||
public TypeCheckResult typeCheck() throws Exception{
|
||||
public TypeCheckResult typeCheckWithoutMain() throws TypeCheckException {
|
||||
this.typeContext = new HashMap<>();
|
||||
this.methodContext = new HashMap<>();
|
||||
|
||||
@@ -36,21 +38,30 @@ public class Program implements Node {
|
||||
// build type context
|
||||
HashMap<String, String> classVars = new HashMap<>();
|
||||
for (FieldDecl fieldDecl: oneClass.fieldDecls){
|
||||
if(fieldDecl.type == "boolean")
|
||||
fieldDecl.type = "bool";
|
||||
classVars.put(fieldDecl.identifier, fieldDecl.type);
|
||||
}
|
||||
typeContext.put(oneClass.name, classVars);
|
||||
|
||||
// build method context
|
||||
HashMap<String, ParameterList> methodIdentifierAndParameter = new HashMap<>();
|
||||
HashMap<String, HashMap<String, ParameterList>> returnTypeAndMethod = new HashMap<>();
|
||||
for (MethodDecl methodDecl : oneClass.methodDecls){
|
||||
|
||||
methodIdentifierAndParameter.put(methodDecl.name, methodDecl.parameters);
|
||||
returnTypeAndMethod.put(methodDecl.returnType, methodIdentifierAndParameter);
|
||||
HashMap<String, HashMap<String, ParameterList>> identifierAndMethod = new HashMap<>();
|
||||
for (MethodDecl methodDecl : oneClass.methodDecls){
|
||||
if(methodDecl.returnType == null) continue;
|
||||
HashMap<String, ParameterList> returnTypeAndParameter = new HashMap<>();
|
||||
returnTypeAndParameter.put(methodDecl.returnType, methodDecl.parameters);
|
||||
identifierAndMethod.put(methodDecl.name, returnTypeAndParameter);
|
||||
}
|
||||
methodContext.put(oneClass.name, returnTypeAndMethod);
|
||||
methodContext.put(oneClass.name, identifierAndMethod);
|
||||
}
|
||||
|
||||
int mainCounter = 0;
|
||||
// check if main exists
|
||||
for(RefType oneClass : classes){
|
||||
if(oneClass.hasMain)
|
||||
mainCounter++;
|
||||
}
|
||||
if(mainCounter != 1) {
|
||||
//throw new TypeCheckException("There is not 1 Main method.");
|
||||
}
|
||||
|
||||
// typecheck each class
|
||||
@@ -62,47 +73,100 @@ public class Program implements Node {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void codeGen() throws Exception{
|
||||
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream("output.jar"))) {
|
||||
public TypeCheckResult typeCheck() throws TypeCheckException {
|
||||
this.typeContext = new HashMap<>();
|
||||
this.methodContext = new HashMap<>();
|
||||
|
||||
for(RefType oneClass : classes){
|
||||
|
||||
// build type context
|
||||
HashMap<String, String> classVars = new HashMap<>();
|
||||
for (FieldDecl fieldDecl: oneClass.fieldDecls){
|
||||
classVars.put(fieldDecl.identifier, fieldDecl.type);
|
||||
}
|
||||
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;
|
||||
HashMap<String, ParameterList> returnTypeAndParameter = new HashMap<>();
|
||||
returnTypeAndParameter.put(methodDecl.returnType, methodDecl.parameters);
|
||||
identifierAndMethod.put(methodDecl.name, returnTypeAndParameter);
|
||||
}
|
||||
methodContext.put(oneClass.name, identifierAndMethod);
|
||||
}
|
||||
|
||||
// check if main exists
|
||||
int mainCounter = 0;
|
||||
for(RefType oneClass : classes){
|
||||
if(oneClass.hasMain)
|
||||
mainCounter++;
|
||||
}
|
||||
if(mainCounter != 1)
|
||||
throw new TypeCheckException("There is not 1 Main method.");
|
||||
|
||||
// typecheck each class
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
for(RefType oneClass : classes){
|
||||
oneClass.typeCheck(methodContext, typeContext);
|
||||
}
|
||||
result.type = "program";
|
||||
return result;
|
||||
}
|
||||
|
||||
public void codeGen() throws Exception {
|
||||
// Store the names of the generated class files
|
||||
List<String> classFileNames = new ArrayList<>();
|
||||
|
||||
try {
|
||||
for (RefType oneClass : classes) {
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null);
|
||||
|
||||
oneClass.codeGen(cw, methodContext, typeContext);
|
||||
oneClass.codeGen(cw, methodContext, typeContext);
|
||||
|
||||
cw.visitEnd();
|
||||
byte[] bytecode = cw.toByteArray();
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(oneClass.name + ".class")) {
|
||||
String classFileName = oneClass.name + ".class";
|
||||
classFileNames.add(classFileName);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(classFileName)) {
|
||||
fos.write(bytecode);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now create the JAR file
|
||||
try (FileOutputStream fos = new FileOutputStream("output.jar");
|
||||
JarOutputStream jos = new JarOutputStream(fos)) {
|
||||
|
||||
/*// Write the bytecode to a .class file in the .jar file
|
||||
JarEntry entry = new JarEntry(oneClass.name + ".class");
|
||||
jos.putNextEntry(entry);
|
||||
jos.write(bytecode);
|
||||
jos.closeEntry();
|
||||
for (String classFileName : classFileNames) {
|
||||
addFileToJar(jos, classFileName);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
|
||||
/*
|
||||
for(RefType oneClass : classes){
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC,oneClass.name, null,
|
||||
"java/lang/Object", null);
|
||||
oneClass.codeGen(cw);
|
||||
|
||||
cw.visitEnd();
|
||||
byte[] bytecode = cw.toByteArray();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFileToJar(JarOutputStream jos, String fileName) throws IOException {
|
||||
File file = new File(fileName);
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
JarEntry entry = new JarEntry(fileName);
|
||||
jos.putNextEntry(entry);
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
jos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
jos.closeEntry();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,8 +174,7 @@ public class Program implements Node {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Program program = (Program) o;
|
||||
System.out.println(classes);
|
||||
System.out.println(program.classes);
|
||||
System.out.println("In program: " + Objects.equals(classes, program.classes));
|
||||
return (Objects.equals(classes, program.classes));
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
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;
|
||||
@@ -13,12 +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;
|
||||
// do we need expression, statementexpression
|
||||
public String thisClass;
|
||||
|
||||
public BlockStatement(List<IStatement> statements, String returnType) {
|
||||
this.statements = statements;
|
||||
@@ -28,24 +28,54 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
|
||||
HashMap<String, HashMap<String, String>> typeContext,
|
||||
HashMap<String, String> localVars) throws Exception {
|
||||
HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
this.localVars = localVars;
|
||||
if (statements.size() == 0) {
|
||||
if (statements.isEmpty()) {
|
||||
result.type = "void";
|
||||
}
|
||||
|
||||
for (IStatement statement : statements) {
|
||||
|
||||
if(statement instanceof IfStatement ifStatement){
|
||||
ifStatement.thisClass = this.thisClass;
|
||||
}
|
||||
if(statement instanceof IfElseStatement ifElseStatement){
|
||||
ifElseStatement.thisClass = this.thisClass;
|
||||
}
|
||||
if(statement instanceof WhileStatement whileStatement){
|
||||
whileStatement.thisClass = this.thisClass;
|
||||
}
|
||||
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||
methodCall.thisClass = thisClass;
|
||||
}
|
||||
if(statement instanceof AssignStatementExpression assignStatementExpression){
|
||||
assignStatementExpression.thisClass = thisClass;
|
||||
}
|
||||
if(statement instanceof LocalVarDecl localVarDecl){
|
||||
localVarDecl.thisClass = thisClass;
|
||||
}
|
||||
if (statement instanceof PrintStatement printStatement) {
|
||||
printStatement.thisClass = thisClass;
|
||||
}
|
||||
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 LocalVarDecl){
|
||||
LocalVarDecl localVarDecl = (LocalVarDecl) statement;
|
||||
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||
typeOfCurrentStatement.type = "void";
|
||||
}
|
||||
if(statement instanceof LocalVarDecl localVarDecl){
|
||||
localVars.put(localVarDecl.identifier, localVarDecl.type);
|
||||
}
|
||||
|
||||
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];
|
||||
@@ -54,10 +84,10 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
|
||||
if (!firstType.equals(this.returnType) || !firstType.equals(this.returnType)) {
|
||||
if (!firstType.equals("void") && this.returnType != null) {
|
||||
throw new Exception("TypeCheck Exception: if paths return wrong type");
|
||||
throw new TypeCheckException("The if-Path returns the wrong type.");
|
||||
}
|
||||
if (!secondType.equals("void") && this.returnType != null) {
|
||||
throw new Exception("TypeCheck Exception: else paths return wrong type");
|
||||
throw new TypeCheckException("The else-path returns the wrong type.");
|
||||
}
|
||||
boolean firstIsVoid = firstType.equals("void");
|
||||
|
||||
@@ -69,34 +99,33 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(typeOfCurrentStatement.type.equals("void"))
|
||||
continue;
|
||||
// set return of block if not known yet
|
||||
|
||||
if(this.returnType == null)
|
||||
// set return of block if not known yet
|
||||
if(this.returnType == null|| this.returnType == "not")
|
||||
this.returnType = typeOfCurrentStatement.type;
|
||||
|
||||
if (!typeOfCurrentStatement.type.equals(this.returnType))
|
||||
throw new Exception("TypeCheck Exception: Block returns the wrong type.");
|
||||
throw new TypeCheckException("At least some statements of the block returns the wrong type or missing return statement.");
|
||||
}
|
||||
if(this.returnType == null)
|
||||
this.returnType = "void";
|
||||
|
||||
result.type = this.returnType;
|
||||
// todo check if the block returns the needed return type in every case
|
||||
// todo ignore unreachable statements?
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
// Create a new HashMap for the local variables of the block
|
||||
// It has every variable of the parent block
|
||||
// This Map is discarded at the end of the block
|
||||
//TODO: Do this for every block --> if, while, ...
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
for (IStatement statement : statements) {
|
||||
statement.codeGen(mv, blockLocalVars, typeContext);
|
||||
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,14 +134,17 @@ public class BlockStatement extends AbstractType implements IStatement {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BlockStatement blockStatement = (BlockStatement) o;
|
||||
return (Objects.equals(localVars, blockStatement.localVars)
|
||||
&& Objects.equals(returnType, blockStatement.returnType)
|
||||
&& Objects.equals(statements, blockStatement.statements)
|
||||
boolean result = Objects.equals(returnType, blockStatement.returnType)
|
||||
&& Objects.equals(statements, blockStatement.statements
|
||||
/*&& (Objects.equals(localVars, blockStatement.localVars)*/
|
||||
);
|
||||
System.out.println("In BlockStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -7,30 +7,32 @@ 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{
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "void";
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
//An empty statement does not generate any code
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return true;
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
@@ -11,8 +12,8 @@ import java.util.List;
|
||||
|
||||
public interface IStatement extends Node {
|
||||
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
|
||||
|
||||
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
||||
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,5 +1,6 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
@@ -8,13 +9,13 @@ 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{
|
||||
IExpression condition;
|
||||
public IExpression condition;
|
||||
IStatement ifStatement;
|
||||
IStatement elseStatement;
|
||||
public String thisClass;
|
||||
|
||||
public IfElseStatement(IExpression condition, IStatement ifStatement, IStatement elseStatement) {
|
||||
this.condition = condition;
|
||||
@@ -22,15 +23,21 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
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(ifStatement instanceof BlockStatement blockStatement){
|
||||
blockStatement.thisClass = thisClass;
|
||||
}
|
||||
if(elseStatement instanceof BlockStatement blockStatement){
|
||||
blockStatement.thisClass = thisClass;
|
||||
}
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
if (!conditionType.type.equals("bool")) {
|
||||
throw new IllegalArgumentException("should be boolean");
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new TypeCheckException("The condition of a if statement is " + conditionType.type + ", but should be boolean.");
|
||||
}
|
||||
|
||||
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
|
||||
@@ -38,7 +45,7 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
|
||||
if (!ifStatementType.type.equals(elseStatementType.type)) {
|
||||
if(ifStatementType.type != "void" && elseStatementType.type != "void")
|
||||
throw new IllegalArgumentException("TypeCeck Exception: if and else have different types");
|
||||
throw new TypeCheckException("If- and else-path return different not-void types.");
|
||||
}
|
||||
|
||||
result.type = ifStatementType.type + "," + elseStatementType.type;
|
||||
@@ -46,23 +53,23 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
Label statementEnd = new Label();
|
||||
|
||||
condition.codeGen(mv, localVars, typeContext);
|
||||
condition.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.codeGen(mv, blockLocalVars, typeContext); //If the condition is true, execute the ifBlock
|
||||
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
|
||||
ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is true, execute the ifBlock
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the else statement
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
elseStatement.codeGen(mv, blockLocalVars, typeContext); //If the condition is false, execute the elseBlock
|
||||
elseStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is false, execute the elseBlock
|
||||
|
||||
mv.visitLabel(statementEnd); //End of the if-else statement
|
||||
|
||||
@@ -73,14 +80,17 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IfElseStatement ifElseStatement = (IfElseStatement) o;
|
||||
return (Objects.equals(condition, ifElseStatement.condition)
|
||||
boolean result = (Objects.equals(condition, ifElseStatement.condition)
|
||||
&& Objects.equals(ifStatement, ifElseStatement.ifStatement)
|
||||
&& Objects.equals(elseStatement, ifElseStatement.elseStatement)
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
@@ -8,14 +9,12 @@ 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{
|
||||
IExpression condition;
|
||||
|
||||
//Do we need a block statement here?
|
||||
public IExpression condition;
|
||||
IStatement ifStatement;
|
||||
public String thisClass;
|
||||
|
||||
public IfStatement(IExpression condition, IStatement ifStatement) {
|
||||
this.condition = condition;
|
||||
@@ -23,31 +22,34 @@ public class IfStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
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();
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
if (!conditionType.equals("bool")) {
|
||||
throw new Exception("TypeCheck Exception: Condition of If-Statement should be bool.");
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new TypeCheckException("Condition of If-Statement is " + conditionType.type + ", but should be boolean.");
|
||||
}
|
||||
|
||||
if(ifStatement instanceof BlockStatement blockStatement){
|
||||
blockStatement.thisClass = thisClass;
|
||||
}
|
||||
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
|
||||
result.type = ifStatementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
|
||||
condition.codeGen(mv, localVars, typeContext);
|
||||
condition.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.codeGen(mv, blockLocalVars, typeContext);
|
||||
ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||
|
||||
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
||||
}
|
||||
@@ -57,14 +59,17 @@ public class IfStatement extends AbstractType implements IStatement{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IfStatement ifStatementObj = (IfStatement) o;
|
||||
return (Objects.equals(condition, ifStatementObj.condition)
|
||||
boolean result = (Objects.equals(condition, ifStatementObj.condition)
|
||||
&& Objects.equals(ifStatement, ifStatementObj.ifStatement)
|
||||
);
|
||||
System.out.println("In IfStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +1,96 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class LocalVarDecl implements IStatement{
|
||||
public class LocalVarDecl extends AbstractType implements IStatement{
|
||||
String type;
|
||||
String identifier;
|
||||
public LocalVarDecl(String type, String identifier) {
|
||||
IExpression expression;
|
||||
public String thisClass;
|
||||
public LocalVarDecl(String type, String identifier, IExpression expression) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
TypeCheckHelper.typeExists(this.type, new ArrayList<>(methodContext.keySet()));
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
|
||||
// left
|
||||
TypeCheckHelper.typeExists(this.type, new ArrayList<>(methodContext.keySet()));
|
||||
localVars.put(this.identifier, this.type);
|
||||
|
||||
// right part if existing
|
||||
if(expression != null){
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "void";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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);
|
||||
|
||||
// Set a default value for the variable --> less problems
|
||||
int index = localVars.size()-1;
|
||||
|
||||
switch (type){
|
||||
case "int":
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
case "bool":
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
default:
|
||||
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||
|
||||
if (index == -1){
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
|
||||
if (expression != null) {
|
||||
expression.codeGen(mv, localVars, typeContext,methodContext);
|
||||
|
||||
// Store the result in the local variable
|
||||
switch (type){
|
||||
case "int", "char", "boolean":
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
default:
|
||||
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||
}
|
||||
} else {
|
||||
|
||||
// Set a default value for the variable --> fewer problems
|
||||
switch (type) {
|
||||
case "int", "boolean", "char":
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
default:
|
||||
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,13 +99,16 @@ public class LocalVarDecl implements IStatement{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
LocalVarDecl localVarDecl = (LocalVarDecl) o;
|
||||
return (Objects.equals(type, localVarDecl.type)
|
||||
boolean result = (Objects.equals(type, localVarDecl.type)
|
||||
&& Objects.equals(identifier, localVarDecl.identifier)
|
||||
);
|
||||
System.out.println("In LocalVarDecl: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PrintStatement extends AbstractType implements IStatement {
|
||||
String variableName;
|
||||
public String thisClass;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PrintStatement printStatement = (PrintStatement) o;
|
||||
boolean result = (Objects.equals(variableName, printStatement.variableName)
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public PrintStatement(String variableName) {
|
||||
this.variableName = variableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
String typeOfVar = localVars.get(variableName);
|
||||
if (typeOfVar == null) {
|
||||
typeOfVar = typeContext.get(thisClass).get(variableName);
|
||||
}
|
||||
if (!Objects.equals(typeOfVar, "int"))
|
||||
throw new TypeCheckException("The variable to be printed is " + typeOfVar + " but should be int.");
|
||||
result.type = "void";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@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 {
|
||||
// Load System.out onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||
|
||||
// Load the value of the variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, variableName);
|
||||
|
||||
// If not a localVar, maybe a class field of this class
|
||||
if (index == -1){
|
||||
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);
|
||||
|
||||
// Call the println method
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +1,40 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
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) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
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 (expression == null) {
|
||||
result.type = "void";
|
||||
} else {
|
||||
if(expression instanceof MethodCallStatementExpression methodCallStatementExpression)
|
||||
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;
|
||||
}
|
||||
@@ -33,23 +43,19 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
||||
return result;
|
||||
}
|
||||
|
||||
//TODO: We do not differentiate between primitive types and reference types
|
||||
// This is a problem at "BinaryExpression" and here because we need to know the type to return
|
||||
// At this point in time we can either return reference types or have an error message
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
|
||||
if (expression != null) {
|
||||
expression.codeGen(mv, localVars, typeContext);
|
||||
expression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
//Get the Type of the expression
|
||||
//TODO: Resolve how do we get the type of the expression
|
||||
String type = expression.getTypeCheckResult().type;
|
||||
|
||||
if (type.equals("int") || type.equals("bool") || type.equals("char")) {
|
||||
if (type.equals("int") || type.equals("boolean") || type.equals("char")) {
|
||||
mv.visitInsn(Opcodes.IRETURN);
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
@@ -61,12 +67,16 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ReturnStatement returnStatement = (ReturnStatement) o;
|
||||
return (Objects.equals(expression, returnStatement.expression)
|
||||
boolean result = (Objects.equals(expression, returnStatement.expression)
|
||||
&& Objects.equals(expression.getTypeCheckResult(), returnStatement.expression.getTypeCheckResult())
|
||||
);
|
||||
System.out.println("In ReturnStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public TypeCheckResult getTypeCheckResult() {
|
||||
// return this.
|
||||
// }
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
@@ -8,12 +9,12 @@ 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 {
|
||||
IExpression condition;
|
||||
IStatement statement;
|
||||
public String thisClass;
|
||||
|
||||
public WhileStatement(IExpression condition, IStatement statement) {
|
||||
this.condition = condition;
|
||||
@@ -21,13 +22,13 @@ public class WhileStatement extends AbstractType implements IStatement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
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();
|
||||
|
||||
// check condition
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
if (!conditionType.equals("bool")) {
|
||||
throw new IllegalArgumentException("Expected boolean");
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new TypeCheckException("Condition of while-statement is of type " + conditionType.type + " but should be boolean.");
|
||||
}
|
||||
|
||||
// check code block
|
||||
@@ -40,7 +41,7 @@ public class WhileStatement extends AbstractType implements IStatement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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 {
|
||||
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
@@ -49,13 +50,11 @@ public class WhileStatement extends AbstractType implements IStatement {
|
||||
|
||||
mv.visitLabel(LoopStart);
|
||||
|
||||
condition.codeGen(mv, localVars, typeContext);
|
||||
condition.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
||||
|
||||
statement.codeGen(mv, blockLocalVars, typeContext);
|
||||
//statement.codeGen(mv);
|
||||
//TODO: If the block ends with a return statement, we might have to pop it from the stack
|
||||
// So the next iteration starts with a clean stack
|
||||
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
@@ -66,13 +65,17 @@ public class WhileStatement extends AbstractType implements IStatement {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
WhileStatement whileStatement = (WhileStatement) o;
|
||||
return (Objects.equals(condition, whileStatement.condition)
|
||||
boolean result = (Objects.equals(condition, whileStatement.condition)
|
||||
&& Objects.equals(statement, whileStatement.statement)
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return getTypeCheckResult();
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +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;
|
||||
@@ -20,6 +22,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
public IExpression left;
|
||||
public IExpression right;
|
||||
private InstVarExpression instVar;
|
||||
public String thisClass;
|
||||
|
||||
public AssignStatementExpression(String operator, IExpression leftExpression, IExpression rightExpression){
|
||||
this.operator = operator;
|
||||
@@ -28,27 +31,40 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||
TypeCheckHelper helper = new TypeCheckHelper();
|
||||
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();
|
||||
|
||||
TypeCheckResult leftType;
|
||||
|
||||
if (left instanceof LocalVarIdentifier) {
|
||||
if (left instanceof LocalVarIdentifier localVarIdentifier) {
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
leftType = new TypeCheckResult();
|
||||
LocalVarIdentifier localVarIdentifier = (LocalVarIdentifier) left;
|
||||
String identifier = localVarIdentifier.getIdentifier();
|
||||
leftType.type = localVars.get(identifier);
|
||||
}else{
|
||||
|
||||
// local var may be actually instVar of this
|
||||
if(leftType.type == null){
|
||||
leftType.type = typeContext.get(thisClass).get(identifier);
|
||||
}
|
||||
}else {
|
||||
if(left instanceof InstVarExpression instVarExpression)
|
||||
instVarExpression.thisClass = this.thisClass;
|
||||
leftType = left.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
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);
|
||||
|
||||
String upperbound = helper.upperBound(leftType.type, rightType.type);
|
||||
String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||
if(Objects.equals(leftType.type, "boolean"))
|
||||
leftType.type = "bool";
|
||||
leftType.type = "boolean";
|
||||
if (!Objects.equals(upperbound, leftType.type)) {
|
||||
throw new Exception("TypeCheck Exception: upper bound of assignment is not left type");
|
||||
throw new TypeCheckException("The upper bound of assignment is not the left type.");
|
||||
}
|
||||
result.type = "void";
|
||||
setTypeCheckResult(result);
|
||||
@@ -61,36 +77,37 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
//TODO: Do we need the value on the stack after assigning it?
|
||||
//TODO: WE do not differentiate between InstanceVar and FieldVar
|
||||
|
||||
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||
right.codeGen(mv, localVars, typeContext);
|
||||
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 {
|
||||
|
||||
if (left instanceof LocalVarIdentifier) {
|
||||
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, varName);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Exception("Variable " + varName + " not found");
|
||||
String fieldType = typeContext.get(thisClass).get(varName);
|
||||
if (fieldType != null) {
|
||||
// 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);
|
||||
// Get the field descriptor
|
||||
String descriptor = getFieldDescriptor(fieldType, typeContext, varName, thisClass);
|
||||
// Store the value in the field
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, thisClass, varName, descriptor);
|
||||
return;
|
||||
} else {
|
||||
throw new Exception("Variable " + varName + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
String type = localVars.get(localVar.getIdentifier());
|
||||
// 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);
|
||||
switch (type) {
|
||||
case "int":
|
||||
case "bool":
|
||||
case "int", "char", "boolean":
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
default:
|
||||
@@ -101,38 +118,129 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
} else if (left instanceof InstVarExpression) {
|
||||
instVar = (InstVarExpression) left;
|
||||
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
boolean isLocal = false;
|
||||
|
||||
// Duplicate the top of the stack as we'll need it for both the PUTFIELD and subsequent expressions
|
||||
mv.visitInsn(Opcodes.DUP_X1);
|
||||
// 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 = CodeGenHelper.GetLocalVarIndex(localVars, instVar.receivers.get(0).identifier);
|
||||
|
||||
// Get the field information
|
||||
String fieldType = typeContext.get(instVar.classRef.name).get(instVar.fieldName);
|
||||
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);
|
||||
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
|
||||
switch (fieldType) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "bool":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
default:
|
||||
String fullReturnType = typeContext.get(instVar.classRef.name).get(instVar.fieldName);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Store the value in the field
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.classRef.name, instVar.fieldName, descriptor.toString());
|
||||
//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
|
||||
|
||||
String typeOfPrevious = "";
|
||||
String currentType = "";
|
||||
if (instVar.receivers.size() > 0) {
|
||||
for (int i = 0; i < instVar.receivers.size(); i++) {
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext, String varName, String classToSearchFieldIn) {
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default: {
|
||||
String fullReturnType = typeContext.get(classToSearchFieldIn).get(varName);
|
||||
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (type.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||
return descriptor.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -143,4 +251,8 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
&& Objects.equals(right, assignStatementExpression.right)
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
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 org.objectweb.asm.ClassWriter;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@@ -18,8 +17,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
List<IExpression> arguments;
|
||||
Receiver receiver;
|
||||
List<ReceivingMethod> receivingMethods;
|
||||
RefType classThatHasTheMethodIfNotThis;
|
||||
RefType thisClass;
|
||||
public String thisClass;
|
||||
|
||||
public MethodCallStatementExpression(String methodName, Receiver receiver, List<ReceivingMethod> receivingMethods, List<IExpression> arguments) {
|
||||
this.methodName = methodName;
|
||||
@@ -28,79 +26,287 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
|
||||
RefType searchMethodHere;
|
||||
if(classThatHasTheMethodIfNotThis == null){
|
||||
searchMethodHere = thisClass;
|
||||
String classToSearchMethodIn = thisClass;
|
||||
|
||||
if (this.receiver != null) {
|
||||
if (!receiver.thisExpression) {
|
||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
if (classToSearchMethodIn == null)
|
||||
classToSearchMethodIn = thisClass;
|
||||
}
|
||||
}
|
||||
|
||||
String currentType = "";
|
||||
|
||||
// receiver is instVar
|
||||
if (receiver != null) {
|
||||
if (receiver.instVarExpression != null) {
|
||||
receiver.instVarExpression.thisClass = this.thisClass;
|
||||
String typeOfSubreceiver = receiver.instVarExpression.typeCheck(methodContext, typeContext, localVars).type;
|
||||
|
||||
currentType = typeOfSubreceiver;
|
||||
} else {
|
||||
currentType = classToSearchMethodIn;
|
||||
}
|
||||
} else {
|
||||
searchMethodHere = classThatHasTheMethodIfNotThis;
|
||||
currentType = thisClass;
|
||||
}
|
||||
|
||||
List<MethodDecl> methods = searchMethodHere.methodDecls;
|
||||
|
||||
if(!methods.contains(methodName)){
|
||||
throw new Exception("method not found");
|
||||
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;
|
||||
receivingMethods.get(i).checkParameters(methodContext, typeContext, localVars);
|
||||
}
|
||||
currentType = (String) methodContext.get(currentType).get(methodName).keySet().toArray()[0];
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = currentType;
|
||||
setTypeCheckResult(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 Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Errors occur due to the change in parameter in the RefType class
|
||||
// I need the methodContext here to get the method descriptor
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
//Generate Bytecode for the receiver
|
||||
if (classThatHasTheMethodIfNotThis != null) {
|
||||
//TODO: classThatHasTheMethodIfNotThis must be an object --> instance of the class not the class itself
|
||||
// Need to call codeGen so it pushes the instance onto the stack, which will be popped of
|
||||
//classThatHasTheMethodIfNotThis.codeGen();
|
||||
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 {
|
||||
String owner;
|
||||
|
||||
String descriptor;
|
||||
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
||||
for (MethodDecl methodDecl : methodDecls) {
|
||||
if (methodDecl.name.equals(methodName)) {
|
||||
//Get the method descriptor
|
||||
// descriptor = methodDecl.getMethodDescriptor(methodContext);
|
||||
// Load the object onto the stack
|
||||
if (receiver != null) {
|
||||
if (receiver.thisExpression) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
owner = thisClass;
|
||||
} else if (receiver.instVarExpression != null) {
|
||||
receiver.instVarExpression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
owner = receiver.instVarExpression.getTypeCheckResult().type;
|
||||
} else if (receiver.newStatementExpression != null) {
|
||||
receiver.newStatementExpression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
owner = receiver.newStatementExpression.getTypeCheckResult().type;
|
||||
} else if (receiver.identifier != null) {
|
||||
String type = localVars.get(receiver.identifier);
|
||||
if (type == null) {
|
||||
// If it is not a local variable, assume it is a field of the current class
|
||||
type = typeContext.get(thisClass).get(receiver.identifier);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0); // Load "this" onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";"); // Load the field onto the stack
|
||||
} else {
|
||||
// It's a local variable
|
||||
int index = localVars.keySet().stream().toList().indexOf(receiver.identifier) + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
|
||||
mv.visitVarInsn(opcode, index); // Load local variable onto the stack
|
||||
}
|
||||
owner = type;
|
||||
} else {
|
||||
throw new ExecutionControl.NotImplementedException("Receiver type not supported.");
|
||||
}
|
||||
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classThatHasTheMethodIfNotThis.name, methodName, descriptor, false);
|
||||
|
||||
} else {
|
||||
// Load this onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
owner = thisClass;
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext);
|
||||
}
|
||||
String returnOfPreviousMethod = null;
|
||||
// Invoke the method for each receiving method in the chain
|
||||
for (ReceivingMethod receivingMethod : receivingMethods) {
|
||||
// Get the owner class for the current method in the chain
|
||||
if (returnOfPreviousMethod != null) {
|
||||
// If the return of the previous method is not null, use it as the owner class for the current method in the chain
|
||||
owner = returnOfPreviousMethod;
|
||||
}
|
||||
|
||||
// Get the method descriptor
|
||||
String descriptor;
|
||||
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
||||
for (MethodDecl methodDecl : methodDecls) {
|
||||
if (methodDecl.name.equals(methodName)) {
|
||||
//Get the method descriptor
|
||||
// descriptor = methodDecl.getMethodDescriptor(methodContext);
|
||||
// Generate the code for each argument expression for the current method
|
||||
for (IExpression argument : receivingMethod.arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
|
||||
// Invoke the current method
|
||||
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);
|
||||
}
|
||||
|
||||
// Invoke the final method
|
||||
|
||||
// Generate the code for each argument expression
|
||||
for (IExpression argument : arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
|
||||
if (returnOfPreviousMethod != null) {
|
||||
owner = returnOfPreviousMethod;
|
||||
}
|
||||
|
||||
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
TypeCheckResult result = argument.getTypeCheckResult();
|
||||
String type = result.type;
|
||||
|
||||
switch (type) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
case "void":
|
||||
descriptor.append("V");
|
||||
break;
|
||||
default:
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (type.contains(".")) type = type.replaceAll("\\.", "/");
|
||||
descriptor.append("L").append(type).append(";");
|
||||
break;
|
||||
}
|
||||
}
|
||||
descriptor.append(")");
|
||||
|
||||
String classToSearchMethodIn;
|
||||
//Return Type
|
||||
if (receiver != null) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, descriptor, false);
|
||||
} else {
|
||||
classToSearchMethodIn = thisClass;
|
||||
}
|
||||
|
||||
|
||||
String returnType = methodContext.get(classToSearchMethodIn).get(methodName).keySet().toArray()[0].toString();
|
||||
|
||||
switch (returnType) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
case "void":
|
||||
descriptor.append("V");
|
||||
break;
|
||||
default:
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (returnType.contains(".")) returnType = returnType.replaceAll("\\.", "/");
|
||||
descriptor.append("L").append(returnType).append(";");
|
||||
break;
|
||||
}
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MethodCallStatementExpression methodCallStatementExpression = (MethodCallStatementExpression) o;
|
||||
return (Objects.equals(methodName, methodCallStatementExpression.methodName)
|
||||
&& Objects.equals(arguments, methodCallStatementExpression.arguments)
|
||||
);
|
||||
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
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
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,18 +25,45 @@ public class NewStatementExpression 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 Exception {
|
||||
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
|
||||
throw new Exception("TypeCheck Exception: An instance of " + className + " is created, but the type does not exist.");
|
||||
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());
|
||||
}
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = className;
|
||||
setTypeCheckResult(result);
|
||||
boolean result = (Objects.equals(className, newStatementExpression.className)
|
||||
&& Objects.equals(arguments, newStatementExpression.arguments)
|
||||
);
|
||||
System.out.println("In newStatementExpression: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
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;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@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 {
|
||||
//Create new instance of the class
|
||||
mv.visitTypeInsn(Opcodes.NEW, className);
|
||||
|
||||
@@ -45,16 +71,20 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext);
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
String descriptor = getConstructorDescriptor();
|
||||
|
||||
//Call the constructor
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", descriptor, false);
|
||||
|
||||
// One instance of the class remains now on the stack
|
||||
// Which will then be used in an assignment or method call
|
||||
}
|
||||
|
||||
private String getConstructorDescriptor() {
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
|
||||
for (IExpression parameter : arguments) {
|
||||
TypeCheckResult result = parameter.getTypeCheckResult();
|
||||
@@ -64,7 +94,7 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "bool":
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
@@ -84,4 +114,8 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
||||
descriptor.append(")V"); // Constructors always return void
|
||||
return descriptor.toString();
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,33 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Receiver implements Node {
|
||||
boolean thisExpression;
|
||||
InstVarExpression instVarExpression;
|
||||
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;
|
||||
}
|
||||
@@ -24,6 +43,7 @@ public class Receiver implements Node {
|
||||
public Receiver(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,43 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ReceivingMethod implements Node {
|
||||
String methodName;
|
||||
List<IExpression> arguments;
|
||||
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;
|
||||
}
|
||||
void checkParameters(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
for (IExpression parameter : arguments){
|
||||
if(parameter instanceof LocalVarIdentifier localVarIdentifier){
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
}
|
||||
parameter.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,42 +32,57 @@ 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<>()), new BlockStatement(new ArrayList<>(), "void"));
|
||||
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) {
|
||||
return new FieldDecl(ctx.type().getText(), ctx.Identifier().getText());
|
||||
if (ctx.expression() != null) {
|
||||
IExpression expression = (IExpression) visit(ctx.expression());
|
||||
return new FieldDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||
} else {
|
||||
return new FieldDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText());
|
||||
if (ctx.expression() != null) {
|
||||
IExpression expression = (IExpression) visit(ctx.expression());
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||
} else {
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitConstuctorDecl(DecafParser.ConstuctorDeclContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
ParameterList parameterList = (ParameterList) visit(ctx.parameterList());
|
||||
return new MethodDecl("", null, name, parameterList, new BlockStatement(new ArrayList<>(), "void"));
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
if (ctx.parameterList() != null) {
|
||||
parameterList = (ParameterList) visit(ctx.parameterList());
|
||||
}
|
||||
BlockStatement block = (BlockStatement) visitBlock(ctx.block());
|
||||
return new MethodDecl("", null, name, parameterList, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,13 +90,16 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
String type;
|
||||
String name = ctx.Identifier().getText();
|
||||
BlockStatement block = (BlockStatement) visitBlock(ctx.block());
|
||||
ParameterList parameterList = (ParameterList) visit(ctx.parameterList());
|
||||
if (ctx.Void() != null) {
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
if (ctx.parameterList() != null) {
|
||||
parameterList = (ParameterList) visit(ctx.parameterList());
|
||||
}
|
||||
if (ctx.Void() != null) {
|
||||
type = "void";
|
||||
} else {
|
||||
type = ctx.type().getText();
|
||||
}
|
||||
return new MethodDecl("", type , name, parameterList, block);
|
||||
return new MethodDecl("", type, name, parameterList, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,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);
|
||||
@@ -114,20 +132,26 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
return visitEmptyStatement(ctx.emptyStatement());
|
||||
} else if (ctx.localVarDecl() != null) {
|
||||
return visitLocalVarDecl(ctx.localVarDecl());
|
||||
} else if (ctx.print() != null) {
|
||||
return visitPrint(ctx.print());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
@@ -175,27 +199,35 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
} else if (ctx.newDecl() != null) {
|
||||
return visitNewDecl(ctx.newDecl());
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPrint(DecafParser.PrintContext ctx) {
|
||||
return new PrintStatement(ctx.Identifier().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public Node visitMethodCall(DecafParser.MethodCallContext ctx) {
|
||||
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));
|
||||
}
|
||||
Receiver receiver = (Receiver) visit(ctx.receiver());
|
||||
return new MethodCallStatementExpression(methodName, receiver, receivingMethods, arguments);
|
||||
if (ctx.receiver() != null) {
|
||||
Receiver receiver = (Receiver) visit(ctx.receiver());
|
||||
return new MethodCallStatementExpression(methodName, receiver, receivingMethods, arguments);
|
||||
} else {
|
||||
return new MethodCallStatementExpression(methodName, null, receivingMethods, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,6 +249,18 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitSubReceiver(DecafParser.SubReceiverContext ctx) {
|
||||
if (ctx.This() != null) {
|
||||
return new SubReceiver(true);
|
||||
} else if (ctx.newDecl() != null) {
|
||||
return new SubReceiver((NewStatementExpression) visit(ctx.newDecl()));
|
||||
} else if (ctx.Identifier() != null) {
|
||||
return new SubReceiver(ctx.Identifier().getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitNewDecl(DecafParser.NewDeclContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
@@ -243,7 +287,8 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
} else if (ctx.value() != null) {
|
||||
return visitValue(ctx.value());
|
||||
} else if (ctx.binaryExpr() != null) {
|
||||
//todo
|
||||
IExpression expression = (IExpression) visit(ctx.binaryExpr());
|
||||
return new UnaryExpression("!", expression);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -255,9 +300,8 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
Node right = visitDotExpr(ctx.dotExpr());
|
||||
return new BinaryExpression(ctx.LineOperator().getText(), (IExpression) left, (IExpression) right);
|
||||
} else {
|
||||
visitDotExpr(ctx.dotExpr());
|
||||
return visitDotExpr(ctx.dotExpr());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,23 +311,23 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
Node right = visitDotSubExpr(ctx.dotSubExpr());
|
||||
return new BinaryExpression(ctx.DotOperator().getText(), (IExpression) left, (IExpression) right);
|
||||
} else {
|
||||
visitDotSubExpr(ctx.dotSubExpr());
|
||||
return visitDotSubExpr(ctx.dotSubExpr());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//todo
|
||||
@Override
|
||||
public Node visitDotSubExpr(DecafParser.DotSubExprContext ctx) {
|
||||
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.calcExpr() != null) {
|
||||
} else if (ctx.methodCall() != null) {
|
||||
return visitMethodCall(ctx.methodCall());
|
||||
} else if (ctx.calcExpr() != null) {
|
||||
return visitCalcExpr(ctx.calcExpr());
|
||||
}
|
||||
return null;
|
||||
@@ -292,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();
|
||||
@@ -318,13 +362,24 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
public Node visitAssignableExpr(DecafParser.AssignableExprContext ctx) {
|
||||
if (ctx.Identifier() != null) {
|
||||
return new LocalVarIdentifier(ctx.Identifier().getText());
|
||||
} else if (ctx.instVar() != null) {
|
||||
return visitInstVar(ctx.instVar());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitInstVar(DecafParser.InstVarContext ctx) {
|
||||
return super.visitInstVar(ctx);
|
||||
List<SubReceiver> receivers = new ArrayList<>();
|
||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||
String fieldName = ctx.Identifier().getText();
|
||||
for (DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
||||
receivers.add((SubReceiver) visit(subReceiver));
|
||||
}
|
||||
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||
}
|
||||
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
||||
}
|
||||
|
||||
public List<IExpression> generateExpressions(DecafParser.ArgumentListContext ctx) {
|
||||
@@ -348,13 +403,8 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getReturnType(List<IStatement> statements){
|
||||
for(IStatement stmt: statements) {
|
||||
if(stmt instanceof ReturnStatement) {
|
||||
return "not";
|
||||
}
|
||||
}
|
||||
return "void";
|
||||
public String getReturnType(List<IStatement> statements) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,81 +1,83 @@
|
||||
BooleanValue=1
|
||||
NullValue=2
|
||||
AccessModifierPublic=3
|
||||
MainMethodDecl=4
|
||||
Void=5
|
||||
Int=6
|
||||
Boolean=7
|
||||
Char=8
|
||||
DotOperator=9
|
||||
LineOperator=10
|
||||
ComparisonOperator=11
|
||||
LogicalOpertor=12
|
||||
Assign=13
|
||||
Minus=14
|
||||
Plus=15
|
||||
Multipilkation=16
|
||||
Division=17
|
||||
Modulo=18
|
||||
Greater=19
|
||||
Less=20
|
||||
GreaterEqual=21
|
||||
LessEqual=22
|
||||
Equal=23
|
||||
NotEqual=24
|
||||
Not=25
|
||||
And=26
|
||||
Or=27
|
||||
Dot=28
|
||||
OpenRoundBracket=29
|
||||
ClosedRoundBracket=30
|
||||
OpenCurlyBracket=31
|
||||
ClosedCurlyBracket=32
|
||||
Semicolon=33
|
||||
Comma=34
|
||||
Class=35
|
||||
This=36
|
||||
While=37
|
||||
If=38
|
||||
Else=39
|
||||
Return=40
|
||||
New=41
|
||||
IntValue=42
|
||||
CharValue=43
|
||||
Identifier=44
|
||||
WS=45
|
||||
'null'=2
|
||||
'public'=3
|
||||
'public static void main(String[] args)'=4
|
||||
'void'=5
|
||||
'int'=6
|
||||
'boolean'=7
|
||||
'char'=8
|
||||
'='=13
|
||||
'-'=14
|
||||
'+'=15
|
||||
'*'=16
|
||||
'/'=17
|
||||
'%'=18
|
||||
'>'=19
|
||||
'<'=20
|
||||
'>='=21
|
||||
'<='=22
|
||||
'=='=23
|
||||
'!='=24
|
||||
'!'=25
|
||||
'&&'=26
|
||||
'||'=27
|
||||
'.'=28
|
||||
'('=29
|
||||
')'=30
|
||||
'{'=31
|
||||
'}'=32
|
||||
';'=33
|
||||
','=34
|
||||
'class'=35
|
||||
'this'=36
|
||||
'while'=37
|
||||
'if'=38
|
||||
'else'=39
|
||||
'return'=40
|
||||
'new'=41
|
||||
T__0=1
|
||||
BooleanValue=2
|
||||
NullValue=3
|
||||
AccessModifierPublic=4
|
||||
MainMethodDecl=5
|
||||
Void=6
|
||||
Int=7
|
||||
Boolean=8
|
||||
Char=9
|
||||
DotOperator=10
|
||||
LineOperator=11
|
||||
ComparisonOperator=12
|
||||
LogicalOpertor=13
|
||||
Assign=14
|
||||
Minus=15
|
||||
Plus=16
|
||||
Multipilkation=17
|
||||
Division=18
|
||||
Modulo=19
|
||||
Greater=20
|
||||
Less=21
|
||||
GreaterEqual=22
|
||||
LessEqual=23
|
||||
Equal=24
|
||||
NotEqual=25
|
||||
Not=26
|
||||
And=27
|
||||
Or=28
|
||||
Dot=29
|
||||
OpenRoundBracket=30
|
||||
ClosedRoundBracket=31
|
||||
OpenCurlyBracket=32
|
||||
ClosedCurlyBracket=33
|
||||
Semicolon=34
|
||||
Comma=35
|
||||
Class=36
|
||||
This=37
|
||||
While=38
|
||||
If=39
|
||||
Else=40
|
||||
Return=41
|
||||
New=42
|
||||
IntValue=43
|
||||
CharValue=44
|
||||
Identifier=45
|
||||
WS=46
|
||||
'print'=1
|
||||
'null'=3
|
||||
'public'=4
|
||||
'public static void main(String[] args)'=5
|
||||
'void'=6
|
||||
'int'=7
|
||||
'boolean'=8
|
||||
'char'=9
|
||||
'='=14
|
||||
'-'=15
|
||||
'+'=16
|
||||
'*'=17
|
||||
'/'=18
|
||||
'%'=19
|
||||
'>'=20
|
||||
'<'=21
|
||||
'>='=22
|
||||
'<='=23
|
||||
'=='=24
|
||||
'!='=25
|
||||
'!'=26
|
||||
'&&'=27
|
||||
'||'=28
|
||||
'.'=29
|
||||
'('=30
|
||||
')'=31
|
||||
'{'=32
|
||||
'}'=33
|
||||
';'=34
|
||||
','=35
|
||||
'class'=36
|
||||
'this'=37
|
||||
'while'=38
|
||||
'if'=39
|
||||
'else'=40
|
||||
'return'=41
|
||||
'new'=42
|
||||
|
||||
@@ -432,6 +432,18 @@ public class DecafBaseListener implements DecafListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitValue(DecafParser.ValueContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterPrint(DecafParser.PrintContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitPrint(DecafParser.PrintContext ctx) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
||||
@@ -257,4 +257,11 @@ public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitValue(DecafParser.ValueContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitPrint(DecafParser.PrintContext ctx) { return visitChildren(ctx); }
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -17,14 +17,14 @@ public class DecafLexer extends Lexer {
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
BooleanValue=1, NullValue=2, AccessModifierPublic=3, MainMethodDecl=4,
|
||||
Void=5, Int=6, Boolean=7, Char=8, DotOperator=9, LineOperator=10, ComparisonOperator=11,
|
||||
LogicalOpertor=12, Assign=13, Minus=14, Plus=15, Multipilkation=16, Division=17,
|
||||
Modulo=18, Greater=19, Less=20, GreaterEqual=21, LessEqual=22, Equal=23,
|
||||
NotEqual=24, Not=25, And=26, Or=27, Dot=28, OpenRoundBracket=29, ClosedRoundBracket=30,
|
||||
OpenCurlyBracket=31, ClosedCurlyBracket=32, Semicolon=33, Comma=34, Class=35,
|
||||
This=36, While=37, If=38, Else=39, Return=40, New=41, IntValue=42, CharValue=43,
|
||||
Identifier=44, WS=45;
|
||||
T__0=1, BooleanValue=2, NullValue=3, AccessModifierPublic=4, MainMethodDecl=5,
|
||||
Void=6, Int=7, Boolean=8, Char=9, DotOperator=10, LineOperator=11, ComparisonOperator=12,
|
||||
LogicalOpertor=13, Assign=14, Minus=15, Plus=16, Multipilkation=17, Division=18,
|
||||
Modulo=19, Greater=20, Less=21, GreaterEqual=22, LessEqual=23, Equal=24,
|
||||
NotEqual=25, Not=26, And=27, Or=28, Dot=29, OpenRoundBracket=30, ClosedRoundBracket=31,
|
||||
OpenCurlyBracket=32, ClosedCurlyBracket=33, Semicolon=34, Comma=35, Class=36,
|
||||
This=37, While=38, If=39, Else=40, Return=41, New=42, IntValue=43, CharValue=44,
|
||||
Identifier=45, WS=46;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
@@ -35,7 +35,7 @@ public class DecafLexer extends Lexer {
|
||||
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||
"T__0", "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
||||
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
||||
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
||||
@@ -49,7 +49,7 @@ public class DecafLexer extends Lexer {
|
||||
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, null, "'null'", "'public'", "'public static void main(String[] args)'",
|
||||
null, "'print'", null, "'null'", "'public'", "'public static void main(String[] args)'",
|
||||
"'void'", "'int'", "'boolean'", "'char'", null, null, null, null, "'='",
|
||||
"'-'", "'+'", "'*'", "'/'", "'%'", "'>'", "'<'", "'>='", "'<='", "'=='",
|
||||
"'!='", "'!'", "'&&'", "'||'", "'.'", "'('", "')'", "'{'", "'}'", "';'",
|
||||
@@ -60,7 +60,7 @@ public class DecafLexer extends Lexer {
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||
null, null, "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
||||
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
||||
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
||||
@@ -129,7 +129,7 @@ public class DecafLexer extends Lexer {
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\u0004\u0000-\u0145\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+
|
||||
"\u0004\u0000.\u014d\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+
|
||||
"\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+
|
||||
"\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+
|
||||
"\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b"+
|
||||
@@ -142,194 +142,198 @@ public class DecafLexer extends Lexer {
|
||||
"\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007"+
|
||||
"!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007"+
|
||||
"&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007"+
|
||||
"+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u0001\u0000"+
|
||||
"\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+
|
||||
"\u0001\u0000\u0001\u0000\u0003\u0000k\b\u0000\u0001\u0001\u0001\u0001"+
|
||||
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002"+
|
||||
"+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u00020\u0007"+
|
||||
"0\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+
|
||||
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+
|
||||
"\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001s\b\u0001\u0001\u0002"+
|
||||
"\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006"+
|
||||
"\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+
|
||||
"\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001"+
|
||||
"\b\u0001\b\u0003\b\u00b9\b\b\u0001\t\u0001\t\u0003\t\u00bd\b\t\u0001\n"+
|
||||
"\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0003\n\u00c5\b\n\u0001\u000b"+
|
||||
"\u0001\u000b\u0003\u000b\u00c9\b\u000b\u0001\f\u0001\f\u0001\r\u0001\r"+
|
||||
"\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010"+
|
||||
"\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013"+
|
||||
"\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015"+
|
||||
"\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017"+
|
||||
"\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a"+
|
||||
"\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c"+
|
||||
"\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f"+
|
||||
"\u0001 \u0001 \u0001!\u0001!\u0001\"\u0001\"\u0001\"\u0001\"\u0001\"\u0001"+
|
||||
"\"\u0001#\u0001#\u0001#\u0001#\u0001#\u0001$\u0001$\u0001$\u0001$\u0001"+
|
||||
"$\u0001$\u0001%\u0001%\u0001%\u0001&\u0001&\u0001&\u0001&\u0001&\u0001"+
|
||||
"\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001(\u0001(\u0001"+
|
||||
"(\u0001(\u0001)\u0005)\u0122\b)\n)\f)\u0125\t)\u0001)\u0004)\u0128\b)"+
|
||||
"\u000b)\f)\u0129\u0001*\u0001*\u0003*\u012e\b*\u0001*\u0001*\u0001+\u0001"+
|
||||
"+\u0001,\u0001,\u0001-\u0001-\u0001-\u0003-\u0139\b-\u0001.\u0001.\u0005"+
|
||||
".\u013d\b.\n.\f.\u0140\t.\u0001/\u0001/\u0001/\u0001/\u0000\u00000\u0001"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+
|
||||
"\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+
|
||||
"\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+
|
||||
"\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001"+
|
||||
"\t\u0003\t\u00c1\b\t\u0001\n\u0001\n\u0003\n\u00c5\b\n\u0001\u000b\u0001"+
|
||||
"\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u00cd"+
|
||||
"\b\u000b\u0001\f\u0001\f\u0003\f\u00d1\b\f\u0001\r\u0001\r\u0001\u000e"+
|
||||
"\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0011"+
|
||||
"\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0014"+
|
||||
"\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016"+
|
||||
"\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018"+
|
||||
"\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a"+
|
||||
"\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001d"+
|
||||
"\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001 \u0001"+
|
||||
" \u0001!\u0001!\u0001\"\u0001\"\u0001#\u0001#\u0001#\u0001#\u0001#\u0001"+
|
||||
"#\u0001$\u0001$\u0001$\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0001"+
|
||||
"%\u0001%\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'"+
|
||||
"\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001"+
|
||||
")\u0001)\u0001*\u0005*\u012a\b*\n*\f*\u012d\t*\u0001*\u0004*\u0130\b*"+
|
||||
"\u000b*\f*\u0131\u0001+\u0001+\u0003+\u0136\b+\u0001+\u0001+\u0001,\u0001"+
|
||||
",\u0001-\u0001-\u0001.\u0001.\u0001.\u0003.\u0141\b.\u0001/\u0001/\u0005"+
|
||||
"/\u0145\b/\n/\f/\u0148\t/\u00010\u00010\u00010\u00010\u0000\u00001\u0001"+
|
||||
"\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t\u0005\u000b\u0006\r\u0007"+
|
||||
"\u000f\b\u0011\t\u0013\n\u0015\u000b\u0017\f\u0019\r\u001b\u000e\u001d"+
|
||||
"\u000f\u001f\u0010!\u0011#\u0012%\u0013\'\u0014)\u0015+\u0016-\u0017/"+
|
||||
"\u00181\u00193\u001a5\u001b7\u001c9\u001d;\u001e=\u001f? A!C\"E#G$I%K"+
|
||||
"&M\'O(Q)S*U+W\u0000Y\u0000[\u0000],_-\u0001\u0000\u0006\u0002\u0000++"+
|
||||
"--\u0001\u000009\u0002\u0000\n\n\r\r\u0002\u0000AZaz\u0002\u0000$$__\u0003"+
|
||||
"\u0000\t\n\r\r \u0151\u0000\u0001\u0001\u0000\u0000\u0000\u0000\u0003"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000\u0007"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001\u0000"+
|
||||
"\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000\u0000"+
|
||||
"\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000\u0000"+
|
||||
")\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-\u0001"+
|
||||
"\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000\u0000"+
|
||||
"\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000\u0000"+
|
||||
"7\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000\u0000;\u0001"+
|
||||
"\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?\u0001\u0000\u0000"+
|
||||
"\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000\u0000"+
|
||||
"E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000\u0000\u0000I\u0001"+
|
||||
"\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000M\u0001\u0000\u0000"+
|
||||
"\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001\u0000\u0000\u0000\u0000"+
|
||||
"S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000\u0000\u0000]\u0001"+
|
||||
"\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0001j\u0001\u0000\u0000"+
|
||||
"\u0000\u0003l\u0001\u0000\u0000\u0000\u0005q\u0001\u0000\u0000\u0000\u0007"+
|
||||
"x\u0001\u0000\u0000\u0000\t\u009f\u0001\u0000\u0000\u0000\u000b\u00a4"+
|
||||
"\u0001\u0000\u0000\u0000\r\u00a8\u0001\u0000\u0000\u0000\u000f\u00b0\u0001"+
|
||||
"\u0000\u0000\u0000\u0011\u00b8\u0001\u0000\u0000\u0000\u0013\u00bc\u0001"+
|
||||
"\u0000\u0000\u0000\u0015\u00c4\u0001\u0000\u0000\u0000\u0017\u00c8\u0001"+
|
||||
"\u0000\u0000\u0000\u0019\u00ca\u0001\u0000\u0000\u0000\u001b\u00cc\u0001"+
|
||||
"\u0000\u0000\u0000\u001d\u00ce\u0001\u0000\u0000\u0000\u001f\u00d0\u0001"+
|
||||
"\u0000\u0000\u0000!\u00d2\u0001\u0000\u0000\u0000#\u00d4\u0001\u0000\u0000"+
|
||||
"\u0000%\u00d6\u0001\u0000\u0000\u0000\'\u00d8\u0001\u0000\u0000\u0000"+
|
||||
")\u00da\u0001\u0000\u0000\u0000+\u00dd\u0001\u0000\u0000\u0000-\u00e0"+
|
||||
"\u0001\u0000\u0000\u0000/\u00e3\u0001\u0000\u0000\u00001\u00e6\u0001\u0000"+
|
||||
"\u0000\u00003\u00e8\u0001\u0000\u0000\u00005\u00eb\u0001\u0000\u0000\u0000"+
|
||||
"7\u00ee\u0001\u0000\u0000\u00009\u00f0\u0001\u0000\u0000\u0000;\u00f2"+
|
||||
"\u0001\u0000\u0000\u0000=\u00f4\u0001\u0000\u0000\u0000?\u00f6\u0001\u0000"+
|
||||
"\u0000\u0000A\u00f8\u0001\u0000\u0000\u0000C\u00fa\u0001\u0000\u0000\u0000"+
|
||||
"E\u00fc\u0001\u0000\u0000\u0000G\u0102\u0001\u0000\u0000\u0000I\u0107"+
|
||||
"\u0001\u0000\u0000\u0000K\u010d\u0001\u0000\u0000\u0000M\u0110\u0001\u0000"+
|
||||
"\u0000\u0000O\u0115\u0001\u0000\u0000\u0000Q\u011c\u0001\u0000\u0000\u0000"+
|
||||
"S\u0123\u0001\u0000\u0000\u0000U\u012b\u0001\u0000\u0000\u0000W\u0131"+
|
||||
"\u0001\u0000\u0000\u0000Y\u0133\u0001\u0000\u0000\u0000[\u0138\u0001\u0000"+
|
||||
"\u0000\u0000]\u013a\u0001\u0000\u0000\u0000_\u0141\u0001\u0000\u0000\u0000"+
|
||||
"ab\u0005t\u0000\u0000bc\u0005r\u0000\u0000cd\u0005u\u0000\u0000dk\u0005"+
|
||||
"e\u0000\u0000ef\u0005f\u0000\u0000fg\u0005a\u0000\u0000gh\u0005l\u0000"+
|
||||
"\u0000hi\u0005s\u0000\u0000ik\u0005e\u0000\u0000ja\u0001\u0000\u0000\u0000"+
|
||||
"je\u0001\u0000\u0000\u0000k\u0002\u0001\u0000\u0000\u0000lm\u0005n\u0000"+
|
||||
"\u0000mn\u0005u\u0000\u0000no\u0005l\u0000\u0000op\u0005l\u0000\u0000"+
|
||||
"p\u0004\u0001\u0000\u0000\u0000qr\u0005p\u0000\u0000rs\u0005u\u0000\u0000"+
|
||||
"st\u0005b\u0000\u0000tu\u0005l\u0000\u0000uv\u0005i\u0000\u0000vw\u0005"+
|
||||
"c\u0000\u0000w\u0006\u0001\u0000\u0000\u0000xy\u0005p\u0000\u0000yz\u0005"+
|
||||
"u\u0000\u0000z{\u0005b\u0000\u0000{|\u0005l\u0000\u0000|}\u0005i\u0000"+
|
||||
"\u0000}~\u0005c\u0000\u0000~\u007f\u0005 \u0000\u0000\u007f\u0080\u0005"+
|
||||
"s\u0000\u0000\u0080\u0081\u0005t\u0000\u0000\u0081\u0082\u0005a\u0000"+
|
||||
"\u0000\u0082\u0083\u0005t\u0000\u0000\u0083\u0084\u0005i\u0000\u0000\u0084"+
|
||||
"\u0085\u0005c\u0000\u0000\u0085\u0086\u0005 \u0000\u0000\u0086\u0087\u0005"+
|
||||
"v\u0000\u0000\u0087\u0088\u0005o\u0000\u0000\u0088\u0089\u0005i\u0000"+
|
||||
"\u0000\u0089\u008a\u0005d\u0000\u0000\u008a\u008b\u0005 \u0000\u0000\u008b"+
|
||||
"\u008c\u0005m\u0000\u0000\u008c\u008d\u0005a\u0000\u0000\u008d\u008e\u0005"+
|
||||
"i\u0000\u0000\u008e\u008f\u0005n\u0000\u0000\u008f\u0090\u0005(\u0000"+
|
||||
"\u0000\u0090\u0091\u0005S\u0000\u0000\u0091\u0092\u0005t\u0000\u0000\u0092"+
|
||||
"\u0093\u0005r\u0000\u0000\u0093\u0094\u0005i\u0000\u0000\u0094\u0095\u0005"+
|
||||
"n\u0000\u0000\u0095\u0096\u0005g\u0000\u0000\u0096\u0097\u0005[\u0000"+
|
||||
"\u0000\u0097\u0098\u0005]\u0000\u0000\u0098\u0099\u0005 \u0000\u0000\u0099"+
|
||||
"\u009a\u0005a\u0000\u0000\u009a\u009b\u0005r\u0000\u0000\u009b\u009c\u0005"+
|
||||
"g\u0000\u0000\u009c\u009d\u0005s\u0000\u0000\u009d\u009e\u0005)\u0000"+
|
||||
"\u0000\u009e\b\u0001\u0000\u0000\u0000\u009f\u00a0\u0005v\u0000\u0000"+
|
||||
"\u00a0\u00a1\u0005o\u0000\u0000\u00a1\u00a2\u0005i\u0000\u0000\u00a2\u00a3"+
|
||||
"\u0005d\u0000\u0000\u00a3\n\u0001\u0000\u0000\u0000\u00a4\u00a5\u0005"+
|
||||
"i\u0000\u0000\u00a5\u00a6\u0005n\u0000\u0000\u00a6\u00a7\u0005t\u0000"+
|
||||
"\u0000\u00a7\f\u0001\u0000\u0000\u0000\u00a8\u00a9\u0005b\u0000\u0000"+
|
||||
"\u00a9\u00aa\u0005o\u0000\u0000\u00aa\u00ab\u0005o\u0000\u0000\u00ab\u00ac"+
|
||||
"\u0005l\u0000\u0000\u00ac\u00ad\u0005e\u0000\u0000\u00ad\u00ae\u0005a"+
|
||||
"\u0000\u0000\u00ae\u00af\u0005n\u0000\u0000\u00af\u000e\u0001\u0000\u0000"+
|
||||
"\u0000\u00b0\u00b1\u0005c\u0000\u0000\u00b1\u00b2\u0005h\u0000\u0000\u00b2"+
|
||||
"\u00b3\u0005a\u0000\u0000\u00b3\u00b4\u0005r\u0000\u0000\u00b4\u0010\u0001"+
|
||||
"\u0000\u0000\u0000\u00b5\u00b9\u0003\u001f\u000f\u0000\u00b6\u00b9\u0003"+
|
||||
"!\u0010\u0000\u00b7\u00b9\u0003#\u0011\u0000\u00b8\u00b5\u0001\u0000\u0000"+
|
||||
"\u0000\u00b8\u00b6\u0001\u0000\u0000\u0000\u00b8\u00b7\u0001\u0000\u0000"+
|
||||
"\u0000\u00b9\u0012\u0001\u0000\u0000\u0000\u00ba\u00bd\u0003\u001d\u000e"+
|
||||
"\u0000\u00bb\u00bd\u0003\u001b\r\u0000\u00bc\u00ba\u0001\u0000\u0000\u0000"+
|
||||
"\u00bc\u00bb\u0001\u0000\u0000\u0000\u00bd\u0014\u0001\u0000\u0000\u0000"+
|
||||
"\u00be\u00c5\u0003%\u0012\u0000\u00bf\u00c5\u0003\'\u0013\u0000\u00c0"+
|
||||
"\u00c5\u0003)\u0014\u0000\u00c1\u00c5\u0003+\u0015\u0000\u00c2\u00c5\u0003"+
|
||||
"-\u0016\u0000\u00c3\u00c5\u0003/\u0017\u0000\u00c4\u00be\u0001\u0000\u0000"+
|
||||
"\u0000\u00c4\u00bf\u0001\u0000\u0000\u0000\u00c4\u00c0\u0001\u0000\u0000"+
|
||||
"\u0000\u00c4\u00c1\u0001\u0000\u0000\u0000\u00c4\u00c2\u0001\u0000\u0000"+
|
||||
"\u0000\u00c4\u00c3\u0001\u0000\u0000\u0000\u00c5\u0016\u0001\u0000\u0000"+
|
||||
"\u0000\u00c6\u00c9\u00033\u0019\u0000\u00c7\u00c9\u00035\u001a\u0000\u00c8"+
|
||||
"\u00c6\u0001\u0000\u0000\u0000\u00c8\u00c7\u0001\u0000\u0000\u0000\u00c9"+
|
||||
"\u0018\u0001\u0000\u0000\u0000\u00ca\u00cb\u0005=\u0000\u0000\u00cb\u001a"+
|
||||
"\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005-\u0000\u0000\u00cd\u001c\u0001"+
|
||||
"\u0000\u0000\u0000\u00ce\u00cf\u0005+\u0000\u0000\u00cf\u001e\u0001\u0000"+
|
||||
"\u0000\u0000\u00d0\u00d1\u0005*\u0000\u0000\u00d1 \u0001\u0000\u0000\u0000"+
|
||||
"\u00d2\u00d3\u0005/\u0000\u0000\u00d3\"\u0001\u0000\u0000\u0000\u00d4"+
|
||||
"\u00d5\u0005%\u0000\u0000\u00d5$\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005"+
|
||||
">\u0000\u0000\u00d7&\u0001\u0000\u0000\u0000\u00d8\u00d9\u0005<\u0000"+
|
||||
"\u0000\u00d9(\u0001\u0000\u0000\u0000\u00da\u00db\u0005>\u0000\u0000\u00db"+
|
||||
"\u00dc\u0005=\u0000\u0000\u00dc*\u0001\u0000\u0000\u0000\u00dd\u00de\u0005"+
|
||||
"<\u0000\u0000\u00de\u00df\u0005=\u0000\u0000\u00df,\u0001\u0000\u0000"+
|
||||
"\u0000\u00e0\u00e1\u0005=\u0000\u0000\u00e1\u00e2\u0005=\u0000\u0000\u00e2"+
|
||||
".\u0001\u0000\u0000\u0000\u00e3\u00e4\u0005!\u0000\u0000\u00e4\u00e5\u0005"+
|
||||
"=\u0000\u0000\u00e50\u0001\u0000\u0000\u0000\u00e6\u00e7\u0005!\u0000"+
|
||||
"\u0000\u00e72\u0001\u0000\u0000\u0000\u00e8\u00e9\u0005&\u0000\u0000\u00e9"+
|
||||
"\u00ea\u0005&\u0000\u0000\u00ea4\u0001\u0000\u0000\u0000\u00eb\u00ec\u0005"+
|
||||
"|\u0000\u0000\u00ec\u00ed\u0005|\u0000\u0000\u00ed6\u0001\u0000\u0000"+
|
||||
"\u0000\u00ee\u00ef\u0005.\u0000\u0000\u00ef8\u0001\u0000\u0000\u0000\u00f0"+
|
||||
"\u00f1\u0005(\u0000\u0000\u00f1:\u0001\u0000\u0000\u0000\u00f2\u00f3\u0005"+
|
||||
")\u0000\u0000\u00f3<\u0001\u0000\u0000\u0000\u00f4\u00f5\u0005{\u0000"+
|
||||
"\u0000\u00f5>\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005}\u0000\u0000\u00f7"+
|
||||
"@\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005;\u0000\u0000\u00f9B\u0001"+
|
||||
"\u0000\u0000\u0000\u00fa\u00fb\u0005,\u0000\u0000\u00fbD\u0001\u0000\u0000"+
|
||||
"\u0000\u00fc\u00fd\u0005c\u0000\u0000\u00fd\u00fe\u0005l\u0000\u0000\u00fe"+
|
||||
"\u00ff\u0005a\u0000\u0000\u00ff\u0100\u0005s\u0000\u0000\u0100\u0101\u0005"+
|
||||
"s\u0000\u0000\u0101F\u0001\u0000\u0000\u0000\u0102\u0103\u0005t\u0000"+
|
||||
"\u0000\u0103\u0104\u0005h\u0000\u0000\u0104\u0105\u0005i\u0000\u0000\u0105"+
|
||||
"\u0106\u0005s\u0000\u0000\u0106H\u0001\u0000\u0000\u0000\u0107\u0108\u0005"+
|
||||
"w\u0000\u0000\u0108\u0109\u0005h\u0000\u0000\u0109\u010a\u0005i\u0000"+
|
||||
"\u0000\u010a\u010b\u0005l\u0000\u0000\u010b\u010c\u0005e\u0000\u0000\u010c"+
|
||||
"J\u0001\u0000\u0000\u0000\u010d\u010e\u0005i\u0000\u0000\u010e\u010f\u0005"+
|
||||
"f\u0000\u0000\u010fL\u0001\u0000\u0000\u0000\u0110\u0111\u0005e\u0000"+
|
||||
"\u0000\u0111\u0112\u0005l\u0000\u0000\u0112\u0113\u0005s\u0000\u0000\u0113"+
|
||||
"\u0114\u0005e\u0000\u0000\u0114N\u0001\u0000\u0000\u0000\u0115\u0116\u0005"+
|
||||
"r\u0000\u0000\u0116\u0117\u0005e\u0000\u0000\u0117\u0118\u0005t\u0000"+
|
||||
"\u0000\u0118\u0119\u0005u\u0000\u0000\u0119\u011a\u0005r\u0000\u0000\u011a"+
|
||||
"\u011b\u0005n\u0000\u0000\u011bP\u0001\u0000\u0000\u0000\u011c\u011d\u0005"+
|
||||
"n\u0000\u0000\u011d\u011e\u0005e\u0000\u0000\u011e\u011f\u0005w\u0000"+
|
||||
"\u0000\u011fR\u0001\u0000\u0000\u0000\u0120\u0122\u0007\u0000\u0000\u0000"+
|
||||
"\u0121\u0120\u0001\u0000\u0000\u0000\u0122\u0125\u0001\u0000\u0000\u0000"+
|
||||
"\u0123\u0121\u0001\u0000\u0000\u0000\u0123\u0124\u0001\u0000\u0000\u0000"+
|
||||
"\u0124\u0127\u0001\u0000\u0000\u0000\u0125\u0123\u0001\u0000\u0000\u0000"+
|
||||
"\u0126\u0128\u0007\u0001\u0000\u0000\u0127\u0126\u0001\u0000\u0000\u0000"+
|
||||
"\u0128\u0129\u0001\u0000\u0000\u0000\u0129\u0127\u0001\u0000\u0000\u0000"+
|
||||
"\u0129\u012a\u0001\u0000\u0000\u0000\u012aT\u0001\u0000\u0000\u0000\u012b"+
|
||||
"\u012d\u0005\'\u0000\u0000\u012c\u012e\b\u0002\u0000\u0000\u012d\u012c"+
|
||||
"\u0001\u0000\u0000\u0000\u012d\u012e\u0001\u0000\u0000\u0000\u012e\u012f"+
|
||||
"\u0001\u0000\u0000\u0000\u012f\u0130\u0005\'\u0000\u0000\u0130V\u0001"+
|
||||
"\u0000\u0000\u0000\u0131\u0132\u0007\u0003\u0000\u0000\u0132X\u0001\u0000"+
|
||||
"\u0000\u0000\u0133\u0134\u0007\u0001\u0000\u0000\u0134Z\u0001\u0000\u0000"+
|
||||
"\u0000\u0135\u0139\u0003W+\u0000\u0136\u0139\u0003Y,\u0000\u0137\u0139"+
|
||||
"\u0007\u0004\u0000\u0000\u0138\u0135\u0001\u0000\u0000\u0000\u0138\u0136"+
|
||||
"\u0001\u0000\u0000\u0000\u0138\u0137\u0001\u0000\u0000\u0000\u0139\\\u0001"+
|
||||
"\u0000\u0000\u0000\u013a\u013e\u0003W+\u0000\u013b\u013d\u0003[-\u0000"+
|
||||
"\u013c\u013b\u0001\u0000\u0000\u0000\u013d\u0140\u0001\u0000\u0000\u0000"+
|
||||
"\u013e\u013c\u0001\u0000\u0000\u0000\u013e\u013f\u0001\u0000\u0000\u0000"+
|
||||
"\u013f^\u0001\u0000\u0000\u0000\u0140\u013e\u0001\u0000\u0000\u0000\u0141"+
|
||||
"\u0142\u0007\u0005\u0000\u0000\u0142\u0143\u0001\u0000\u0000\u0000\u0143"+
|
||||
"\u0144\u0006/\u0000\u0000\u0144`\u0001\u0000\u0000\u0000\u000b\u0000j"+
|
||||
"\u00b8\u00bc\u00c4\u00c8\u0123\u0129\u012d\u0138\u013e\u0001\u0006\u0000"+
|
||||
"\u0000";
|
||||
"&M\'O(Q)S*U+W,Y\u0000[\u0000]\u0000_-a.\u0001\u0000\u0006\u0002\u0000"+
|
||||
"++--\u0001\u000009\u0002\u0000\n\n\r\r\u0002\u0000AZaz\u0002\u0000$$_"+
|
||||
"_\u0003\u0000\t\n\r\r \u0159\u0000\u0001\u0001\u0000\u0000\u0000\u0000"+
|
||||
"\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000"+
|
||||
"\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001"+
|
||||
"\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000"+
|
||||
"\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000"+
|
||||
"\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-"+
|
||||
"\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000"+
|
||||
"\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000"+
|
||||
"\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000\u0000;"+
|
||||
"\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?\u0001\u0000"+
|
||||
"\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000"+
|
||||
"\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000\u0000\u0000I"+
|
||||
"\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000M\u0001\u0000"+
|
||||
"\u0000\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001\u0000\u0000\u0000"+
|
||||
"\u0000S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000\u0000\u0000W"+
|
||||
"\u0001\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0000a\u0001\u0000"+
|
||||
"\u0000\u0000\u0001c\u0001\u0000\u0000\u0000\u0003r\u0001\u0000\u0000\u0000"+
|
||||
"\u0005t\u0001\u0000\u0000\u0000\u0007y\u0001\u0000\u0000\u0000\t\u0080"+
|
||||
"\u0001\u0000\u0000\u0000\u000b\u00a7\u0001\u0000\u0000\u0000\r\u00ac\u0001"+
|
||||
"\u0000\u0000\u0000\u000f\u00b0\u0001\u0000\u0000\u0000\u0011\u00b8\u0001"+
|
||||
"\u0000\u0000\u0000\u0013\u00c0\u0001\u0000\u0000\u0000\u0015\u00c4\u0001"+
|
||||
"\u0000\u0000\u0000\u0017\u00cc\u0001\u0000\u0000\u0000\u0019\u00d0\u0001"+
|
||||
"\u0000\u0000\u0000\u001b\u00d2\u0001\u0000\u0000\u0000\u001d\u00d4\u0001"+
|
||||
"\u0000\u0000\u0000\u001f\u00d6\u0001\u0000\u0000\u0000!\u00d8\u0001\u0000"+
|
||||
"\u0000\u0000#\u00da\u0001\u0000\u0000\u0000%\u00dc\u0001\u0000\u0000\u0000"+
|
||||
"\'\u00de\u0001\u0000\u0000\u0000)\u00e0\u0001\u0000\u0000\u0000+\u00e2"+
|
||||
"\u0001\u0000\u0000\u0000-\u00e5\u0001\u0000\u0000\u0000/\u00e8\u0001\u0000"+
|
||||
"\u0000\u00001\u00eb\u0001\u0000\u0000\u00003\u00ee\u0001\u0000\u0000\u0000"+
|
||||
"5\u00f0\u0001\u0000\u0000\u00007\u00f3\u0001\u0000\u0000\u00009\u00f6"+
|
||||
"\u0001\u0000\u0000\u0000;\u00f8\u0001\u0000\u0000\u0000=\u00fa\u0001\u0000"+
|
||||
"\u0000\u0000?\u00fc\u0001\u0000\u0000\u0000A\u00fe\u0001\u0000\u0000\u0000"+
|
||||
"C\u0100\u0001\u0000\u0000\u0000E\u0102\u0001\u0000\u0000\u0000G\u0104"+
|
||||
"\u0001\u0000\u0000\u0000I\u010a\u0001\u0000\u0000\u0000K\u010f\u0001\u0000"+
|
||||
"\u0000\u0000M\u0115\u0001\u0000\u0000\u0000O\u0118\u0001\u0000\u0000\u0000"+
|
||||
"Q\u011d\u0001\u0000\u0000\u0000S\u0124\u0001\u0000\u0000\u0000U\u012b"+
|
||||
"\u0001\u0000\u0000\u0000W\u0133\u0001\u0000\u0000\u0000Y\u0139\u0001\u0000"+
|
||||
"\u0000\u0000[\u013b\u0001\u0000\u0000\u0000]\u0140\u0001\u0000\u0000\u0000"+
|
||||
"_\u0142\u0001\u0000\u0000\u0000a\u0149\u0001\u0000\u0000\u0000cd\u0005"+
|
||||
"p\u0000\u0000de\u0005r\u0000\u0000ef\u0005i\u0000\u0000fg\u0005n\u0000"+
|
||||
"\u0000gh\u0005t\u0000\u0000h\u0002\u0001\u0000\u0000\u0000ij\u0005t\u0000"+
|
||||
"\u0000jk\u0005r\u0000\u0000kl\u0005u\u0000\u0000ls\u0005e\u0000\u0000"+
|
||||
"mn\u0005f\u0000\u0000no\u0005a\u0000\u0000op\u0005l\u0000\u0000pq\u0005"+
|
||||
"s\u0000\u0000qs\u0005e\u0000\u0000ri\u0001\u0000\u0000\u0000rm\u0001\u0000"+
|
||||
"\u0000\u0000s\u0004\u0001\u0000\u0000\u0000tu\u0005n\u0000\u0000uv\u0005"+
|
||||
"u\u0000\u0000vw\u0005l\u0000\u0000wx\u0005l\u0000\u0000x\u0006\u0001\u0000"+
|
||||
"\u0000\u0000yz\u0005p\u0000\u0000z{\u0005u\u0000\u0000{|\u0005b\u0000"+
|
||||
"\u0000|}\u0005l\u0000\u0000}~\u0005i\u0000\u0000~\u007f\u0005c\u0000\u0000"+
|
||||
"\u007f\b\u0001\u0000\u0000\u0000\u0080\u0081\u0005p\u0000\u0000\u0081"+
|
||||
"\u0082\u0005u\u0000\u0000\u0082\u0083\u0005b\u0000\u0000\u0083\u0084\u0005"+
|
||||
"l\u0000\u0000\u0084\u0085\u0005i\u0000\u0000\u0085\u0086\u0005c\u0000"+
|
||||
"\u0000\u0086\u0087\u0005 \u0000\u0000\u0087\u0088\u0005s\u0000\u0000\u0088"+
|
||||
"\u0089\u0005t\u0000\u0000\u0089\u008a\u0005a\u0000\u0000\u008a\u008b\u0005"+
|
||||
"t\u0000\u0000\u008b\u008c\u0005i\u0000\u0000\u008c\u008d\u0005c\u0000"+
|
||||
"\u0000\u008d\u008e\u0005 \u0000\u0000\u008e\u008f\u0005v\u0000\u0000\u008f"+
|
||||
"\u0090\u0005o\u0000\u0000\u0090\u0091\u0005i\u0000\u0000\u0091\u0092\u0005"+
|
||||
"d\u0000\u0000\u0092\u0093\u0005 \u0000\u0000\u0093\u0094\u0005m\u0000"+
|
||||
"\u0000\u0094\u0095\u0005a\u0000\u0000\u0095\u0096\u0005i\u0000\u0000\u0096"+
|
||||
"\u0097\u0005n\u0000\u0000\u0097\u0098\u0005(\u0000\u0000\u0098\u0099\u0005"+
|
||||
"S\u0000\u0000\u0099\u009a\u0005t\u0000\u0000\u009a\u009b\u0005r\u0000"+
|
||||
"\u0000\u009b\u009c\u0005i\u0000\u0000\u009c\u009d\u0005n\u0000\u0000\u009d"+
|
||||
"\u009e\u0005g\u0000\u0000\u009e\u009f\u0005[\u0000\u0000\u009f\u00a0\u0005"+
|
||||
"]\u0000\u0000\u00a0\u00a1\u0005 \u0000\u0000\u00a1\u00a2\u0005a\u0000"+
|
||||
"\u0000\u00a2\u00a3\u0005r\u0000\u0000\u00a3\u00a4\u0005g\u0000\u0000\u00a4"+
|
||||
"\u00a5\u0005s\u0000\u0000\u00a5\u00a6\u0005)\u0000\u0000\u00a6\n\u0001"+
|
||||
"\u0000\u0000\u0000\u00a7\u00a8\u0005v\u0000\u0000\u00a8\u00a9\u0005o\u0000"+
|
||||
"\u0000\u00a9\u00aa\u0005i\u0000\u0000\u00aa\u00ab\u0005d\u0000\u0000\u00ab"+
|
||||
"\f\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005i\u0000\u0000\u00ad\u00ae"+
|
||||
"\u0005n\u0000\u0000\u00ae\u00af\u0005t\u0000\u0000\u00af\u000e\u0001\u0000"+
|
||||
"\u0000\u0000\u00b0\u00b1\u0005b\u0000\u0000\u00b1\u00b2\u0005o\u0000\u0000"+
|
||||
"\u00b2\u00b3\u0005o\u0000\u0000\u00b3\u00b4\u0005l\u0000\u0000\u00b4\u00b5"+
|
||||
"\u0005e\u0000\u0000\u00b5\u00b6\u0005a\u0000\u0000\u00b6\u00b7\u0005n"+
|
||||
"\u0000\u0000\u00b7\u0010\u0001\u0000\u0000\u0000\u00b8\u00b9\u0005c\u0000"+
|
||||
"\u0000\u00b9\u00ba\u0005h\u0000\u0000\u00ba\u00bb\u0005a\u0000\u0000\u00bb"+
|
||||
"\u00bc\u0005r\u0000\u0000\u00bc\u0012\u0001\u0000\u0000\u0000\u00bd\u00c1"+
|
||||
"\u0003!\u0010\u0000\u00be\u00c1\u0003#\u0011\u0000\u00bf\u00c1\u0003%"+
|
||||
"\u0012\u0000\u00c0\u00bd\u0001\u0000\u0000\u0000\u00c0\u00be\u0001\u0000"+
|
||||
"\u0000\u0000\u00c0\u00bf\u0001\u0000\u0000\u0000\u00c1\u0014\u0001\u0000"+
|
||||
"\u0000\u0000\u00c2\u00c5\u0003\u001f\u000f\u0000\u00c3\u00c5\u0003\u001d"+
|
||||
"\u000e\u0000\u00c4\u00c2\u0001\u0000\u0000\u0000\u00c4\u00c3\u0001\u0000"+
|
||||
"\u0000\u0000\u00c5\u0016\u0001\u0000\u0000\u0000\u00c6\u00cd\u0003\'\u0013"+
|
||||
"\u0000\u00c7\u00cd\u0003)\u0014\u0000\u00c8\u00cd\u0003+\u0015\u0000\u00c9"+
|
||||
"\u00cd\u0003-\u0016\u0000\u00ca\u00cd\u0003/\u0017\u0000\u00cb\u00cd\u0003"+
|
||||
"1\u0018\u0000\u00cc\u00c6\u0001\u0000\u0000\u0000\u00cc\u00c7\u0001\u0000"+
|
||||
"\u0000\u0000\u00cc\u00c8\u0001\u0000\u0000\u0000\u00cc\u00c9\u0001\u0000"+
|
||||
"\u0000\u0000\u00cc\u00ca\u0001\u0000\u0000\u0000\u00cc\u00cb\u0001\u0000"+
|
||||
"\u0000\u0000\u00cd\u0018\u0001\u0000\u0000\u0000\u00ce\u00d1\u00035\u001a"+
|
||||
"\u0000\u00cf\u00d1\u00037\u001b\u0000\u00d0\u00ce\u0001\u0000\u0000\u0000"+
|
||||
"\u00d0\u00cf\u0001\u0000\u0000\u0000\u00d1\u001a\u0001\u0000\u0000\u0000"+
|
||||
"\u00d2\u00d3\u0005=\u0000\u0000\u00d3\u001c\u0001\u0000\u0000\u0000\u00d4"+
|
||||
"\u00d5\u0005-\u0000\u0000\u00d5\u001e\u0001\u0000\u0000\u0000\u00d6\u00d7"+
|
||||
"\u0005+\u0000\u0000\u00d7 \u0001\u0000\u0000\u0000\u00d8\u00d9\u0005*"+
|
||||
"\u0000\u0000\u00d9\"\u0001\u0000\u0000\u0000\u00da\u00db\u0005/\u0000"+
|
||||
"\u0000\u00db$\u0001\u0000\u0000\u0000\u00dc\u00dd\u0005%\u0000\u0000\u00dd"+
|
||||
"&\u0001\u0000\u0000\u0000\u00de\u00df\u0005>\u0000\u0000\u00df(\u0001"+
|
||||
"\u0000\u0000\u0000\u00e0\u00e1\u0005<\u0000\u0000\u00e1*\u0001\u0000\u0000"+
|
||||
"\u0000\u00e2\u00e3\u0005>\u0000\u0000\u00e3\u00e4\u0005=\u0000\u0000\u00e4"+
|
||||
",\u0001\u0000\u0000\u0000\u00e5\u00e6\u0005<\u0000\u0000\u00e6\u00e7\u0005"+
|
||||
"=\u0000\u0000\u00e7.\u0001\u0000\u0000\u0000\u00e8\u00e9\u0005=\u0000"+
|
||||
"\u0000\u00e9\u00ea\u0005=\u0000\u0000\u00ea0\u0001\u0000\u0000\u0000\u00eb"+
|
||||
"\u00ec\u0005!\u0000\u0000\u00ec\u00ed\u0005=\u0000\u0000\u00ed2\u0001"+
|
||||
"\u0000\u0000\u0000\u00ee\u00ef\u0005!\u0000\u0000\u00ef4\u0001\u0000\u0000"+
|
||||
"\u0000\u00f0\u00f1\u0005&\u0000\u0000\u00f1\u00f2\u0005&\u0000\u0000\u00f2"+
|
||||
"6\u0001\u0000\u0000\u0000\u00f3\u00f4\u0005|\u0000\u0000\u00f4\u00f5\u0005"+
|
||||
"|\u0000\u0000\u00f58\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005.\u0000"+
|
||||
"\u0000\u00f7:\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005(\u0000\u0000\u00f9"+
|
||||
"<\u0001\u0000\u0000\u0000\u00fa\u00fb\u0005)\u0000\u0000\u00fb>\u0001"+
|
||||
"\u0000\u0000\u0000\u00fc\u00fd\u0005{\u0000\u0000\u00fd@\u0001\u0000\u0000"+
|
||||
"\u0000\u00fe\u00ff\u0005}\u0000\u0000\u00ffB\u0001\u0000\u0000\u0000\u0100"+
|
||||
"\u0101\u0005;\u0000\u0000\u0101D\u0001\u0000\u0000\u0000\u0102\u0103\u0005"+
|
||||
",\u0000\u0000\u0103F\u0001\u0000\u0000\u0000\u0104\u0105\u0005c\u0000"+
|
||||
"\u0000\u0105\u0106\u0005l\u0000\u0000\u0106\u0107\u0005a\u0000\u0000\u0107"+
|
||||
"\u0108\u0005s\u0000\u0000\u0108\u0109\u0005s\u0000\u0000\u0109H\u0001"+
|
||||
"\u0000\u0000\u0000\u010a\u010b\u0005t\u0000\u0000\u010b\u010c\u0005h\u0000"+
|
||||
"\u0000\u010c\u010d\u0005i\u0000\u0000\u010d\u010e\u0005s\u0000\u0000\u010e"+
|
||||
"J\u0001\u0000\u0000\u0000\u010f\u0110\u0005w\u0000\u0000\u0110\u0111\u0005"+
|
||||
"h\u0000\u0000\u0111\u0112\u0005i\u0000\u0000\u0112\u0113\u0005l\u0000"+
|
||||
"\u0000\u0113\u0114\u0005e\u0000\u0000\u0114L\u0001\u0000\u0000\u0000\u0115"+
|
||||
"\u0116\u0005i\u0000\u0000\u0116\u0117\u0005f\u0000\u0000\u0117N\u0001"+
|
||||
"\u0000\u0000\u0000\u0118\u0119\u0005e\u0000\u0000\u0119\u011a\u0005l\u0000"+
|
||||
"\u0000\u011a\u011b\u0005s\u0000\u0000\u011b\u011c\u0005e\u0000\u0000\u011c"+
|
||||
"P\u0001\u0000\u0000\u0000\u011d\u011e\u0005r\u0000\u0000\u011e\u011f\u0005"+
|
||||
"e\u0000\u0000\u011f\u0120\u0005t\u0000\u0000\u0120\u0121\u0005u\u0000"+
|
||||
"\u0000\u0121\u0122\u0005r\u0000\u0000\u0122\u0123\u0005n\u0000\u0000\u0123"+
|
||||
"R\u0001\u0000\u0000\u0000\u0124\u0125\u0005n\u0000\u0000\u0125\u0126\u0005"+
|
||||
"e\u0000\u0000\u0126\u0127\u0005w\u0000\u0000\u0127T\u0001\u0000\u0000"+
|
||||
"\u0000\u0128\u012a\u0007\u0000\u0000\u0000\u0129\u0128\u0001\u0000\u0000"+
|
||||
"\u0000\u012a\u012d\u0001\u0000\u0000\u0000\u012b\u0129\u0001\u0000\u0000"+
|
||||
"\u0000\u012b\u012c\u0001\u0000\u0000\u0000\u012c\u012f\u0001\u0000\u0000"+
|
||||
"\u0000\u012d\u012b\u0001\u0000\u0000\u0000\u012e\u0130\u0007\u0001\u0000"+
|
||||
"\u0000\u012f\u012e\u0001\u0000\u0000\u0000\u0130\u0131\u0001\u0000\u0000"+
|
||||
"\u0000\u0131\u012f\u0001\u0000\u0000\u0000\u0131\u0132\u0001\u0000\u0000"+
|
||||
"\u0000\u0132V\u0001\u0000\u0000\u0000\u0133\u0135\u0005\'\u0000\u0000"+
|
||||
"\u0134\u0136\b\u0002\u0000\u0000\u0135\u0134\u0001\u0000\u0000\u0000\u0135"+
|
||||
"\u0136\u0001\u0000\u0000\u0000\u0136\u0137\u0001\u0000\u0000\u0000\u0137"+
|
||||
"\u0138\u0005\'\u0000\u0000\u0138X\u0001\u0000\u0000\u0000\u0139\u013a"+
|
||||
"\u0007\u0003\u0000\u0000\u013aZ\u0001\u0000\u0000\u0000\u013b\u013c\u0007"+
|
||||
"\u0001\u0000\u0000\u013c\\\u0001\u0000\u0000\u0000\u013d\u0141\u0003Y"+
|
||||
",\u0000\u013e\u0141\u0003[-\u0000\u013f\u0141\u0007\u0004\u0000\u0000"+
|
||||
"\u0140\u013d\u0001\u0000\u0000\u0000\u0140\u013e\u0001\u0000\u0000\u0000"+
|
||||
"\u0140\u013f\u0001\u0000\u0000\u0000\u0141^\u0001\u0000\u0000\u0000\u0142"+
|
||||
"\u0146\u0003Y,\u0000\u0143\u0145\u0003].\u0000\u0144\u0143\u0001\u0000"+
|
||||
"\u0000\u0000\u0145\u0148\u0001\u0000\u0000\u0000\u0146\u0144\u0001\u0000"+
|
||||
"\u0000\u0000\u0146\u0147\u0001\u0000\u0000\u0000\u0147`\u0001\u0000\u0000"+
|
||||
"\u0000\u0148\u0146\u0001\u0000\u0000\u0000\u0149\u014a\u0007\u0005\u0000"+
|
||||
"\u0000\u014a\u014b\u0001\u0000\u0000\u0000\u014b\u014c\u00060\u0000\u0000"+
|
||||
"\u014cb\u0001\u0000\u0000\u0000\u000b\u0000r\u00c0\u00c4\u00cc\u00d0\u012b"+
|
||||
"\u0131\u0135\u0140\u0146\u0001\u0006\u0000\u0000";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
||||
@@ -1,81 +1,83 @@
|
||||
BooleanValue=1
|
||||
NullValue=2
|
||||
AccessModifierPublic=3
|
||||
MainMethodDecl=4
|
||||
Void=5
|
||||
Int=6
|
||||
Boolean=7
|
||||
Char=8
|
||||
DotOperator=9
|
||||
LineOperator=10
|
||||
ComparisonOperator=11
|
||||
LogicalOpertor=12
|
||||
Assign=13
|
||||
Minus=14
|
||||
Plus=15
|
||||
Multipilkation=16
|
||||
Division=17
|
||||
Modulo=18
|
||||
Greater=19
|
||||
Less=20
|
||||
GreaterEqual=21
|
||||
LessEqual=22
|
||||
Equal=23
|
||||
NotEqual=24
|
||||
Not=25
|
||||
And=26
|
||||
Or=27
|
||||
Dot=28
|
||||
OpenRoundBracket=29
|
||||
ClosedRoundBracket=30
|
||||
OpenCurlyBracket=31
|
||||
ClosedCurlyBracket=32
|
||||
Semicolon=33
|
||||
Comma=34
|
||||
Class=35
|
||||
This=36
|
||||
While=37
|
||||
If=38
|
||||
Else=39
|
||||
Return=40
|
||||
New=41
|
||||
IntValue=42
|
||||
CharValue=43
|
||||
Identifier=44
|
||||
WS=45
|
||||
'null'=2
|
||||
'public'=3
|
||||
'public static void main(String[] args)'=4
|
||||
'void'=5
|
||||
'int'=6
|
||||
'boolean'=7
|
||||
'char'=8
|
||||
'='=13
|
||||
'-'=14
|
||||
'+'=15
|
||||
'*'=16
|
||||
'/'=17
|
||||
'%'=18
|
||||
'>'=19
|
||||
'<'=20
|
||||
'>='=21
|
||||
'<='=22
|
||||
'=='=23
|
||||
'!='=24
|
||||
'!'=25
|
||||
'&&'=26
|
||||
'||'=27
|
||||
'.'=28
|
||||
'('=29
|
||||
')'=30
|
||||
'{'=31
|
||||
'}'=32
|
||||
';'=33
|
||||
','=34
|
||||
'class'=35
|
||||
'this'=36
|
||||
'while'=37
|
||||
'if'=38
|
||||
'else'=39
|
||||
'return'=40
|
||||
'new'=41
|
||||
T__0=1
|
||||
BooleanValue=2
|
||||
NullValue=3
|
||||
AccessModifierPublic=4
|
||||
MainMethodDecl=5
|
||||
Void=6
|
||||
Int=7
|
||||
Boolean=8
|
||||
Char=9
|
||||
DotOperator=10
|
||||
LineOperator=11
|
||||
ComparisonOperator=12
|
||||
LogicalOpertor=13
|
||||
Assign=14
|
||||
Minus=15
|
||||
Plus=16
|
||||
Multipilkation=17
|
||||
Division=18
|
||||
Modulo=19
|
||||
Greater=20
|
||||
Less=21
|
||||
GreaterEqual=22
|
||||
LessEqual=23
|
||||
Equal=24
|
||||
NotEqual=25
|
||||
Not=26
|
||||
And=27
|
||||
Or=28
|
||||
Dot=29
|
||||
OpenRoundBracket=30
|
||||
ClosedRoundBracket=31
|
||||
OpenCurlyBracket=32
|
||||
ClosedCurlyBracket=33
|
||||
Semicolon=34
|
||||
Comma=35
|
||||
Class=36
|
||||
This=37
|
||||
While=38
|
||||
If=39
|
||||
Else=40
|
||||
Return=41
|
||||
New=42
|
||||
IntValue=43
|
||||
CharValue=44
|
||||
Identifier=45
|
||||
WS=46
|
||||
'print'=1
|
||||
'null'=3
|
||||
'public'=4
|
||||
'public static void main(String[] args)'=5
|
||||
'void'=6
|
||||
'int'=7
|
||||
'boolean'=8
|
||||
'char'=9
|
||||
'='=14
|
||||
'-'=15
|
||||
'+'=16
|
||||
'*'=17
|
||||
'/'=18
|
||||
'%'=19
|
||||
'>'=20
|
||||
'<'=21
|
||||
'>='=22
|
||||
'<='=23
|
||||
'=='=24
|
||||
'!='=25
|
||||
'!'=26
|
||||
'&&'=27
|
||||
'||'=28
|
||||
'.'=29
|
||||
'('=30
|
||||
')'=31
|
||||
'{'=32
|
||||
'}'=33
|
||||
';'=34
|
||||
','=35
|
||||
'class'=36
|
||||
'this'=37
|
||||
'while'=38
|
||||
'if'=39
|
||||
'else'=40
|
||||
'return'=41
|
||||
'new'=42
|
||||
|
||||
@@ -357,4 +357,14 @@ public interface DecafListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitValue(DecafParser.ValueContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link DecafParser#print}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterPrint(DecafParser.PrintContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link DecafParser#print}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitPrint(DecafParser.PrintContext ctx);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -220,4 +220,10 @@ public interface DecafVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitValue(DecafParser.ValueContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link DecafParser#print}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitPrint(DecafParser.PrintContext ctx);
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package AST;
|
||||
import ASTs.emptyClassAST;
|
||||
import ASTs.*;
|
||||
import abstractSyntaxTree.Program;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class testAll {
|
||||
|
||||
AstComparer astComparer;
|
||||
@@ -13,14 +11,88 @@ public class testAll {
|
||||
this.astComparer = new AstComparer("src/test/resources");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void TestAstGeneration()
|
||||
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();
|
||||
String pathToCode = "basicClasses/emptyClass.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyClassWithConstructor(){
|
||||
Program ast = EmptyClassWithConstructorAST.getProgram();
|
||||
String pathToCode = "basicClasses/emptyClassWithConstructor.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFakultaet(){
|
||||
Program ast = FakultaetAST.getProgram();
|
||||
String pathToCode = "basicClasses/Fakultaet.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldVariable(){
|
||||
Program ast = FieldVarAST.getProgram();
|
||||
String pathToCode = "SimpleTests/FieldVar.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfElseIfStatementWithOneReturne(){
|
||||
Program ast = IfElseIfStatementWithOneReturnAST.getProgram();
|
||||
String pathToCode = "SimpleTests/IfElseIfStatementWithOneReturn.java";
|
||||
testAst(ast, pathToCode);
|
||||
}
|
||||
|
||||
public void testAst(Program ast, String pathToCode)
|
||||
{
|
||||
System.out.println("Current working directory: " + new File(".").getAbsolutePath());
|
||||
Program testEmptyClassAST = emptyClassAST.getEmptyProgramm();
|
||||
|
||||
try {
|
||||
astComparer.astComparison("basicClasses/emptyClass.java", testEmptyClassAST);
|
||||
astComparer.astComparison(pathToCode, ast);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
59
src/test/java/ASTs/AssignWrongTypeAST.java
Normal file
59
src/test/java/ASTs/AssignWrongTypeAST.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.BooleanConstantExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AssignWrongTypeAST {
|
||||
public static Program getProgram(){
|
||||
|
||||
// TestMethod
|
||||
//Expressions
|
||||
// 0
|
||||
IntConstantExpression intConstantExpression0 = new IntConstantExpression(1);
|
||||
LocalVarDecl localVarDecl = new LocalVarDecl("int", "x", intConstantExpression0);
|
||||
|
||||
//1
|
||||
LocalVarIdentifier localVarIdentifier0 = new LocalVarIdentifier("x");
|
||||
BooleanConstantExpression booleanConstantExpression0 = new BooleanConstantExpression(true);
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", localVarIdentifier0, booleanConstantExpression0);
|
||||
|
||||
//2
|
||||
ReturnStatement returnStatement0 = new ReturnStatement(localVarIdentifier0);
|
||||
|
||||
String classThatContainsMethod = "AssignWrongType";
|
||||
String nameMethod0 = "test";
|
||||
String returnType = "int";
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
iStatementList.add(localVarDecl);
|
||||
iStatementList.add(assignStatementExpression0);
|
||||
iStatementList.add(returnStatement0);
|
||||
BlockStatement codeBlock = new BlockStatement(iStatementList, null);
|
||||
MethodDecl test = new MethodDecl(classThatContainsMethod, returnType, nameMethod0, parameterList, codeBlock);
|
||||
|
||||
String name = "AssignWrongType";
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(test);
|
||||
boolean hasMain = false;
|
||||
RefType assignWrongType = new RefType(name, fieldDeclList, methodDeclList, hasMain);
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(assignWrongType);
|
||||
Program program = new Program(refTypeList);
|
||||
return program;
|
||||
}
|
||||
}
|
||||
77
src/test/java/ASTs/AssignWrongTypeASTTyped.java
Normal file
77
src/test/java/ASTs/AssignWrongTypeASTTyped.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.BooleanConstantExpression;
|
||||
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class AssignWrongTypeASTTyped {
|
||||
public static Program getProgram(){
|
||||
|
||||
// TestMethod
|
||||
//Expressions
|
||||
// 0
|
||||
IntConstantExpression intConstantExpression0 = new IntConstantExpression(1);
|
||||
LocalVarDecl localVarDecl = new LocalVarDecl("int", "x", intConstantExpression0);
|
||||
|
||||
//1
|
||||
LocalVarIdentifier localVarIdentifier0 = new LocalVarIdentifier("x");
|
||||
BooleanConstantExpression booleanConstantExpression0 = new BooleanConstantExpression(true);
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", localVarIdentifier0, booleanConstantExpression0);
|
||||
|
||||
//2
|
||||
ReturnStatement returnStatement0 = new ReturnStatement(localVarIdentifier0);
|
||||
|
||||
String classThatContainsMethod = "AssignWrongType";
|
||||
String nameMethod0 = "test";
|
||||
String returnType = "int";
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
List<IStatement> iStatementList = new ArrayList<>();
|
||||
iStatementList.add(localVarDecl);
|
||||
iStatementList.add(assignStatementExpression0);
|
||||
iStatementList.add(returnStatement0);
|
||||
BlockStatement codeBlock = new BlockStatement(iStatementList, null);
|
||||
MethodDecl test = new MethodDecl(classThatContainsMethod, returnType, nameMethod0, parameterList, codeBlock);
|
||||
|
||||
String name = "AssignWrongType";
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(test);
|
||||
boolean hasMain = false;
|
||||
RefType assignWrongType = new RefType(name, fieldDeclList, methodDeclList, hasMain);
|
||||
List<RefType> refTypeList = new ArrayList<>();
|
||||
refTypeList.add(assignWrongType);
|
||||
Program program = new Program(refTypeList);
|
||||
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
//Type Context
|
||||
TypingHelper.addTypeContext(program, "AssignWrongType", new HashMap<>());
|
||||
|
||||
|
||||
//Method Context
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
method0.put("int", new ParameterList(new ArrayList<>()));
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
methods.put("test", method0);
|
||||
TypingHelper.addMethodContext(program, "AssignWrongType", methods);
|
||||
}
|
||||
}
|
||||
73
src/test/java/ASTs/CharArgumentAST.java
Normal file
73
src/test/java/ASTs/CharArgumentAST.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.*;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CharArgumentAST {
|
||||
public static Program getProgram() {
|
||||
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(getRefType());
|
||||
Program program = new Program(classes);
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
FieldDecl fieldDecl0 = new FieldDecl("char", "c", null);
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(fieldDecl0);
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
methodDeclList.add(method1());
|
||||
RefType charArgumentClass = new RefType("CharArgument", fieldDeclList, methodDeclList, false);
|
||||
|
||||
return charArgumentClass;
|
||||
}
|
||||
|
||||
public static MethodDecl method0(){
|
||||
SubReceiver subReceiver0 =new SubReceiver(true);
|
||||
List<SubReceiver> subReceiverList0 = new ArrayList<>();
|
||||
subReceiverList0.add(subReceiver0);
|
||||
InstVarExpression instVarExpression0 = new InstVarExpression(subReceiverList0, new ArrayList<>(), "c");
|
||||
CharConstantExpression charConstantExpression0 = new CharConstantExpression('a');
|
||||
List<IExpression> argumentList0 = new ArrayList<>();
|
||||
argumentList0.add(charConstantExpression0);
|
||||
MethodCallStatementExpression methodCallStatementExpression0 = new MethodCallStatementExpression("foo", null, new ArrayList<>(), argumentList0);
|
||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", instVarExpression0,methodCallStatementExpression0);
|
||||
List<IStatement> iStatementList0 = new ArrayList<>();
|
||||
iStatementList0.add(assignStatementExpression0);
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList0, null);
|
||||
MethodDecl methodDecl0 =new MethodDecl("CharArgument", null,
|
||||
"CharArgument", new ParameterList(new ArrayList<>()), blockStatement0);
|
||||
|
||||
return methodDecl0;
|
||||
}
|
||||
|
||||
public static MethodDecl method1(){
|
||||
ReturnStatement returnStatement0 =new ReturnStatement(new LocalVarIdentifier("c"));
|
||||
List<IStatement> iStatementList0 =new ArrayList<>();
|
||||
iStatementList0.add(returnStatement0);
|
||||
BlockStatement blockStatement0 = new BlockStatement(iStatementList0, null);
|
||||
Parameter parameter00 = new Parameter("char", "c");
|
||||
List<Parameter> parameterList0 = new ArrayList<>();
|
||||
parameterList0.add(parameter00);
|
||||
ParameterList parameterListObj0 = new ParameterList(parameterList0);
|
||||
MethodDecl methodDecl = new MethodDecl("CharArgument", "char", "foo",
|
||||
parameterListObj0, blockStatement0);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
}
|
||||
100
src/test/java/ASTs/CharArgumentASTTyped.java
Normal file
100
src/test/java/ASTs/CharArgumentASTTyped.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package ASTs;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import Typecheck.TypingHelper;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.*;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class CharArgumentASTTyped {
|
||||
public static Program getProgram() {
|
||||
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(getRefType());
|
||||
Program program = new Program(classes);
|
||||
addTyping(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public static RefType getRefType() {
|
||||
FieldDecl fieldDecl0 = new FieldDecl("char", "c", null);
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(fieldDecl0);
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
methodDeclList.add(method1());
|
||||
RefType charArgumentClass = new RefType("CharArgument", fieldDeclList, methodDeclList, false);
|
||||
|
||||
return charArgumentClass;
|
||||
}
|
||||
|
||||
public static MethodDecl method0(){
|
||||
SubReceiver subReceiver0 =new SubReceiver(true);
|
||||
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, "void");
|
||||
MethodDecl methodDecl0 =new MethodDecl("CharArgument", null,
|
||||
"CharArgument", new ParameterList(new ArrayList<>()), blockStatement0);
|
||||
|
||||
return methodDecl0;
|
||||
}
|
||||
|
||||
public static MethodDecl method1(){
|
||||
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, "char");
|
||||
Parameter parameter00 = new Parameter("char", "c");
|
||||
List<Parameter> parameterList0 = new ArrayList<>();
|
||||
parameterList0.add(parameter00);
|
||||
ParameterList parameterListObj0 = new ParameterList(parameterList0);
|
||||
MethodDecl methodDecl = new MethodDecl("CharArgument", "char", "foo",
|
||||
parameterListObj0, blockStatement0);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
HashMap<String, String> charArgumentMap0 = new HashMap<>();
|
||||
charArgumentMap0.put("c", "char");
|
||||
TypingHelper.addTypeContext(program, "CharArgument", charArgumentMap0);
|
||||
|
||||
// MethodContext
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
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("foo", method0);
|
||||
TypingHelper.addMethodContext(program, "CharArgument", methods);
|
||||
}
|
||||
}
|
||||
41
src/test/java/ASTs/ClassWithMainAST.java
Normal file
41
src/test/java/ASTs/ClassWithMainAST.java
Normal file
@@ -0,0 +1,41 @@
|
||||
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 ClassWithMainAST {
|
||||
|
||||
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 classWithMain = new RefType("classWithMain", fieldDeclList, methodDeclList, true);
|
||||
|
||||
return classWithMain;
|
||||
}
|
||||
|
||||
public static MethodDecl method0(){
|
||||
BlockStatement blockStatement = new BlockStatement(new ArrayList<>(), null);
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
MethodDecl methodDecl =new MethodDecl("classWithMain", "void", "main",
|
||||
parameterListObj, blockStatement);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
}
|
||||
51
src/test/java/ASTs/ClassWithMainASTTyped.java
Normal file
51
src/test/java/ASTs/ClassWithMainASTTyped.java
Normal file
@@ -0,0 +1,51 @@
|
||||
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 ClassWithMainASTTyped {
|
||||
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 classWithMain = new RefType("classWithMain", fieldDeclList, methodDeclList, true);
|
||||
|
||||
return classWithMain;
|
||||
}
|
||||
|
||||
public static MethodDecl method0(){
|
||||
BlockStatement blockStatement = new BlockStatement(new ArrayList<>(), "void");
|
||||
List<Parameter> parameterList = new ArrayList<>();
|
||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
||||
MethodDecl methodDecl =new MethodDecl("classWithMain", "void", "main",
|
||||
parameterListObj, blockStatement);
|
||||
|
||||
return methodDecl;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
TypingHelper.addTypeContext(program, "classWithMain", new HashMap<>());
|
||||
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, "classWithMain", 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);
|
||||
}
|
||||
}
|
||||
50
src/test/java/ASTs/DivideByZeroAST.java
Normal file
50
src/test/java/ASTs/DivideByZeroAST.java
Normal file
@@ -0,0 +1,50 @@
|
||||
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<>();
|
||||
methodDeclList.add(method0());
|
||||
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, true);
|
||||
|
||||
return refType;
|
||||
}
|
||||
public static MethodDecl method0(){
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
69
src/test/java/ASTs/DivideByZeroASTTyped.java
Normal file
69
src/test/java/ASTs/DivideByZeroASTTyped.java
Normal file
@@ -0,0 +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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ 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;
|
||||
@@ -12,23 +11,21 @@ import abstractSyntaxTree.Statement.IStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class emptyClassWithConstructorAST extends Program {
|
||||
public emptyClassWithConstructorAST()
|
||||
{
|
||||
super(staticClasses());
|
||||
}
|
||||
private static List<RefType> staticClasses() {
|
||||
public class EmptyClassWithConstructorAST {
|
||||
public static Program getProgram() {
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
|
||||
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
||||
List<IStatement> emptyIStatementList = new ArrayList<>();
|
||||
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, "void");
|
||||
MethodDecl constructor = new MethodDecl("emptyClassWithConstructor", "null", "emptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, null);
|
||||
MethodDecl constructor = new MethodDecl("EmptyClassWithConstructor", null, "EmptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(constructor);
|
||||
RefType emptyClass = new RefType("emptyClass", fieldDeclList, methodDeclList, false);
|
||||
RefType emptyClass = new RefType("EmptyClassWithConstructor", fieldDeclList, methodDeclList, false);
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(emptyClass);
|
||||
return classes;
|
||||
|
||||
Program program = new Program(classes);
|
||||
return program;
|
||||
}
|
||||
}
|
||||
46
src/test/java/ASTs/EmptyClassWithConstructorASTTyped.java
Normal file
46
src/test/java/ASTs/EmptyClassWithConstructorASTTyped.java
Normal file
@@ -0,0 +1,46 @@
|
||||
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 abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class EmptyClassWithConstructorASTTyped {
|
||||
public static Program getProgram() {
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
|
||||
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
||||
List<IStatement> emptyIStatementList = new ArrayList<>();
|
||||
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, "void");
|
||||
MethodDecl constructor = new MethodDecl("EmptyClassWithConstructor", null, "EmptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(constructor);
|
||||
RefType emptyClass = new RefType("EmptyClassWithConstructor", fieldDeclList, methodDeclList, false);
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(emptyClass);
|
||||
|
||||
Program program = new Program(classes);
|
||||
addTyping(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
TypingHelper.addTypeContext(program, "EmptyClassWithConstructor", 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, "EmptyClassWithConstructor", methods);
|
||||
}
|
||||
}
|
||||
112
src/test/java/ASTs/FakultaetAST.java
Normal file
112
src/test/java/ASTs/FakultaetAST.java
Normal file
@@ -0,0 +1,112 @@
|
||||
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 FakultaetAST {
|
||||
public static Program getProgram() {
|
||||
|
||||
String name = "Fakultaet";
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
methodDeclList.add(method1());
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
RefType fakultaet = new RefType(name, fieldDeclList, methodDeclList, true);
|
||||
classes.add(fakultaet);
|
||||
Program program = new Program(classes);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
private static MethodDecl method0() {
|
||||
String classThatContainsMethod = "Fakultaet";
|
||||
String name = "main";
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
String returnType = "void";
|
||||
List<IStatement> iStmtList = new ArrayList<>();
|
||||
BlockStatement blockStatement = new BlockStatement(iStmtList, null);
|
||||
return new MethodDecl(classThatContainsMethod, returnType, name, parameterList, blockStatement);
|
||||
}
|
||||
|
||||
private static MethodDecl method1() {
|
||||
String classThatContainsMethod = "Fakultaet";
|
||||
String name = "fak";
|
||||
// Parameters
|
||||
Parameter param0 = new Parameter("int", "number");
|
||||
List<Parameter> paramList = new ArrayList<>() {{
|
||||
add(param0);
|
||||
}};
|
||||
ParameterList parameterListObj = new ParameterList(paramList);
|
||||
|
||||
String returnType = "int";
|
||||
|
||||
// Block Statement
|
||||
List<IStatement> iStmtList0 = new ArrayList<>();
|
||||
// If Statament
|
||||
//condition
|
||||
LocalVarIdentifier binExprIdentifier = new LocalVarIdentifier("number");
|
||||
IntConstantExpression binExprIntConst = new IntConstantExpression(0);
|
||||
BinaryExpression binExpr = new BinaryExpression("<", binExprIdentifier, binExprIntConst);
|
||||
|
||||
IntConstantExpression return0Expr0 = new IntConstantExpression(1);
|
||||
ReturnStatement returnStatement0 = new ReturnStatement(return0Expr0);
|
||||
List<IStatement> iStmtList1 = new ArrayList<>();
|
||||
iStmtList1.add(returnStatement0);
|
||||
BlockStatement ifStmt = new BlockStatement(iStmtList1, null);
|
||||
IfStatement ifStatement = new IfStatement(binExpr, ifStmt);
|
||||
|
||||
iStmtList0.add(ifStatement);
|
||||
|
||||
// Expression 1
|
||||
IntConstantExpression intConst0 = new IntConstantExpression(1);
|
||||
LocalVarDecl localVarExpr0 = new LocalVarDecl("int", "factorial", intConst0);
|
||||
|
||||
iStmtList0.add(localVarExpr0);
|
||||
// Expression 2
|
||||
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 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);
|
||||
|
||||
iStmtList0.add(whileStatement0);
|
||||
|
||||
// Return Statement
|
||||
LocalVarIdentifier returnIdentifier = new LocalVarIdentifier("factorial");
|
||||
ReturnStatement returnStatement = new ReturnStatement(returnIdentifier);
|
||||
|
||||
iStmtList0.add(returnStatement);
|
||||
BlockStatement blockStatement = new BlockStatement(iStmtList0, null);
|
||||
return new MethodDecl(classThatContainsMethod, returnType, name, parameterListObj, blockStatement);
|
||||
}
|
||||
|
||||
}
|
||||
153
src/test/java/ASTs/FakultaetASTTyped.java
Normal file
153
src/test/java/ASTs/FakultaetASTTyped.java
Normal file
@@ -0,0 +1,153 @@
|
||||
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 FakultaetASTTyped {
|
||||
public static Program getProgram() {
|
||||
|
||||
String name = "Fakultaet";
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(method0());
|
||||
methodDeclList.add(method1());
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
RefType fakultaet = new RefType(name, fieldDeclList, methodDeclList, true);
|
||||
classes.add(fakultaet);
|
||||
Program program = new Program(classes);
|
||||
addTyping(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
private static MethodDecl method0() {
|
||||
String classThatContainsMethod = "Fakultaet";
|
||||
String name = "main";
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
String returnType = "void";
|
||||
List<IStatement> iStmtList = new ArrayList<>();
|
||||
BlockStatement blockStatement = new BlockStatement(iStmtList, "void");
|
||||
return new MethodDecl(classThatContainsMethod, returnType, name, parameterList, blockStatement);
|
||||
}
|
||||
|
||||
private static MethodDecl method1() {
|
||||
String classThatContainsMethod = "Fakultaet";
|
||||
String name = "fak";
|
||||
// Parameters
|
||||
Parameter param0 = new Parameter("int", "number");
|
||||
List<Parameter> paramList = new ArrayList<>() {{
|
||||
add(param0);
|
||||
}};
|
||||
ParameterList parameterListObj = new ParameterList(paramList);
|
||||
|
||||
String returnType = "int";
|
||||
|
||||
// Block Statement
|
||||
List<IStatement> iStmtList0 = new ArrayList<>();
|
||||
// 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();
|
||||
typeCheckResult1.type = "int";
|
||||
return0Expr0.setTypeCheckResult(typeCheckResult1);
|
||||
ReturnStatement returnStatement0 = new ReturnStatement(return0Expr0);
|
||||
List<IStatement> iStmtList1 = new ArrayList<>();
|
||||
iStmtList1.add(returnStatement0);
|
||||
BlockStatement ifStmt = new BlockStatement(iStmtList1, "int");
|
||||
IfStatement ifStatement = new IfStatement(binExpr, ifStmt);
|
||||
|
||||
iStmtList0.add(ifStatement);
|
||||
|
||||
// Expression 1
|
||||
IntConstantExpression intConst0 = new IntConstantExpression(1);
|
||||
LocalVarDecl localVarExpr0 = new LocalVarDecl("int", "factorial", intConst0);
|
||||
|
||||
iStmtList0.add(localVarExpr0);
|
||||
// Expression 2
|
||||
IntConstantExpression intConst1 = new IntConstantExpression(0);
|
||||
LocalVarDecl localVarExpr1 = new LocalVarDecl("int", "i", intConst1);
|
||||
|
||||
iStmtList0.add(localVarExpr1);
|
||||
|
||||
//While Statement
|
||||
LocalVarIdentifier identifierI = new LocalVarIdentifier("i");
|
||||
identifierI.setTypeCheckResult(new TypeCheckResult("int"));
|
||||
BinaryExpression whileCondition = new BinaryExpression("<=", identifierI, new LocalVarIdentifier("number"));
|
||||
whileCondition.setTypeCheckResult(new TypeCheckResult("void"));
|
||||
|
||||
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);
|
||||
|
||||
iStmtList0.add(whileStatement0);
|
||||
|
||||
// Return Statement
|
||||
LocalVarIdentifier returnIdentifier = new LocalVarIdentifier("factorial");
|
||||
TypeCheckResult typeCheckResult0 = new TypeCheckResult();
|
||||
typeCheckResult0.type = "int";
|
||||
returnIdentifier.setTypeCheckResult(typeCheckResult0);
|
||||
ReturnStatement returnStatement = new ReturnStatement(returnIdentifier);
|
||||
|
||||
iStmtList0.add(returnStatement);
|
||||
BlockStatement blockStatement = new BlockStatement(iStmtList0, "int");
|
||||
return new MethodDecl(classThatContainsMethod, returnType, name, parameterListObj, blockStatement);
|
||||
}
|
||||
|
||||
public static void addTyping(Program program){
|
||||
// TypeContext
|
||||
TypingHelper.addTypeContext(program, "Fakultaet", new HashMap<>());
|
||||
|
||||
// MethodContext
|
||||
//main Method
|
||||
HashMap<String, ParameterList> method1 = new HashMap<>();
|
||||
method1.put("void", new ParameterList(new ArrayList<>()));
|
||||
//fak Method
|
||||
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||
List<Parameter> parameterList0 = new ArrayList<>(){{
|
||||
add(new Parameter("int", "number"));
|
||||
}};
|
||||
ParameterList parameterListObj0 = new ParameterList(parameterList0);
|
||||
method0.put("int", parameterListObj0);
|
||||
|
||||
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||
methods.put("fak", method0);
|
||||
methods.put("main", method1);
|
||||
TypingHelper.addMethodContext(program, "Fakultaet", methods);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
32
src/test/java/ASTs/emptyClassASTTyped.java
Normal file
32
src/test/java/ASTs/emptyClassASTTyped.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package ASTs;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import Typecheck.TypingHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class emptyClassASTTyped {
|
||||
public static Program getEmptyProgramm() {
|
||||
List<FieldDecl> emptyFieldDeclList = new ArrayList<>();
|
||||
List<MethodDecl> emptyMethodDeclList = new ArrayList<>();
|
||||
RefType emptyClass = new RefType("emptyClass", emptyFieldDeclList, emptyMethodDeclList, false);
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(emptyClass);
|
||||
Program program = new Program(classes);
|
||||
addTyping(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
public static void addTyping(Program program) {
|
||||
HashMap<String, String> fields = new HashMap<>();
|
||||
//fields.put();
|
||||
TypingHelper.addTypeContext(program, "emptyClass", fields);
|
||||
TypingHelper.addMethodContext(program, "emptyClass", new HashMap<>());
|
||||
}
|
||||
}
|
||||
@@ -3,21 +3,24 @@ package ASTs;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.*;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
|
||||
public class fourClassesAST extends Program {
|
||||
|
||||
public fourClassesAST()
|
||||
@@ -26,55 +29,174 @@ public class fourClassesAST extends Program {
|
||||
}
|
||||
private static List<RefType> staticClasses() {
|
||||
|
||||
/////////// Classes ///////////
|
||||
|
||||
///////// Class: FourClasses /////////
|
||||
|
||||
/////// Fields ///////
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
|
||||
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
||||
|
||||
/////// Methods ///////
|
||||
|
||||
// Main //
|
||||
|
||||
List<IStatement> emptyIStatementList = new ArrayList<>();
|
||||
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, "void");
|
||||
MethodDecl constructor = new MethodDecl("emptyClassWithConstructor", "null", "emptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||
|
||||
//IStatement
|
||||
List<IStatement> fourClassesMainBlockIstatements = new ArrayList<>();
|
||||
|
||||
IExpression atntiLeft = new InstVarExpression("Test", "t");
|
||||
IExpression atntiRight = new NewStatementExpression();
|
||||
AssignStatementExpression atnti = new AssignStatementExpression(atntiLeft, "=", );
|
||||
|
||||
|
||||
ReturnStatement fcmbiReturn = new ReturnStatement();
|
||||
|
||||
fourClassesMainBlockIstatements.add(atnti);
|
||||
//BlockStatement
|
||||
BlockStatement fourClassesMainBlock = new BlockStatement(fourClassesMainBlockIstatements, "int");
|
||||
|
||||
//Parameter
|
||||
Parameter intI = new Parameter("int", "i");
|
||||
List<Parameter> fourClassesMainParameterList = new ArrayList<>();
|
||||
|
||||
ParameterList fourClassesMainParameters = new ParameterList(fourClassesMainParameterList);
|
||||
|
||||
MethodDecl fourClassesMain = new MethodDecl("fourClasses", "int", "main", fourClassesMainParameters, fourClassesMainBlock);
|
||||
List<MethodDecl> MethodDeclList = new ArrayList<>();
|
||||
|
||||
RefType emptyClass = new RefType("emptyClass", fieldDeclList, MethodDeclList, false);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
classes.add(emptyClass);
|
||||
return classes;
|
||||
return program;
|
||||
}
|
||||
}*/
|
||||
|
||||
public RefType Test() {
|
||||
|
||||
|
||||
// Class Test
|
||||
|
||||
//public int x
|
||||
FieldDecl publicIntX = new FieldDecl("int","x");
|
||||
|
||||
//public int y
|
||||
FieldDecl publicIntY = new FieldDecl("int", "y");
|
||||
|
||||
//public Test3 test3
|
||||
FieldDecl Test3test3 = new FieldDecl("Test3", "test3");
|
||||
|
||||
// FieldDeclList
|
||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||
fieldDeclList.add(publicIntX);
|
||||
fieldDeclList.add(publicIntY);
|
||||
fieldDeclList.add(Test3test3);
|
||||
|
||||
// (int i)
|
||||
List<Parameter> par11 = new ArrayList<>();
|
||||
Parameter inti = new Parameter("int", "i");
|
||||
par11.add(inti);
|
||||
ParameterList par1 = new ParameterList(par11);
|
||||
|
||||
//this.x
|
||||
InstVarExpression thisX = new InstVarExpression("X");
|
||||
|
||||
// i
|
||||
LocalVarIdentifier i = new LocalVarIdentifier("i");
|
||||
|
||||
//this.x = i
|
||||
AssignStatementExpression thisXeqI = new AssignStatementExpression("=", thisX, i);
|
||||
|
||||
//this.test3
|
||||
LocalVarIdentifier thisTest3 = new LocalVarIdentifier("test3");
|
||||
|
||||
// 2
|
||||
IntConstantExpression two = new IntConstantExpression(2);
|
||||
//(i * 2)
|
||||
BinaryExpression iTimes2 = new BinaryExpression("*", i, two);
|
||||
|
||||
//new Test3(i*2)
|
||||
List<IExpression> exprNewTest3 = new ArrayList<>();
|
||||
exprNewTest3.add(iTimes2);
|
||||
NewStatementExpression newTest3 = new NewStatementExpression("Test3",exprNewTest3 );
|
||||
|
||||
//this.test3 = new Test3(i * 2);
|
||||
AssignStatementExpression thisTesteqNewTest3 = new AssignStatementExpression("=", thisTest3, newTest3);
|
||||
|
||||
// {}
|
||||
List<IStatement> ilistTest = new ArrayList<>();
|
||||
ilistTest.add(thisTesteqNewTest3);
|
||||
BlockStatement blockTest = new BlockStatement(ilistTest,"void");
|
||||
|
||||
//public Test (int i)
|
||||
MethodDecl Test = new MethodDecl("Test", "void",
|
||||
"Test", par1, blockTest);
|
||||
|
||||
|
||||
// public Test3 getTest3() {return this.test3;}
|
||||
|
||||
//this.test3
|
||||
//LocalVarIdentifier thisTest3 = new LocalVarIdentifier("test3")
|
||||
|
||||
// return this.test3
|
||||
ReturnStatement returnThisTest3 = new ReturnStatement(thisTest3);
|
||||
|
||||
// {return this.test3}
|
||||
List<IStatement> getTest3Stmts = new ArrayList<>();
|
||||
getTest3Stmts.add(returnThisTest3);
|
||||
BlockStatement blockReturnThisTest3 = new BlockStatement(getTest3Stmts, "Test3");
|
||||
|
||||
ParameterList emptyParamList = new ParameterList(null);
|
||||
MethodDecl getTest3 = new MethodDecl("Test", "Test3",
|
||||
"gettest3", emptyParamList, blockReturnThisTest3);
|
||||
|
||||
|
||||
//this.x
|
||||
//LocalVarIdentifier thisX = new LocalVarIdentifier("x");
|
||||
|
||||
//return this.x
|
||||
ReturnStatement returnThisX = new ReturnStatement(thisX);
|
||||
|
||||
// {return this.x}
|
||||
List<IStatement> stmtsBlockReturnX = new ArrayList<>();
|
||||
stmtsBlockReturnX.add(returnThisX);
|
||||
BlockStatement blockReturnX = new BlockStatement(stmtsBlockReturnX,"int");
|
||||
|
||||
//public int getX() {
|
||||
// return this.x;
|
||||
// }
|
||||
MethodDecl getX = new MethodDecl("Test", "int",
|
||||
"getX", emptyParamList, blockReturnX);
|
||||
|
||||
//MethodDeclList
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(Test);
|
||||
methodDeclList.add(getTest3);
|
||||
methodDeclList.add(getX);
|
||||
|
||||
// Class Test
|
||||
RefType ClassTest = new RefType("Test", fieldDeclList,
|
||||
methodDeclList, false);
|
||||
|
||||
return ClassTest;
|
||||
}
|
||||
|
||||
public RefType FourClasses() {
|
||||
|
||||
LocalVarDecl localVarDecl1 = () -> {
|
||||
String type = Test2;
|
||||
String identifier = "t2";
|
||||
NewStatementExpression expression = () -> {
|
||||
String className = "Test2";
|
||||
List<IExpression> arguments = () -> {
|
||||
InstVarExpression arg0 = () -> {
|
||||
List<SubReceiver> receivers = () -> {
|
||||
ArrayList subReceiverList = new ArrayList<>();
|
||||
SubReceiver subreceiver1 = new SubReceiver();
|
||||
|
||||
subReceiverList.add(subreceiver1);
|
||||
|
||||
return subReceiverList;
|
||||
};
|
||||
List<ReceivingMethod> = () -> {
|
||||
ArrayList receivingMethodList = new ArrayList<>();
|
||||
ReceivingMethod receivingMethod01 = () -> {
|
||||
new ReceivingMethod();
|
||||
}
|
||||
return receivingMethodList
|
||||
};
|
||||
|
||||
return new InstVarExpression();
|
||||
};
|
||||
};
|
||||
return new NewStatementExpression();
|
||||
};
|
||||
|
||||
return new LocalVarDecl();
|
||||
};
|
||||
|
||||
LocalVarIdentifier localVarIdentifier01 = new LocalVarIdentifier("i");
|
||||
List<IExpression> localargumentList01 = new ArrayList<>();
|
||||
localargumentList01.add(localVarIdentifier01);
|
||||
NewStatementExpression newstmtexpr01 = new NewStatementExpression("Test", localargumentList01);
|
||||
LocalVarDecl statement01 = new LocalVarDecl("Test", "t", newstmtexpr01);
|
||||
List<IStatement> statements01 = new ArrayList<>();
|
||||
statements01.add(statement01);
|
||||
BlockStatement blockStatement0 = new BlockStatement(statements01, "int");
|
||||
|
||||
Parameter parameter01 = new Parameter("int", "i");
|
||||
List<Parameter> parameterList0x = new ArrayList<>();
|
||||
parameterList0x.add(parameter01);
|
||||
ParameterList parameterList0 = new ParameterList(parameterList0x);
|
||||
MethodDecl methodDecl0 = new MethodDecl("FourClasses", "int", "main", parameterList0, blockStatement0);
|
||||
|
||||
List<FieldDecl> fieldDeclsList = new ArrayList<>();
|
||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||
methodDeclList.add(methodDecl0);
|
||||
RefType FourClassesClass = new RefType("FourClasses", fieldDeclsList, methodDeclList, true);
|
||||
|
||||
return FourClassesClass;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
177
src/test/java/ByteCode/ByteCodeTester.java
Normal file
177
src/test/java/ByteCode/ByteCodeTester.java
Normal file
@@ -0,0 +1,177 @@
|
||||
package ByteCode;
|
||||
|
||||
import abstractSyntaxTree.Program;
|
||||
import astGenerator.ASTGenerator;
|
||||
import gen.DecafLexer;
|
||||
import gen.DecafParser;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class ByteCodeTester {
|
||||
CompareByteCodeBehaviour byteCodeBehaviourComparer;
|
||||
public ByteCodeTester(){
|
||||
byteCodeBehaviourComparer = new CompareByteCodeBehaviour();
|
||||
}
|
||||
|
||||
public void testByteCodeFromAst(String correctClassFilePath, Program abstractSyntaxTree, String className) {
|
||||
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) {
|
||||
Program abstractSyntaxTree = generateAST(fileToComparePath);
|
||||
typeCheckWithoutmain(abstractSyntaxTree);
|
||||
generateCode(abstractSyntaxTree);
|
||||
testAST(correctClassFilePath, className);
|
||||
}
|
||||
|
||||
private void typeCheckWithoutmain(Program abstractSyntaxTree){
|
||||
try {
|
||||
abstractSyntaxTree.typeCheckWithoutMain();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le type-check");
|
||||
}
|
||||
}
|
||||
|
||||
private void generateCode(Program abstractSyntaxTree){
|
||||
try {
|
||||
abstractSyntaxTree.codeGen();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le codegen");
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
private void testAST(String correctClassFilePath, String className) {
|
||||
try {
|
||||
ClassFileLoader classLoader1 = new ClassFileLoader(correctClassFilePath);
|
||||
ClassFileLoader classLoader2 = new ClassFileLoader(className+ ".class");
|
||||
|
||||
Class<?> class1 = classLoader1.findClass(className);
|
||||
Class<?> class2 = classLoader2.findClass(className);
|
||||
|
||||
assertTrue(CompareByteCodeSyntax.haveSameBehavior(class1, class2));
|
||||
assertTrue(byteCodeBehaviourComparer.compareMethodBehaviour(class1, class2));
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
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 {
|
||||
abstractSyntaxTree.codeGen();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le codegen");
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
|
||||
compareJarFiles(jarPath, "output.jar", classNames);
|
||||
}
|
||||
|
||||
public void compareJarFilesFromScratch(String javaCodePath, String jarPath, String[] classNames){
|
||||
String content = "";
|
||||
try {
|
||||
content = Files.readString(Path.of(javaCodePath));
|
||||
} 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);
|
||||
|
||||
try {
|
||||
abstractSyntaxTree.typeCheckWithoutMain();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le type-check");
|
||||
fail();
|
||||
}
|
||||
|
||||
try {
|
||||
abstractSyntaxTree.codeGen();
|
||||
} catch (Exception e){
|
||||
System.out.println("Le Exception in le codegen");
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
|
||||
compareJarFiles(jarPath, "output.jar", classNames);
|
||||
|
||||
}
|
||||
|
||||
public void compareJarFiles(String jarPath1, String jarPath2, String[] classNames) {
|
||||
try {
|
||||
JarFileLoader loader1 = new JarFileLoader(jarPath1);
|
||||
JarFileLoader loader2 = new JarFileLoader(jarPath2);
|
||||
CompareByteCodeBehaviour comparator = new CompareByteCodeBehaviour();
|
||||
|
||||
for (String className : classNames) {
|
||||
Class<?> class1 = loader1.loadClass(className);
|
||||
Class<?> class2 = loader2.loadClass(className);
|
||||
|
||||
boolean comparisonResult0 = CompareByteCodeSyntax.haveSameBehavior(class1, class2);
|
||||
System.out.println("Syntax Comparison result for " + className + ": " + comparisonResult0);
|
||||
|
||||
boolean comparisonResult1 = comparator.compareMethodBehaviour(class1, class2);
|
||||
System.out.println("Behaviour Comparison result for " + className + ": " + comparisonResult1);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FileClassLoader extends ClassLoader {
|
||||
public class ClassFileLoader extends ClassLoader {
|
||||
private final String classFilePath;
|
||||
|
||||
public FileClassLoader(String classFilePath) {
|
||||
public ClassFileLoader(String classFilePath) {
|
||||
this.classFilePath = classFilePath;
|
||||
}
|
||||
|
||||
@@ -34,4 +34,4 @@ public class FileClassLoader extends ClassLoader {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import java.lang.reflect.Method;
|
||||
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;
|
||||
|
||||
@@ -37,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)) {
|
||||
@@ -48,18 +58,27 @@ 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){
|
||||
try {
|
||||
this.sortMethods(class1, class2);
|
||||
// Create instances
|
||||
Constructor<?> constructor1 = class1.getDeclaredConstructor();
|
||||
Constructor<?> constructor2 = class2.getDeclaredConstructor();
|
||||
Constructor<?>[] constructors1 = class1.getDeclaredConstructors();
|
||||
Constructor<?>[] constructors2 = class2.getDeclaredConstructors();
|
||||
Constructor<?> constructor1 = constructors1[0];
|
||||
Constructor<?> constructor2 = constructors2[0];
|
||||
constructor1.setAccessible(true);
|
||||
constructor2.setAccessible(true);
|
||||
Object obj1 = constructor1.newInstance();
|
||||
Object obj2 = constructor2.newInstance();
|
||||
Object[] constructorArgs = getDefaultArguments(constructor1.getParameters());
|
||||
Object obj1 = constructor1.newInstance(constructorArgs);
|
||||
Object obj2 = constructor2.newInstance(constructorArgs);
|
||||
|
||||
// Get methods
|
||||
Method[] methods1 = new Method[this.methodArray1.size()];
|
||||
@@ -67,31 +86,53 @@ 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);
|
||||
|
||||
System.out.println("Result method 1: " + result1);
|
||||
System.out.println("Result method 2: " + result2);
|
||||
|
||||
if (!result1.equals(result2)) {
|
||||
return false;
|
||||
if( !((result1 == null) && (result2 == null))) {
|
||||
if(( result1 == null) || (result2 == null) ) {
|
||||
return false;
|
||||
}
|
||||
if (!result1.equals(result2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException |
|
||||
NoSuchMethodException | InvocationTargetException e) {
|
||||
InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -99,15 +140,42 @@ 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] = random.nextBoolean();
|
||||
}
|
||||
// Add more cases as needed for different parameter types
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
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] = random.nextBoolean();
|
||||
} else if (paramType == int.class) {
|
||||
defaultArgs[i] = random.nextInt(10);
|
||||
} else if (paramType == char.class) {
|
||||
defaultArgs[i] = '\u0000';
|
||||
} else if (paramType == String.class) {
|
||||
defaultArgs[i] = "baguette";
|
||||
}
|
||||
} else {
|
||||
defaultArgs[i] = null; // Use null for non-primitive types
|
||||
}
|
||||
}
|
||||
return defaultArgs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CompareByteCodeSyntax {
|
||||
|
||||
public static boolean haveSameBehavior(Class<?> class1, Class<?> class2) {
|
||||
@@ -24,9 +25,11 @@ public class CompareByteCodeSyntax {
|
||||
|
||||
public static boolean compareClassSignatures(Class<?> class1, Class<?> class2) {
|
||||
if (!Arrays.equals(class1.getInterfaces(), class2.getInterfaces())) {
|
||||
System.out.println("Interfaces do not match");
|
||||
return false;
|
||||
}
|
||||
if (class1.getSuperclass() != class2.getSuperclass()) {
|
||||
System.out.println("Superclasses do not match");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -36,6 +39,7 @@ public class CompareByteCodeSyntax {
|
||||
Method[] methods1 = class1.getDeclaredMethods();
|
||||
Method[] methods2 = class2.getDeclaredMethods();
|
||||
if (methods1.length != methods2.length) {
|
||||
System.out.println("Method counts do not match");
|
||||
return false;
|
||||
}
|
||||
for (Method method1 : methods1) {
|
||||
@@ -49,6 +53,7 @@ public class CompareByteCodeSyntax {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
System.out.println("No matching method found for: " + method1.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -57,17 +62,22 @@ public class CompareByteCodeSyntax {
|
||||
|
||||
public static boolean compareMethod(Method method1, Method method2) {
|
||||
if (!method1.getReturnType().equals(method2.getReturnType())) {
|
||||
System.out.println("Return types do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(method1.getParameterTypes(), method2.getParameterTypes())) {
|
||||
System.out.println("Parameter types do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(method1.getExceptionTypes(), method2.getExceptionTypes())) {
|
||||
System.out.println("Exception types do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||
return false;
|
||||
}
|
||||
if (!compareAnnotations(method1.getAnnotations(), method2.getAnnotations())) {
|
||||
System.out.println("Annotations do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,6 +85,7 @@ public class CompareByteCodeSyntax {
|
||||
Field[] fields1 = class1.getDeclaredFields();
|
||||
Field[] fields2 = class2.getDeclaredFields();
|
||||
if (fields1.length != fields2.length) {
|
||||
System.out.println("Field counts do not match");
|
||||
return false;
|
||||
}
|
||||
for (Field field1 : fields1) {
|
||||
@@ -88,6 +99,7 @@ public class CompareByteCodeSyntax {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
System.out.println("No matching field found for: " + field1.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -96,9 +108,11 @@ public class CompareByteCodeSyntax {
|
||||
|
||||
public static boolean compareField(Field field1, Field field2) {
|
||||
if (!field1.getType().equals(field2.getType())) {
|
||||
System.out.println("Field types do not match for fields " + field1.getName() + " and " + field2.getName());
|
||||
return false;
|
||||
}
|
||||
if (!compareAnnotations(field1.getAnnotations(), field2.getAnnotations())) {
|
||||
System.out.println("Annotations do not match for fields " + field1.getName() + " and " + field2.getName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -106,6 +120,7 @@ public class CompareByteCodeSyntax {
|
||||
|
||||
public static boolean compareAnnotations(Annotation[] annotations1, Annotation[] annotations2) {
|
||||
if (annotations1.length != annotations2.length) {
|
||||
System.out.println("Annotation counts do not match");
|
||||
return false;
|
||||
}
|
||||
for (Annotation annotation1 : annotations1) {
|
||||
@@ -117,10 +132,10 @@ public class CompareByteCodeSyntax {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
System.out.println("No matching annotation found for: " + annotation1.annotationType().getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
50
src/test/java/ByteCode/JarFileLoader.java
Normal file
50
src/test/java/ByteCode/JarFileLoader.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package ByteCode;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class JarFileLoader extends ClassLoader {
|
||||
private final String jarFilePath;
|
||||
|
||||
public JarFileLoader(String jarFilePath) {
|
||||
this.jarFilePath = jarFilePath;
|
||||
System.out.println("Jar File Path: " + jarFilePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String classFileName = name.replace('.', '/') + ".class";
|
||||
try {
|
||||
byte[] classData = loadClassDataFromJar(classFileName);
|
||||
return defineClass(name, classData, 0, classData.length);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new ClassNotFoundException("Class not found: " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] loadClassDataFromJar(String classFileName) throws IOException {
|
||||
try (JarFile jarFile = new JarFile(new File(jarFilePath))) {
|
||||
JarEntry entry = jarFile.getJarEntry(classFileName);
|
||||
if (entry == null) {
|
||||
System.err.println("Class file " + classFileName + " not found in jar file.");
|
||||
throw new IOException("Class file " + classFileName + " not found in jar file.");
|
||||
}
|
||||
|
||||
try (InputStream is = jarFile.getInputStream(entry);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user