From c265ca853f8114e7a02d61bb4744c9b5e817ec43 Mon Sep 17 00:00:00 2001
From: John Tinnerholm <jtinnerholm@gmail.com>
Date: Sat, 19 Dec 2020 20:31:17 +0100
Subject: [PATCH] Added C-code generator + test to TDDD55-lab

---
 lab3-4/Makefile                          |   5 +-
 lab3-4/codegen-test.sh                   | 258 ++++++++++++++++++
 lab3-4/codegen.cc                        | 316 ++++++++++++++++++++++-
 lab3-4/codegen.hh                        |   4 +-
 lab3-4/main.cc                           |  25 +-
 lab3-4/stl.h                             |  49 ++++
 lab3-4/symtab.cc                         | 104 +++++++-
 lab3-4/symtab.hh                         |  11 +-
 lab3-4/test/README.md                    |  33 +++
 lab3-4/test/expression_output_ref        |  10 +
 lab3-4/test/expression_test.prog         |  41 +++
 lab3-4/test/factorial_output_ref         |   2 +
 lab3-4/test/factorial_test.prog          |  24 ++
 lab3-4/test/fibonacci_output_ref         |  10 +
 lab3-4/test/fibonacci_test.prog          |  30 +++
 lab3-4/test/simple_array_output_ref      |   5 +
 lab3-4/test/simple_array_test.prog       |  27 ++
 lab3-4/test/simple_array_test_output_ref |   5 +
 lab3-4/test/simple_simple_array.prog     |  12 +
 lab3-4/test/sort_test.prog               |  63 +++++
 lab3-4/test/sort_test_output_ref         |  21 ++
 21 files changed, 1024 insertions(+), 31 deletions(-)
 create mode 100644 lab3-4/codegen-test.sh
 create mode 100644 lab3-4/stl.h
 create mode 100644 lab3-4/test/README.md
 create mode 100644 lab3-4/test/expression_output_ref
 create mode 100644 lab3-4/test/expression_test.prog
 create mode 100644 lab3-4/test/factorial_output_ref
 create mode 100644 lab3-4/test/factorial_test.prog
 create mode 100644 lab3-4/test/fibonacci_output_ref
 create mode 100644 lab3-4/test/fibonacci_test.prog
 create mode 100644 lab3-4/test/simple_array_output_ref
 create mode 100644 lab3-4/test/simple_array_test.prog
 create mode 100644 lab3-4/test/simple_array_test_output_ref
 create mode 100644 lab3-4/test/simple_simple_array.prog
 create mode 100644 lab3-4/test/sort_test.prog
 create mode 100644 lab3-4/test/sort_test_output_ref

diff --git a/lab3-4/Makefile b/lab3-4/Makefile
index f5294b1..a8e7fee 100644
--- a/lab3-4/Makefile
+++ b/lab3-4/Makefile
@@ -15,6 +15,8 @@ OUTFILE =	compiler
 
 FLEX	= flex
 BISON	= bison
+TESTFILES=expression_test.c factorial_test.c fibonacci_test.c sort_test.c simple_array_test.c
+TESTEXECS=expression_test factorial_test fibonacci_test sort_test simple_array_test
 
 DPFILE  =	Makefile.dependencies
 
@@ -39,10 +41,9 @@ parser.o : parser.cc
 	$(CC) $(CFLAGS) -c $<
 
 clean : 
-	rm -f $(OBJECTS) core *~ scanner.cc parser.cc parser.hh $(DPFILE) $(OUTFILE) parser.cc.output
+	rm -f $(OBJECTS) core *~ scanner.cc parser.cc parser.hh $(DPFILE) $(OUTFILE) parser.cc.output  $(TESTFILES) $(TESTEXECS)
 	touch $(DPFILE)
 
-
 $(DPFILE) depend : $(BASESRC) $(HEADERS)
 	$(CC) $(DPFLAGS) $(CFLAGS) $(BASESRC) > $(DPFILE)
 
