Compiler-AST.st 12 KB

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