Compiler-Core.st 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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. 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. InterfacingObject 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 | ^ self 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 | ^ self 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. Object subclass: #NodeVisitor
  242. instanceVariableNames: ''
  243. package: 'Compiler-Core'!
  244. !NodeVisitor commentStamp!
  245. I am the abstract super class of all AST node visitors.!
  246. !NodeVisitor methodsFor: 'visiting'!
  247. visit: aNode
  248. ^ aNode accept: self
  249. !
  250. visitAll: aCollection
  251. ^ aCollection collect: [ :each | self visit: each ]
  252. !
  253. visitAssignmentNode: aNode
  254. ^ self visitNode: aNode
  255. !
  256. visitBlockNode: aNode
  257. ^ self visitNode: aNode
  258. !
  259. visitBlockSequenceNode: aNode
  260. ^ self visitSequenceNode: aNode
  261. !
  262. visitCascadeNode: aNode
  263. ^ self visitNode: aNode
  264. !
  265. visitDynamicArrayNode: aNode
  266. ^ self visitNode: aNode
  267. !
  268. visitDynamicDictionaryNode: aNode
  269. ^ self visitNode: aNode
  270. !
  271. visitJSStatementNode: aNode
  272. ^ self visitNode: aNode
  273. !
  274. visitMethodNode: aNode
  275. ^ self visitNode: aNode
  276. !
  277. visitNode: aNode
  278. ^ self visitAll: aNode nodes
  279. !
  280. visitReturnNode: aNode
  281. ^ self visitNode: aNode
  282. !
  283. visitSendNode: aNode
  284. ^ self visitNode: aNode
  285. !
  286. visitSequenceNode: aNode
  287. ^ self visitNode: aNode
  288. !
  289. visitValueNode: aNode
  290. ^ self visitNode: aNode
  291. !
  292. visitVariableNode: aNode
  293. ^ self visitNode: aNode
  294. ! !
  295. !String methodsFor: '*Compiler-Core'!
  296. asVariableName
  297. ^ (Smalltalk reservedWords includes: self)
  298. ifTrue: [ self, '_' ]
  299. ifFalse: [ self ]
  300. ! !