Homework 3
This commit is contained in:
parent
bf60a078d7
commit
0afc86ceeb
129 changed files with 3163 additions and 4316 deletions
|
@ -2,9 +2,10 @@
|
|||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="lib" path="lib/antlr-4.4-complete.jar"/>
|
||||
<classpathentry kind="lib" path="lib/junit-4.12.jar"/>
|
||||
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/antlr-4.7.1-complete.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="lib" path="lib/javaliParserObf.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
2
.project
2
.project
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Javali-HW2</name>
|
||||
<name>Javali-HW3</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
antlr4.antlrRegisteredTools=4.4@/tmp/antlr-4.4-complete.jar\:4.7.1@/home/carlos/eth/cd/nop90/HW2/lib/antlr-4.7.1-complete.jar
|
||||
antlr4.antlrToolPath=/home/carlos/eth/cd/nop90/HW2/lib/antlr-4.7.1-complete.jar
|
||||
antlr4.encoding=UTF-8
|
||||
antlr4.listener=true
|
||||
antlr4.visitor=false
|
||||
antlr4.vmArgs=
|
||||
antlr4ide.is_project_specific=true
|
||||
autobuilding=true
|
||||
eclipse.preferences.version=1
|
||||
is_project_specific=
|
||||
outlet.DEFAULT_OUTPUT.cleanupDerived=true
|
||||
outlet.DEFAULT_OUTPUT.derived=true
|
||||
outlet.DEFAULT_OUTPUT.directory=./target/generated-sources/antlr4
|
|
@ -1,7 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -1,5 +1,6 @@
|
|||
Grade: 29/30
|
||||
Grade: 25/25
|
||||
|
||||
251/251 tests passed [25/25]
|
||||
105/105 tests passed [20/20]
|
||||
|
||||
Submitted test cases: [5/5]
|
||||
|
||||
Submitted test cases: [4/5]
|
55
README.md
Normal file
55
README.md
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Compiler design
|
||||
## Parser and syntactic analysis
|
||||
See repo containing [Homework #2](https://svn.inf.ethz.ch/svn/trg/cd_students/ss18/teams/nop90/HW2).
|
||||
|
||||
## Semantic analysis
|
||||
This project checks a list class declaration as trees of Ast nodes for
|
||||
possible semantic errors.
|
||||
|
||||
### Design
|
||||
The semantic checks described [here](./SemanticChecks.md) are implemented in three
|
||||
phases.
|
||||
|
||||
1. Circular inheritance check (just with the names, and checking for non-existent
|
||||
types) to avoid stack overflow problems in the main analysis. May throw a
|
||||
`NO_SUCH_TYPE` error if the parent of a given class doesn't exist.
|
||||
2. Main semantic analysis, performed by `StmtAnalyzer` and `ExprAnalyzer`,
|
||||
two visitors that traverse each `ClassDecl` and all of its contents looking
|
||||
for semantic errors. Some types and methods may not have been discovered
|
||||
when they are accessed, and to that end the functions `findType(String)`
|
||||
and `findMethod(String,ClassSymbol)` lookup both, searching unvisited class
|
||||
and method declarations in order to find the corresponding symbol.
|
||||
3. Lookup of start point (method `void main()` in `Main` class)
|
||||
|
||||
### Testing
|
||||
A set of test cases (Javali programs, valid and invalid) are provided. The ones
|
||||
designed specifically for this homework assignment are located in
|
||||
`javali_tests/HW3_nop90`, and they cover all the code in the `cd.frontend.semantic`
|
||||
and `cd.ir` packages. They cover all the kinds of errors that can arise
|
||||
from a semantic analysis of Javali programs. As the order of the errors
|
||||
is not determined, each test case only checks one failing condition, and
|
||||
therefore many more test cases are needed for this homework than for
|
||||
previous ones.
|
||||
|
||||
The test files are organized in folders, with names ending in Tests or Errors,
|
||||
the latter only contain test cases that result in semantic errors.
|
||||
|
||||
To run the tests that exist in the `javali_tests` folder you can simply run
|
||||
|
||||
$ ant clean clean-test compile test
|
||||
|
||||
### Development environment
|
||||
This project is designed for Eclipse and GNU/Linux, but it can be run
|
||||
in other environments, as long as they have a 32bit `IA 86x assembly` compiler
|
||||
and a `JVM`. Check the `Config` class for more information.
|
||||
|
||||
### Documentation
|
||||
Available as [javadoc](javadoc/index.html). It is generated running the following command:
|
||||
|
||||
$ ant clean-doc generate-doc
|
||||
|
||||
### Important files
|
||||
* `TODO.md`: contains tasks to complete
|
||||
* `SemanticChecks.md`: contains the semantic checks numbered for quick reference
|
||||
* [Javali Grammar](https://www.ethz.ch/content/dam/ethz/special-interest/infk/inst-cs/lst-dam/documents/Education/Classes/Spring2018/210_Compiler_Design/Homework/javali.pdf)
|
||||
* [HW3 statement](https://www.ethz.ch/content/dam/ethz/special-interest/infk/inst-cs/lst-dam/documents/Education/Classes/Spring2018/210_Compiler_Design/Homework/hw3.pdf)
|
43
SemanticChecks.md
Normal file
43
SemanticChecks.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Class and method declaration errors
|
||||
1. All programs must have a method main() with void return type in the class Main (`INVALID_START_POINT`)
|
||||
2. The superclass of each class exists (`NO_SUCH_TYPE`)
|
||||
3. There is no circular inheritance (`CIRCULAR_INHERITANCE`)
|
||||
4. No class is declared with the name `Object` (`OBJECT_CLASS_DEFINED`)
|
||||
5. Unique names (`DOUBLE_DECLARATION`) for each group:
|
||||
1. Class names
|
||||
2. Field names in a single class (field shadowing is allowed)
|
||||
3. Method names in a single class (Override is allowed, overloading not)
|
||||
4. Method parameters and local variable names
|
||||
6. Overridden methods must: (`INVALID_OVERRIDE`)
|
||||
1. Have the same number of parameters
|
||||
2. The return types must match
|
||||
3. The type of the parameters must match (name can differ)
|
||||
|
||||
# Method body errors
|
||||
1. `write()` must take one argument of type `int` (`TYPE_ERROR`)
|
||||
2. `read()` and `writeln()` must take no arguments (`WRONG_NUMBER_OF_ARGUMENTS`)
|
||||
3. The condition of a `while` or `if` statement must be typed `booelan` (`TYPE_ERROR`)
|
||||
4. Assignments: the type of the right-hand side must be a suptype of the type of the left-hand side. (`TYPE_ERROR`)
|
||||
5. Operators (`TYPE_ERROR`):
|
||||
1. `*`, `/`, `%`, `+`, `-`, `<`, `>`, `<=`, `>=` take `int` arguments only.
|
||||
2. `!`, `&&`, `||` take `boolean` arguments only.
|
||||
3. `==` and `!=` takes any couple of arguments as long as one of the types is a subtype of the other.
|
||||
4. A cast is only possible if one of the types is a subtype of the other
|
||||
6. Method invocation, must match with declaration:
|
||||
1. The number of parameters (`WRONG_NUMBER_OF_ARGUMENTS`)
|
||||
2. The type of each of the parameters (`TYPE_ERROR`)
|
||||
7. Arrays:
|
||||
1. When indexing, the index expression must be an `int` (`TYPE_ERROR`)
|
||||
2. When creating one, the index expression must be an `int` (`TYPE_ERROR`)
|
||||
8. The constant `null` can be assigned to any reference type.
|
||||
9. The type name in a `new` statement must exist (`NO_SUCH_TYPE`)
|
||||
10. The left-hand side of an assignment can only be: (`NOT_ASSIGNABLE`)
|
||||
1. A variable
|
||||
2. A field
|
||||
3. Array dereferences (indexing)
|
||||
11. There must be no attempt to access the field or method of a
|
||||
non-object type, such as arrays or primitive types (`TYPE_ERROR`)
|
||||
12. A method with a return type must have a return statement at the end
|
||||
of all its paths (`MISSING_RETURN`). A while loop is not a valid return
|
||||
regardless of the condition. A ifElse must have a return on both the
|
||||
else and otherwise block. There may be some statements after a return.
|
75
TODO.md
Normal file
75
TODO.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
## Possible code changes
|
||||
### General
|
||||
* DONE Use more specific messages when throwing a `SemanticFailure` exception. This has the caveat that the automated testing relies on those tests?
|
||||
|
||||
### StmtAnalyzer
|
||||
* DONE Propagate the change of class parameter from `ExprAnalyzer`.
|
||||
* DONE Complete checks for `MISSING_RETURN`, some ideas:
|
||||
* DONE Assume no instructions will appear after a return statement and analyze only the last `Stmt` using other visitor
|
||||
with different class parameters (for example passing the desired type and returning a `Optional<TypeSymbol>`).
|
||||
* DONE Decide the logic behind a return statement in a `while` loop, maybe treat it as an `if` with an empty `else` block.
|
||||
* A `while` as last instruction is not a valid return.
|
||||
* A `if` as last instruction must have a valid return a the end of its then and otherwise blocks.
|
||||
|
||||
### ExprAnalyzer
|
||||
* DONE Change the second class parameter to give method AND class information (needed by var and this nodes)
|
||||
* DISCARDED Add a ClassSymbol to MethodSymbol and use it as class parameter, the problem arises when visiting a method,
|
||||
should an empty method with the proper class be provided? Could also be solved by using `Symbol` as class parameter.
|
||||
* DONE Create a new class that includes a `ClassSymbol` and a `MethodSymbol` and use that. Keep `MethodSymbol == null`
|
||||
when appropriate.
|
||||
|
||||
## Tests
|
||||
This tests have been selected to increase to 100% the code coverage obtained by running the tests designed for the previous HW,
|
||||
which are in folder svn/HW2/javali_tests/HW2_nop90
|
||||
|
||||
As they are mostly related to errors that haven't been triggered, each test should be separate, in order to generate all
|
||||
of the errors.
|
||||
|
||||
### Remaining
|
||||
### Done
|
||||
* access var from class or superclass
|
||||
* test ! operator
|
||||
* type error in unaryOp
|
||||
* type error in array size
|
||||
* call method from superclass
|
||||
* call a method that doesn't exist
|
||||
* call a method with the wrong type of params
|
||||
* call a method with the wrong number of params
|
||||
* assign to all possible syntactically correct options
|
||||
* field
|
||||
* var
|
||||
* array index
|
||||
* method (error)
|
||||
* this (error)
|
||||
* indexing both types error
|
||||
* try to access a field of something that is not a class type
|
||||
* typing error in cast
|
||||
* AND and OR operations
|
||||
* equals operators (a case that is OK and another that's not)
|
||||
* binary operation with wrong type (any but == and !=)
|
||||
* search for a type that doesn't exist in a method body
|
||||
* don't have a Main class
|
||||
* don't have a main() method in the Main class (all possibilities)
|
||||
* wrong name
|
||||
* wrong return value
|
||||
* wrong parameters
|
||||
* inherited main method (it should work)
|
||||
* write something that is not an integer
|
||||
* declare a variable mutiple times (local variables)
|
||||
* declare a local variable with the same name as a parameter
|
||||
* check MISSING_RETURN
|
||||
* nested ifElse as end of method
|
||||
* while as end of method
|
||||
* normal returns at the end of the method
|
||||
* return with further statements after it
|
||||
* while with non-int condition
|
||||
* use a array type that hasn't been discovered yet
|
||||
* ```class A { B[] name; } class B {}```
|
||||
* name a class Object
|
||||
* name a class like another class
|
||||
* name a parameter like another
|
||||
* override methods and try to break that
|
||||
* same return type
|
||||
* same number of params
|
||||
* same type of params
|
||||
* name a variable like another (field level)
|
75
build.xml
75
build.xml
|
@ -1,4 +1,4 @@
|
|||
<project name="compiler-design" default="generate-parser" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
|
||||
<project name="compiler-design" default="test" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
|
||||
|
||||
<!-- A very simple ant file that primarily exists to run cup and lex;
|
||||
it also includes targets to build the compiler and run tests for those
|
||||
|
@ -8,55 +8,25 @@
|
|||
<property name="src.dir" value="${basedir}/src"/>
|
||||
<property name="test.dir" value="${basedir}/test"/>
|
||||
<property name="javali_tests.dir" value="${basedir}/javali_tests"/>
|
||||
<property name="parser.dir" value="${src.dir}/cd/frontend/parser"/>
|
||||
<property name="parser.jar" value="${basedir}/lib/javaliParserObf.jar"/>
|
||||
<property name="build.dir" value="${basedir}/bin"/>
|
||||
<property name="junit.jar" value="${basedir}/lib/junit-4.12.jar"/>
|
||||
<property name="hamcrest.jar" value="${basedir}/lib/hamcrest-core-1.3.jar"/>
|
||||
<property name="antlr.jar" value="${basedir}/lib/antlr-4.7.1-complete.jar"/>
|
||||
<property name="antlr.jar" value="${basedir}/lib/antlr-4.4-complete.jar"/>
|
||||
<property name="antlr.profile" value="false"/>
|
||||
<property name="antlr.report" value="false"/>
|
||||
<property name="jacocoant.jar" value="${basedir}/lib/jacocoant.jar"/>
|
||||
<property name="coverage.file" location="${build.dir}/jacoco.exec"/>
|
||||
<property name="min.coverage" value="0.5"/>
|
||||
<property name="coverage.check" value="cd.frontend.*:cd.backend.*"/>
|
||||
|
||||
<target name="generate-parser">
|
||||
<echo message="ANTLR4 ${parser.dir}/Javali.g4" level="info"/>
|
||||
<echo>${basedir}</echo>
|
||||
<java classname="org.antlr.v4.Tool" failonerror="true" classpath="${antlr.jar}">
|
||||
<arg value="${parser.dir}/Javali.g4" />
|
||||
<arg value="-o" />
|
||||
<arg value="${parser.dir}" />
|
||||
<arg value="-no-listener" />
|
||||
<arg value="-visitor" />
|
||||
</java>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- Deletes the generated ANTLR parser files. Don't use in HW1! -->
|
||||
<target name="clean-parser">
|
||||
<delete file="${parser.dir}/Javali.tokens"/>
|
||||
<delete file="${parser.dir}/JavaliLexer.java"/>
|
||||
<delete file="${parser.dir}/JavaliParser.java"/>
|
||||
<delete file="${parser.dir}/JavaliWalker.tokens"/>
|
||||
<delete file="${parser.dir}/JavaliWalker.java"/>
|
||||
<delete file="${parser.dir}/JavaliBaseListener.java"/>
|
||||
<delete file="${parser.dir}/JavaliBaseVisitor.java"/>
|
||||
<delete file="${parser.dir}/JavaliListener.java"/>
|
||||
<delete file="${parser.dir}/JavaliVisitor.java"/>
|
||||
<delete file="${parser.dir}/JavaliLexer.tokens"/>
|
||||
<delete file="${parser.dir}/Javali.interp"/>
|
||||
<delete file="${parser.dir}/JavaliLexer.interp"/>
|
||||
</target>
|
||||
<property name="doc.dir" value="javadoc"/>
|
||||
|
||||
<!-- Cleans generated code, but NOT the parser source! -->
|
||||
<target name="clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
</target>
|
||||
|
||||
<!-- Builds the compiler framework for HW > HW1. -->
|
||||
<target name="compile" depends="generate-parser">
|
||||
<target name="compile">
|
||||
<mkdir dir="${build.dir}"/>
|
||||
|
||||
<javac debug="true" destdir="${build.dir}" includeantruntime="false">
|
||||
|
@ -66,6 +36,7 @@
|
|||
<pathelement location="${antlr.jar}"/>
|
||||
<pathelement location="${junit.jar}"/>
|
||||
<pathelement location="${hamcrest.jar}"/>
|
||||
<pathelement location="${parser.jar}"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
@ -108,4 +79,40 @@
|
|||
<fail if="tests-failed" />
|
||||
</target>
|
||||
|
||||
<target name="test-coverage-report">
|
||||
<jacoco:report>
|
||||
<executiondata>
|
||||
<file file="${coverage.file}"/>
|
||||
</executiondata>
|
||||
|
||||
<structure name="JaCoCo Ant Example">
|
||||
<classfiles>
|
||||
<fileset dir="${build.dir}"/>
|
||||
</classfiles>
|
||||
<sourcefiles encoding="UTF-8">
|
||||
<fileset dir="${src.dir}"/>
|
||||
</sourcefiles>
|
||||
</structure>
|
||||
<check>
|
||||
<rule element="PACKAGE" includes="${coverage.check}">
|
||||
<limit counter="LINE" value="COVEREDRATIO" minimum="${min.coverage}"/>
|
||||
</rule>
|
||||
</check>
|
||||
</jacoco:report>
|
||||
<echo message="Coverage above ${min.coverage} in ${coverage.check}: OK" level="info"/>
|
||||
</target>
|
||||
|
||||
<target name="clean-doc">
|
||||
<delete dir="javadoc"/>
|
||||
</target>
|
||||
|
||||
<target name="generate-doc">
|
||||
<javadoc sourcepath="${src.dir}" destdir="${doc.dir}"
|
||||
private="true" use="true" author="true">
|
||||
<package name="cd"/>
|
||||
<package name="cd.frontend.semantic"/>
|
||||
<package name="cd.ir"/>
|
||||
<arg value="-notimestamp"/>
|
||||
</javadoc>
|
||||
</target>
|
||||
</project>
|
||||
|
|
9
javali_tests/HW3/ErrCallBase.javali
Normal file
9
javali_tests/HW3/ErrCallBase.javali
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Test that you cannot invoke a method on an integer.
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int x;
|
||||
x = 1;
|
||||
x.foo();
|
||||
}
|
||||
}
|
9
javali_tests/HW3/ErrCircularInheritance.javali
Normal file
9
javali_tests/HW3/ErrCircularInheritance.javali
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* Test that the circular inheritance between Foo and Bar is detected */
|
||||
class Foo extends Bar { }
|
||||
class Bar extends Foo { }
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
writeln();
|
||||
}
|
||||
}
|
11
javali_tests/HW3/ErrIfCondition.javali
Normal file
11
javali_tests/HW3/ErrIfCondition.javali
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* Test that if conditions must be boolean */
|
||||
class Main {
|
||||
void main() {
|
||||
if (84 / 2) {
|
||||
write(1);
|
||||
writeln();
|
||||
}
|
||||
write(2);
|
||||
writeln();
|
||||
}
|
||||
}
|
14
javali_tests/HW3/ErrUnknownField1.javali
Normal file
14
javali_tests/HW3/ErrUnknownField1.javali
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* Test that an invalid field name is detected */
|
||||
|
||||
class X {
|
||||
int field;
|
||||
}
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
X x;
|
||||
x = new X();
|
||||
x.field = 0;
|
||||
x.notafield = 1; /* ILLEGAL: bad field name */
|
||||
}
|
||||
}
|
30
javali_tests/HW3/OkInheritanceFields.javali
Normal file
30
javali_tests/HW3/OkInheritanceFields.javali
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Test that fields are inherited */
|
||||
|
||||
class A {
|
||||
int foo;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
int bar;
|
||||
}
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
A a;
|
||||
B b;
|
||||
|
||||
a = new A();
|
||||
a.foo = 1;
|
||||
write(a.foo);
|
||||
|
||||
a = new B();
|
||||
a.foo = 2;
|
||||
write(a.foo);
|
||||
|
||||
b = new B();
|
||||
b.foo = 3;
|
||||
b.bar = 4;
|
||||
write(b.foo);
|
||||
write(b.bar);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Test that arrays are not covariant
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean y;
|
||||
A[] Array1;
|
||||
B[] Array2;
|
||||
Array2 = new B[10];
|
||||
|
||||
Array1 = Array2;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
class A {}
|
|
@ -0,0 +1,11 @@
|
|||
// The left-hand side of an assignment cannot be a method call
|
||||
// Valid options are variable accesses, fields or an indexed array
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
action() = read();
|
||||
}
|
||||
int action() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// The left-hand side of an assignment cannot be a reference to this
|
||||
// Valid options are variable accesses, fields or an indexed array
|
||||
|
||||
class Main {
|
||||
void main () {
|
||||
int b;
|
||||
int[] c;
|
||||
c = new int[5];
|
||||
this.a = 10;
|
||||
b = 10;
|
||||
c[4] = 10;
|
||||
this = null;
|
||||
}
|
||||
int a;
|
||||
}
|
14
javali_tests/HW3_nop90/Assignments/OkArraySubtypes.javali
Normal file
14
javali_tests/HW3_nop90/Assignments/OkArraySubtypes.javali
Normal file
|
@ -0,0 +1,14 @@
|
|||
// any array is a subtype of Object
|
||||
// assignment and 'is equal' with an object of type 'Object' is fine
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean y;
|
||||
Object x;
|
||||
int[] testArray;
|
||||
testArray = new int[10];
|
||||
x = testArray;
|
||||
testArray = null;
|
||||
x = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Multiple classes can't share the same name
|
||||
|
||||
class Aclass {}
|
||||
class Aclass {}
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Two fields in a class cannot share the same name
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
int a;
|
||||
Object b;
|
||||
Main a;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Two local variables in a method cannot share the same name
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
void test() {
|
||||
int a, a;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// test double declaration
|
||||
// test local variable and parameter have same name
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
int action(int p1, boolean p2) {
|
||||
Object p1;
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// No pair of parameters in a method declaration can have the same name
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
int action(int p1, boolean p2, Object p, Object p) {}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// No class can have the name "Object"
|
||||
|
||||
class Aclass {}
|
||||
class Object extends Aclass {}
|
||||
class Main extends Object {
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// Error: the return type of the "main" method must be "void"
|
||||
|
||||
class Main {
|
||||
int main() {
|
||||
return 10;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// Error: the main method must have no arguments
|
||||
|
||||
class Main {
|
||||
void main(Object[] args) {}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// Error: there is no class called Main (case-sensitive)
|
||||
|
||||
class MAIN {}
|
||||
class main extends Object {}
|
|
@ -0,0 +1,11 @@
|
|||
// Error: the "Main" class does not contain a method called "main"
|
||||
|
||||
class Main {
|
||||
void maini() {}
|
||||
void mein() {}
|
||||
void moon() {}
|
||||
}
|
||||
|
||||
class NotMain extends Main {
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// The main method can be inherited from another class
|
||||
|
||||
class OtherMain {
|
||||
void main () {}
|
||||
}
|
||||
|
||||
class Main extends OtherMain {}
|
|
@ -0,0 +1,15 @@
|
|||
// The main method can be overridden in the inherit process, as any other method can
|
||||
|
||||
class A {
|
||||
void main() {
|
||||
write(1);
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
void main() {
|
||||
write(2);
|
||||
}
|
||||
}
|
||||
|
||||
class Main extends B {}
|
7
javali_tests/HW3_nop90/ErrorOverloadMethod.javali
Normal file
7
javali_tests/HW3_nop90/ErrorOverloadMethod.javali
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Methods cannot be overloaded
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
void method(int a) {}
|
||||
void method(int[] a) {}
|
||||
}
|
21
javali_tests/HW3_nop90/FieldTests/ErrorAccessField.javali
Normal file
21
javali_tests/HW3_nop90/FieldTests/ErrorAccessField.javali
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Test 'NO SUCH FIELD'
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
C1 c1;
|
||||
C2 c2;
|
||||
c1 = new C1();
|
||||
c2 = new C2();
|
||||
c1.a = 5;
|
||||
c2.b = 6;
|
||||
}
|
||||
}
|
||||
|
||||
class C1{
|
||||
int a;
|
||||
}
|
||||
|
||||
class C2 extends C1 {}
|
||||
|
||||
class C3 extends C2 {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Access a field from an array (error, not a class type). Not even the length field exists
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int[] c;
|
||||
c = new int[10];
|
||||
write(c.length);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Error: access a field from a non-class type (primitive type int)
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int a;
|
||||
write(a.end);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// access a field from a class and a superclass (also includes hidden fields)
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
C1 c1;
|
||||
C2 c2;
|
||||
C4 c4;
|
||||
c1 = new C1();
|
||||
c2 = new C2();
|
||||
c4 = new C4();
|
||||
c1.a = 5;
|
||||
c2.a = 6;
|
||||
c4.a = false;
|
||||
}
|
||||
}
|
||||
|
||||
class C1{
|
||||
int a;
|
||||
}
|
||||
|
||||
class C2 extends C1 {}
|
||||
|
||||
class C3 extends C2 {}
|
||||
|
||||
class C4 extends C3 {
|
||||
boolean a;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Test more complex/nested cases of CIRCULAR INHERITANCE
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
}
|
||||
|
||||
class D1 extends C{}
|
||||
|
||||
class E extends D1{}
|
||||
|
||||
class D2 extends C{}
|
||||
|
||||
class E2 extends D2{}
|
||||
|
||||
class F extends E2{}
|
||||
|
||||
class C extends F{}
|
|
@ -0,0 +1,28 @@
|
|||
// Test long loops of circular inheritance
|
||||
|
||||
class A extends Z {}
|
||||
class B extends A {}
|
||||
class C extends B {}
|
||||
class D extends C {}
|
||||
class E extends D {}
|
||||
class F extends E {}
|
||||
class G extends F {}
|
||||
class H extends G {}
|
||||
class I extends H {}
|
||||
class J extends I {}
|
||||
class K extends J {}
|
||||
class L extends K {}
|
||||
class M extends L {}
|
||||
class N extends M {}
|
||||
class O extends N {}
|
||||
class P extends O {}
|
||||
class Q extends P {}
|
||||
class R extends Q {}
|
||||
class S extends R {}
|
||||
class T extends S {}
|
||||
class U extends T {}
|
||||
class V extends U {}
|
||||
class W extends V {}
|
||||
class X extends W {}
|
||||
class Y extends X {}
|
||||
class Z extends Y {}
|
|
@ -0,0 +1,5 @@
|
|||
// Test inheritance of itself
|
||||
|
||||
class Main extends Main {
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// Simple circular inheritance loop
|
||||
|
||||
class Main extends Other {
|
||||
void main() {}
|
||||
}
|
||||
|
||||
class Other extends Main {}
|
|
@ -0,0 +1,10 @@
|
|||
// Inherited methods cannot be overloaded
|
||||
|
||||
class Main extends Other {
|
||||
void main() {}
|
||||
void method(int a) {}
|
||||
}
|
||||
|
||||
class Other {
|
||||
void method() {}
|
||||
}
|
30
javali_tests/HW3_nop90/InheritanceTests/OkAccessField.javali
Normal file
30
javali_tests/HW3_nop90/InheritanceTests/OkAccessField.javali
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Access inherited and hidden fields (general check)
|
||||
|
||||
class Other {
|
||||
int a;
|
||||
int b;
|
||||
Object c;
|
||||
Other o;
|
||||
}
|
||||
|
||||
class Main extends Other {
|
||||
int a, b;
|
||||
|
||||
void main() {
|
||||
Other o;
|
||||
o = (Other) this;
|
||||
a = 1;
|
||||
b = 2;
|
||||
o.a = -1;
|
||||
o.b = -2;
|
||||
write(a);
|
||||
write(b);
|
||||
write(o.a);
|
||||
write(o.b);
|
||||
if (c != null) {
|
||||
if (o.o != null) {
|
||||
write(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// call an method from a superclass
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
C2 c;
|
||||
c = new C2();
|
||||
c.aux();
|
||||
}
|
||||
}
|
||||
|
||||
class C1{
|
||||
void aux(){
|
||||
write(2);
|
||||
}
|
||||
}
|
||||
|
||||
class C2 extends C1 {}
|
16
javali_tests/HW3_nop90/InheritanceTests/OkHideField.javali
Normal file
16
javali_tests/HW3_nop90/InheritanceTests/OkHideField.javali
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Hide a field from a superclass (type doesn't need to match)
|
||||
|
||||
class Parent {
|
||||
int a;
|
||||
}
|
||||
class Main extends Parent {
|
||||
Object a;
|
||||
Main b;
|
||||
void main() {
|
||||
Parent c;
|
||||
b = new Main();
|
||||
b.a = new Object();
|
||||
c = new Parent();
|
||||
c.a = 10;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// The number of parameters when overriding a method must be equal
|
||||
|
||||
class Other {
|
||||
void action() {
|
||||
write(10);
|
||||
}
|
||||
}
|
||||
|
||||
class Main extends Other {
|
||||
void action(int num) {
|
||||
write(num);
|
||||
return num + 1;
|
||||
}
|
||||
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// The return type when overriding a method must be equal
|
||||
|
||||
class Other {
|
||||
void action() {}
|
||||
}
|
||||
|
||||
class Main extends Other {
|
||||
int action() {
|
||||
write(10);
|
||||
return 8;
|
||||
}
|
||||
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// The type of parameters when overriding a method must match the overridden method
|
||||
|
||||
class Other {
|
||||
void action(int num) {
|
||||
write(num);
|
||||
}
|
||||
}
|
||||
|
||||
class Main extends Other{
|
||||
void action(boolean name) {
|
||||
if (name) {
|
||||
writeln();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Call method that has been overridden (both the new and old one)
|
||||
|
||||
class Other {
|
||||
void method() {}
|
||||
}
|
||||
|
||||
class Main extends Other {
|
||||
void main() {
|
||||
Other o;
|
||||
method();
|
||||
o = (Other) this;
|
||||
o.method();
|
||||
}
|
||||
|
||||
void method() {}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// An array doesn't have methods
|
||||
|
||||
class Main {
|
||||
Object[] array;
|
||||
void main() {
|
||||
array.go();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// A primitive variable doesn't have methods
|
||||
|
||||
class Main {
|
||||
int a;
|
||||
void main() {
|
||||
a.go();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// call an method with wrong number of parameters
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
aux(a, b, c);
|
||||
}
|
||||
|
||||
void aux(int a, int b) {}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// call an method with wrong types of parameters
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int a;
|
||||
boolean b;
|
||||
aux(a, b);
|
||||
}
|
||||
|
||||
void aux(int a, int b) {}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// call an method that does not exist (even in superclass)
|
||||
|
||||
class Main extends Other {
|
||||
void main() {
|
||||
aux();
|
||||
go();
|
||||
}
|
||||
|
||||
void aux() {}
|
||||
}
|
||||
|
||||
class Other {
|
||||
void aux() {}
|
||||
void otherAux() {}
|
||||
void noGo() {}
|
||||
void GO() {}
|
||||
void gO() {}
|
||||
void Go() {}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// No such type in method body (handled by TypeGenerator)
|
||||
|
||||
class Main {
|
||||
void method(NoSuchType param) {}
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// No such type in method body (handled by checkCircularInheritance)
|
||||
|
||||
class Main extends NoSuchType {
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// No such type in method body (handled by ExprVisitor and StmtVisitor)
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
Object a;
|
||||
write((NoType) a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Test NO SUCH VARIABLE
|
||||
// All referenced variables must exist.
|
||||
|
||||
class Main extends Other {
|
||||
int a;
|
||||
int b;
|
||||
int C;
|
||||
Object notC;
|
||||
|
||||
void main() {
|
||||
int a;
|
||||
boolean b;
|
||||
write(c + 1);
|
||||
}
|
||||
}
|
||||
|
||||
class Other {
|
||||
boolean a;
|
||||
boolean b;
|
||||
boolean C;
|
||||
Object[] notC;
|
||||
|
||||
void main() {
|
||||
int a;
|
||||
boolean b;
|
||||
Object c;
|
||||
}
|
||||
}
|
22
javali_tests/HW3_nop90/OkDoubleNamesDiffScopes.javali
Normal file
22
javali_tests/HW3_nop90/OkDoubleNamesDiffScopes.javali
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Names are case-sensitive
|
||||
// There exists different scopes for fields, methods, class types, parameters and local variables
|
||||
|
||||
class main extends Main {
|
||||
main main;
|
||||
Main Main;
|
||||
|
||||
main main(Main main, main Main) {
|
||||
Main MAIN;
|
||||
main maiN;
|
||||
maiN = new Main();
|
||||
return maiN;
|
||||
}
|
||||
}
|
||||
|
||||
class Main {
|
||||
main main;
|
||||
Main Main;
|
||||
void main() {
|
||||
|
||||
}
|
||||
}
|
31
javali_tests/HW3_nop90/OkUndiscoveredType.javali
Normal file
31
javali_tests/HW3_nop90/OkUndiscoveredType.javali
Normal file
|
@ -0,0 +1,31 @@
|
|||
// This method is used to force TypeGenerator to search through the list of class declarations and find
|
||||
// types that don't exist in the type list but have a class declared for them.
|
||||
|
||||
class Other {
|
||||
// Must discover in class declaration list
|
||||
Main[] array;
|
||||
Third third;
|
||||
// Already exist
|
||||
Fourth fourth; // discovered as parent of Third
|
||||
Other other; // already visited
|
||||
int a; // primitive and object types (and corresponding arrays) created before visiting classes
|
||||
boolean b;
|
||||
int[] As;
|
||||
boolean[] Bs;
|
||||
Object o;
|
||||
Object[] Os;
|
||||
Third[] thirds; // array types created when visiting corresponding classes
|
||||
Other[] others;
|
||||
}
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
}
|
||||
|
||||
class Third extends Fourth {
|
||||
|
||||
}
|
||||
|
||||
class Fourth {
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// The arguments of a BinaryOp (except == and !=) must be of the type specified by the operator
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int a;
|
||||
boolean b;
|
||||
write( a + b );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Error: both sides of a BinaryOp (except == and !=) must be of the same type
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int a, b, c;
|
||||
boolean d, e;
|
||||
a = a + b;
|
||||
d = a <= b;
|
||||
d = b && c;
|
||||
}
|
||||
}
|
25
javali_tests/HW3_nop90/OperatorTests/ErrorEquals.javali
Normal file
25
javali_tests/HW3_nop90/OperatorTests/ErrorEquals.javali
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Test the equal/not equal operations
|
||||
// this test should trigger an TYPE ERROR
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
C1 a;
|
||||
C3 d;
|
||||
D1 f;
|
||||
boolean x,y,z;
|
||||
a = new C1();
|
||||
d = new C3();
|
||||
f = new D1();
|
||||
|
||||
y = f == d;
|
||||
x = a != f;
|
||||
}
|
||||
}
|
||||
|
||||
class C1 {}
|
||||
|
||||
class C2 extends C1{}
|
||||
|
||||
class C3 extends C2{}
|
||||
|
||||
class D1 {}
|
19
javali_tests/HW3_nop90/OperatorTests/ErrorUnaryOp.javali
Normal file
19
javali_tests/HW3_nop90/OperatorTests/ErrorUnaryOp.javali
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Test type errors with unary operator
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int x,y,z;
|
||||
boolean a;
|
||||
x = -100;
|
||||
y = 5;
|
||||
|
||||
a = -true;
|
||||
z = -y;
|
||||
x = +x;
|
||||
write(x);
|
||||
writeln();
|
||||
write(z);
|
||||
writeln();
|
||||
write(-a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Test boolean && and || operators
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean a, b, c;
|
||||
a = b && c || a;
|
||||
}
|
||||
}
|
31
javali_tests/HW3_nop90/OperatorTests/OkEquals.javali
Normal file
31
javali_tests/HW3_nop90/OperatorTests/OkEquals.javali
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Test the equal/not equal operations, one of the types must be a subtype of the other
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
C1 c1;
|
||||
C2 c2;
|
||||
C3 c3;
|
||||
Object o1, o2;
|
||||
boolean s;
|
||||
|
||||
o1 = new Object();
|
||||
o2 = new Object();
|
||||
c1 = new C1();
|
||||
c2 = new C2();
|
||||
c3 = new C3();
|
||||
|
||||
s = o1 == o2;
|
||||
s = c1 != c2;
|
||||
s = c3 == c1;
|
||||
s = o2 != o1;
|
||||
s = null == c2;
|
||||
s = o1 == c2;
|
||||
s = null == o;
|
||||
}
|
||||
}
|
||||
|
||||
class C1 {}
|
||||
|
||||
class C2 extends C1{}
|
||||
|
||||
class C3 extends C2{}
|
36
javali_tests/HW3_nop90/OperatorTests/OkNot.javali
Normal file
36
javali_tests/HW3_nop90/OperatorTests/OkNot.javali
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Test '!' operator
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean a,b,c,d;
|
||||
int x,y;
|
||||
|
||||
a = true;
|
||||
c = !false;
|
||||
b = !a;
|
||||
x = 100;
|
||||
y = 5;
|
||||
|
||||
if (a) {
|
||||
write(1);}
|
||||
writeln();
|
||||
|
||||
if (!b){
|
||||
write(2);
|
||||
}
|
||||
writeln();
|
||||
|
||||
while(c){
|
||||
write(3);
|
||||
c = false;
|
||||
}
|
||||
writeln();
|
||||
|
||||
// !x < 2 * y --> !x type error
|
||||
// !(x < 2 * y) --> correct syntax
|
||||
while(!(x<2*y)){
|
||||
write(y);
|
||||
y = y*2;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// A method that returns a non-void type should have arguments in all returns
|
||||
|
||||
class Main {
|
||||
int method() {
|
||||
return;
|
||||
}
|
||||
|
||||
void main() {}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// For a if/else to be a valid return, it needs to have a return statement in both sides
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
write(things());
|
||||
writeln();
|
||||
}
|
||||
|
||||
int things() {
|
||||
Object c, d;
|
||||
c = new Object();
|
||||
d = new Object();
|
||||
|
||||
if (c == d) {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// The return type must be a subtype of the method's return type
|
||||
|
||||
class Main {
|
||||
Main main;
|
||||
Object object;
|
||||
|
||||
void main() {}
|
||||
|
||||
Object method() {
|
||||
return null;
|
||||
return object;
|
||||
return main;
|
||||
}
|
||||
|
||||
Main otherMethod() {
|
||||
return null;
|
||||
return main;
|
||||
return object; // error
|
||||
}
|
||||
}
|
20
javali_tests/HW3_nop90/ReturnTests/ErrorNoReturn.javali
Normal file
20
javali_tests/HW3_nop90/ReturnTests/ErrorNoReturn.javali
Normal file
|
@ -0,0 +1,20 @@
|
|||
// A method with a non-void return type must have a return statement
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
write(things());
|
||||
writeln();
|
||||
}
|
||||
|
||||
int things() {
|
||||
int a;
|
||||
int b;
|
||||
Object c, d;
|
||||
a = 10;
|
||||
b = 100;
|
||||
c = new Object();
|
||||
d = new Object();
|
||||
a = b;
|
||||
c = d;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Test nested return statement
|
||||
// the return statement is nested in if/else statements
|
||||
// conditions for the if/else aren't checked
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
|
||||
int aux (boolean e){
|
||||
boolean a,b,c,d;
|
||||
a = true;
|
||||
b = true;
|
||||
c = false;
|
||||
|
||||
if (a){
|
||||
if (b){
|
||||
if (c){
|
||||
|
||||
} else {
|
||||
if (e) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
javali_tests/HW3_nop90/ReturnTests/ErrorNoReturnWhile.javali
Normal file
11
javali_tests/HW3_nop90/ReturnTests/ErrorNoReturnWhile.javali
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Test return statement in while loop
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
|
||||
int aux() {
|
||||
while (true) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// A method that returns void can't have a return with an argument
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// A if/else block is valid return statment if all possible branches return some value
|
||||
// Also serves to check subtyping
|
||||
// The return logic leads to nonsensical programs with statements after the return, but that's ok
|
||||
|
||||
class Main {
|
||||
// All returns must be empty, but we don't care for their existence
|
||||
void main() {
|
||||
int a, b, c;
|
||||
if (a == b) {
|
||||
return;
|
||||
} else {
|
||||
while (a > b) {
|
||||
return;
|
||||
}
|
||||
if (c > b) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All returns must be null, Main (all subtypes of Main), and there must be an unconditional return
|
||||
Main action1() {
|
||||
Main a;
|
||||
Object b;
|
||||
boolean x, y;
|
||||
if (x) {
|
||||
if (y) {
|
||||
if (x || y) {
|
||||
if (x == y && x != y) {
|
||||
return null;
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
} else {
|
||||
if (b == null) {
|
||||
return a;
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (b == a || a == null) {
|
||||
return null;
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// All returns must be null, Main[] (all subtypes of Main[]), and there must be an unconditional return
|
||||
Main[] action2() {
|
||||
Main[] a, b;
|
||||
if (a == b) {
|
||||
return a;
|
||||
} else {
|
||||
if (b != null) {
|
||||
return b;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All returns must be int (no subtypes), and there must be an unconditional return
|
||||
int action3() {
|
||||
int a, b, c, d;
|
||||
if (a > b) {
|
||||
return c - d;
|
||||
while (a != a) {
|
||||
return b;
|
||||
}
|
||||
} else {
|
||||
return c * d / a + b % c - a;
|
||||
}
|
||||
}
|
||||
}
|
21
javali_tests/HW3_nop90/ReturnTests/OkMiddleReturn.javali
Normal file
21
javali_tests/HW3_nop90/ReturnTests/OkMiddleReturn.javali
Normal file
|
@ -0,0 +1,21 @@
|
|||
// The return statement can be placed in the middle of the method, and no warning will be thrown about unexecuted
|
||||
// statements
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
write(things());
|
||||
writeln();
|
||||
}
|
||||
|
||||
int things() {
|
||||
int a;
|
||||
a = 10;
|
||||
return a;
|
||||
|
||||
// These statements won't be reached
|
||||
// but there is a complete return statement
|
||||
a = 20;
|
||||
writeln();
|
||||
writeln();
|
||||
}
|
||||
}
|
24
javali_tests/HW3_nop90/ReturnTests/OkSimpleIfElse.javali
Normal file
24
javali_tests/HW3_nop90/ReturnTests/OkSimpleIfElse.javali
Normal file
|
@ -0,0 +1,24 @@
|
|||
// A if/else with a return in both branches is valid
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
write(things());
|
||||
writeln();
|
||||
}
|
||||
|
||||
int things() {
|
||||
int a;
|
||||
int b;
|
||||
Object c, d;
|
||||
a = 10;
|
||||
b = 100;
|
||||
c = new Object();
|
||||
d = new Object();
|
||||
|
||||
if (c == d) {
|
||||
return 10;
|
||||
} else {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
}
|
12
javali_tests/HW3_nop90/TypeErrors/ArrayIndex.javali
Normal file
12
javali_tests/HW3_nop90/TypeErrors/ArrayIndex.javali
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Test type errors when accessing an Array
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean x;
|
||||
int y;
|
||||
int [] testArray;
|
||||
testArray = new int[10];
|
||||
|
||||
y = testArray[x];
|
||||
}
|
||||
}
|
22
javali_tests/HW3_nop90/TypeErrors/CastUnrelatedType.javali
Normal file
22
javali_tests/HW3_nop90/TypeErrors/CastUnrelatedType.javali
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Test types in a Cast (cannot cast to unrelated type)
|
||||
// Casts to primitive types and arrays are controlled by the parser
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
C1 a, b;
|
||||
C2 c, d;
|
||||
Object o;
|
||||
c = new C2();
|
||||
a = new C1();
|
||||
|
||||
b = (C1) c;
|
||||
d = (C2) a;
|
||||
o = (Object) a;
|
||||
o = (Object) c;
|
||||
o = (Main) c;
|
||||
}
|
||||
}
|
||||
|
||||
class C1 {}
|
||||
|
||||
class C2 extends C1{}
|
9
javali_tests/HW3_nop90/TypeErrors/ConditionIf.javali
Normal file
9
javali_tests/HW3_nop90/TypeErrors/ConditionIf.javali
Normal file
|
@ -0,0 +1,9 @@
|
|||
// The condition of an if statement must be an int
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
if (null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
7
javali_tests/HW3_nop90/TypeErrors/ConditionWhile.javali
Normal file
7
javali_tests/HW3_nop90/TypeErrors/ConditionWhile.javali
Normal file
|
@ -0,0 +1,7 @@
|
|||
// The condition of a while must be an boolean
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
while (null) {}
|
||||
}
|
||||
}
|
8
javali_tests/HW3_nop90/TypeErrors/IndexObjectType.javali
Normal file
8
javali_tests/HW3_nop90/TypeErrors/IndexObjectType.javali
Normal file
|
@ -0,0 +1,8 @@
|
|||
// A object (non-array) type cannot be indexed
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
Object a;
|
||||
a[1] = new Object();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// A primitive type cannot be indexed
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int a;
|
||||
a[1] = 10;
|
||||
}
|
||||
}
|
8
javali_tests/HW3_nop90/TypeErrors/NewArraySize.javali
Normal file
8
javali_tests/HW3_nop90/TypeErrors/NewArraySize.javali
Normal file
|
@ -0,0 +1,8 @@
|
|||
// The size for a new array declaration must be an int
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
Object[] array;
|
||||
array = new Object[array];
|
||||
}
|
||||
}
|
10
javali_tests/HW3_nop90/TypeErrors/WriteArg.javali
Normal file
10
javali_tests/HW3_nop90/TypeErrors/WriteArg.javali
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Test type error in write() statement
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean a;
|
||||
a = true;
|
||||
write(10);
|
||||
write(a);
|
||||
}
|
||||
}
|
24
javali_tests/from_prev_HW/Arrays.javali
Normal file
24
javali_tests/from_prev_HW/Arrays.javali
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* testing arrays with primitive types as well as new objects
|
||||
the if/else statements shows that the array is boolean array is initialized with false
|
||||
*/
|
||||
class Main {
|
||||
void main() {
|
||||
int [] testArray;
|
||||
boolean [] boolarray;
|
||||
|
||||
boolarray = new boolean [3];
|
||||
testArray = new int [10];
|
||||
|
||||
testArray[5] = 3;
|
||||
boolarray[1] = true;
|
||||
|
||||
if (boolarray[0]){
|
||||
write(1);}
|
||||
else{
|
||||
write(5);}
|
||||
writeln();
|
||||
if (boolarray[1]){
|
||||
write(1);}
|
||||
|
||||
}
|
||||
}
|
12
javali_tests/from_prev_HW/Assignments.javali
Normal file
12
javali_tests/from_prev_HW/Assignments.javali
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* testing assign statements*/
|
||||
class Main {
|
||||
void main() {
|
||||
a = read();
|
||||
b = methodCall();
|
||||
c = methodCall(param1, param2);
|
||||
d = object.access;
|
||||
e = new Ast();
|
||||
d = new int[size];
|
||||
f = new Object[size];
|
||||
}
|
||||
}
|
16
javali_tests/from_prev_HW/Casts.javali
Executable file
16
javali_tests/from_prev_HW/Casts.javali
Executable file
|
@ -0,0 +1,16 @@
|
|||
/* testing casting as well as creating new Objects*/
|
||||
class Main
|
||||
{
|
||||
void main()
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
Object c;
|
||||
Object d;
|
||||
|
||||
c = null;
|
||||
d = new Object();
|
||||
a = 10;
|
||||
c = (Object) d;
|
||||
}
|
||||
}
|
21
javali_tests/from_prev_HW/Division.javali
Executable file
21
javali_tests/from_prev_HW/Division.javali
Executable file
|
@ -0,0 +1,21 @@
|
|||
class Main {
|
||||
void main() {
|
||||
int a, b, c, d, e;
|
||||
|
||||
a = 10;
|
||||
b = -1;
|
||||
c = 0;
|
||||
d = 100;
|
||||
e = 2;
|
||||
|
||||
write(a / b); writeln();
|
||||
write(d / e); writeln();
|
||||
write(c / d); writeln();
|
||||
write(b / a + c); writeln();
|
||||
write(d / e * a / b * c); writeln();
|
||||
write(d / e * a / b); writeln();
|
||||
write(d / e + a / b); writeln();
|
||||
write(d / e * a * b * c); writeln();
|
||||
write(d / e * a - b + c); writeln();
|
||||
}
|
||||
}
|
9
javali_tests/from_prev_HW/DoubleInheritance.javali
Normal file
9
javali_tests/from_prev_HW/DoubleInheritance.javali
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* testing basic inheritance*/
|
||||
class C1 {}
|
||||
class C2 extends C1 {}
|
||||
class C3 extends C2 {}
|
||||
class C4 extends C2 {}
|
||||
class C5 extends C3 {}
|
||||
class Main {
|
||||
void main() {}
|
||||
}
|
20
javali_tests/from_prev_HW/EightVariablesWrite.javali
Executable file
20
javali_tests/from_prev_HW/EightVariablesWrite.javali
Executable file
|
@ -0,0 +1,20 @@
|
|||
/* Test expression evaluation with 8 variables */
|
||||
class Main {
|
||||
void main() {
|
||||
int r1, r2, r3;
|
||||
int i0, i1, i2, i3, i4, i5, i6, i7;
|
||||
|
||||
i0 = 0;
|
||||
i1 = 1;
|
||||
i2 = 2;
|
||||
i3 = 3;
|
||||
i4 = 4;
|
||||
i5 = 5;
|
||||
i6 = 6;
|
||||
i7 = 7;
|
||||
|
||||
write(i0 + (i1 + ( i2 + ( i3 + ( i4 + (i5 + (i6 + i7))))))); writeln();
|
||||
write(((((((i0 + i1) + i2) + i3) + i4) + i5) + i6) + i7); writeln();
|
||||
write(((i0 + i1) + (i2 + i3)) + ((i4 + i5) + (i6 + i7))); writeln();
|
||||
}
|
||||
}
|
22
javali_tests/from_prev_HW/Expressions.javali
Normal file
22
javali_tests/from_prev_HW/Expressions.javali
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* testing different expressions
|
||||
compiler should recognize Type error: Return statement of method with void return type should not have arguments
|
||||
*/
|
||||
class Main {
|
||||
void main() {
|
||||
return;
|
||||
return true;
|
||||
return false;
|
||||
return 0x10;
|
||||
return 10;
|
||||
return variable;
|
||||
return array[index];
|
||||
return methodAccess();
|
||||
return object.field;
|
||||
return object.call();
|
||||
return op + op2;
|
||||
return op / asd * asd && a == true;
|
||||
return this.run();
|
||||
return this;
|
||||
return this.field;
|
||||
}
|
||||
}
|
31
javali_tests/from_prev_HW/Multiplication.javali
Executable file
31
javali_tests/from_prev_HW/Multiplication.javali
Executable file
|
@ -0,0 +1,31 @@
|
|||
class Main {
|
||||
void main() {
|
||||
int r1;
|
||||
int i0, i1;
|
||||
int x,y,z;
|
||||
|
||||
i0 = 5;
|
||||
i1 = 2;
|
||||
|
||||
r1 = i1 * 3;
|
||||
write(r1); writeln();
|
||||
|
||||
r1 = i0 * i1;
|
||||
write(r1); writeln();
|
||||
|
||||
r1 = r1 * i0 * i1 * 3;
|
||||
write(r1); writeln();
|
||||
|
||||
y = 5;
|
||||
z = 10;
|
||||
x = (-y * z);
|
||||
write(x); writeln();
|
||||
|
||||
y = 0;
|
||||
z = - 10;
|
||||
x = (y * z);
|
||||
write(x); writeln();
|
||||
write(y * z); writeln();
|
||||
write(0 * -10); writeln();
|
||||
}
|
||||
}
|
20
javali_tests/from_prev_HW/NULLTest.javali
Executable file
20
javali_tests/from_prev_HW/NULLTest.javali
Executable file
|
@ -0,0 +1,20 @@
|
|||
/* testing null references:
|
||||
assigning null to an int or a boolean results in an error
|
||||
write(null) results in a parser failure
|
||||
*/
|
||||
class Main {
|
||||
void main() {
|
||||
int a;
|
||||
boolean b;
|
||||
Object c;
|
||||
|
||||
a = null;
|
||||
b = null;
|
||||
c = null;
|
||||
|
||||
write(a);
|
||||
writeln();
|
||||
//write(null)
|
||||
|
||||
}
|
||||
}
|
8
javali_tests/from_prev_HW/OrderOfDeclarations.javali
Normal file
8
javali_tests/from_prev_HW/OrderOfDeclarations.javali
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*Check the order of the declarations in the generated parser
|
||||
* Do the variables come always first or in their place? */
|
||||
class ClassName {
|
||||
void a() {}
|
||||
int a;
|
||||
void a() {}
|
||||
void tests(boolean d, nulle a) {}
|
||||
}
|
25
javali_tests/from_prev_HW/Overflow.javali
Executable file
25
javali_tests/from_prev_HW/Overflow.javali
Executable file
|
@ -0,0 +1,25 @@
|
|||
/* Test what happens for Integers that are to big for 32bits
|
||||
2147483647 (=0x7FFFFFFF) is the biggest integer in 32bits (IntMAX)
|
||||
*/
|
||||
class Main {
|
||||
void main() {
|
||||
int x,y,z;
|
||||
x = 2147483647;
|
||||
write( x ); writeln();
|
||||
/* add 1 to IntMax and output it */
|
||||
write( x + 1); writeln();
|
||||
|
||||
/* read an int bigger than IntMAX */
|
||||
x = read();
|
||||
write(x); writeln();
|
||||
|
||||
/* performe some operation that should generate an int overflow */
|
||||
x = 21474836400;
|
||||
y = 60000;
|
||||
write( x + y); writeln();
|
||||
z = 20000000;
|
||||
write( y * z); writeln();
|
||||
write( (y * z) ); writeln();
|
||||
|
||||
}
|
||||
}
|
1
javali_tests/from_prev_HW/Overflow.javali.in
Executable file
1
javali_tests/from_prev_HW/Overflow.javali.in
Executable file
|
@ -0,0 +1 @@
|
|||
2147483647
|
15
javali_tests/from_prev_HW/ParamLists.javali
Normal file
15
javali_tests/from_prev_HW/ParamLists.javali
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*Testing all related to methods (declaration and execution)*/
|
||||
class Main {
|
||||
void main() {
|
||||
callWithParams(a, b, c, 0, false);
|
||||
object.call(a, b, d);
|
||||
}
|
||||
|
||||
int method(int a, String b, int[] c) {
|
||||
|
||||
}
|
||||
|
||||
int[] method2() {}
|
||||
Object method3() {}
|
||||
Model[] method4() {}
|
||||
}
|
26
javali_tests/from_prev_HW/ReadWrite.javali
Executable file
26
javali_tests/from_prev_HW/ReadWrite.javali
Executable file
|
@ -0,0 +1,26 @@
|
|||
/* Test read/write native functions */
|
||||
class Main {
|
||||
void main() {
|
||||
int r1, r2, readvar, a1;
|
||||
|
||||
r1 = 6;
|
||||
/* r2 = 22 */
|
||||
r2 = read();
|
||||
|
||||
write(r1); writeln(); // 6
|
||||
|
||||
/* test expressions inside write() */
|
||||
write(r1 - 3); writeln(); // 3
|
||||
write(r1 - 6); writeln(); // 0
|
||||
write(r1 - 7); writeln(); // -1
|
||||
/* should output 111 */
|
||||
readvar = read(); // 1
|
||||
write( (r1 + (r2 * 5)) + readvar); // 117
|
||||
write(- r1); // -6
|
||||
writeln();
|
||||
/* should output 15 */
|
||||
a1 = read(); // -15
|
||||
write(- a1); // 15
|
||||
|
||||
}
|
||||
}
|
6
javali_tests/from_prev_HW/ReadWrite.javali.in
Executable file
6
javali_tests/from_prev_HW/ReadWrite.javali.in
Executable file
|
@ -0,0 +1,6 @@
|
|||
22
|
||||
|
||||
|
||||
1
|
||||
|
||||
-15
|
34
javali_tests/from_prev_HW/Statements.javali
Normal file
34
javali_tests/from_prev_HW/Statements.javali
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* testing different statements
|
||||
'condition' is not initialized
|
||||
*/
|
||||
class Main {
|
||||
void main() {
|
||||
if (condition) {
|
||||
instructions();
|
||||
asd.b = c;
|
||||
if (cond2) {
|
||||
|
||||
} else {
|
||||
nonEmptyBlock = a;
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
// Whiles
|
||||
while (condition) {
|
||||
while (anotherLoop == false) {
|
||||
nestedLoops();
|
||||
}
|
||||
}
|
||||
while (false) {} // emptyloop
|
||||
// Returns
|
||||
return; // empty
|
||||
return expr; // with expressions (expressions already tested)
|
||||
return array[index];
|
||||
// Writes
|
||||
write(a);
|
||||
write(9 + 10);
|
||||
writeln();
|
||||
write(call());
|
||||
}
|
||||
}
|
15
javali_tests/from_prev_HW/UnaryOperators.javali
Executable file
15
javali_tests/from_prev_HW/UnaryOperators.javali
Executable file
|
@ -0,0 +1,15 @@
|
|||
class Main {
|
||||
void main() {
|
||||
int a, b;
|
||||
|
||||
a = 1;
|
||||
b = 2;
|
||||
|
||||
write(+a); writeln();
|
||||
write(-a); writeln();
|
||||
write(+a --b); writeln();
|
||||
write(-a--b); writeln();
|
||||
write(-----a-----5--b); writeln();
|
||||
write(-----a*---------b);writeln();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue