Compiler-AST.st 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  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. isNavigationNode
  95. "Answer true if the node can be navigated to"
  96. ^ false
  97. !
  98. isReturnNode
  99. ^ false
  100. !
  101. isSendNode
  102. ^ false
  103. !
  104. isSequenceNode
  105. ^ false
  106. !
  107. isSuper
  108. ^ false
  109. !
  110. isValueNode
  111. ^ false
  112. !
  113. isVariableNode
  114. ^ false
  115. !
  116. requiresSmalltalkContext
  117. "Answer true if the receiver requires a smalltalk context.
  118. Only send nodes require a context.
  119. If no node requires a context, the method will be compiled without one.
  120. See `IRJSTranslator` and `JSStream` for context creation"
  121. ^ (self dagChildren
  122. detect: [ :each | each requiresSmalltalkContext ]
  123. ifNone: [ nil ]) notNil
  124. ! !
  125. ASTNode subclass: #AssignmentNode
  126. slots: {#left. #right}
  127. package: 'Compiler-AST'!
  128. !AssignmentNode commentStamp!
  129. I represent an assignment node.!
  130. !AssignmentNode methodsFor: 'accessing'!
  131. dagChildren
  132. ^ Array with: self left with: self right
  133. !
  134. left
  135. ^ left
  136. !
  137. left: aNode
  138. left := aNode
  139. !
  140. right
  141. ^ right
  142. !
  143. right: aNode
  144. right := aNode
  145. ! !
  146. !AssignmentNode methodsFor: 'testing'!
  147. isAssignmentNode
  148. ^ true
  149. ! !
  150. !AssignmentNode methodsFor: 'visiting'!
  151. acceptDagVisitor: aVisitor
  152. ^ aVisitor visitAssignmentNode: self
  153. ! !
  154. ASTNode subclass: #BlockNode
  155. slots: {#parameters. #scope}
  156. package: 'Compiler-AST'!
  157. !BlockNode commentStamp!
  158. I represent an block closure node.!
  159. !BlockNode methodsFor: 'accessing'!
  160. parameters
  161. ^ parameters ifNil: [ parameters := Array new ]
  162. !
  163. parameters: aCollection
  164. parameters := aCollection
  165. !
  166. scope
  167. ^ scope
  168. !
  169. scope: aLexicalScope
  170. scope := aLexicalScope
  171. ! !
  172. !BlockNode methodsFor: 'testing'!
  173. isBlockNode
  174. ^ true
  175. ! !
  176. !BlockNode methodsFor: 'visiting'!
  177. acceptDagVisitor: aVisitor
  178. ^ aVisitor visitBlockNode: self
  179. ! !
  180. ASTNode subclass: #CascadeNode
  181. slots: {#receiver}
  182. package: 'Compiler-AST'!
  183. !CascadeNode commentStamp!
  184. I represent an cascade node.!
  185. !CascadeNode methodsFor: 'accessing'!
  186. receiver
  187. ^ receiver
  188. !
  189. receiver: aNode
  190. receiver := aNode
  191. ! !
  192. !CascadeNode methodsFor: 'testing'!
  193. isCascadeNode
  194. ^ true
  195. ! !
  196. !CascadeNode methodsFor: 'visiting'!
  197. acceptDagVisitor: aVisitor
  198. ^ aVisitor visitCascadeNode: self
  199. ! !
  200. ASTNode subclass: #DynamicArrayNode
  201. slots: {}
  202. package: 'Compiler-AST'!
  203. !DynamicArrayNode commentStamp!
  204. I represent an dynamic array node.!
  205. !DynamicArrayNode methodsFor: 'visiting'!
  206. acceptDagVisitor: aVisitor
  207. ^ aVisitor visitDynamicArrayNode: self
  208. ! !
  209. ASTNode subclass: #DynamicDictionaryNode
  210. slots: {}
  211. package: 'Compiler-AST'!
  212. !DynamicDictionaryNode commentStamp!
  213. I represent an dynamic dictionary node.!
  214. !DynamicDictionaryNode methodsFor: 'visiting'!
  215. acceptDagVisitor: aVisitor
  216. ^ aVisitor visitDynamicDictionaryNode: self
  217. ! !
  218. ASTNode subclass: #JSStatementNode
  219. slots: {}
  220. package: 'Compiler-AST'!
  221. !JSStatementNode commentStamp!
  222. I represent an JavaScript statement node.!
  223. !JSStatementNode methodsFor: 'testing'!
  224. requiresSmalltalkContext
  225. ^ true
  226. ! !
  227. !JSStatementNode methodsFor: 'visiting'!
  228. acceptDagVisitor: aVisitor
  229. ^ aVisitor visitJSStatementNode: self
  230. ! !
  231. ASTNode subclass: #MethodNode
  232. slots: {#selector. #arguments. #pragmas. #scope. #classReferences. #sendIndexes}
  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. messageSends
  251. ^ self sendIndexes keys
  252. !
  253. method
  254. ^ self
  255. !
  256. pragmas
  257. ^ pragmas ifNil: [ #() ]
  258. !
  259. pragmas: aCollection
  260. pragmas := aCollection
  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 detect: [ :one | one isSequenceNode ] ifNone: [ nil ]
  282. ! !
  283. !MethodNode methodsFor: 'visiting'!
  284. acceptDagVisitor: aVisitor
  285. ^ aVisitor visitMethodNode: self
  286. ! !
  287. ASTNode subclass: #ReturnNode
  288. slots: {#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. acceptDagVisitor: aVisitor
  308. ^ aVisitor visitReturnNode: self
  309. ! !
  310. ASTNode subclass: #SendNode
  311. slots: {#selector. #arguments. #receiver. #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. !
  322. dagChildren
  323. self receiver ifNil: [ ^ self arguments copy ].
  324. ^ self arguments copyWithFirst: self receiver
  325. !
  326. index
  327. ^ index
  328. !
  329. index: anInteger
  330. index := anInteger
  331. !
  332. navigationLink
  333. ^ self selector
  334. !
  335. receiver
  336. ^ receiver
  337. !
  338. receiver: aNode
  339. receiver := aNode
  340. !
  341. selector
  342. ^ selector
  343. !
  344. selector: aString
  345. selector := aString
  346. !
  347. superSend
  348. ^ self receiver ifNil: [ false ] ifNotNil: [ :recv | recv isSuper ]
  349. ! !
  350. !SendNode methodsFor: 'testing'!
  351. isNavigationNode
  352. ^ true
  353. !
  354. isSendNode
  355. ^ true
  356. !
  357. requiresSmalltalkContext
  358. ^ true
  359. ! !
  360. !SendNode methodsFor: 'visiting'!
  361. acceptDagVisitor: aVisitor
  362. ^ aVisitor visitSendNode: self
  363. ! !
  364. ASTNode subclass: #SequenceNode
  365. slots: {#temps}
  366. package: 'Compiler-AST'!
  367. !SequenceNode commentStamp!
  368. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  369. !SequenceNode methodsFor: 'accessing'!
  370. temps
  371. ^ temps ifNil: [ #() ]
  372. !
  373. temps: aCollection
  374. temps := aCollection
  375. ! !
  376. !SequenceNode methodsFor: 'testing'!
  377. isSequenceNode
  378. ^ true
  379. ! !
  380. !SequenceNode methodsFor: 'visiting'!
  381. acceptDagVisitor: aVisitor
  382. ^ aVisitor visitSequenceNode: self
  383. ! !
  384. SequenceNode subclass: #BlockSequenceNode
  385. slots: {}
  386. package: 'Compiler-AST'!
  387. !BlockSequenceNode commentStamp!
  388. I represent an special sequence node for block scopes.!
  389. !BlockSequenceNode methodsFor: 'testing'!
  390. isBlockSequenceNode
  391. ^ true
  392. ! !
  393. !BlockSequenceNode methodsFor: 'visiting'!
  394. acceptDagVisitor: aVisitor
  395. ^ aVisitor visitBlockSequenceNode: self
  396. ! !
  397. ASTNode subclass: #ValueNode
  398. slots: {#value}
  399. package: 'Compiler-AST'!
  400. !ValueNode commentStamp!
  401. I represent a value node.!
  402. !ValueNode methodsFor: 'accessing'!
  403. value
  404. ^ value
  405. !
  406. value: anObject
  407. value := anObject
  408. ! !
  409. !ValueNode methodsFor: 'testing'!
  410. isImmutable
  411. ^ self value isImmutable
  412. !
  413. isValueNode
  414. ^ true
  415. ! !
  416. !ValueNode methodsFor: 'visiting'!
  417. acceptDagVisitor: aVisitor
  418. ^ aVisitor visitValueNode: self
  419. ! !
  420. ValueNode subclass: #VariableNode
  421. slots: {#assigned. #binding}
  422. package: 'Compiler-AST'!
  423. !VariableNode commentStamp!
  424. I represent an variable node.!
  425. !VariableNode methodsFor: 'accessing'!
  426. alias
  427. ^ self binding alias
  428. !
  429. assigned
  430. ^ assigned ifNil: [ false ]
  431. !
  432. assigned: aBoolean
  433. assigned := aBoolean
  434. !
  435. binding
  436. ^ binding
  437. !
  438. binding: aScopeVar
  439. binding := aScopeVar
  440. !
  441. navigationLink
  442. ^ self value
  443. ! !
  444. !VariableNode methodsFor: 'testing'!
  445. isImmutable
  446. ^ self binding isImmutable
  447. !
  448. isNavigationNode
  449. ^ true
  450. !
  451. isSuper
  452. ^ self binding isSuper
  453. !
  454. isVariableNode
  455. ^ true
  456. ! !
  457. !VariableNode methodsFor: 'visiting'!
  458. acceptDagVisitor: aVisitor
  459. ^ aVisitor visitVariableNode: self
  460. ! !
  461. Object subclass: #AstPragmator
  462. slots: {#methodNode}
  463. package: 'Compiler-AST'!
  464. !AstPragmator commentStamp!
  465. I am abstract superclass for pragma-processing transformer.
  466. My subclasses should implement messages for each pragma
  467. they process. Pragma processing checks if a message is known
  468. to a class but not to its superclass. IOW, each and only those
  469. pragmas are processed which are defined as methods in the subclass.
  470. These messages can access sequence node in which
  471. a pragma occurred and its containing method node
  472. as `self sequenceNode` and `self methodNode`.
  473. See `EarlyPragmator` for an example.!
  474. !AstPragmator methodsFor: 'accessing'!
  475. methodNode
  476. ^ methodNode
  477. !
  478. methodNode: anObject
  479. methodNode := anObject
  480. ! !
  481. !AstPragmator methodsFor: 'visiting'!
  482. value: aMethodNode
  483. self methodNode: aMethodNode.
  484. self processPragmas: aMethodNode pragmas.
  485. ^ aMethodNode
  486. ! !
  487. AstPragmator subclass: #AstEarlyPragmator
  488. slots: {}
  489. package: 'Compiler-AST'!
  490. !AstEarlyPragmator methodsFor: 'pragmas'!
  491. inlineJS: aString
  492. self methodNode sequenceNode dagChildren ifNotEmpty: [
  493. CompilerError signal: 'There must be no other code or code generator pragma than a lone inlineJS:' ].
  494. self methodNode sequenceNode addDagChild: (
  495. JSStatementNode new
  496. source: aString;
  497. yourself)
  498. ! !
  499. Error subclass: #CompilerError
  500. slots: {}
  501. package: 'Compiler-AST'!
  502. !CompilerError commentStamp!
  503. I am the common superclass of all compiling errors.!
  504. PathDagVisitor subclass: #ParentFakingPathDagVisitor
  505. slots: {#setParentSelector}
  506. package: 'Compiler-AST'!
  507. !ParentFakingPathDagVisitor commentStamp!
  508. I am base class of `DagNode` visitor.
  509. I hold the path of ancestors up to actual node
  510. in `self path`.!
  511. !ParentFakingPathDagVisitor methodsFor: 'visiting'!
  512. visit: aNode
  513. self path ifNotEmpty: [ :p | aNode parent: p last ].
  514. ^ super visit: aNode
  515. ! !
  516. ParentFakingPathDagVisitor subclass: #NodeVisitor
  517. slots: {}
  518. package: 'Compiler-AST'!
  519. !NodeVisitor commentStamp!
  520. I am the abstract super class of all AST node visitors.!
  521. !NodeVisitor methodsFor: 'visiting'!
  522. visitAssignmentNode: aNode
  523. ^ self visitDagNode: aNode
  524. !
  525. visitBlockNode: aNode
  526. ^ self visitDagNode: aNode
  527. !
  528. visitBlockSequenceNode: aNode
  529. ^ self visitSequenceNode: aNode
  530. !
  531. visitCascadeNode: aNode
  532. ^ self visitDagNode: aNode
  533. !
  534. visitDagNode: aNode
  535. ^ self visitDagNodeVariantSimple: aNode
  536. !
  537. visitDynamicArrayNode: aNode
  538. ^ self visitDagNode: aNode
  539. !
  540. visitDynamicDictionaryNode: aNode
  541. ^ self visitDagNode: aNode
  542. !
  543. visitJSStatementNode: aNode
  544. ^ self visitDagNode: aNode
  545. !
  546. visitMethodNode: aNode
  547. ^ self visitDagNode: aNode
  548. !
  549. visitReturnNode: aNode
  550. ^ self visitDagNode: aNode
  551. !
  552. visitSendNode: aNode
  553. ^ self visitDagNode: aNode
  554. !
  555. visitSequenceNode: aNode
  556. ^ self visitDagNode: aNode
  557. !
  558. visitValueNode: aNode
  559. ^ self visitDagNode: aNode
  560. !
  561. visitVariableNode: aNode
  562. ^ self visitDagNode: aNode
  563. ! !
  564. AstPragmator setTraitComposition: {TPragmator} asTraitComposition!
  565. ! !
  566. !CompiledMethod methodsFor: '*Compiler-AST'!
  567. ast
  568. self source ifEmpty: [ CompilerError signal: 'Method source is empty' ].
  569. ^ Compiler new
  570. ast: self source
  571. forClass: self origin
  572. protocol: self protocol
  573. ! !