Compiler-AST.st 12 KB

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