Compiler-AST.st 14 KB

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