Changes between Version 3 and Version 4 of Annotations


Ignore:
Timestamp:
Oct 13, 2008 3:09:43 PM (6 years ago)
Author:
batterseapower
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Annotations

    v3 v4  
    33== Motivation == 
    44 
    5 Annotations are useful for both [wiki:Plugins Plugins] and for users that would like to introspect more carefully on other, already-compiled modules. 
     5Annotations are useful for both [wiki:Plugins Plugins] and for users that would like to introspect more carefully on other, already-compiled modules. The concept is substantially similar to the annotation systems in such popular languages as C# and Java. Some use cases might be: 
     6 
     7 * Mark functions for modification by [wiki:Plugins Plugins] 
     8 
     9 * Store extra information relevant to a plugin but which is added by that plugin itself, such as a strictness analysis plugin that adds a demand signature to functions, which can be inspected later on by the same plugin when it comes to compile modules that depend on that one 
     10 
     11 * Specify extra documentation or comments for functions / types in the source code that could be extracted / nicely formatted by a later program 
     12 
     13 * Mark certain functions as tests, suitable for execution by a QuickCheck runner 
    614 
    715== State Of Play == 
     
    917An annotations system was implemented as part of the Compiler Plugins Summer of Code project (Summer 08). It is currently in the process of being revised before being committed to GHC HEAD. Details of the implementation are below. 
    1018 
    11 == Summer of Code Implementation == 
    12  
    13 Annotations look like this: 
     19== Summer of Code Implementation (OLD) == 
     20 
     21In this old implementation, annotations look like this: 
    1422 
    1523{{{ 
     
    107115Yet another disadvantage is that we will be doing some compile time compilation without it being introduced with the $() syntax that has heralded all such computation previously - instead, annotations are wrapped in a sort of "implicit splice". This might cause user confusion. 
    108116 
    109 Another disadvantage is that currently there is no standard Binary class in the Haskell libraries. We propose to add such a beast by adding [http://code.haskell.org/binary/ 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: 
     117=== Serialization Issues === 
     118 
     119Another disadvantage of this new annotations scheme is that currently there is no standard Binary class in the Haskell libraries. We propose to add such a beast by adding [http://code.haskell.org/binary/ 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: 
    110120 
    111121 * It is compiler independent 
     
    115125 * The binary package will be distributed with the Haskell Platform anyway because it is depended on by cabal-install 
    116126 
     127 * We can provide ''deriving (Binary)'' 
     128 
    117129Disadvantages are that: 
    118130 
     
    121133 * 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...) 
    122134 
     135 * By adding binary as a boot library distributed with GHC it will be impossible to upgrade binary separately from GHC itself without introducing problems. Consider packages P and Q, the binary package distributed with ghc (binary-1) and that installed at a later point by a user (binary-2), and the following web of dependencies: 
     136 
     137{{{ 
     138           P 
     139           |\____ 
     140          /      Q 
     141        ghc       \ 
     142        /       binary-1 
     143    binary-2 
     144}}} 
     145 
     146P depends indirectly on both binary versions. What happens if it tries to use an instance of Binary from binary-1 with ghc, or an instance of Binary from binary-2 with Q? They won't unify, so this is a (rather confusing) type error! Argh! What's more, this really might happen because Binary is exported in the API to access annotations: 
     147 
     148{{{ 
     149-- For normal GHC API users: 
     150getAnnotations :: (Typeable a, Binary a) => Name -> GHCM [a] 
     151 
     152-- Only for plugins adding their own annotations: 
     153getAnnotations :: (Typeable a, Binary a) => Name -> CoreM [a] 
     154putAnnotations :: (Typeable a, Binary a) => Name -> a -> CoreM () 
     155}}} 
     156 
     157We have sort of the same problem outlined above even today because bytestring is a boot library. However, since bytestring isn't exported by GHC you don't end up with this sort of weird situation. (Though it might give Cabal as much of a headache as the binary problem outlined above). 
     158 
     159The main alternative to using binary as a boot package is to import the whole source tree for binary and bytestring but rename them to ghc-binary and ghc-bytestring respectively. This ensures there are no conflicts with user code, but: 
     160 
     161 * Might be confusing! 
     162 
     163 * Means user code might have to make use of the package-qualified import syntax if they intend to reference both ghc-binary and binary from their code 
     164 
     165 * Means we have to have two identical instance declarations for any user types that want to be used both as normal Binary and GHC Binary 
     166 
     167 * Means we can't support ''deriving Binary'' 
     168 
     169 * Etc etc... 
     170 
     171The other alternative we came up with is to change the GHC API to annotations to this: 
     172 
     173 
     174{{{ 
     175-- For normal GHC API users: 
     176getAnnotations :: (Typeable a) => (ByteString -> a) -> Name -> GHCM [a] 
     177 
     178-- Only for plugins adding their own annotations: 
     179getAnnotations :: (Typeable a) => (ByteString -> a) -> Name -> CoreM [a] 
     180putAnnotations :: (Typeable a) => (a -> ByteString) -> Name -> a -> CoreM () 
     181}}} 
     182 
     183This doesn't require any more packages (we could even remove the ByteString usages here) and it does allow use of multiple different serialization libraries for annotations (should that be desirable). However, this doesn't enforce that the serializer and deserializer for a particular bit of data should be coherent and makes the API a bit unfriendlier. 
     184 
    123185== Future Work == 
    124186 
    125  * Plugins cannot currently add further annotations during compilation that will be compiled into the result. I.e. any annotations they add are transient and disappear at the end of that particular run of the Core pipeline. 
     187 * '''(Only in SoC implementation)''' Plugins cannot currently add further annotations during compilation that will be compiled into the result. I.e. any annotations they add are transient and disappear at the end of that particular run of the Core pipeline. 
    126188  
    127189 * We might want to add attribute metadata, so users can specify the multiplicity attributes should take, what sorts of things they can be attached to (value, type, module), and perhaps even what types they can be attached to (e.g. "only things of type a -> Bool for some a"), similar to C# ([http://msdn.microsoft.com/en-us/library/tw5zxet9(VS.80).aspx]) or Java. 
     
    143205  * Non-top-level identifiers (for plugins: tricky because such names are unstable) 
    144206 
    145  * I believe it would make sense to allow annotations to use the implementations of values in the module being compiled,: after all, I they can use the implementations of values in imported modules. This would filling out the relevant field with an error during compilation (for the benefit of plugins) and linking the annotation fields up to the required values after compilation. Is this a good idea? 
     207 * '''(Only in SoC implementation)''' I believe it would make sense to allow annotations to use the implementations of values in the module being compiled,: after all, I they can use the implementations of values in imported modules. This would filling out the relevant field with an error during compilation (for the benefit of plugins) and linking the annotation fields up to the required values after compilation. Is this a good idea? 
    146208 
    147209 * Have retention policies, similar to Java?