2
0

Compiler-AST.st 14 KB

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