Compiler-AST.st 14 KB

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