Compiler-AST.st 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. Smalltalk createPackage: 'Compiler-AST'!
  2. DagParentNode subclass: #ASTNode
  3. slots: {#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. isSuper
  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. slots: {#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. slots: {#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. slots: {#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. slots: {}
  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. slots: {}
  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. slots: {}
  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. slots: {#selector. #arguments. #source. #pragmas. #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. pragmas
  263. ^ pragmas ifNil: [ #() ]
  264. !
  265. pragmas: aCollection
  266. pragmas := aCollection
  267. !
  268. scope
  269. ^ scope
  270. !
  271. scope: aMethodScope
  272. scope := aMethodScope
  273. !
  274. selector
  275. ^ selector
  276. !
  277. selector: aString
  278. selector := aString
  279. !
  280. sendIndexes
  281. ^ sendIndexes
  282. !
  283. sendIndexes: aDictionary
  284. sendIndexes := aDictionary
  285. !
  286. sequenceNode
  287. self dagChildren do: [ :each |
  288. each isSequenceNode ifTrue: [ ^ each ] ].
  289. ^ nil
  290. !
  291. source
  292. ^ source
  293. !
  294. source: aString
  295. source := aString
  296. ! !
  297. !MethodNode methodsFor: 'visiting'!
  298. acceptDagVisitor: aVisitor
  299. ^ aVisitor visitMethodNode: self
  300. ! !
  301. ASTNode subclass: #ReturnNode
  302. slots: {#scope}
  303. package: 'Compiler-AST'!
  304. !ReturnNode commentStamp!
  305. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  306. !ReturnNode methodsFor: 'accessing'!
  307. scope
  308. ^ scope
  309. !
  310. scope: aLexicalScope
  311. scope := aLexicalScope
  312. ! !
  313. !ReturnNode methodsFor: 'testing'!
  314. isReturnNode
  315. ^ true
  316. !
  317. nonLocalReturn
  318. ^ self scope isMethodScope not
  319. ! !
  320. !ReturnNode methodsFor: 'visiting'!
  321. acceptDagVisitor: aVisitor
  322. ^ aVisitor visitReturnNode: self
  323. ! !
  324. ASTNode subclass: #SendNode
  325. slots: {#selector. #arguments. #receiver. #index. #shouldBeInlined}
  326. package: 'Compiler-AST'!
  327. !SendNode commentStamp!
  328. I represent an message send node.!
  329. !SendNode methodsFor: 'accessing'!
  330. arguments
  331. ^ arguments ifNil: [ arguments := #() ]
  332. !
  333. arguments: aCollection
  334. arguments := aCollection
  335. !
  336. dagChildren
  337. self receiver ifNil: [ ^ self arguments copy ].
  338. ^ (Array with: self receiver)
  339. addAll: self arguments;
  340. yourself
  341. !
  342. index
  343. ^ index
  344. !
  345. index: anInteger
  346. index := anInteger
  347. !
  348. navigationLink
  349. ^ self selector
  350. !
  351. receiver
  352. ^ receiver
  353. !
  354. receiver: aNode
  355. receiver := aNode
  356. !
  357. selector
  358. ^ selector
  359. !
  360. selector: aString
  361. selector := aString
  362. !
  363. shouldBeInlined
  364. ^ shouldBeInlined ifNil: [ false ]
  365. !
  366. shouldBeInlined: aBoolean
  367. shouldBeInlined := aBoolean
  368. !
  369. superSend
  370. ^ self receiver notNil and: [ self receiver isSuper ]
  371. ! !
  372. !SendNode methodsFor: 'testing'!
  373. isNavigationNode
  374. ^ true
  375. !
  376. isSendNode
  377. ^ true
  378. !
  379. requiresSmalltalkContext
  380. ^ true
  381. ! !
  382. !SendNode methodsFor: 'visiting'!
  383. acceptDagVisitor: aVisitor
  384. ^ aVisitor visitSendNode: self
  385. ! !
  386. ASTNode subclass: #SequenceNode
  387. slots: {#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. isSequenceNode
  406. ^ true
  407. ! !
  408. !SequenceNode methodsFor: 'visiting'!
  409. acceptDagVisitor: aVisitor
  410. ^ aVisitor visitSequenceNode: self
  411. ! !
  412. SequenceNode subclass: #BlockSequenceNode
  413. slots: {}
  414. package: 'Compiler-AST'!
  415. !BlockSequenceNode commentStamp!
  416. I represent an special sequence node for block scopes.!
  417. !BlockSequenceNode methodsFor: 'testing'!
  418. isBlockSequenceNode
  419. ^ true
  420. ! !
  421. !BlockSequenceNode methodsFor: 'visiting'!
  422. acceptDagVisitor: aVisitor
  423. ^ aVisitor visitBlockSequenceNode: self
  424. ! !
  425. ASTNode subclass: #ValueNode
  426. slots: {#value}
  427. package: 'Compiler-AST'!
  428. !ValueNode commentStamp!
  429. I represent a value node.!
  430. !ValueNode methodsFor: 'accessing'!
  431. value
  432. ^ value
  433. !
  434. value: anObject
  435. value := anObject
  436. ! !
  437. !ValueNode methodsFor: 'testing'!
  438. isImmutable
  439. ^ self value isImmutable
  440. !
  441. isValueNode
  442. ^ true
  443. ! !
  444. !ValueNode methodsFor: 'visiting'!
  445. acceptDagVisitor: aVisitor
  446. ^ aVisitor visitValueNode: self
  447. ! !
  448. ValueNode subclass: #VariableNode
  449. slots: {#assigned. #binding}
  450. package: 'Compiler-AST'!
  451. !VariableNode commentStamp!
  452. I represent an variable node.!
  453. !VariableNode methodsFor: 'accessing'!
  454. alias
  455. ^ self binding alias
  456. !
  457. assigned
  458. ^ assigned ifNil: [ false ]
  459. !
  460. assigned: aBoolean
  461. assigned := aBoolean
  462. !
  463. beAssigned
  464. self binding validateAssignment.
  465. assigned := true
  466. !
  467. binding
  468. ^ binding
  469. !
  470. binding: aScopeVar
  471. binding := aScopeVar
  472. !
  473. navigationLink
  474. ^ self value
  475. ! !
  476. !VariableNode methodsFor: 'testing'!
  477. isArgument
  478. ^ self binding isArgVar
  479. !
  480. isImmutable
  481. ^ self binding isImmutable
  482. !
  483. isNavigationNode
  484. ^ true
  485. !
  486. isSuper
  487. ^ self binding isSuper
  488. !
  489. isVariableNode
  490. ^ true
  491. ! !
  492. !VariableNode methodsFor: 'visiting'!
  493. acceptDagVisitor: aVisitor
  494. ^ aVisitor visitVariableNode: self
  495. ! !
  496. Error subclass: #CompilerError
  497. slots: {}
  498. package: 'Compiler-AST'!
  499. !CompilerError commentStamp!
  500. I am the common superclass of all compiling errors.!
  501. PathDagVisitor subclass: #ParentFakingPathDagVisitor
  502. slots: {#setParentSelector}
  503. package: 'Compiler-AST'!
  504. !ParentFakingPathDagVisitor commentStamp!
  505. I am base class of `DagNode` visitor.
  506. I hold the path of ancestors up to actual node
  507. in `self path`.!
  508. !ParentFakingPathDagVisitor methodsFor: 'visiting'!
  509. visit: aNode
  510. self path ifNotEmpty: [ :p | aNode parent: p last ].
  511. ^ super visit: aNode
  512. ! !
  513. ParentFakingPathDagVisitor subclass: #NodeVisitor
  514. slots: {}
  515. package: 'Compiler-AST'!
  516. !NodeVisitor commentStamp!
  517. I am the abstract super class of all AST node visitors.!
  518. !NodeVisitor methodsFor: 'visiting'!
  519. visitAssignmentNode: aNode
  520. ^ self visitDagNode: aNode
  521. !
  522. visitBlockNode: aNode
  523. ^ self visitDagNode: aNode
  524. !
  525. visitBlockSequenceNode: aNode
  526. ^ self visitSequenceNode: aNode
  527. !
  528. visitCascadeNode: aNode
  529. ^ self visitDagNode: aNode
  530. !
  531. visitDagNode: aNode
  532. ^ self visitDagNodeVariantSimple: aNode
  533. !
  534. visitDynamicArrayNode: aNode
  535. ^ self visitDagNode: aNode
  536. !
  537. visitDynamicDictionaryNode: aNode
  538. ^ self visitDagNode: aNode
  539. !
  540. visitJSStatementNode: aNode
  541. ^ self visitDagNode: aNode
  542. !
  543. visitMethodNode: aNode
  544. ^ self visitDagNode: aNode
  545. !
  546. visitReturnNode: aNode
  547. ^ self visitDagNode: aNode
  548. !
  549. visitSendNode: aNode
  550. ^ self visitDagNode: aNode
  551. !
  552. visitSequenceNode: aNode
  553. ^ self visitDagNode: aNode
  554. !
  555. visitValueNode: aNode
  556. ^ self visitDagNode: aNode
  557. !
  558. visitVariableNode: aNode
  559. ^ self visitDagNode: aNode
  560. ! !
  561. NodeVisitor subclass: #AstPragmator
  562. slots: {#methodNode}
  563. package: 'Compiler-AST'!
  564. !AstPragmator commentStamp!
  565. I am abstract superclass for pragma-processing transformer.
  566. My subclasses should implement messages for each pragma
  567. they process. Pragma processing checks if a message is known
  568. to a class but not to its superclass. IOW, each and only those
  569. pragmas are processed which are defined as methods in the subclass.
  570. These messages can access sequence node in which
  571. a pragma occurred and its containing method node
  572. as `self sequenceNode` and `self methodNode`.
  573. See `EarlyPragmator` for an example.!
  574. !AstPragmator methodsFor: 'accessing'!
  575. methodNode
  576. ^ methodNode
  577. !
  578. methodNode: anObject
  579. methodNode := anObject
  580. ! !
  581. !AstPragmator methodsFor: 'visiting'!
  582. visitMethodNode: aNode
  583. self methodNode: aNode.
  584. self processPragmas: aNode pragmas.
  585. ^ super visitMethodNode: aNode
  586. ! !
  587. AstPragmator subclass: #AstEarlyPragmator
  588. slots: {}
  589. package: 'Compiler-AST'!
  590. !AstEarlyPragmator methodsFor: 'pragmas'!
  591. inlineJS: aString
  592. self methodNode sequenceNode dagChildren ifNotEmpty: [
  593. CompilerError signal: 'There must be no other code or code generator pragma than a lone inlineJS:' ].
  594. self methodNode sequenceNode addDagChild: (
  595. JSStatementNode new
  596. source: aString;
  597. yourself)
  598. ! !
  599. AstPragmator setTraitComposition: {TPragmator} asTraitComposition!
  600. ! !
  601. !CompiledMethod methodsFor: '*Compiler-AST'!
  602. ast
  603. self source ifEmpty: [ CompilerError signal: 'Method source is empty' ].
  604. ^ Compiler new
  605. ast: self source
  606. forClass: self origin
  607. protocol: self protocol
  608. ! !