Compiler-AST.st 13 KB

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