Compiler-AST.st 13 KB

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