diff --git a/lab3-4/Makefile b/lab3-4/Makefile index f5294b149b5dc292c8d8dc147cabf45ab5b550fd..a8e7fee206b62ace085a68116e30684de422b136 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 0000000000000000000000000000000000000000..4c4aa3aa0236dc9dc6cbd67fc113cd876cf8c10c --- /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 3212f7930d9ca0a8978fd0f662c2401c81b46e97..a49b68265f38f3674f39b3b18251ffd777455ef8 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,323 @@ 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: { + ::string itVar = sym1->id + "_" + ::string(int1); + o << setw(8) << "for(int " << itVar << " = 0 ;" + << setw(8) << itVar << "<" << int1 << ";" + << setw(8) << itVar << "++;)" //Increment & close for loop. + /*Assign the array*/ + << setw(8) << sym3 << "[" << itVar << "]" << "=" + << setw(8) << sym1 << "[" << itVar << "];"; + } + 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 d6eff4c1fdd4b8c6d4a04814f5282344eed47a63..0d9f2848b7f3b734a524e87939838ff0109afbfc 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 bf0b53055b650ad34cf55e509135836e013cb5c2..651111cefd5cd06aee23e259598525764c8e88bd 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 0000000000000000000000000000000000000000..960f51523906690b8d89bbd17a9cc8846b4b441d --- /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 e023ac8493f8fe8a66c8b6b4ede4386574552913..337f5fc4124e3b7024351c20c0951b11c843dd1c 100644 --- a/lab3-4/symtab.cc +++ b/lab3-4/symtab.cc @@ -42,6 +42,9 @@ ostream& SymbolInformation::print(ostream& o) case kShortFormat: o << id; break; + case kCFormat: + o << id; + break; default: o << "Bad output format\n"; abort(); @@ -64,7 +67,6 @@ ostream& TypeInformation::print(ostream& o) o << '\n'; o << " Dimensions: " << arrayDimensions << '\n'; o << " Size: " << size << '\n'; - case kSummaryFormat: o << (void*)this << ' '; if (elementType != NULL) @@ -94,7 +96,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"; @@ -133,6 +144,10 @@ ostream& VariableInformation::print(ostream& o) o << id; break; + case kCFormat: + o << id; + break; + default: o << "Bad output format\n"; abort(); @@ -185,6 +200,7 @@ ostream& FunctionInformation::print(ostream& o) tmp = tmp->prev; } o << LongSymbols; + o << '\n'; } else { @@ -193,8 +209,8 @@ ostream& FunctionInformation::print(ostream& o) o << " Body: " << (void*)body << '\n'; if (body) o << body; - o << '\n'; - + o << '\n'; + o << " Quads: " << (void*)quads << '\n'; if (quads) o << quads; o << '\n'; @@ -222,6 +238,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 +452,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 +624,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 9933ed03f02d86c8bad5e9293321b40d8dc9000f..7e06b3ede4fae221a4478d5d26018a81d8106a87 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 0000000000000000000000000000000000000000..d294d57c6bbb13201a1c19d26e65f388d43ab26c --- /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 0000000000000000000000000000000000000000..06f0020e3ee761427853c94ba35abb6e18a97bea --- /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 0000000000000000000000000000000000000000..f042d94bbe449ab655806245fe759e4e04625bef --- /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 0000000000000000000000000000000000000000..97de8a402e55404f9bec1b20743574090c2aa142 --- /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 0000000000000000000000000000000000000000..639e15bae1677ef627e36bb90a20fa61d4c4f00f --- /dev/null +++ b/lab3-4/test/factorial_test.prog @@ -0,0 +1,26 @@ +/* + 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 0000000000000000000000000000000000000000..f6cdd598aa3b34353a46a15bf8997de599e13686 --- /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 0000000000000000000000000000000000000000..c4c000bb0b50a635d773af1a311200693766b88d --- /dev/null +++ b/lab3-4/test/fibonacci_test.prog @@ -0,0 +1,33 @@ +/* + 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 0000000000000000000000000000000000000000..283c4a18310f8ea653f2a5fa3c6f2ce3ccbdddfe --- /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 0000000000000000000000000000000000000000..2cd55393ce1267290cc623b9c6456001a10868cf --- /dev/null +++ b/lab3-4/test/simple_array_test.prog @@ -0,0 +1,29 @@ +/* + 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 0000000000000000000000000000000000000000..283c4a18310f8ea653f2a5fa3c6f2ce3ccbdddfe --- /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 0000000000000000000000000000000000000000..c0de8122caf001febded932fe7d642aedb84e543 --- /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 0000000000000000000000000000000000000000..38356d3a33049a4c23f162f87f527e6deae99083 --- /dev/null +++ b/lab3-4/test/sort_test.prog @@ -0,0 +1,68 @@ +/* + 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 0000000000000000000000000000000000000000..5f1f82681404882692d82fe80c3cb68940968f19 --- /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 diff --git a/traces/trace-lab3.txt b/traces/trace-lab3.txt index 1c7a2d1c439f8d556d7956287a5851a56b366ef2..220a27ae9b74b6457ef552e9877ff19f72b86c89 100644 --- a/traces/trace-lab3.txt +++ b/traces/trace-lab3.txt @@ -1,18 +1,19 @@ -FunctionInformation @ 0x760330 +FunctionInformation @ 0x7fffd215ded0 Tag: 0 - ID: main. + ID: main Table: 0 Parent: 0 Returns: 0 Parameters: none Locals: - 0x76a2c0 f - 0x76a160 e - 0x76a000 d - 0x769ea0 c - 0x769d20 b - 0x769c88 a - Body: 0x76e7a8 + 0x7fffd2170370 f + 0x7fffd2170110 e + 0x7fffd216feb0 d + 0x7fffd216fc50 c + 0x7fffd216f9d0 b + 0x7fffd216f8c0 a + + Body: 0x7fffd217b020 StatementList (statement, preceding) +-CallStatement (call) | +-FunctionCall (function, arguments) [integer] @@ -78,25 +79,27 @@ StatementList (statement, preceding) Quads: 0 ------------------------------------------------------------------------------- -SymbolTable @ 0x760360 +SymbolTable @ 0x7fffd215df28 ------------------------------------------------------------------------------- -7 0x76a280 0x76a280 'real<11>.' array 11 of real [88] -11 0x764510 getint() -> integer -65 0x769c88 a : 0x761388 integer [4] -66 0x769d20 b : 0x7613c8 real [8] --> 0x769c88 a -67 0x769ea0 c : 0x769e60 'integer<10>.' array 10 of integer [40] --> 0x769d20 b -68 0x76a000 d : 0x769fc0 'integer<11>.' array 11 of integer [44] --> 0x769ea0 c -69 0x76a160 e : 0x76a120 'real<10>.' array 10 of real [80] --> 0x76a000 d -70 0x76a2c0 f : 0x76a280 'real<11>.' array 11 of real [88] --> 0x76a160 e -71 0x76c9f0 g(x) -> array 11 of integer -88 0x761388 0x761388 integer [4] -92 0x761408 putreal(x) -> integer -250 0x76a120 0x76a120 'real<10>.' array 10 of real [80] -511 0x76b630 fib(x) -> integer -519 0x76a310 fac(x) -> integer -603 0x7613c8 0x7613c8 real [8] -664 0x769fc0 0x769fc0 'integer<11>.' array 11 of integer [44] -775 0x762460 putint(x) -> integer -907 0x769e60 0x769e60 'integer<10>.' array 10 of integer [40] -918 0x7634b8 getreal() -> real +7 0x7fffd2170300 0x7fffd2170300 'real<11>.' array 11 of real [88] +11 0x7fffd2168320 getint() -> integer +65 0x7fffd216f8c0 a : 0x7fffd215ff80 integer [8] +66 0x7fffd216f9d0 b : 0x7fffd215fff0 real [8] --> 0x7fffd216f8c0 a +67 0x7fffd216fc50 c : 0x7fffd216fbe0 'integer<10>.' array 10 of integer [80] --> 0x7fffd216f9d0 b +68 0x7fffd216feb0 d : 0x7fffd216fe40 'integer<11>.' array 11 of integer [88] --> 0x7fffd216fc50 c +69 0x7fffd2170110 e : 0x7fffd21700a0 'real<10>.' array 10 of real [80] --> 0x7fffd216feb0 d +70 0x7fffd2170370 f : 0x7fffd2170300 'real<11>.' array 11 of real [88] --> 0x7fffd2170110 e +70 0x7fffd2170400 f(z; y; x) -> integer +71 0x7fffd21777b0 g(x) -> array 11 of integer +88 0x7fffd215ff80 0x7fffd215ff80 integer [8] +92 0x7fffd2160060 putreal(x) -> integer +250 0x7fffd21700a0 0x7fffd21700a0 'real<10>.' array 10 of real [80] +481 0x7fffd2162110 putline() -> no return type +511 0x7fffd21750c0 fib(x) -> integer +519 0x7fffd2172b00 fac(x) -> integer +603 0x7fffd215fff0 0x7fffd215fff0 real [8] +664 0x7fffd216fe40 0x7fffd216fe40 'integer<11>.' array 11 of integer [88] +775 0x7fffd21641c0 putint(x) -> integer +907 0x7fffd216fbe0 0x7fffd216fbe0 'integer<10>.' array 10 of integer [80] +918 0x7fffd2166270 getreal() -> real -------------------------------------------------------------------------------