Compiler-Interpreter.st 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. Smalltalk current createPackage: 'Compiler-Interpreter'!
  2. NodeVisitor subclass: #AIContext
  3. instanceVariableNames: 'outerContext innerContext pc locals method ast interpreter'
  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. returnValue
  539. ^ returnValue ifNil: [ self context receiver ]
  540. !
  541. returnValue: anObject
  542. returnValue := anObject
  543. !
  544. stack
  545. ^ stack ifNil: [ stack := OrderedCollection new ]
  546. ! !
  547. !Interpreter methodsFor: 'interpreting'!
  548. interpret
  549. "Interpret the next node to be evaluated"
  550. self visit: self node
  551. !
  552. next
  553. self node: self node nextNode
  554. !
  555. proceed
  556. "Eagerly evaluate the ast"
  557. [ self node notNil ] whileTrue: [
  558. self step ]
  559. !
  560. skip
  561. self next
  562. !
  563. step
  564. self
  565. interpret;
  566. next
  567. ! !
  568. !Interpreter methodsFor: 'private'!
  569. assign: aNode to: anObject
  570. aNode binding isInstanceVar
  571. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  572. ifFalse: [ self context localAt: aNode value put: anObject ]
  573. !
  574. eval: aString
  575. "Evaluate aString as JS source inside an JS function.
  576. aString is not sandboxed."
  577. | source function |
  578. source := String streamContents: [ :str |
  579. str nextPutAll: '(function('.
  580. self context locals keys
  581. do: [ :each | str nextPutAll: each ]
  582. separatedBy: [ str nextPutAll: ',' ].
  583. str
  584. nextPutAll: '){ return (function() {';
  585. nextPutAll: aString;
  586. nextPutAll: '})() })' ].
  587. function := Compiler new eval: source.
  588. ^ function valueWithPossibleArguments: self context locals values
  589. !
  590. messageFromSendNode: aSendNode arguments: aCollection
  591. ^ Message new
  592. selector: aSendNode selector;
  593. arguments: aCollection;
  594. yourself
  595. !
  596. messageNotUnderstood: aMessage receiver: anObject
  597. MessageNotUnderstood new
  598. meesage: aMessage;
  599. receiver: anObject;
  600. signal
  601. !
  602. sendMessage: aMessage to: anObject superSend: aBoolean
  603. | method |
  604. aBoolean ifFalse: [ ^ aMessage sendTo: anObject ].
  605. anObject class superclass ifNil: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  606. method := anObject class superclass methodDictionary
  607. at: aMessage selector
  608. ifAbsent: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  609. ^ method sendTo: anObject arguments: aMessage arguments
  610. ! !
  611. !Interpreter methodsFor: 'stack'!
  612. peek
  613. "Peek the top object of the context stack"
  614. ^ self stack last
  615. !
  616. pop
  617. "Pop an object from the context stack"
  618. | value |
  619. value := self peek.
  620. self stack removeLast.
  621. ^ value
  622. !
  623. push: anObject
  624. "Push an object to the context stack"
  625. ^ self stack add: anObject
  626. ! !
  627. !Interpreter methodsFor: 'testing'!
  628. atEnd
  629. ^ self shouldReturn or: [ self node isNil ]
  630. !
  631. shouldReturn
  632. ^ returnValue notNil
  633. ! !
  634. !Interpreter methodsFor: 'visiting'!
  635. visit: aNode
  636. self shouldReturn ifFalse: [ super visit: aNode ]
  637. !
  638. visitAssignmentNode: aNode
  639. "Do not pop as the pushed value would be the right node"
  640. self assign: aNode left to: self peek
  641. !
  642. visitClassReferenceNode: aNode
  643. self push: (Smalltalk current at: aNode value)
  644. !
  645. visitJSStatementNode: aNode
  646. self returnValue: (self eval: aNode source)
  647. !
  648. visitNode: aNode
  649. "Do nothing by default. Especially, do not visit children recursively."
  650. !
  651. visitReturnNode: aNode
  652. self returnValue: self pop
  653. !
  654. visitSendNode: aNode
  655. | receiver args message result |
  656. args := aNode arguments collect: [ :each |
  657. self pop ].
  658. receiver := self pop.
  659. message := self
  660. messageFromSendNode: aNode
  661. arguments: args.
  662. result := self sendMessage: message to: receiver superSend: aNode superSend.
  663. self push: result
  664. !
  665. visitValueNode: aNode
  666. self push: aNode value
  667. !
  668. visitVariableNode: aNode
  669. "TODO: what about other vars (JS globals for instance)?"
  670. self push: (aNode binding isInstanceVar
  671. ifTrue: [ self context receiver instVarAt: aNode value ]
  672. ifFalse: [ self context localAt: aNode value ])
  673. ! !
  674. !Node methodsFor: '*Compiler-Interpreter'!
  675. interpreter: anInterpreter continue: aBlock
  676. ^ anInterpreter interpretNode: self continue: aBlock
  677. !
  678. isSteppingNode
  679. ^ false
  680. ! !
  681. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  682. interpreter: anInterpreter continue: aBlock
  683. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  684. !
  685. isSteppingNode
  686. ^ true
  687. ! !
  688. !BlockNode methodsFor: '*Compiler-Interpreter'!
  689. interpreter: anInterpreter continue: aBlock
  690. ^ anInterpreter interpretBlockNode: self continue: aBlock
  691. !
  692. isSteppingNode
  693. ^ true
  694. ! !
  695. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  696. interpreter: anInterpreter continue: aBlock
  697. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  698. ! !
  699. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  700. interpreter: anInterpreter continue: aBlock
  701. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  702. !
  703. isSteppingNode
  704. ^ true
  705. ! !
  706. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  707. interpreter: anInterpreter continue: aBlock
  708. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  709. !
  710. isSteppingNode
  711. ^ true
  712. ! !
  713. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  714. interpreter: anInterpreter continue: aBlock
  715. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  716. !
  717. isSteppingNode
  718. ^ true
  719. ! !
  720. !MethodNode methodsFor: '*Compiler-Interpreter'!
  721. interpreter: anInterpreter continue: aBlock
  722. ^ anInterpreter interpretMethodNode: self continue: aBlock
  723. ! !
  724. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  725. interpreter: anInterpreter continue: aBlock
  726. ^ anInterpreter interpretReturnNode: self continue: aBlock
  727. ! !
  728. !SendNode methodsFor: '*Compiler-Interpreter'!
  729. interpreter: anInterpreter continue: aBlock
  730. ^ anInterpreter interpretSendNode: self continue: aBlock
  731. !
  732. isSteppingNode
  733. ^ true
  734. ! !
  735. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  736. interpreter: anInterpreter continue: aBlock
  737. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  738. ! !
  739. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  740. interpreter: anInterpreter continue: aBlock
  741. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  742. ! !
  743. !ValueNode methodsFor: '*Compiler-Interpreter'!
  744. interpreter: anInterpreter continue: aBlock
  745. ^ anInterpreter interpretValueNode: self continue: aBlock
  746. ! !
  747. !VariableNode methodsFor: '*Compiler-Interpreter'!
  748. interpreter: anInterpreter continue: aBlock
  749. ^ anInterpreter interpretVariableNode: self continue: aBlock
  750. ! !
  751. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  752. interpreter: anInterpreter continue: aBlock
  753. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  754. ! !