Compiler-AST.st 12 KB

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