CS143-Lab/assignments/PA3/dumptype.cc
2023-03-16 15:55:37 +00:00

475 lines
13 KiB
C++

//
// See copyright.h for copyright notice and limitation of liability
// and disclaimer of warranty provisions.
//
#include "copyright.h"
#include "cool.h"
#include "tree.h"
#include "cool-tree.h"
#include "utilities.h"
// defined in stringtab.cc
void dump_Symbol(ostream& stream, int padding, Symbol b);
// defined in cool.h
void dump_Boolean(ostream& stream, int padding, Boolean b);
//////////////////////////////////////////////////////////////////
//
// 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. Using virtual functions is an easy way to
// implement recursive tree traversals in C++; each kind of tree node
// has a virtual function that "knows" how to perform the part of
// the traversal for that one node. It may help to know the inheritance hierarchy
// of the classes that define the structure of the Cool AST. In the
// list below, the outer classes are the Phyla which group together
// related kinds of abstract tree nodes (e.g., the two kinds of Features
// and the many different kinds of Expression). The inner, indented classes
// inherit from the nearest Phyla class; these are the concrete classes that
// appear in the AST.
//
// Program_class
// program_class
//
// Class__class
// class_
//
// Feature_class
// method
// attr
//
// Formal_class
// formal
//
// Case_class
// branch_class
//
// Expression_class
// assign
// static_dispatch
// dispatch
// cond
// loop
// typcase
// block
// let
// plus
// sub
// mul
// divide
// neg
// lt
// eq
// leq
// comp
// int_const
// bool_const
// string_const
// new_
// isvoid
// no_expr
// object
//
// All of the Phyla inherit from the tree_node class, which has a member
// called type. The type member holds the type of the AST node.
//
// Some AST nodes have lists of other tree nodes as components. Lists in the
// AST are built using the class list_node defined in tree.h. The list
// classes in the Cool AST are:
//
// Classes a list of Class_
// Features a list of Feature
// Expressions a list of Expression
// Cases a list of Case
//
//
// 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(ostream& stream, int n)
{
if (type)
{ stream << pad(n) << ": " << type << endl; }
else
{ stream << pad(n) << ": _no_type" << endl; }
}
void dump_line(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(ostream& stream, int n)
{
dump_line(stream,n,this);
stream << pad(n) << "_object\n";
dump_Symbol(stream, n+2, name);
dump_type(stream,n);
}