Annotation.st
changeset 13613 f3c2a2ac07a1
parent 13479 d2d9938cf03f
child 13625 fffe5dbb451b
--- a/Annotation.st	Sun Aug 21 12:33:30 2011 +0200
+++ b/Annotation.st	Sun Aug 21 12:47:20 2011 +0200
@@ -53,6 +53,17 @@
 	privateIn:Annotation
 !
 
+Annotation comment:'I represent an occurrence of a pragma in a compiled method.  A pragma is a literal message pattern that occurs between angle brackets at the start of a method after any temporaries.  A common example is the primitive pragma:
+	<primitive: 123 errorCode: ''errorCode''>
+but one can add one''s own and use them as metadata attached to a method.  Because pragmas are messages one can browsse senders and implementors and perform them.  One can query a method for its pragmas by sendng it the pragmas message, which answers an Array of instances of me, one for each pragma in the method.
+I can provide information about the defining class, method, its selector, as well as the information about the pragma keyword and its arguments. See the two ''accessing'' protocols for details. ''accessing-method'' provides information about the method the pragma is found in, while ''accessing-pragma'' is about the pragma itself.
+Instances are retrieved using one of the pragma search methods of the ''finding'' protocol on the class side.
+To browse all methods with pragmas in the system evaluate
+	SystemNavigation default browseAllSelect: [:m| m pragmas notEmpty]
+and to browse all nonprimitive methods with pragmas evaluate
+	SystemNavigation default browseAllSelect: [:m| m primitive isZero and: [m pragmas notEmpty]]'
+!
+
 !Annotation class methodsFor:'documentation'!
 
 copyright
@@ -83,8 +94,26 @@
 "
 ! !
 
+!Annotation class methodsFor:'initialization'!
+
+initialize
+    "Invoked at system start or when the class is dynamically loaded."
+
+    Pragma := self.
+
+    "Modified: / 20-08-2011 / 21:21:24 / cg"
+! !
+
 !Annotation class methodsFor:'instance creation'!
 
+for: aMethod selector: aSelector arguments: anArray
+	^self new
+		setMethod: aMethod;
+		setKeyword: aSelector;
+		setArguments: anArray;
+		yourself
+!
+
 key: key arguments: arguments
 
     ^(self respondsTo: key)
@@ -124,6 +153,68 @@
     "Created: / 16-07-2010 / 11:31:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!Annotation class methodsFor:'finding'!
+
+allNamed: aSymbol from: aSubClass to: aSuperClass
+	"Answer a collection of all pragmas found in methods of all classes between aSubClass and aSuperClass (inclusive) whose keyword is aSymbol."
+	
+	^ Array streamContents: [ :stream |
+		aSubClass withAllSuperclassesDo: [ :class |
+			self withPragmasIn: class do:  [ :pragma |
+				pragma keyword = aSymbol
+					ifTrue: [ stream nextPut: pragma ] ].
+			aSuperClass = class
+				ifTrue: [ ^ stream contents ] ] ].
+!
+
+allNamed: aSymbol from: aSubClass to: aSuperClass sortedByArgument: anInteger
+	"Answer a collection of all pragmas found in methods of all classes between aSubClass and aSuperClass (inclusive) whose keyword is aSymbol, sorted according to argument anInteger."
+
+	^ self allNamed: aSymbol from: aSubClass to: aSuperClass sortedUsing: [ :a :b | (a argumentAt: anInteger) < (b argumentAt: anInteger) ].
+!
+
+allNamed: aSymbol from: aSubClass to: aSuperClass sortedUsing: aSortBlock
+	"Answer a collection of all pragmas found in methods of all classes between aSubClass and aSuperClass (inclusive) whose keyword is aSymbol, sorted according to aSortBlock."
+	
+	^ (self allNamed: aSymbol from: aSubClass to: aSuperClass) sort: aSortBlock.
+!
+
+allNamed: aSymbol in: aClass
+	"Answer a collection of all pragmas found in methods of aClass whose keyword is aSymbol."
+	
+	^ Array streamContents: [ :stream |
+		self withPragmasIn: aClass do: [ :pragma |
+			pragma keyword = aSymbol
+				ifTrue: [ stream nextPut: pragma ] ] ].
+!
+
+allNamed: aSymbol in: aClass sortedByArgument: anInteger
+	"Answer a collection of all pragmas found in methods of aClass whose keyword is aSymbol, sorted according to argument anInteger."
+
+	^ self allNamed: aSymbol in: aClass sortedUsing: [ :a :b | (a argumentAt: anInteger) < (b argumentAt: anInteger) ].
+!
+
+allNamed: aSymbol in: aClass sortedUsing: aSortBlock
+	"Answer a collection of all pragmas found in methods of aClass whose keyword is aSymbol, sorted according to aSortBlock."
+	
+	^ (self allNamed: aSymbol in: aClass) sort: aSortBlock.
+! !
+
+!Annotation class methodsFor:'private'!
+
+keyword: aSymbol arguments: anArray
+	^ self new
+		setKeyword: aSymbol;
+		setArguments: anArray;
+		yourself.
+!
+
+withPragmasIn: aClass do: aBlock
+        aClass selectorsAndMethodsDo: [ :selector :method | method annotationsDo: aBlock ].
+
+    "Modified: / 20-08-2011 / 21:31:49 / cg"
+! !
+
 !Annotation methodsFor:'accessing'!
 
 first
