Compiler-AST.st 13 KB

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