1
0

Compiler-Interpreter.st 23 KB

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