// compile all test files using:
// ls Test/JavaSources/*.java | grep -v ".*Main.java" | xargs -I {} cabal run compiler {}
// compile (in project root) using:
// pushd Test/JavaSources; javac -g:none Main.java; popd
// afterwards, run using
// java -ea -cp Test/JavaSources/ Main

public class Main {
    public static void main(String[] args)
    {
        TestEmpty empty = new TestEmpty();
        TestFields fields = new TestFields();
        TestConstructor constructor = new TestConstructor(42);
        TestArithmetic arithmetic = new TestArithmetic();
        TestMultipleClasses multipleClasses = new TestMultipleClasses();
        TestRecursion recursion = new TestRecursion(10);
        TestMalicious malicious = new TestMalicious();
        TestLoop loop = new TestLoop();
        TestMethodOverload overload = new TestMethodOverload();
        TestShenanigance shenanigance = new TestShenanigance();
        TestOptionalParameter optionalParameter = new TestOptionalParameter();
        
        // constructing a basic class works
        assert empty != null;
        // initializers (and default initializers to 0/null) work
        assert fields.a == 0 && fields.b == 42;
        // constructor parameters override initializers
        assert constructor.a == 42;
        // basic arithmetics
        assert arithmetic.basic(1, 2, 3) == 2;
        // we have boolean logic as well
        assert arithmetic.logic(false, false, true) == true;
        // multiple classes within one file work. Referencing another classes fields/methods works.
        assert multipleClasses.a.a == 42;
        // self-referencing classes work.
        assert recursion.child.child.child.child.child.value == 5;
        // self-referencing methods work.
        assert recursion.fibonacci(15) == 610;
        assert loop.factorial(5) == 120;
        assert loop.weirdFor() == 5;
        // methods with the same name but different parameters work
        assert overload.MethodOverload() == 42;
        assert overload.MethodOverload(15) == 42 + 15;
        // constructor overloading works, too.
        assert (new TestConstructorOverload()).a == 42;
        assert (new TestConstructorOverload(12)).a == 12;
        // intentionally dodgy expressions work
        assert malicious.assignNegativeIncrement(42) == -42;
        assert malicious.tripleAddition(1, 2, 3) == 6;
        for(int i = 0; i < 3; i++)
        {
            assert malicious.cursedFormatting(i) == i;
        }
        // other syntactic sugar
        assert shenanigance.testAssignment() == 5;
        assert shenanigance.divEqual() == 234_343_000 / 4;
        assert shenanigance.testIf(5);
        // optional parameters
        assert optionalParameter.oneOptional() == 1;
        assert optionalParameter.oneOptional(2) == 2;
        assert optionalParameter.normalAndOptional(1) == 6;
        assert optionalParameter.normalAndOptional(1, 0) == 4;
    }
}