Compiler projects using llvm

//
// See copyright.h for copyright notice and limitation of liability
// and disclaimer of warranty provisions.
//
#include "copyright.h"

#include "cool_tree.h"
#include "tree.h"
#include "utils.h"

//////////////////////////////////////////////////////////////////
//
//  dumptype.cc
//
//  dumptype defines a simple recursive traversal of the abstract
//  syntax tree (AST) that prints each node and any associated
//  type information.  Use dump_with_types to inspect the results of
//  type inference.
//
//  dump_with_types takes two argumenmts:
//     an output stream
//     an indentation "n", the number of blanks to insert at the beginning of
//                         a new line.
//
//  dump_with_types is just a simple pretty printer, formatting the output
//  to show the AST relationships between nodes and their types.
//  dump_type is a virtual function, with a separate implementation for
//  each kind of AST node.
//
//  dump_type prints the type of an Expression on the output stream,
//  after indenting the correct number of spaces.  A check is made to
//  see if no type is assigned to the node.
//
//  Note that the "type" member referred to here is inherited from tree_node
//  by all subclasses of Expression_class.  Note also that dump_type is
//  defined for the Phylum Expression here, and is therefore inherited by
//  every distinct subclass of Expression.
//

void Expression_class::dump_type(std::ostream &stream, int n) {
  if (type) {
    stream << pad(n) << ": " << type->get_string() << std::endl;
  } else {
    stream << pad(n) << ": _no_type" << std::endl;
  }
}

void dump_line(std::ostream &stream, int n, tree_node *t) {
  stream << pad(n) << "#" << t->get_line_number() << "\n";
}

//
//  program_class prints "program" and then each of the
//  component classes of the program, one at a time, at a
//  greater indentation. The recursive invocation on
//  "classes->nth(i)->dump_with_types(...)" shows how useful
//  and compact virtual functions are for this kind of computation.
//
//  Note the use of the iterator to cycle through all of the
//  classes.  The methods first, more, next, and nth on AST lists
//  are defined in tree.h.
//
void program_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_program\n";
  for (int i = classes->first(); classes->more(i); i = classes->next(i)) {
    classes->nth(i)->dump_with_types(stream, n + 2);
  }
}

//
// Prints the components of a class, including all of the features.
// Note that printing the Features is another use of an iterator.
//
void class__class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_class\n";
  dump_Symbol(stream, n + 2, name);
  dump_Symbol(stream, n + 2, parent);
  stream << pad(n + 2) << "\"";
  print_escaped_string(stream, filename->get_string());
  stream << "\"\n" << pad(n + 2) << "(\n";
  for (int i = features->first(); features->more(i); i = features->next(i))
    features->nth(i)->dump_with_types(stream, n + 2);
  stream << pad(n + 2) << ")\n";
}

//
// dump_with_types for method_class first prints that this is a method,
// then prints the method name followed by the formal parameters
// (another use of an iterator, this time access all of the list members
// of type Formal), the return type, and finally calls dump_type recursively
// on the method body.

void method_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_method\n";
  dump_Symbol(stream, n + 2, name);
  for (int i = formals->first(); formals->more(i); i = formals->next(i))
    formals->nth(i)->dump_with_types(stream, n + 2);
  dump_Symbol(stream, n + 2, return_type);
  expr->dump_with_types(stream, n + 2);
}

//
//  attr_class::dump_with_types prints the attribute name, type declaration,
//  and any initialization expression at the appropriate offset.
//
void attr_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_attr\n";
  dump_Symbol(stream, n + 2, name);
  dump_Symbol(stream, n + 2, type_decl);
  init->dump_with_types(stream, n + 2);
}

//
// formal_class::dump_with_types dumps the name and type declaration
// of a formal parameter.
//
void formal_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_formal\n";
  dump_Symbol(stream, n + 2, name);
  dump_Symbol(stream, n + 2, type_decl);
}

//
// branch_class::dump_with_types dumps the name, type declaration,
// and body of any case branch.
//
void branch_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_branch\n";
  dump_Symbol(stream, n + 2, name);
  dump_Symbol(stream, n + 2, type_decl);
  expr->dump_with_types(stream, n + 2);
}

