Compiler-AST.st 12 KB

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