Compiler-AST.st 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  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. ValueNode subclass: #VariableNode
  261. slots: {#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. navigationLink
  282. ^ self value
  283. ! !
  284. !VariableNode methodsFor: 'testing'!
  285. isImmutable
  286. ^ self binding isImmutable
  287. !
  288. isNavigationNode
  289. ^ true
  290. !
  291. isSuper
  292. ^ self binding isSuper
  293. ! !
  294. !VariableNode methodsFor: 'visiting'!
  295. acceptDagVisitor: aVisitor
  296. ^ aVisitor visitVariableNode: self
  297. ! !
  298. ASTNode subclass: #JSStatementNode
  299. slots: {}
  300. package: 'Compiler-AST'!
  301. !JSStatementNode commentStamp!
  302. I represent an JavaScript statement node.!
  303. !JSStatementNode methodsFor: 'visiting'!
  304. acceptDagVisitor: aVisitor
  305. ^ aVisitor visitJSStatementNode: self
  306. ! !
  307. ASTNode subclass: #MethodNode
  308. slots: {#selector. #arguments. #pragmas. #scope. #classReferences. #sendIndexes. #sequenceNode}
  309. package: 'Compiler-AST'!
  310. !MethodNode commentStamp!
  311. I represent an method node.
  312. A method node must be the root and only method node of a valid AST.!
  313. !MethodNode methodsFor: 'accessing'!
  314. arguments
  315. ^ arguments ifNil: [ #() ]
  316. !
  317. arguments: aCollection
  318. arguments := aCollection
  319. !
  320. classReferences
  321. ^ classReferences
  322. !
  323. classReferences: aCollection
  324. classReferences := aCollection
  325. !
  326. dagChild
  327. ^ self sequenceNode
  328. !
  329. messageSends
  330. ^ self sendIndexes keys
  331. !
  332. method
  333. ^ self
  334. !
  335. pragmas
  336. ^ pragmas ifNil: [ #() ]
  337. !
  338. pragmas: aCollection
  339. pragmas := aCollection
  340. !
  341. scope
  342. ^ scope
  343. !
  344. scope: aMethodScope
  345. scope := aMethodScope
  346. !
  347. selector
  348. ^ selector
  349. !
  350. selector: aString
  351. selector := aString
  352. !
  353. sendIndexes
  354. ^ sendIndexes
  355. !
  356. sendIndexes: aDictionary
  357. sendIndexes := aDictionary
  358. !
  359. sequenceNode
  360. ^ sequenceNode
  361. !
  362. sequenceNode: aSequenceNode
  363. sequenceNode := aSequenceNode
  364. ! !
  365. !MethodNode methodsFor: 'visiting'!
  366. acceptDagVisitor: aVisitor
  367. ^ aVisitor visitMethodNode: self
  368. ! !
  369. ASTNode subclass: #ReturnNode
  370. slots: {#scope. #expression}
  371. package: 'Compiler-AST'!
  372. !ReturnNode commentStamp!
  373. I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
  374. !ReturnNode methodsFor: 'accessing'!
  375. dagChild
  376. ^ self expression
  377. !
  378. expression
  379. ^ expression ifNil: [ nodes first ]
  380. !
  381. expression: anObject
  382. expression := anObject
  383. !
  384. scope
  385. ^ scope
  386. !
  387. scope: aLexicalScope
  388. scope := aLexicalScope
  389. ! !
  390. !ReturnNode methodsFor: 'testing'!
  391. isReturnNode
  392. ^ true
  393. !
  394. nonLocalReturn
  395. ^ self scope isMethodScope not
  396. ! !
  397. !ReturnNode methodsFor: 'visiting'!
  398. acceptDagVisitor: aVisitor
  399. ^ aVisitor visitReturnNode: self
  400. ! !
  401. ASTNode subclass: #SequenceNode
  402. slots: {#temps}
  403. package: 'Compiler-AST'!
  404. !SequenceNode commentStamp!
  405. I represent an sequence node. A sequence represent a set of instructions inside the same scope (the method scope or a block scope).!
  406. !SequenceNode methodsFor: 'accessing'!
  407. temps
  408. ^ temps ifNil: [ #() ]
  409. !
  410. temps: aCollection
  411. temps := aCollection
  412. ! !
  413. !SequenceNode methodsFor: 'visiting'!
  414. acceptDagVisitor: aVisitor
  415. ^ aVisitor visitSequenceNode: self
  416. ! !
  417. SequenceNode subclass: #BlockSequenceNode
  418. slots: {}
  419. package: 'Compiler-AST'!
  420. !BlockSequenceNode commentStamp!
  421. I represent an special sequence node for block scopes.!
  422. !BlockSequenceNode methodsFor: 'visiting'!
  423. acceptDagVisitor: aVisitor
  424. ^ aVisitor visitBlockSequenceNode: self
  425. ! !
  426. Object subclass: #AstPragmator
  427. slots: {#methodNode}
  428. package: 'Compiler-AST'!
  429. !AstPragmator commentStamp!
  430. I am abstract superclass for pragma-processing transformer.
  431. My subclasses should implement messages for each pragma
  432. they process. Pragma processing checks if a message is known
  433. to a class but not to its superclass. IOW, each and only those
  434. pragmas are processed which are defined as methods in the subclass.
  435. These messages can access sequence node in which
  436. a pragma occurred and its containing method node
  437. as `self sequenceNode` and `self methodNode`.
  438. See `EarlyPragmator` for an example.!
  439. !AstPragmator methodsFor: 'accessing'!
  440. methodNode
  441. ^ methodNode
  442. !
  443. methodNode: anObject
  444. methodNode := anObject
  445. ! !
  446. !AstPragmator methodsFor: 'visiting'!
  447. value: aMethodNode
  448. self methodNode: aMethodNode.
  449. self processPragmas: aMethodNode pragmas.
  450. ^ aMethodNode
  451. ! !
  452. AstPragmator subclass: #AstEarlyPragmator
  453. slots: {}
  454. package: 'Compiler-AST'!
  455. !AstEarlyPragmator methodsFor: 'pragmas'!
  456. inlineJS: aString
  457. self methodNode sequenceNode dagChildren ifNotEmpty: [
  458. CompilerError signal: 'There must be no other code or code generator pragma than a lone inlineJS:' ].
  459. self methodNode sequenceNode addDagChild: (
  460. JSStatementNode new
  461. source: aString;
  462. yourself)
  463. ! !
  464. Error subclass: #CompilerError
  465. slots: {}
  466. package: 'Compiler-AST'!
  467. !CompilerError commentStamp!
  468. I am the common superclass of all compiling errors.!
  469. PathDagVisitor subclass: #ParentFakingPathDagVisitor
  470. slots: {#setParentSelector}
  471. package: 'Compiler-AST'!
  472. !ParentFakingPathDagVisitor commentStamp!
  473. I am base class of `DagNode` visitor.
  474. I hold the path of ancestors up to actual node
  475. in `self path`.!
  476. !ParentFakingPathDagVisitor methodsFor: 'visiting'!
  477. visit: aNode
  478. self path ifNotEmpty: [ :p | aNode parent: p last ].
  479. ^ super visit: aNode
  480. ! !
  481. ParentFakingPathDagVisitor subclass: #NodeVisitor
  482. slots: {}
  483. package: 'Compiler-AST'!
  484. !NodeVisitor commentStamp!
  485. I am the abstract super class of all AST node visitors.!
  486. !NodeVisitor methodsFor: 'visiting'!
  487. visitAssignmentNode: aNode
  488. ^ self visitDagNode: aNode
  489. !
  490. visitBlockNode: aNode
  491. ^ self visitDagNode: aNode
  492. !
  493. visitBlockSequenceNode: aNode
  494. ^ self visitSequenceNode: aNode
  495. !
  496. visitCascadeNode: aNode
  497. ^ self visitDagNode: aNode
  498. !
  499. visitDagNode: aNode
  500. ^ self visitDagNodeVariantSimple: aNode
  501. !
  502. visitDynamicArrayNode: aNode
  503. ^ self visitDagNode: aNode
  504. !
  505. visitDynamicDictionaryNode: aNode
  506. ^ self visitDagNode: aNode
  507. !
  508. visitJSStatementNode: aNode
  509. ^ self visitDagNode: aNode
  510. !
  511. visitMethodNode: aNode
  512. ^ self visitDagNode: aNode
  513. !
  514. visitReturnNode: aNode
  515. ^ self visitDagNode: aNode
  516. !
  517. visitSendNode: aNode
  518. ^ self visitDagNode: aNode
  519. !
  520. visitSequenceNode: aNode
  521. ^ self visitDagNode: aNode
  522. !
  523. visitValueNode: aNode
  524. ^ self visitDagNode: aNode
  525. !
  526. visitVariableNode: aNode
  527. ^ self visitDagNode: aNode
  528. ! !
  529. JSStatementNode setTraitComposition: {TDagSink} asTraitComposition!
  530. MethodNode setTraitComposition: {TSingleDagChild} asTraitComposition!
  531. ReturnNode setTraitComposition: {TSingleDagChild} asTraitComposition!
  532. AstPragmator setTraitComposition: {TPragmator} asTraitComposition!
  533. ValueNode setTraitComposition: {TDagSink} asTraitComposition!
  534. SendNode setTraitComposition: {TDerivedDagChildren} asTraitComposition!
  535. BlockNode setTraitComposition: {TSingleDagChild} asTraitComposition!
  536. AssignmentNode setTraitComposition: {TDerivedDagChildren} asTraitComposition!
  537. ! !
  538. !CompiledMethod methodsFor: '*Compiler-AST'!
  539. ast
  540. self source ifEmpty: [ CompilerError signal: 'Method source is empty' ].
  541. ^ Compiler new
  542. ast: self source
  543. forClass: self origin
  544. protocol: self protocol
  545. ! !