Compiler-AST.st 9.9 KB

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