Compiler-Interpreter.st 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  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. | peekedValue |
  737. peekedValue := self peek.
  738. self stack removeLast.
  739. ^ peekedValue
  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. | poppedValue |
  758. poppedValue := 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: poppedValue.
  763. self assign: aNode left to: poppedValue
  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. !Node methodsFor: '*Compiler-Interpreter'!
  823. interpreter: anInterpreter continue: aBlock
  824. ^ anInterpreter interpretNode: self continue: aBlock
  825. !
  826. isSteppingNode
  827. ^ false
  828. ! !
  829. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  830. interpreter: anInterpreter continue: aBlock
  831. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  832. !
  833. isSteppingNode
  834. ^ true
  835. ! !
  836. !BlockNode methodsFor: '*Compiler-Interpreter'!
  837. interpreter: anInterpreter continue: aBlock
  838. ^ anInterpreter interpretBlockNode: self continue: aBlock
  839. !
  840. isSteppingNode
  841. ^ true
  842. ! !
  843. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  844. interpreter: anInterpreter continue: aBlock
  845. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  846. ! !
  847. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  848. interpreter: anInterpreter continue: aBlock
  849. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  850. !
  851. isSteppingNode
  852. ^ true
  853. ! !
  854. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  855. interpreter: anInterpreter continue: aBlock
  856. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  857. !
  858. isSteppingNode
  859. ^ true
  860. ! !
  861. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  862. interpreter: anInterpreter continue: aBlock
  863. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  864. !
  865. isSteppingNode
  866. ^ true
  867. ! !
  868. !MethodNode methodsFor: '*Compiler-Interpreter'!
  869. interpreter: anInterpreter continue: aBlock
  870. ^ anInterpreter interpretMethodNode: self continue: aBlock
  871. ! !
  872. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  873. interpreter: anInterpreter continue: aBlock
  874. ^ anInterpreter interpretReturnNode: self continue: aBlock
  875. ! !
  876. !SendNode methodsFor: '*Compiler-Interpreter'!
  877. interpreter: anInterpreter continue: aBlock
  878. ^ anInterpreter interpretSendNode: self continue: aBlock
  879. !
  880. isSteppingNode
  881. ^ true
  882. ! !
  883. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  884. interpreter: anInterpreter continue: aBlock
  885. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  886. ! !
  887. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  888. interpreter: anInterpreter continue: aBlock
  889. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  890. ! !
  891. !ValueNode methodsFor: '*Compiler-Interpreter'!
  892. interpreter: anInterpreter continue: aBlock
  893. ^ anInterpreter interpretValueNode: self continue: aBlock
  894. ! !
  895. !VariableNode methodsFor: '*Compiler-Interpreter'!
  896. interpreter: anInterpreter continue: aBlock
  897. ^ anInterpreter interpretVariableNode: self continue: aBlock
  898. ! !
  899. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  900. interpreter: anInterpreter continue: aBlock
  901. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  902. ! !