|Maintainable compiler design? firstname.lastname@example.org (=?ISO-8859-1?Q?Christoffer_Lern=F6?=) (2009-07-27)|
|Re: Maintainable compiler design? email@example.com (Michiel) (2009-07-29)|
|Re: Maintainable compiler design? firstname.lastname@example.org (BGB / cr88192) (2009-07-29)|
|Re: Maintainable compiler design? email@example.com (Martin Ward) (2009-08-06)|
|Re: Maintainable compiler design? firstname.lastname@example.org (James Harris) (2009-08-06)|
|From:||Martin Ward <email@example.com>|
|Date:||Thu, 6 Aug 2009 10:24:10 +0100|
|Posted-Date:||06 Aug 2009 14:02:40 EDT|
On Wednesday 29 Jul 2009 18:12, Michiel <firstname.lastname@example.org> wrote:
> I now made lazy properties of the relevant AST nodes. For
> example, when I want to know the type of an expression, I'll just ask
> the expression node and it will, only once, compute its own type by
> querying its subexpressions, and so on.
> To be honest, I'm not sure if a design like this has been used before.
Back in the late 1980's when I developed the first version of the
FermaT Program Transformation System, one of the initial design
decisions was to use a version of Lisp as the implementation language.
AST nodes are implemented as Lisp cons cells, editing a node in the
tree involves building a new tree, sharing subtrees wherever
possible. This means that the original tree is still available via the
original root node.
Any function whose value depends only on the current node and its
decendants is "memoised": its value is computed once and then stored
in the AST node. Each AST node is a list of the form: (table, type,
value, c1, c2, ...) where cn is the nth component. "table" is a table
of values for functions. If the value is present in the table, it is
returned immediately, otherwise it is calculated and stored in the
table (using !set-cons so that the AST node is updated in-place). For
example, "variables used in this statement" is an example of such a
An additional advantage is that a naive implementation of a function,
which would take exponential time to execute, will execute in linear
time. For example, the "pretty printer" computes how many lines and
characters are needed to print the current AST node. If it fits on one
line, then the corresponding string is stored. In order to pretty
print a node we need to know how big each of its components are: so
the pretty printer gets called *twice* on each component. This would
lead to exponential execution time, if the result of the first call
were not cached in the node!
FermaT is available under the GPL from here:
email@example.com http://www.cse.dmu.ac.uk/~mward/ Erdos number: 4
G.K.Chesterton web site: http://www.cse.dmu.ac.uk/~mward/gkc/
Mirrors: http://www.gkc.org.uk and http://www.gkc.org.uk/gkc
Return to the
Search the comp.compilers archives again.