Compiler-Core.st 6.0 KB

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