@@ -141,7 +232,101 @@
     "Modified: / 16-07-2010 / 11:29:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
-!Annotation methodsFor:'printing & storing'!
+!Annotation methodsFor:'accessing-method'!
+
+method
+        "Answer the compiled-method containing the pragma."
+        
+        self halt:'inimplemented'
+
+    "Modified: / 21-08-2011 / 12:44:37 / cg"
+!
+
+methodClass
+        "Answer the class of the method containing the pragma."
+        
+        ^ self method methodClass
+
+    "Modified: / 21-08-2011 / 12:44:47 / cg"
+!
+
+selector
+        "Answer the selector of the method containing the pragma.
+         Do not confuse this with the selector of the pragma's message pattern."
+        
+        ^ self method selector
+
+    "Modified: / 21-08-2011 / 12:45:20 / cg"
+! !
+
+!Annotation methodsFor:'accessing-pragma'!
+
+argumentAt: anInteger
+	"Answer one of the arguments of the pragma."
+	
+	^ self arguments at: anInteger.
+!
+
+arguments
+        "Answer the arguments of the receiving pragma. For a pragma defined as <key1: val1 key2: val2> this will answer #(val1 val2)."
+
+    self subclassResponsibility
+
+    "Modified: / 21-08-2011 / 12:43:54 / cg"
+!
+
+keyword
+        "Answer the keyword of the pragma (the selector of its message pattern).
+         For a pragma defined as <key1: val1 key2: val2> this will answer #key1:key2:."
+        
+        self subclassResponsibility
+
+    "Modified: / 21-08-2011 / 12:45:07 / cg"
+!
+
+message
+	"Answer the message of the receiving pragma."
+	
+	^ Message selector: self keyword arguments: self arguments. 
+!
+
+numArgs
+	"Answer the number of arguments in the pragma."
+
+	^ self arguments size.
+! !
+
+!Annotation methodsFor:'comparing'!
+
+analogousCodeTo: anObject 
+        ^self class == anObject class
+          and: [self keyword == anObject keyword
+          and: [self arguments = anObject arguments]]
+
+    "Modified: / 21-08-2011 / 12:45:37 / cg"
+! !
+
+!Annotation methodsFor:'initialization'!
+
+setArguments: anArray
+    self subclassResponsibility
+
+    "Modified: / 21-08-2011 / 12:45:51 / cg"
+!
+
+setKeyword: aSymbol
+        self subclassResponsibility
+
+    "Modified: / 21-08-2011 / 12:46:06 / cg"
+!
+
+setMethod: aCompiledMethod
+        self subclassResponsibility
+
+    "Modified: / 21-08-2011 / 12:46:16 / cg"
+! !
+
+!Annotation methodsFor:'printing'!
 
 printOn:aStream
     "append a printed representation if the receiver to the argument, aStream"
@@ -149,7 +334,9 @@
     self storeOn:aStream.
 
     "Modified: / 19-05-2010 / 16:25:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
+! !
+
+!Annotation methodsFor:'printing & storing'!
 
 storeOn:aStream
 
@@ -172,10 +359,38 @@
     ^self subclassResponsibility
 
     "Created: / 20-05-2010 / 11:15:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+sendTo: anObject
+	"Send the pragma keyword together with its arguments to anObject and answer the result."
+	
+	^ anObject perform: self keyword withArguments: self arguments
+!
+
+withArgumentsDo: aBlock
+	"Pass the arguments of the receiving pragma into aBlock and answer the result."
+	
+	^ aBlock valueWithArguments: self arguments
 ! !
 
 !Annotation methodsFor:'testing'!
 
+hasLiteral: aLiteral
+        ^self keyword == aLiteral 
+           or: [self arguments hasLiteral: aLiteral]
+
+    "Modified: / 21-08-2011 / 12:46:44 / cg"
+!
+
+hasLiteralSuchThat: aBlock
+        "Answer true if litBlock returns true for any literal in the receiver, even if embedded in further array structure.
+         This method is only intended for private use by CompiledMethod hasLiteralSuchThat:"
+        ^(aBlock value: self keyword)
+           or: [self arguments hasLiteralSuchThat: aBlock]
+
+    "Modified: / 21-08-2011 / 12:46:31 / cg"
+!
+
 isUnknown
     ^ false
 ! !
@@ -348,9 +563,11 @@
 !Annotation class methodsFor:'documentation'!
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Annotation.st,v 1.2 2011-07-03 15:00:45 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Annotation.st,v 1.3 2011-08-21 10:47:20 cg Exp $'
 !
 
 version_SVN
     ^ '§Id: Annotation.st,v 1.1 2011/06/28 11:04:04 vrany Exp §'
 ! !
+
+Annotation initialize!