Compiler-Core.st 6.7 KB

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