Compiler-Core.st 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. Smalltalk current createPackage: 'Compiler-Core'!
  2. Object subclass: #AbstractCodeGenerator
  3. instanceVariableNames: 'currentClass source'
  4. package: 'Compiler-Core'!
  5. !AbstractCodeGenerator commentStamp!
  6. I am the abstract super class of all code generators and provide their common API.!
  7. !AbstractCodeGenerator methodsFor: 'accessing'!
  8. classNameFor: aClass
  9. ^aClass isMetaclass
  10. ifTrue: [aClass instanceClass name, '.klass']
  11. ifFalse: [
  12. aClass isNil
  13. ifTrue: ['nil']
  14. ifFalse: [aClass name]]
  15. !
  16. currentClass
  17. ^currentClass
  18. !
  19. currentClass: aClass
  20. currentClass := aClass
  21. !
  22. pseudoVariables
  23. ^ Smalltalk current pseudoVariableNames
  24. !
  25. safeVariableNameFor: aString
  26. ^(Smalltalk current reservedWords includes: aString)
  27. ifTrue: [aString, '_']
  28. ifFalse: [aString]
  29. !
  30. source
  31. ^source ifNil: ['']
  32. !
  33. source: aString
  34. source := aString
  35. ! !
  36. !AbstractCodeGenerator methodsFor: 'compiling'!
  37. compileNode: aNode
  38. self subclassResponsibility
  39. ! !
  40. AbstractCodeGenerator subclass: #CodeGenerator
  41. instanceVariableNames: ''
  42. package: 'Compiler-Core'!
  43. !CodeGenerator commentStamp!
  44. I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.
  45. See `InliningCodeGenerator` for an optimized JavaScript code generation.!
  46. !CodeGenerator methodsFor: 'compiling'!
  47. compileNode: aNode
  48. | ir stream |
  49. self semanticAnalyzer visit: aNode.
  50. ir := self translator visit: aNode.
  51. ^ self irTranslator
  52. visit: ir;
  53. contents
  54. !
  55. irTranslator
  56. ^ IRJSTranslator new
  57. !
  58. semanticAnalyzer
  59. ^ SemanticAnalyzer on: self currentClass
  60. !
  61. translator
  62. ^ IRASTTranslator new
  63. source: self source;
  64. theClass: self currentClass;
  65. yourself
  66. ! !
  67. Object subclass: #Compiler
  68. instanceVariableNames: 'currentClass source unknownVariables codeGeneratorClass'
  69. package: 'Compiler-Core'!
  70. !Compiler commentStamp!
  71. I provide the public interface for compiling Amber source code into JavaScript.
  72. The code generator used to produce JavaScript can be plugged with `#codeGeneratorClass`.
  73. The default code generator is an instance of `InlinedCodeGenerator`!
  74. !Compiler methodsFor: 'accessing'!
  75. codeGeneratorClass
  76. ^codeGeneratorClass ifNil: [InliningCodeGenerator]
  77. !
  78. codeGeneratorClass: aClass
  79. codeGeneratorClass := aClass
  80. !
  81. currentClass
  82. ^currentClass
  83. !
  84. currentClass: aClass
  85. currentClass := aClass
  86. !
  87. source
  88. ^source ifNil: ['']
  89. !
  90. source: aString
  91. source := aString
  92. !
  93. unknownVariables
  94. ^unknownVariables
  95. !
  96. unknownVariables: aCollection
  97. unknownVariables := aCollection
  98. ! !
  99. !Compiler methodsFor: 'compiling'!
  100. compile: aString
  101. ^self compileNode: (self parse: aString)
  102. !
  103. compile: aString forClass: aClass
  104. self currentClass: aClass.
  105. self source: aString.
  106. ^self compile: aString
  107. !
  108. compileExpression: aString
  109. self currentClass: DoIt.
  110. self source: 'doIt ^[', aString, '] value'.
  111. ^self compileNode: (self parse: self source)
  112. !
  113. compileExpression: aString on: anObject
  114. self currentClass: anObject class.
  115. self source: 'xxxDoIt ^[', aString, '] value'.
  116. ^self compileNode: (self parse: self source)
  117. !
  118. compileNode: aNode
  119. | generator result |
  120. generator := self codeGeneratorClass new.
  121. generator
  122. source: self source;
  123. currentClass: self currentClass.
  124. result := generator compileNode: aNode.
  125. self unknownVariables: #().
  126. ^result
  127. !
  128. eval: aString
  129. <return eval(aString)>
  130. !
  131. evaluateExpression: aString
  132. "Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
  133. ^ self evaluateExpression: aString on: DoIt new
  134. !
  135. evaluateExpression: aString on: anObject
  136. "Unlike #eval: evaluate a Smalltalk expression with anObject as the receiver and answer the returned object"
  137. | result method |
  138. method := self eval: (self compileExpression: aString on: anObject).
  139. method category: 'xxxDoIt'.
  140. anObject class addCompiledMethod: method.
  141. result := anObject xxxDoIt.
  142. anObject class removeCompiledMethod: method.
  143. ^result
  144. !
  145. install: aString forClass: aBehavior category: anotherString
  146. ^ ClassBuilder new
  147. installMethod: (self eval: (self compile: aString forClass: aBehavior))
  148. forClass: aBehavior
  149. category: anotherString
  150. !
  151. parse: aString
  152. ^Smalltalk current parse: aString
  153. !
  154. parseExpression: aString
  155. ^self parse: 'doIt ^[', aString, '] value'
  156. !
  157. recompile: aClass
  158. aClass methodDictionary values
  159. do: [ :each | self install: each source forClass: aClass category: each category ]
  160. displayingProgress: 'Recompiling ', aClass name.
  161. "self setupClass: aClass."
  162. aClass isMetaclass ifFalse: [ self recompile: aClass class ]
  163. !
  164. recompileAll
  165. Smalltalk current classes
  166. do: [:each | self recompile: each ]
  167. displayingProgress: 'Compiling all classes...'
  168. ! !
  169. !Compiler class methodsFor: 'compiling'!
  170. recompile: aClass
  171. self new recompile: aClass
  172. !
  173. recompileAll
  174. Smalltalk current classes do: [:each |
  175. self recompile: each]
  176. ! !
  177. Object subclass: #DoIt
  178. instanceVariableNames: ''
  179. package: 'Compiler-Core'!
  180. !DoIt commentStamp!
  181. `DoIt` is the class used to compile and evaluate expressions. See `Compiler >> evaluateExpression:`.!
  182. Object subclass: #NodeVisitor
  183. instanceVariableNames: ''
  184. package: 'Compiler-Core'!
  185. !NodeVisitor commentStamp!
  186. I am the abstract super class of all AST node visitors.!
  187. !NodeVisitor methodsFor: 'visiting'!
  188. visit: aNode
  189. ^ aNode accept: self
  190. !
  191. visitAll: aCollection
  192. ^ aCollection collect: [ :each | self visit: each ]
  193. !
  194. visitAssignmentNode: aNode
  195. ^ self visitNode: aNode
  196. !
  197. visitBlockNode: aNode
  198. ^ self visitNode: aNode
  199. !
  200. visitBlockSequenceNode: aNode
  201. ^ self visitSequenceNode: aNode
  202. !
  203. visitCascadeNode: aNode
  204. ^ self visitNode: aNode
  205. !
  206. visitClassReferenceNode: aNode
  207. ^ self visitVariableNode: aNode
  208. !
  209. visitDynamicArrayNode: aNode
  210. ^ self visitNode: aNode
  211. !
  212. visitDynamicDictionaryNode: aNode
  213. ^ self visitNode: aNode
  214. !
  215. visitJSStatementNode: aNode
  216. ^ self visitNode: aNode
  217. !
  218. visitMethodNode: aNode
  219. ^ self visitNode: aNode
  220. !
  221. visitNode: aNode
  222. ^ self visitAll: aNode nodes
  223. !
  224. visitReturnNode: aNode
  225. ^ self visitNode: aNode
  226. !
  227. visitSendNode: aNode
  228. ^ self visitNode: aNode
  229. !
  230. visitSequenceNode: aNode
  231. ^ self visitNode: aNode
  232. !
  233. visitValueNode: aNode
  234. ^ self visitNode: aNode
  235. !
  236. visitVariableNode: aNode
  237. ^ self visitNode: aNode
  238. ! !