Compare commits
118 Commits
ed2f64eff9
...
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 |
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>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
<component name="PWA">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<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>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -3,7 +3,6 @@
|
|||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/NichtHaskell.iml" filepath="$PROJECT_DIR$/NichtHaskell.iml" />
|
<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>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</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.
35
pom.xml
35
pom.xml
@@ -4,25 +4,46 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>Clippit.org</groupId>
|
<groupId>Clippit.org</groupId>
|
||||||
<artifactId>NichtHaskell</artifactId>
|
<artifactId>NichtHaskell</artifactId>
|
||||||
<version>1</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>20</maven.compiler.source>
|
<java.version>22</java.version>
|
||||||
<maven.compiler.target>20</maven.compiler.target>
|
<maven.compiler.source>22</maven.compiler.source>
|
||||||
|
<maven.compiler.target>22</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<version>2.22.2</version>
|
<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>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
|||||||
@@ -8,5 +8,17 @@
|
|||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<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>
|
</component>
|
||||||
</module>
|
</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,4 +1,4 @@
|
|||||||
import abstractSyntaxTree.Class.RefType;
|
import TypeCheck.TypeCheckException;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
import astGenerator.ASTGenerator;
|
import astGenerator.ASTGenerator;
|
||||||
import gen.DecafLexer;
|
import gen.DecafLexer;
|
||||||
@@ -9,6 +9,7 @@ import org.antlr.v4.runtime.CommonTokenStream;
|
|||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -18,41 +19,53 @@ public class Compiler {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception{
|
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
|
String filePath = args[0];
|
||||||
Path absolutePath = filePath.toAbsolutePath();
|
|
||||||
System.out.println("Processing input: " + absolutePath);
|
|
||||||
|
|
||||||
String content;
|
boolean suppressDetails = false;
|
||||||
try {
|
|
||||||
content = Files.readString(filePath);
|
if (args.length > 1 && args[1].equals("--suppress-details")) {
|
||||||
}catch (java.nio.file.NoSuchFileException e){
|
suppressDetails = true;
|
||||||
System.out.println("File not found");
|
}
|
||||||
|
|
||||||
|
Path path = Paths.get(filePath);
|
||||||
|
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
System.out.println("Your input file was not found: " + path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!suppressDetails)
|
||||||
|
System.out.println("Processing input: " + path);
|
||||||
|
|
||||||
System.out.println("--- print content ---");
|
String content = Files.readString(path);
|
||||||
System.out.println(content);
|
|
||||||
|
if(!suppressDetails)
|
||||||
|
System.out.println("The content of your input file is: \n" + content);
|
||||||
|
|
||||||
CharStream codeCharStream = CharStreams.fromString(content);
|
CharStream codeCharStream = CharStreams.fromString(content);
|
||||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
|
||||||
System.out.println("--- print tokens ---");
|
|
||||||
tokens.fill();
|
tokens.fill();
|
||||||
|
|
||||||
List<Token> tokenList = tokens.getTokens();
|
if(!suppressDetails) {
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
List<Token> tokenList = tokens.getTokens();
|
||||||
for (Token token : tokenList) {
|
|
||||||
stringBuilder.append(token.getText()).append(" ");
|
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);
|
DecafParser parser = new DecafParser(tokens);
|
||||||
@@ -63,14 +76,44 @@ public class Compiler {
|
|||||||
Program abstractSyntaxTree =(Program) generator.visit(tree);
|
Program abstractSyntaxTree =(Program) generator.visit(tree);
|
||||||
|
|
||||||
|
|
||||||
System.out.println("--- AST generator ---");
|
|
||||||
System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes with names:");
|
if(!suppressDetails) {
|
||||||
for (RefType refType : abstractSyntaxTree.classes) {
|
System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes: ");
|
||||||
System.out.println(refType.name);
|
abstractSyntaxTree.classes.forEach(refType -> {
|
||||||
|
System.out.println("\t" + refType.name);
|
||||||
|
});
|
||||||
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstractSyntaxTree.typeCheck();
|
try {
|
||||||
|
abstractSyntaxTree.typeCheck();
|
||||||
|
}catch(TypeCheckException e){
|
||||||
|
System.out.println("A TypeCheck error was found in you input. Your input was not compiled.");
|
||||||
|
System.out.println(e);
|
||||||
|
return;
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("A unexpected error occurred in TypeCheck.");
|
||||||
|
System.out.println(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
abstractSyntaxTree.codeGen();
|
if(!suppressDetails)
|
||||||
|
System.out.println("No TypeCheck errors found.");
|
||||||
|
|
||||||
|
abstractSyntaxTree.codeGen();//todo remove
|
||||||
|
|
||||||
|
try {
|
||||||
|
abstractSyntaxTree.codeGen();
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("A error occurred during code generation. Your input was not compiled.");
|
||||||
|
System.out.println(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File outputJarFile = new File("output.jar");
|
||||||
|
if (outputJarFile.exists())
|
||||||
|
outputJarFile.delete();
|
||||||
|
|
||||||
|
System.out.println("Your input was compiled. You can find the output in your current working directory.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ subExpression: This | assignableExpr | stmtExpr | OpenRoundBracket subExpression
|
|||||||
//.trim().toLength().toLowerCase().count ...
|
//.trim().toLength().toLowerCase().count ...
|
||||||
methodCall: receiver? receivingMethod* Identifier OpenRoundBracket argumentList ClosedRoundBracket;
|
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;
|
stmtExpr: assign | newDecl | methodCall;
|
||||||
|
|
||||||
@@ -62,6 +62,9 @@ value: IntValue | BooleanValue | CharValue | NullValue;
|
|||||||
AccessModifierPublic : 'public' ;
|
AccessModifierPublic : 'public' ;
|
||||||
MainMethodDecl : 'public static void main(String[] args)';
|
MainMethodDecl : 'public static void main(String[] args)';
|
||||||
|
|
||||||
|
//Print Statement print(VariableA);
|
||||||
|
print: 'print' OpenRoundBracket Identifier ClosedRoundBracket Semicolon;
|
||||||
|
|
||||||
//Types
|
//Types
|
||||||
Void : 'void';
|
Void : 'void';
|
||||||
Int : 'int';
|
Int : 'int';
|
||||||
@@ -111,7 +114,7 @@ New : 'new';
|
|||||||
|
|
||||||
|
|
||||||
//Values
|
//Values
|
||||||
IntValue : ('+'|'-')*[0-9]+;
|
IntValue : ('+'|'-')?[0-9]+;
|
||||||
CharValue: '\''~[\r\n]?'\'';
|
CharValue: '\''~[\r\n]?'\'';
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
class EmptyClass {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
class Example1 {
|
|
||||||
Example e;
|
|
||||||
public Example1(){}
|
|
||||||
int meth(int n){
|
|
||||||
Example e = new Example();
|
|
||||||
int i = m1(2).m2().m3();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Example m1(int n){
|
|
||||||
return new Example();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Example {
|
|
||||||
Example1 example1;
|
|
||||||
Example1 m(int a){
|
|
||||||
return new Example1();
|
|
||||||
}
|
|
||||||
Example m2(){return new Example();}
|
|
||||||
int m3(){return 1;}
|
|
||||||
}
|
|
||||||
@@ -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){
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,17 +8,18 @@ public class TypeCheckHelper {
|
|||||||
boolean type1Primitiv = Objects.equals(type1, "boolean") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
|
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");
|
boolean type2Primitiv = Objects.equals(type2, "boolean") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
|
||||||
|
|
||||||
String result;
|
String result = "class";
|
||||||
if(type1Primitiv && type2Primitiv){
|
if(type1Primitiv && type2Primitiv){
|
||||||
if(Objects.equals(type1, type2)){
|
if(Objects.equals(type1, type2)){
|
||||||
result = type1;
|
result = type1;
|
||||||
}else{
|
}else{
|
||||||
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
||||||
}
|
}
|
||||||
}else if(type1Primitiv || type2Primitiv){
|
}else if(type1Primitiv ^ type2Primitiv){
|
||||||
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
||||||
}else{
|
}else{
|
||||||
result = "class";
|
if(Objects.equals(type1, type2))
|
||||||
|
result = type1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,27 @@
|
|||||||
package TypeCheck;
|
package TypeCheck;
|
||||||
|
|
||||||
|
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class TypeCheckResult {
|
public class TypeCheckResult {
|
||||||
|
|
||||||
|
public TypeCheckResult(){}
|
||||||
|
public TypeCheckResult(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
public String 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,11 +1,12 @@
|
|||||||
package abstractSyntaxTree.Class;
|
package abstractSyntaxTree.Class;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Program;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.FieldVisitor;
|
import org.objectweb.asm.FieldVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -17,12 +18,14 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public class FieldDecl extends AbstractType implements Node {
|
public class FieldDecl extends AbstractType implements Node {
|
||||||
|
|
||||||
public String type; // from parser
|
public String type;
|
||||||
public String identifier; // from parser
|
public String identifier;
|
||||||
|
public IExpression expression;
|
||||||
|
|
||||||
public FieldDecl(String type, String identifier){
|
public FieldDecl(String type, String identifier, IExpression expression){
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||||
|
|
||||||
@@ -41,35 +44,24 @@ public class FieldDecl extends AbstractType implements Node {
|
|||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
//write field table
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassWriter cw) {
|
||||||
//TODO: Do we have fields with initial values? --> No dont think so --> assign
|
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, descriptor, null, null);
|
||||||
fv.visitEnd();
|
fv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldDescriptor() {
|
|
||||||
switch (type) {
|
|
||||||
case "int":
|
|
||||||
return "I";
|
|
||||||
case "boolean":
|
|
||||||
return "Z";
|
|
||||||
case "char":
|
|
||||||
return "C";
|
|
||||||
default:
|
|
||||||
return "L" + type + ";";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
FieldDecl fieldDecl = (FieldDecl) o;
|
FieldDecl fieldDecl = (FieldDecl) o;
|
||||||
return ( Objects.equals(type, fieldDecl.type)
|
boolean result = Objects.equals(type, fieldDecl.type)
|
||||||
&& Objects.equals(identifier, fieldDecl.identifier));
|
&& Objects.equals(identifier, fieldDecl.identifier)
|
||||||
|
&& Objects.equals(expression, fieldDecl.expression);
|
||||||
|
|
||||||
|
System.out.println("In FieldDecl: " + result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package abstractSyntaxTree.Class;
|
package abstractSyntaxTree.Class;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Program;
|
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -35,7 +34,6 @@ public class MethodDecl implements Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||||
// jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben
|
|
||||||
List<Parameter> parametersList = parameters.parameterList;
|
List<Parameter> parametersList = parameters.parameterList;
|
||||||
for(Parameter parameter : parametersList){
|
for(Parameter parameter : parametersList){
|
||||||
localVars.put(parameter.identifier, parameter.type);
|
localVars.put(parameter.identifier, parameter.type);
|
||||||
@@ -43,19 +41,21 @@ public class MethodDecl implements Node {
|
|||||||
|
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
codeBlock.thisClass = classThatContainsMethod;
|
codeBlock.thisClass = classThatContainsMethod;
|
||||||
String CodeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type;
|
String codeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type;
|
||||||
if(!Objects.equals(this.returnType, CodeBlockType))
|
if(Objects.equals(this.name, classThatContainsMethod))
|
||||||
throw new TypeCheckException("Method returns " + CodeBlockType + ", but should return " + this.returnType + ". ");
|
codeBlockType = null;
|
||||||
|
|
||||||
|
if(!Objects.equals(this.returnType, codeBlockType))
|
||||||
|
throw new TypeCheckException("Method returns " + codeBlockType + ", but should return " + this.returnType + ". ");
|
||||||
|
|
||||||
result.type = codeBlock.returnType;
|
result.type = codeBlock.returnType;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO: Es wird kein Bytecode für Standardkonstruktoren für die Klassen generiert
|
|
||||||
//TODO: Stack computing schlägt fehl --> Reihenfolge aufruf? --> Sobald if-else / if / while drin sind? --> vllt auch schon bei MethodenDecl
|
|
||||||
//Need to get the returnType of the method if it is an object
|
//Need to get the returnType of the method if it is an object
|
||||||
// methodContext (class, (returnType, (identifier, parameter)))
|
// methodContext (class, (identifier, (returnType, parameter)))
|
||||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
// 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);
|
localVars.put("this", classThatContainsMethod);
|
||||||
for (Parameter param : parameters.parameterList) {
|
for (Parameter param : parameters.parameterList) {
|
||||||
@@ -64,27 +64,63 @@ public class MethodDecl implements Node {
|
|||||||
|
|
||||||
// check if the method is a constructor
|
// check if the method is a constructor
|
||||||
if (classThatContainsMethod.equals(name) && returnType == null) {
|
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);
|
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
|
||||||
|
|
||||||
//Call the superclass constructor
|
//Call the superclass constructor
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
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
|
//Load the parameters onto the stack
|
||||||
int localVarIndex = 1;
|
int localVarIndex = 1;
|
||||||
for (Parameter param : parameters.parameterList) {
|
for (Parameter param : parameters.parameterList) {
|
||||||
String paramType = param.type;
|
String paramType = param.type;
|
||||||
switch(paramType) {
|
switch(paramType) {
|
||||||
case "int", "boolean", "char" -> mv.visitVarInsn(Opcodes.ILOAD, localVarIndex);
|
case "int", "boolean", "char" -> {
|
||||||
default -> mv.visitVarInsn(Opcodes.ALOAD, localVarIndex);
|
mv.visitVarInsn(Opcodes.ILOAD, localVarIndex);
|
||||||
|
mv.visitVarInsn(Opcodes.ISTORE, localVarIndex);
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, localVarIndex);
|
||||||
|
mv.visitVarInsn(Opcodes.ASTORE, localVarIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
localVarIndex++;
|
localVarIndex++;
|
||||||
}
|
}
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", descriptor, false);
|
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
codeBlock.codeGen(mv, localVars, typeContext);
|
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
//automatically computed max stack and max locals
|
//automatically computed max stack and max locals
|
||||||
@@ -96,17 +132,17 @@ public class MethodDecl implements Node {
|
|||||||
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
|
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
codeBlock.codeGen(mv, localVars, typeContext);
|
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
|
||||||
} else {
|
} 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();
|
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
|
// 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
|
// For methods which return an actual value, the return opcode is created in the method body to ensure the
|
||||||
@@ -118,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
|
// get the method descriptor
|
||||||
StringBuilder descriptor = new StringBuilder("(");
|
StringBuilder descriptor = new StringBuilder("(");
|
||||||
|
|
||||||
@@ -131,8 +167,18 @@ public class MethodDecl implements Node {
|
|||||||
case "void" -> descriptor.append("V");
|
case "void" -> descriptor.append("V");
|
||||||
default -> {
|
default -> {
|
||||||
// object
|
// object
|
||||||
//TODO: This is not finished for objects --> classes and methods
|
if (param.type != null) {
|
||||||
if (returnType != null) descriptor.append("L").append(returnType).append(";");
|
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(";");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,10 +219,12 @@ public class MethodDecl implements Node {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
MethodDecl methodDecl = (MethodDecl) o;
|
MethodDecl methodDecl = (MethodDecl) o;
|
||||||
return (Objects.equals(name, methodDecl.name)
|
boolean result = (Objects.equals(name, methodDecl.name)
|
||||||
&& Objects.equals(parameters, methodDecl.parameters)
|
&& Objects.equals(parameters, methodDecl.parameters)
|
||||||
&& Objects.equals(returnType, methodDecl.returnType)
|
&& Objects.equals(returnType, methodDecl.returnType)
|
||||||
&& Objects.equals(codeBlock, methodDecl.codeBlock));
|
&& Objects.equals(codeBlock, methodDecl.codeBlock));
|
||||||
|
System.out.println("In MethodDecl: " + result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package abstractSyntaxTree.Class;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@@ -67,7 +67,6 @@ public class RefType extends AbstractType implements Node {
|
|||||||
|
|
||||||
// type check each method
|
// type check each method
|
||||||
for (MethodDecl methodDecl : methodDecls) {
|
for (MethodDecl methodDecl : methodDecls) {
|
||||||
// methodDecl.classThatContainsMethod = this.name;
|
|
||||||
methodDecl.typeCheck(methodContext, typeContext);
|
methodDecl.typeCheck(methodContext, typeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ public class RefType extends AbstractType implements Node {
|
|||||||
// Method for code generation which iterates over all the field declarations
|
// Method for code generation which iterates over all the field declarations
|
||||||
// and method declarations and calls their CodeGen methods
|
// 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,
|
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null,
|
||||||
"java/lang/Object", null);
|
"java/lang/Object", null);
|
||||||
@@ -88,22 +87,37 @@ public class RefType extends AbstractType implements Node {
|
|||||||
field.codeGen(cw);
|
field.codeGen(cw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean hasCustomConstructor = false;
|
||||||
for (MethodDecl method : methodDecls) {
|
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();
|
cw.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
System.out.println("Dont forget me ;)");
|
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
RefType refType = (RefType) o;
|
RefType refType = (RefType) o;
|
||||||
return ( Objects.equals(name, refType.name)
|
boolean result = ( Objects.equals(name, refType.name)
|
||||||
&& Objects.equals(fieldDecls, refType.fieldDecls)
|
&& Objects.equals(fieldDecls, refType.fieldDecls)
|
||||||
&& Objects.equals(methodDecls, refType.methodDecls)
|
&& Objects.equals(methodDecls, refType.methodDecls)
|
||||||
&& Objects.equals(hasMain, refType.hasMain));
|
&& 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.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -14,7 +13,10 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
BoolDatatype boolDatatype = (BoolDatatype) o;
|
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
|
@Override
|
||||||
public TypeCheckResult typeCheck() {
|
public TypeCheckResult typeCheck() {
|
||||||
@@ -39,4 +41,6 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
|||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.getTypeCheckResult();
|
return super.getTypeCheckResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package abstractSyntaxTree.Datatype;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -21,18 +22,23 @@ public class CharDatatype extends AbstractType implements IDatatype{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv) throws Exception {
|
||||||
|
if (value <= 5) {
|
||||||
// Possible use of BIPUSH and SIPUSH if the value is small enough
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
//This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway
|
} else if (value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
mv.visitLdcInsn((int)value);
|
} else {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
CharDatatype charDatatype = (CharDatatype) o;
|
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
|
@Override
|
||||||
|
|||||||
@@ -5,14 +5,9 @@ import TypeCheck.TypeCheckResult;
|
|||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
public interface IDatatype {
|
public interface IDatatype {
|
||||||
// typeCheck method
|
|
||||||
TypeCheckResult typeCheck() throws TypeCheckException;
|
TypeCheckResult typeCheck() throws TypeCheckException;
|
||||||
|
|
||||||
// visit method for code generation
|
|
||||||
|
|
||||||
void codeGen(MethodVisitor mv) throws Exception;
|
void codeGen(MethodVisitor mv) throws Exception;
|
||||||
|
|
||||||
TypeCheckResult getTypeCheckResult();
|
TypeCheckResult getTypeCheckResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Check if we need to differentiate between primitive types and reference types --> for example in "=="
|
|
||||||
@@ -21,8 +21,6 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
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)
|
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
||||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||||
@@ -36,7 +34,10 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
IntDatatype intDatatype = (IntDatatype) o;
|
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
|
@Override
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import TypeCheck.AbstractType;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.beans.Expression;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -17,6 +16,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
public String operator;
|
public String operator;
|
||||||
public IExpression left;
|
public IExpression left;
|
||||||
public IExpression right;
|
public IExpression right;
|
||||||
|
public String thisClass;
|
||||||
|
|
||||||
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
@@ -28,6 +28,10 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
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 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 leftType = left.typeCheck(methodContext, typeContext, localVars);
|
||||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
@@ -46,7 +50,8 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
case "<=":
|
case "<=":
|
||||||
case ">=":
|
case ">=":
|
||||||
case "!=":
|
case "!=":
|
||||||
result.type = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||||
|
result.type = "boolean";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "-":
|
case "-":
|
||||||
@@ -57,9 +62,6 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
result.type = "int";
|
result.type = "int";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//case "&" ist für logisches und auf bit level
|
|
||||||
//case "|" ist für logisches oder auf bit level
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
@@ -67,7 +69,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 for the jump instruction
|
||||||
Label operationFalse = new Label(); //Operation is false
|
Label operationFalse = new Label(); //Operation is false
|
||||||
Label operationTrue = new Label(); //Operation is true
|
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
|
Label expressionEnd = new Label(); //End of the whole expression
|
||||||
|
|
||||||
// Bytecode for the binary operation
|
// Bytecode for the binary operation
|
||||||
switch (operator) {
|
if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
|
||||||
case "&&":
|
switch (operator) {
|
||||||
left.codeGen(mv, localVars, typeContext);
|
case "+" -> {
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
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);
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||||
break;
|
}
|
||||||
|
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 "||":
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
left.codeGen(mv, localVars, typeContext);
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
}
|
||||||
|
case "==" -> {
|
||||||
|
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
right.codeGen(mv, localVars, typeContext);
|
switch (left.getTypeCheckResult().type) {
|
||||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
case "int", "boolean", "char" -> mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue);
|
||||||
break;
|
|
||||||
|
|
||||||
case "==":
|
default -> mv.visitJumpInsn(Opcodes.IF_ACMPEQ, operationTrue);
|
||||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
}
|
||||||
|
}
|
||||||
|
case "<" -> {
|
||||||
|
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
left.codeGen(mv, localVars, typeContext);
|
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||||
right.codeGen(mv, localVars, typeContext);
|
}
|
||||||
|
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
|
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||||
break;
|
}
|
||||||
|
case "<=" -> {
|
||||||
|
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
case "<":
|
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||||
left.codeGen(mv, localVars, typeContext);
|
}
|
||||||
right.codeGen(mv, localVars, typeContext);
|
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
|
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||||
break;
|
}
|
||||||
|
case "!=" -> {
|
||||||
|
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
case ">":
|
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||||
left.codeGen(mv, localVars, typeContext);
|
}
|
||||||
right.codeGen(mv, localVars, typeContext);
|
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
|
mv.visitLabel(operationTrue);
|
||||||
break;
|
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||||
|
|
||||||
case "<=":
|
mv.visitLabel(expressionEnd);
|
||||||
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 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.visitLabel(operationTrue);
|
|
||||||
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
|
||||||
|
|
||||||
mv.visitLabel(expressionEnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -181,10 +176,14 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
BinaryExpression binaryExpression = (BinaryExpression) o;
|
BinaryExpression binaryExpression = (BinaryExpression) o;
|
||||||
return (Objects.equals(operator, binaryExpression.operator)
|
boolean result = (Objects.equals(operator, binaryExpression.operator)
|
||||||
&& Objects.equals(left, binaryExpression.left)
|
&& Objects.equals(left, binaryExpression.left)
|
||||||
&& Objects.equals(right, binaryExpression.right)
|
&& Objects.equals(right, binaryExpression.right)
|
||||||
|
&& Objects.equals(left.getTypeCheckResult(), binaryExpression.left.getTypeCheckResult())
|
||||||
);
|
);
|
||||||
|
System.out.println("In BinaryExpression: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@@ -9,6 +8,7 @@ import org.objectweb.asm.Opcodes;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BooleanConstantExpression extends AbstractType implements IExpression{
|
public class BooleanConstantExpression extends AbstractType implements IExpression{
|
||||||
public boolean value;
|
public boolean value;
|
||||||
@@ -26,7 +26,7 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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){
|
if (value){
|
||||||
mv.visitInsn(Opcodes.ICONST_1);
|
mv.visitInsn(Opcodes.ICONST_1);
|
||||||
} else {
|
} else {
|
||||||
@@ -37,4 +37,15 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi
|
|||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.objectweb.asm.Opcodes;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class CharConstantExpression extends AbstractType implements IExpression{
|
public class CharConstantExpression extends AbstractType implements IExpression{
|
||||||
public char value;
|
public char value;
|
||||||
@@ -25,12 +26,29 @@ public class CharConstantExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 {
|
||||||
mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
|
if (value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,8 @@ import java.util.HashMap;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
public interface IExpression extends Node {
|
public interface IExpression extends Node {
|
||||||
// typeCheck method
|
|
||||||
//TypeCheckResult typeCheck() throws Exception;
|
|
||||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
|
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;
|
||||||
// visit method for code generation
|
|
||||||
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
|
||||||
|
|
||||||
TypeCheckResult getTypeCheckResult();
|
TypeCheckResult getTypeCheckResult();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||||
import gen.DecafParser;
|
|
||||||
import jdk.jshell.spi.ExecutionControl;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@@ -16,14 +14,14 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class InstVarExpression extends AbstractType implements IExpression{
|
public class InstVarExpression extends AbstractType implements IExpression {
|
||||||
|
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
public List<SubReceiver> receivers;
|
public List<SubReceiver> receivers;
|
||||||
public List<ReceivingMethod> receivingMethods;
|
public List<ReceivingMethod> receivingMethods;
|
||||||
public String fieldName;
|
public String fieldName;
|
||||||
|
|
||||||
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName){
|
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName) {
|
||||||
this.receivers = receivers;
|
this.receivers = receivers;
|
||||||
this.receivingMethods = receivingMethods;
|
this.receivingMethods = receivingMethods;
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
@@ -31,24 +29,155 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||||
String varType = typeContext.get(thisClass).get(fieldName);
|
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);
|
||||||
|
|
||||||
|
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) {
|
if (varType == null) {
|
||||||
throw new TypeCheckException("Field " + fieldName + " was not found in class " + thisClass + ".");
|
throw new TypeCheckException("Field " + fieldName + " was not found in class " + thisClass + ".");
|
||||||
}
|
}
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
result.type = varType;
|
result.type = varType;
|
||||||
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
// typeContext: (ClassName, (FieldName, FieldType))
|
// 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
|
// Load "this" onto the stack
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
String typeOfReciever = "";
|
||||||
|
String descriptor = "";
|
||||||
|
String classOfField = "";
|
||||||
|
|
||||||
//Get the field information
|
// Determine if the reference is this or not
|
||||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
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();
|
StringBuilder descriptor = new StringBuilder();
|
||||||
|
|
||||||
|
|
||||||
@@ -63,16 +192,13 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
descriptor.append("C");
|
descriptor.append("C");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
String fullReturnType = typeContext.get(thisClass).get(fieldName);
|
String fullReturnType = fieldType;
|
||||||
|
|
||||||
// If it is a class reference replace the "." with "/" and return it
|
// If it is a class reference replace the "." with "/" and return it
|
||||||
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return descriptor.toString();
|
||||||
// Load the variable onto the stack
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -80,13 +206,18 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
InstVarExpression instVarExpression = (InstVarExpression) o;
|
InstVarExpression instVarExpression = (InstVarExpression) o;
|
||||||
return (Objects.equals(thisClass, instVarExpression.thisClass)
|
boolean result = (Objects.equals(receivers, instVarExpression.receivers)
|
||||||
&& Objects.equals(fieldName, instVarExpression.fieldName)
|
&& Objects.equals(fieldName, instVarExpression.fieldName)
|
||||||
|
&& Objects.equals(receivingMethods, instVarExpression.receivingMethods)
|
||||||
|
&& Objects.equals(thisClass, instVarExpression.thisClass)
|
||||||
);
|
);
|
||||||
|
System.out.println("In InstVarExpression: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.getTypeCheckResult();
|
return super.getTypeCheckResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,9 +27,16 @@ public class IntConstantExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 {
|
||||||
//TODO: When we are finished this can be done more efficiently
|
if (value >= -1 && value <= 5) {
|
||||||
mv.visitLdcInsn(value);
|
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
|
@Override
|
||||||
@@ -37,8 +44,11 @@ public class IntConstantExpression extends AbstractType implements IExpression{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
IntConstantExpression intConstantExpression = (IntConstantExpression) o;
|
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
|
@Override
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
@@ -11,12 +11,12 @@ import java.util.LinkedHashMap;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||||
|
|
||||||
String identifier;
|
String identifier;
|
||||||
|
public String thisClass;
|
||||||
public LocalVarIdentifier(String identifier){
|
public LocalVarIdentifier(String identifier){
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
}
|
}
|
||||||
@@ -31,6 +31,12 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
if (localVars.containsKey(identifier)) {
|
if (localVars.containsKey(identifier)) {
|
||||||
result.type = localVars.get(identifier);
|
result.type = localVars.get(identifier);
|
||||||
} else {
|
} else {
|
||||||
|
// 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.");
|
throw new TypeCheckException("Local var " + identifier + " does not exist.");
|
||||||
}
|
}
|
||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
@@ -38,42 +44,42 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 {
|
||||||
// Check if the variable is in the list of local variables
|
String type = null;
|
||||||
String type = localVars.get(identifier);
|
|
||||||
if (type == null){
|
|
||||||
throw new Exception("Variable " + identifier + " not declared");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the index of the variable
|
// if it's a local variable
|
||||||
int index = -1;
|
if (localVars.containsKey(identifier)) {
|
||||||
int counter = 0;
|
type = localVars.get(identifier);
|
||||||
for (String key : localVars.keySet()){
|
// Find the index of the variable
|
||||||
if (key.equals(identifier)){
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
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");
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
}
|
|
||||||
|
|
||||||
// Load the variable onto the stack
|
|
||||||
switch (type){
|
|
||||||
case "int":
|
|
||||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
|
||||||
break;
|
|
||||||
case "boolean":
|
|
||||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
|
||||||
break;
|
|
||||||
case "void":
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,7 +92,10 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
LocalVarIdentifier localVarIdentifier = (LocalVarIdentifier) o;
|
LocalVarIdentifier localVarIdentifier = (LocalVarIdentifier) o;
|
||||||
return (Objects.equals(identifier, localVarIdentifier.identifier)
|
boolean result = (Objects.equals(identifier, localVarIdentifier.identifier)
|
||||||
);
|
);
|
||||||
|
System.out.println("In localVarIdentifier: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package abstractSyntaxTree.Expression;
|
|||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SubReceiver implements Node {
|
public class SubReceiver implements Node {
|
||||||
boolean thisExpression;
|
public boolean thisExpression;
|
||||||
public NewStatementExpression newStatementExpression;
|
public NewStatementExpression newStatementExpression;
|
||||||
public String identifier;
|
public String identifier;
|
||||||
|
|
||||||
@@ -19,4 +21,16 @@ public class SubReceiver implements Node {
|
|||||||
public SubReceiver(String identifier) {
|
public SubReceiver(String identifier) {
|
||||||
this.identifier = 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ package abstractSyntaxTree.Expression;
|
|||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Datatype.IDatatype;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -15,8 +13,8 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public class UnaryExpression extends AbstractType implements IExpression{
|
public class UnaryExpression extends AbstractType implements IExpression{
|
||||||
public String operator;
|
public String operator;
|
||||||
public IDatatype operand;
|
public IExpression operand;
|
||||||
public UnaryExpression(String operator, IDatatype operand){
|
public UnaryExpression(String operator, IExpression operand){
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
this.operand = operand;
|
this.operand = operand;
|
||||||
}
|
}
|
||||||
@@ -24,7 +22,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
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 result = new TypeCheckResult();
|
||||||
|
|
||||||
TypeCheckResult operandTypeCheckResult = operand.typeCheck();
|
TypeCheckResult operandTypeCheckResult = operand.typeCheck(methodContext, typeContext, localVars);
|
||||||
String operandType = operandTypeCheckResult.type;
|
String operandType = operandTypeCheckResult.type;
|
||||||
|
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
@@ -51,9 +49,9 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
switch (operator) {
|
||||||
case "!":
|
case "!":
|
||||||
@@ -77,9 +75,12 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
UnaryExpression unaryExpression = (UnaryExpression) o;
|
UnaryExpression unaryExpression = (UnaryExpression) o;
|
||||||
return (Objects.equals(operator, unaryExpression.operator)
|
boolean result = (Objects.equals(operator, unaryExpression.operator)
|
||||||
&& Objects.equals(operand, unaryExpression.operand)
|
&& Objects.equals(operand, unaryExpression.operand)
|
||||||
);
|
);
|
||||||
|
System.out.println("In UnaryExpression: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,8 +19,11 @@ public class Parameter implements Node {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Parameter parameter = (Parameter) o;
|
Parameter parameter = (Parameter) o;
|
||||||
return (Objects.equals(type, parameter.type)
|
boolean result = (Objects.equals(type, parameter.type)
|
||||||
&& Objects.equals(identifier, parameter.identifier)
|
&& 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 (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
ParameterList parameterListObj = (ParameterList) o;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import abstractSyntaxTree.Parameter.ParameterList;
|
|||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -27,8 +29,7 @@ public class Program implements Node {
|
|||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypeCheckResult typeCheckWithoutMain() throws TypeCheckException {
|
||||||
public TypeCheckResult typeCheck() throws TypeCheckException {
|
|
||||||
this.typeContext = new HashMap<>();
|
this.typeContext = new HashMap<>();
|
||||||
this.methodContext = new HashMap<>();
|
this.methodContext = new HashMap<>();
|
||||||
|
|
||||||
@@ -53,13 +54,55 @@ public class Program implements Node {
|
|||||||
methodContext.put(oneClass.name, identifierAndMethod);
|
methodContext.put(oneClass.name, identifierAndMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mainCounter = 0;
|
int mainCounter = 0;
|
||||||
// check if main exists
|
// check if main exists
|
||||||
for(RefType oneClass : classes){
|
for(RefType oneClass : classes){
|
||||||
if(oneClass.hasMain)
|
if(oneClass.hasMain)
|
||||||
mainCounter++;
|
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 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)
|
if(mainCounter != 1)
|
||||||
throw new TypeCheckException("There is not 1 Main method.");
|
throw new TypeCheckException("There is not 1 Main method.");
|
||||||
|
|
||||||
@@ -72,47 +115,58 @@ public class Program implements Node {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen() throws Exception{
|
public void codeGen() throws Exception {
|
||||||
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream("output.jar"))) {
|
// Store the names of the generated class files
|
||||||
|
List<String> classFileNames = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
for (RefType oneClass : classes) {
|
for (RefType oneClass : classes) {
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null);
|
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();
|
cw.visitEnd();
|
||||||
byte[] bytecode = cw.toByteArray();
|
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);
|
fos.write(bytecode);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
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
|
for (String classFileName : classFileNames) {
|
||||||
JarEntry entry = new JarEntry(oneClass.name + ".class");
|
addFileToJar(jos, classFileName);
|
||||||
jos.putNextEntry(entry);
|
}
|
||||||
jos.write(bytecode);
|
} catch (IOException e) {
|
||||||
jos.closeEntry();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throw new RuntimeException(e);
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
/*
|
|
||||||
for(RefType oneClass : classes){
|
private void addFileToJar(JarOutputStream jos, String fileName) throws IOException {
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
File file = new File(fileName);
|
||||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC,oneClass.name, null,
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
"java/lang/Object", null);
|
JarEntry entry = new JarEntry(fileName);
|
||||||
oneClass.codeGen(cw);
|
jos.putNextEntry(entry);
|
||||||
|
|
||||||
cw.visitEnd();
|
byte[] buffer = new byte[1024];
|
||||||
byte[] bytecode = cw.toByteArray();
|
int bytesRead;
|
||||||
|
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||||
|
jos.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
jos.closeEntry();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -120,8 +174,7 @@ public class Program implements Node {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Program program = (Program) o;
|
Program program = (Program) o;
|
||||||
System.out.println(classes);
|
System.out.println("In program: " + Objects.equals(classes, program.classes));
|
||||||
System.out.println(program.classes);
|
|
||||||
return (Objects.equals(classes, program.classes));
|
return (Objects.equals(classes, program.classes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,10 @@ package abstractSyntaxTree.Statement;
|
|||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Class.FieldDecl;
|
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -16,13 +15,10 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BlockStatement extends AbstractType implements IStatement {
|
public class BlockStatement extends AbstractType implements IStatement {
|
||||||
|
|
||||||
//We will need a parameter which holds the symbol table
|
|
||||||
HashMap<String, String> localVars;
|
HashMap<String, String> localVars;
|
||||||
public String returnType; // "not" --> not void
|
public String returnType;
|
||||||
public List<IStatement> statements;
|
public List<IStatement> statements;
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
// do we need expression, statementexpression
|
|
||||||
|
|
||||||
public BlockStatement(List<IStatement> statements, String returnType) {
|
public BlockStatement(List<IStatement> statements, String returnType) {
|
||||||
this.statements = statements;
|
this.statements = statements;
|
||||||
@@ -60,14 +56,26 @@ public class BlockStatement extends AbstractType implements IStatement {
|
|||||||
if(statement instanceof LocalVarDecl localVarDecl){
|
if(statement instanceof LocalVarDecl localVarDecl){
|
||||||
localVarDecl.thisClass = thisClass;
|
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);
|
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||||
|
typeOfCurrentStatement.type = "void";
|
||||||
|
}
|
||||||
if(statement instanceof LocalVarDecl localVarDecl){
|
if(statement instanceof LocalVarDecl localVarDecl){
|
||||||
localVars.put(localVarDecl.identifier, localVarDecl.type);
|
localVars.put(localVarDecl.identifier, localVarDecl.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeOfCurrentStatement.type.contains(",")) {
|
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[] substrings = typeOfCurrentStatement.type.split(",");
|
||||||
|
|
||||||
String firstType = substrings[0];
|
String firstType = substrings[0];
|
||||||
@@ -93,29 +101,31 @@ public class BlockStatement extends AbstractType implements IStatement {
|
|||||||
|
|
||||||
if(typeOfCurrentStatement.type.equals("void"))
|
if(typeOfCurrentStatement.type.equals("void"))
|
||||||
continue;
|
continue;
|
||||||
// set return of block if not known yet
|
|
||||||
|
|
||||||
|
// set return of block if not known yet
|
||||||
if(this.returnType == null|| this.returnType == "not")
|
if(this.returnType == null|| this.returnType == "not")
|
||||||
this.returnType = typeOfCurrentStatement.type;
|
this.returnType = typeOfCurrentStatement.type;
|
||||||
|
|
||||||
if (!typeOfCurrentStatement.type.equals(this.returnType))
|
if (!typeOfCurrentStatement.type.equals(this.returnType))
|
||||||
throw new TypeCheckException("At least some statements of the block returns the wrong type or missing return statement.");
|
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;
|
result.type = this.returnType;
|
||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
// Create a new HashMap for the local variables of the block
|
||||||
// It has every variable of the parent block
|
// It has every variable of the parent block
|
||||||
// This Map is discarded at the end of the 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);
|
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||||
|
|
||||||
for (IStatement statement : statements) {
|
for (IStatement statement : statements) {
|
||||||
statement.codeGen(mv, blockLocalVars, typeContext);
|
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,10 +134,13 @@ public class BlockStatement extends AbstractType implements IStatement {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
BlockStatement blockStatement = (BlockStatement) o;
|
BlockStatement blockStatement = (BlockStatement) o;
|
||||||
return (Objects.equals(localVars, blockStatement.localVars)
|
boolean result = Objects.equals(returnType, blockStatement.returnType)
|
||||||
&& Objects.equals(returnType, blockStatement.returnType)
|
&& Objects.equals(statements, blockStatement.statements
|
||||||
&& Objects.equals(statements, blockStatement.statements)
|
/*&& (Objects.equals(localVars, blockStatement.localVars)*/
|
||||||
);
|
);
|
||||||
|
System.out.println("In BlockStatement: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import org.objectweb.asm.MethodVisitor;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class EmptyStatement extends AbstractType implements IStatement{
|
public class EmptyStatement extends AbstractType implements IStatement{
|
||||||
|
|
||||||
@@ -20,17 +19,20 @@ public class EmptyStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
//An empty statement does not generate any code
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.getTypeCheckResult();
|
return super.getTypeCheckResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ 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 TypeCheckException;
|
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();
|
TypeCheckResult getTypeCheckResult();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class IfElseStatement extends AbstractType implements IStatement{
|
public class IfElseStatement extends AbstractType implements IStatement{
|
||||||
@@ -54,23 +53,23 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@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);
|
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
Label statementEnd = 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)
|
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
|
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 if-else statement
|
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the else statement
|
||||||
|
|
||||||
mv.visitLabel(conditionFalse);
|
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
|
mv.visitLabel(statementEnd); //End of the if-else statement
|
||||||
|
|
||||||
@@ -81,10 +80,13 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
IfElseStatement ifElseStatement = (IfElseStatement) o;
|
IfElseStatement ifElseStatement = (IfElseStatement) o;
|
||||||
return (Objects.equals(condition, ifElseStatement.condition)
|
boolean result = (Objects.equals(condition, ifElseStatement.condition)
|
||||||
&& Objects.equals(ifStatement, ifElseStatement.ifStatement)
|
&& Objects.equals(ifStatement, ifElseStatement.ifStatement)
|
||||||
&& Objects.equals(elseStatement, ifElseStatement.elseStatement)
|
&& Objects.equals(elseStatement, ifElseStatement.elseStatement)
|
||||||
);
|
);
|
||||||
|
System.out.println("In PrintStatement: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,13 +9,10 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class IfStatement extends AbstractType implements IStatement{
|
public class IfStatement extends AbstractType implements IStatement{
|
||||||
public IExpression condition;
|
public IExpression condition;
|
||||||
|
|
||||||
//Do we need a block statement here?
|
|
||||||
IStatement ifStatement;
|
IStatement ifStatement;
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
|
|
||||||
@@ -31,7 +28,7 @@ public class IfStatement extends AbstractType implements IStatement{
|
|||||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
if (!conditionType.type.equals("boolean")) {
|
if (!conditionType.type.equals("boolean")) {
|
||||||
throw new TypeCheckException("Condition of If-Statement should is " + conditionType.type + ", but should be boolean.");
|
throw new TypeCheckException("Condition of If-Statement is " + conditionType.type + ", but should be boolean.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ifStatement instanceof BlockStatement blockStatement){
|
if(ifStatement instanceof BlockStatement blockStatement){
|
||||||
@@ -43,16 +40,16 @@ public class IfStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
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)
|
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
|
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
||||||
}
|
}
|
||||||
@@ -62,9 +59,12 @@ public class IfStatement extends AbstractType implements IStatement{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
IfStatement ifStatementObj = (IfStatement) o;
|
IfStatement ifStatementObj = (IfStatement) o;
|
||||||
return (Objects.equals(condition, ifStatementObj.condition)
|
boolean result = (Objects.equals(condition, ifStatementObj.condition)
|
||||||
&& Objects.equals(ifStatement, ifStatementObj.ifStatement)
|
&& Objects.equals(ifStatement, ifStatementObj.ifStatement)
|
||||||
);
|
);
|
||||||
|
System.out.println("In IfStatement: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package abstractSyntaxTree.Statement;
|
package abstractSyntaxTree.Statement;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@@ -34,8 +37,14 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
if(expression instanceof MethodCallStatementExpression){
|
if(expression instanceof MethodCallStatementExpression){
|
||||||
MethodCallStatementExpression methodCall = (MethodCallStatementExpression) expression;
|
MethodCallStatementExpression methodCall = (MethodCallStatementExpression) expression;
|
||||||
methodCall.thisClass = this.thisClass;
|
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);
|
expression.typeCheck(methodContext, typeContext, localVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,27 +56,41 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
localVars.put(identifier, type);
|
||||||
|
|
||||||
|
|
||||||
int index = localVars.size()-1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||||
|
|
||||||
// Set a default value for the variable --> less problems
|
if (index == -1){
|
||||||
switch (type){
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
case "int":
|
}
|
||||||
mv.visitInsn(Opcodes.ICONST_0);
|
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
if (expression != null) {
|
||||||
break;
|
expression.codeGen(mv, localVars, typeContext,methodContext);
|
||||||
case "boolean":
|
|
||||||
mv.visitInsn(Opcodes.ICONST_0);
|
// Store the result in the local variable
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
switch (type){
|
||||||
break;
|
case "int", "char", "boolean":
|
||||||
case "void":
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mv.visitInsn(Opcodes.ACONST_NULL);
|
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +99,12 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
LocalVarDecl localVarDecl = (LocalVarDecl) o;
|
LocalVarDecl localVarDecl = (LocalVarDecl) o;
|
||||||
return (Objects.equals(type, localVarDecl.type)
|
boolean result = (Objects.equals(type, localVarDecl.type)
|
||||||
&& Objects.equals(identifier, localVarDecl.identifier)
|
&& Objects.equals(identifier, localVarDecl.identifier)
|
||||||
);
|
);
|
||||||
|
System.out.println("In LocalVarDecl: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,16 +4,19 @@ import TypeCheck.TypeCheckException;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ReturnStatement extends AbstractType implements IStatement{
|
public class ReturnStatement extends AbstractType implements IStatement{
|
||||||
IExpression expression;
|
IExpression expression; // Needs typeCheckResult
|
||||||
|
public String thisClass;
|
||||||
|
|
||||||
public ReturnStatement(IExpression expression) {
|
public ReturnStatement(IExpression expression) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
@@ -26,6 +29,12 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
result.type = "void";
|
result.type = "void";
|
||||||
} else {
|
} 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);
|
TypeCheckResult typedExpression = expression.typeCheck(methodContext, typeContext, localVars);
|
||||||
result.type = typedExpression.type;
|
result.type = typedExpression.type;
|
||||||
}
|
}
|
||||||
@@ -34,16 +43,13 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
return result;
|
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
|
@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) {
|
if (expression != null) {
|
||||||
expression.codeGen(mv, localVars, typeContext);
|
expression.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
//Get the Type of the expression
|
//Get the Type of the expression
|
||||||
//TODO: Resolve how do we get the type of the expression
|
|
||||||
String type = expression.getTypeCheckResult().type;
|
String type = expression.getTypeCheckResult().type;
|
||||||
|
|
||||||
if (type.equals("int") || type.equals("boolean") || type.equals("char")) {
|
if (type.equals("int") || type.equals("boolean") || type.equals("char")) {
|
||||||
@@ -61,8 +67,12 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
ReturnStatement returnStatement = (ReturnStatement) o;
|
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
|
@Override
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class WhileStatement extends AbstractType implements IStatement {
|
public class WhileStatement extends AbstractType implements IStatement {
|
||||||
@@ -29,7 +28,7 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
// check condition
|
// check condition
|
||||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||||
if (!conditionType.type.equals("boolean")) {
|
if (!conditionType.type.equals("boolean")) {
|
||||||
throw new IllegalArgumentException("Expected boolean");
|
throw new TypeCheckException("Condition of while-statement is of type " + conditionType.type + " but should be boolean.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check code block
|
// check code block
|
||||||
@@ -42,7 +41,7 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||||
|
|
||||||
@@ -51,13 +50,11 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
|
|
||||||
mv.visitLabel(LoopStart);
|
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)
|
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
||||||
|
|
||||||
statement.codeGen(mv, blockLocalVars, typeContext);
|
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||||
//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
|
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
||||||
|
|
||||||
mv.visitLabel(conditionFalse);
|
mv.visitLabel(conditionFalse);
|
||||||
@@ -68,9 +65,13 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
WhileStatement whileStatement = (WhileStatement) o;
|
WhileStatement whileStatement = (WhileStatement) o;
|
||||||
return (Objects.equals(condition, whileStatement.condition)
|
boolean result = (Objects.equals(condition, whileStatement.condition)
|
||||||
&& Objects.equals(statement, whileStatement.statement)
|
&& Objects.equals(statement, whileStatement.statement)
|
||||||
);
|
);
|
||||||
|
System.out.println("In PrintStatement: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package abstractSyntaxTree.StatementExpression;
|
package abstractSyntaxTree.StatementExpression;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import abstractSyntaxTree.Statement.WhileStatement;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -36,17 +37,27 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
TypeCheckResult leftType;
|
TypeCheckResult leftType;
|
||||||
|
|
||||||
if (left instanceof LocalVarIdentifier localVarIdentifier) {
|
if (left instanceof LocalVarIdentifier localVarIdentifier) {
|
||||||
|
localVarIdentifier.thisClass = thisClass;
|
||||||
leftType = new TypeCheckResult();
|
leftType = new TypeCheckResult();
|
||||||
String identifier = localVarIdentifier.getIdentifier();
|
String identifier = localVarIdentifier.getIdentifier();
|
||||||
leftType.type = localVars.get(identifier);
|
leftType.type = localVars.get(identifier);
|
||||||
|
|
||||||
// local var may be actually instvar of this
|
// local var may be actually instVar of this
|
||||||
if(leftType.type == null){
|
if(leftType.type == null){
|
||||||
leftType.type = typeContext.get(thisClass).get(identifier);
|
leftType.type = typeContext.get(thisClass).get(identifier);
|
||||||
}
|
}
|
||||||
}else{
|
}else {
|
||||||
|
if(left instanceof InstVarExpression instVarExpression)
|
||||||
|
instVarExpression.thisClass = this.thisClass;
|
||||||
leftType = left.typeCheck(methodContext, typeContext, localVars);
|
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);
|
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||||
@@ -66,33 +77,35 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 {
|
||||||
//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);
|
|
||||||
|
|
||||||
if (left instanceof LocalVarIdentifier) {
|
if (left instanceof LocalVarIdentifier) {
|
||||||
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
||||||
String varName = localVar.getIdentifier();
|
String varName = localVar.getIdentifier();
|
||||||
|
|
||||||
//Get the index of the local variable
|
//Get the index of the local variable
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, varName);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(varName)) {
|
|
||||||
index = counter+1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
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());
|
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) {
|
switch (type) {
|
||||||
case "int", "char", "boolean":
|
case "int", "char", "boolean":
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
@@ -105,38 +118,129 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
} else if (left instanceof InstVarExpression) {
|
} else if (left instanceof InstVarExpression) {
|
||||||
instVar = (InstVarExpression) left;
|
instVar = (InstVarExpression) left;
|
||||||
|
|
||||||
// Load "this" onto the stack
|
boolean isLocal = false;
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
|
||||||
|
|
||||||
// Duplicate the top of the stack as we'll need it for both the PUTFIELD and subsequent expressions
|
// Load the reference onto the stack
|
||||||
mv.visitInsn(Opcodes.DUP_X1);
|
// 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
|
if (index == -1) {
|
||||||
String fieldType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
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 "boolean":
|
|
||||||
descriptor.append("Z");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
String fullReturnType = typeContext.get(instVar.thisClass).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
|
//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
|
||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor.toString());
|
|
||||||
|
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
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|||||||
@@ -3,13 +3,10 @@ package abstractSyntaxTree.StatementExpression;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.MethodDecl;
|
|
||||||
import abstractSyntaxTree.Class.RefType;
|
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import jdk.jshell.spi.ExecutionControl;
|
import jdk.jshell.spi.ExecutionControl;
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@@ -34,8 +31,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
|
|
||||||
String classToSearchMethodIn = thisClass;
|
String classToSearchMethodIn = thisClass;
|
||||||
|
|
||||||
//method is called on something that is not this ???
|
if (this.receiver != null) {
|
||||||
if(this.receiver != null) {
|
|
||||||
if (!receiver.thisExpression) {
|
if (!receiver.thisExpression) {
|
||||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||||
if (classToSearchMethodIn == null)
|
if (classToSearchMethodIn == null)
|
||||||
@@ -45,34 +41,32 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
|
|
||||||
String currentType = "";
|
String currentType = "";
|
||||||
|
|
||||||
// receiver is instvar
|
// receiver is instVar
|
||||||
if(receiver != null) {
|
if (receiver != null) {
|
||||||
if (receiver.instVarExpression != null) {
|
if (receiver.instVarExpression != null) {
|
||||||
String Subreceiver = receiver.instVarExpression.receivers.get(0).identifier; // e
|
receiver.instVarExpression.thisClass = this.thisClass;
|
||||||
String mostLeftField = receiver.instVarExpression.fieldName; // example1
|
String typeOfSubreceiver = receiver.instVarExpression.typeCheck(methodContext, typeContext, localVars).type;
|
||||||
|
|
||||||
String typeOfSubreceiver = typeContext.get(thisClass).get(Subreceiver);
|
currentType = typeOfSubreceiver;
|
||||||
|
} else {
|
||||||
receiver.instVarExpression.thisClass = typeOfSubreceiver;
|
currentType = classToSearchMethodIn;
|
||||||
receiver.instVarExpression.typeCheck(methodContext, typeContext, localVars);
|
|
||||||
currentType = typeContext.get(typeOfSubreceiver).get(mostLeftField);
|
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
currentType = thisClass;
|
currentType = thisClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if classToSearchMethodIn does not conatin method, throw exception. go through list and check each
|
for (int i = 0; i < receivingMethods.size(); i++) {
|
||||||
|
|
||||||
for(int i = 0; i < receivingMethods.size(); i++){
|
|
||||||
currentType = (String) methodContext.get(currentType).get(receivingMethods.get(i).methodName).keySet().toArray()[0];
|
currentType = (String) methodContext.get(currentType).get(receivingMethods.get(i).methodName).keySet().toArray()[0];
|
||||||
if(currentType == null)
|
if (currentType == null)
|
||||||
throw new TypeCheckException("The method " + methodName + " was not found in "+ classToSearchMethodIn + ".");
|
throw new TypeCheckException("The method " + methodName + " was not found in " + classToSearchMethodIn + ".");
|
||||||
|
receivingMethods.get(i).thisClass = this.thisClass;
|
||||||
receivingMethods.get(i).checkParameters(methodContext, typeContext, localVars);
|
receivingMethods.get(i).checkParameters(methodContext, typeContext, localVars);
|
||||||
System.out.println(currentType);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
currentType = (String) methodContext.get(currentType).get(methodName).keySet().toArray()[0];
|
currentType = (String) methodContext.get(currentType).get(methodName).keySet().toArray()[0];
|
||||||
|
|
||||||
|
for (IExpression argument : arguments) {
|
||||||
|
argument.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
}
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
result.type = currentType;
|
result.type = currentType;
|
||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
@@ -80,63 +74,239 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Errors occur due to the change in parameter in the RefType class
|
//Errors occur due to the change in parameter in the RefType class
|
||||||
// I need the methodContext here to get the method descriptor
|
|
||||||
@Override
|
@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 {
|
||||||
//Generate Bytecode for the receiver
|
String owner;
|
||||||
if (receiver.thisExpression) {
|
|
||||||
// If the receiver is "this" then load "this" onto the stack
|
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
|
||||||
} else if (receiver.instVarExpression != null) {
|
|
||||||
receiver.instVarExpression.codeGen(mv, localVars, typeContext);
|
|
||||||
|
|
||||||
} else if (receiver.newStatementExpression != null) {
|
// Load the object onto the stack
|
||||||
receiver.newStatementExpression.codeGen(mv, localVars, typeContext);
|
if (receiver != null) {
|
||||||
|
if (receiver.thisExpression) {
|
||||||
// Not sure about this part
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
} else if (receiver.identifier != null) {
|
owner = thisClass;
|
||||||
// Load local variable onto the stack
|
} else if (receiver.instVarExpression != null) {
|
||||||
for (String key : localVars.keySet()) {
|
receiver.instVarExpression.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
if (key.equals(receiver.identifier)) {
|
owner = receiver.instVarExpression.getTypeCheckResult().type;
|
||||||
String type = localVars.get(key);
|
} 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;
|
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
|
||||||
mv.visitVarInsn(opcode, Integer.parseInt(key));
|
mv.visitVarInsn(opcode, index); // Load local variable onto the stack
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
owner = type;
|
||||||
|
} else {
|
||||||
|
throw new ExecutionControl.NotImplementedException("Receiver type not supported.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
owner = thisClass;
|
||||||
|
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(")");
|
||||||
|
|
||||||
// Generate Bytecode for the arguments
|
String classToSearchMethodIn;
|
||||||
for (IExpression argument : arguments) {
|
//Return Type
|
||||||
argument.codeGen(mv, localVars, typeContext);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
classToSearchMethodIn = thisClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String descriptor;
|
String returnType = methodContext.get(classToSearchMethodIn).get(methodName).keySet().toArray()[0].toString();
|
||||||
// List<MethodDecl> methodDecls = thisClass.methodDecls;
|
|
||||||
// for (MethodDecl methodDecl : methodDecls) {
|
switch (returnType) {
|
||||||
// if (methodDecl.name.equals(methodName)) {
|
case "int":
|
||||||
// //Get the method descriptor
|
descriptor.append("I");
|
||||||
// //descriptor = methodDecl.getMethodDescriptor(methodContext); //methodContext is missing
|
break;
|
||||||
// }
|
case "boolean":
|
||||||
// }
|
descriptor.append("Z");
|
||||||
// Invoke the method
|
break;
|
||||||
// String className = classThatHasTheMethodIfNotThis != null ? classThatHasTheMethodIfNotThis.name : thisClass.name;
|
case "char":
|
||||||
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, methodName, descriptor, false);
|
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
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
MethodCallStatementExpression methodCallStatementExpression = (MethodCallStatementExpression) o;
|
MethodCallStatementExpression methodCallStatementExpression = (MethodCallStatementExpression) o;
|
||||||
return (Objects.equals(methodName, methodCallStatementExpression.methodName)
|
boolean typeCheckResults = testTypeChecks(this, methodCallStatementExpression);
|
||||||
&& Objects.equals(arguments, methodCallStatementExpression.arguments)
|
|
||||||
);
|
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
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.getTypeCheckResult();
|
return super.getTypeCheckResult();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -5,19 +5,17 @@ import TypeCheck.TypeCheckException;
|
|||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
|
|
||||||
|
public String thisClass;
|
||||||
private String className;
|
private String className;
|
||||||
private List<IExpression> arguments;
|
private List<IExpression> arguments;
|
||||||
|
|
||||||
@@ -26,12 +24,38 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
NewStatementExpression newStatementExpression = (NewStatementExpression) o;
|
||||||
|
boolean resultTypeCheckArguments = true;
|
||||||
|
for (int i = 0; i < newStatementExpression.arguments.size(); i++){
|
||||||
|
resultTypeCheckArguments = resultTypeCheckArguments && Objects.equals(this.arguments.get(i).getTypeCheckResult(), newStatementExpression.arguments.get(i).getTypeCheckResult());
|
||||||
|
}
|
||||||
|
boolean result = (Objects.equals(className, newStatementExpression.className)
|
||||||
|
&& Objects.equals(arguments, newStatementExpression.arguments)
|
||||||
|
);
|
||||||
|
System.out.println("In newStatementExpression: " + result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
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()))){
|
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
|
||||||
throw new TypeCheckException("An instance of " + className + " is created, but the type does not exist.");
|
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();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
result.type = className;
|
result.type = className;
|
||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
@@ -39,7 +63,7 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 new instance of the class
|
//Create new instance of the class
|
||||||
mv.visitTypeInsn(Opcodes.NEW, className);
|
mv.visitTypeInsn(Opcodes.NEW, className);
|
||||||
|
|
||||||
@@ -47,7 +71,7 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
mv.visitInsn(Opcodes.DUP);
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
|
||||||
for (IExpression argument : arguments) {
|
for (IExpression argument : arguments) {
|
||||||
argument.codeGen(mv, localVars, typeContext);
|
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
}
|
}
|
||||||
String descriptor = getConstructorDescriptor();
|
String descriptor = getConstructorDescriptor();
|
||||||
|
|
||||||
@@ -59,7 +83,8 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getConstructorDescriptor() {
|
private String getConstructorDescriptor() {
|
||||||
StringBuilder descriptor = new StringBuilder();
|
StringBuilder descriptor = new StringBuilder("(");
|
||||||
|
|
||||||
|
|
||||||
for (IExpression parameter : arguments) {
|
for (IExpression parameter : arguments) {
|
||||||
TypeCheckResult result = parameter.getTypeCheckResult();
|
TypeCheckResult result = parameter.getTypeCheckResult();
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
package abstractSyntaxTree.StatementExpression;
|
package abstractSyntaxTree.StatementExpression;
|
||||||
|
|
||||||
import TypeCheck.TypeCheckException;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.Objects;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
public class Receiver implements Node {
|
public class Receiver implements Node {
|
||||||
boolean thisExpression;
|
boolean thisExpression;
|
||||||
@@ -18,6 +12,22 @@ public class Receiver implements Node {
|
|||||||
NewStatementExpression newStatementExpression;
|
NewStatementExpression newStatementExpression;
|
||||||
String identifier;
|
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) {
|
public Receiver(boolean thisExpression) {
|
||||||
this.thisExpression = thisExpression;
|
this.thisExpression = thisExpression;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,31 @@ package abstractSyntaxTree.StatementExpression;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ReceivingMethod implements Node {
|
public class ReceivingMethod implements Node {
|
||||||
public String methodName;
|
public String methodName;
|
||||||
public List<IExpression> arguments;
|
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) {
|
public ReceivingMethod(String methodName, List<IExpression> arguments) {
|
||||||
this.methodName = methodName;
|
this.methodName = methodName;
|
||||||
@@ -18,6 +34,9 @@ public class ReceivingMethod implements Node {
|
|||||||
}
|
}
|
||||||
void checkParameters(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
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){
|
for (IExpression parameter : arguments){
|
||||||
|
if(parameter instanceof LocalVarIdentifier localVarIdentifier){
|
||||||
|
localVarIdentifier.thisClass = thisClass;
|
||||||
|
}
|
||||||
parameter.typeCheck(methodContext, typeContext, localVars);
|
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,40 +32,46 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
List<FieldDecl> fieldDecls = new ArrayList<>();
|
List<FieldDecl> fieldDecls = new ArrayList<>();
|
||||||
List<MethodDecl> methodDecls = new ArrayList<>();
|
List<MethodDecl> methodDecls = new ArrayList<>();
|
||||||
boolean hasMain;
|
boolean hasMain;
|
||||||
if(ctx.MainMethodDecl() != null) {
|
if (ctx.MainMethodDecl() != null) {
|
||||||
hasMain = true;
|
hasMain = true;
|
||||||
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()), new BlockStatement(new ArrayList<>(), null));
|
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()), (BlockStatement) visitBlock(ctx.block()));
|
||||||
|
methodDecls.add(mainMethod);
|
||||||
} else {
|
} else {
|
||||||
hasMain = false;
|
hasMain = false;
|
||||||
}
|
}
|
||||||
for (DecafParser.LocalVarDeclContext fieldDecl: ctx.localVarDecl()) {
|
for (DecafParser.LocalVarDeclContext fieldDecl : ctx.localVarDecl()) {
|
||||||
fieldDecls.add((FieldDecl) generateFieldDecl(fieldDecl));
|
fieldDecls.add((FieldDecl) generateFieldDecl(fieldDecl));
|
||||||
}
|
}
|
||||||
for (DecafParser.ConstuctorDeclContext constDecl: ctx.constuctorDecl()) {
|
for (DecafParser.ConstuctorDeclContext constDecl : ctx.constuctorDecl()) {
|
||||||
MethodDecl constructor = ((MethodDecl) visit(constDecl));
|
MethodDecl constructor = ((MethodDecl) visit(constDecl));
|
||||||
constructor.classThatContainsMethod = name;
|
constructor.classThatContainsMethod = name;
|
||||||
methodDecls.add(constructor);
|
methodDecls.add(constructor);
|
||||||
}
|
}
|
||||||
for (DecafParser.MethodDeclContext methodDecl: ctx.methodDecl()) {
|
for (DecafParser.MethodDeclContext methodDecl : ctx.methodDecl()) {
|
||||||
MethodDecl method = (MethodDecl) visit(methodDecl);
|
MethodDecl method = (MethodDecl) visit(methodDecl);
|
||||||
method.classThatContainsMethod = name;
|
method.classThatContainsMethod = name;
|
||||||
methodDecls.add(method);
|
methodDecls.add(method);
|
||||||
}
|
}
|
||||||
return new RefType(name,fieldDecls, methodDecls, hasMain);
|
return new RefType(name, fieldDecls, methodDecls, hasMain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node generateFieldDecl(DecafParser.LocalVarDeclContext ctx) {
|
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
|
@Override
|
||||||
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||||
if (ctx.expression() != null) {
|
if (ctx.expression() != null) {
|
||||||
IExpression expression = (IExpression) visit(ctx.expression());
|
IExpression expression = (IExpression) visit(ctx.expression());
|
||||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||||
} else {
|
} else {
|
||||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,7 +99,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
} else {
|
} else {
|
||||||
type = ctx.type().getText();
|
type = ctx.type().getText();
|
||||||
}
|
}
|
||||||
return new MethodDecl("", type , name, parameterList, block);
|
return new MethodDecl("", type, name, parameterList, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -104,7 +110,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
@Override
|
@Override
|
||||||
public Node visitParameterList(DecafParser.ParameterListContext ctx) {
|
public Node visitParameterList(DecafParser.ParameterListContext ctx) {
|
||||||
List<Parameter> parameters = new ArrayList<>();
|
List<Parameter> parameters = new ArrayList<>();
|
||||||
for (DecafParser.ParameterContext parameter: ctx.parameter()) {
|
for (DecafParser.ParameterContext parameter : ctx.parameter()) {
|
||||||
parameters.add((Parameter) visit(parameter));
|
parameters.add((Parameter) visit(parameter));
|
||||||
}
|
}
|
||||||
return new ParameterList(parameters);
|
return new ParameterList(parameters);
|
||||||
@@ -126,20 +132,26 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
return visitEmptyStatement(ctx.emptyStatement());
|
return visitEmptyStatement(ctx.emptyStatement());
|
||||||
} else if (ctx.localVarDecl() != null) {
|
} else if (ctx.localVarDecl() != null) {
|
||||||
return visitLocalVarDecl(ctx.localVarDecl());
|
return visitLocalVarDecl(ctx.localVarDecl());
|
||||||
|
} else if (ctx.print() != null) {
|
||||||
|
return visitPrint(ctx.print());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitReturnStmt(DecafParser.ReturnStmtContext ctx) {
|
public Node visitReturnStmt(DecafParser.ReturnStmtContext ctx) {
|
||||||
Node expression = visitExpression(ctx.expression());
|
if (ctx.expression() != null) {
|
||||||
return new ReturnStatement((IExpression) expression);
|
Node expression = visitExpression(ctx.expression());
|
||||||
|
return new ReturnStatement((IExpression) expression);
|
||||||
|
} else {
|
||||||
|
return new ReturnStatement(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitBlock(DecafParser.BlockContext ctx) {
|
public Node visitBlock(DecafParser.BlockContext ctx) {
|
||||||
List<IStatement> stmts = new ArrayList<>();
|
List<IStatement> stmts = new ArrayList<>();
|
||||||
for (DecafParser.StatementContext stmt: ctx.statement()) {
|
for (DecafParser.StatementContext stmt : ctx.statement()) {
|
||||||
Node statement = visitStatement(stmt);
|
Node statement = visitStatement(stmt);
|
||||||
stmts.add((IStatement) statement);
|
stmts.add((IStatement) statement);
|
||||||
}
|
}
|
||||||
@@ -187,23 +199,27 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
} else if (ctx.newDecl() != null) {
|
} else if (ctx.newDecl() != null) {
|
||||||
return visitNewDecl(ctx.newDecl());
|
return visitNewDecl(ctx.newDecl());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visitPrint(DecafParser.PrintContext ctx) {
|
||||||
|
return new PrintStatement(ctx.Identifier().getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitAssign(DecafParser.AssignContext ctx) {
|
public Node visitAssign(DecafParser.AssignContext ctx) {
|
||||||
Node right = visitExpression(ctx.expression());
|
Node right = visitExpression(ctx.expression());
|
||||||
Node left = visitAssignableExpr(ctx.assignableExpr());
|
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
|
@Override
|
||||||
public Node visitMethodCall(DecafParser.MethodCallContext ctx) {
|
public Node visitMethodCall(DecafParser.MethodCallContext ctx) {
|
||||||
String methodName = ctx.Identifier().getText();
|
String methodName = ctx.Identifier().getText();
|
||||||
List<IExpression> arguments = generateExpressions(ctx.argumentList());
|
List<IExpression> arguments = generateExpressions(ctx.argumentList());
|
||||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||||
for(DecafParser.ReceivingMethodContext receivingMethod: ctx.receivingMethod()) {
|
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||||
}
|
}
|
||||||
if (ctx.receiver() != null) {
|
if (ctx.receiver() != null) {
|
||||||
@@ -271,7 +287,8 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
} else if (ctx.value() != null) {
|
} else if (ctx.value() != null) {
|
||||||
return visitValue(ctx.value());
|
return visitValue(ctx.value());
|
||||||
} else if (ctx.binaryExpr() != null) {
|
} else if (ctx.binaryExpr() != null) {
|
||||||
//todo
|
IExpression expression = (IExpression) visit(ctx.binaryExpr());
|
||||||
|
return new UnaryExpression("!", expression);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -303,14 +320,14 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
if (ctx.IntValue() != null) {
|
if (ctx.IntValue() != null) {
|
||||||
int value = Integer.parseInt(ctx.IntValue().getText());
|
int value = Integer.parseInt(ctx.IntValue().getText());
|
||||||
return new IntConstantExpression(value);
|
return new IntConstantExpression(value);
|
||||||
} else if(ctx.Identifier() != null) {
|
} else if (ctx.Identifier() != null) {
|
||||||
String identifier = ctx.Identifier().getText();
|
String identifier = ctx.Identifier().getText();
|
||||||
return new LocalVarIdentifier(identifier);
|
return new LocalVarIdentifier(identifier);
|
||||||
} else if(ctx.instVar() != null) {
|
} else if (ctx.instVar() != null) {
|
||||||
return visitInstVar(ctx.instVar());
|
return visitInstVar(ctx.instVar());
|
||||||
} else if(ctx.methodCall() != null) {
|
} else if (ctx.methodCall() != null) {
|
||||||
return visitMethodCall(ctx.methodCall());
|
return visitMethodCall(ctx.methodCall());
|
||||||
} else if(ctx.calcExpr() != null) {
|
} else if (ctx.calcExpr() != null) {
|
||||||
return visitCalcExpr(ctx.calcExpr());
|
return visitCalcExpr(ctx.calcExpr());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -319,7 +336,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
@Override
|
@Override
|
||||||
public Node visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) {
|
public Node visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) {
|
||||||
String operator;
|
String operator;
|
||||||
if(ctx.nonCalcOperator().LogicalOpertor() != null) {
|
if (ctx.nonCalcOperator().LogicalOpertor() != null) {
|
||||||
operator = ctx.nonCalcOperator().LogicalOpertor().getText();
|
operator = ctx.nonCalcOperator().LogicalOpertor().getText();
|
||||||
} else {
|
} else {
|
||||||
operator = ctx.nonCalcOperator().ComparisonOperator().getText();
|
operator = ctx.nonCalcOperator().ComparisonOperator().getText();
|
||||||
@@ -356,10 +373,10 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
List<SubReceiver> receivers = new ArrayList<>();
|
List<SubReceiver> receivers = new ArrayList<>();
|
||||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||||
String fieldName = ctx.Identifier().getText();
|
String fieldName = ctx.Identifier().getText();
|
||||||
for(DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
for (DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
||||||
receivers.add((SubReceiver) visit(subReceiver));
|
receivers.add((SubReceiver) visit(subReceiver));
|
||||||
}
|
}
|
||||||
for(DecafParser.ReceivingMethodContext receivingMethod: ctx.receivingMethod()) {
|
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||||
}
|
}
|
||||||
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,81 +1,83 @@
|
|||||||
BooleanValue=1
|
T__0=1
|
||||||
NullValue=2
|
BooleanValue=2
|
||||||
AccessModifierPublic=3
|
NullValue=3
|
||||||
MainMethodDecl=4
|
AccessModifierPublic=4
|
||||||
Void=5
|
MainMethodDecl=5
|
||||||
Int=6
|
Void=6
|
||||||
Boolean=7
|
Int=7
|
||||||
Char=8
|
Boolean=8
|
||||||
DotOperator=9
|
Char=9
|
||||||
LineOperator=10
|
DotOperator=10
|
||||||
ComparisonOperator=11
|
LineOperator=11
|
||||||
LogicalOpertor=12
|
ComparisonOperator=12
|
||||||
Assign=13
|
LogicalOpertor=13
|
||||||
Minus=14
|
Assign=14
|
||||||
Plus=15
|
Minus=15
|
||||||
Multipilkation=16
|
Plus=16
|
||||||
Division=17
|
Multipilkation=17
|
||||||
Modulo=18
|
Division=18
|
||||||
Greater=19
|
Modulo=19
|
||||||
Less=20
|
Greater=20
|
||||||
GreaterEqual=21
|
Less=21
|
||||||
LessEqual=22
|
GreaterEqual=22
|
||||||
Equal=23
|
LessEqual=23
|
||||||
NotEqual=24
|
Equal=24
|
||||||
Not=25
|
NotEqual=25
|
||||||
And=26
|
Not=26
|
||||||
Or=27
|
And=27
|
||||||
Dot=28
|
Or=28
|
||||||
OpenRoundBracket=29
|
Dot=29
|
||||||
ClosedRoundBracket=30
|
OpenRoundBracket=30
|
||||||
OpenCurlyBracket=31
|
ClosedRoundBracket=31
|
||||||
ClosedCurlyBracket=32
|
OpenCurlyBracket=32
|
||||||
Semicolon=33
|
ClosedCurlyBracket=33
|
||||||
Comma=34
|
Semicolon=34
|
||||||
Class=35
|
Comma=35
|
||||||
This=36
|
Class=36
|
||||||
While=37
|
This=37
|
||||||
If=38
|
While=38
|
||||||
Else=39
|
If=39
|
||||||
Return=40
|
Else=40
|
||||||
New=41
|
Return=41
|
||||||
IntValue=42
|
New=42
|
||||||
CharValue=43
|
IntValue=43
|
||||||
Identifier=44
|
CharValue=44
|
||||||
WS=45
|
Identifier=45
|
||||||
'null'=2
|
WS=46
|
||||||
'public'=3
|
'print'=1
|
||||||
'public static void main(String[] args)'=4
|
'null'=3
|
||||||
'void'=5
|
'public'=4
|
||||||
'int'=6
|
'public static void main(String[] args)'=5
|
||||||
'boolean'=7
|
'void'=6
|
||||||
'char'=8
|
'int'=7
|
||||||
'='=13
|
'boolean'=8
|
||||||
'-'=14
|
'char'=9
|
||||||
'+'=15
|
'='=14
|
||||||
'*'=16
|
'-'=15
|
||||||
'/'=17
|
'+'=16
|
||||||
'%'=18
|
'*'=17
|
||||||
'>'=19
|
'/'=18
|
||||||
'<'=20
|
'%'=19
|
||||||
'>='=21
|
'>'=20
|
||||||
'<='=22
|
'<'=21
|
||||||
'=='=23
|
'>='=22
|
||||||
'!='=24
|
'<='=23
|
||||||
'!'=25
|
'=='=24
|
||||||
'&&'=26
|
'!='=25
|
||||||
'||'=27
|
'!'=26
|
||||||
'.'=28
|
'&&'=27
|
||||||
'('=29
|
'||'=28
|
||||||
')'=30
|
'.'=29
|
||||||
'{'=31
|
'('=30
|
||||||
'}'=32
|
')'=31
|
||||||
';'=33
|
'{'=32
|
||||||
','=34
|
'}'=33
|
||||||
'class'=35
|
';'=34
|
||||||
'this'=36
|
','=35
|
||||||
'while'=37
|
'class'=36
|
||||||
'if'=38
|
'this'=37
|
||||||
'else'=39
|
'while'=38
|
||||||
'return'=40
|
'if'=39
|
||||||
'new'=41
|
'else'=40
|
||||||
|
'return'=41
|
||||||
|
'new'=42
|
||||||
|
|||||||
@@ -432,6 +432,18 @@ public class DecafBaseListener implements DecafListener {
|
|||||||
* <p>The default implementation does nothing.</p>
|
* <p>The default implementation does nothing.</p>
|
||||||
*/
|
*/
|
||||||
@Override public void exitValue(DecafParser.ValueContext ctx) { }
|
@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}
|
* {@inheritDoc}
|
||||||
|
|||||||
@@ -257,4 +257,11 @@ public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
|
|||||||
* {@link #visitChildren} on {@code ctx}.</p>
|
* {@link #visitChildren} on {@code ctx}.</p>
|
||||||
*/
|
*/
|
||||||
@Override public T visitValue(DecafParser.ValueContext ctx) { return visitChildren(ctx); }
|
@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 =
|
protected static final PredictionContextCache _sharedContextCache =
|
||||||
new PredictionContextCache();
|
new PredictionContextCache();
|
||||||
public static final int
|
public static final int
|
||||||
BooleanValue=1, NullValue=2, AccessModifierPublic=3, MainMethodDecl=4,
|
T__0=1, BooleanValue=2, NullValue=3, AccessModifierPublic=4, MainMethodDecl=5,
|
||||||
Void=5, Int=6, Boolean=7, Char=8, DotOperator=9, LineOperator=10, ComparisonOperator=11,
|
Void=6, Int=7, Boolean=8, Char=9, DotOperator=10, LineOperator=11, ComparisonOperator=12,
|
||||||
LogicalOpertor=12, Assign=13, Minus=14, Plus=15, Multipilkation=16, Division=17,
|
LogicalOpertor=13, Assign=14, Minus=15, Plus=16, Multipilkation=17, Division=18,
|
||||||
Modulo=18, Greater=19, Less=20, GreaterEqual=21, LessEqual=22, Equal=23,
|
Modulo=19, Greater=20, Less=21, GreaterEqual=22, LessEqual=23, Equal=24,
|
||||||
NotEqual=24, Not=25, And=26, Or=27, Dot=28, OpenRoundBracket=29, ClosedRoundBracket=30,
|
NotEqual=25, Not=26, And=27, Or=28, Dot=29, OpenRoundBracket=30, ClosedRoundBracket=31,
|
||||||
OpenCurlyBracket=31, ClosedCurlyBracket=32, Semicolon=33, Comma=34, Class=35,
|
OpenCurlyBracket=32, ClosedCurlyBracket=33, Semicolon=34, Comma=35, Class=36,
|
||||||
This=36, While=37, If=38, Else=39, Return=40, New=41, IntValue=42, CharValue=43,
|
This=37, While=38, If=39, Else=40, Return=41, New=42, IntValue=43, CharValue=44,
|
||||||
Identifier=44, WS=45;
|
Identifier=45, WS=46;
|
||||||
public static String[] channelNames = {
|
public static String[] channelNames = {
|
||||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||||
};
|
};
|
||||||
@@ -35,7 +35,7 @@ public class DecafLexer extends Lexer {
|
|||||||
|
|
||||||
private static String[] makeRuleNames() {
|
private static String[] makeRuleNames() {
|
||||||
return new String[] {
|
return new String[] {
|
||||||
"BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
"T__0", "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||||
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
||||||
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
||||||
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
||||||
@@ -49,7 +49,7 @@ public class DecafLexer extends Lexer {
|
|||||||
|
|
||||||
private static String[] makeLiteralNames() {
|
private static String[] makeLiteralNames() {
|
||||||
return new String[] {
|
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, "'='",
|
"'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 final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||||
private static String[] makeSymbolicNames() {
|
private static String[] makeSymbolicNames() {
|
||||||
return new String[] {
|
return new String[] {
|
||||||
null, "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
null, null, "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||||
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
||||||
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
||||||
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
||||||
@@ -129,7 +129,7 @@ public class DecafLexer extends Lexer {
|
|||||||
public ATN getATN() { return _ATN; }
|
public ATN getATN() { return _ATN; }
|
||||||
|
|
||||||
public static final String _serializedATN =
|
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\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+
|
||||||
"\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+
|
"\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"+
|
"\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"+
|
"\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*\u0002+\u0007"+
|
"&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007"+
|
||||||
"+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u0001\u0000"+
|
"+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u00020\u0007"+
|
||||||
"\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+
|
"0\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\u0001\u0001\u0001\u0001\u0001"+
|
||||||
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002"+
|
"\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\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\u0004"+
|
||||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
|
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||||
"\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\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006"+
|
"\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\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+
|
||||||
"\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001"+
|
"\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+
|
||||||
"\b\u0001\b\u0003\b\u00b9\b\b\u0001\t\u0001\t\u0003\t\u00bd\b\t\u0001\n"+
|
"\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001"+
|
||||||
"\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0003\n\u00c5\b\n\u0001\u000b"+
|
"\t\u0003\t\u00c1\b\t\u0001\n\u0001\n\u0003\n\u00c5\b\n\u0001\u000b\u0001"+
|
||||||
"\u0001\u000b\u0003\u000b\u00c9\b\u000b\u0001\f\u0001\f\u0001\r\u0001\r"+
|
"\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u00cd"+
|
||||||
"\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010"+
|
"\b\u000b\u0001\f\u0001\f\u0003\f\u00d1\b\f\u0001\r\u0001\r\u0001\u000e"+
|
||||||
"\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013"+
|
"\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0011"+
|
||||||
"\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015"+
|
"\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0014"+
|
||||||
"\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017"+
|
"\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016"+
|
||||||
"\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a"+
|
"\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018"+
|
||||||
"\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c"+
|
"\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a"+
|
||||||
"\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f"+
|
"\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001d"+
|
||||||
"\u0001 \u0001 \u0001!\u0001!\u0001\"\u0001\"\u0001\"\u0001\"\u0001\"\u0001"+
|
"\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\'\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)"+
|
"\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001"+
|
||||||
"\u000b)\f)\u0129\u0001*\u0001*\u0003*\u012e\b*\u0001*\u0001*\u0001+\u0001"+
|
")\u0001)\u0001*\u0005*\u012a\b*\n*\f*\u012d\t*\u0001*\u0004*\u0130\b*"+
|
||||||
"+\u0001,\u0001,\u0001-\u0001-\u0001-\u0003-\u0139\b-\u0001.\u0001.\u0005"+
|
"\u000b*\f*\u0131\u0001+\u0001+\u0003+\u0136\b+\u0001+\u0001+\u0001,\u0001"+
|
||||||
".\u013d\b.\n.\f.\u0140\t.\u0001/\u0001/\u0001/\u0001/\u0000\u00000\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"+
|
"\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\b\u0011\t\u0013\n\u0015\u000b\u0017\f\u0019\r\u001b\u000e\u001d"+
|
||||||
"\u000f\u001f\u0010!\u0011#\u0012%\u0013\'\u0014)\u0015+\u0016-\u0017/"+
|
"\u000f\u001f\u0010!\u0011#\u0012%\u0013\'\u0014)\u0015+\u0016-\u0017/"+
|
||||||
"\u00181\u00193\u001a5\u001b7\u001c9\u001d;\u001e=\u001f? A!C\"E#G$I%K"+
|
"\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++"+
|
"&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"+
|
"++--\u0001\u000009\u0002\u0000\n\n\r\r\u0002\u0000AZaz\u0002\u0000$$_"+
|
||||||
"\u0000\t\n\r\r \u0151\u0000\u0001\u0001\u0000\u0000\u0000\u0000\u0003"+
|
"_\u0003\u0000\t\n\r\r \u0159\u0000\u0001\u0001\u0000\u0000\u0000\u0000"+
|
||||||
"\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000\u0007"+
|
"\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000"+
|
||||||
"\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b\u0001"+
|
"\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b"+
|
||||||
"\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001\u0000"+
|
"\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001"+
|
||||||
"\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001\u0000"+
|
"\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001"+
|
||||||
"\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001\u0000"+
|
"\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001"+
|
||||||
"\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001\u0000"+
|
"\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001"+
|
||||||
"\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001\u0000"+
|
"\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001"+
|
||||||
"\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000\u0000"+
|
"\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000"+
|
||||||
"\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000\u0000"+
|
"\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000"+
|
||||||
")\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-\u0001"+
|
"\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-"+
|
||||||
"\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000\u0000"+
|
"\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000"+
|
||||||
"\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000\u0000"+
|
"\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000"+
|
||||||
"7\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000\u0000;\u0001"+
|
"\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000\u0000;"+
|
||||||
"\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?\u0001\u0000\u0000"+
|
"\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?\u0001\u0000"+
|
||||||
"\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000\u0000"+
|
"\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000"+
|
||||||
"E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000\u0000\u0000I\u0001"+
|
"\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000\u0000\u0000I"+
|
||||||
"\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000M\u0001\u0000\u0000"+
|
"\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000M\u0001\u0000"+
|
||||||
"\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001\u0000\u0000\u0000\u0000"+
|
"\u0000\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001\u0000\u0000\u0000"+
|
||||||
"S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000\u0000\u0000]\u0001"+
|
"\u0000S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000\u0000\u0000W"+
|
||||||
"\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0001j\u0001\u0000\u0000"+
|
"\u0001\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0000a\u0001\u0000"+
|
||||||
"\u0000\u0003l\u0001\u0000\u0000\u0000\u0005q\u0001\u0000\u0000\u0000\u0007"+
|
"\u0000\u0000\u0001c\u0001\u0000\u0000\u0000\u0003r\u0001\u0000\u0000\u0000"+
|
||||||
"x\u0001\u0000\u0000\u0000\t\u009f\u0001\u0000\u0000\u0000\u000b\u00a4"+
|
"\u0005t\u0001\u0000\u0000\u0000\u0007y\u0001\u0000\u0000\u0000\t\u0080"+
|
||||||
"\u0001\u0000\u0000\u0000\r\u00a8\u0001\u0000\u0000\u0000\u000f\u00b0\u0001"+
|
"\u0001\u0000\u0000\u0000\u000b\u00a7\u0001\u0000\u0000\u0000\r\u00ac\u0001"+
|
||||||
"\u0000\u0000\u0000\u0011\u00b8\u0001\u0000\u0000\u0000\u0013\u00bc\u0001"+
|
"\u0000\u0000\u0000\u000f\u00b0\u0001\u0000\u0000\u0000\u0011\u00b8\u0001"+
|
||||||
"\u0000\u0000\u0000\u0015\u00c4\u0001\u0000\u0000\u0000\u0017\u00c8\u0001"+
|
"\u0000\u0000\u0000\u0013\u00c0\u0001\u0000\u0000\u0000\u0015\u00c4\u0001"+
|
||||||
"\u0000\u0000\u0000\u0019\u00ca\u0001\u0000\u0000\u0000\u001b\u00cc\u0001"+
|
"\u0000\u0000\u0000\u0017\u00cc\u0001\u0000\u0000\u0000\u0019\u00d0\u0001"+
|
||||||
"\u0000\u0000\u0000\u001d\u00ce\u0001\u0000\u0000\u0000\u001f\u00d0\u0001"+
|
"\u0000\u0000\u0000\u001b\u00d2\u0001\u0000\u0000\u0000\u001d\u00d4\u0001"+
|
||||||
"\u0000\u0000\u0000!\u00d2\u0001\u0000\u0000\u0000#\u00d4\u0001\u0000\u0000"+
|
"\u0000\u0000\u0000\u001f\u00d6\u0001\u0000\u0000\u0000!\u00d8\u0001\u0000"+
|
||||||
"\u0000%\u00d6\u0001\u0000\u0000\u0000\'\u00d8\u0001\u0000\u0000\u0000"+
|
"\u0000\u0000#\u00da\u0001\u0000\u0000\u0000%\u00dc\u0001\u0000\u0000\u0000"+
|
||||||
")\u00da\u0001\u0000\u0000\u0000+\u00dd\u0001\u0000\u0000\u0000-\u00e0"+
|
"\'\u00de\u0001\u0000\u0000\u0000)\u00e0\u0001\u0000\u0000\u0000+\u00e2"+
|
||||||
"\u0001\u0000\u0000\u0000/\u00e3\u0001\u0000\u0000\u00001\u00e6\u0001\u0000"+
|
"\u0001\u0000\u0000\u0000-\u00e5\u0001\u0000\u0000\u0000/\u00e8\u0001\u0000"+
|
||||||
"\u0000\u00003\u00e8\u0001\u0000\u0000\u00005\u00eb\u0001\u0000\u0000\u0000"+
|
"\u0000\u00001\u00eb\u0001\u0000\u0000\u00003\u00ee\u0001\u0000\u0000\u0000"+
|
||||||
"7\u00ee\u0001\u0000\u0000\u00009\u00f0\u0001\u0000\u0000\u0000;\u00f2"+
|
"5\u00f0\u0001\u0000\u0000\u00007\u00f3\u0001\u0000\u0000\u00009\u00f6"+
|
||||||
"\u0001\u0000\u0000\u0000=\u00f4\u0001\u0000\u0000\u0000?\u00f6\u0001\u0000"+
|
"\u0001\u0000\u0000\u0000;\u00f8\u0001\u0000\u0000\u0000=\u00fa\u0001\u0000"+
|
||||||
"\u0000\u0000A\u00f8\u0001\u0000\u0000\u0000C\u00fa\u0001\u0000\u0000\u0000"+
|
"\u0000\u0000?\u00fc\u0001\u0000\u0000\u0000A\u00fe\u0001\u0000\u0000\u0000"+
|
||||||
"E\u00fc\u0001\u0000\u0000\u0000G\u0102\u0001\u0000\u0000\u0000I\u0107"+
|
"C\u0100\u0001\u0000\u0000\u0000E\u0102\u0001\u0000\u0000\u0000G\u0104"+
|
||||||
"\u0001\u0000\u0000\u0000K\u010d\u0001\u0000\u0000\u0000M\u0110\u0001\u0000"+
|
"\u0001\u0000\u0000\u0000I\u010a\u0001\u0000\u0000\u0000K\u010f\u0001\u0000"+
|
||||||
"\u0000\u0000O\u0115\u0001\u0000\u0000\u0000Q\u011c\u0001\u0000\u0000\u0000"+
|
"\u0000\u0000M\u0115\u0001\u0000\u0000\u0000O\u0118\u0001\u0000\u0000\u0000"+
|
||||||
"S\u0123\u0001\u0000\u0000\u0000U\u012b\u0001\u0000\u0000\u0000W\u0131"+
|
"Q\u011d\u0001\u0000\u0000\u0000S\u0124\u0001\u0000\u0000\u0000U\u012b"+
|
||||||
"\u0001\u0000\u0000\u0000Y\u0133\u0001\u0000\u0000\u0000[\u0138\u0001\u0000"+
|
"\u0001\u0000\u0000\u0000W\u0133\u0001\u0000\u0000\u0000Y\u0139\u0001\u0000"+
|
||||||
"\u0000\u0000]\u013a\u0001\u0000\u0000\u0000_\u0141\u0001\u0000\u0000\u0000"+
|
"\u0000\u0000[\u013b\u0001\u0000\u0000\u0000]\u0140\u0001\u0000\u0000\u0000"+
|
||||||
"ab\u0005t\u0000\u0000bc\u0005r\u0000\u0000cd\u0005u\u0000\u0000dk\u0005"+
|
"_\u0142\u0001\u0000\u0000\u0000a\u0149\u0001\u0000\u0000\u0000cd\u0005"+
|
||||||
"e\u0000\u0000ef\u0005f\u0000\u0000fg\u0005a\u0000\u0000gh\u0005l\u0000"+
|
"p\u0000\u0000de\u0005r\u0000\u0000ef\u0005i\u0000\u0000fg\u0005n\u0000"+
|
||||||
"\u0000hi\u0005s\u0000\u0000ik\u0005e\u0000\u0000ja\u0001\u0000\u0000\u0000"+
|
"\u0000gh\u0005t\u0000\u0000h\u0002\u0001\u0000\u0000\u0000ij\u0005t\u0000"+
|
||||||
"je\u0001\u0000\u0000\u0000k\u0002\u0001\u0000\u0000\u0000lm\u0005n\u0000"+
|
"\u0000jk\u0005r\u0000\u0000kl\u0005u\u0000\u0000ls\u0005e\u0000\u0000"+
|
||||||
"\u0000mn\u0005u\u0000\u0000no\u0005l\u0000\u0000op\u0005l\u0000\u0000"+
|
"mn\u0005f\u0000\u0000no\u0005a\u0000\u0000op\u0005l\u0000\u0000pq\u0005"+
|
||||||
"p\u0004\u0001\u0000\u0000\u0000qr\u0005p\u0000\u0000rs\u0005u\u0000\u0000"+
|
"s\u0000\u0000qs\u0005e\u0000\u0000ri\u0001\u0000\u0000\u0000rm\u0001\u0000"+
|
||||||
"st\u0005b\u0000\u0000tu\u0005l\u0000\u0000uv\u0005i\u0000\u0000vw\u0005"+
|
"\u0000\u0000s\u0004\u0001\u0000\u0000\u0000tu\u0005n\u0000\u0000uv\u0005"+
|
||||||
"c\u0000\u0000w\u0006\u0001\u0000\u0000\u0000xy\u0005p\u0000\u0000yz\u0005"+
|
"u\u0000\u0000vw\u0005l\u0000\u0000wx\u0005l\u0000\u0000x\u0006\u0001\u0000"+
|
||||||
"u\u0000\u0000z{\u0005b\u0000\u0000{|\u0005l\u0000\u0000|}\u0005i\u0000"+
|
"\u0000\u0000yz\u0005p\u0000\u0000z{\u0005u\u0000\u0000{|\u0005b\u0000"+
|
||||||
"\u0000}~\u0005c\u0000\u0000~\u007f\u0005 \u0000\u0000\u007f\u0080\u0005"+
|
"\u0000|}\u0005l\u0000\u0000}~\u0005i\u0000\u0000~\u007f\u0005c\u0000\u0000"+
|
||||||
"s\u0000\u0000\u0080\u0081\u0005t\u0000\u0000\u0081\u0082\u0005a\u0000"+
|
"\u007f\b\u0001\u0000\u0000\u0000\u0080\u0081\u0005p\u0000\u0000\u0081"+
|
||||||
"\u0000\u0082\u0083\u0005t\u0000\u0000\u0083\u0084\u0005i\u0000\u0000\u0084"+
|
"\u0082\u0005u\u0000\u0000\u0082\u0083\u0005b\u0000\u0000\u0083\u0084\u0005"+
|
||||||
"\u0085\u0005c\u0000\u0000\u0085\u0086\u0005 \u0000\u0000\u0086\u0087\u0005"+
|
"l\u0000\u0000\u0084\u0085\u0005i\u0000\u0000\u0085\u0086\u0005c\u0000"+
|
||||||
"v\u0000\u0000\u0087\u0088\u0005o\u0000\u0000\u0088\u0089\u0005i\u0000"+
|
"\u0000\u0086\u0087\u0005 \u0000\u0000\u0087\u0088\u0005s\u0000\u0000\u0088"+
|
||||||
"\u0000\u0089\u008a\u0005d\u0000\u0000\u008a\u008b\u0005 \u0000\u0000\u008b"+
|
"\u0089\u0005t\u0000\u0000\u0089\u008a\u0005a\u0000\u0000\u008a\u008b\u0005"+
|
||||||
"\u008c\u0005m\u0000\u0000\u008c\u008d\u0005a\u0000\u0000\u008d\u008e\u0005"+
|
"t\u0000\u0000\u008b\u008c\u0005i\u0000\u0000\u008c\u008d\u0005c\u0000"+
|
||||||
"i\u0000\u0000\u008e\u008f\u0005n\u0000\u0000\u008f\u0090\u0005(\u0000"+
|
"\u0000\u008d\u008e\u0005 \u0000\u0000\u008e\u008f\u0005v\u0000\u0000\u008f"+
|
||||||
"\u0000\u0090\u0091\u0005S\u0000\u0000\u0091\u0092\u0005t\u0000\u0000\u0092"+
|
"\u0090\u0005o\u0000\u0000\u0090\u0091\u0005i\u0000\u0000\u0091\u0092\u0005"+
|
||||||
"\u0093\u0005r\u0000\u0000\u0093\u0094\u0005i\u0000\u0000\u0094\u0095\u0005"+
|
"d\u0000\u0000\u0092\u0093\u0005 \u0000\u0000\u0093\u0094\u0005m\u0000"+
|
||||||
"n\u0000\u0000\u0095\u0096\u0005g\u0000\u0000\u0096\u0097\u0005[\u0000"+
|
"\u0000\u0094\u0095\u0005a\u0000\u0000\u0095\u0096\u0005i\u0000\u0000\u0096"+
|
||||||
"\u0000\u0097\u0098\u0005]\u0000\u0000\u0098\u0099\u0005 \u0000\u0000\u0099"+
|
"\u0097\u0005n\u0000\u0000\u0097\u0098\u0005(\u0000\u0000\u0098\u0099\u0005"+
|
||||||
"\u009a\u0005a\u0000\u0000\u009a\u009b\u0005r\u0000\u0000\u009b\u009c\u0005"+
|
"S\u0000\u0000\u0099\u009a\u0005t\u0000\u0000\u009a\u009b\u0005r\u0000"+
|
||||||
"g\u0000\u0000\u009c\u009d\u0005s\u0000\u0000\u009d\u009e\u0005)\u0000"+
|
"\u0000\u009b\u009c\u0005i\u0000\u0000\u009c\u009d\u0005n\u0000\u0000\u009d"+
|
||||||
"\u0000\u009e\b\u0001\u0000\u0000\u0000\u009f\u00a0\u0005v\u0000\u0000"+
|
"\u009e\u0005g\u0000\u0000\u009e\u009f\u0005[\u0000\u0000\u009f\u00a0\u0005"+
|
||||||
"\u00a0\u00a1\u0005o\u0000\u0000\u00a1\u00a2\u0005i\u0000\u0000\u00a2\u00a3"+
|
"]\u0000\u0000\u00a0\u00a1\u0005 \u0000\u0000\u00a1\u00a2\u0005a\u0000"+
|
||||||
"\u0005d\u0000\u0000\u00a3\n\u0001\u0000\u0000\u0000\u00a4\u00a5\u0005"+
|
"\u0000\u00a2\u00a3\u0005r\u0000\u0000\u00a3\u00a4\u0005g\u0000\u0000\u00a4"+
|
||||||
"i\u0000\u0000\u00a5\u00a6\u0005n\u0000\u0000\u00a6\u00a7\u0005t\u0000"+
|
"\u00a5\u0005s\u0000\u0000\u00a5\u00a6\u0005)\u0000\u0000\u00a6\n\u0001"+
|
||||||
"\u0000\u00a7\f\u0001\u0000\u0000\u0000\u00a8\u00a9\u0005b\u0000\u0000"+
|
"\u0000\u0000\u0000\u00a7\u00a8\u0005v\u0000\u0000\u00a8\u00a9\u0005o\u0000"+
|
||||||
"\u00a9\u00aa\u0005o\u0000\u0000\u00aa\u00ab\u0005o\u0000\u0000\u00ab\u00ac"+
|
"\u0000\u00a9\u00aa\u0005i\u0000\u0000\u00aa\u00ab\u0005d\u0000\u0000\u00ab"+
|
||||||
"\u0005l\u0000\u0000\u00ac\u00ad\u0005e\u0000\u0000\u00ad\u00ae\u0005a"+
|
"\f\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005i\u0000\u0000\u00ad\u00ae"+
|
||||||
"\u0000\u0000\u00ae\u00af\u0005n\u0000\u0000\u00af\u000e\u0001\u0000\u0000"+
|
"\u0005n\u0000\u0000\u00ae\u00af\u0005t\u0000\u0000\u00af\u000e\u0001\u0000"+
|
||||||
"\u0000\u00b0\u00b1\u0005c\u0000\u0000\u00b1\u00b2\u0005h\u0000\u0000\u00b2"+
|
"\u0000\u0000\u00b0\u00b1\u0005b\u0000\u0000\u00b1\u00b2\u0005o\u0000\u0000"+
|
||||||
"\u00b3\u0005a\u0000\u0000\u00b3\u00b4\u0005r\u0000\u0000\u00b4\u0010\u0001"+
|
"\u00b2\u00b3\u0005o\u0000\u0000\u00b3\u00b4\u0005l\u0000\u0000\u00b4\u00b5"+
|
||||||
"\u0000\u0000\u0000\u00b5\u00b9\u0003\u001f\u000f\u0000\u00b6\u00b9\u0003"+
|
"\u0005e\u0000\u0000\u00b5\u00b6\u0005a\u0000\u0000\u00b6\u00b7\u0005n"+
|
||||||
"!\u0010\u0000\u00b7\u00b9\u0003#\u0011\u0000\u00b8\u00b5\u0001\u0000\u0000"+
|
"\u0000\u0000\u00b7\u0010\u0001\u0000\u0000\u0000\u00b8\u00b9\u0005c\u0000"+
|
||||||
"\u0000\u00b8\u00b6\u0001\u0000\u0000\u0000\u00b8\u00b7\u0001\u0000\u0000"+
|
"\u0000\u00b9\u00ba\u0005h\u0000\u0000\u00ba\u00bb\u0005a\u0000\u0000\u00bb"+
|
||||||
"\u0000\u00b9\u0012\u0001\u0000\u0000\u0000\u00ba\u00bd\u0003\u001d\u000e"+
|
"\u00bc\u0005r\u0000\u0000\u00bc\u0012\u0001\u0000\u0000\u0000\u00bd\u00c1"+
|
||||||
"\u0000\u00bb\u00bd\u0003\u001b\r\u0000\u00bc\u00ba\u0001\u0000\u0000\u0000"+
|
"\u0003!\u0010\u0000\u00be\u00c1\u0003#\u0011\u0000\u00bf\u00c1\u0003%"+
|
||||||
"\u00bc\u00bb\u0001\u0000\u0000\u0000\u00bd\u0014\u0001\u0000\u0000\u0000"+
|
"\u0012\u0000\u00c0\u00bd\u0001\u0000\u0000\u0000\u00c0\u00be\u0001\u0000"+
|
||||||
"\u00be\u00c5\u0003%\u0012\u0000\u00bf\u00c5\u0003\'\u0013\u0000\u00c0"+
|
"\u0000\u0000\u00c0\u00bf\u0001\u0000\u0000\u0000\u00c1\u0014\u0001\u0000"+
|
||||||
"\u00c5\u0003)\u0014\u0000\u00c1\u00c5\u0003+\u0015\u0000\u00c2\u00c5\u0003"+
|
"\u0000\u0000\u00c2\u00c5\u0003\u001f\u000f\u0000\u00c3\u00c5\u0003\u001d"+
|
||||||
"-\u0016\u0000\u00c3\u00c5\u0003/\u0017\u0000\u00c4\u00be\u0001\u0000\u0000"+
|
"\u000e\u0000\u00c4\u00c2\u0001\u0000\u0000\u0000\u00c4\u00c3\u0001\u0000"+
|
||||||
"\u0000\u00c4\u00bf\u0001\u0000\u0000\u0000\u00c4\u00c0\u0001\u0000\u0000"+
|
"\u0000\u0000\u00c5\u0016\u0001\u0000\u0000\u0000\u00c6\u00cd\u0003\'\u0013"+
|
||||||
"\u0000\u00c4\u00c1\u0001\u0000\u0000\u0000\u00c4\u00c2\u0001\u0000\u0000"+
|
"\u0000\u00c7\u00cd\u0003)\u0014\u0000\u00c8\u00cd\u0003+\u0015\u0000\u00c9"+
|
||||||
"\u0000\u00c4\u00c3\u0001\u0000\u0000\u0000\u00c5\u0016\u0001\u0000\u0000"+
|
"\u00cd\u0003-\u0016\u0000\u00ca\u00cd\u0003/\u0017\u0000\u00cb\u00cd\u0003"+
|
||||||
"\u0000\u00c6\u00c9\u00033\u0019\u0000\u00c7\u00c9\u00035\u001a\u0000\u00c8"+
|
"1\u0018\u0000\u00cc\u00c6\u0001\u0000\u0000\u0000\u00cc\u00c7\u0001\u0000"+
|
||||||
"\u00c6\u0001\u0000\u0000\u0000\u00c8\u00c7\u0001\u0000\u0000\u0000\u00c9"+
|
"\u0000\u0000\u00cc\u00c8\u0001\u0000\u0000\u0000\u00cc\u00c9\u0001\u0000"+
|
||||||
"\u0018\u0001\u0000\u0000\u0000\u00ca\u00cb\u0005=\u0000\u0000\u00cb\u001a"+
|
"\u0000\u0000\u00cc\u00ca\u0001\u0000\u0000\u0000\u00cc\u00cb\u0001\u0000"+
|
||||||
"\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005-\u0000\u0000\u00cd\u001c\u0001"+
|
"\u0000\u0000\u00cd\u0018\u0001\u0000\u0000\u0000\u00ce\u00d1\u00035\u001a"+
|
||||||
"\u0000\u0000\u0000\u00ce\u00cf\u0005+\u0000\u0000\u00cf\u001e\u0001\u0000"+
|
"\u0000\u00cf\u00d1\u00037\u001b\u0000\u00d0\u00ce\u0001\u0000\u0000\u0000"+
|
||||||
"\u0000\u0000\u00d0\u00d1\u0005*\u0000\u0000\u00d1 \u0001\u0000\u0000\u0000"+
|
"\u00d0\u00cf\u0001\u0000\u0000\u0000\u00d1\u001a\u0001\u0000\u0000\u0000"+
|
||||||
"\u00d2\u00d3\u0005/\u0000\u0000\u00d3\"\u0001\u0000\u0000\u0000\u00d4"+
|
"\u00d2\u00d3\u0005=\u0000\u0000\u00d3\u001c\u0001\u0000\u0000\u0000\u00d4"+
|
||||||
"\u00d5\u0005%\u0000\u0000\u00d5$\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005"+
|
"\u00d5\u0005-\u0000\u0000\u00d5\u001e\u0001\u0000\u0000\u0000\u00d6\u00d7"+
|
||||||
">\u0000\u0000\u00d7&\u0001\u0000\u0000\u0000\u00d8\u00d9\u0005<\u0000"+
|
"\u0005+\u0000\u0000\u00d7 \u0001\u0000\u0000\u0000\u00d8\u00d9\u0005*"+
|
||||||
"\u0000\u00d9(\u0001\u0000\u0000\u0000\u00da\u00db\u0005>\u0000\u0000\u00db"+
|
"\u0000\u0000\u00d9\"\u0001\u0000\u0000\u0000\u00da\u00db\u0005/\u0000"+
|
||||||
"\u00dc\u0005=\u0000\u0000\u00dc*\u0001\u0000\u0000\u0000\u00dd\u00de\u0005"+
|
"\u0000\u00db$\u0001\u0000\u0000\u0000\u00dc\u00dd\u0005%\u0000\u0000\u00dd"+
|
||||||
"<\u0000\u0000\u00de\u00df\u0005=\u0000\u0000\u00df,\u0001\u0000\u0000"+
|
"&\u0001\u0000\u0000\u0000\u00de\u00df\u0005>\u0000\u0000\u00df(\u0001"+
|
||||||
"\u0000\u00e0\u00e1\u0005=\u0000\u0000\u00e1\u00e2\u0005=\u0000\u0000\u00e2"+
|
"\u0000\u0000\u0000\u00e0\u00e1\u0005<\u0000\u0000\u00e1*\u0001\u0000\u0000"+
|
||||||
".\u0001\u0000\u0000\u0000\u00e3\u00e4\u0005!\u0000\u0000\u00e4\u00e5\u0005"+
|
"\u0000\u00e2\u00e3\u0005>\u0000\u0000\u00e3\u00e4\u0005=\u0000\u0000\u00e4"+
|
||||||
"=\u0000\u0000\u00e50\u0001\u0000\u0000\u0000\u00e6\u00e7\u0005!\u0000"+
|
",\u0001\u0000\u0000\u0000\u00e5\u00e6\u0005<\u0000\u0000\u00e6\u00e7\u0005"+
|
||||||
"\u0000\u00e72\u0001\u0000\u0000\u0000\u00e8\u00e9\u0005&\u0000\u0000\u00e9"+
|
"=\u0000\u0000\u00e7.\u0001\u0000\u0000\u0000\u00e8\u00e9\u0005=\u0000"+
|
||||||
"\u00ea\u0005&\u0000\u0000\u00ea4\u0001\u0000\u0000\u0000\u00eb\u00ec\u0005"+
|
"\u0000\u00e9\u00ea\u0005=\u0000\u0000\u00ea0\u0001\u0000\u0000\u0000\u00eb"+
|
||||||
"|\u0000\u0000\u00ec\u00ed\u0005|\u0000\u0000\u00ed6\u0001\u0000\u0000"+
|
"\u00ec\u0005!\u0000\u0000\u00ec\u00ed\u0005=\u0000\u0000\u00ed2\u0001"+
|
||||||
"\u0000\u00ee\u00ef\u0005.\u0000\u0000\u00ef8\u0001\u0000\u0000\u0000\u00f0"+
|
"\u0000\u0000\u0000\u00ee\u00ef\u0005!\u0000\u0000\u00ef4\u0001\u0000\u0000"+
|
||||||
"\u00f1\u0005(\u0000\u0000\u00f1:\u0001\u0000\u0000\u0000\u00f2\u00f3\u0005"+
|
"\u0000\u00f0\u00f1\u0005&\u0000\u0000\u00f1\u00f2\u0005&\u0000\u0000\u00f2"+
|
||||||
")\u0000\u0000\u00f3<\u0001\u0000\u0000\u0000\u00f4\u00f5\u0005{\u0000"+
|
"6\u0001\u0000\u0000\u0000\u00f3\u00f4\u0005|\u0000\u0000\u00f4\u00f5\u0005"+
|
||||||
"\u0000\u00f5>\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005}\u0000\u0000\u00f7"+
|
"|\u0000\u0000\u00f58\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005.\u0000"+
|
||||||
"@\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005;\u0000\u0000\u00f9B\u0001"+
|
"\u0000\u00f7:\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005(\u0000\u0000\u00f9"+
|
||||||
"\u0000\u0000\u0000\u00fa\u00fb\u0005,\u0000\u0000\u00fbD\u0001\u0000\u0000"+
|
"<\u0001\u0000\u0000\u0000\u00fa\u00fb\u0005)\u0000\u0000\u00fb>\u0001"+
|
||||||
"\u0000\u00fc\u00fd\u0005c\u0000\u0000\u00fd\u00fe\u0005l\u0000\u0000\u00fe"+
|
"\u0000\u0000\u0000\u00fc\u00fd\u0005{\u0000\u0000\u00fd@\u0001\u0000\u0000"+
|
||||||
"\u00ff\u0005a\u0000\u0000\u00ff\u0100\u0005s\u0000\u0000\u0100\u0101\u0005"+
|
"\u0000\u00fe\u00ff\u0005}\u0000\u0000\u00ffB\u0001\u0000\u0000\u0000\u0100"+
|
||||||
"s\u0000\u0000\u0101F\u0001\u0000\u0000\u0000\u0102\u0103\u0005t\u0000"+
|
"\u0101\u0005;\u0000\u0000\u0101D\u0001\u0000\u0000\u0000\u0102\u0103\u0005"+
|
||||||
"\u0000\u0103\u0104\u0005h\u0000\u0000\u0104\u0105\u0005i\u0000\u0000\u0105"+
|
",\u0000\u0000\u0103F\u0001\u0000\u0000\u0000\u0104\u0105\u0005c\u0000"+
|
||||||
"\u0106\u0005s\u0000\u0000\u0106H\u0001\u0000\u0000\u0000\u0107\u0108\u0005"+
|
"\u0000\u0105\u0106\u0005l\u0000\u0000\u0106\u0107\u0005a\u0000\u0000\u0107"+
|
||||||
"w\u0000\u0000\u0108\u0109\u0005h\u0000\u0000\u0109\u010a\u0005i\u0000"+
|
"\u0108\u0005s\u0000\u0000\u0108\u0109\u0005s\u0000\u0000\u0109H\u0001"+
|
||||||
"\u0000\u010a\u010b\u0005l\u0000\u0000\u010b\u010c\u0005e\u0000\u0000\u010c"+
|
"\u0000\u0000\u0000\u010a\u010b\u0005t\u0000\u0000\u010b\u010c\u0005h\u0000"+
|
||||||
"J\u0001\u0000\u0000\u0000\u010d\u010e\u0005i\u0000\u0000\u010e\u010f\u0005"+
|
"\u0000\u010c\u010d\u0005i\u0000\u0000\u010d\u010e\u0005s\u0000\u0000\u010e"+
|
||||||
"f\u0000\u0000\u010fL\u0001\u0000\u0000\u0000\u0110\u0111\u0005e\u0000"+
|
"J\u0001\u0000\u0000\u0000\u010f\u0110\u0005w\u0000\u0000\u0110\u0111\u0005"+
|
||||||
"\u0000\u0111\u0112\u0005l\u0000\u0000\u0112\u0113\u0005s\u0000\u0000\u0113"+
|
"h\u0000\u0000\u0111\u0112\u0005i\u0000\u0000\u0112\u0113\u0005l\u0000"+
|
||||||
"\u0114\u0005e\u0000\u0000\u0114N\u0001\u0000\u0000\u0000\u0115\u0116\u0005"+
|
"\u0000\u0113\u0114\u0005e\u0000\u0000\u0114L\u0001\u0000\u0000\u0000\u0115"+
|
||||||
"r\u0000\u0000\u0116\u0117\u0005e\u0000\u0000\u0117\u0118\u0005t\u0000"+
|
"\u0116\u0005i\u0000\u0000\u0116\u0117\u0005f\u0000\u0000\u0117N\u0001"+
|
||||||
"\u0000\u0118\u0119\u0005u\u0000\u0000\u0119\u011a\u0005r\u0000\u0000\u011a"+
|
"\u0000\u0000\u0000\u0118\u0119\u0005e\u0000\u0000\u0119\u011a\u0005l\u0000"+
|
||||||
"\u011b\u0005n\u0000\u0000\u011bP\u0001\u0000\u0000\u0000\u011c\u011d\u0005"+
|
"\u0000\u011a\u011b\u0005s\u0000\u0000\u011b\u011c\u0005e\u0000\u0000\u011c"+
|
||||||
"n\u0000\u0000\u011d\u011e\u0005e\u0000\u0000\u011e\u011f\u0005w\u0000"+
|
"P\u0001\u0000\u0000\u0000\u011d\u011e\u0005r\u0000\u0000\u011e\u011f\u0005"+
|
||||||
"\u0000\u011fR\u0001\u0000\u0000\u0000\u0120\u0122\u0007\u0000\u0000\u0000"+
|
"e\u0000\u0000\u011f\u0120\u0005t\u0000\u0000\u0120\u0121\u0005u\u0000"+
|
||||||
"\u0121\u0120\u0001\u0000\u0000\u0000\u0122\u0125\u0001\u0000\u0000\u0000"+
|
"\u0000\u0121\u0122\u0005r\u0000\u0000\u0122\u0123\u0005n\u0000\u0000\u0123"+
|
||||||
"\u0123\u0121\u0001\u0000\u0000\u0000\u0123\u0124\u0001\u0000\u0000\u0000"+
|
"R\u0001\u0000\u0000\u0000\u0124\u0125\u0005n\u0000\u0000\u0125\u0126\u0005"+
|
||||||
"\u0124\u0127\u0001\u0000\u0000\u0000\u0125\u0123\u0001\u0000\u0000\u0000"+
|
"e\u0000\u0000\u0126\u0127\u0005w\u0000\u0000\u0127T\u0001\u0000\u0000"+
|
||||||
"\u0126\u0128\u0007\u0001\u0000\u0000\u0127\u0126\u0001\u0000\u0000\u0000"+
|
"\u0000\u0128\u012a\u0007\u0000\u0000\u0000\u0129\u0128\u0001\u0000\u0000"+
|
||||||
"\u0128\u0129\u0001\u0000\u0000\u0000\u0129\u0127\u0001\u0000\u0000\u0000"+
|
"\u0000\u012a\u012d\u0001\u0000\u0000\u0000\u012b\u0129\u0001\u0000\u0000"+
|
||||||
"\u0129\u012a\u0001\u0000\u0000\u0000\u012aT\u0001\u0000\u0000\u0000\u012b"+
|
"\u0000\u012b\u012c\u0001\u0000\u0000\u0000\u012c\u012f\u0001\u0000\u0000"+
|
||||||
"\u012d\u0005\'\u0000\u0000\u012c\u012e\b\u0002\u0000\u0000\u012d\u012c"+
|
"\u0000\u012d\u012b\u0001\u0000\u0000\u0000\u012e\u0130\u0007\u0001\u0000"+
|
||||||
"\u0001\u0000\u0000\u0000\u012d\u012e\u0001\u0000\u0000\u0000\u012e\u012f"+
|
"\u0000\u012f\u012e\u0001\u0000\u0000\u0000\u0130\u0131\u0001\u0000\u0000"+
|
||||||
"\u0001\u0000\u0000\u0000\u012f\u0130\u0005\'\u0000\u0000\u0130V\u0001"+
|
"\u0000\u0131\u012f\u0001\u0000\u0000\u0000\u0131\u0132\u0001\u0000\u0000"+
|
||||||
"\u0000\u0000\u0000\u0131\u0132\u0007\u0003\u0000\u0000\u0132X\u0001\u0000"+
|
"\u0000\u0132V\u0001\u0000\u0000\u0000\u0133\u0135\u0005\'\u0000\u0000"+
|
||||||
"\u0000\u0000\u0133\u0134\u0007\u0001\u0000\u0000\u0134Z\u0001\u0000\u0000"+
|
"\u0134\u0136\b\u0002\u0000\u0000\u0135\u0134\u0001\u0000\u0000\u0000\u0135"+
|
||||||
"\u0000\u0135\u0139\u0003W+\u0000\u0136\u0139\u0003Y,\u0000\u0137\u0139"+
|
"\u0136\u0001\u0000\u0000\u0000\u0136\u0137\u0001\u0000\u0000\u0000\u0137"+
|
||||||
"\u0007\u0004\u0000\u0000\u0138\u0135\u0001\u0000\u0000\u0000\u0138\u0136"+
|
"\u0138\u0005\'\u0000\u0000\u0138X\u0001\u0000\u0000\u0000\u0139\u013a"+
|
||||||
"\u0001\u0000\u0000\u0000\u0138\u0137\u0001\u0000\u0000\u0000\u0139\\\u0001"+
|
"\u0007\u0003\u0000\u0000\u013aZ\u0001\u0000\u0000\u0000\u013b\u013c\u0007"+
|
||||||
"\u0000\u0000\u0000\u013a\u013e\u0003W+\u0000\u013b\u013d\u0003[-\u0000"+
|
"\u0001\u0000\u0000\u013c\\\u0001\u0000\u0000\u0000\u013d\u0141\u0003Y"+
|
||||||
"\u013c\u013b\u0001\u0000\u0000\u0000\u013d\u0140\u0001\u0000\u0000\u0000"+
|
",\u0000\u013e\u0141\u0003[-\u0000\u013f\u0141\u0007\u0004\u0000\u0000"+
|
||||||
"\u013e\u013c\u0001\u0000\u0000\u0000\u013e\u013f\u0001\u0000\u0000\u0000"+
|
"\u0140\u013d\u0001\u0000\u0000\u0000\u0140\u013e\u0001\u0000\u0000\u0000"+
|
||||||
"\u013f^\u0001\u0000\u0000\u0000\u0140\u013e\u0001\u0000\u0000\u0000\u0141"+
|
"\u0140\u013f\u0001\u0000\u0000\u0000\u0141^\u0001\u0000\u0000\u0000\u0142"+
|
||||||
"\u0142\u0007\u0005\u0000\u0000\u0142\u0143\u0001\u0000\u0000\u0000\u0143"+
|
"\u0146\u0003Y,\u0000\u0143\u0145\u0003].\u0000\u0144\u0143\u0001\u0000"+
|
||||||
"\u0144\u0006/\u0000\u0000\u0144`\u0001\u0000\u0000\u0000\u000b\u0000j"+
|
"\u0000\u0000\u0145\u0148\u0001\u0000\u0000\u0000\u0146\u0144\u0001\u0000"+
|
||||||
"\u00b8\u00bc\u00c4\u00c8\u0123\u0129\u012d\u0138\u013e\u0001\u0006\u0000"+
|
"\u0000\u0000\u0146\u0147\u0001\u0000\u0000\u0000\u0147`\u0001\u0000\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 =
|
public static final ATN _ATN =
|
||||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||||
static {
|
static {
|
||||||
|
|||||||
@@ -1,81 +1,83 @@
|
|||||||
BooleanValue=1
|
T__0=1
|
||||||
NullValue=2
|
BooleanValue=2
|
||||||
AccessModifierPublic=3
|
NullValue=3
|
||||||
MainMethodDecl=4
|
AccessModifierPublic=4
|
||||||
Void=5
|
MainMethodDecl=5
|
||||||
Int=6
|
Void=6
|
||||||
Boolean=7
|
Int=7
|
||||||
Char=8
|
Boolean=8
|
||||||
DotOperator=9
|
Char=9
|
||||||
LineOperator=10
|
DotOperator=10
|
||||||
ComparisonOperator=11
|
LineOperator=11
|
||||||
LogicalOpertor=12
|
ComparisonOperator=12
|
||||||
Assign=13
|
LogicalOpertor=13
|
||||||
Minus=14
|
Assign=14
|
||||||
Plus=15
|
Minus=15
|
||||||
Multipilkation=16
|
Plus=16
|
||||||
Division=17
|
Multipilkation=17
|
||||||
Modulo=18
|
Division=18
|
||||||
Greater=19
|
Modulo=19
|
||||||
Less=20
|
Greater=20
|
||||||
GreaterEqual=21
|
Less=21
|
||||||
LessEqual=22
|
GreaterEqual=22
|
||||||
Equal=23
|
LessEqual=23
|
||||||
NotEqual=24
|
Equal=24
|
||||||
Not=25
|
NotEqual=25
|
||||||
And=26
|
Not=26
|
||||||
Or=27
|
And=27
|
||||||
Dot=28
|
Or=28
|
||||||
OpenRoundBracket=29
|
Dot=29
|
||||||
ClosedRoundBracket=30
|
OpenRoundBracket=30
|
||||||
OpenCurlyBracket=31
|
ClosedRoundBracket=31
|
||||||
ClosedCurlyBracket=32
|
OpenCurlyBracket=32
|
||||||
Semicolon=33
|
ClosedCurlyBracket=33
|
||||||
Comma=34
|
Semicolon=34
|
||||||
Class=35
|
Comma=35
|
||||||
This=36
|
Class=36
|
||||||
While=37
|
This=37
|
||||||
If=38
|
While=38
|
||||||
Else=39
|
If=39
|
||||||
Return=40
|
Else=40
|
||||||
New=41
|
Return=41
|
||||||
IntValue=42
|
New=42
|
||||||
CharValue=43
|
IntValue=43
|
||||||
Identifier=44
|
CharValue=44
|
||||||
WS=45
|
Identifier=45
|
||||||
'null'=2
|
WS=46
|
||||||
'public'=3
|
'print'=1
|
||||||
'public static void main(String[] args)'=4
|
'null'=3
|
||||||
'void'=5
|
'public'=4
|
||||||
'int'=6
|
'public static void main(String[] args)'=5
|
||||||
'boolean'=7
|
'void'=6
|
||||||
'char'=8
|
'int'=7
|
||||||
'='=13
|
'boolean'=8
|
||||||
'-'=14
|
'char'=9
|
||||||
'+'=15
|
'='=14
|
||||||
'*'=16
|
'-'=15
|
||||||
'/'=17
|
'+'=16
|
||||||
'%'=18
|
'*'=17
|
||||||
'>'=19
|
'/'=18
|
||||||
'<'=20
|
'%'=19
|
||||||
'>='=21
|
'>'=20
|
||||||
'<='=22
|
'<'=21
|
||||||
'=='=23
|
'>='=22
|
||||||
'!='=24
|
'<='=23
|
||||||
'!'=25
|
'=='=24
|
||||||
'&&'=26
|
'!='=25
|
||||||
'||'=27
|
'!'=26
|
||||||
'.'=28
|
'&&'=27
|
||||||
'('=29
|
'||'=28
|
||||||
')'=30
|
'.'=29
|
||||||
'{'=31
|
'('=30
|
||||||
'}'=32
|
')'=31
|
||||||
';'=33
|
'{'=32
|
||||||
','=34
|
'}'=33
|
||||||
'class'=35
|
';'=34
|
||||||
'this'=36
|
','=35
|
||||||
'while'=37
|
'class'=36
|
||||||
'if'=38
|
'this'=37
|
||||||
'else'=39
|
'while'=38
|
||||||
'return'=40
|
'if'=39
|
||||||
'new'=41
|
'else'=40
|
||||||
|
'return'=41
|
||||||
|
'new'=42
|
||||||
|
|||||||
@@ -357,4 +357,14 @@ public interface DecafListener extends ParseTreeListener {
|
|||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
*/
|
*/
|
||||||
void exitValue(DecafParser.ValueContext ctx);
|
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
|
* @return the visitor result
|
||||||
*/
|
*/
|
||||||
T visitValue(DecafParser.ValueContext ctx);
|
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,5 +1,5 @@
|
|||||||
package AST;
|
package AST;
|
||||||
import ASTs.emptyClassAST;
|
import ASTs.*;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -8,15 +8,86 @@ public class testAll {
|
|||||||
AstComparer astComparer;
|
AstComparer astComparer;
|
||||||
public testAll()
|
public testAll()
|
||||||
{
|
{
|
||||||
this.astComparer = new AstComparer("test/resources");
|
this.astComparer = new AstComparer("src/test/resources");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAssignWrongType(){
|
||||||
|
Program ast = AssignWrongTypeAST.getProgram();
|
||||||
|
String pathToCode = "failTests/AssignWrongType.java";
|
||||||
|
testAst(ast, pathToCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void TestEmptyClass(){
|
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();
|
Program ast = emptyClassAST.getEmptyProgramm();
|
||||||
String pathToCode = "basicClasses/emptyClass.java";
|
String pathToCode = "basicClasses/emptyClass.java";
|
||||||
testAst(ast, pathToCode);
|
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)
|
public void testAst(Program ast, String pathToCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
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.FieldDecl;
|
||||||
import abstractSyntaxTree.Class.MethodDecl;
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
import abstractSyntaxTree.Class.RefType;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
@@ -12,23 +11,21 @@ import abstractSyntaxTree.Statement.IStatement;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class emptyClassWithConstructorAST extends Program {
|
public class EmptyClassWithConstructorAST {
|
||||||
public emptyClassWithConstructorAST()
|
public static Program getProgram() {
|
||||||
{
|
|
||||||
super(staticClasses());
|
|
||||||
}
|
|
||||||
private static List<RefType> staticClasses() {
|
|
||||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||||
|
|
||||||
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
||||||
List<IStatement> emptyIStatementList = new ArrayList<>();
|
List<IStatement> emptyIStatementList = new ArrayList<>();
|
||||||
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, "void");
|
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, null);
|
||||||
MethodDecl constructor = new MethodDecl("emptyClassWithConstructor", "null", "emptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
MethodDecl constructor = new MethodDecl("EmptyClassWithConstructor", null, "EmptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||||
methodDeclList.add(constructor);
|
methodDeclList.add(constructor);
|
||||||
RefType emptyClass = new RefType("emptyClass", fieldDeclList, methodDeclList, false);
|
RefType emptyClass = new RefType("EmptyClassWithConstructor", fieldDeclList, methodDeclList, false);
|
||||||
List<RefType> classes = new ArrayList<>();
|
List<RefType> classes = new ArrayList<>();
|
||||||
classes.add(emptyClass);
|
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.FieldDecl;
|
||||||
import abstractSyntaxTree.Class.MethodDecl;
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
import abstractSyntaxTree.Class.RefType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.*;
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
|
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||||
import abstractSyntaxTree.Statement.ReturnStatement;
|
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
public class fourClassesAST extends Program {
|
public class fourClassesAST extends Program {
|
||||||
|
|
||||||
public fourClassesAST()
|
public fourClassesAST()
|
||||||
@@ -26,55 +29,174 @@ public class fourClassesAST extends Program {
|
|||||||
}
|
}
|
||||||
private static List<RefType> staticClasses() {
|
private static List<RefType> staticClasses() {
|
||||||
|
|
||||||
/////////// Classes ///////////
|
return program;
|
||||||
|
|
||||||
///////// 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;
|
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,6 +4,8 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import static ByteCode.CompareByteCodeSyntax.compareMethod;
|
import static ByteCode.CompareByteCodeSyntax.compareMethod;
|
||||||
|
|
||||||
@@ -37,6 +39,14 @@ public class CompareByteCodeBehaviour {
|
|||||||
Method[] methods1 = class1.getDeclaredMethods();
|
Method[] methods1 = class1.getDeclaredMethods();
|
||||||
Method[] methods2 = class2.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 method1 : methods1) {
|
||||||
for (Method method2 : methods2) {
|
for (Method method2 : methods2) {
|
||||||
if (compareMethod(method1, method2)) {
|
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){
|
public boolean compareMethodBehaviour(Class<?> class1, Class<?> class2){
|
||||||
try {
|
try {
|
||||||
this.sortMethods(class1, class2);
|
this.sortMethods(class1, class2);
|
||||||
// Create instances
|
// Create instances
|
||||||
Constructor<?> constructor1 = class1.getDeclaredConstructor();
|
Constructor<?>[] constructors1 = class1.getDeclaredConstructors();
|
||||||
Constructor<?> constructor2 = class2.getDeclaredConstructor();
|
Constructor<?>[] constructors2 = class2.getDeclaredConstructors();
|
||||||
|
Constructor<?> constructor1 = constructors1[0];
|
||||||
|
Constructor<?> constructor2 = constructors2[0];
|
||||||
constructor1.setAccessible(true);
|
constructor1.setAccessible(true);
|
||||||
constructor2.setAccessible(true);
|
constructor2.setAccessible(true);
|
||||||
Object obj1 = constructor1.newInstance();
|
Object[] constructorArgs = getDefaultArguments(constructor1.getParameters());
|
||||||
Object obj2 = constructor2.newInstance();
|
Object obj1 = constructor1.newInstance(constructorArgs);
|
||||||
|
Object obj2 = constructor2.newInstance(constructorArgs);
|
||||||
|
|
||||||
// Get methods
|
// Get methods
|
||||||
Method[] methods1 = new Method[this.methodArray1.size()];
|
Method[] methods1 = new Method[this.methodArray1.size()];
|
||||||
@@ -67,31 +86,53 @@ public class CompareByteCodeBehaviour {
|
|||||||
Method[] methods2 = new Method[this.methodArray2.size()];
|
Method[] methods2 = new Method[this.methodArray2.size()];
|
||||||
methods2 = this.methodArray2.toArray(methods2);
|
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
|
// Compare methods
|
||||||
for (int i = 0; i < methods1.length; i++) {
|
for (int i = 0; i < methods1.length; i++) {
|
||||||
Method method1 = methods1[i];
|
Method method1 = methods1[i];
|
||||||
Method method2 = methods2[i];
|
Method method2 = methods2[i];
|
||||||
|
|
||||||
|
System.out.println("\n" + method1);
|
||||||
|
System.out.println(method2);
|
||||||
|
|
||||||
method1.setAccessible(true);
|
method1.setAccessible(true);
|
||||||
method2.setAccessible(true);
|
method2.setAccessible(true);
|
||||||
|
|
||||||
|
|
||||||
// Test with some sample inputs
|
// Test with some sample inputs
|
||||||
Object[] testInputs = getTestInputs(method1.getParameterTypes());
|
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 result1 = method1.invoke(obj1, testInputs);
|
||||||
Object result2 = method2.invoke(obj2, 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)) {
|
if( !((result1 == null) && (result2 == null))) {
|
||||||
return false;
|
if(( result1 == null) || (result2 == null) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!result1.equals(result2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InstantiationException | IllegalAccessException |
|
} catch (InstantiationException | IllegalAccessException |
|
||||||
NoSuchMethodException | InvocationTargetException e) {
|
InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -99,15 +140,42 @@ public class CompareByteCodeBehaviour {
|
|||||||
private static Object[] getTestInputs(Class<?>[] parameterTypes) {
|
private static Object[] getTestInputs(Class<?>[] parameterTypes) {
|
||||||
// Create test inputs based on parameter types
|
// Create test inputs based on parameter types
|
||||||
Object[] inputs = new Object[parameterTypes.length];
|
Object[] inputs = new Object[parameterTypes.length];
|
||||||
|
Random random = new Random();
|
||||||
for (int i = 0; i < parameterTypes.length; i++) {
|
for (int i = 0; i < parameterTypes.length; i++) {
|
||||||
if (parameterTypes[i] == int.class) {
|
if (parameterTypes[i] == int.class) {
|
||||||
inputs[i] = 1; // example value
|
inputs[i] = random.nextInt(10); // example value
|
||||||
} else if (parameterTypes[i] == String.class) {
|
} 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
|
// Add more cases as needed for different parameter types
|
||||||
}
|
}
|
||||||
return inputs;
|
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.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class CompareByteCodeSyntax {
|
public class CompareByteCodeSyntax {
|
||||||
|
|
||||||
public static boolean haveSameBehavior(Class<?> class1, Class<?> class2) {
|
public static boolean haveSameBehavior(Class<?> class1, Class<?> class2) {
|
||||||
@@ -24,9 +25,11 @@ public class CompareByteCodeSyntax {
|
|||||||
|
|
||||||
public static boolean compareClassSignatures(Class<?> class1, Class<?> class2) {
|
public static boolean compareClassSignatures(Class<?> class1, Class<?> class2) {
|
||||||
if (!Arrays.equals(class1.getInterfaces(), class2.getInterfaces())) {
|
if (!Arrays.equals(class1.getInterfaces(), class2.getInterfaces())) {
|
||||||
|
System.out.println("Interfaces do not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (class1.getSuperclass() != class2.getSuperclass()) {
|
if (class1.getSuperclass() != class2.getSuperclass()) {
|
||||||
|
System.out.println("Superclasses do not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -36,6 +39,7 @@ public class CompareByteCodeSyntax {
|
|||||||
Method[] methods1 = class1.getDeclaredMethods();
|
Method[] methods1 = class1.getDeclaredMethods();
|
||||||
Method[] methods2 = class2.getDeclaredMethods();
|
Method[] methods2 = class2.getDeclaredMethods();
|
||||||
if (methods1.length != methods2.length) {
|
if (methods1.length != methods2.length) {
|
||||||
|
System.out.println("Method counts do not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Method method1 : methods1) {
|
for (Method method1 : methods1) {
|
||||||
@@ -49,6 +53,7 @@ public class CompareByteCodeSyntax {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
System.out.println("No matching method found for: " + method1.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,17 +62,22 @@ public class CompareByteCodeSyntax {
|
|||||||
|
|
||||||
public static boolean compareMethod(Method method1, Method method2) {
|
public static boolean compareMethod(Method method1, Method method2) {
|
||||||
if (!method1.getReturnType().equals(method2.getReturnType())) {
|
if (!method1.getReturnType().equals(method2.getReturnType())) {
|
||||||
|
System.out.println("Return types do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Arrays.equals(method1.getParameterTypes(), method2.getParameterTypes())) {
|
if (!Arrays.equals(method1.getParameterTypes(), method2.getParameterTypes())) {
|
||||||
|
System.out.println("Parameter types do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Arrays.equals(method1.getExceptionTypes(), method2.getExceptionTypes())) {
|
if (!Arrays.equals(method1.getExceptionTypes(), method2.getExceptionTypes())) {
|
||||||
|
System.out.println("Exception types do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!compareAnnotations(method1.getAnnotations(), method2.getAnnotations())) {
|
if (!compareAnnotations(method1.getAnnotations(), method2.getAnnotations())) {
|
||||||
|
System.out.println("Annotations do not match for methods " + method1.getName() + " and " + method2.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +85,7 @@ public class CompareByteCodeSyntax {
|
|||||||
Field[] fields1 = class1.getDeclaredFields();
|
Field[] fields1 = class1.getDeclaredFields();
|
||||||
Field[] fields2 = class2.getDeclaredFields();
|
Field[] fields2 = class2.getDeclaredFields();
|
||||||
if (fields1.length != fields2.length) {
|
if (fields1.length != fields2.length) {
|
||||||
|
System.out.println("Field counts do not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Field field1 : fields1) {
|
for (Field field1 : fields1) {
|
||||||
@@ -88,6 +99,7 @@ public class CompareByteCodeSyntax {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
System.out.println("No matching field found for: " + field1.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,9 +108,11 @@ public class CompareByteCodeSyntax {
|
|||||||
|
|
||||||
public static boolean compareField(Field field1, Field field2) {
|
public static boolean compareField(Field field1, Field field2) {
|
||||||
if (!field1.getType().equals(field2.getType())) {
|
if (!field1.getType().equals(field2.getType())) {
|
||||||
|
System.out.println("Field types do not match for fields " + field1.getName() + " and " + field2.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!compareAnnotations(field1.getAnnotations(), field2.getAnnotations())) {
|
if (!compareAnnotations(field1.getAnnotations(), field2.getAnnotations())) {
|
||||||
|
System.out.println("Annotations do not match for fields " + field1.getName() + " and " + field2.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -106,6 +120,7 @@ public class CompareByteCodeSyntax {
|
|||||||
|
|
||||||
public static boolean compareAnnotations(Annotation[] annotations1, Annotation[] annotations2) {
|
public static boolean compareAnnotations(Annotation[] annotations1, Annotation[] annotations2) {
|
||||||
if (annotations1.length != annotations2.length) {
|
if (annotations1.length != annotations2.length) {
|
||||||
|
System.out.println("Annotation counts do not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Annotation annotation1 : annotations1) {
|
for (Annotation annotation1 : annotations1) {
|
||||||
@@ -117,10 +132,10 @@ public class CompareByteCodeSyntax {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
System.out.println("No matching annotation found for: " + annotation1.annotationType().getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ public class JarFileLoader extends ClassLoader {
|
|||||||
byte[] classData = loadClassDataFromJar(classFileName);
|
byte[] classData = loadClassDataFromJar(classFileName);
|
||||||
return defineClass(name, classData, 0, classData.length);
|
return defineClass(name, classData, 0, classData.length);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ClassNotFoundException("Class not found", e);
|
e.printStackTrace();
|
||||||
|
throw new ClassNotFoundException("Class not found: " + name, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ public class JarFileLoader extends ClassLoader {
|
|||||||
try (JarFile jarFile = new JarFile(new File(jarFilePath))) {
|
try (JarFile jarFile = new JarFile(new File(jarFilePath))) {
|
||||||
JarEntry entry = jarFile.getJarEntry(classFileName);
|
JarEntry entry = jarFile.getJarEntry(classFileName);
|
||||||
if (entry == null) {
|
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.");
|
throw new IOException("Class file " + classFileName + " not found in jar file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,116 +1,193 @@
|
|||||||
package ByteCode;
|
package ByteCode;
|
||||||
|
|
||||||
import abstractSyntaxTree.Program;
|
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 org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import ASTs.*;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
import ASTs.emptyClassAST;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
|
||||||
public class TestAll {
|
public class TestAll {
|
||||||
CompareByteCodeBehaviour byteCodeBehaviourComparer;
|
ByteCodeTester byteCodeTester;
|
||||||
public TestAll(){
|
public TestAll(){byteCodeTester = new ByteCodeTester();}
|
||||||
byteCodeBehaviourComparer = new CompareByteCodeBehaviour();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testByteCodeFromAst(String classPath, Program abstractSyntaxTree, String className) {
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
abstractSyntaxTree.codeGen();
|
|
||||||
} catch (Exception e){
|
|
||||||
System.out.println("Le Exception in le codegen");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
ClassFileLoader classLoader1 = new ClassFileLoader(classPath);
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testByteCodeFromScratch(String correctClassFilePath, String fileToComparePath, String className) {
|
|
||||||
|
|
||||||
String content = "";
|
|
||||||
try {
|
|
||||||
System.out.println("Classpath: " + Path.of(fileToComparePath));
|
|
||||||
content = Files.readString(Path.of(fileToComparePath));
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("File not found!");
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
CharStream codeCharStream = CharStreams.fromString(content);
|
|
||||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
|
||||||
|
|
||||||
tokens.fill();
|
|
||||||
|
|
||||||
DecafParser parser = new DecafParser(tokens);
|
|
||||||
|
|
||||||
ParseTree tree = parser.program();
|
|
||||||
|
|
||||||
ASTGenerator generator = new ASTGenerator();
|
|
||||||
Program abstractSyntaxTree = (Program) generator.visit(tree);
|
|
||||||
|
|
||||||
try {
|
|
||||||
abstractSyntaxTree.typeCheck();
|
|
||||||
} catch (Exception e){
|
|
||||||
System.out.println("Le Exception in le type-check");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
abstractSyntaxTree.codeGen();
|
|
||||||
} catch (Exception e){
|
|
||||||
System.out.println("Le Exception in le codegen");
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmptyClass() {
|
public void testEmptyClass() {
|
||||||
String classPath = "src/test/resources/basicClasses/emptyClass.class";
|
String classPath = "src/test/resources/basicClasses/emptyClass.class";
|
||||||
Program ast = emptyClassAST.getEmptyProgramm();
|
Program ast = emptyClassASTTyped.getEmptyProgramm();
|
||||||
String className = "emptyClass";
|
String className = "emptyClass";
|
||||||
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
||||||
testByteCodeFromAst(classPath, ast ,className);
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
//testByteCodeFromScratch(classPath, javacode, className);
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyClassWithConstructor() {
|
||||||
|
String classPath = "src/test/resources/basicClasses/EmptyClassWithConstructor.class";
|
||||||
|
Program ast = EmptyClassWithConstructorASTTyped.getProgram();
|
||||||
|
String className = "EmptyClassWithConstructor";
|
||||||
|
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
||||||
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFakultaet() {
|
||||||
|
String classPath = "src/test/resources/basicClasses/Fakultaet.class";
|
||||||
|
Program ast = FakultaetAST.getProgram();
|
||||||
|
String className = "Fakultaet";
|
||||||
|
String javacode = "src/test/resources/basicClasses/Fakultaet.java";
|
||||||
|
byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassWithMain() {
|
||||||
|
String classPath = "src/test/resources/basicClasses/classWithMain.class";
|
||||||
|
Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "classWithMain";
|
||||||
|
String javacode = "src/test/resources/basicClasses/classWithMain.java";
|
||||||
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCharArgument() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/CharArgument.class";
|
||||||
|
Program ast = CharArgumentASTTyped.getProgram();
|
||||||
|
String className = "CharArgument";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/CharArgument.java";
|
||||||
|
//byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassFields() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/ClassFields.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "ClassFields";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/ClassFields.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructorParams() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/ConstructorParams.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "ConstructorParams";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/ConstructorParams.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructorThisDot() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/ConstructorThisDot.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "ConstructorThisDot";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/ConstructorThisDot.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We dont do null assignments
|
||||||
|
/*
|
||||||
|
@Test
|
||||||
|
public void testExplicitNullAssign() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/ExplicitNullAssign.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "ExplicitNullAssign";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/ExplicitNullAssign.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFieldVar() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/FieldVar.class";
|
||||||
|
Program ast = FieldVarASTTyped.getProgram();
|
||||||
|
String className = "FieldVar";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/FieldVar.java";
|
||||||
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFieldWithExpr() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/FieldWithExpr.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "FieldWithExpr";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/FieldWithExpr.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetterFunction() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/GetterFunction.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "GetterFunction";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/GetterFunction.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDivMethod() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/DivMethod.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "DivMethod";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/DivMethod.java";
|
||||||
|
//byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIfElseIfStatement() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/IfElseIfStatement.class";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String className = "IfElseIfStatement";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/IfElseIfStatement.java";
|
||||||
|
//testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIfElseIfStatementWithOneReturn() {
|
||||||
|
String classPath = "src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.class";
|
||||||
|
Program ast = IfElseIfStatementWithOneReturnAST.getProgram();
|
||||||
|
String className = "IfElseIfStatementWithOneReturn";
|
||||||
|
String javacode = "src/test/resources/SimpleTests/IfElseIfStatementWithOneReturn.java";
|
||||||
|
byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||||
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoClasses() {
|
||||||
|
String jarPath = "src/test/resources/basicClasses/TwoClasses.jar";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String[] classNames = {"ClassOne", "ClassTwo"};
|
||||||
|
String javacode = "src/test/resources/basicClasses/TwoClasses.java";
|
||||||
|
byteCodeTester.compareJarFilesFromScratch(javacode, jarPath, classNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFourClasses() {
|
||||||
|
String jarPath = "src/test/resources/basicClasses/FourClasses.jar";
|
||||||
|
//Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
|
String[] classNames = {"FourClasses", "Test", "Test2", "Test3"};
|
||||||
|
String javacode = "src/test/resources/basicClasses/FourClasses.java";
|
||||||
|
byteCodeTester.compareJarFilesFromScratch(javacode, jarPath, classNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,4 +31,46 @@ public class TestAll {
|
|||||||
public void testPublicEmptyClass() throws Exception {
|
public void testPublicEmptyClass() throws Exception {
|
||||||
testLexer.testTokens("basicClasses/PublicEmptyClass.java", "basicClasses/PublicEmptyClass.tokens");
|
testLexer.testTokens("basicClasses/PublicEmptyClass.java", "basicClasses/PublicEmptyClass.tokens");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFakultaet() throws Exception {
|
||||||
|
testLexer.testTokens("basicClasses/Fakultaet.java", "basicClasses/Fakultaet.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAssignWrongType() throws Exception {
|
||||||
|
testLexer.testTokens("FailTests/AssignWrongType.java", "FailTests/AssignWrongType.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBoolAssignedInt() throws Exception {
|
||||||
|
testLexer.testTokens("FailTests/BoolAssignedInt.java", "FailTests/BoolAssignedInt.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDivideByZero() throws Exception {
|
||||||
|
testLexer.testTokens("FailTests/DivideByZero.java", "FailTests/DivideByZero.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateFieldDeclaration() throws Exception {
|
||||||
|
testLexer.testTokens("FailTests/DuplicateFieldDeclaration.java", "FailTests/DuplicateFieldDeclaration.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateMethod() throws Exception {
|
||||||
|
testLexer.testTokens("FailTests/DuplicateMethod.java", "FailTests/DuplicateMethod.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFieldVar() throws Exception {
|
||||||
|
testLexer.testTokens("SimpleTests/FieldVar.java", "SimpleTests/FieldVar.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIfElseIfStatementWithOneReturn() throws Exception {
|
||||||
|
testLexer.testTokens("SimpleTests/IfElseIfStatementWithOneReturn.java", "SimpleTests/IfElseIfStatementWithOneReturn.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user