Starting from TC-3,
ast::VarDec inherits both from
ast::Escapable. Printing an
operator<< can be troublesome as this
operator may be overloaded for both
ast::VarDec’s base classes,
but not for
ast::VarDec itself, resulting in an ambiguous
overload resolution. The simplest way to get rid of this ambiguity is
to convert the
ast::VarDec object to the type of one of its base
classes (“upcast”) before printing it, either by creating a alias or
(more simply) by using the
const ast::VarDec& vardec = ... // Printing VARDEC as an ast::Dec using an intermediate // variable (alias). const ast::Dec& dec = vardec; ostr << dec; // Printing VARDEC as an ast::Escapable using an // on-the-fly conversion. ostr << static_cast<const ast::Escapable&>(vardec);
The computation of name bindings can be carried out in different ways, depending on the input language: Tiger without object constructs (“Panther”), Tiger with object constructs and Tiger with support for function overloading. These different flavors of the binding computation are performed by options --bindings-compute, --object-bindings-compute and --overfun-bindings-compute respectively (see Invoking tc in Tiger Compiler Reference Manual).
However, some subsequent task may later just require that an AST is annotated with bindings (“bound”) regardless of the technique used to compute these bindings. The purpose of the ‘bound’ task is to address this need: ensuring that one of the bindings task has been executed. This task can be considered as a disjunction (logical “or”) of the ‘bindings-compute’, ‘object-bindings-compute’ and ‘overfun-bindings-compute’ tasks, the first one being the default binding strategy.