dumptype.cc
//
// 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);
}