2
0

Compiler-AST.st 12 KB

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