fail-conversion1.ma
==========
# test number to matrix conversion 
number a;

matrix b <- [ 1, 2, 3; 8+9, 4-2, 4]; 

a <- b;  # should fail 

---
Fatal error: exception Failure("number type expected from b!")
---

fail-conversion2.ma
==========
# test string to number conversion
number failedNum <- 5;

string failedString;
failedString <- "num to string fail";

failedNum <- failedString;  # should return error

---
Fatal error: exception Failure("number type expected from failedString!")
---

fail-conversion3.ma
==========
# test string to matrix conversion 

string failedStringMatrix;
failedStringMatrix <- "[ 1, 2, 3; 8+9, 4-2, 4]";
matrix faildString;

faildString <- failedStringMatrix; # should return error message

---
Fatal error: exception Failure("matrix type expected from failedStringMatrix!")
---

fail-declaration1.ma
==========
# test number declaration

number Num <- "15"; #should return error message

---
Fatal error: exception Failure("number type expected from "15"!")
---

fail-declaration2.ma
==========
#test string declaration
string s1 <- hi; #should return error message

---
Fatal error: exception Failure("Use of undeclared variable hi!")

---

fail-declaration3.ma
==========
#test matrix declaration

matrix b <- [ 1, 2, 3;; 8+9, 4-2, 4];  #should return error message

---
Fatal error: exception Parsing.Parse_error
---

fail-declaration4.ma
==========
# can't declare void variables!

void foo;

print("HELLO!");

---
Fatal error: exception Failure("Illegal void variable foo!")

---

fail-declaration5.ma
==========
# jagged matrix!

matrix b <- [1,2,3,4;1,2,3];

print(b);

---
Fatal error: exception Failure("Matrix initialization cannot be jagged! 1, 2, 3, 4; 1, 2, 3")
---

fail-expressions1.ma
==========
# testing failing matrix access

string a <- "Hello World";

matrix b <- [1,2,3;a,5,6];

print(b[4]);


---
Fatal error: exception Failure("Only number type allowed in matrix init block. string used!")
---

fail-expressions2.ma
==========
# failing test for expressions, cannot have booleans in print statements

number a <- 1;

number b <- 1;

print(a&b);
---
Logical operators only work with integral types!
  %tmp = and double %a, %b
LLVM ERROR: Broken module found, compilation aborted!

---

fail-expressions3.ma
==========
# failing test for expressions, cannot have booleans in print statements

number a <- 1;

number b <- 1;

print(a|b);
---
Logical operators only work with integral types!
  %tmp = or double %a, %b
LLVM ERROR: Broken module found, compilation aborted!

---

fail-expressions4.ma
==========
# failing test for unary expressions, logical not 

number a <- 1;

if (!a = 0){
	print("Success");
} 



---
Logical operators only work with integral types!
  %tmp = xor double %a, 0xFFFFFFFFFFFFFFFF
LLVM ERROR: Broken module found, compilation aborted!

---

fail-expressions5.ma
==========
#testing string expressions, cannot print double quotes, only single quotes 