diff --git a/lab3-4/codegen-test.sh b/lab3-4/codegen-test.sh
new file mode 100644
index 0000000..4c4aa3a
--- /dev/null
+++ b/lab3-4/codegen-test.sh
@@ -0,0 +1,258 @@
+#!bin/bash
+# Author: John Tinnerholm(johti17) johti17@liu.se
+# This file tests if the last lab (Lab-4 generates correct code)
+# Simple passing this test might not be enough to complete the laboration since there might be other issues..
+# To the curious reader, yes this could have been solved by a function..
+
+echo "****Testing Lab 4****"
+echo "Testing simple expressions"
+./compiler -c ./test/expression_test.prog > expression_test.c
+if [ $? -eq 0 ]; then
+    echo "Compilation-OK"
+else
+    echo "Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Frontend OK"
+echo "Translating to C-Code..."
+
+gcc expression_test.c -o  expression_test -lm
+
+if [ $? -eq 0 ]; then
+    echo "C-Code-Compilation-OK"
+else
+    echo "C-Code-Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Testing the expression_test"
+
+
+./expression_test > expression_output
+
+if [ $? -eq 0 ]; then
+    echo "Program ran sucessfully"
+else
+    echo "Program-Failed.. exiting"
+    exit 1
+fi
+
+echo "Checking that we get the correct output.."
+
+if cmp -s "./expression_output" "test/expression_output_ref"; then
+    echo "The program generated the correct output"
+else
+    echo "The output does not match..."
+    diff -y expression_output ./test/expression_output_ref
+    echo "Exiting.."
+    exit 1
+fi
+echo "Removing the testfile: rm expression_output"
+#Remove the testfile
+rm expression_output
+echo "***********************"
+echo "expression_test passed!"
+echo "***********************"
+#= Factorial =#
+echo "Testing factorial_test"
+./compiler -c ./test/factorial_test.prog > factorial_test.c
+if [ $? -eq 0 ]; then
+    echo "Compilation-OK"
+else
+    echo "Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Frontend OK"
+echo "Translating to C-Code..."
+
+gcc factorial_test.c -o  factorial_test -lm
+
+if [ $? -eq 0 ]; then
+    echo "C-Code-Compilation-OK"
+else
+    echo "C-Code-Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Testing the factorial_test"
+
+
+./factorial_test > factorial_output
+
+if [ $? -eq 0 ]; then
+    echo "Program ran sucessfully"
+else
+    echo "Program-Failed.. exiting"
+    exit 1
+fi
+
+echo "Checking that we get the correct output.."
+
+if cmp -s "./factorial_output" "test/factorial_output_ref"; then
+    echo "The program generated the correct output"
+else
+    echo "The output does not match..."
+    diff -y factorial_output ./test/factorial_output_ref
+    echo "Exiting.."
+    exit 1
+fi
+echo "Removing the testfile: rm factorial_output"
+#Remove the testfile
+rm factorial_output
+echo "***********************"
+echo "factorial_test passed!"
+echo "***********************"
+#= Fibonacci =#
+echo "Testing fibonacci_test"
+./compiler -c ./test/fibonacci_test.prog > fibonacci_test.c
+if [ $? -eq 0 ]; then
+    echo "Compilation-OK"
+else
+    echo "Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Frontend OK"
+echo "Translating to C-Code..."
+
+gcc fibonacci_test.c -o  fibonacci_test -lm
+
+if [ $? -eq 0 ]; then
+    echo "C-Code-Compilation-OK"
+else
+    echo "C-Code-Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Testing the fibonacci_test"
+
+
+./fibonacci_test > fibonacci_output
+
+if [ $? -eq 0 ]; then
+    echo "Program ran sucessfully"
+else
+    echo "Program-Failed.. exiting"
+    exit 1
+fi
+
+echo "Checking that we get the correct output.."
+
+if cmp -s "./fibonacci_output" "test/fibonacci_output_ref"; then
+    echo "The program generated the correct output"
+else
+    echo "The output does not match..."
+    diff -y fibonacci_output ./test/fibonacci_output_ref
+    echo "Exiting.."
+    exit 1
+fi
+echo "Removing the testfile: rm fibonacci_output"
+#Remove the testfile
+rm fibonacci_output
+echo "***********************"
+echo "fibonacci_test passed!"
+echo "***********************"
+#= Simple array =#
+echo "Testing simple_array_test"
+./compiler -c ./test/simple_array_test.prog > simple_array_test.c
+if [ $? -eq 0 ]; then
+    echo "Compilation-OK"
+else
+    echo "Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Frontend OK"
+echo "Translating to C-Code..."
+
+gcc simple_array_test.c -o  simple_array_test -lm
+
+if [ $? -eq 0 ]; then
+    echo "C-Code-Compilation-OK"
+else
+    echo "C-Code-Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Testing the simple_array_test"
+
+
+./simple_array_test > simple_array_test_output
+
+if [ $? -eq 0 ]; then
+    echo "Program ran sucessfully"
+else
+    echo "Program-Failed.. exiting"
+    exit 1
+fi
+
+echo "Checking that we get the correct output.."
+
+if cmp -s "./simple_array_test_output" "test/simple_array_test_output_ref"; then
+    echo "The program generated the correct output"
+else
+    echo "The output does not match..."
+    diff -y simple_array_test_output ./test/simple_array_test_output_ref
+    echo "Exiting.."
+    exit 1
+fi
+echo "Removing the testfile: rm simple_array_output"
+#Remove the testfile
+rm simple_array_test_output
+echo "***********************"
+echo "simple_array_test passed!"
+echo "***********************"
+
+
+#= Simple array =#
+echo "Testing sort_test"
+./compiler -c ./test/sort_test.prog > sort_test.c
+if [ $? -eq 0 ]; then
+    echo "Compilation-OK"
+else
+    echo "Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Frontend OK"
+echo "Translating to C-Code..."
+
+gcc sort_test.c -o  sort_test -lm
+
+if [ $? -eq 0 ]; then
+    echo "C-Code-Compilation-OK"
+else
+    echo "C-Code-Compilation-Failed.. exiting"
+    exit 1
+fi
+
+echo "Testing the sort_test"
+
+
+./sort_test > sort_test_output
+
+if [ $? -eq 0 ]; then
+    echo "Program ran sucessfully"
+else
+    echo "Program-Failed.. exiting"
+    exit 1
+fi
+
+echo "Checking that we get the correct output.."
+
+if cmp -s "./sort_test_output" "test/sort_test_output_ref"; then
+    echo "The program generated the correct output"
+else
+    echo "The output does not match..."
+    diff -y sort_test_output ./test/sort_test_output_ref
+    echo "Exiting.."
+    exit 1
+fi
+echo "Removing the testfile: rm simple_array_output"
+#Remove the testfile
+rm sort_test_output
+echo "***********************"
+echo "sort_test passed!"
+echo "***********************"
diff --git a/lab3-4/codegen.cc b/lab3-4/codegen.cc
index 3212f79..c517e2c 100644
--- a/lab3-4/codegen.cc
+++ b/lab3-4/codegen.cc
@@ -593,10 +593,11 @@ VariableInformation *NotEqual::GenerateCode(QuadsList& q)
     VariableInformation *r0;
 
     r0 = BinaryGenerateCode(q, req, ieq, left, right, this, kIntegerType);
