[Grace-core] Annotations: starting discussion

James Noble kjx at ecs.vuw.ac.nz
Tue Jun 26 23:25:01 PDT 2012


And here's the other one. the state of discussion on annotations.

The main thing that I think has changed is 
that we now think we will have to "strop" annotations

@foo @bar
@(foo,bar)
[foo, bar]
<<foo, bar>>
«foo, bar»    // just to make andrew happy, but we won't adopt it

or at least have a keyword or some defined place where you'd find annotations.
rather than get to them implicitly

Basically we need to permit annotations to everything:

 - declarations (var, def, method, type)
      <<@public, @synchronised, @transatction>> method main {print "Hello"}

 - literals (objects, numbers, strings, blocks)
      <<@confined, @sychronised, at multi-reader>> object {... } 

 - types, including method arguments & results
      type Integer = <<@MachineInteger, at Nofractions, at Primitive>> Number
      method report (input : <<@Confined>> Number) -> <<@Confined>> Number

 - requests,   (resulting in Ly/AmbientTalk style adverbs:
          foo.<<@asynch>>bar()
          bar <<@asunch>>+ 3 


and ideally do it in a way that doesn't make the whole language horrible.

Haskell doesn't have annotations, does it?

James 

	From: 	James Noble <kjx at ecs.vuw.ac.nz>
	Date: 	8 December 2011 1:29:49 AM NZDT
	Subject: 	Annotations Proposal  (including Brands as object & type annotations)
	To: 	Andrew P. Black <black at cs.pdx.edu>, Kim Bruce <kim at cs.pomona.edu>

I keep talking about this but haven't written much up.

Basically the plan is to rip off Ceylon's design, but do better, perhaps.

http://in.relation.to/Bloggers/IntroductionToCeylonPart12

- Annotations look like implicit self requests --- i.e. syntactically function calls.
  - probably not permit multipart names here.

- Annotations are defined in a dialect as private/confidential methods of the dialect   
 that return a subclass of Annotation (and are annotated annotation). 
     - either subclassing or generics used to tag annotations as to what syntatic elements they can annotate
     - those methods should be const & return value objects  (deep value objects?) 

- Annotations on declarations are written as method calls, and accumulate and all apply to the subsequent declarations
  - no-arg annotations may be written together one line, the parser needs to do the right thing

  doc "This function prints hello world"
  public callable synchronized final method hello {print "Hello World"} 

 - syntactic problem: assuming no stropping or other markers - 
        - how do we know where annotations end?
        - especially in type declarations?  do we have to work from right-to-left?  

  - annotations also need to be placed on types
        - again, how do you distinguish within type declaration bodies what's being used as annotation and what's a definition?
         (i.e. how do you give an interface that defines a bunch of annotations?)

  - annotations also need to be placed on expression 
         - scala uses "exp : annotation"  syntax.
         - another option is to use annotations that are identity functions (mostly)
               cast<Integer>( 1.0 + 1.0 ) 
               debuggable ( x.foo ) 

- Annotations as meta-objects 
     - annotations can be placed on objects.  
            - how? annotations on class declarations & object constructors.
            - any other way (annotated expressions?) 
            - are annotations added at creation time & thus static, or...? 

                    actor object {  
                          inherits Actors.Actor
                          method run { "do stuff" }  
                     }

     - annotations need to be able to placed on types too:

                   type MyActor =  actor Actors.Actor & { "whatver stuff I have" } 

- Brands are just special annotations on types
     - generally IF a type is branded, it will only match similarly branded objects.
     - thus introducing full nominal types through the back door...  :-)
     - someone should check this against Chapter 8 Section 8.1 of the Modula-3  book.

               brand("Cowboy")  class Cowboy {
                  public method draw { ... } 
               }


               brand("Window")  class Window  {
                  public method draw { ... } 
               }

             def myWindow : brand("Window") {draw -> Unit }    = Cowbow.new // fails, hopefully at compile time, certainly at runtime!


     - brands could be any (constant) object, strings are easy, but real programs
        will probably use private objects in a module so that they cannot be duplicated.
             - nasty issue, doing e.g. def myBrand = object {} // gets the null object, which is hash-consed :-)
		   or at any rate equal to any other object {}
             - brands must count in object identity:  object {} != brand("foo") object {} 
             - adding a mutable field forces uniqueness (but means the brand itself is no longer immutable - does that matter?)

                      def myBrand = object { var foo } 

       - in the implementation, treat object annotations like generic parameters? 
              - really, like lisp propertylists.

      - do we e.g. want *negative* brands,  objects with negative brands only match types if the brand is present in the types              
           - standard brands are "positive", acting like an extra uncallable method on the type.
           - an UNBRANDED TYPE will match all structurally-confirming branded and unbranded types (see note below)
   	      - a negative brand would somehow stop an unbranded typed from matching, unless the type was also branded...
           - how would that work with dynamic (doesn't even match dynamic, perhaps?) 

- Major issue - to strop or not to strop? 
 - not stropping (the syntatic proposal above) makes the code look much much nicer
   but introduces ambiguities / feedback loops into the _parser_
- stropping, we could follow Java & Scala = write @public @annotation 
  or follow C# [public, annotation] - no ambiguity, but looks uglier.
- possible alternative strop: annotations must be followed by a comma 
  public, void, def x = 3 
- or since they are implicit method calls anyway, just use semicolons:  public; static; synchronized; method main {print "Hello"} 

- Partial list of annotations
  - public -> Annotation < Declaration >
  - private -> Annotation < Declaration >
  - const -> Annotation < Request > 
  - value -> Annotation< Object > 
  - final ->  Annotation< Declaration > 
  - brand( brnd : Any ) -> Annotation< Type | Object >  
  - owned -> Annotation<Object >



More information about the Grace-core mailing list