Compiler-AST.st 13 KB

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