+    auto result = currentFunction->TemporaryVariable(kIntegerType);
     q += new Quad(inot,
 		  dynamic_cast<SymbolInformation*>(r0),
 		  static_cast<SymbolInformation*>(NULL),
-		  dynamic_cast<SymbolInformation*>(r0));
+		  dynamic_cast<SymbolInformation*>(result));
     return r0;
 }
 
@@ -965,6 +966,319 @@ ostream& Quad::print(ostream& o)
 }
 
 
+
+void QuadsList::print_c(ostream& o)
+{
+    QuadsListElement        *elem;
+
+    elem = head;
+    o << ShortSymbols;
+    while (elem)
+    {
+      //        o << elem->data << '\n';
+	elem->data->print_c(o);
+	o << "\n";
+        elem = elem->next;
+    }
+
+    o << CFormat;
+}
+
+void Quad::print_c(ostream& o)
+{
+    o << "    ";
+    static ::string ss = "(";
+    static bool firstParam = true;
+    switch(opcode)
+    {
+    case iconst:
+        o << setw(8) << "integer"
+          << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << int1;
+        break;
+    case rconst:
+        o << setw(8) <<"real"
+          << setw(8) << sym3
+	  << setw(8) << "="
+          << setw(8) << real1;
+        break;
+    case iaddr:
+      o	  << setw(8) << "integer"
+	  << setw(8) << sym3
+	  << setw(8) << "="
+          << setw(8) << "(integer)" << sym1;
+        break;
+    case itor:
+        o << setw(8) <<  "real"
+	  << setw(8) << sym3
+	  << setw(8) <<"="
+          << setw(8) << "(real)"<< sym1;
+        break;
+    case rtrunc:
+        o << setw(8) << "integer"
+	  << setw(8) << sym3
+          << setw(8) <<"="
+          << setw(8) << "(integer)" <<sym3;
+        break;
+    case iadd:
+      o << setw(8) << "integer"
+	<< setw(8) << sym3
+	  << setw(8) << " = "
+          << setw(8) << sym1
+	  << setw(8) << " + "
+          << setw(8) << sym2;
+        break;
+    case isub:
+      o << setw(8) << "integer"
+	  << setw(8) << sym3
+	  << setw(8) << " = "
+          << setw(8) << sym1
+	  << setw(8) << " - "
+          << setw(8) << sym2;
+        break;
+    case imul:
+        o << setw(8) << "integer"
+          << setw(8) << sym3
+	  << setw(8) << " = "
+          << setw(8) << sym1
+	  << setw(8) << " * "
+          << setw(8) << sym2;
+        break;
+    case idiv:
+        o << setw(8) << "real"
+	  << setw(8) << sym3
+	  << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "/"
+          << setw(8) << sym2;
+        break;
+    case ipow:
+      o   << setw(8) << "real"
+	  << setw(8) << sym3
+	  << setw(8) << "= pow("
+          << setw(8) << sym1
+	  << setw(8) << ","
+          << setw(8) << sym2 << ")";
+        break;
+    case radd:
+      o   << setw(8) << "real"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "+"
+          << setw(8) << sym2;
+        break;
+    case rsub:
+       o  << setw(8)  << "real"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "-"
+          << setw(8) << sym2;
+        break;
+    case rmul:
+      o  << setw(8)  << "real"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "*"
+          << setw(8) << sym2;
+        break;
+    case rdiv:
+        o  << setw(8) << "real"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "/"
+          << setw(8) << sym2;
+        break;
+    case rpow:
+      o   << setw(8) << "real "
+	  << setw(8) << sym3
+	  << setw(8) << "= pow("
+          << setw(8) << sym1
+	  << setw(8) << ","
+          << setw(8) << sym2 << ")";
+        break;
+    case igt:
+        o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << ">"
+          << setw(8) << sym2;
+        break;
+    case ilt:
+      o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "<"
+          << setw(8) << sym2;
+        break;
+    case ieq:
+          o << setw(8) << "conditional"
+	    << setw(8) << sym3
+	    << setw(8) << "="
+	    << setw(8) << sym1
+	    << setw(8) << "=="
+	    << setw(8) << sym2;
+        break;
+    case rgt:
+     o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << ">"
+          << setw(8) << sym2;
+        break;
+    case rlt:
+     o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "<"
+          << setw(8) << sym2;
+        break;
+    case req:
+     o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "=="
+          << setw(8) << sym2;
+     break;
+    case iand:
+        o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "&&"
+          << setw(8) << sym2;
+	break;
+    case ior:
+      o << setw(8) << "conditional"
+	  << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1
+	  << setw(8) << "||"
+          << setw(8) << sym2;
+        break;
+    case inot:
+        o << setw(8) << "conditional"
+          << setw(8) << sym3
+          << setw(8) << "="
+	  << setw(8) << "!"
+          << setw(8) << sym3;
+        break;
+    case jtrue:
+      o << setw(8) << "if("
+	<< setw(8) << sym2
+	<< setw(8) << ")"
+	<< setw(8)
+	<< setw(8) << "goto clabel" << int1;
+        break;
+    case jfalse:
+      o << setw(8) << "if(!"
+	<< setw(8) << sym2 << setw(8) << ")"
+	<< setw(8)
+	<< setw(8) << "goto clabel" << int1;
+        break;
+    case jump:
+        o << setw(8) << "goto    "
+          << setw(8) << "clabel"
+	  << int1
+          << setw(8) << "/*jmp*/";
+        break;
+    case clabel:
+        o << setw(8) << "clabel"
+          << int1
+          << ":";
+        break;
+    case istore:
+         o << setw(8) << ""
+	  << setw(8) << "*(integer*)" << sym3
+          << setw(8) << "="
+          << setw(8) << sym1;
+        break;
+        break;
+    case iload:
+    	 o << setw(8) << "integer"
+          << setw(8) << sym3
+          << setw(8) << "= /*iload*/"
+          << setw(8) << "*(integer*)" << sym1;
+        break;
+    case rstore:
+        o << setw(8) << ""
+	  << setw(8) << "*(real*)" << sym3
+          << setw(8) << "="
+          << setw(8) << sym1;
+        break;
+    case rload:
+        o
+	  << setw(8) << "real"
+          << setw(8) << sym3
+          << setw(8) << "= /*rload*/"
+          << setw(8) << "*(real*)" << sym1;
+        break;
+    case creturn:
+        o << setw(8) << "return "
+          << setw(8) << sym3
+          << setw(8)
+	  << setw(8) << "/*Return statement*/";
+        break;
+    case param: {
+      if (firstParam) {
+	ss = ss + sym1->id;
+	firstParam = false;
+      } else {
+	ss = ss + "," + sym1->id;
+      }
+    }
+      break;
+    case call: {
+      o << setw(8) << "integer " << sym3 //Let it be ints for now..
+	<< setw(8) << "="
+        << setw(8) << sym1
+	<< setw(8) << ss
+	<< setw(8) << ")";
+	ss = "("; //Reset callstack
+	firstParam = true;
+     }
+        break;
+    case iassign:
+        o << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1;
+        break;
+    case rassign:
+        o << setw(8) << sym3
+          << setw(8) << "="
+          << setw(8) << sym1;
+        break;
+    case aassign:
+        o << setw(8) << "aassign "
+          << setw(8) << sym1
+          << setw(8) << int1
+          << setw(8) << sym3;
+        break;
+    case hcf:
+      o << setw(8) << "exit(-1)";
+        break;
+    case nop:
+      o << setw(8) << ";/*No operation*/"
+	<< setw(8) << "";
+        break;
+    default:
+        o << "unknown (" << opcode << ")";
+        break;
+    }
+    //Add semicolon to all statements
+    o << setw(8) << ";";
+}
+
+
 ostream& operator<<(ostream& o, QuadsList *q)
 {
     if (q != NULL)
diff --git a/lab3-4/codegen.hh b/lab3-4/codegen.hh
index d6eff4c..0d9f284 100644
--- a/lab3-4/codegen.hh
+++ b/lab3-4/codegen.hh
@@ -87,9 +87,9 @@ class Quad
 {
 private:
     ostream& print(ostream&);
-
 public:
     tQuadType        opcode;
+    void print_c(ostream& o);
 
     //
     // Arguments. Make sure you initialize the right ones!
@@ -162,8 +162,8 @@ class QuadsList
     static long              labelCounter;
 
     ostream& print(ostream&);
-    
 public:
+    void print_c(ostream&);
     QuadsList() :
         head(NULL),
         tail(NULL) {};
diff --git a/lab3-4/main.cc b/lab3-4/main.cc
index bf0b530..651111c 100644
--- a/lab3-4/main.cc
+++ b/lab3-4/main.cc
@@ -13,17 +13,18 @@ extern int yydebug;
 extern int errorCount;
 extern int warningCount;
 
-static char *optionString = "dh";
+static char *optionString = "dhc";
 
 void Usage(char *program)
 {
     cerr << "Usage:\n"
-         << program << " [-d] [filename]\n"
+         << program << " [-d|-c] [filename]\n"
          << program << " -h\n"
          << "\n"
          << "Options:\n"
          << "  -h               Shows this message.\n"
-         << "  -d               Turn on parser debugging.\n";
+         << "  -d               Turn on parser debugging.\n"
+         << "  -c               Generates a C-representation of the program\n";
 
     exit(1);
 }
@@ -37,11 +38,12 @@ int main(int argc, char **argv)
     // Set up the symbol table
     //
 
-    currentFunction = new FunctionInformation("main.");
+    currentFunction = new FunctionInformation("main");
     kIntegerType    = new TypeInformation("integer", sizeof(long));
     kRealType       = new TypeInformation("real", sizeof(double));
 
     kFPrintFunction = new FunctionInformation("putreal");
+    FunctionInformation *kPLReadFunction = new FunctionInformation("putline");
     kIPrintFunction = new FunctionInformation("putint");
     kFReadFunction = new FunctionInformation("getreal");
     kIReadFunction = new FunctionInformation("getint");
@@ -52,6 +54,7 @@ int main(int argc, char **argv)
     kFPrintFunction->AddParameter("x", kRealType);
     kIReadFunction->SetReturnType(kIntegerType);
     kFReadFunction->SetReturnType(kRealType);
+    kIReadFunction->SetReturnType(kIntegerType);
     
     currentFunction->AddSymbol(kIntegerType);
     currentFunction->AddSymbol(kRealType);
@@ -59,6 +62,7 @@ int main(int argc, char **argv)
     currentFunction->AddSymbol(kFPrintFunction);
     currentFunction->AddSymbol(kIReadFunction);
     currentFunction->AddSymbol(kFReadFunction);
+    currentFunction->AddSymbol(kPLReadFunction);
 
     //
     // Check command-line arguments
@@ -78,7 +82,13 @@ int main(int argc, char **argv)
             break;
         case '?':
             Usage(argv[0]);
-            break;
+            break;    
+	case 'c':
+	  std::cout << "/*Using standard-library*/\n";
+	  std::cout << "#include \"stl.h\"\n";
+	  SymbolInformation::outputFormat = SymbolInformation::kCFormat;
+	  currentFunction->outputFormat = SymbolInformation::kCFormat;
+	  break;
         }
     }
 
