Compiler-Core.st 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. Smalltalk current createPackage: 'Compiler-Core' properties: #{}!
  2. Object subclass: #Compiler
  3. instanceVariableNames: 'currentClass source unknownVariables codeGeneratorClass'
  4. package: 'Compiler-Core'!
  5. !Compiler methodsFor: 'accessing'!
  6. codeGeneratorClass
  7. ^codeGeneratorClass ifNil: [FunCodeGenerator]
  8. !
  9. codeGeneratorClass: aClass
  10. codeGeneratorClass := aClass
  11. !
  12. currentClass
  13. ^currentClass
  14. !
  15. currentClass: aClass
  16. currentClass := aClass
  17. !
  18. source
  19. ^source ifNil: ['']
  20. !
  21. source: aString
  22. source := aString
  23. !
  24. unknownVariables
  25. ^unknownVariables
  26. !
  27. unknownVariables: aCollection
  28. unknownVariables := aCollection
  29. ! !
  30. !Compiler methodsFor: 'compiling'!
  31. compile: aString
  32. ^self compileNode: (self parse: aString)
  33. !
  34. compile: aString forClass: aClass
  35. self currentClass: aClass.
  36. self source: aString.
  37. ^self compile: aString
  38. !
  39. compileExpression: aString
  40. self currentClass: DoIt.
  41. self source: 'doIt ^[', aString, '] value'.
  42. ^self compileNode: (self parse: self source)
  43. !
  44. compileNode: aNode
  45. | generator result |
  46. generator := self codeGeneratorClass new.
  47. generator
  48. source: self source;
  49. currentClass: self currentClass.
  50. result := generator compileNode: aNode.
  51. self unknownVariables: #().
  52. ^result
  53. !
  54. eval: aString
  55. <return eval(aString)>
  56. !
  57. evaluateExpression: aString
  58. "Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
  59. | result |
  60. DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
  61. result := DoIt new doIt.
  62. DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').
  63. ^result
  64. !
  65. parse: aString
  66. ^Smalltalk current parse: aString
  67. !
  68. parseExpression: aString
  69. ^self parse: 'doIt ^[', aString, '] value'
  70. !
  71. recompile: aClass
  72. aClass methodDictionary do: [:each |
  73. self install: each source forClass: aClass category: each category].
  74. self setupClass: aClass.
  75. aClass isMetaclass ifFalse: [self recompile: aClass class]
  76. !
  77. recompileAll
  78. Smalltalk current classes do: [:each |
  79. Transcript show: each; cr.
  80. [self recompile: each] valueWithTimeout: 100]
  81. !
  82. setupClass: aClass
  83. <smalltalk.init(aClass)>
  84. ! !
  85. !Compiler class methodsFor: 'compiling'!
  86. recompile: aClass
  87. self new recompile: aClass
  88. !
  89. recompileAll
  90. Smalltalk current classes do: [:each |
  91. self recompile: each]
  92. ! !
  93. Object subclass: #DoIt
  94. instanceVariableNames: ''
  95. package: 'Compiler-Core'!
  96. Object subclass: #JSStream
  97. instanceVariableNames: 'stream'
  98. package: 'Compiler-Core'!
  99. !JSStream methodsFor: 'accessing'!
  100. contents
  101. ^ stream contents
  102. ! !
  103. !JSStream methodsFor: 'initialization'!
  104. initialize
  105. super initialize.
  106. stream := '' writeStream.
  107. ! !
  108. !JSStream methodsFor: 'streaming'!
  109. lf
  110. stream lf
  111. !
  112. nextPut: aString
  113. stream nextPut: aString
  114. !
  115. nextPutAll: aString
  116. stream nextPutAll: aString
  117. !
  118. nextPutAssignment: varInstruction to: valueInstruction
  119. varInstruction emitOn: self.
  120. stream nextPutAll: '='.
  121. valueInstruction emitOn: self
  122. !
  123. nextPutClosureWith: aBlock arguments: anArray
  124. stream nextPutAll: '(function('.
  125. anArray
  126. do: [ :each | stream nextPutAll: each ]
  127. separatedBy: [ stream nextPut: ',' ].
  128. stream nextPutAll: '){'; lf.
  129. aBlock value.
  130. stream nextPutAll: '})'
  131. !
  132. nextPutFunctionWith: aBlock arguments: anArray
  133. stream nextPutAll: 'fn: function('.
  134. anArray
  135. do: [ :each | stream nextPutAll: each ]
  136. separatedBy: [ stream nextPut: ',' ].
  137. stream nextPutAll: '){'; lf.
  138. self nextPutVar: '$return'.
  139. stream nextPutAll: 'var self=this;'; lf.
  140. aBlock value.
  141. stream nextPutAll: 'return $return || self;}'
  142. !
  143. nextPutMethodDeclaration: aMethod with: aBlock
  144. stream
  145. nextPutAll: 'smalltalk.method({'; lf;
  146. nextPutAll: 'selector: "', aMethod selector, '",'; lf;
  147. nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.
  148. aBlock value.
  149. stream
  150. nextPutAll: ',', String lf, 'messageSends: ';
  151. nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
  152. nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
  153. nextPutAll: 'referencedClasses: ['.
  154. aMethod classReferences
  155. do: [:each | stream nextPutAll: each asJavascript]
  156. separatedBy: [stream nextPutAll: ','].
  157. stream
  158. nextPutAll: ']';
  159. nextPutAll: '})'
  160. !
  161. nextPutNonLocalReturnHandlingWith: aBlock
  162. stream
  163. nextPutAll: 'var $early={};'; lf;
  164. nextPutAll: 'try {'; lf.
  165. aBlock value.
  166. stream
  167. nextPutAll: '}'; lf;
  168. nextPutAll: 'catch(e) {if(e===$early)return e[0]; throw e}'; lf
  169. !
  170. nextPutNonLocalReturnWith: aBlock
  171. stream nextPutAll: '(function(){throw $early=['.
  172. aBlock value.
  173. stream nextPutAll: ']})()'
  174. !
  175. nextPutReturnWith: aBlock
  176. stream nextPutAll: '$return='.
  177. aBlock value
  178. !
  179. nextPutSendTo: receiver selector: selector arguments: arguments
  180. stream nextPutAll: 'smalltalk.send('.
  181. receiver emitOn: self.
  182. stream nextPutAll: ',"', selector asSelector, '",['.
  183. arguments
  184. do: [ :each | each emitOn: self ]
  185. separatedBy: [ stream nextPutAll: ',' ].
  186. stream nextPutAll: '])'
  187. !
  188. nextPutSequenceWith: aBlock
  189. stream
  190. nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf.
  191. aBlock value.
  192. stream
  193. nextPutAll: '};'; lf
  194. !
  195. nextPutStatement: anInteger with: aBlock
  196. stream
  197. nextPutAll: 'case ', anInteger asString, ':'; lf.
  198. aBlock value.
  199. stream
  200. nextPutAll: ';'; lf;
  201. nextPutAll: 'smalltalk.thisContext.pc=', (anInteger + 1) asString, ';'; lf
  202. !
  203. nextPutVar: aString
  204. stream nextPutAll: 'var ', aString, ';'; lf
  205. !
  206. nextPutVars: aCollection
  207. stream nextPutAll: 'var '.
  208. aCollection
  209. do: [ :each | stream nextPutAll: each ]
  210. separatedBy: [ stream nextPutAll: ',' ].
  211. stream nextPutAll: ';'; lf
  212. ! !
  213. Object subclass: #NodeVisitor
  214. instanceVariableNames: ''
  215. package: 'Compiler-Core'!
  216. !NodeVisitor methodsFor: 'visiting'!
  217. visit: aNode
  218. aNode accept: self
  219. !
  220. visitAll: aCollection
  221. aCollection do: [ :each | self visit: each ]
  222. !
  223. visitAssignmentNode: aNode
  224. self visitNode: aNode
  225. !
  226. visitBlockNode: aNode
  227. self visitNode: aNode
  228. !
  229. visitBlockSequenceNode: aNode
  230. self visitSequenceNode: aNode
  231. !
  232. visitCascadeNode: aNode
  233. self visitNode: aNode
  234. !
  235. visitClassReferenceNode: aNode
  236. self visitNode: aNode
  237. !
  238. visitDynamicArrayNode: aNode
  239. self visitNode: aNode
  240. !
  241. visitDynamicDictionaryNode: aNode
  242. self visitNode: aNode
  243. !
  244. visitJSStatementNode: aNode
  245. self visitNode: aNode
  246. !
  247. visitMethodNode: aNode
  248. self visitNode: aNode
  249. !
  250. visitNode: aNode
  251. aNode nodes do: [ :each | self visit: each ]
  252. !
  253. visitReturnNode: aNode
  254. self visitNode: aNode
  255. !
  256. visitSendNode: aNode
  257. self visitNode: aNode
  258. !
  259. visitSequenceNode: aNode
  260. self visitNode: aNode
  261. !
  262. visitValueNode: aNode
  263. self visitNode: aNode
  264. !
  265. visitVariableNode: aNode
  266. self visitNode: aNode
  267. ! !