Compiler-AST.st 13 KB

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