Compiler-AST.st 15 KB

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