@@ -100,8 +110,7 @@ int main(int argc, char **argv)
     // Compile the input
     //
 
-    yyparse();
-
-    return 0;
+    int retcode = yyparse();
+    return retcode;
 }
     
diff --git a/lab3-4/stl.h b/lab3-4/stl.h
new file mode 100644
index 0000000..960f515
--- /dev/null
+++ b/lab3-4/stl.h
@@ -0,0 +1,49 @@
+/*
+ The quite limited standard library/runtime for your language
+--
+John Tinnerholm
+*/
+
+#include <math.h>
+#include <stdio.h>
+
+//Array preprocessing
+#define array_real(X) real([X])
+#define array_integer(X) real([X])
+
+#define real double
+#define integer long
+#define conditional bool
+#define bool integer
+
+
+integer putint(long x) {
+  printf("%ld", x);
+  return 0;
+}
+
+integer putreal(double x) {
+  printf("%lf", x);
+  return 0;
+}
+
+double getreal() {
+  double r;
+  scanf("%lf", &r);
+  return r;
+}
+
+double getint() {
+  long l;
+  scanf("%ld", &l);
+  return l;
+}
+
+
+integer putline()
+{
+  printf("\n");
+  return 0;
+}
+
+
diff --git a/lab3-4/symtab.cc b/lab3-4/symtab.cc
index e023ac8..74a3233 100644
--- a/lab3-4/symtab.cc
+++ b/lab3-4/symtab.cc
@@ -7,7 +7,8 @@ using namespace std;
 
 /*
  * Global variables
- */
+*/
+
 
 FunctionInformation *currentFunction;
 TypeInformation     *kIntegerType;
