2
0

Compiler-Core.st 5.9 KB

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