Compiler-AST.st 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  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. navigationNodeAt: aPoint ifAbsent: aBlock
  14. "Answer the navigation node in the receiver's tree at aPoint
  15. or nil if no navigation node was found.
  16. See `node >> isNaviationNode`"
  17. | children |
  18. children := self allDagChildren select: [ :each |
  19. each isNavigationNode and: [ each inPosition: aPoint ] ].
  20. children ifEmpty: [ ^ aBlock value ].
  21. ^ (children asArray sort: [ :a :b |
  22. (a positionStart dist: aPoint) <=
  23. (b positionStart dist: aPoint) ]) first
  24. !
  25. parent
  26. ^ parent
  27. !
  28. parent: aNode
  29. parent := aNode
  30. !
  31. position
  32. "answer the line and column of the receiver in the source code"
  33. ^ position ifNil: [
  34. self parent ifNotNil: [ :node | node position ] ]
  35. !
  36. position: aPosition
  37. position := aPosition
  38. !
  39. positionEnd
  40. ^ self positionStart + ((self source lines size - 1) @ (self source lines last size - 1))
  41. !
  42. positionStart
  43. ^ self position
  44. !
  45. shouldBeAliased
  46. ^ shouldBeAliased ifNil: [ false ]
  47. !
  48. shouldBeAliased: aBoolean
  49. shouldBeAliased := aBoolean
  50. !
  51. size
  52. ^ self source size
  53. !
  54. source
  55. ^ source ifNil: [ '' ]
  56. !
  57. source: aString
  58. source := aString
  59. ! !
  60. !ASTNode methodsFor: 'building'!
  61. withTail: aCollection
  62. ^ aCollection inject: self into: [
  63. :receiver :send | SendNode new
  64. position: send position;
  65. source: send source;
  66. receiver: receiver;
  67. selector: send selector;
  68. arguments: send arguments;
  69. yourself ]
  70. ! !
  71. !ASTNode methodsFor: 'testing'!
  72. inPosition: aPoint
  73. ^ (self positionStart <= aPoint and: [
  74. self positionEnd >= aPoint ])
  75. !
  76. isImmutable
  77. ^ false
  78. !
  79. isNavigationNode
  80. "Answer true if the node can be navigated to"
  81. ^ false
  82. !
  83. isReturnNode
  84. ^ false
  85. !
  86. isSuper
  87. ^ false
  88. ! !
  89. ASTNode subclass: #AssignmentNode
  90. slots: {#left. #right}
  91. package: 'Compiler-AST'!
  92. !AssignmentNode commentStamp!
  93. I represent an assignment node.!
  94. !AssignmentNode methodsFor: 'accessing'!
  95. dagChildren
  96. ^ { self left. self right }
  97. !
  98. left
  99. ^ left
  100. !
  101. left: aNode
  102. left := aNode
  103. !
  104. right
  105. ^ right
  106. !
  107. right: aNode
  108. right := aNode
  109. ! !
  110. !AssignmentNode methodsFor: 'visiting'!
  111. acceptDagVisitor: aVisitor
  112. ^ aVisitor visitAssignmentNode: self
  113. ! !
  114. ASTNode subclass: #BlockNode
  115. slots: {#parameters. #scope. #sequenceNode}
  116. package: 'Compiler-AST'!
  117. !BlockNode commentStamp!
  118. I represent an block closure node.!
  119. !BlockNode methodsFor: 'accessing'!
  120. dagChild
  121. ^ self sequenceNode
  122. !
  123. parameters
  124. ^ parameters ifNil: [ parameters := Array new ]
  125. !
  126. parameters: aCollection
  127. parameters := aCollection
  128. !
  129. scope
  130. ^ scope
  131. !
  132. scope: aLexicalScope
  133. scope := aLexicalScope
  134. !
  135. sequenceNode
  136. ^ sequenceNode
  137. !
  138. sequenceNode: anObject
  139. sequenceNode := anObject
  140. ! !
  141. !BlockNode methodsFor: 'visiting'!
  142. acceptDagVisitor: aVisitor
  143. ^ aVisitor visitBlockNode: self
  144. ! !
  145. ASTNode subclass: #CascadeNode
  146. slots: {#receiver}
  147. package: 'Compiler-AST'!
  148. !CascadeNode commentStamp!
  149. I represent an cascade node.!
  150. !CascadeNode methodsFor: 'accessing'!
  151. receiver
  152. ^ receiver
  153. !
  154. receiver: aNode
  155. receiver := aNode
  156. ! !
  157. !CascadeNode methodsFor: 'visiting'!
  158. acceptDagVisitor: aVisitor
  159. ^ aVisitor visitCascadeNode: self
  160. ! !
  161. ASTNode subclass: #DynamicArrayNode
  162. slots: {}
  163. package: 'Compiler-AST'!
  164. !DynamicArrayNode commentStamp!
  165. I represent an dynamic array node.!
  166. !DynamicArrayNode methodsFor: 'visiting'!
  167. acceptDagVisitor: aVisitor
  168. ^ aVisitor visitDynamicArrayNode: self
  169. ! !
  170. ASTNode subclass: #DynamicDictionaryNode
  171. slots: {}
  172. package: 'Compiler-AST'!
  173. !DynamicDictionaryNode commentStamp!
  174. I represent an dynamic dictionary node.!
  175. !DynamicDictionaryNode methodsFor: 'visiting'!
  176. acceptDagVisitor: aVisitor
  177. ^ aVisitor visitDynamicDictionaryNode: self
  178. ! !
  179. ASTNode subclass: #JSStatementNode
  180. slots: {}
  181. package: 'Compiler-AST'!
  182. !JSStatementNode commentStamp!
  183. I represent an JavaScript statement node.!
  184. !JSStatementNode methodsFor: 'visiting'!
  185. acceptDagVisitor: aVisitor
  186. ^ aVisitor visitJSStatementNode: self
  187. ! !
  188. ASTNode subclass: #MethodNode
  189. slots: {#selector. #arguments. #pragmas. #scope. #classReferences. #sendIndexes. #sequenceNode}
  190. package: 'Compiler-AST'!
  191. !MethodNode commentStamp!
  192. I represent an method node.
  193. A method node must be the root and only method node of a valid AST.!
  194. !MethodNode methodsFor: 'accessing'!
  195. arguments
  196. ^ arguments ifNil: [ #() ]
  197. !
  198. arguments: aCollection
  199. arguments := aCollection
  200. !
  201. classReferences
  202. ^ classReferences
  203. !
  204. classReferences: aCollection
  205. classReferences := aCollection
  206. !
  207. dagChild
  208. ^ self sequenceNode
  209. !
  210. messageSends
  211. ^ self sendIndexes keys
  212. !
  213. method
  214. ^ self
  215. !
  216. pragmas
  217. ^ pragmas ifNil: [ #() ]
  218. !
  219. pragmas: aCollection
  220. pragmas := aCollection
  221. !
  222. scope
  223. ^ scope
  224. !
  225. scope: aMethodScope
  226. scope := aMethodScope
  227. !
  228. selector
  229. ^ selector
  230. !
  231. selector: aString
  232. selector := aString
  233. !
  234. sendIndexes
  235. ^ sendIndexes
  236. !
  237. sendIndexes: aDictionary
  238. sendIndexes := aDictionary
  239. !
  240. sequenceNode
  241. ^ sequenceNode
  242. !
  243. sequenceNode: aSequenceNode
  244. sequenceNode := aSequenceNode
  245. ! !
  246. !MethodNode methodsFor: 'visiting'!
  247. acceptDagVisitor: aVisitor
  248. ^ aVisitor visitMethodNode: self
  249. ! !
  250. ASTNode subclass: #ReturnNode
  251. slots: {#scope. #expression}
  252. package: 'Compiler-AST'!
  253. !ReturnNode commentStamp!
  254. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  255. !ReturnNode methodsFor: 'accessing'!
  256. dagChild
  257. ^ self expression
  258. !
  259. expression
  260. ^ expression ifNil: [ nodes first ]
  261. !
  262. expression: anObject
  263. expression := anObject
  264. !
  265. scope
  266. ^ scope
  267. !
  268. scope: aLexicalScope
  269. scope := aLexicalScope
  270. ! !
  271. !ReturnNode methodsFor: 'testing'!
  272. isReturnNode
  273. ^ true
  274. !
  275. nonLocalReturn
  276. ^ self scope isMethodScope not
  277. ! !
  278. !ReturnNode methodsFor: 'visiting'!
  279. acceptDagVisitor: aVisitor
  280. ^ aVisitor visitReturnNode: self
  281. ! !
  282. ASTNode subclass: #SendNode
  283. slots: {#selector. #arguments. #receiver. #index. #isSideEffect}
  284. package: 'Compiler-AST'!
  285. !SendNode commentStamp!
  286. I represent an message send node.!
  287. !SendNode methodsFor: 'accessing'!
  288. arguments
  289. ^ arguments ifNil: [ arguments := #() ]
  290. !
  291. arguments: aCollection
  292. arguments := aCollection
  293. !
  294. beSideEffect
  295. isSideEffect := true
  296. !
  297. dagChildren
  298. self receiver ifNil: [ ^ self arguments copy ].
  299. ^ self arguments copyWithFirst: self receiver
  300. !
  301. index
  302. ^ index
  303. !
  304. index: anInteger
  305. index := anInteger
  306. !
  307. isSideEffect
  308. ^ isSideEffect ifNil: [ false ]
  309. !
  310. navigationLink
  311. ^ self selector
  312. !
  313. receiver
  314. ^ receiver
  315. !
  316. receiver: aNode
  317. receiver := aNode
  318. !
  319. selector
  320. ^ selector
  321. !
  322. selector: aString
  323. selector := aString
  324. !
  325. superSend
  326. ^ self receiver ifNil: [ false ] ifNotNil: [ :recv | recv isSuper ]
  327. ! !
  328. !SendNode methodsFor: 'testing'!
  329. isNavigationNode
  330. ^ true
  331. ! !
  332. !SendNode methodsFor: 'visiting'!
  333. acceptDagVisitor: aVisitor
  334. ^ aVisitor visitSendNode: self
  335. ! !
  336. ASTNode subclass: #SequenceNode
  337. slots: {#temps}
  338. package: 'Compiler-AST'!
  339. !SequenceNode commentStamp!
  340. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  341. !SequenceNode methodsFor: 'accessing'!
  342. temps
  343. ^ temps ifNil: [ #() ]
  344. !
  345. temps: aCollection
  346. temps := aCollection
  347. ! !
  348. !SequenceNode methodsFor: 'visiting'!
  349. acceptDagVisitor: aVisitor
  350. ^ aVisitor visitSequenceNode: self
  351. ! !
  352. SequenceNode subclass: #BlockSequenceNode
  353. slots: {}
  354. package: 'Compiler-AST'!
  355. !BlockSequenceNode commentStamp!
  356. I represent an special sequence node for block scopes.!
  357. !BlockSequenceNode methodsFor: 'visiting'!
  358. acceptDagVisitor: aVisitor
  359. ^ aVisitor visitBlockSequenceNode: self
  360. ! !
  361. ASTNode subclass: #ValueNode
  362. slots: {#value}
  363. package: 'Compiler-AST'!
  364. !ValueNode commentStamp!
  365. I represent a value node.!
  366. !ValueNode methodsFor: 'accessing'!
  367. value
  368. ^ value
  369. !
  370. value: anObject
  371. value := anObject
  372. ! !
  373. !ValueNode methodsFor: 'testing'!
  374. isImmutable
  375. ^ self value isImmutable
  376. ! !
  377. !ValueNode methodsFor: 'visiting'!
  378. acceptDagVisitor: aVisitor
  379. ^ aVisitor visitValueNode: self
  380. ! !
  381. ValueNode subclass: #VariableNode
  382. slots: {#assigned. #binding}
  383. package: 'Compiler-AST'!
  384. !VariableNode commentStamp!
  385. I represent an variable node.!
  386. !VariableNode methodsFor: 'accessing'!
  387. alias
  388. ^ self binding alias
  389. !
  390. assigned
  391. ^ assigned ifNil: [ false ]
  392. !
  393. assigned: aBoolean
  394. assigned := aBoolean
  395. !
  396. binding
  397. ^ binding
  398. !
  399. binding: aScopeVar
  400. binding := aScopeVar
  401. !
  402. navigationLink
  403. ^ self value
  404. ! !
  405. !VariableNode methodsFor: 'testing'!
  406. isImmutable
  407. ^ self binding isImmutable
  408. !
  409. isNavigationNode
  410. ^ true
  411. !
  412. isSuper
  413. ^ self binding isSuper
  414. ! !
  415. !VariableNode methodsFor: 'visiting'!
  416. acceptDagVisitor: aVisitor
  417. ^ aVisitor visitVariableNode: self
  418. ! !
  419. Object subclass: #AstPragmator
  420. slots: {#methodNode}
  421. package: 'Compiler-AST'!
  422. !AstPragmator commentStamp!
  423. I am abstract superclass for pragma-processing transformer.
  424. My subclasses should implement messages for each pragma
  425. they process. Pragma processing checks if a message is known
  426. to a class but not to its superclass. IOW, each and only those
  427. pragmas are processed which are defined as methods in the subclass.
  428. These messages can access sequence node in which
  429. a pragma occurred and its containing method node
  430. as `self sequenceNode` and `self methodNode`.
  431. See `EarlyPragmator` for an example.!
  432. !AstPragmator methodsFor: 'accessing'!
  433. methodNode
  434. ^ methodNode
  435. !
  436. methodNode: anObject
  437. methodNode := anObject
  438. ! !
  439. !AstPragmator methodsFor: 'visiting'!
  440. value: aMethodNode
  441. self methodNode: aMethodNode.
  442. self processPragmas: aMethodNode pragmas.
  443. ^ aMethodNode
  444. ! !
  445. AstPragmator subclass: #AstEarlyPragmator
  446. slots: {}
  447. package: 'Compiler-AST'!
  448. !AstEarlyPragmator methodsFor: 'pragmas'!
  449. inlineJS: aString
  450. self methodNode sequenceNode dagChildren ifNotEmpty: [
  451. CompilerError signal: 'There must be no other code or code generator pragma than a lone inlineJS:' ].
  452. self methodNode sequenceNode addDagChild: (
  453. JSStatementNode new
  454. source: aString;
  455. yourself)
  456. ! !
  457. Error subclass: #CompilerError
  458. slots: {}
  459. package: 'Compiler-AST'!
  460. !CompilerError commentStamp!
  461. I am the common superclass of all compiling errors.!
  462. PathDagVisitor subclass: #ParentFakingPathDagVisitor
  463. slots: {#setParentSelector}
  464. package: 'Compiler-AST'!
  465. !ParentFakingPathDagVisitor commentStamp!
  466. I am base class of `DagNode` visitor.
  467. I hold the path of ancestors up to actual node
  468. in `self path`.!
  469. !ParentFakingPathDagVisitor methodsFor: 'visiting'!
  470. visit: aNode
  471. self path ifNotEmpty: [ :p | aNode parent: p last ].
  472. ^ super visit: aNode
  473. ! !
  474. ParentFakingPathDagVisitor subclass: #NodeVisitor
  475. slots: {}
  476. package: 'Compiler-AST'!
  477. !NodeVisitor commentStamp!
  478. I am the abstract super class of all AST node visitors.!
  479. !NodeVisitor methodsFor: 'visiting'!
  480. visitAssignmentNode: aNode
  481. ^ self visitDagNode: aNode
  482. !
  483. visitBlockNode: aNode
  484. ^ self visitDagNode: aNode
  485. !
  486. visitBlockSequenceNode: aNode
  487. ^ self visitSequenceNode: aNode
  488. !
  489. visitCascadeNode: aNode
  490. ^ self visitDagNode: aNode
  491. !
  492. visitDagNode: aNode
  493. ^ self visitDagNodeVariantSimple: aNode
  494. !
  495. visitDynamicArrayNode: aNode
  496. ^ self visitDagNode: aNode
  497. !
  498. visitDynamicDictionaryNode: aNode
  499. ^ self visitDagNode: aNode
  500. !
  501. visitJSStatementNode: aNode
  502. ^ self visitDagNode: aNode
  503. !
  504. visitMethodNode: aNode
  505. ^ self visitDagNode: aNode
  506. !
  507. visitReturnNode: aNode
  508. ^ self visitDagNode: aNode
  509. !
  510. visitSendNode: aNode
  511. ^ self visitDagNode: aNode
  512. !
  513. visitSequenceNode: aNode
  514. ^ self visitDagNode: aNode
  515. !
  516. visitValueNode: aNode
  517. ^ self visitDagNode: aNode
  518. !
  519. visitVariableNode: aNode
  520. ^ self visitDagNode: aNode
  521. ! !
  522. AssignmentNode setTraitComposition: {TDerivedDagChildren} asTraitComposition!
  523. BlockNode setTraitComposition: {TSingleDagChild} asTraitComposition!
  524. JSStatementNode setTraitComposition: {TDagSink} asTraitComposition!
  525. MethodNode setTraitComposition: {TSingleDagChild} asTraitComposition!
  526. ReturnNode setTraitComposition: {TSingleDagChild} asTraitComposition!
  527. SendNode setTraitComposition: {TDerivedDagChildren} asTraitComposition!
  528. ValueNode setTraitComposition: {TDagSink} asTraitComposition!
  529. AstPragmator setTraitComposition: {TPragmator} asTraitComposition!
  530. ! !
  531. !CompiledMethod methodsFor: '*Compiler-AST'!
  532. ast
  533. self source ifEmpty: [ CompilerError signal: 'Method source is empty' ].
  534. ^ Compiler new
  535. ast: self source
  536. forClass: self origin
  537. protocol: self protocol
  538. ! !