2
0

Helios-Helpers.st 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. Smalltalk current createPackage: 'Helios-Helpers'!
  2. Object subclass: #HLGenerationOutput
  3. instanceVariableNames: 'sourceCodes protocol targetClass'
  4. package: 'Helios-Helpers'!
  5. !HLGenerationOutput commentStamp!
  6. I am a simple data object used to store the result of a generation process!
  7. !HLGenerationOutput methodsFor: 'accessing'!
  8. protocol
  9. ^ protocol
  10. !
  11. protocol: aString
  12. protocol := aString
  13. !
  14. sourceCodes
  15. ^ sourceCodes
  16. !
  17. sourceCodes: aCollection
  18. sourceCodes := aCollection
  19. !
  20. targetClass
  21. ^ targetClass
  22. !
  23. targetClass: aClass
  24. targetClass := aClass
  25. ! !
  26. !HLGenerationOutput methodsFor: 'initialization'!
  27. initialize
  28. super initialize.
  29. sourceCodes := OrderedCollection new
  30. ! !
  31. !HLGenerationOutput methodsFor: 'protocol'!
  32. addSourceCode: aString
  33. sourceCodes add: aString
  34. !
  35. compile
  36. sourceCodes do: [ :methodSourceCode |
  37. (targetClass includesSelector: methodSourceCode selector)
  38. ifFalse: [
  39. targetClass
  40. compile: methodSourceCode sourceCode
  41. protocol: protocol ] ]
  42. ! !
  43. HLGenerationOutput subclass: #HLGenerationOutputWithIndex
  44. instanceVariableNames: 'index'
  45. package: 'Helios-Helpers'!
  46. !HLGenerationOutputWithIndex commentStamp!
  47. I am a simple data object used to store the result of a generation process.
  48. In addition of my super class, I have an index where to put the cursor at the end of the process for the first method created (aka. the first in `sourceCodes`)!
  49. !HLGenerationOutputWithIndex methodsFor: 'accessing'!
  50. index
  51. ^ index
  52. !
  53. index: anIndex
  54. index := anIndex
  55. ! !
  56. Object subclass: #HLGenerator
  57. instanceVariableNames: 'output'
  58. package: 'Helios-Helpers'!
  59. !HLGenerator commentStamp!
  60. I am the abstract super class of the generators.
  61. My main method is `generate` which produce an `output` object!
  62. !HLGenerator methodsFor: 'accessing'!
  63. class: aClass
  64. output targetClass: aClass
  65. !
  66. output
  67. ^ output
  68. ! !
  69. !HLGenerator methodsFor: 'initialization'!
  70. initialize
  71. super initialize.
  72. output := HLGenerationOutput new
  73. ! !
  74. !HLGenerator methodsFor: 'protocol'!
  75. generate
  76. output targetClass ifNil: [ self error: 'class should not be nil'].
  77. ! !
  78. HLGenerator subclass: #HLAccessorsGenerator
  79. instanceVariableNames: ''
  80. package: 'Helios-Helpers'!
  81. !HLAccessorsGenerator commentStamp!
  82. I am a generator used to compile the getters/setters of a class!
  83. !HLAccessorsGenerator methodsFor: 'double-dispatch'!
  84. accessorProtocolForObject
  85. output protocol: 'accessing'
  86. !
  87. accessorsSourceCodesForObject
  88. | sources |
  89. sources := OrderedCollection new.
  90. output targetClass instanceVariableNames sorted do: [ :each |
  91. sources
  92. add: (self getterFor: each);
  93. add: (self setterFor: each) ].
  94. output sourceCodes: sources
  95. ! !
  96. !HLAccessorsGenerator methodsFor: 'private'!
  97. getterFor: anInstanceVariable
  98. ^ HLMethodSourceCode new
  99. selector:anInstanceVariable;
  100. sourceCode: (String streamContents: [ :stream |
  101. stream << anInstanceVariable.
  102. stream cr tab.
  103. stream << '^ ' << anInstanceVariable ])
  104. !
  105. setterFor: anInstanceVariable
  106. ^ HLMethodSourceCode new
  107. selector: anInstanceVariable, ':';
  108. sourceCode: (String streamContents: [ :stream |
  109. stream << anInstanceVariable << ': anObject'.
  110. stream cr tab.
  111. stream << anInstanceVariable << ' := anObject' ])
  112. ! !
  113. !HLAccessorsGenerator methodsFor: 'protocol'!
  114. generate
  115. super generate.
  116. output targetClass
  117. accessorsSourceCodesWith: self;
  118. accessorProtocolWith: self
  119. ! !
  120. HLGenerator subclass: #HLInitializeGenerator
  121. instanceVariableNames: ''
  122. package: 'Helios-Helpers'!
  123. !HLInitializeGenerator commentStamp!
  124. I am used to double-dispatch the `initialize` method(s) generation.
  125. Usage:
  126. ^ HLInitializeGenerator new
  127. class: aClass;
  128. generate;
  129. output
  130. I am a disposable object!
  131. !HLInitializeGenerator methodsFor: 'double-dispatch'!
  132. initializeForObject
  133. output addSourceCode: self initializeCodeForObject
  134. !
  135. initializeIndexForObject
  136. output index: self computeIndexForObject
  137. !
  138. initializeProtocolForObject
  139. output protocol: self retrieveProtocolForObject
  140. ! !
  141. !HLInitializeGenerator methodsFor: 'initialization'!
  142. initialize
  143. super initialize.
  144. output := HLGenerationOutputWithIndex new
  145. ! !
  146. !HLInitializeGenerator methodsFor: 'private'!
  147. computeIndexForObject
  148. | instVars headerSize firstInstVarSize |
  149. "32 is the size of the `initiliaze super initialize` part"
  150. headerSize := 32.
  151. instVars := output targetClass instanceVariableNames.
  152. firstInstVarSize := instVars sorted
  153. ifEmpty: [ 0 ]
  154. ifNotEmpty:[ instVars first size + 4 ].
  155. ^ headerSize + firstInstVarSize
  156. !
  157. generateInitializeCodeForObject
  158. ^ String streamContents: [ :str || instVars size |
  159. instVars := output targetClass instanceVariableNames sorted.
  160. size := instVars size.
  161. str << 'initialize'.
  162. str cr tab << 'super initialize.';cr.
  163. str cr tab.
  164. instVars withIndexDo: [ :name :index |
  165. index ~= 1 ifTrue: [ str cr tab ].
  166. str << name << ' := nil'.
  167. index ~= size ifTrue: [ str << '.' ] ] ].
  168. !
  169. initializeCodeForObject
  170. ^ HLMethodSourceCode new
  171. selector: 'initialize';
  172. sourceCode: self generateInitializeCodeForObject;
  173. yourself
  174. !
  175. retrieveProtocolForObject
  176. ^ 'initialization'
  177. ! !
  178. !HLInitializeGenerator methodsFor: 'protocol'!
  179. generate
  180. super generate.
  181. output targetClass
  182. initializeSourceCodesWith: self;
  183. initializeIndexWith: self;
  184. initializeProtocolWith: self
  185. ! !
  186. Object subclass: #HLMethodSourceCode
  187. instanceVariableNames: 'selector sourceCode'
  188. package: 'Helios-Helpers'!
  189. !HLMethodSourceCode commentStamp!
  190. I am a simple data object keeping track of the information about a method that will be compiled at the end of the generation process!
  191. !HLMethodSourceCode methodsFor: 'accessing'!
  192. selector
  193. ^ selector
  194. !
  195. selector: aSelector
  196. selector := aSelector
  197. !
  198. sourceCode
  199. ^ sourceCode
  200. !
  201. sourceCode: aString
  202. sourceCode := aString
  203. ! !