Compiler-Core.st 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. Smalltalk createPackage: 'Compiler-Core'!
  2. Object subclass: #AbstractCodeGenerator
  3. instanceVariableNames: 'currentClass currentPackage 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. currentClass
  9. ^ currentClass
  10. !
  11. currentClass: aClass
  12. currentClass := aClass
  13. !
  14. currentPackage
  15. ^ currentPackage
  16. !
  17. currentPackage: anObject
  18. currentPackage := anObject
  19. !
  20. pseudoVariables
  21. ^ Smalltalk pseudoVariableNames
  22. !
  23. source
  24. ^ source ifNil: [ '' ]
  25. !
  26. source: aString
  27. source := aString
  28. ! !
  29. !AbstractCodeGenerator methodsFor: 'compiling'!
  30. compileNode: aNode
  31. ^ self transformers
  32. inject: aNode
  33. into: [ :input :transformer | transformer visit: input ]
  34. !
  35. transformers
  36. self subclassResponsibility
  37. ! !
  38. AbstractCodeGenerator subclass: #CodeGenerator
  39. instanceVariableNames: ''
  40. package: 'Compiler-Core'!
  41. !CodeGenerator commentStamp!
  42. I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.
  43. See `InliningCodeGenerator` for an optimized JavaScript code generation.!
  44. !CodeGenerator methodsFor: 'compiling'!
  45. irTranslator
  46. ^ IRJSTranslator new
  47. !
  48. semanticAnalyzer
  49. ^ (self semanticAnalyzerClass on: self currentClass)
  50. thePackage: self currentPackage;
  51. yourself
  52. !
  53. semanticAnalyzerClass
  54. ^ SemanticAnalyzer
  55. !
  56. transformers
  57. ^ {
  58. self semanticAnalyzer.
  59. self translator.
  60. self irTranslator currentClass: self currentClass; yourself
  61. }
  62. !
  63. translator
  64. ^ IRASTTranslator new
  65. source: self source;
  66. theClass: self currentClass;
  67. yourself
  68. ! !
  69. Object subclass: #Compiler
  70. instanceVariableNames: 'currentClass currentPackage source unknownVariables codeGeneratorClass'
  71. package: 'Compiler-Core'!
  72. !Compiler commentStamp!
  73. I provide the public interface for compiling Amber source code into JavaScript.
  74. The code generator used to produce JavaScript can be plugged with `#codeGeneratorClass`.
  75. The default code generator is an instance of `InlinedCodeGenerator`!
  76. !Compiler methodsFor: 'accessing'!
  77. codeGeneratorClass
  78. ^ codeGeneratorClass ifNil: [ InliningCodeGenerator ]
  79. !
  80. codeGeneratorClass: aClass
  81. codeGeneratorClass := aClass
  82. !
  83. currentClass
  84. ^ currentClass
  85. !
  86. currentClass: aClass
  87. currentClass := aClass
  88. !
  89. currentPackage
  90. ^ currentPackage
  91. !
  92. currentPackage: anObject
  93. currentPackage := anObject
  94. !
  95. source
  96. ^ source ifNil: [ '' ]
  97. !
  98. source: aString
  99. source := aString
  100. !
  101. unknownVariables
  102. ^ unknownVariables
  103. !
  104. unknownVariables: aCollection
  105. unknownVariables := aCollection
  106. ! !
  107. !Compiler methodsFor: 'compiling'!
  108. compile: aString forClass: aClass protocol: anotherString
  109. ^ self
  110. source: aString;
  111. compileNode: (self parse: aString)
  112. forClass: aClass
  113. package: (aClass packageOfProtocol: anotherString)
  114. !
  115. compileExpression: aString on: anObject
  116. ^ self
  117. compile: 'xxxDoIt ^ [ ', aString, ' ] value'
  118. forClass: anObject class
  119. protocol: '**xxxDoIt'
  120. !
  121. compileNode: aNode
  122. | generator result |
  123. generator := self codeGeneratorClass new.
  124. generator
  125. source: self source;
  126. currentClass: self currentClass;
  127. currentPackage: self currentPackage.
  128. result := generator compileNode: aNode.
  129. self unknownVariables: #().
  130. ^ result
  131. !
  132. compileNode: aNode forClass: aClass package: aPackage
  133. ^ self
  134. currentClass: aClass;
  135. currentPackage: aPackage;
  136. compileNode: aNode
  137. !
  138. eval: aString
  139. <inlineJS: 'return eval(aString)'>
  140. !
  141. eval: aString forPackage: aPackage
  142. <inlineJS: 'return aPackage && aPackage.innerEval
  143. ? aPackage.innerEval(aString)
  144. : eval(aString)'>
  145. !
  146. evaluateExpression: aString
  147. "Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
  148. ^ self evaluateExpression: aString on: DoIt new
  149. !
  150. evaluateExpression: aString on: anObject
  151. "Unlike #eval: evaluate a Smalltalk expression with anObject as the receiver and answer the returned object"
  152. | result method |
  153. method := self eval: (self compileExpression: aString on: anObject).
  154. method protocol: '**xxxDoIt'.
  155. anObject class addCompiledMethod: method.
  156. result := anObject xxxDoIt.
  157. anObject class removeCompiledMethod: method.
  158. ^ result
  159. !
  160. install: aString forClass: aBehavior protocol: anotherString
  161. | compiledMethod |
  162. compiledMethod := self
  163. eval: (self compile: aString forClass: aBehavior protocol: anotherString)
  164. forPackage: (aBehavior packageOfProtocol: anotherString).
  165. ^ ClassBuilder new
  166. installMethod: compiledMethod
  167. forClass: aBehavior
  168. protocol: anotherString
  169. !
  170. parse: aString
  171. ^ Smalltalk parse: aString
  172. !
  173. parseExpression: aString
  174. ^ self parse: 'doIt ^ [ ', aString, ' ] value'
  175. !
  176. recompile: aClass
  177. aClass methodDictionary values
  178. do: [ :each |
  179. self
  180. install: each source
  181. forClass: aClass
  182. protocol: each protocol ]
  183. displayingProgress: 'Recompiling ', aClass name.
  184. aClass isMetaclass ifFalse: [ self recompile: aClass class ]
  185. !
  186. recompileAll
  187. Smalltalk classes
  188. do: [ :each | self recompile: each ]
  189. displayingProgress: 'Compiling all classes...'
  190. ! !
  191. !Compiler class methodsFor: 'compiling'!
  192. recompile: aClass
  193. self new recompile: aClass
  194. !
  195. recompileAll
  196. Smalltalk classes do: [ :each |
  197. self recompile: each ]
  198. ! !
  199. Error subclass: #CompilerError
  200. instanceVariableNames: ''
  201. package: 'Compiler-Core'!
  202. !CompilerError commentStamp!
  203. I am the common superclass of all compiling errors.!
  204. Object subclass: #DoIt
  205. instanceVariableNames: ''
  206. package: 'Compiler-Core'!
  207. !DoIt commentStamp!
  208. `DoIt` is the class used to compile and evaluate expressions. See `Compiler >> evaluateExpression:`.!
  209. Object subclass: #Evaluator
  210. instanceVariableNames: ''
  211. package: 'Compiler-Core'!
  212. !Evaluator commentStamp!
  213. I evaluate code against a receiver, dispatching #evaluate:on: to the receiver.!
  214. !Evaluator methodsFor: 'evaluating'!
  215. evaluate: aString context: aContext
  216. "Similar to #evaluate:for:, with the following differences:
  217. - instead of compiling and running `aString`, `aString` is interpreted using an `ASTInterpreter`
  218. - instead of evaluating against a receiver, evaluate in the context of `aContext`"
  219. | compiler ast |
  220. compiler := Compiler new.
  221. [ ast := compiler parseExpression: aString ]
  222. on: Error
  223. do: [ :ex | ^ Terminal alert: ex messageText ].
  224. (AISemanticAnalyzer on: aContext receiver class)
  225. context: aContext;
  226. visit: ast.
  227. ^ aContext evaluateNode: ast
  228. !
  229. evaluate: aString for: anObject
  230. ^ anObject evaluate: aString on: self
  231. !
  232. evaluate: aString receiver: anObject
  233. | compiler |
  234. compiler := Compiler new.
  235. [ compiler parseExpression: aString ]
  236. on: Error
  237. do: [ :ex | ^ Terminal alert: ex messageText ].
  238. ^ compiler evaluateExpression: aString on: anObject
  239. ! !
  240. !Evaluator class methodsFor: 'instance creation'!
  241. evaluate: aString for: anObject
  242. ^ self new evaluate: aString for: anObject
  243. ! !
  244. !String methodsFor: '*Compiler-Core'!
  245. asVariableName
  246. ^ (Smalltalk reservedWords includes: self)
  247. ifTrue: [ self, '_' ]
  248. ifFalse: [ self ]
  249. ! !