print("""");
---
Fatal error: exception Parsing.Parse_error

---

fail-expressions6.ma
==========
# testing expressions, newline 

print("
");
---
Fatal error: exception Parsing.Parse_error

---

fail-expressions7.ma
==========
# testing relational operator, cannot be chained 

number a <- 1;

number b <- 2;

number c <- 3;

if ( a<b<c ){
	print("Success");
}
---
Fatal error: exception Parsing.Parse_error

---

fail-expressions8.ma
==========
# failing test with string and matrix types

matrix a <- [1,2,3; 4,5,6];

string b <- "Hello World";

a[4] <- b;

print(a[4]);


---
Fatal error: exception Failure("number type expected from b!")

---

fail-functions1.ma
==========
# failed function overloading
# identical signatures

void foo(string s) {
	print(s);
}

void foo(string s) {
	print(s);
}

print("I shouldn't be printed!");
---
Fatal error: exception Failure("Duplicate function foo(string)!")
---

fail-functions11.ma
==========
# multiple returns from functions!

number foo() {
    return 0;
    return 1;
}

print("YOU SHALL NOT PASS!");

---
Fatal error: exception Failure("No statements are allowed after return inside a block!")
---

fail-functions12.ma
==========
# Parsing error when declaring on return!

number foo() {
    return number a;
}

print(a);

---
Fatal error: exception Parsing.Parse_error

---

fail-functions13.ma
==========
# referencing an undeclared variable in a function!
# variable declared after function 

void foo(string s) {
    print(a + 5);
    print(s);
}

foo("NOPE!");
number a <- 10;

---
Fatal error: exception Failure("Use of undeclared variable a!")

---

fail-functions2.ma
==========
# defining a shape function
# overriding a system call isn't allowed

matrix shape(matrix a) {
	print(a);

	return shape(a);
}

matrix b <- shape([](5, 6));

print(5);
---
Fatal error: exception Failure("Duplicate function shape(matrix)!")
---

fail-functions3.ma
==========
# no return type specified in function declaration

foo() {
	number a <- 5;
	return a;
}

number a <- foo();
---
Fatal error: exception Parsing.Parse_error
---

fail-functions4.ma
==========
# declare a return type but return something else!
# LOL

number foo(number a, number b) {
	return [](5, 6);
}

number a <- foo(6, 6);
---
Fatal error: exception Failure("number type expected from [ ](5, 6)!")

---

fail-functions5.ma
==========
number foo(string s) {
    print(s);
    return 1;
}

void foo(string s) {
    print(s);
}

number a <- foo("hello");
number b <- foo("world");
---
Fatal error: exception Failure("Duplicate function foo(string)!")
---

fail-functions6.ma
==========
# function return doesn't match return type!

number foo(string s) {
	matrix b <- [](5, 6);

	return b;
}

print("Hello!");
---
Fatal error: exception Failure("number type expected from b!")
---

fail-functions7.ma
==========
# assignment on return not right!

number foo(number a) {
	return a;
}

matrix b <- foo(5);
---
Fatal error: exception Failure("matrix type expected from foo_number(5)!")
---

fail-functions8.ma
==========
# foo should not return anything!

void foo() {
	return 0;
}

number a <- foo();

print(a);
---
Fatal error: exception Failure("number type expected from foo_()!")
---

fail-functions9.ma
==========
# can't call functions before they're declared!

foo();

void foo() {
    print("YO!");
}

---
Fatal error: exception Failure("Use of undeclared function foo!")

---

fail-overload1.ma
==========
# too many variables!

number operator .* (number a, number b, number c) {
	return a + b + c;
}

print(5 .* 7 .* 3);
---
Fatal error: exception Failure("Use of unknown operator number .* number!")
---

fail-overload2.ma
==========
# declare overloaded operator, called with wrong types

number operator .* (number a, number b) {
	return a + b;	
}

string s <- "Hello!";
number b <- 6;

print(s .* b);
---
Fatal error: exception Failure("Use of unknown operator string .* number!")

---

fail-overload3.ma
==========
# same function signatures!

number operator ^ (number a, number b) {
	return a * b;
}

number operator ^ (number a, number b) {
	return a * b;
}

print("Don't see me!");
---
Fatal error: exception Failure("Duplicate function _pow(number,number)!")

---

fail-parser1.ma
==========
# invalid keyword!

int a;
---
Fatal error: exception Parsing.Parse_error
---

fail-parser2.ma
==========
# if statements always require brackets!

number a <- 10;

if (a = 10)
	print("Nope.");
---
Fatal error: exception Parsing.Parse_error
---

fail-parser3.ma
==========
# no semi-colons :(

void foo() {
	print("hello");
}

foo()
---
Fatal error: exception Parsing.Parse_error
---

fail-parser4.ma
==========
# capitalization matters!

String s <- "Hello World";

print(s);
---
Fatal error: exception Parsing.Parse_error
---

fail-parser5.ma
==========
# for loops also must be in brackets!

matrix a <- [1;2;3;4;5;5];

for (number b in a)
	print(b);
---
Fatal error: exception Parsing.Parse_error
---

fail-parser6.ma
==========
# while loops must be in brackets!

while (1 = 1)
	print("I'm stuck!");
---
Fatal error: exception Parsing.Parse_error
---

fail-scope1.ma
==========
# testing different function scopes

number a(){
    number first <- 6;
    print (first); # function a scope, prints 6
}

number b(){
    print (first); # failed test: can't find "first"
}
---
Fatal error: exception Failure("Use of undeclared variable first!")

---

fail-scope2.ma
==========
# failing scope test 

string a() {

	string s;
    s <- "6";
    print (s); # function a scope, prints "6"

}

string b(){
    print (s); # failed:can't find s
}

---
Fatal error: exception Failure("Use of undeclared variable s!")

---

fail-scope3.ma
==========
# testing scoping with matrices

matrix a(){
    matrix m <- [1,2];
    print (m); # function a scope, prints [1,2]
}

matrix b(){
    print (m); # failed:can't find m
}

---
Fatal error: exception Failure("Use of undeclared variable m!")

---

fail-statements1.ma
==========
# main program returns void, so this shouldn't be allowed.

number a;
a <- 5;

return a;
---
Fatal error: exception Failure("void type expected from a!")

---

fail-statements2.ma
==========
# numbers don't evaluate to anything

while (1) {
	print("yep.");
}
---
Branch condition is not 'i1' type!
  br double 1.000000e+00, label %while_body, label %merge
double 1.000000e+00
LLVM ERROR: Broken module found, compilation aborted!
---

fail-statements3.ma
==========
# string equality doesn't work.

string s <- "Hello!";

while (s = "Hello!") {
	print("Yep!");
	s <- "Nope.";
}
---
Fatal error: exception Failure("Use of unknown operator string = string!")
---

fail-statements4.ma
==========
# nested ifs must be in else blocks!

number b <- 99;

if (b = 88) {
	print(b);
} else if {
	print("Nope.");
}
---
Fatal error: exception Parsing.Parse_error
---

fail-statements5.ma
==========
# flipping numbers and matrix in for loop

number a;
matrix b <- [1;2;3;4;5];

for (b in a) {
	print(b);
}

---
Fatal error: exception Failure("check_expr_typ: Can't find len_number")
---

fail-statements6.ma
==========
# flipping numbers and matrix in for loop
# define a len_number function

number len(number b) {
	return b;
}

number a;
matrix b <- [1;2;3;4;5];

for (b in a) {
	print(b);
}

---
Fatal error: exception Failure("matrix type expected from a[_tmp_for_i18, 0]!")
---

fail-statements7.ma
==========
# Cannot chain relational operators!

number a <- 10;

if ((a = 10) = 1) {
	print("Nope.");
}
---
Both operands to FCmp instruction are not of the same type!
  %tmp1 = fcmp oeq i1 %tmp, double 1.000000e+00
LLVM ERROR: Broken module found, compilation aborted!
---

test-conversion1.ma
==========
# test number to number conversion
number successNum <- 15;
number number2 <- 35;

successNum <- number2;  

print(successNum); #should print 35

---
35.000

---

test-conversion2.ma
==========
# test string to string conversion 

string successString <- "Failure";
string string2 <- "Success";

successString <- string2;

print(successString); # should print "Success"


---
Success
---

test-conversion3.ma
==========
#test matrix to matrix conversion

matrix successMatrix <- [ 1, 2, 3; 8+9, 4-2, 4];
matrix matrix2 <- [ 2, 1, 5; 10, 9, 8; 500-3, 1234, 100];

successMatrix <- matrix2;

print(successMatrix); # should print out [ 2, 1, 5; 10, 9, 8; 500-3, 1234, 100];







---
2.000, 1.000, 5.000; 
10.000, 9.000, 8.000; 
497.000, 1234.000, 100.000; 

---

test-declaration1.ma
==========
# test number declaration 

number Num1 <- 15; 

print(Num1); #should print 15 


---
15.000

---

test-declaration2.ma
==========
#test string declaration 

string s <- "hi"; 

print(s); #should print "hi"


---
hi
---

test-declaration3.ma
==========
#test matrix declaration

matrix b <- [ 1, 2, 3; 8+9, 4-2, 4];

print(b); #should print [ 1, 2, 3; 17, 2, 4];


---
1.000, 2.000, 3.000; 
17.000, 2.000, 4.000; 

---

test-declaration4.ma
==========
# test declaration in separate lines

number a;
a <- 8;
print(a);
---
8.000
---

test-declaration5.ma
==========
string s;

print(s);


---
(null)

---

test-declarations6.ma
==========
# numbers are initialized to zero!

number a;

print(a);


---
0.000

---

test-declarations7.ma
==========
matrix a <- [3,4];

print(a[2]);

---
4.000

---

test-expressions1.ma
==========
# testing unary expressions

number a <- 50;

if(!(a=40)){
	print ("Success");
}


---
Success
---

test-expressions10.ma
==========
# unary expressions, matrix transpose 

matrix a <- [1, 3, 5; 2, 4, 6];

matrix b <- a';

print(b[4]);


---
4.000
---

test-expressions11.ma
==========
# testing primary expressions, matrix access, logical not 

number a <- 1;

if(!(a=0)){
	print("Success");
}


---
Success

---

test-expressions12.ma
==========
# testing multiplicative expressions 

matrix a <- [1, 2, 3];

matrix b <- [4; 5; 6];

print(a * b);



---
32.000;
---

test-expressions13.ma
==========
# testing multiplicative expressions 

number a <- 5;

number b <- 2;

print(a*b);


---
10.000
---

test-expressions14.ma
==========
# testing multiplicative expresssions, division 

number a <- 12;

number b <- 2;

print(a / b);

---
6.000

---

test-expressions15.ma
==========
# testing multiplicative expressions, modulo

number a <- 11 ;

number b <- 2 ;

print(a%b);


---
1.000

---

test-expressions16.ma
==========
# additive expressions, expressions + expression 

string a <- "Hello ";

string b <- "World";

print(strcat(a,b));
 
---
Hello World

---

test-expressions17.ma
==========
# testing additive expressions, numbers and matrices

matrix a <- [1,2,3;4,5,6];

matrix b <- [1,2,3;4,5,6];

matrix c <- a + b;

print(c[4]);

---
8.000
---

test-expressions18.ma
==========
# testing additive expressions, subtraction

matrix a <- [1,2,3;4,5,6];

matrix b <- [1,2,3;4,5,6];

matrix c <- a - b;

print(c[5]);



---
0.000
---

test-expressions19.ma
==========
# testing relational expressions 

number a <-5;

number b <-10;

if(a<b){
	
	print("Success");
}


---
Success

---

test-expressions2.ma
==========
# testing primary expressions

matrix a <- [1, 2, 3; 8+9, 4-2, 4];

matrix b <- [4, 5, 3; 7, 5, 3];

number c <- a[4] - b[1]; #[-3, -3, 0; 10, -3, 1]

print(c);


---
13.000
---

test-expressions20.ma
==========
# testing relational expressions 

number a <- 5;

number b <- 10;

if(!(a>b)){
	print("Success");
}

---
Success
---

test-expressions21.ma
==========
# testing relational expressions 

number a <- 5;

number b <- 5;

if (a<=b){
	print("Success");
}




---
Success

---

test-expressions22.ma
==========
# testing relational expressions 

number a <- 5;

number b <- 5;

if (a>=b){
	print("Success");
}




---
Success

---

test-expressions23.ma
==========
# testing equality operators 

number a <- 5;

number b <- 5;

if(a=b){

	print("Success");
}


---
Success

---

test-expressions24.ma
==========
# testing equality operators 

number a <- 5;

number b <- 5;

print (a!=b);


---
0.000
---

test-expressions25.ma
==========
# testing expressions, logical operators

number a <- 10;

number b <- 12;

if((a=10)&(b=12)){
	print("Success");
}

---
Success

---

test-expressions26.ma
==========
# testing expressions, logical operators

number a <- 0;

number b <- 12;

if((a=5)|(b=12))
{
	print("Success");
}


---
Success

---

test-expressions27.ma
==========
# testing expressions, assignment expression 

number a <- 5 ;

number b <- 10 ;

number c <- 15 ;

number d <- a <- b <- c ;

print(d);


---
15.000
---

test-expressions28.ma
==========
# testing expressions, lvalues

number a;

a <- 5;

print(a);


---
5.000

---

test-expressions29.ma
==========
# testing assingment expressions, L Values 

number a <- 5;

number b <- 10;

matrix c <- [1,2,3;4,5,6];

print(c[b-a]);



---
5.000
---

test-expressions3.ma
==========
# testing primary expressions 

number a <-5;

print(a);






---
5.000
---

test-expressions30.ma
==========
# testing expressions, value versus reference 

number a <- 5;

number b <- 10;

number c <- a+b;

a <- 10;

print(c);


---
15.000
---

test-expressions31.ma
==========
# testing expressions, when /n in strings, will print "/n" and not new line 

print("Hello /n World");
---
Hello /n World
---

test-expressions32.ma
==========
# testing additive expressions, adding number to matrix 

number a <- 5;

matrix b <- [1,2,3;4,5,6];

matrix c <- a + b;

print(c[6]);

---
11.000
---

test-expressions34.ma
==========
# assigning number to matrix 

matrix a <- [1,2,3;4,5,6];

number b <- 100;

a[4] <- b;

print(a[2,1]);

---
100.000
---

test-expressions35.ma
==========
# creating 2 by 3 matrix filled with zeros

matrix a <- [](2,3);

print(a[6]);

---
0.000
---

test-expressions36.ma
==========
# matrix insertion returns the value replaced!

matrix a <- [1,2,3,4;5,6,7,8];

number b <- a[2, 3] <- 19;

print(b);
print(a[2,3]);
---
7.000
19.000
---

test-expressions37.ma
==========
# matrix insertion returns the value replaced!

matrix a <- [1,2,3,4;5,6,7,8];

number b <- a[3] <- 34;

print(b);
print(a[3]);
---
3.000
34.000
---

test-expressions38.ma
==========
# test 2d matrix multiplication

matrix A <- [1,2,9;5,2,1];

matrix B <- [8,1;4,2;4,2];

print(A * B);
---
52.000, 23.000; 
52.000, 11.000; 
---

test-expressions4.ma
==========
# testing primary expressions 

number a <- 5;

number b <- 10;

number c <- (a + b);

print(c);


---
15.000
---

test-expressions5.ma
==========
# testing primary expressions

string a <- "Success";

void foo (string s)
{
	print(s);
}

foo(a);


---
Success
---

test-expressions6.ma
==========
# testing primary expressions, matrix access 

matrix a <- [1, 2, 3; 4, 5, 6];

print(a[1]);


---
1.000
---

test-expressions7.ma
==========
# testing primary expressions, matrix access 

number b <- 5;
matrix a <- [1,2,3;4,5,6];

print(a[b]);


---
5.000
---

test-expressions8.ma
==========
# testing unary expressions 

number a <- 5;

print (-a);


---
-5.000
---

test-expressions9.ma
==========
# testing unary operators 

matrix a <- [1,2,3;4,5,6];

matrix b <- -a;

print(b[1]);

---
-1.000
---

test-functions1.ma
==========
# passing an argument to a void function

void foo(string s) {
	print(s);
}

string s <- "Hello World!";
foo(s);

---
Hello World!
---

test-functions10.ma
==========
number foo() {
	number a <- 5;
	return a;
}

print(foo());

number bar(number a) {
	number x <- foo() + a;
	return x;
}

print(bar(8));

---
5.000
13.000
---

test-functions11.ma
==========
# return a matrix from a function!

matrix foo() {
    return [](5, 5);
}

matrix a <- foo();
print(a);

---
0.000, 0.000, 0.000, 0.000, 0.000; 
0.000, 0.000, 0.000, 0.000, 0.000; 
0.000, 0.000, 0.000, 0.000, 0.000; 
0.000, 0.000, 0.000, 0.000, 0.000; 
0.000, 0.000, 0.000, 0.000, 0.000; 
---

test-functions12.ma
==========
# return a matrix from a function!

matrix foo() {
	matrix b <- [1,2,3,4,5;1,2,3,4,5];
    return b;
}

matrix a <- foo();
print(a);
---
1.000, 2.000, 3.000, 4.000, 5.000; 
1.000, 2.000, 3.000, 4.000, 5.000; 
---

test-functions13.ma
==========
# return a matrix from a function!

matrix foo() {
	return [1,2,3,4,5;1,2,3,4,5];
}

matrix a <- foo();
print(a);
---
1.000, 2.000, 3.000, 4.000, 5.000; 
1.000, 2.000, 3.000, 4.000, 5.000; 
---

test-functions14.ma
==========
number foo() {
    return number a <- 6;
}

print(foo());

---
6.000
---

test-functions15.ma
==========
number factorial (number i) {
	if (i = 0) {
		return 1;
	} else {
		return i * factorial(i - 1);
	}
}

print(factorial(5));

print(factorial(10));
---
120.000
3628800.000
---

test-functions2.ma
==========
# function overloading

void foo(string s) {
	print(s);
}

void foo(string s, string t) {
	print(s);
	print(t);
}

foo("Hello, sir!");
foo("How are you doing?", "Well, I presume?");

---
Hello, sir!
How are you doing?
Well, I presume?
---

test-functions3.ma
==========
# variable scoping in functions

void foo() {
	string s <- "Hello";
	print(s);
}

string s <- "World!";

foo();
print(s);

---
Hello
World!

---

test-functions4.ma
==========
# test return variables are correct for numbers

number foo(number a, number b) {
	return a * b - a + b * 5;
}

number a <- foo(4, 6);

print(a);

---
50.000

---

test-functions5.ma
==========
# global variable modifications are sticky
# variables are passed by value

number a <- 7;

number foo(number x) {
	x <- x * 5;

	print(x);

	return 2;
}

number b <- foo(a);

print(a);
print(b);

---
35.000
7.000
2.000
---

test-functions6.ma
==========
# matrices are passed by reference/pointer

matrix a <- [](2, 1);

print(a[1]);

void foo(matrix x) {
    x[1] <- 5;
    x[2] <- 18;
}

foo(a);

print(a[1]);
print(a[2]);

---
0.000
5.000
18.000
---

test-functions7.ma
==========
# string concatenation is destructive

string foo(string s) {
	return strcat("Hello ", s);
}

print(foo("World!"));

---
Hello World!

---

test-functions8.ma
==========
# string concatenation is destructive!

string s <- "Hello!";
string t <- " World!";

string x <- strcat(s, t);

print(x);
print(s);
print(t);
x <- strcat(t, s);

print(x);
---
Hello! World!
Hello! World!
World!
World!Hello! World!

---

test-functions9.ma
==========
# referencing an undeclared variable in a function!
# variable declared after function 

void foo(string s) {
    print(a + 5);
    print(s);
}

number a <- 10;
foo("NOPE!");

---
15.000
NOPE!

---

test-overload1.ma
==========
# basic operator overloading

number operator .* (number a, number b) {
	number c <- 1;

	while (b > 0) {
		c <- c * a;
		b <- b - 1;
	}

	return c;
}

number a <- 5 .* 2;
print(a);

---
25.000
---

test-overload2.ma
==========
# unary operators!

string operator - (string s) {
	return strcat("Hello ", s);
}

string a <- "World";
print(-a);
---
Hello World
---

test-overload3.ma
==========
# sequential chaining of overloaded operator

number operator .* (number a, number b) {
	number c <- 0;

	while (b > 1) {
		c <- c + a * a;
		b <- b - 1;
	}

	return c;
}

number z <- 5 .* 2;
number a <- z .* 8;
print(a);

---
4375.000
---

test-overload4.ma
==========
# mixed variables in overloads

number operator + (string s, number b) {
    print(b);
    print(s);

    return 0;
}

number a <- "Hello World!" + 6;
print(a);
---
6.000
Hello World!
0.000

---

test-overload5.ma
==========
# Overloading overloaded operators

string operator + (string s, number b) {
    print(b);
    print(s);

    return "what?";
}

string operator + (string s, string t) {
	print(strcat(s, t));

	return "lol";
}

string a <- "Meh" + 8.2;
print(a);
string k <- "Hello ";
string l <- "World!";
string s <- k + l;
print(s);
---
8.200
Meh
what?
Hello World!
lol

---

test-overload6.ma
==========
# Overloading overloaded operators
# This is the same as test-overload5.ma

string operator + (string s, number b) {
    print(b);
    print(s);

    return "what?";
}

string operator + (string s, string t) {
	print(strcat(s, t));

	return "lol";
}

string a <- "Meh" + 8.2;
print(a);
string s <- "Hello " + "World! 2";
print(s);

---
8.200
Meh
what?
Hello World! 2
lol

---

test-overload7.ma
==========
# chain two different overloaded operators
# really the power function, but we're using this symbol because power is defined in stdlib
number operator ./ (number a, number b) {
    number c <- 1;

    while (b > 0) {
        c <- c * a;
        b <- b - 1;
    }

    return c;
}

number operator .* (number a, number b) {
	return a - b * 10;
}

print(5 ./ 10 .* 5);
---
9765575.000

---

test-overload8.ma
==========
# Define a custom operator to test daisy chaining of operators
number operator .* (number a, number b) {
	return a + b * a;
}

number a <- 5 .* 2 .* 8; # 135 expected
print(a);

---
135.000
---

test-scope1.ma
==========
# testing different function scopes

number first <- 5;

print (first); # global scope, should print 5

number a(){

    return first;

}

number b(){

    return first;
}

print(a());
print(b());

---
5.000
5.000
5.000

---

test-scope2.ma
==========
# testing scope with strings 

string s <- "Hello World";

print(s); 

string a(){
    print(s); 
    return "Success";
}

string b(){
    print(s);
    return "Success";
}

print(a());
print(b());



---
Hello World
Hello World
Success
Hello World
Success

---

test-scope3.ma
==========
# scope passing matrix 


matrix m <- [ 1, 2, 3; 8+9, 4-2, 4]; 

print(m);  # global scope, should print [1,2,3;17,2,4]

matrix a() {

    return m;
}

matrix b() {
    return m;
}

print(a());
print(b());


---
1.000, 2.000, 3.000; 
17.000, 2.000, 4.000; 
1.000, 2.000, 3.000; 
17.000, 2.000, 4.000; 
1.000, 2.000, 3.000; 
17.000, 2.000, 4.000; 

---

test-scope4.ma
==========
# scope testing 

number a <- 1;
number c <- 5;  
print(c);

number foo() {  
    c <- 10;
    print(c);
    
    number a <-10;

    number p <- 99; 

    return p; 
}
print (c);
print (a);
c <- foo();
print(c); 

---
5.000
5.000
1.000
10.000
99.000

---

test-scope5.ma
==========
# scope testing 

string s;

s <- "Outside";


string foo () {
	
	string s;
	s <- "Inside";
	return s;


}
print(foo());
print(s);
---
Inside
Outside

---

test-statements1.ma
==========
# test an if-else statement

number foo(number a) {
    if (a = 1) {
        print(a);
    } else {
        print(a + 1);
    }

    return 0;
}

print(foo(1));

---
1.000
0.000

---

test-statements11.ma
==========
# nested while loop

number b <- 10;

while (b != 5) {
	b <- 5;
}

print(b);

while (b != 11) {
	number c <- 1;
	while (c < 111) {
		c <- c * b;
		print(c);
		b <- b + 1;
	}
	print(b);
}
---
5.000
5.000
30.000
210.000
8.000
8.000
72.000
720.000
11.000
---

test-statements12.ma
==========
# compare numerals

if (1 = 1) {
	print("1 is equal to 1.");
}
---
1 is equal to 1.
---

test-statements13.ma
==========
# this program should not loop.

number a <- 10;

if (a = 10) {
	print("I'm okay!");
} else {
	while (1 = 1) {
		print("HELP ME!");
	}
}
---
I'm okay!
---

test-statements14.ma
==========
# nested if statements

number b <- 99;

if (b >= 92) {
	if (b >= 93) {
		if (b >= 95) {
			if (b >= 99) {
				print(b);
			}
		}
	}
}

if (b < 99) {
	print("Nope.");
} else {
	if (b < 94) {
		print("Nope.");
	} else {
		print(b);
	}
}
---
99.000
99.000
---

test-statements15.ma
==========
# for loop test

matrix a <- [1,2,3,4,5,6,7,8];
number b <- 0;

for (b in a) {
	print(b);
}

---
1.000
2.000
3.000
4.000
5.000
6.000
7.000
8.000
---

test-statements16.ma
==========
# var declaration in for loop

matrix a <- [1;2;3;4;5];

for (number b in a) {
	print(b);
}
---
1.000
2.000
3.000
4.000
5.000
---

test-statements2.ma
==========
# greater than test

number a <- 8;

if (a > 6) {
	print("a is greater than 6.");
}
---
a is greater than 6.

---

test-statements3.ma
==========
# less than test

number a <- 8;

if (a < 10) {
	print("a is less than 10.");
}
---
a is less than 10.

---

test-statements4.ma
==========
# testing both printing functions

print("Hello World");
printnl("Hello ");
print("World");

---
Hello World
Hello World

---

test-statements5.ma
==========
# test a while statement

number a <- 0;

while (a <= 10) {
	print(a);
	a <- a + 1;
}
---
0.000
1.000
2.000
3.000
4.000
5.000
6.000
7.000
8.000
9.000
10.000
---

test-statements6.ma
==========
# test LET

number b <- 5;

if (b <= 5) {
	print("Yep.");
}
---
Yep.
---

test-statements7.ma
==========
# test GET

number b <- 5;

if (b >= 5) {
	print("Yep.");
}

b <- 6;

if (b >= 5) {
	print("Yep.");
}
---
Yep.
Yep.
---

test-statements8.ma
==========
# compare two numbers

number a <- 6;
number b <- 6;

if (a = b) {
	print("a and b are equal.");
}

print("Success!");

---
a and b are equal.
Success!
---

test-statements9.ma
==========
# if else if else if else statements

number b <- 99;

if (b = 88) {
	print(b);
} else {
	if (b = 77) {
		print(b);
	} else {
		if (b = 99) {
			print(b);
		}
	}
}
---
99.000
---

