package de.fuberlin.projecta;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import de.fuberlin.projecta.analysis.SemanticException;
import de.fuberlin.projecta.lexer.io.ICharStream;
import de.fuberlin.projecta.lexer.io.StringCharStream;
/**
* This tests the following parts: Lexer -> Parser -> Semantic analysis -> Code
* generation
*
* This is a complete test for the whole compiler (frontend+backend)
*/
public class CompilerTest {
// "forward declare"
static String mainC(String block) {
return ParserTest.mainC(block);
}
static String executeCode(String code) {
ICharStream stream = new StringCharStream(code);
String output = CompilerMain.execute(stream, /* verbose = */true);
return output;
}
@Test
public void testPrint() {
final String code = mainC("string s; s = \"foo\"; print s;");
String output = executeCode(code);
assertEquals(output, "foo");
}
@Test
public void testImplicitReturnValueOnIntegerAssignment() {
String code = "def int foo() { int i; i = 1; }"
+ mainC("int j; j = foo(); print j; return 0;");
String output = executeCode(code);
assertEquals("1", output);
}
@Test
public void testAdd() {
final String code = mainC("int a; a = 1 + 1; print a;");
String output = executeCode(code);
assertEquals(output, "2");
}
@Test
public void testFuncReturnInt() {
final String code = "def int foo(){return 0;} def int main(){int i; i = foo(); print i; return 0;}";
String output = executeCode(code);
assertEquals(output, "0");
}
@Test
public void testUnimplicitVarIncrementingInFuncAssign() {
final String code = "def int foo(){return 0;} def int main(){int i; i = foo(); print i; return 0;}";
String output = executeCode(code);
assertEquals(output, "0");
}
@Test
public void testImplicitVarIncrementingInFuncAssign() {
final String code = "def int foo(){return 0;} def int main(){foo(); return 0;}";
String output = executeCode(code);
assertEquals(output, "");
}
@Test
public void testIfOnTrueWithIntegerComparison() {
final String code = "def int main(){int i; int j; i = 1; j = 2; if(i <= j) { print i; print j;} return 0;}";
String output = executeCode(code);
assertEquals(output, "12");
}
@Test
public void testIfElseOnTrueWithIntegerComparison() {
final String code = "def int main(){int i; int j; i = 1; j = 2; if(i <= j) { print i; print j;} else {print j; print i;} return 0;}";
String output = executeCode(code);
assertEquals(output, "12");
}
@Test
public void testIfOnFalseWithIntegerComparison() {
final String code = "def int main(){int i; int j; i = 1; j = 2; if(i >= j) { print i; print j;} return 0;}";
String output = executeCode(code);
assertEquals(output, "");
}
@Test
public void testIfElseOnFalseWithIntegerComparison() {
final String code = "def int main(){int i; int j; i = 1; j = 2; if(i >= j) { print i; print j;} else {print j; print i;} return 0;}";
String output = executeCode(code);
assertEquals(output, "21");
}
@Test
public void testLiteralComparison() {
final String code = "def int main(){bool a; bool b; bool c; bool d; a = 3 == 4; b = 3 == 3; c = 3 != 4; d = 3 != 3; print a; print b; print c; print d; return 1;}";
String output = executeCode(code);
assertEquals(output, "0110");
}
@Test
public void testWhile() {
final String code = mainC("int i; int j; i = 0; j = 10; while(i < j) {print i; i = j;}");
String output = executeCode(code);
assertEquals(output, "0");
}
@Test
public void testParameterWithoutLoading() {
final String code = "def int foo(int i) { int j; j = i + i; return j;} def int main(){int i; i = 3; i = foo(i); print i; return 0;}";
String output = executeCode(code);
assertEquals(output, "6");
}
@Test
public void testFuncCallWithLiteralParameter() {
final String code = "def int foo(int i){ return i;} def int main(){int i; i = foo(3)*foo(4); print i; return 0;}";
String output = executeCode(code);
assertEquals("12", output);
}
@Test
public void testReturnWithBinaryOp() {
final String code = "def int foo(int i){ return i+1;} def int main(){int i; i = foo(3); print i; return 0;}";
String output = executeCode(code);
assertEquals("4", output);
}
@Test
public void testFuncCallWithBinaryOp() {
final String code = "def int foo(int i){ return i;} def int main(){int i; i = foo(3+4); print i; return 0;}";
String output = executeCode(code);
assertEquals("7", output);
}
@Test
public void testMultiExpression() {
String code = mainC("int a; a = 1 + 2 + 3; print a;");
String output = executeCode(code);
assertEquals("6", output);
}
@Test
public void testRecursiveFuncCall() {
final String code = "def int foo(int i){if (i==0) {return 1;} return foo(i-1);} def int main(){int i; i = foo(3); print i; return 0;}";
String output = executeCode(code);
assertEquals("1", output);
}
@Test
public void testIfElsePrintStatement() {
final String code = mainC("int a; int b; bool c; a = 1; b = 2; c = true;\n"
+ "if (c) { print a; }\n" + "else { print b; }");
String output = executeCode(code);
assertEquals("1", output);
}
@Test
public void testIfElseReturnStatement() {
final String code = "def int foo() { int a; int b; bool c; a = 1; b = 2; c = true;\n"
+ "if (c) { return a; }\n"
+ "else { return b; }\n"
+ "}\n"
+ mainC("int a; a = foo(); print a;");
System.out.println(code);
String output = executeCode(code);
assertEquals("1", output);
}
@Test
public void testRecordDeclaration() {
final String code = mainC("record {int i; int j;} myRecord;");
System.out.println(code);
String output = executeCode(code);
assertEquals("", output);
}
@Test
public void testRecordFuncCall() {
final String code = "def int foo(record {int i;} a) { int x; x = a.i; print x; return a.i + 1;} "
+ "def int main(){ record {int i;} a; int bla; a.i = 3; bla = foo(a); print bla; return 0;}";
System.out.println(code);
String output = executeCode(code);
assertEquals("34", output);
}
@Test
public void testNestedRecords() {
final String code = "def real main(){record{real x; record{int c;}b;}a;"
+ "int d; a.b.c = 3; a.x = 3.14; d = a.b.c; print a.x; return a.x;}";
System.out.println(code);
String output = executeCode(code);
assertEquals("3.140000", output);
}
/*
* @Test public void testUnaryOpInIfStatement() { final String code =
* mainC("bool b; int i; b = false; if (!b) { i = 1; } else { i = 0; } print i;"
* ); System.out.println(code); String output = executeCode(code);
* assertEquals("1", output); }
*/
@Test
public void testNestedRecords2() {
final String code = mainC("record { real x; record {real x; record { int i;} inner; } middle; } outer;"
+ "outer.middle.inner.i=3; print outer.middle.inner.i;");
System.out.println(code);
String output = executeCode(code);
assertEquals("3", output);
}
@Test
public void testArray() {
final String code = mainC("int[10] test; int i; int tmp;" + "i = 0; "
+ "while (i < 10){" + "test[i] = i;" + "tmp = test[i];"
+ "print tmp;" + "i=i+1; " + "}");
System.out.println(code);
String output = executeCode(code);
assertEquals("0123456789", output);
}
@Test
public void testArrayFuncCall() {
final String code = "def int fun(int[30] x) { return x[1]; } "
+ "def int main(){int[30] x; int i; x[1] = 1; i = fun(x); print i; return 0;}";
System.out.println(code);
String output = executeCode(code);
assertEquals("1", output);
}
@Test
public void testMultiDimensionalArrays() {
final String code = mainC("int[3][5] test; int i; int j; int tmp;"
+ "i = 0;" + "while (i < 3){" + "j = 0;" + "while(j < 5){"
+ "test[i][j] = i+j;" + "j=j+1;" + "}" + "i=i+1; " + "} "
+ "i = 0;" + "while (i < 3){" + "j = 0;" + "while(j < 5){"
+ "tmp = test[i][j];" + "print tmp;" + "j=j+1;" + "}"
+ "i=i+1; " + "} "
);
System.out.println(code);
String output = executeCode(code);
assertEquals("012341234523456", output);
}
@Test
public void testVoidMain() {
String code = "def void main() { string s; s = \"foo\"; print s; return; }";
String output = executeCode(code);
assertEquals("foo", output);
}
@Test
public void testDoWhileStatement() {
String code = mainC("int i; i = 0; do {" + "print i;" + "i = i+1;"
+ "} while (i < 5);");
String output = executeCode(code);
System.out.println(output);
assertEquals("01234", output);
}
@Test
public void testPrintNestedArray() {
String code = "def void foo(int[30][50] array, int i)"
+ "{print array[i][0];} "
+ mainC("int[30][50] array; int i; array[0][0] = 0; i = 0; foo(array,i);");
String output = executeCode(code);
System.out.println(output);
assertEquals("0", output);
}
@Test
public void testPrintBasicParameter() {
String code = "def void foo(int i, real r, string s){" +
"print i; print r; print s; return;}" +
"def void main(){" +
"int a; real b; string c; a = 2; b = 1.0; c = \"bar\"; foo(a,b,c);}";
String output = executeCode(code);
System.out.println(output);
assertEquals("21.000000bar", output);
}
@Test
public void testBasicParameter(){
String code = "def void foo(int i, real r){" +
"int a; a = i; a = i+1; print i; print r;}" +
"def void main(){" +
"int a; real b; string c; a = 2; b = 1.0; foo(a,b);}";
String output = executeCode(code);
System.out.println(output);
assertEquals("21.000000", output);
}
@Test
public void testRealEquations(){
String code = "def void main(){real r; real x; r = 1.0; x = 2.0; r = r + x; print r;}";
String output = executeCode(code);
System.out.println(output);
assertEquals("3.000000", output);
}
@Test(expected= SemanticException.class)
public void testAssignValueToParameterVariable(){
String code = "def void foo(int i){i = 4;}def void main(){foo(3);}";
String output = executeCode(code);
System.out.println(output);
}
}