Compiler-AST.st 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. Smalltalk createPackage: 'Compiler-AST'!
  2. Object subclass: #Node
  3. instanceVariableNames: 'parent position nodes shouldBeInlined shouldBeAliased'
  4. package: 'Compiler-AST'!
  5. !Node commentStamp!
  6. I am the abstract root class of the abstract syntax tree.
  7. Concrete classes should implement `#accept:` to allow visiting.
  8. `position` holds a point containing line and column number of the symbol location in the original source file.!
  9. !Node methodsFor: 'accessing'!
  10. addNode: aNode
  11. self nodes add: aNode.
  12. aNode parent: self
  13. !
  14. method
  15. ^ self parent ifNotNil: [ :node | node method ]
  16. !
  17. nextChild
  18. "Answer the next node after aNode.
  19. Recurse into the possible children of the receiver to answer the next node to be evaluated"
  20. ^ self nodes isEmpty
  21. ifTrue: [ self ]
  22. ifFalse: [ self nodes first nextChild ]
  23. !
  24. nextNode
  25. ^ self parent ifNotNil: [ :node |
  26. node nextNode: self ]
  27. !
  28. nextNode: aNode
  29. "Answer the next node after aNode.
  30. Recurse into the possible children of the next node to answer the next node to be evaluated"
  31. | next |
  32. next := self nodes
  33. at: (self nodes indexOf: aNode) + 1
  34. ifAbsent: [ ^ self ].
  35. ^ next nextChild
  36. !
  37. nodes
  38. ^ nodes ifNil: [ nodes := Array new ]
  39. !
  40. parent
  41. ^ parent
  42. !
  43. parent: aNode
  44. parent := aNode
  45. !
  46. position
  47. "answer the line and column of the receiver in the source code"
  48. ^ position ifNil: [
  49. self parent ifNotNil: [ :node | node position ] ]
  50. !
  51. shouldBeAliased
  52. ^ shouldBeAliased ifNil: [ false ]
  53. !
  54. shouldBeAliased: aBoolean
  55. shouldBeAliased := aBoolean
  56. !
  57. shouldBeInlined
  58. ^ shouldBeInlined ifNil: [ false ]
  59. !
  60. shouldBeInlined: aBoolean
  61. shouldBeInlined := aBoolean
  62. ! !
  63. !Node methodsFor: 'building'!
  64. nodes: aCollection
  65. nodes := aCollection.
  66. aCollection do: [ :each | each parent: self ]
  67. !
  68. position: aPosition
  69. position := aPosition
  70. ! !
  71. !Node methodsFor: 'copying'!
  72. postCopy
  73. super postCopy.
  74. self nodes do: [ :each | each parent: self ]
  75. ! !
  76. !Node methodsFor: 'testing'!
  77. isAssignmentNode
  78. ^ false
  79. !
  80. isBlockNode
  81. ^ false
  82. !
  83. isBlockSequenceNode
  84. ^ false
  85. !
  86. isCascadeNode
  87. ^ false
  88. !
  89. isImmutable
  90. ^ false
  91. !
  92. isJSStatementNode
  93. ^ false
  94. !
  95. isLastChild
  96. ^ self parent nodes last = self
  97. !
  98. isNode
  99. ^ true
  100. !
  101. isReferenced
  102. "Answer true if the receiver is referenced by other nodes.
  103. Do not take sequences or assignments into account"
  104. ^ (self parent isSequenceNode or: [
  105. self parent isAssignmentNode ]) not
  106. !
  107. isReturnNode
  108. ^ false
  109. !
  110. isSendNode
  111. ^ false
  112. !
  113. isSequenceNode
  114. ^ false
  115. !
  116. isValueNode
  117. ^ false
  118. !
  119. isVariableNode
  120. ^ false
  121. !
  122. requiresSmalltalkContext
  123. "Answer true if the receiver requires a smalltalk context.
  124. Only send nodes require a context.
  125. If no node requires a context, the method will be compiled without one.
  126. See `IRJSTranslator` and `JSStream` for context creation"
  127. ^ (self nodes
  128. detect: [ :each | each requiresSmalltalkContext ]
  129. ifNone: [ nil ]) notNil
  130. !
  131. stopOnStepping
  132. ^ false
  133. !
  134. subtreeNeedsAliasing
  135. ^ (self shouldBeAliased or: [ self shouldBeInlined ]) or: [
  136. self nodes anySatisfy: [ :each | each subtreeNeedsAliasing ] ]
  137. ! !
  138. !Node methodsFor: 'visiting'!
  139. accept: aVisitor
  140. ^ aVisitor visitNode: self
  141. ! !
  142. Node subclass: #AssignmentNode
  143. instanceVariableNames: 'left right'
  144. package: 'Compiler-AST'!
  145. !AssignmentNode commentStamp!
  146. I represent an assignment node.!
  147. !AssignmentNode methodsFor: 'accessing'!
  148. left
  149. ^ left
  150. !
  151. left: aNode
  152. left := aNode.
  153. aNode parent: self
  154. !
  155. nodes
  156. ^ Array with: self left with: self right
  157. !
  158. right
  159. ^ right
  160. !
  161. right: aNode
  162. right := aNode.
  163. aNode parent: self
  164. ! !
  165. !AssignmentNode methodsFor: 'testing'!
  166. isAssignmentNode
  167. ^ true
  168. !
  169. shouldBeAliased
  170. ^ super shouldBeAliased or: [ self isReferenced ]
  171. ! !
  172. !AssignmentNode methodsFor: 'visiting'!
  173. accept: aVisitor
  174. ^ aVisitor visitAssignmentNode: self
  175. ! !
  176. Node subclass: #BlockNode
  177. instanceVariableNames: 'parameters scope'
  178. package: 'Compiler-AST'!
  179. !BlockNode commentStamp!
  180. I represent an block closure node.!
  181. !BlockNode methodsFor: 'accessing'!
  182. nextChild
  183. "Answer the receiver as we want to avoid eager evaluation"
  184. ^ self
  185. !
  186. nextNode: aNode
  187. "Answer the receiver as we want to avoid eager evaluation"
  188. ^ self
  189. !
  190. parameters
  191. ^ parameters ifNil: [ parameters := Array new ]
  192. !
  193. parameters: aCollection
  194. parameters := aCollection
  195. !
  196. scope
  197. ^ scope
  198. !
  199. scope: aLexicalScope
  200. scope := aLexicalScope
  201. ! !
  202. !BlockNode methodsFor: 'testing'!
  203. isBlockNode
  204. ^ true
  205. !
  206. subtreeNeedsAliasing
  207. ^ self shouldBeAliased or: [ self shouldBeInlined ]
  208. ! !
  209. !BlockNode methodsFor: 'visiting'!
  210. accept: aVisitor
  211. ^ aVisitor visitBlockNode: self
  212. ! !
  213. Node subclass: #CascadeNode
  214. instanceVariableNames: 'receiver'
  215. package: 'Compiler-AST'!
  216. !CascadeNode commentStamp!
  217. I represent an cascade node.!
  218. !CascadeNode methodsFor: 'accessing'!
  219. receiver
  220. ^ receiver
  221. !
  222. receiver: aNode
  223. receiver := aNode
  224. ! !
  225. !CascadeNode methodsFor: 'testing'!
  226. isCascadeNode
  227. ^ true
  228. ! !
  229. !CascadeNode methodsFor: 'visiting'!
  230. accept: aVisitor
  231. ^ aVisitor visitCascadeNode: self
  232. ! !
  233. Node subclass: #DynamicArrayNode
  234. instanceVariableNames: ''
  235. package: 'Compiler-AST'!
  236. !DynamicArrayNode commentStamp!
  237. I represent an dynamic array node.!
  238. !DynamicArrayNode methodsFor: 'visiting'!
  239. accept: aVisitor
  240. ^ aVisitor visitDynamicArrayNode: self
  241. ! !
  242. Node subclass: #DynamicDictionaryNode
  243. instanceVariableNames: ''
  244. package: 'Compiler-AST'!
  245. !DynamicDictionaryNode commentStamp!
  246. I represent an dynamic dictionary node.!
  247. !DynamicDictionaryNode methodsFor: 'visiting'!
  248. accept: aVisitor
  249. ^ aVisitor visitDynamicDictionaryNode: self
  250. ! !
  251. Node subclass: #JSStatementNode
  252. instanceVariableNames: 'source'
  253. package: 'Compiler-AST'!
  254. !JSStatementNode commentStamp!
  255. I represent an JavaScript statement node.!
  256. !JSStatementNode methodsFor: 'accessing'!
  257. source
  258. ^ source ifNil: [ '' ]
  259. !
  260. source: aString
  261. source := aString
  262. ! !
  263. !JSStatementNode methodsFor: 'testing'!
  264. isJSStatementNode
  265. ^ true
  266. ! !
  267. !JSStatementNode methodsFor: 'visiting'!
  268. accept: aVisitor
  269. ^ aVisitor visitJSStatementNode: self
  270. ! !
  271. Node subclass: #MethodNode
  272. instanceVariableNames: 'selector arguments source scope classReferences sendIndexes superSends'
  273. package: 'Compiler-AST'!
  274. !MethodNode commentStamp!
  275. I represent an method node.
  276. A method node must be the root and only method node of a valid AST.!
  277. !MethodNode methodsFor: 'accessing'!
  278. arguments
  279. ^ arguments ifNil: [ #() ]
  280. !
  281. arguments: aCollection
  282. arguments := aCollection
  283. !
  284. classReferences
  285. ^ classReferences
  286. !
  287. classReferences: aCollection
  288. classReferences := aCollection
  289. !
  290. extent
  291. ^ self source lines size @ (self source lines last size + 1)
  292. !
  293. messageSends
  294. ^ self sendIndexes keys
  295. !
  296. method
  297. ^ self
  298. !
  299. scope
  300. ^ scope
  301. !
  302. scope: aMethodScope
  303. scope := aMethodScope
  304. !
  305. selector
  306. ^ selector
  307. !
  308. selector: aString
  309. selector := aString
  310. !
  311. sendIndexes
  312. ^ sendIndexes
  313. !
  314. sendIndexes: aDictionary
  315. sendIndexes := aDictionary
  316. !
  317. source
  318. ^ source
  319. !
  320. source: aString
  321. source := aString
  322. !
  323. superSends
  324. ^ superSends
  325. !
  326. superSends: aCollection
  327. superSends := aCollection
  328. ! !
  329. !MethodNode methodsFor: 'visiting'!
  330. accept: aVisitor
  331. ^ aVisitor visitMethodNode: self
  332. ! !
  333. Node subclass: #ReturnNode
  334. instanceVariableNames: 'scope'
  335. package: 'Compiler-AST'!
  336. !ReturnNode commentStamp!
  337. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  338. !ReturnNode methodsFor: 'accessing'!
  339. scope
  340. ^ scope
  341. !
  342. scope: aLexicalScope
  343. scope := aLexicalScope
  344. ! !
  345. !ReturnNode methodsFor: 'testing'!
  346. isReturnNode
  347. ^ true
  348. !
  349. nonLocalReturn
  350. ^ self scope isMethodScope not
  351. ! !
  352. !ReturnNode methodsFor: 'visiting'!
  353. accept: aVisitor
  354. ^ aVisitor visitReturnNode: self
  355. ! !
  356. Node subclass: #SendNode
  357. instanceVariableNames: 'selector arguments receiver superSend index'
  358. package: 'Compiler-AST'!
  359. !SendNode commentStamp!
  360. I represent an message send node.!
  361. !SendNode methodsFor: 'accessing'!
  362. arguments
  363. ^ arguments ifNil: [ arguments := #() ]
  364. !
  365. arguments: aCollection
  366. arguments := aCollection.
  367. aCollection do: [ :each | each parent: self ]
  368. !
  369. cascadeNodeWithMessages: aCollection
  370. | first |
  371. first := SendNode new
  372. selector: self selector;
  373. arguments: self arguments;
  374. yourself.
  375. ^ CascadeNode new
  376. receiver: self receiver;
  377. nodes: (Array with: first), aCollection;
  378. yourself
  379. !
  380. index
  381. ^ index
  382. !
  383. index: anInteger
  384. index := anInteger
  385. !
  386. nodes
  387. self receiver ifNil: [ ^ self arguments copy ].
  388. ^ (Array with: self receiver)
  389. addAll: self arguments;
  390. yourself
  391. !
  392. receiver
  393. ^ receiver
  394. !
  395. receiver: aNode
  396. receiver := aNode.
  397. aNode isNode ifTrue: [
  398. aNode parent: self ]
  399. !
  400. selector
  401. ^ selector
  402. !
  403. selector: aString
  404. selector := aString
  405. !
  406. superSend
  407. ^ superSend ifNil: [ false ]
  408. !
  409. superSend: aBoolean
  410. superSend := aBoolean
  411. !
  412. valueForReceiver: anObject
  413. ^ SendNode new
  414. position: self position;
  415. receiver: (self receiver
  416. ifNil: [ anObject ]
  417. ifNotNil: [ self receiver valueForReceiver: anObject ]);
  418. selector: self selector;
  419. arguments: self arguments;
  420. yourself
  421. ! !
  422. !SendNode methodsFor: 'testing'!
  423. isCascadeSendNode
  424. ^ self parent isCascadeNode
  425. !
  426. isSendNode
  427. ^ true
  428. !
  429. requiresSmalltalkContext
  430. ^ true
  431. !
  432. shouldBeAliased
  433. "Because we keep track of send indexes, some send nodes need additional care for aliasing.
  434. See IRJSVisitor >> visitIRSend:"
  435. | sends |
  436. sends := (self method sendIndexes at: self selector) size.
  437. ^ super shouldBeAliased or: [
  438. (sends > 1 and: [ self index < sends ]) and: [ self isReferenced ] ]
  439. !
  440. stopOnStepping
  441. ^ true
  442. ! !
  443. !SendNode methodsFor: 'visiting'!
  444. accept: aVisitor
  445. ^ aVisitor visitSendNode: self
  446. ! !
  447. Node subclass: #SequenceNode
  448. instanceVariableNames: 'temps scope'
  449. package: 'Compiler-AST'!
  450. !SequenceNode commentStamp!
  451. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  452. !SequenceNode methodsFor: 'accessing'!
  453. scope
  454. ^ scope
  455. !
  456. scope: aLexicalScope
  457. scope := aLexicalScope
  458. !
  459. temps
  460. ^ temps ifNil: [ #() ]
  461. !
  462. temps: aCollection
  463. temps := aCollection
  464. ! !
  465. !SequenceNode methodsFor: 'converting'!
  466. asBlockSequenceNode
  467. ^ BlockSequenceNode new
  468. position: self position;
  469. nodes: self nodes;
  470. temps: self temps;
  471. yourself
  472. ! !
  473. !SequenceNode methodsFor: 'testing'!
  474. isSequenceNode
  475. ^ true
  476. ! !
  477. !SequenceNode methodsFor: 'visiting'!
  478. accept: aVisitor
  479. ^ aVisitor visitSequenceNode: self
  480. ! !
  481. SequenceNode subclass: #BlockSequenceNode
  482. instanceVariableNames: ''
  483. package: 'Compiler-AST'!
  484. !BlockSequenceNode commentStamp!
  485. I represent an special sequence node for block scopes.!
  486. !BlockSequenceNode methodsFor: 'testing'!
  487. isBlockSequenceNode
  488. ^ true
  489. ! !
  490. !BlockSequenceNode methodsFor: 'visiting'!
  491. accept: aVisitor
  492. ^ aVisitor visitBlockSequenceNode: self
  493. ! !
  494. Node subclass: #ValueNode
  495. instanceVariableNames: 'value'
  496. package: 'Compiler-AST'!
  497. !ValueNode commentStamp!
  498. I represent a value node.!
  499. !ValueNode methodsFor: 'accessing'!
  500. value
  501. ^ value
  502. !
  503. value: anObject
  504. value := anObject
  505. ! !
  506. !ValueNode methodsFor: 'testing'!
  507. isImmutable
  508. ^ self value isImmutable
  509. !
  510. isValueNode
  511. ^ true
  512. ! !
  513. !ValueNode methodsFor: 'visiting'!
  514. accept: aVisitor
  515. ^ aVisitor visitValueNode: self
  516. ! !
  517. ValueNode subclass: #VariableNode
  518. instanceVariableNames: 'assigned binding'
  519. package: 'Compiler-AST'!
  520. !VariableNode commentStamp!
  521. I represent an variable node.!
  522. !VariableNode methodsFor: 'accessing'!
  523. alias
  524. ^ self binding alias
  525. !
  526. assigned
  527. ^ assigned ifNil: [ false ]
  528. !
  529. assigned: aBoolean
  530. assigned := aBoolean
  531. !
  532. beAssigned
  533. self binding validateAssignment.
  534. assigned := true
  535. !
  536. binding
  537. ^ binding
  538. !
  539. binding: aScopeVar
  540. binding := aScopeVar
  541. ! !
  542. !VariableNode methodsFor: 'testing'!
  543. isArgument
  544. ^ self binding isArgVar
  545. !
  546. isImmutable
  547. ^ self binding isImmutable
  548. !
  549. isVariableNode
  550. ^ true
  551. ! !
  552. !VariableNode methodsFor: 'visiting'!
  553. accept: aVisitor
  554. ^ aVisitor visitVariableNode: self
  555. ! !
  556. !Object methodsFor: '*Compiler-AST'!
  557. isNode
  558. ^ false
  559. ! !
  560. !CompiledMethod methodsFor: '*Compiler-AST'!
  561. ast
  562. self source ifEmpty: [ self error: 'Method source is empty' ].
  563. ^ Smalltalk parse: self source
  564. ! !