1
0

Compiler-AST.st 12 KB

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