@@ -42,6 +43,9 @@ ostream& SymbolInformation::print(ostream& o)
     case kShortFormat:
         o << id;
         break;
+    case kCFormat:
+        o << id;
+        break;		
     default:
         o << "Bad output format\n";
         abort();
@@ -55,7 +59,7 @@ ostream& TypeInformation::print(ostream& o)
     switch (outputFormat)
     {
     case kFullFormat:
-        o << "TypeInformation @ " << (void*)this << '\n';
+        o << "/*TypeInformation @ " << (void*)this << '\n';
         o << "  Tag:   " << tag << '\n';
         o << "  ID:    " << id << '\n';
         o << "  Table: " << (void*)table << '\n';
@@ -64,7 +68,8 @@ ostream& TypeInformation::print(ostream& o)
         o << '\n';
         o << "  Dimensions:  " << arrayDimensions << '\n';
         o << "  Size:  " << size << '\n';
-
+	o << "*/";
+	break;
     case kSummaryFormat:
         o << (void*)this << ' ';
         if (elementType != NULL)
@@ -79,7 +84,7 @@ ostream& TypeInformation::print(ostream& o)
             o << id;
         }
         
-        o << " [" << size << "]";
+        o << " [" << size << "] ";
         break;
         
     case kShortFormat:
@@ -94,7 +99,16 @@ ostream& TypeInformation::print(ostream& o)
             o << id;
         }
         break;
-        
+    case kCFormat:
+      if (elementType != NULL)
+        {
+             o << "[" << arrayDimensions << "]";
+        }
+        else
+        {
+	  o << id;
+        }
+        break;
 
     default:
         o << "Bad output format\n";
