LRDE Tiger Compiler  1.34a $Id: 7fef12e1f5fa43449d667a0eec1d837c40fc1202 $
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
exp.hh File Reference

Classes Exp, Ex, Cx, Nx, and Ix. More...

#include <iosfwd>
#include <tree/all.hh>
#include <temp/fwd.hh>
#include <frame/frame.hh>
#include <translate/exp.hxx>
Include dependency graph for exp.hh:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  translate::Exp
 Root for all the following classes. More...
class  translate::Cx
 Natural representation for conditionals. More...
class  translate::Ex
 Natural representation for expressions. More...
class  translate::Nx
 Natural representation for statements. More...
class  translate::Ix
 Specialization of Exp for branchings. More...

Namespaces

namespace  translate
 Translation from ast::Ast to tree::Node.

Typedefs

typedef misc::ref< Exp > translate::rExp
 Reference counted Exp pointer.
typedef misc::ref< Cx > translate::rCx
 Reference counted Cx pointer.
typedef misc::ref< Ex > translate::rEx
 Reference counted Ex pointer.
typedef misc::ref< Nx > translate::rNx
 Reference counted Nx pointer.
typedef misc::ref< Ix > translate::rIx
 Reference counted Ix pointer.

Functions

std::ostream & translate::operator<< (std::ostream &ostr, const Exp &exp)
 Report exp on ostr.

Detailed Description

Classes Exp, Ex, Cx, Nx, and Ix.

The class defined in this file are helping tools for the translation.

The idea is quite simple: at some moment the tree::expressions should actually be used as simple tree::statement. Also, it would be stupid to keep something like `a < b' as an expression which gives one or zero, and then, when used in a condition implement something like `if (a < b) <> 0 then...'.

The idea is that every tree::expression or tree::statement will be kept in a structure which reflects its* natural* usage, but this structure must be able to present an entity (such as a tree::expression) as a statement when needed, or as a condional etc.

There are basically three families (actually, there are four, the fourth one being defined further below):

  • Ex

    The family of what is naturally a tree::expression, i.e., something which has a value. Can be used as an expression, or statement, or conditional (in which case what is important is whether it evaluates to zero, or not).

  • Nx

    The family of the statements, i.e., what has no value. Can only be used as a statement: it is abornal (hence abort ()) to use it as an expression or a conditional. This should never happen: the type checking actually guarantees it never happens.

  • Cx

    The family of the conditionals, i.e., what used to be written with relative operators in Tiger (<, <> etc.). Since our goal is to translate a `if a < b then...' into `CJUMP(<, a, b, ...)', we need to remember what is the operator, and what are its arguments. Of course this can be used as a conditional (CJUMP), as an expression (in which case we must return 0 or 1), or as a statement (in case someone wrote `a < b' alone in Tiger for instance, even if it looks brain dead).

So we have Ex, Nx and Cx which we want to be able to read as if they were Ex (in which case we will un-Ex or de-Ex them thanks to un_ex (), or read as Nx thanks to un_nx (), or finally un_cx () if used as conditional.

un_ex and un_nx need no argument. But un_cx means building a CJUMP. A CJUMP, when you build it, needs 5 args, the operator and two arguments (which you always have or can easily simulate), and two NAMEs which correspond to the THEN and the ELSE. So naturally un_cx will need two additional arguments: the tree::Label to which you are branching.

Using this scheme works fine.

But there is room for improvement. Consider the following program:

if if 1 then 2 else 3 then 4 else 5

Using the implementation suggested above, you will first compute the result of the inner if-then-else into a temporary, and then check whether this temporary is 0 or not. A better implementation would try to branch to `4' at the end of the `2' is 2 appears to be different from 0, otherwise branch to 5, and likewise in the else branch.

In other words, instead of having a cascade of `set a temporary, and then decode the temporary', the idea is to directly branch from the then and else parts. This will typically give mcuh better code for things like

if 0 < a && a < b && b < c && c < 3 then impossible := 1

In order to do this, you need to keep the structure of the if-then-else, i.e., keep the test, then and else clauses separated. An extra class is needed, named, Ix.

The memory management is quite simple: calling un_xx will delete the object. This means that each Exp object must be un_xx'ed exactly once: if less, there is a memory leak, if more, then a free'd object is reused.