Compiler-AST.st 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  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. extent
  15. "Answer the line and column of the end position of the receiver in the source code"
  16. ^ self nextNode
  17. ifNil: [ self parent ifNotNil: [ :node | node extent ] ]
  18. ifNotNil: [ :node | node position ]
  19. !
  20. nextChild
  21. "Answer the next node after aNode.
  22. Recurse into the possible children of the receiver to answer the next node to be evaluated"
  23. ^ self nodes isEmpty
  24. ifTrue: [ self ]
  25. ifFalse: [ self nodes first nextChild ]
  26. !
  27. nextNode
  28. ^ self parent ifNotNil: [ :node |
  29. node nextNode: self ]
  30. !
  31. nextNode: aNode
  32. "Answer the next node after aNode.
  33. Recurse into the possible children of the next node to answer the next node to be evaluated"
  34. | next |
  35. next := self nodes
  36. at: (self nodes indexOf: aNode) + 1
  37. ifAbsent: [ ^ self ].
  38. ^ next nextChild
  39. !
  40. nodes
  41. ^nodes ifNil: [nodes := Array new]
  42. !
  43. parent
  44. ^ parent
  45. !
  46. parent: aNode
  47. parent := aNode
  48. !
  49. position
  50. "answer the line and column of the receiver in the source code"
  51. ^ position ifNil: [
  52. self parent ifNotNil: [ :node | node position ] ]
  53. !
  54. shouldBeAliased
  55. ^ shouldBeAliased ifNil: [ false ]
  56. !
  57. shouldBeAliased: aBoolean
  58. shouldBeAliased := aBoolean
  59. !
  60. shouldBeInlined
  61. ^ shouldBeInlined ifNil: [ false ]
  62. !
  63. shouldBeInlined: aBoolean
  64. shouldBeInlined := aBoolean
  65. ! !
  66. !Node methodsFor: 'building'!
  67. nodes: aCollection
  68. nodes := aCollection.
  69. aCollection do: [ :each | each parent: self ]
  70. !
  71. position: aPosition
  72. position := aPosition
  73. ! !
  74. !Node methodsFor: 'testing'!
  75. isAssignmentNode
  76. ^ false
  77. !
  78. isBlockNode
  79. ^false
  80. !
  81. isBlockSequenceNode
  82. ^false
  83. !
  84. isImmutable
  85. ^false
  86. !
  87. isJSStatementNode
  88. ^ false
  89. !
  90. isNode
  91. ^ true
  92. !
  93. isReturnNode
  94. ^false
  95. !
  96. isSendNode
  97. ^false
  98. !
  99. isValueNode
  100. ^false
  101. !
  102. stopOnStepping
  103. ^ false
  104. !
  105. subtreeNeedsAliasing
  106. ^(self shouldBeAliased or: [ self shouldBeInlined ]) or: [
  107. (self nodes detect: [ :each | each subtreeNeedsAliasing ] ifNone: [ false ]) ~= false ]
  108. ! !
  109. !Node methodsFor: 'visiting'!
  110. accept: aVisitor
  111. ^ aVisitor visitNode: self
  112. ! !
  113. Node subclass: #AssignmentNode
  114. instanceVariableNames: 'left right'
  115. package: 'Compiler-AST'!
  116. !AssignmentNode commentStamp!
  117. I represent an assignment node.!
  118. !AssignmentNode methodsFor: 'accessing'!
  119. left
  120. ^left
  121. !
  122. left: aNode
  123. left := aNode.
  124. aNode parent: self
  125. !
  126. nodes
  127. ^ Array with: self left with: self right
  128. !
  129. right
  130. ^right
  131. !
  132. right: aNode
  133. right := aNode.
  134. aNode parent: self
  135. ! !
  136. !AssignmentNode methodsFor: 'testing'!
  137. isAssignmentNode
  138. ^ true
  139. ! !
  140. !AssignmentNode methodsFor: 'visiting'!
  141. accept: aVisitor
  142. ^ aVisitor visitAssignmentNode: self
  143. ! !
  144. Node subclass: #BlockNode
  145. instanceVariableNames: 'parameters scope'
  146. package: 'Compiler-AST'!
  147. !BlockNode commentStamp!
  148. I represent an block closure node.!
  149. !BlockNode methodsFor: 'accessing'!
  150. nextNode: aNode
  151. "Answer the receiver as we want to avoid eager evaluation"
  152. ^ self
  153. !
  154. parameters
  155. ^parameters ifNil: [parameters := Array new]
  156. !
  157. parameters: aCollection
  158. parameters := aCollection
  159. !
  160. scope
  161. ^ scope
  162. !
  163. scope: aLexicalScope
  164. scope := aLexicalScope
  165. ! !
  166. !BlockNode methodsFor: 'testing'!
  167. isBlockNode
  168. ^true
  169. !
  170. subtreeNeedsAliasing
  171. ^ self shouldBeAliased or: [ self shouldBeInlined ]
  172. ! !
  173. !BlockNode methodsFor: 'visiting'!
  174. accept: aVisitor
  175. ^ aVisitor visitBlockNode: self
  176. ! !
  177. Node subclass: #CascadeNode
  178. instanceVariableNames: 'receiver'
  179. package: 'Compiler-AST'!
  180. !CascadeNode commentStamp!
  181. I represent an cascade node.!
  182. !CascadeNode methodsFor: 'accessing'!
  183. receiver
  184. ^receiver
  185. !
  186. receiver: aNode
  187. receiver := aNode
  188. ! !
  189. !CascadeNode methodsFor: 'visiting'!
  190. accept: aVisitor
  191. ^ aVisitor visitCascadeNode: self
  192. ! !
  193. Node subclass: #DynamicArrayNode
  194. instanceVariableNames: ''
  195. package: 'Compiler-AST'!
  196. !DynamicArrayNode commentStamp!
  197. I represent an dynamic array node.!
  198. !DynamicArrayNode methodsFor: 'visiting'!
  199. accept: aVisitor
  200. ^ aVisitor visitDynamicArrayNode: self
  201. ! !
  202. Node subclass: #DynamicDictionaryNode
  203. instanceVariableNames: ''
  204. package: 'Compiler-AST'!
  205. !DynamicDictionaryNode commentStamp!
  206. I represent an dynamic dictionary node.!
  207. !DynamicDictionaryNode methodsFor: 'visiting'!
  208. accept: aVisitor
  209. ^ aVisitor visitDynamicDictionaryNode: self
  210. ! !
  211. Node subclass: #JSStatementNode
  212. instanceVariableNames: 'source'
  213. package: 'Compiler-AST'!
  214. !JSStatementNode commentStamp!
  215. I represent an JavaScript statement node.!
  216. !JSStatementNode methodsFor: 'accessing'!
  217. source
  218. ^source ifNil: ['']
  219. !
  220. source: aString
  221. source := aString
  222. ! !
  223. !JSStatementNode methodsFor: 'testing'!
  224. isJSStatementNode
  225. ^ true
  226. ! !
  227. !JSStatementNode methodsFor: 'visiting'!
  228. accept: aVisitor
  229. ^ aVisitor visitJSStatementNode: self
  230. ! !
  231. Node subclass: #MethodNode
  232. instanceVariableNames: 'selector arguments source scope classReferences messageSends superSends'
  233. package: 'Compiler-AST'!
  234. !MethodNode commentStamp!
  235. I represent an method node.
  236. A method node must be the root and only method node of a valid AST.!
  237. !MethodNode methodsFor: 'accessing'!
  238. arguments
  239. ^arguments ifNil: [#()]
  240. !
  241. arguments: aCollection
  242. arguments := aCollection
  243. !
  244. classReferences
  245. ^ classReferences
  246. !
  247. classReferences: aCollection
  248. classReferences := aCollection
  249. !
  250. extent
  251. ^ self source lines size @ (self source lines last size + 1)
  252. !
  253. messageSends
  254. ^ messageSends
  255. !
  256. messageSends: aCollection
  257. messageSends := aCollection
  258. !
  259. scope
  260. ^ scope
  261. !
  262. scope: aMethodScope
  263. scope := aMethodScope
  264. !
  265. selector
  266. ^selector
  267. !
  268. selector: aString
  269. selector := aString
  270. !
  271. source
  272. ^source
  273. !
  274. source: aString
  275. source := aString
  276. !
  277. superSends
  278. ^ superSends
  279. !
  280. superSends: aCollection
  281. superSends := aCollection
  282. ! !
  283. !MethodNode methodsFor: 'visiting'!
  284. accept: aVisitor
  285. ^ aVisitor visitMethodNode: self
  286. ! !
  287. Node subclass: #ReturnNode
  288. instanceVariableNames: 'scope'
  289. package: 'Compiler-AST'!
  290. !ReturnNode commentStamp!
  291. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  292. !ReturnNode methodsFor: 'accessing'!
  293. scope
  294. ^ scope
  295. !
  296. scope: aLexicalScope
  297. scope := aLexicalScope
  298. ! !
  299. !ReturnNode methodsFor: 'testing'!
  300. isReturnNode
  301. ^ true
  302. !
  303. nonLocalReturn
  304. ^ self scope isMethodScope not
  305. ! !
  306. !ReturnNode methodsFor: 'visiting'!
  307. accept: aVisitor
  308. ^ aVisitor visitReturnNode: self
  309. ! !
  310. Node subclass: #SendNode
  311. instanceVariableNames: 'selector arguments receiver superSend index'
  312. package: 'Compiler-AST'!
  313. !SendNode commentStamp!
  314. I represent an message send node.!
  315. !SendNode methodsFor: 'accessing'!
  316. arguments
  317. ^arguments ifNil: [arguments := #()]
  318. !
  319. arguments: aCollection
  320. arguments := aCollection.
  321. aCollection do: [ :each | each parent: self ]
  322. !
  323. cascadeNodeWithMessages: aCollection
  324. | first |
  325. first := SendNode new
  326. selector: self selector;
  327. arguments: self arguments;
  328. yourself.
  329. ^CascadeNode new
  330. receiver: self receiver;
  331. nodes: (Array with: first), aCollection;
  332. yourself
  333. !
  334. index
  335. ^ index
  336. !
  337. index: anInteger
  338. index := anInteger
  339. !
  340. nodes
  341. ^ (Array withAll: self arguments)
  342. add: self receiver;
  343. yourself
  344. !
  345. receiver
  346. ^receiver
  347. !
  348. receiver: aNode
  349. receiver := aNode.
  350. aNode isNode ifTrue: [
  351. aNode parent: self ]
  352. !
  353. selector
  354. ^selector
  355. !
  356. selector: aString
  357. selector := aString
  358. !
  359. superSend
  360. ^ superSend ifNil: [ false ]
  361. !
  362. superSend: aBoolean
  363. superSend := aBoolean
  364. !
  365. valueForReceiver: anObject
  366. ^SendNode new
  367. position: self position;
  368. receiver: (self receiver
  369. ifNil: [anObject]
  370. ifNotNil: [self receiver valueForReceiver: anObject]);
  371. selector: self selector;
  372. arguments: self arguments;
  373. yourself
  374. ! !
  375. !SendNode methodsFor: 'testing'!
  376. isSendNode
  377. ^ true
  378. !
  379. stopOnStepping
  380. ^ true
  381. ! !
  382. !SendNode methodsFor: 'visiting'!
  383. accept: aVisitor
  384. ^ aVisitor visitSendNode: self
  385. ! !
  386. Node subclass: #SequenceNode
  387. instanceVariableNames: 'temps scope'
  388. package: 'Compiler-AST'!
  389. !SequenceNode commentStamp!
  390. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  391. !SequenceNode methodsFor: 'accessing'!
  392. scope
  393. ^ scope
  394. !
  395. scope: aLexicalScope
  396. scope := aLexicalScope
  397. !
  398. temps
  399. ^temps ifNil: [#()]
  400. !
  401. temps: aCollection
  402. temps := aCollection
  403. ! !
  404. !SequenceNode methodsFor: 'testing'!
  405. asBlockSequenceNode
  406. ^BlockSequenceNode new
  407. position: self position;
  408. nodes: self nodes;
  409. temps: self temps;
  410. yourself
  411. ! !
  412. !SequenceNode methodsFor: 'visiting'!
  413. accept: 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. accept: aVisitor
  427. ^ aVisitor visitBlockSequenceNode: self
  428. ! !
  429. Node 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. accept: 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. !VariableNode methodsFor: 'testing'!
  478. isImmutable
  479. ^false
  480. ! !
  481. !VariableNode methodsFor: 'visiting'!
  482. accept: aVisitor
  483. ^ aVisitor visitVariableNode: self
  484. ! !
  485. VariableNode subclass: #ClassReferenceNode
  486. instanceVariableNames: ''
  487. package: 'Compiler-AST'!
  488. !ClassReferenceNode commentStamp!
  489. I represent an class reference node.!
  490. !ClassReferenceNode methodsFor: 'visiting'!
  491. accept: aVisitor
  492. ^ aVisitor visitClassReferenceNode: self
  493. ! !
  494. !Object methodsFor: '*Compiler-AST'!
  495. isNode
  496. ^ false
  497. ! !
  498. !CompiledMethod methodsFor: '*Compiler-AST'!
  499. ast
  500. self source ifEmpty: [ self error: 'Method source is empty' ].
  501. ^ Smalltalk current parse: self source
  502. ! !