@@ -117,7 +131,7 @@ ostream& VariableInformation::print(ostream& o)
         o << '\n';
         o << "  Next:  " << (void*)prev << ' ';
         if (prev) o << SummarySymbols << prev << LongSymbols;
-        o << '\n';
+        o << "\n";
         break;
 
     case kSummaryFormat:
@@ -133,6 +147,10 @@ ostream& VariableInformation::print(ostream& o)
         o << id;
         break;
 
+    case kCFormat:
+      o << id;
+      break;
+
     default:
         o << "Bad output format\n";
         abort();
@@ -148,7 +166,7 @@ ostream& FunctionInformation::print(ostream& o)
     switch (outputFormat)
     {
     case kFullFormat:
-        o << "FunctionInformation @ " << (void*)this << '\n';
+        o << "  FunctionInformation @ " << (void*)this << '\n';
         o << "  Tag:     " << tag << '\n';
         o << "  ID:      " << id << '\n';
         o << "  Table:   " << (void*)table << '\n';
@@ -169,6 +187,7 @@ ostream& FunctionInformation::print(ostream& o)
                 tmp = tmp->prev;
             }
             o << LongSymbols;
+	    o << "/*";
         }
         else
         {
@@ -185,21 +204,22 @@ ostream& FunctionInformation::print(ostream& o)
                 tmp = tmp->prev;
             }
             o << LongSymbols;
+	    o << "\n";
         }
         else
         {
             o << "  Locals: none\n";
         }
         
-        o << "  Body:  " << (void*)body << '\n';
+        o << "Body:  " << (void*)body << '\n';
         if (body) o << body;
-        o << '\n';
+        o << "*/\n";
 
         o << "  Quads: " << (void*)quads << '\n';
         if (quads) o << quads;
-        o << '\n';
+        o << "\n";
         
-        o << symbolTable;
+        o << "\n" << symbolTable << "\n";
         break;
 
     case kSummaryFormat:
@@ -222,6 +242,60 @@ ostream& FunctionInformation::print(ostream& o)
     case kShortFormat:
         o << id;
         break;
+
+    case kCFormat:
+      	/*C-Code preamble*/
+	if (returnType == NULL) {
+	  o << "void\n";
+	} else {
+	  o << returnType << "\n";
+	}
+	    
+	o << "" << id << "(";
+	//Parameters
+	if (lastParam != NULL)
+        {
+            tmp = lastParam;
+            while (tmp != NULL)
+            {
+	      if (tmp->type->elementType != NULL){ //Array... 
+		o << tmp->type->elementType << "*" << "\t";
+	      } else {
+		//		o << tmp->type->elementType;
+		o << tmp->type << "\t";
+	      }
+	      if (tmp->prev == NULL) {
+		o << tmp->id;
+	      } else {
+		o << tmp->id << ",";
+	      }
+	      tmp = tmp->prev;
+            }
+        }
+	o << ")\n";
+	/* Generate C-Code for the body! */
+	o << "{\n";
+	if (lastLocal)
+        {
+	  o << "//Locals:\n";
+            tmp = lastLocal;
+            while (tmp != NULL)
+            {
+	      if (tmp->type->elementType != NULL){ //Array...
+		o << tmp->type->elementType;
+		o << "\t";
+		o << tmp;
+		o << tmp->type << ";\n";
+	      }
+	      else {
+		o << tmp->type << "\t" << tmp << ";\n";
+	      }
+	      tmp = tmp->prev;
+            }
+        }
+	quads->print_c(o);
+	o << "}\n";
+	break;
         
     default:
         o << "Bad output format.\n";
@@ -382,7 +456,7 @@ VariableInformation *FunctionInformation::TemporaryVariable(TypeInformation *typ
 
     temporaryCount += 1;
 
-    info = new VariableInformation(::string("T:") + (int)temporaryCount, type);
+    info = new VariableInformation(::string("T_") + (int)temporaryCount, type);
     info->prev = NULL;
     AddSymbol(info);
 
@@ -554,6 +628,12 @@ ostream& LongSymbols(ostream& o)
     return o;
 }
 
