Compiler-Interpreter.st 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234
  1. Smalltalk current createPackage: 'Compiler-Interpreter'!
  2. BlockClosure subclass: #AIBlockClosure
  3. instanceVariableNames: 'node outerContext'
  4. package: 'Compiler-Interpreter'!
  5. !AIBlockClosure commentStamp!
  6. I am a special `BlockClosure` subclass used by an interpreter to interpret a block node.
  7. While I am polymorphic with `BlockClosure`, some methods such as `#new` will raise interpretation errors. Unlike a `BlockClosure`, my instance are not JavaScript functions.
  8. Evaluating an instance will result in interpreting the `node` instance variable (instance of `BlockNode`).!
  9. !AIBlockClosure methodsFor: 'accessing'!
  10. compiledSource
  11. "Unlike blocks, the receiver doesn't represent a JS function"
  12. ^ '[ AST Block closure ]'
  13. !
  14. numArgs
  15. ^ node temps size
  16. ! !
  17. !AIBlockClosure methodsFor: 'converting'!
  18. currySelf
  19. self interpreterError
  20. ! !
  21. !AIBlockClosure methodsFor: 'error handling'!
  22. interpreterError
  23. AIInterpreterError signal: 'Method cannot be interpreted by the interpreter.'
  24. ! !
  25. !AIBlockClosure methodsFor: 'evaluating'!
  26. applyTo: anObject arguments: aCollection
  27. self interpreterError
  28. !
  29. value
  30. ^ self valueWithPossibleArguments: #()
  31. !
  32. value: anArgument
  33. ^ self valueWithPossibleArguments: {anArgument}
  34. !
  35. value: firstArgument value: secondArgument
  36. ^ self valueWithPossibleArguments: {firstArgument . secondArgument}
  37. !
  38. value: firstArgument value: secondArgument value: thirdArgument
  39. ^ self valueWithPossibleArguments: {firstArgument . secondArgument . thirdArgument}
  40. !
  41. valueWithPossibleArguments: aCollection
  42. | context sequenceNode |
  43. context := outerContext newBlockContext.
  44. "Interpret a copy of the sequence node to avoid creating a new AIBlockClosure"
  45. sequenceNode := node nodes first copy
  46. parent: nil;
  47. yourself.
  48. "Populate the arguments into the context locals"
  49. node parameters withIndexDo: [ :each :index |
  50. context localAt: each put: (aCollection at: index ifAbsent: [ nil ]) ].
  51. "Interpret the first node of the BlockSequenceNode"
  52. context interpreter
  53. node: sequenceNode nextChild;
  54. proceed.
  55. outerContext interpreter
  56. returnValue: context interpreter returnValue.
  57. console log: context interpreter returnValue.
  58. ^ context interpreter pop
  59. ! !
  60. !AIBlockClosure methodsFor: 'initialization'!
  61. initializeWithContext: aContext node: aNode
  62. node := aNode.
  63. outerContext := aContext
  64. ! !
  65. !AIBlockClosure class methodsFor: 'instance creation'!
  66. forContext: aContext node: aNode
  67. ^ self new
  68. initializeWithContext: aContext node: aNode;
  69. yourself
  70. ! !
  71. Object subclass: #AIContext
  72. instanceVariableNames: 'outerContext innerContext pc locals method index ast interpreter'
  73. package: 'Compiler-Interpreter'!
  74. !AIContext commentStamp!
  75. I am like a `MethodContext`, used by the `ASTInterpreter`.
  76. Unlike a `MethodContext`, my instances are not read-only.
  77. When debugging, my instances are created by copying the current `MethodContext` (thisContext)!
  78. !AIContext methodsFor: 'accessing'!
  79. index
  80. ^ index ifNil: [ 0 ]
  81. !
  82. index: anInteger
  83. index := anInteger
  84. !
  85. innerContext
  86. ^ innerContext
  87. !
  88. innerContext: anAIContext
  89. innerContext := anAIContext
  90. !
  91. localAt: aString
  92. "Lookup the local value up to the method context"
  93. ^ self locals at: aString ifAbsent: [
  94. self isBlockContext
  95. ifTrue: [ nil ]
  96. ifFalse: [ self outerContext localAt: aString ] ]
  97. !
  98. localAt: aString put: anObject
  99. self locals at: aString put: anObject
  100. !
  101. locals
  102. locals ifNil: [ self initializeLocals ].
  103. ^ locals
  104. !
  105. method
  106. ^ method
  107. !
  108. method: aCompiledMethod
  109. method := aCompiledMethod
  110. !
  111. methodContext
  112. self isBlockContext ifFalse: [ ^ self ].
  113. ^ self outerContext ifNotNil: [ :outer |
  114. outer methodContext ]
  115. !
  116. outerContext
  117. ^ outerContext
  118. !
  119. outerContext: anAIContext
  120. outerContext := anAIContext.
  121. outerContext innerContext: self
  122. !
  123. selector
  124. ^ self method ifNotNil: [
  125. self method selector ]
  126. ! !
  127. !AIContext methodsFor: 'converting'!
  128. asString
  129. ^self isBlockContext
  130. ifTrue: [ 'a block (in ', self methodContext asString, ')' ]
  131. ifFalse: [ self receiver class name, ' >> ', self selector ]
  132. ! !
  133. !AIContext methodsFor: 'factory'!
  134. newBlockContext
  135. ^ self class new
  136. outerContext: self;
  137. yourself
  138. ! !
  139. !AIContext methodsFor: 'initialization'!
  140. initializeAST
  141. ast := self method ast.
  142. (SemanticAnalyzer on: self method methodClass)
  143. visit: ast
  144. !
  145. initializeFromMethodContext: aMethodContext
  146. self
  147. pc: aMethodContext pc;
  148. index: aMethodContext index;
  149. receiver: aMethodContext receiver;
  150. method: aMethodContext method.
  151. aMethodContext outerContext ifNotNil: [ :outer |
  152. "If the method context is nil, the block was defined in JS, so ignore it"
  153. outer methodContext ifNotNil: [
  154. self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
  155. aMethodContext locals keysAndValuesDo: [ :key :value |
  156. self locals at: key put: value ] ]
  157. !
  158. initializeInterpreter
  159. interpreter := Interpreter new
  160. context: self;
  161. yourself.
  162. ast ifNotNil: [ interpreter node: self retrieveNode ].
  163. (self innerContext notNil and: [
  164. self innerContext isBlockContext not ]) ifTrue: [
  165. self setupInterpreter: interpreter ]
  166. !
  167. initializeLocals
  168. locals := Dictionary new.
  169. locals at: 'thisContext' put: self.
  170. ! !
  171. !AIContext methodsFor: 'interpreting'!
  172. arguments
  173. ^ self ast arguments collect: [ :each |
  174. self localAt: each ]
  175. !
  176. ast
  177. self isBlockContext ifTrue: [ ^ self outerContext ast ].
  178. ast ifNil: [ self initializeAST ].
  179. ^ ast
  180. !
  181. interpreter
  182. interpreter ifNil: [ self initializeInterpreter ].
  183. ^ interpreter
  184. !
  185. interpreter: anInterpreter
  186. interpreter := anInterpreter
  187. !
  188. pc
  189. ^ pc ifNil: [ pc := 0 ]
  190. !
  191. pc: anInteger
  192. pc := anInteger
  193. !
  194. receiver
  195. ^ self localAt: 'self'
  196. !
  197. receiver: anObject
  198. self localAt: 'self' put: anObject
  199. !
  200. retrieveNode
  201. ^ ASTPCNodeVisitor new
  202. context: self;
  203. visit: self ast;
  204. currentNode
  205. !
  206. setupInterpreter: anInterpreter
  207. "Push the send args and receiver to the interpreter stack"
  208. self innerContext arguments reversed do: [ :each |
  209. anInterpreter push: each ].
  210. anInterpreter push: (self innerContext receiver)
  211. ! !
  212. !AIContext methodsFor: 'testing'!
  213. isBlockContext
  214. "Block context do not have selectors."
  215. ^ self selector isNil
  216. ! !
  217. !AIContext class methodsFor: 'instance creation'!
  218. fromMethodContext: aMethodContext
  219. ^ self new
  220. initializeFromMethodContext: aMethodContext;
  221. yourself
  222. ! !
  223. Error subclass: #AIInterpreterError
  224. instanceVariableNames: ''
  225. package: 'Compiler-Interpreter'!
  226. !AIInterpreterError commentStamp!
  227. I get signaled when an AST interpreter is unable to interpret a node.!
  228. Object subclass: #ASTDebugger
  229. instanceVariableNames: 'interpreter context'
  230. package: 'Compiler-Interpreter'!
  231. !ASTDebugger commentStamp!
  232. I am a stepping debugger interface for Amber code.
  233. I internally use an instance of `ASTSteppingInterpreter` to actually step through node and interpret them.
  234. My instances are created from a `MethodContext` with `ASTDebugger class >> context:`.
  235. They hold an `AIContext` instance internally, recursive copy of the `MethodContext`.
  236. ## API
  237. Use the methods of the `'stepping'` protocol to do stepping.!
  238. !ASTDebugger methodsFor: 'accessing'!
  239. context
  240. ^ context
  241. !
  242. context: aContext
  243. context := aContext
  244. !
  245. interpreter
  246. ^ interpreter ifNil: [ interpreter := self defaultInterpreterClass new ]
  247. !
  248. interpreter: anInterpreter
  249. interpreter := anInterpreter
  250. !
  251. method
  252. ^ self context method
  253. !
  254. nextNode
  255. ^ self interpreter nextNode
  256. ! !
  257. !ASTDebugger methodsFor: 'defaults'!
  258. defaultInterpreterClass
  259. ^ ASTSteppingInterpreter
  260. ! !
  261. !ASTDebugger methodsFor: 'initialization'!
  262. buildAST
  263. "Build the AST tree from the method source code.
  264. The AST is annotated with a SemanticAnalyzer,
  265. to know the semantics and bindings of each node needed for later debugging"
  266. | ast |
  267. ast := Smalltalk current parse: self method source.
  268. (SemanticAnalyzer on: self context receiver class)
  269. visit: ast.
  270. ^ ast
  271. !
  272. initializeInterpreter
  273. | ast next |
  274. ast := self buildAST.
  275. next := ASTPCNodeVisitor new
  276. context: self context;
  277. visit: ast;
  278. currentNode.
  279. self interpreter interpret: next
  280. !
  281. initializeWithContext: aContext
  282. "TODO: do we need to handle block contexts?"
  283. self context: aContext.
  284. self initializeInterpreter
  285. ! !
  286. !ASTDebugger methodsFor: 'stepping'!
  287. proceed
  288. self shouldBeImplemented
  289. !
  290. restart
  291. self shouldBeImplemented
  292. !
  293. step
  294. "The ASTSteppingInterpreter stops at each node interpretation.
  295. One step will interpret nodes until:
  296. - we get at the end
  297. - the next node is a stepping node (send, assignment, etc.)"
  298. [ (self interpreter nextNode notNil and: [ self interpreter nextNode stopOnStepping ])
  299. or: [ self interpreter atEnd not ] ]
  300. whileFalse: [
  301. self interpreter step.
  302. self step ]
  303. !
  304. stepInto
  305. self shouldBeImplemented
  306. !
  307. stepOver
  308. self step
  309. ! !
  310. !ASTDebugger methodsFor: 'testing'!
  311. atEnd
  312. ^ self interpreter atEnd
  313. ! !
  314. !ASTDebugger class methodsFor: 'instance creation'!
  315. context: aContext
  316. ^ self new
  317. initializeWithContext: aContext;
  318. yourself
  319. ! !
  320. Object subclass: #ASTInterpreter
  321. instanceVariableNames: 'currentNode nextNode context shouldReturn result'
  322. package: 'Compiler-Interpreter'!
  323. !ASTInterpreter commentStamp!
  324. I am like a `NodeVisitor`, interpreting nodes one after each other.
  325. I am built using Continuation Passing Style for stepping purposes.
  326. ## Usage example:
  327. | ast interpreter |
  328. ast := Smalltalk current parse: 'foo 1+2+4'.
  329. (SemanticAnalyzer on: Object) visit: ast.
  330. ASTInterpreter new
  331. interpret: ast nodes first;
  332. result "Answers 7"!
  333. !ASTInterpreter methodsFor: 'accessing'!
  334. context
  335. ^ context ifNil: [ context := AIContext new ]
  336. !
  337. context: anAIContext
  338. context := anAIContext
  339. !
  340. currentNode
  341. ^ currentNode
  342. !
  343. nextNode
  344. ^ nextNode ifNil: [ self currentNode ]
  345. !
  346. nextNode: aNode
  347. nextNode := aNode
  348. !
  349. result
  350. ^ result
  351. ! !
  352. !ASTInterpreter methodsFor: 'initialization'!
  353. initialize
  354. super initialize.
  355. shouldReturn := false
  356. ! !
  357. !ASTInterpreter methodsFor: 'interpreting'!
  358. interpret: aNode
  359. shouldReturn := false.
  360. self interpret: aNode continue: [ :value |
  361. result := value ]
  362. !
  363. interpret: aNode continue: aBlock
  364. shouldReturn ifTrue: [ ^ self ].
  365. aNode isNode
  366. ifTrue: [
  367. currentNode := aNode.
  368. self interpretNode: aNode continue: [ :value |
  369. self continue: aBlock value: value ] ]
  370. ifFalse: [ self continue: aBlock value: aNode ]
  371. !
  372. interpretAssignmentNode: aNode continue: aBlock
  373. self interpret: aNode right continue: [ :value |
  374. self
  375. continue: aBlock
  376. value: (self assign: aNode left to: value) ]
  377. !
  378. interpretBlockNode: aNode continue: aBlock
  379. self
  380. continue: aBlock
  381. value: [
  382. self withBlockContext: [
  383. self interpret: aNode nodes first; result ] ]
  384. !
  385. interpretBlockSequenceNode: aNode continue: aBlock
  386. self interpretSequenceNode: aNode continue: aBlock
  387. !
  388. interpretCascadeNode: aNode continue: aBlock
  389. "TODO: Handle super sends"
  390. self interpret: aNode receiver continue: [ :receiver |
  391. "Only interpret the receiver once"
  392. aNode nodes do: [ :each | each receiver: receiver ].
  393. self
  394. interpretAll: aNode nodes allButLast
  395. continue: [
  396. self
  397. interpret: aNode nodes last
  398. continue: [ :val | self continue: aBlock value: val ] ] ]
  399. !
  400. interpretClassReferenceNode: aNode continue: aBlock
  401. self continue: aBlock value: (Smalltalk current at: aNode value)
  402. !
  403. interpretDynamicArrayNode: aNode continue: aBlock
  404. self interpretAll: aNode nodes continue: [ :array |
  405. self
  406. continue: aBlock
  407. value: array ]
  408. !
  409. interpretDynamicDictionaryNode: aNode continue: aBlock
  410. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  411. hashedCollection := HashedCollection new.
  412. array do: [ :each | hashedCollection add: each ].
  413. self
  414. continue: aBlock
  415. value: hashedCollection ]
  416. !
  417. interpretJSStatementNode: aNode continue: aBlock
  418. shouldReturn := true.
  419. self continue: aBlock value: (self eval: aNode source)
  420. !
  421. interpretMethodNode: aNode continue: aBlock
  422. self interpretAll: aNode nodes continue: [ :array |
  423. self continue: aBlock value: array first ]
  424. !
  425. interpretNode: aNode continue: aBlock
  426. aNode interpreter: self continue: aBlock
  427. !
  428. interpretReturnNode: aNode continue: aBlock
  429. self interpret: aNode nodes first continue: [ :value |
  430. shouldReturn := true.
  431. self continue: aBlock value: value ]
  432. !
  433. interpretSendNode: aNode continue: aBlock
  434. self interpret: aNode receiver continue: [ :receiver |
  435. self interpretAll: aNode arguments continue: [ :args |
  436. self
  437. messageFromSendNode: aNode
  438. arguments: args
  439. do: [ :message |
  440. self context pc: self context pc + 1.
  441. self
  442. continue: aBlock
  443. value: (self sendMessage: message to: receiver superSend: aNode superSend) ] ] ]
  444. !
  445. interpretSequenceNode: aNode continue: aBlock
  446. self interpretAll: aNode nodes continue: [ :array |
  447. self continue: aBlock value: array last ]
  448. !
  449. interpretValueNode: aNode continue: aBlock
  450. self continue: aBlock value: aNode value
  451. !
  452. interpretVariableNode: aNode continue: aBlock
  453. self
  454. continue: aBlock
  455. value: (aNode binding isInstanceVar
  456. ifTrue: [ self context receiver instVarAt: aNode value ]
  457. ifFalse: [ self context localAt: aNode value ])
  458. ! !
  459. !ASTInterpreter methodsFor: 'private'!
  460. assign: aNode to: anObject
  461. ^ aNode binding isInstanceVar
  462. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  463. ifFalse: [ self context localAt: aNode value put: anObject ]
  464. !
  465. continue: aBlock value: anObject
  466. result := anObject.
  467. aBlock value: anObject
  468. !
  469. eval: aString
  470. "Evaluate aString as JS source inside an JS function.
  471. aString is not sandboxed."
  472. | source function |
  473. source := String streamContents: [ :str |
  474. str nextPutAll: '(function('.
  475. self context locals keys
  476. do: [ :each | str nextPutAll: each ]
  477. separatedBy: [ str nextPutAll: ',' ].
  478. str
  479. nextPutAll: '){ return (function() {';
  480. nextPutAll: aString;
  481. nextPutAll: '})() })' ].
  482. function := Compiler new eval: source.
  483. ^ function valueWithPossibleArguments: self context locals values
  484. !
  485. interpretAll: aCollection continue: aBlock
  486. self
  487. interpretAll: aCollection
  488. continue: aBlock
  489. result: OrderedCollection new
  490. !
  491. interpretAll: nodes continue: aBlock result: aCollection
  492. nodes isEmpty
  493. ifTrue: [ self continue: aBlock value: aCollection ]
  494. ifFalse: [
  495. self interpret: nodes first continue: [:value |
  496. self
  497. interpretAll: nodes allButFirst
  498. continue: aBlock
  499. result: aCollection, { value } ] ]
  500. !
  501. messageFromSendNode: aSendNode arguments: aCollection do: aBlock
  502. self
  503. continue: aBlock
  504. value: (Message new
  505. selector: aSendNode selector;
  506. arguments: aCollection;
  507. yourself)
  508. !
  509. sendMessage: aMessage to: anObject superSend: aBoolean
  510. | method |
  511. aBoolean ifFalse: [ ^ aMessage sendTo: anObject ].
  512. anObject class superclass ifNil: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  513. method := anObject class superclass methodDictionary
  514. at: aMessage selector
  515. ifAbsent: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  516. ^ method fn applyTo: anObject arguments: aMessage arguments
  517. !
  518. withBlockContext: aBlock
  519. "Evaluate aBlock with a BlockContext:
  520. - a context is pushed before aBlock evaluation.
  521. - the context is poped after aBlock evaluation
  522. - the result of aBlock evaluation is answered"
  523. | blockResult |
  524. self context: (AIContext new
  525. outerContext: self context;
  526. yourself).
  527. blockResult := aBlock value.
  528. self context: self context outerContext.
  529. ^ blockResult
  530. ! !
  531. !ASTInterpreter methodsFor: 'testing'!
  532. shouldReturn
  533. ^ shouldReturn ifNil: [ false ]
  534. ! !
  535. ASTInterpreter subclass: #ASTSteppingInterpreter
  536. instanceVariableNames: 'continuation nextNode'
  537. package: 'Compiler-Interpreter'!
  538. !ASTSteppingInterpreter commentStamp!
  539. I am an interpreter with stepping capabilities. The higher level `ASTDebugger` class should be used as a debugger model, as it provides convenience methods for debugging.
  540. ## API
  541. Use `#step` to actually interpret the next node. Interpretation stops at each node evaluation, weither it's a message node or not.
  542. ## Usage example:
  543. | ast interpreter |
  544. ast := Smalltalk current parse: 'foo 1+2+4'.
  545. (SemanticAnalyzer on: Object) visit: ast.
  546. interpreter := ASTSteppingInterpreter new
  547. interpret: ast nodes first;
  548. yourself.
  549. interpreter step; step.
  550. interpreter step; step.
  551. interpreter result."Answers 1"
  552. interpreter step.
  553. interpreter result. "Answers 3"
  554. interpreter step.
  555. interpreter result. "Answers 7"!
  556. !ASTSteppingInterpreter methodsFor: 'accessing'!
  557. nextNode
  558. ^ nextNode
  559. ! !
  560. !ASTSteppingInterpreter methodsFor: 'initialization'!
  561. initialize
  562. super initialize.
  563. continuation := []
  564. ! !
  565. !ASTSteppingInterpreter methodsFor: 'interpreting'!
  566. interpret: aNode continue: aBlock
  567. nextNode := aNode.
  568. continuation := [
  569. super interpret: aNode continue: aBlock ]
  570. ! !
  571. !ASTSteppingInterpreter methodsFor: 'stepping'!
  572. step
  573. continuation value
  574. ! !
  575. !ASTSteppingInterpreter methodsFor: 'testing'!
  576. atEnd
  577. ^ self shouldReturn or: [ self nextNode == self currentNode ]
  578. ! !
  579. NodeVisitor subclass: #ASTPCNodeVisitor
  580. instanceVariableNames: 'useInlinings pc context blockIndex currentNode'
  581. package: 'Compiler-Interpreter'!
  582. !ASTPCNodeVisitor commentStamp!
  583. I visit an AST until I get to the current pc node and answer it.
  584. ## API
  585. My instances must be filled with a context object using `#context:`.
  586. After visiting the AST the current node corresponding to the `pc` is answered by `#currentNode`!
  587. !ASTPCNodeVisitor methodsFor: 'accessing'!
  588. blockIndex
  589. ^ blockIndex ifNil: [ blockIndex := 0 ]
  590. !
  591. context
  592. ^ context
  593. !
  594. context: aContext
  595. context := aContext
  596. !
  597. currentNode
  598. ^ currentNode
  599. !
  600. increaseBlockIndex
  601. blockIndex := self blockIndex + 1
  602. !
  603. pc
  604. ^ pc ifNil: [ 0 ]
  605. !
  606. pc: anInteger
  607. pc := anInteger
  608. !
  609. useInlinings
  610. ^ useInlinings ifNil: [ true ]
  611. !
  612. useInlinings: aBoolean
  613. useInlinings := aBoolean
  614. ! !
  615. !ASTPCNodeVisitor methodsFor: 'visiting'!
  616. visitBlockNode: aNode
  617. aNode shouldBeInlined
  618. ifFalse: [
  619. self blockIndex >= self context index ifFalse: [
  620. self increaseBlockIndex.
  621. super visitBlockNode: aNode ] ]
  622. ifTrue: [ super visitBlockNode: aNode ]
  623. !
  624. visitJSStatementNode: aNode
  625. currentNode := aNode
  626. !
  627. visitSendNode: aNode
  628. super visitSendNode: aNode.
  629. self pc = self context pc ifFalse: [
  630. aNode shouldBeInlined ifFalse: [
  631. self blockIndex = self context index ifTrue: [
  632. self pc: self pc + 1.
  633. currentNode := aNode ] ] ]
  634. ! !
  635. NodeVisitor subclass: #Interpreter
  636. instanceVariableNames: 'node context stack returnValue'
  637. package: 'Compiler-Interpreter'!
  638. !Interpreter methodsFor: 'accessing'!
  639. context
  640. ^ context
  641. !
  642. context: aContext
  643. context := aContext
  644. !
  645. node
  646. "Answer the next node, ie the node to be evaluated in the next step"
  647. ^ node
  648. !
  649. node: aNode
  650. node := aNode
  651. !
  652. result
  653. ^ self returnValue ifNil: [ self context receiver ]
  654. !
  655. returnValue
  656. ^ returnValue
  657. !
  658. returnValue: anObject
  659. returnValue := anObject
  660. !
  661. stack
  662. ^ stack ifNil: [ stack := OrderedCollection new ]
  663. ! !
  664. !Interpreter methodsFor: 'interpreting'!
  665. interpret
  666. "Interpret the next node to be evaluated"
  667. self visit: self node
  668. !
  669. interpret: aNode
  670. self node: aNode.
  671. self interpret
  672. !
  673. next
  674. self node: self node nextNode
  675. !
  676. proceed
  677. "Eagerly evaluate the ast"
  678. [ self atEnd ] whileFalse: [
  679. self step ]
  680. !
  681. restart
  682. self node: self context ast nextChild
  683. !
  684. skip
  685. self next
  686. !
  687. step
  688. self
  689. interpret;
  690. next
  691. !
  692. stepOver
  693. self step.
  694. [ self node isSteppingNode ] whileFalse: [
  695. self step ]
  696. ! !
  697. !Interpreter methodsFor: 'private'!
  698. assign: aNode to: anObject
  699. aNode binding isInstanceVar
  700. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  701. ifFalse: [ self context localAt: aNode value put: anObject ]
  702. !
  703. eval: aString
  704. "Evaluate aString as JS source inside an JS function.
  705. aString is not sandboxed."
  706. | source function |
  707. source := String streamContents: [ :str |
  708. str nextPutAll: '(function('.
  709. self context locals keys
  710. do: [ :each | str nextPutAll: each ]
  711. separatedBy: [ str nextPutAll: ',' ].
  712. str
  713. nextPutAll: '){ return (function() {';
  714. nextPutAll: aString;
  715. nextPutAll: '})() })' ].
  716. function := Compiler new eval: source.
  717. ^ function valueWithPossibleArguments: self context locals values
  718. !
  719. messageFromSendNode: aSendNode arguments: aCollection
  720. ^ Message new
  721. selector: aSendNode selector;
  722. arguments: aCollection;
  723. yourself
  724. !
  725. messageNotUnderstood: aMessage receiver: anObject
  726. MessageNotUnderstood new
  727. meesage: aMessage;
  728. receiver: anObject;
  729. signal
  730. !
  731. sendMessage: aMessage to: anObject superSend: aBoolean
  732. | method |
  733. aBoolean ifFalse: [ ^ aMessage sendTo: anObject ].
  734. anObject class superclass ifNil: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  735. method := anObject class superclass methodDictionary
  736. at: aMessage selector
  737. ifAbsent: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  738. ^ method sendTo: anObject arguments: aMessage arguments
  739. ! !
  740. !Interpreter methodsFor: 'stack'!
  741. peek
  742. "Peek the top object of the context stack"
  743. self stack ifEmpty: [ ^ nil ].
  744. ^ self stack last
  745. !
  746. pop
  747. "Pop an object from the context stack"
  748. | peekedValue |
  749. peekedValue := self peek.
  750. self stack removeLast.
  751. ^ peekedValue
  752. !
  753. push: anObject
  754. "Push an object to the context stack"
  755. ^ self stack add: anObject
  756. ! !
  757. !Interpreter methodsFor: 'testing'!
  758. atEnd
  759. ^ self shouldReturn or: [ self node isNil ]
  760. !
  761. shouldReturn
  762. ^ self returnValue notNil
  763. ! !
  764. !Interpreter methodsFor: 'visiting'!
  765. visit: aNode
  766. self shouldReturn ifFalse: [ super visit: aNode ]
  767. !
  768. visitAssignmentNode: aNode
  769. | poppedValue |
  770. poppedValue := self pop.
  771. "Pop the left side of the assignment.
  772. It already has been visited, and we don't need its value."
  773. self pop.
  774. self push: poppedValue.
  775. self assign: aNode left to: poppedValue
  776. !
  777. visitBlockNode: aNode
  778. "Do not evaluate the block node.
  779. Instead, put all instructions into a block that we push to the stack for later evaluation"
  780. | block |
  781. block := AIBlockClosure forContext: self context node: aNode.
  782. self push: block
  783. !
  784. visitClassReferenceNode: aNode
  785. self push: (Smalltalk current
  786. at: aNode value
  787. ifAbsent: [ PlatformInterface globals at: aNode value ])
  788. !
  789. visitDynamicArrayNode: aNode
  790. | array |
  791. array := #().
  792. aNode nodes do: [ :each |
  793. array addFirst: self pop ].
  794. self push: array
  795. !
  796. visitDynamicDictionaryNode: aNode
  797. | hashedCollection |
  798. hashedCollection := HashedCollection new.
  799. aNode nodes do: [ :each |
  800. hashedCollection add: self pop ].
  801. self push: hashedCollection
  802. !
  803. visitJSStatementNode: aNode
  804. self returnValue: (self eval: aNode source)
  805. !
  806. visitNode: aNode
  807. "Do nothing by default. Especially, do not visit children recursively."
  808. !
  809. visitReturnNode: aNode
  810. self returnValue: self pop
  811. !
  812. visitSendNode: aNode
  813. | receiver args message result |
  814. args := aNode arguments collect: [ :each | self pop ].
  815. receiver := self pop.
  816. message := self
  817. messageFromSendNode: aNode
  818. arguments: args reversed.
  819. result := self sendMessage: message to: receiver superSend: aNode superSend.
  820. self context pc: self context pc + 1.
  821. "For cascade sends, push the reciever if the send is not the last one"
  822. (aNode isCascadeSendNode and: [ aNode isLastChild not ])
  823. ifTrue: [ self push: receiver ]
  824. ifFalse: [ self push: result ]
  825. !
  826. visitValueNode: aNode
  827. self push: aNode value
  828. !
  829. visitVariableNode: aNode
  830. aNode binding isUnknownVar ifTrue: [
  831. ^ self push: (PlatformInterface globals at: aNode value ifAbsent: [ self error: 'Unknown variable' ]) ].
  832. self push: (aNode binding isInstanceVar
  833. ifTrue: [ self context receiver instVarAt: aNode value ]
  834. ifFalse: [ self context localAt: aNode value ])
  835. ! !
  836. !Node methodsFor: '*Compiler-Interpreter'!
  837. interpreter: anInterpreter continue: aBlock
  838. ^ anInterpreter interpretNode: self continue: aBlock
  839. !
  840. isSteppingNode
  841. ^ false
  842. ! !
  843. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  844. interpreter: anInterpreter continue: aBlock
  845. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  846. !
  847. isSteppingNode
  848. ^ true
  849. ! !
  850. !BlockNode methodsFor: '*Compiler-Interpreter'!
  851. interpreter: anInterpreter continue: aBlock
  852. ^ anInterpreter interpretBlockNode: self continue: aBlock
  853. !
  854. isSteppingNode
  855. ^ true
  856. ! !
  857. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  858. interpreter: anInterpreter continue: aBlock
  859. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  860. ! !
  861. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  862. interpreter: anInterpreter continue: aBlock
  863. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  864. !
  865. isSteppingNode
  866. ^ true
  867. ! !
  868. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  869. interpreter: anInterpreter continue: aBlock
  870. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  871. !
  872. isSteppingNode
  873. ^ true
  874. ! !
  875. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  876. interpreter: anInterpreter continue: aBlock
  877. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  878. !
  879. isSteppingNode
  880. ^ true
  881. ! !
  882. !MethodNode methodsFor: '*Compiler-Interpreter'!
  883. interpreter: anInterpreter continue: aBlock
  884. ^ anInterpreter interpretMethodNode: self continue: aBlock
  885. ! !
  886. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  887. interpreter: anInterpreter continue: aBlock
  888. ^ anInterpreter interpretReturnNode: self continue: aBlock
  889. ! !
  890. !SendNode methodsFor: '*Compiler-Interpreter'!
  891. interpreter: anInterpreter continue: aBlock
  892. ^ anInterpreter interpretSendNode: self continue: aBlock
  893. !
  894. isSteppingNode
  895. ^ true
  896. ! !
  897. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  898. interpreter: anInterpreter continue: aBlock
  899. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  900. ! !
  901. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  902. interpreter: anInterpreter continue: aBlock
  903. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  904. ! !
  905. !ValueNode methodsFor: '*Compiler-Interpreter'!
  906. interpreter: anInterpreter continue: aBlock
  907. ^ anInterpreter interpretValueNode: self continue: aBlock
  908. ! !
  909. !VariableNode methodsFor: '*Compiler-Interpreter'!
  910. interpreter: anInterpreter continue: aBlock
  911. ^ anInterpreter interpretVariableNode: self continue: aBlock
  912. ! !
  913. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  914. interpreter: anInterpreter continue: aBlock
  915. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  916. ! !