Compiler-AST.st 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  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. isSuperKeyword
  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: #CascadeNode
  231. instanceVariableNames: 'receiver'
  232. package: 'Compiler-AST'!
  233. !CascadeNode commentStamp!
  234. I represent an cascade node.!
  235. !CascadeNode methodsFor: 'accessing'!
  236. receiver
  237. ^ receiver
  238. !
  239. receiver: aNode
  240. receiver := aNode
  241. ! !
  242. !CascadeNode methodsFor: 'testing'!
  243. isCascadeNode
  244. ^ true
  245. !
  246. subtreeNeedsAliasing
  247. ^ self parent isSequenceNode not
  248. ! !
  249. !CascadeNode methodsFor: 'visiting'!
  250. accept: aVisitor
  251. ^ aVisitor visitCascadeNode: self
  252. ! !
  253. Node subclass: #DynamicArrayNode
  254. instanceVariableNames: ''
  255. package: 'Compiler-AST'!
  256. !DynamicArrayNode commentStamp!
  257. I represent an dynamic array node.!
  258. !DynamicArrayNode methodsFor: 'visiting'!
  259. accept: aVisitor
  260. ^ aVisitor visitDynamicArrayNode: self
  261. ! !
  262. Node subclass: #DynamicDictionaryNode
  263. instanceVariableNames: ''
  264. package: 'Compiler-AST'!
  265. !DynamicDictionaryNode commentStamp!
  266. I represent an dynamic dictionary node.!
  267. !DynamicDictionaryNode methodsFor: 'visiting'!
  268. accept: aVisitor
  269. ^ aVisitor visitDynamicDictionaryNode: self
  270. ! !
  271. Node subclass: #JSStatementNode
  272. instanceVariableNames: ''
  273. package: 'Compiler-AST'!
  274. !JSStatementNode commentStamp!
  275. I represent an JavaScript statement node.!
  276. !JSStatementNode methodsFor: 'testing'!
  277. isJSStatementNode
  278. ^ true
  279. !
  280. requiresSmalltalkContext
  281. ^ true
  282. ! !
  283. !JSStatementNode methodsFor: 'visiting'!
  284. accept: aVisitor
  285. ^ aVisitor visitJSStatementNode: self
  286. ! !
  287. Node subclass: #MethodNode
  288. instanceVariableNames: 'selector arguments source scope classReferences sendIndexes'
  289. package: 'Compiler-AST'!
  290. !MethodNode commentStamp!
  291. I represent an method node.
  292. A method node must be the root and only method node of a valid AST.!
  293. !MethodNode methodsFor: 'accessing'!
  294. arguments
  295. ^ arguments ifNil: [ #() ]
  296. !
  297. arguments: aCollection
  298. arguments := aCollection
  299. !
  300. classReferences
  301. ^ classReferences
  302. !
  303. classReferences: aCollection
  304. classReferences := aCollection
  305. !
  306. messageSends
  307. ^ self sendIndexes keys
  308. !
  309. method
  310. ^ self
  311. !
  312. scope
  313. ^ scope
  314. !
  315. scope: aMethodScope
  316. scope := aMethodScope
  317. !
  318. selector
  319. ^ selector
  320. !
  321. selector: aString
  322. selector := aString
  323. !
  324. sendIndexes
  325. ^ sendIndexes
  326. !
  327. sendIndexes: aDictionary
  328. sendIndexes := aDictionary
  329. !
  330. sequenceNode
  331. self nodes do: [ :each |
  332. each isSequenceNode ifTrue: [ ^ each ] ].
  333. ^ nil
  334. !
  335. source
  336. ^ source
  337. !
  338. source: aString
  339. source := aString
  340. ! !
  341. !MethodNode methodsFor: 'visiting'!
  342. accept: aVisitor
  343. ^ aVisitor visitMethodNode: self
  344. ! !
  345. Node subclass: #ReturnNode
  346. instanceVariableNames: 'scope'
  347. package: 'Compiler-AST'!
  348. !ReturnNode commentStamp!
  349. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  350. !ReturnNode methodsFor: 'accessing'!
  351. scope
  352. ^ scope
  353. !
  354. scope: aLexicalScope
  355. scope := aLexicalScope
  356. ! !
  357. !ReturnNode methodsFor: 'testing'!
  358. isReturnNode
  359. ^ true
  360. !
  361. nonLocalReturn
  362. ^ self scope isMethodScope not
  363. ! !
  364. !ReturnNode methodsFor: 'visiting'!
  365. accept: aVisitor
  366. ^ aVisitor visitReturnNode: self
  367. ! !
  368. Node subclass: #SendNode
  369. instanceVariableNames: 'selector arguments receiver index'
  370. package: 'Compiler-AST'!
  371. !SendNode commentStamp!
  372. I represent an message send node.!
  373. !SendNode methodsFor: 'accessing'!
  374. arguments
  375. ^ arguments ifNil: [ arguments := #() ]
  376. !
  377. arguments: aCollection
  378. arguments := aCollection.
  379. aCollection do: [ :each | each parent: self ]
  380. !
  381. cascadeNodeWithMessages: aCollection
  382. | first |
  383. first := SendNode new
  384. selector: self selector;
  385. arguments: self arguments;
  386. yourself.
  387. ^ CascadeNode new
  388. receiver: self receiver;
  389. nodes: (Array with: first), aCollection;
  390. yourself
  391. !
  392. index
  393. ^ index
  394. !
  395. index: anInteger
  396. index := anInteger
  397. !
  398. navigationLink
  399. ^ self selector
  400. !
  401. nodes
  402. self receiver ifNil: [ ^ self arguments copy ].
  403. ^ (Array with: self receiver)
  404. addAll: self arguments;
  405. yourself
  406. !
  407. receiver
  408. ^ receiver
  409. !
  410. receiver: aNode
  411. receiver := aNode.
  412. aNode isNode ifTrue: [
  413. aNode parent: self ]
  414. !
  415. selector
  416. ^ selector
  417. !
  418. selector: aString
  419. selector := aString
  420. !
  421. superSend
  422. ^ self receiver notNil and: [ self receiver isSuperKeyword ]
  423. ! !
  424. !SendNode methodsFor: 'building'!
  425. valueForReceiver: anObject
  426. ^ SendNode new
  427. position: self position;
  428. source: self source;
  429. receiver: (self receiver
  430. ifNil: [ anObject ]
  431. ifNotNil: [ self receiver valueForReceiver: anObject ]);
  432. selector: self selector;
  433. arguments: self arguments;
  434. yourself
  435. ! !
  436. !SendNode methodsFor: 'testing'!
  437. isCascadeSendNode
  438. ^ self parent isCascadeNode
  439. !
  440. isNavigationNode
  441. ^ true
  442. !
  443. isSendNode
  444. ^ true
  445. !
  446. requiresSmalltalkContext
  447. ^ true
  448. !
  449. shouldBeAliased
  450. "Because we keep track of send indexes, some send nodes need additional care for aliasing.
  451. See IRJSVisitor >> visitIRSend:"
  452. | sends |
  453. sends := (self method sendIndexes at: self selector) size.
  454. ^ (super shouldBeAliased or: [
  455. self isReferenced and: [
  456. self index < sends or: [
  457. self superSend ] ] ])
  458. ! !
  459. !SendNode methodsFor: 'visiting'!
  460. accept: aVisitor
  461. ^ aVisitor visitSendNode: self
  462. ! !
  463. Node subclass: #SequenceNode
  464. instanceVariableNames: 'temps scope'
  465. package: 'Compiler-AST'!
  466. !SequenceNode commentStamp!
  467. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  468. !SequenceNode methodsFor: 'accessing'!
  469. scope
  470. ^ scope
  471. !
  472. scope: aLexicalScope
  473. scope := aLexicalScope
  474. !
  475. temps
  476. ^ temps ifNil: [ #() ]
  477. !
  478. temps: aCollection
  479. temps := aCollection
  480. ! !
  481. !SequenceNode methodsFor: 'building'!
  482. asBlockSequenceNode
  483. ^ BlockSequenceNode new
  484. position: self position;
  485. source: self source;
  486. nodes: self nodes;
  487. temps: self temps;
  488. yourself
  489. ! !
  490. !SequenceNode methodsFor: 'testing'!
  491. isSequenceNode
  492. ^ true
  493. ! !
  494. !SequenceNode methodsFor: 'visiting'!
  495. accept: aVisitor
  496. ^ aVisitor visitSequenceNode: self
  497. ! !
  498. SequenceNode subclass: #BlockSequenceNode
  499. instanceVariableNames: ''
  500. package: 'Compiler-AST'!
  501. !BlockSequenceNode commentStamp!
  502. I represent an special sequence node for block scopes.!
  503. !BlockSequenceNode methodsFor: 'testing'!
  504. isBlockSequenceNode
  505. ^ true
  506. ! !
  507. !BlockSequenceNode methodsFor: 'visiting'!
  508. accept: aVisitor
  509. ^ aVisitor visitBlockSequenceNode: self
  510. ! !
  511. Node subclass: #ValueNode
  512. instanceVariableNames: 'value'
  513. package: 'Compiler-AST'!
  514. !ValueNode commentStamp!
  515. I represent a value node.!
  516. !ValueNode methodsFor: 'accessing'!
  517. value
  518. ^ value
  519. !
  520. value: anObject
  521. value := anObject
  522. ! !
  523. !ValueNode methodsFor: 'testing'!
  524. isImmutable
  525. ^ self value isImmutable
  526. !
  527. isValueNode
  528. ^ true
  529. ! !
  530. !ValueNode methodsFor: 'visiting'!
  531. accept: aVisitor
  532. ^ aVisitor visitValueNode: self
  533. ! !
  534. ValueNode subclass: #VariableNode
  535. instanceVariableNames: 'assigned binding'
  536. package: 'Compiler-AST'!
  537. !VariableNode commentStamp!
  538. I represent an variable node.!
  539. !VariableNode methodsFor: 'accessing'!
  540. alias
  541. ^ self binding alias
  542. !
  543. assigned
  544. ^ assigned ifNil: [ false ]
  545. !
  546. assigned: aBoolean
  547. assigned := aBoolean
  548. !
  549. beAssigned
  550. self binding validateAssignment.
  551. assigned := true
  552. !
  553. binding
  554. ^ binding
  555. !
  556. binding: aScopeVar
  557. binding := aScopeVar
  558. !
  559. navigationLink
  560. ^ self value
  561. ! !
  562. !VariableNode methodsFor: 'testing'!
  563. isArgument
  564. ^ self binding isArgVar
  565. !
  566. isImmutable
  567. ^ self binding isImmutable
  568. !
  569. isNavigationNode
  570. ^ true
  571. !
  572. isSuperKeyword
  573. ^ self value = 'super'
  574. !
  575. isVariableNode
  576. ^ true
  577. ! !
  578. !VariableNode methodsFor: 'visiting'!
  579. accept: aVisitor
  580. ^ aVisitor visitVariableNode: self
  581. ! !
  582. Object subclass: #NodeVisitor
  583. instanceVariableNames: ''
  584. package: 'Compiler-AST'!
  585. !NodeVisitor commentStamp!
  586. I am the abstract super class of all AST node visitors.!
  587. !NodeVisitor methodsFor: 'visiting'!
  588. visit: aNode
  589. ^ aNode accept: self
  590. !
  591. visitAll: aCollection
  592. ^ aCollection collect: [ :each | self visit: each ]
  593. !
  594. visitAssignmentNode: aNode
  595. ^ self visitNode: aNode
  596. !
  597. visitBlockNode: aNode
  598. ^ self visitNode: aNode
  599. !
  600. visitBlockSequenceNode: aNode
  601. ^ self visitSequenceNode: aNode
  602. !
  603. visitCascadeNode: aNode
  604. ^ self visitNode: aNode
  605. !
  606. visitDynamicArrayNode: aNode
  607. ^ self visitNode: aNode
  608. !
  609. visitDynamicDictionaryNode: aNode
  610. ^ self visitNode: aNode
  611. !
  612. visitJSStatementNode: aNode
  613. ^ self visitNode: aNode
  614. !
  615. visitMethodNode: aNode
  616. ^ self visitNode: aNode
  617. !
  618. visitNode: aNode
  619. self visitAll: aNode nodes.
  620. ^ aNode
  621. !
  622. visitReturnNode: aNode
  623. ^ self visitNode: aNode
  624. !
  625. visitSendNode: aNode
  626. ^ self visitNode: aNode
  627. !
  628. visitSequenceNode: aNode
  629. ^ self visitNode: aNode
  630. !
  631. visitValueNode: aNode
  632. ^ self visitNode: aNode
  633. !
  634. visitVariableNode: aNode
  635. ^ self visitNode: aNode
  636. ! !
  637. !CompiledMethod methodsFor: '*Compiler-AST'!
  638. ast
  639. self source ifEmpty: [ self error: 'Method source is empty' ].
  640. ^ Smalltalk parse: self source
  641. ! !
  642. !Object methodsFor: '*Compiler-AST'!
  643. isNode
  644. ^ false
  645. ! !