Compiler-AST.st 12 KB

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