Compiler-Interpreter.st 22 KB

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