Changes between Version 1 and Version 2 of Annotations

Oct 10, 2008 1:06:34 PM (9 years ago)



  • Annotations

    v1 v2  
    6969 * You don't detect non-terminating or otherwise "wrong" annotations at compile time
    71  * It is difficult to specify an interface that allows adding annotations
     71 * It is difficult to specify an API that allows adding annotations to the program being compiled because that API needs both a value (that represents the annotation to plugins that may be later on in the pipeline) and a Core expression (that is inserted into the actual target program). What's more, you need to ensure that you are able to find a Typeable dictionary in the program being compiled that corresponds to the dictionary supplied by the user of the API.
     73 * Modules must refer to all the packages that contain data structures used in their annotations. This may be a particular problem if you wish to annotate values with things from the GHC package.
     75A better implementation is described in this section.
     77When compiling user-declared annotations (i.e. those in the actual text of the program being compiled):
     79 1. The type checker finds the Binary and Typeable instance for the annotation expression, ''e''
     80 2. The expression ''e'' is evaluated and serialized by the compiler using the Binary instance to obtain a sequence of bytes ''b''
     81 3. The TypeRep for ''e'' is obtained using the Typeable instance and transformed into a rose tree of strings (i.e. stripping out the Keys that will vary between GHC runs)
     82 4. The rose tree and ''b'' are both put into the interface file in the section recording annotations for the particular name under consideration
     84When a plugin adds another annotation:
     86 1. At the time the plugin is compiled the type checker finds a Binary and Typeable instance for the expression being added as an annotation, ''e''
     87 2. Compilation proceeds as in the user-declared case
     89When it comes time to read annotations back out in a GHC API client:
     91 1. At the time the client is compiled the type checker finds a Binary and Typeable instance for the target type of annotations
     92 2. The Typeable instance is turned into a rose tree as before and that tree is compared with those trees stored in the interface file being queried for any matches
     93 3. The byte sequences corresponding to those matches are deserialized according to that Binary instance
     95The key difference is that in this version '''dictionaries are not referenced by the files that store annotations''' - instead they are provided at the read site. Crucially, this assumes that the Binary and Typeable instances available at the two different times are coherent - and this is not enforced anywhere (you could end up with incoherence if you have some orphan instances). However, it does enable almost all the problems mentioned above to be overcome.
     97A disadvantage to this approach is that it does not allow functions to be stored in annotations. Under the SoC system, this was allowed:
     100{-# ANN f (\x -> x) #-}
     103But clearly there is no sensible Binary instance for ''a -> b'' in general.
     105Another disadvantage is that currently there is no standard Binary class in the Haskell libraries. We propose to add such a beast by adding [ Data.Binary] as a boot library and supporting automatic instance deriving for it in GHC. The advantages of doing this rather than somehow reusing GHCs inbuilt Binary class are that:
     107 * It is compiler independent
     109 * Much user code already has instances for Data.Binary (it is a popular Hackage package)
     111 * The binary package will be distributed with the Haskell Platform anyway because it is depended on by cabal-install
     113Disadvantages are that:
     115 * It adds another bytestring dependency to GHC (we already depend on bytestring but there was a suggestion that we would stop doing so)
     117 * GHCs own Binary instances for it's own data types cannot be reused straightforwardly. We contend that there are few cases where doing so would be useful, and if e.g. you want to refer to another thing rather than use a GHC Name you can use a TH Name. It would be difficult to piggyback the GHC Binary instance on Data.Binary because there is nowhere in Data.Binary to squirrel away the UserData GHCs Binary instance needs to do some of its stuff (but maybe you could deserialize to a function of type ''UserData -> Iface*'' to achieve the same effect...)
    73119== Future Work ==