Compiler-AST.st 13 KB

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