Compiler-Interpreter.st 22 KB

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