Compiler-Core.st 7.1 KB

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