Homework 3

This commit is contained in:
Carlos Galindo 2020-01-15 22:32:25 +01:00
parent bf60a078d7
commit 0afc86ceeb
Signed by: kauron
GPG key ID: 83E68706DEE119A3
129 changed files with 3163 additions and 4316 deletions

View file

@ -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 {}

View file

@ -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;
}
}

View file

@ -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;
}

View 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;
}
}

View file

@ -0,0 +1,8 @@
// Multiple classes can't share the same name
class Aclass {}
class Aclass {}
class Main {
void main() {}
}

View file

@ -0,0 +1,8 @@
// Two fields in a class cannot share the same name
class Main {
void main() {}
int a;
Object b;
Main a;
}

View file

@ -0,0 +1,8 @@
// Two local variables in a method cannot share the same name
class Main {
void main() {}
void test() {
int a, a;
}
}

View file

@ -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;
}
}

View file

@ -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) {}
}

View file

@ -0,0 +1,7 @@
// No class can have the name "Object"
class Aclass {}
class Object extends Aclass {}
class Main extends Object {
void main() {}
}

View file

@ -0,0 +1,7 @@
// Error: the return type of the "main" method must be "void"
class Main {
int main() {
return 10;
}
}

View file

@ -0,0 +1,5 @@
// Error: the main method must have no arguments
class Main {
void main(Object[] args) {}
}

View file

@ -0,0 +1,4 @@
// Error: there is no class called Main (case-sensitive)
class MAIN {}
class main extends Object {}

View file

@ -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() {}
}

View file

@ -0,0 +1,7 @@
// The main method can be inherited from another class
class OtherMain {
void main () {}
}
class Main extends OtherMain {}

View file

@ -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 {}

View file

@ -0,0 +1,7 @@
// Methods cannot be overloaded
class Main {
void main() {}
void method(int a) {}
void method(int[] a) {}
}

View 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 {}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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{}

View file

@ -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 {}

View file

@ -0,0 +1,5 @@
// Test inheritance of itself
class Main extends Main {
void main() {}
}

View file

@ -0,0 +1,7 @@
// Simple circular inheritance loop
class Main extends Other {
void main() {}
}
class Other extends Main {}

View file

@ -0,0 +1,10 @@
// Inherited methods cannot be overloaded
class Main extends Other {
void main() {}
void method(int a) {}
}
class Other {
void method() {}
}

View 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);
}
}
}
}

View file

@ -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 {}

View 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;
}
}

View file

@ -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() {}
}

View file

@ -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() {}
}

View file

@ -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() {}
}

View file

@ -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() {}
}

View file

@ -0,0 +1,8 @@
// An array doesn't have methods
class Main {
Object[] array;
void main() {
array.go();
}
}

View file

@ -0,0 +1,8 @@
// A primitive variable doesn't have methods
class Main {
int a;
void main() {
a.go();
}
}

View file

@ -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) {}
}

View file

@ -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) {}
}

View file

@ -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() {}
}

View file

@ -0,0 +1,6 @@
// No such type in method body (handled by TypeGenerator)
class Main {
void method(NoSuchType param) {}
void main() {}
}

View file

@ -0,0 +1,5 @@
// No such type in method body (handled by checkCircularInheritance)
class Main extends NoSuchType {
void main() {}
}

View file

@ -0,0 +1,8 @@
// No such type in method body (handled by ExprVisitor and StmtVisitor)
class Main {
void main() {
Object a;
write((NoType) a);
}
}

View file

@ -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;
}
}

View 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() {
}
}

View 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 {
}

View file

@ -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 );
}
}

View file

@ -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;
}
}

View 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 {}

View 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);
}
}

View file

@ -0,0 +1,8 @@
// Test boolean && and || operators
class Main {
void main() {
boolean a, b, c;
a = b && c || a;
}
}

View 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{}

View 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;
}
}
}

View file

@ -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() {}
}

View file

@ -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;
}
}
}

View file

@ -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
}
}

View 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;
}
}

View file

@ -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;
}
}
}
}
}
}

View file

@ -0,0 +1,11 @@
// Test return statement in while loop
class Main {
void main() {}
int aux() {
while (true) {
return 1;
}
}
}

View file

@ -0,0 +1,7 @@
// A method that returns void can't have a return with an argument
class Main {
void main() {
return 3;
}
}

View file

@ -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;
}
}
}

View 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();
}
}

View 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;
}
}
}

View 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];
}
}

View 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{}

View file

@ -0,0 +1,9 @@
// The condition of an if statement must be an int
class Main {
void main() {
if (null) {
return;
}
}
}

View file

@ -0,0 +1,7 @@
// The condition of a while must be an boolean
class Main {
void main() {
while (null) {}
}
}

View file

@ -0,0 +1,8 @@
// A object (non-array) type cannot be indexed
class Main {
void main() {
Object a;
a[1] = new Object();
}
}

View file

@ -0,0 +1,8 @@
// A primitive type cannot be indexed
class Main {
void main() {
int a;
a[1] = 10;
}
}

View 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];
}
}

View file

@ -0,0 +1,10 @@
// Test type error in write() statement
class Main {
void main() {
boolean a;
a = true;
write(10);
write(a);
}
}