Compiler-AST.st 12 KB

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