(* Example cool program testing as many aspects of the code generator as possible. *) class A inherits IO { attr_A_1 : Int <- 10; attr_A_2 : Bool <- false; attr_A_3 : A <- self; method_common(x1: Int) : SELF_TYPE { self }; method_common2() : String { "A" }; }; class B inherits A { }; class C inherits A { attr_C_2 : SELF_TYPE; attr_C_0 : Int <- 10; attr_C_1 : String <- "This is C\n".concat(new A.method_common2()); attr_C_3 : Int <- "12345".length(); attr_C_4 : Bool <- "12345".length() = 5; method_common(x1: Int) : SELF_TYPE { self }; method_common2() : String { "C" }; method_1(x1: Int) : Bool { true }; method_3(x1: Int, x2: A, x3: String) : Object { { x1 <- x1 + 00010 - x1 / 10; x2 <- x2.method_common(x1); x3 <- x3.concat("schade"); } }; method_2(x1: Bool, x2: C) : Object { { if (x1) then x2 <- x2.method_common(20) else "hello world" fi; } }; }; class D inherits C { method_common(x1: Int) : SELF_TYPE { self }; method_new() : D { new D }; method_new_SELF() : D { new SELF_TYPE }; method_new2() : Object { (new SELF_TYPE).method_2(false, self) }; method_staticdispath() : Object { (new SELF_TYPE)@D.method_2(false, self) }; method_case(x1 : Object) : Int { case (x1) of t1: Bool => 1; t2: Int => t2 + 100; t3: String => 3; t4: Object => 4; t5: A => 5; t6: C => 6; t7: B => 7; t8: D => 8; t9: E => 9; esac }; }; class E { method_compare(x1: Int, x2: Int) : Bool { x1 < x2 }; method_compare_eq(x1: String, x2: String) : Bool { x1 = x2 }; method_compare_eq2(x1: D, x2: D) : Bool { x1 = x2 }; method_not(x1: Bool) : Bool { not x1 }; method_isvoid(x1: Object) : Bool { isvoid x1 }; method_let1(x1: Int) : Object { let x2 : Int <- x1 + 10 in x2 <- x1 }; method_let2(x1: Int) : Object { let x2 : Int <- x1 in x2 <- x1 + 100 }; method_2(x1: Bool, x2: C) : Object { { if (x1) then x2 <- x2.method_common(20) else "hello world" fi; } }; method_SELF() : SELF_TYPE { self }; }; class Main inherits IO { main():Int { 0 }; };