From: Jeremy Yallop <jeremy.yallop@ed.ac.uk>
To: caml-list@inria.fr
Subject: Re: [Caml-list] Labelling trees
Date: Fri, 08 Jun 2007 00:48:43 +0100 [thread overview]
Message-ID: <4668995B.4090706@ed.ac.uk> (raw)
In-Reply-To: <1181158983.9266.12.camel@Blefuscu>
David Teller wrote:
> I'm currently in the very first stages of writing down a prototype
> implementation of a type checker. At the moment, I'm looking for "the
> nicest" way of labelling my abstract syntax tree with type annotations
> -- without corrupting the AST at all, if possible.
My favourite encoding of annotated ASTs uses recursive modules and
polymorphic variants. Instead of supplying type parameters for the
annotations and open recursion you can tie the knot using a recursive
module and some `with'-constraints on the signature. Closing the
recursion twice (with different constraints) gives you annotated and
unannotated trees.
Here's an example from an implementation of the core of SML. There
are 7 mutually-recursive types and three annotation types. I hope
it's clear enough how it'd scale up to a more complicated data
structure. Also, there are some type definitions missing, but you
should be able to fill them in easily enough.
First, a module type definition, listing all of the types involved.
This will be used in lieu of the type parameters that you'd normally
use for encoding open recursion.
module type ExpSig =
sig
type atexp
type exprow
type exp
type valdec
type match_
type mrule
type valbind
type pat
end
Now the actual datatype definitions. Notice that we use `T.t' instead
of 't' at each recursive point. The type `pat' is a parameter
although it's not defined here because we'll want to use annotated and
unannotated patterns inside annotated and unannotated expressions.
The module component (T) here is analagous to a functor argument of a
module.
module type Exp =
sig
module T : ExpSig
type atexp = [
`scon of scon
| `vid of vid
| `record of T.exprow option
| `let_ of T.valdec * T.exp
| `paren of T.exp ]
and exp = [
`atexp of T.atexp
| `apply of T.exp * T.atexp
| `typed of T.exp * ty
| `fn of T.match_ ]
and mrule = T.pat * T.exp
and valdec = [
`val_ of tyvarseq * T.valbind
| `local of T.valdec * T.valdec
| `empty
| `valdecs of T.valdec * T.valdec ]
and valbind = [
`bindings of (T.pat * T.exp * T.valbind option)
| `rec_ of T.valbind ]
and match_ = [`match_ of T.mrule * T.match_ option]
and exprow = [`exprow of (label * T.exp * T.exprow option)]
type pat = T.pat
end
Finally, we tie the knot, first directly (to obtain unannotated
trees):
module rec UntypedExp : ExpSig
with type atexp = UntypedExp'.atexp
and type exprow = UntypedExp'.exprow
and type exp = UntypedExp'.exp
and type match_ = UntypedExp'.match_
and type mrule = UntypedExp'.mrule
and type valdec = UntypedExp'.valdec
and type valbind = UntypedExp'.valbind
and type pat = UntypedPat.pat
= UntypedExp
and UntypedExp' : Exp with module T = UntypedExp = UntypedExp'
and then adding annotations for each node type
module rec TypedExp : ExpSig
with type atexp = TypedExp'.atexp * type_
and type exprow = TypedExp'.exprow * rowtype
and type exp = TypedExp'.exp * type_
and type valdec = TypedExp'.valdec * valenv
and type match_ = TypedExp'.match_ * type_
and type mrule = TypedExp'.mrule * type_
and type valbind = TypedExp'.valbind * valenv
and type pat = TypedPat.pat
= TypedExp
and TypedExp' : Exp with module T = TypedExp = TypedExp'
Using modules to collect the definitions together has various other
advantages; for example, it's easy(ish) to write an evaluator that
works for both annotated and unannotated expressions using functors.
Hope this helps,
Jeremy.
prev parent reply other threads:[~2007-06-07 23:55 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-06 19:43 David Teller
2007-06-06 21:22 ` [Caml-list] " Christophe Raffalli
2007-06-07 1:00 ` skaller
2007-06-07 14:26 ` Till Varoquaux
2007-06-07 23:09 ` skaller
2007-06-08 9:52 ` Till Varoquaux
2007-06-08 10:32 ` skaller
2007-06-07 14:25 ` Christian Stork
2007-06-07 23:48 ` Jeremy Yallop [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4668995B.4090706@ed.ac.uk \
--to=jeremy.yallop@ed.ac.uk \
--cc=caml-list@inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox