Compiler-AST.st 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. Smalltalk current createPackage: 'Compiler-AST'!
  2. Object subclass: #Node
  3. instanceVariableNames: 'parent position 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. nextChild
  15. "Answer the next node after aNode.
  16. Recurse into the possible children of the receiver to answer the next node to be evaluated"
  17. ^ self nodes isEmpty
  18. ifTrue: [ self ]
  19. ifFalse: [ self nodes first nextChild ]
  20. !
  21. nextNode
  22. ^ self parent ifNotNil: [ :node |
  23. node nextNode: self ]
  24. !
  25. nextNode: aNode
  26. "Answer the next node after aNode.
  27. Recurse into the possible children of the next node to answer the next node to be evaluated"
  28. | next |
  29. next := self nodes
  30. at: (self nodes indexOf: aNode) + 1
  31. ifAbsent: [ ^ self ].
  32. ^ next nextChild
  33. !
  34. nodes
  35. ^nodes ifNil: [nodes := Array new]
  36. !
  37. parent
  38. ^ parent
  39. !
  40. parent: aNode
  41. parent := aNode
  42. !
  43. position
  44. "answer the line and column of the receiver in the source code"
  45. ^ position ifNil: [
  46. self parent ifNotNil: [ :node | node 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. !Node methodsFor: 'building'!
  61. nodes: aCollection
  62. nodes := aCollection.
  63. aCollection do: [ :each | each parent: self ]
  64. !
  65. position: aPosition
  66. position := aPosition
  67. ! !
  68. !Node methodsFor: 'copying'!
  69. postCopy
  70. super postCopy.
  71. self nodes do: [ :each | each parent: self ]
  72. ! !
  73. !Node methodsFor: 'testing'!
  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 nodes last = self
  94. !
  95. isNode
  96. ^ true
  97. !
  98. isReturnNode
  99. ^false
  100. !
  101. isSendNode
  102. ^false
  103. !
  104. isValueNode
  105. ^false
  106. !
  107. stopOnStepping
  108. ^ false
  109. !
  110. subtreeNeedsAliasing
  111. ^(self shouldBeAliased or: [ self shouldBeInlined ]) or: [
  112. (self nodes detect: [ :each | each subtreeNeedsAliasing ] ifNone: [ false ]) ~= false ]
  113. ! !
  114. !Node methodsFor: 'visiting'!
  115. accept: aVisitor
  116. ^ aVisitor visitNode: self
  117. ! !
  118. Node subclass: #AssignmentNode
  119. instanceVariableNames: 'left right'
  120. package: 'Compiler-AST'!
  121. !AssignmentNode commentStamp!
  122. I represent an assignment node.!
  123. !AssignmentNode methodsFor: 'accessing'!
  124. left
  125. ^left
  126. !
  127. left: aNode
  128. left := aNode.
  129. aNode parent: self
  130. !
  131. nodes
  132. ^ Array with: self left with: self right
  133. !
  134. right
  135. ^right
  136. !
  137. right: aNode
  138. right := aNode.
  139. aNode parent: self
  140. ! !
  141. !AssignmentNode methodsFor: 'testing'!
  142. isAssignmentNode
  143. ^ true
  144. ! !
  145. !AssignmentNode methodsFor: 'visiting'!
  146. accept: aVisitor
  147. ^ aVisitor visitAssignmentNode: self
  148. ! !
  149. Node subclass: #BlockNode
  150. instanceVariableNames: 'parameters scope'
  151. package: 'Compiler-AST'!
  152. !BlockNode commentStamp!
  153. I represent an block closure node.!
  154. !BlockNode methodsFor: 'accessing'!
  155. nextChild
  156. "Answer the receiver as we want to avoid eager evaluation"
  157. ^ self
  158. !
  159. nextNode: aNode
  160. "Answer the receiver as we want to avoid eager evaluation"
  161. ^ self
  162. !
  163. parameters
  164. ^parameters ifNil: [parameters := Array new]
  165. !
  166. parameters: aCollection
  167. parameters := aCollection
  168. !
  169. scope
  170. ^ scope
  171. !
  172. scope: aLexicalScope
  173. scope := aLexicalScope
  174. ! !
  175. !BlockNode methodsFor: 'testing'!
  176. isBlockNode
  177. ^true
  178. !
  179. subtreeNeedsAliasing
  180. ^ self shouldBeAliased or: [ self shouldBeInlined ]
  181. ! !
  182. !BlockNode methodsFor: 'visiting'!
  183. accept: aVisitor
  184. ^ aVisitor visitBlockNode: self
  185. ! !
  186. Node subclass: #CascadeNode
  187. instanceVariableNames: 'receiver'
  188. package: 'Compiler-AST'!
  189. !CascadeNode commentStamp!
  190. I represent an cascade node.!
  191. !CascadeNode methodsFor: 'accessing'!
  192. receiver
  193. ^receiver
  194. !
  195. receiver: aNode
  196. receiver := aNode
  197. ! !
  198. !CascadeNode methodsFor: 'testing'!
  199. isCascadeNode
  200. ^ true
  201. ! !
  202. !CascadeNode methodsFor: 'visiting'!
  203. accept: aVisitor
  204. ^ aVisitor visitCascadeNode: self
  205. ! !
  206. Node subclass: #DynamicArrayNode
  207. instanceVariableNames: ''
  208. package: 'Compiler-AST'!
  209. !DynamicArrayNode commentStamp!
  210. I represent an dynamic array node.!
  211. !DynamicArrayNode methodsFor: 'visiting'!
  212. accept: aVisitor
  213. ^ aVisitor visitDynamicArrayNode: self
  214. ! !
  215. Node subclass: #DynamicDictionaryNode
  216. instanceVariableNames: ''
  217. package: 'Compiler-AST'!
  218. !DynamicDictionaryNode commentStamp!
  219. I represent an dynamic dictionary node.!
  220. !DynamicDictionaryNode methodsFor: 'visiting'!
  221. accept: aVisitor
  222. ^ aVisitor visitDynamicDictionaryNode: self
  223. ! !
  224. Node subclass: #JSStatementNode
  225. instanceVariableNames: 'source'
  226. package: 'Compiler-AST'!
  227. !JSStatementNode commentStamp!
  228. I represent an JavaScript statement node.!
  229. !JSStatementNode methodsFor: 'accessing'!
  230. source
  231. ^source ifNil: ['']
  232. !
  233. source: aString
  234. source := aString
  235. ! !
  236. !JSStatementNode methodsFor: 'testing'!
  237. isJSStatementNode
  238. ^ true
  239. ! !
  240. !JSStatementNode methodsFor: 'visiting'!
  241. accept: aVisitor
  242. ^ aVisitor visitJSStatementNode: self
  243. ! !
  244. Node subclass: #MethodNode
  245. instanceVariableNames: 'selector arguments source scope classReferences sendIndexes superSends'
  246. package: 'Compiler-AST'!
  247. !MethodNode commentStamp!
  248. I represent an method node.
  249. A method node must be the root and only method node of a valid AST.!
  250. !MethodNode methodsFor: 'accessing'!
  251. arguments
  252. ^arguments ifNil: [#()]
  253. !
  254. arguments: aCollection
  255. arguments := aCollection
  256. !
  257. classReferences
  258. ^ classReferences
  259. !
  260. classReferences: aCollection
  261. classReferences := aCollection
  262. !
  263. extent
  264. ^ self source lines size @ (self source lines last size + 1)
  265. !
  266. messageSends
  267. ^ self sendIndexes keys
  268. !
  269. scope
  270. ^ scope
  271. !
  272. scope: aMethodScope
  273. scope := aMethodScope
  274. !
  275. selector
  276. ^selector
  277. !
  278. selector: aString
  279. selector := aString
  280. !
  281. sendIndexes
  282. ^ sendIndexes
  283. !
  284. sendIndexes: aDictionary
  285. sendIndexes := aDictionary
  286. !
  287. source
  288. ^source
  289. !
  290. source: aString
  291. source := aString
  292. !
  293. superSends
  294. ^ superSends
  295. !
  296. superSends: aCollection
  297. superSends := aCollection
  298. ! !
  299. !MethodNode methodsFor: 'visiting'!
  300. accept: aVisitor
  301. ^ aVisitor visitMethodNode: self
  302. ! !
  303. Node subclass: #ReturnNode
  304. instanceVariableNames: 'scope'
  305. package: 'Compiler-AST'!
  306. !ReturnNode commentStamp!
  307. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  308. !ReturnNode methodsFor: 'accessing'!
  309. scope
  310. ^ scope
  311. !
  312. scope: aLexicalScope
  313. scope := aLexicalScope
  314. ! !
  315. !ReturnNode methodsFor: 'testing'!
  316. isReturnNode
  317. ^ true
  318. !
  319. nonLocalReturn
  320. ^ self scope isMethodScope not
  321. ! !
  322. !ReturnNode methodsFor: 'visiting'!
  323. accept: aVisitor
  324. ^ aVisitor visitReturnNode: self
  325. ! !
  326. Node subclass: #SendNode
  327. instanceVariableNames: 'selector arguments receiver superSend index'
  328. package: 'Compiler-AST'!
  329. !SendNode commentStamp!
  330. I represent an message send node.!
  331. !SendNode methodsFor: 'accessing'!
  332. arguments
  333. ^arguments ifNil: [arguments := #()]
  334. !
  335. arguments: aCollection
  336. arguments := aCollection.
  337. aCollection do: [ :each | each parent: self ]
  338. !
  339. cascadeNodeWithMessages: aCollection
  340. | first |
  341. first := SendNode new
  342. selector: self selector;
  343. arguments: self arguments;
  344. yourself.
  345. ^CascadeNode new
  346. receiver: self receiver;
  347. nodes: (Array with: first), aCollection;
  348. yourself
  349. !
  350. index
  351. ^ index
  352. !
  353. index: anInteger
  354. index := anInteger
  355. !
  356. nodes
  357. self receiver ifNil: [ ^ self arguments copy ].
  358. ^ (Array with: self receiver)
  359. addAll: self arguments;
  360. yourself
  361. !
  362. receiver
  363. ^receiver
  364. !
  365. receiver: aNode
  366. receiver := aNode.
  367. aNode isNode ifTrue: [
  368. aNode parent: self ]
  369. !
  370. selector
  371. ^selector
  372. !
  373. selector: aString
  374. selector := aString
  375. !
  376. superSend
  377. ^ superSend ifNil: [ false ]
  378. !
  379. superSend: aBoolean
  380. superSend := aBoolean
  381. !
  382. valueForReceiver: anObject
  383. ^SendNode new
  384. position: self position;
  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. isSendNode
  397. ^ true
  398. !
  399. stopOnStepping
  400. ^ true
  401. ! !
  402. !SendNode methodsFor: 'visiting'!
  403. accept: aVisitor
  404. ^ aVisitor visitSendNode: self
  405. ! !
  406. Node subclass: #SequenceNode
  407. instanceVariableNames: 'temps scope'
  408. package: 'Compiler-AST'!
  409. !SequenceNode commentStamp!
  410. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  411. !SequenceNode methodsFor: 'accessing'!
  412. scope
  413. ^ scope
  414. !
  415. scope: aLexicalScope
  416. scope := aLexicalScope
  417. !
  418. temps
  419. ^temps ifNil: [#()]
  420. !
  421. temps: aCollection
  422. temps := aCollection
  423. ! !
  424. !SequenceNode methodsFor: 'testing'!
  425. asBlockSequenceNode
  426. ^BlockSequenceNode new
  427. position: self position;
  428. nodes: self nodes;
  429. temps: self temps;
  430. yourself
  431. ! !
  432. !SequenceNode methodsFor: 'visiting'!
  433. accept: aVisitor
  434. ^ aVisitor visitSequenceNode: self
  435. ! !
  436. SequenceNode subclass: #BlockSequenceNode
  437. instanceVariableNames: ''
  438. package: 'Compiler-AST'!
  439. !BlockSequenceNode commentStamp!
  440. I represent an special sequence node for block scopes.!
  441. !BlockSequenceNode methodsFor: 'testing'!
  442. isBlockSequenceNode
  443. ^true
  444. ! !
  445. !BlockSequenceNode methodsFor: 'visiting'!
  446. accept: aVisitor
  447. ^ aVisitor visitBlockSequenceNode: self
  448. ! !
  449. Node subclass: #ValueNode
  450. instanceVariableNames: 'value'
  451. package: 'Compiler-AST'!
  452. !ValueNode commentStamp!
  453. I represent a value node.!
  454. !ValueNode methodsFor: 'accessing'!
  455. value
  456. ^value
  457. !
  458. value: anObject
  459. value := anObject
  460. ! !
  461. !ValueNode methodsFor: 'testing'!
  462. isImmutable
  463. ^ self value isImmutable
  464. !
  465. isValueNode
  466. ^true
  467. ! !
  468. !ValueNode methodsFor: 'visiting'!
  469. accept: aVisitor
  470. ^ aVisitor visitValueNode: self
  471. ! !
  472. !ValueNode methodsFor: 'xxxDoIt'!
  473. xxxDoIt ^[self stack] value
  474. ! !
  475. ValueNode subclass: #VariableNode
  476. instanceVariableNames: 'assigned binding'
  477. package: 'Compiler-AST'!
  478. !VariableNode commentStamp!
  479. I represent an variable node.!
  480. !VariableNode methodsFor: 'accessing'!
  481. alias
  482. ^ self binding alias
  483. !
  484. assigned
  485. ^assigned ifNil: [false]
  486. !
  487. assigned: aBoolean
  488. assigned := aBoolean
  489. !
  490. beAssigned
  491. self binding validateAssignment.
  492. assigned := true
  493. !
  494. binding
  495. ^ binding
  496. !
  497. binding: aScopeVar
  498. binding := aScopeVar
  499. ! !
  500. !VariableNode methodsFor: 'testing'!
  501. isImmutable
  502. ^false
  503. ! !
  504. !VariableNode methodsFor: 'visiting'!
  505. accept: aVisitor
  506. ^ aVisitor visitVariableNode: self
  507. ! !
  508. !Object methodsFor: '*Compiler-AST'!
  509. isNode
  510. ^ false
  511. ! !
  512. !CompiledMethod methodsFor: '*Compiler-AST'!
  513. ast
  514. self source ifEmpty: [ self error: 'Method source is empty' ].
  515. ^ Smalltalk current parse: self source
  516. ! !