Compiler-Core.st 6.6 KB

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