Compiler-Core.st 5.6 KB

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