1
0

Compiler-Interpreter.st 25 KB

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