+ostream& CFormat(ostream& o)
+{
+    SymbolInformation::outputFormat = SymbolInformation::kCFormat;
+    return o;
+}
+
 ostream& SummarySymbols(ostream& o)
 {
     SymbolInformation::outputFormat = SymbolInformation::kSummaryFormat;
diff --git a/lab3-4/symtab.hh b/lab3-4/symtab.hh
index 9933ed0..7e06b3e 100644
--- a/lab3-4/symtab.hh
+++ b/lab3-4/symtab.hh
@@ -22,6 +22,7 @@ extern FunctionInformation *kFPrintFunction;
 extern FunctionInformation *kIPrintFunction;
 extern FunctionInformation *kFReadFunction;
 extern FunctionInformation *kIReadFunction;
+extern FunctionInformation *kIReadFunction;
 extern TypeInformation *kRealType;
 extern TypeInformation *kIntegerType;
 
@@ -90,13 +91,10 @@ protected:
     friend class SymbolTable;
     friend ostream& LongSymbols(ostream&);
     friend ostream& SummarySymbols(ostream&);
-    friend ostream& ShortSymbols(ostream&);
-
-    typedef enum { kFullFormat, kSummaryFormat, kShortFormat } tFormatType;
-    
-    static tFormatType outputFormat;
-    
+    friend ostream& ShortSymbols(ostream&);        
 public:
+    typedef enum { kFullFormat, kSummaryFormat, kShortFormat, kCFormat } tFormatType;
+    static tFormatType outputFormat;
     SymbolInformationType       tag;
     ::string                      id;
     SymbolTable                *table;
@@ -233,6 +231,7 @@ public:
 
 ostream& ShortSymbols(ostream& o);
 ostream& LongSymbols(ostream& o);
+ostream& CFormat(ostream& o);
 
 
 #endif
diff --git a/lab3-4/test/README.md b/lab3-4/test/README.md
new file mode 100644
index 0000000..3516330
--- /dev/null
+++ b/lab3-4/test/README.md
@@ -0,0 +1,33 @@
+# This file contains various files for testing 
+
+## expression_test.prog
+This program simple executes and print simple expressions 
+## factorial_test.prog
+This program checks if functions and if/else statements are handled correctly.
+Checks the factorial function 
+## fibonacci_test.prog 
+Similar to the factorial test, also tests recursions
+## sort_test.prog 
+This program simple executes selection sort on an unsorted array 
+## *output_ref
+These are references files specifing the expected output from the programs above. 
+It is used by codegen-test.sh 
+## How to test? 
+To test a program simply execute codegen-test.sh in the parent directory.
+
+```
+bash codegen-test.sh
+```
+## How do I compile my own program? 
+Invoke the compiler. 
+Pipe the output to a file with the suffix.c 
+```
+compiler -c > <name>.c 
+```
+Do not use the -d flag when doing this. 
+
+Then compile this file with
+```
+gcc -lm <name.c>
+``
+
diff --git a/lab3-4/test/expression_output_ref b/lab3-4/test/expression_output_ref
new file mode 100644
index 0000000..06f0020
--- /dev/null
+++ b/lab3-4/test/expression_output_ref
@@ -0,0 +1,10 @@
+3
+0
+4
+1
+4
+3.000000
+0.000000
+4.000000
+1.000000
+4.000000
diff --git a/lab3-4/test/expression_test.prog b/lab3-4/test/expression_test.prog
new file mode 100644
index 0000000..f042d94
--- /dev/null
+++ b/lab3-4/test/expression_test.prog
@@ -0,0 +1,41 @@
+/*
+  This test checks if basic expressions work.
+  Author: John Tinnerholm
+*/
+declare
+    a : integer;
+    b : real;
+begin
+/*Testing integers*/
+ a := 1 + 2;
+ putint(a); //Should be 3
+ putline();
+ a := 2 - 2;
+ putint(a); //Should be 0
+ putline();
+ a := 2 * 2;
+ putint(a); //Should be 4
+ putline();
+ a := 2 / 2;
+ putint(a); //Should be 1
+ putline();
+ a := 2 ^ 2;
+ putint(a); //Should be 4
+ putline();
+/*Testing reals*/
+ b := 1.0 + 2.0;
+ putreal(b); //Should be 3
+ putline();
+ b := 2.0 - 2.0;
+ putreal(b); //Should be 0
+ putline();
+ b := 2.0 * 2.0;
+ putreal(b); //Should be 4
+ putline();
+ b := 2.0 / 2.0;
+ putreal(b); //Should be 1
+ putline();
+ b := 2.0 ^ 2.0;
+ putreal(b); //Should be 4
+ putline();
+end;
diff --git a/lab3-4/test/factorial_output_ref b/lab3-4/test/factorial_output_ref
new file mode 100644
index 0000000..97de8a4
--- /dev/null
+++ b/lab3-4/test/factorial_output_ref
@@ -0,0 +1,2 @@
+3
+120
diff --git a/lab3-4/test/factorial_test.prog b/lab3-4/test/factorial_test.prog
new file mode 100644
index 0000000..3229089
--- /dev/null
+++ b/lab3-4/test/factorial_test.prog
@@ -0,0 +1,24 @@
+/*
+  This test checks if the factorial function works
+  Author: John Tinnerholm
+*/
+declare
+    a : integer;
+function fac (x : integer) : integer
+begin
+    if x == 0 then
+      begin
+        return 1;
+      end
+    else
+      begin
+        return x * fac(x - 1);
+      end if;
+end;
+begin
+ a := 1+2;
+ putint(a); //Should be 3
+ putline();
+ putint(fac(5)); //Should be 120
+ putline();
+end;
diff --git a/lab3-4/test/fibonacci_output_ref b/lab3-4/test/fibonacci_output_ref
new file mode 100644
index 0000000..f6cdd59
--- /dev/null
+++ b/lab3-4/test/fibonacci_output_ref
@@ -0,0 +1,10 @@
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
diff --git a/lab3-4/test/fibonacci_test.prog b/lab3-4/test/fibonacci_test.prog
new file mode 100644
index 0000000..a6ebcc1
--- /dev/null
+++ b/lab3-4/test/fibonacci_test.prog
@@ -0,0 +1,30 @@
+/*
+  This test checks the fibonacci function
+  Author: John Tinnerholm
+*/
+declare
+    a : integer;
+function fib (x : integer) : integer
+begin
+    if x == 0 then
+      begin
+        return 0;
+      end
+    elseif x == 1 then
+      begin
+        return 1;
+      end
+    else
+      begin
+        return fib(x - 1) + fib(x-2);
+      end if;
+end;
+begin
+    a := 0;
+    while a < 10 do
+    begin
+	putint(fib(a));
+	putline();
+	a := a + 1;
+    end while;
+end;
diff --git a/lab3-4/test/simple_array_output_ref b/lab3-4/test/simple_array_output_ref
new file mode 100644
index 0000000..283c4a1
--- /dev/null
+++ b/lab3-4/test/simple_array_output_ref
@@ -0,0 +1,5 @@
+1.000000
+2.000000
+3.000000
+4.000000
+5.000000
diff --git a/lab3-4/test/simple_array_test.prog b/lab3-4/test/simple_array_test.prog
new file mode 100644
index 0000000..734c57d
--- /dev/null
+++ b/lab3-4/test/simple_array_test.prog
@@ -0,0 +1,27 @@
+/*
+ This program initializes an array with 5 elements.
+ it then prints said array.
+ Author: John Tinnerholm
+*/
+declare
+     i : integer;
+     ii : real;
+    elements : array 5 of real;
+begin
+    i := 0;
+    ii := 0.;
+    while i < 5  do
+    begin
+        ii := 1.0 + ii;
+        elements[i] := ii;
+        i := i + 1;
+    end while;
+    /* Should print 1,2,3,4,5 */
+    i := 0;
+    while i < 5 do
+    begin
+        putreal(elements[i]);
+	putline();
+	i := i + 1;
+    end while;
+end;
\ No newline at end of file
diff --git a/lab3-4/test/simple_array_test_output_ref b/lab3-4/test/simple_array_test_output_ref
new file mode 100644
index 0000000..283c4a1
--- /dev/null
+++ b/lab3-4/test/simple_array_test_output_ref
@@ -0,0 +1,5 @@
+1.000000
+2.000000
+3.000000
+4.000000
+5.000000
diff --git a/lab3-4/test/simple_simple_array.prog b/lab3-4/test/simple_simple_array.prog
new file mode 100644
index 0000000..c0de812
--- /dev/null
+++ b/lab3-4/test/simple_simple_array.prog
@@ -0,0 +1,12 @@
+/*
+ We write to the first index of an array.
+ We then print the result
+ Author: John Tinnerholm
+*/
+declare
+    elements : array 1 of real;
+begin
+  elements[0] := 12.;
+  putreal(elements[0]);	
+  putline();
+end;
\ No newline at end of file
diff --git a/lab3-4/test/sort_test.prog b/lab3-4/test/sort_test.prog
new file mode 100644
index 0000000..77b92d5
--- /dev/null
+++ b/lab3-4/test/sort_test.prog
@@ -0,0 +1,63 @@
+/*
+  Implementation of selection sort.
+  This checks if nested while loop works among other things..
+  Author: John Tinnerholm
+*/
+declare
+     i : integer;
+     j : integer;
+    tmp1 : integer;
+    current_min : integer;
+    length_of_array : integer;
+    array_to_be_sorted : array 10 of integer;
+begin
+   i := 0;
+   j := 0;
+   length_of_array := 10;
+
+   array_to_be_sorted[0] := 10;
+   array_to_be_sorted[1] := 9;
+   array_to_be_sorted[2] := 8;
+   array_to_be_sorted[3] := 7;
+   array_to_be_sorted[4] := 6;
+   array_to_be_sorted[5] := 5;
+   array_to_be_sorted[6] := 4;
+   array_to_be_sorted[7] := 3;
+   array_to_be_sorted[8] := 2;
+   array_to_be_sorted[9] := 1;
+//Print unsorted array
+   while i < length_of_array do
+    begin
+        putint(array_to_be_sorted[i]);
+	putline();
+	i := i + 1;
+    end while;
+i := 0;
+j := 0;
+ while i < length_of_array - 1 do
+    begin
+       current_min := i;
+       j := i + 1;
+     while j < length_of_array do
+     begin
+	if array_to_be_sorted[current_min] > array_to_be_sorted[j] then
+	begin
+	   current_min := j;
+	end if;
+	j := j + 1;
+    end while;
+    tmp1 := array_to_be_sorted[i];
+    array_to_be_sorted[i] := array_to_be_sorted[current_min];
+    array_to_be_sorted[current_min] := tmp1;
+    i := i + 1;
+ end while;
+ putline();
+/* Print the sorted array*/
+  i := 0;
+  while i < length_of_array do
+  begin
+     putint(array_to_be_sorted[i]);
+     putline();
+     i := i + 1;
+  end while;
+end;
diff --git a/lab3-4/test/sort_test_output_ref b/lab3-4/test/sort_test_output_ref
new file mode 100644
index 0000000..5f1f826
--- /dev/null
+++ b/lab3-4/test/sort_test_output_ref
@@ -0,0 +1,21 @@
+10
+9
+8
+7
+6
+5
+4
+3
+2
+1
+
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
-- 
GitLab