//
// assign_class::dump_with_types prints "assign" and then (indented)
// the variable being assigned, the expression, and finally the type
// of the result.  Note the call to dump_type (see above) at the
// end of the method.
//
void assign_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_assign\n";
  dump_Symbol(stream, n + 2, name);
  expr->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

//
// static_dispatch_class::dump_with_types prints the expression,
// static dispatch class, function name, and actual arguments
// of any static dispatch.
//
void static_dispatch_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_static_dispatch\n";
  expr->dump_with_types(stream, n + 2);
  dump_Symbol(stream, n + 2, type_name);
  dump_Symbol(stream, n + 2, name);
  stream << pad(n + 2) << "(\n";
  for (int i = actual->first(); actual->more(i); i = actual->next(i))
    actual->nth(i)->dump_with_types(stream, n + 2);
  stream << pad(n + 2) << ")\n";
  dump_type(stream, n);
}

//
//   dispatch_class::dump_with_types is similar to
//   static_dispatch_class::dump_with_types
//
void dispatch_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_dispatch\n";
  expr->dump_with_types(stream, n + 2);
  dump_Symbol(stream, n + 2, name);
  stream << pad(n + 2) << "(\n";
  for (int i = actual->first(); actual->more(i); i = actual->next(i))
    actual->nth(i)->dump_with_types(stream, n + 2);
  stream << pad(n + 2) << ")\n";
  dump_type(stream, n);
}

//
// cond_class::dump_with_types dumps each of the three expressions
// in the conditional and then the type of the entire expression.
//
void cond_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_cond\n";
  pred->dump_with_types(stream, n + 2);
  then_exp->dump_with_types(stream, n + 2);
  else_exp->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

//
// loop_class::dump_with_types dumps the predicate and then the
// body of the loop, and finally the type of the entire expression.
//
void loop_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_loop\n";
  pred->dump_with_types(stream, n + 2);
  body->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

//
//  typcase_class::dump_with_types dumps each branch of the
//  the Case_ one at a time.  The type of the entire expression
//  is dumped at the end.
//
void typcase_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_typcase\n";
  expr->dump_with_types(stream, n + 2);
  for (int i = cases->first(); cases->more(i); i = cases->next(i))
    cases->nth(i)->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

//
//  The rest of the cases for Expression are very straightforward
//  and introduce nothing that isn't already in the code discussed
//  above.
//
void block_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_block\n";
  for (int i = body->first(); body->more(i); i = body->next(i))
    body->nth(i)->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void let_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_let\n";
  dump_Symbol(stream, n + 2, identifier);
  dump_Symbol(stream, n + 2, type_decl);
  init->dump_with_types(stream, n + 2);
  body->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void plus_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_plus\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void sub_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_sub\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void mul_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_mul\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void divide_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_divide\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void neg_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_neg\n";
  e1->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void lt_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_lt\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void eq_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_eq\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void leq_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_leq\n";
  e1->dump_with_types(stream, n + 2);
  e2->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void comp_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_comp\n";
  e1->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void int_const_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_int\n";
  dump_Symbol(stream, n + 2, token);
  dump_type(stream, n);
}

void bool_const_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_bool\n";
  dump_Boolean(stream, n + 2, val);
  dump_type(stream, n);
}

void string_const_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_string\n";
  stream << pad(n + 2) << "\"";
  print_escaped_string(stream, token->get_string());
  stream << "\"\n";
  dump_type(stream, n);
}

void new__class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_new\n";
  dump_Symbol(stream, n + 2, type_name);
  dump_type(stream, n);
}

void isvoid_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_isvoid\n";
  e1->dump_with_types(stream, n + 2);
  dump_type(stream, n);
}

void no_expr_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_no_expr\n";
  dump_type(stream, n);
}

void object_class::dump_with_types(std::ostream &stream, int n) {
  dump_line(stream, n, this);
  stream << pad(n) << "_object\n";
  dump_Symbol(stream, n + 2, name);
  dump_type(stream, n);
}