Compiler-AST.st 12 KB

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