Compiler-Interpreter.st 25 KB

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