Compiler-Core.st 6.8 KB

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