Compiler-Interpreter.st 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. Smalltalk current createPackage: 'Compiler-Interpreter'!
  2. NodeVisitor subclass: #AIContext
  3. instanceVariableNames: 'methodContext outerContext pc locals method'
  4. package: 'Compiler-Interpreter'!
  5. !AIContext commentStamp!
  6. I am like a `MethodContext`, used by the `ASTInterpreter`.
  7. Unlike a `MethodContext`, my instances are not read-only.
  8. When debugging, my instances are created by copying the current `MethodContext` (thisContext)!
  9. !AIContext methodsFor: 'accessing'!
  10. home
  11. ^ self isBlockContext
  12. ifTrue: [ self outerContext methodContext ]
  13. ifFalse: [ self ]
  14. !
  15. localAt: aString
  16. ^ self locals at: aString ifAbsent: [ nil ]
  17. !
  18. localAt: aString put: anObject
  19. self locals at: aString put: anObject
  20. !
  21. locals
  22. locals ifNil: [ self initializeLocals ].
  23. ^ locals
  24. !
  25. method
  26. ^ method
  27. !
  28. method: aCompiledMethod
  29. method := aCompiledMethod
  30. !
  31. outerContext
  32. ^ outerContext
  33. !
  34. outerContext: anAIContext
  35. outerContext := anAIContext
  36. !
  37. pc
  38. ^ pc ifNil: [ pc := 0 ]
  39. !
  40. pc: anInteger
  41. pc := anInteger
  42. !
  43. receiver
  44. ^ self localAt: 'self'
  45. !
  46. receiver: anObject
  47. self localAt: 'self' put: anObject
  48. !
  49. selector
  50. ^ self method
  51. ifNotNil: [ self method selector ]
  52. ! !
  53. !AIContext methodsFor: 'converting'!
  54. asString
  55. ^ methodContext asString
  56. ! !
  57. !AIContext methodsFor: 'initialization'!
  58. initializeFromMethodContext: aMethodContext
  59. methodContext := aMethodContext.
  60. self pc: aMethodContext pc.
  61. self receiver: aMethodContext receiver.
  62. self method: aMethodContext method.
  63. aMethodContext outerContext ifNotNil: [
  64. self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
  65. aMethodContext locals keysAndValuesDo: [ :key :value |
  66. self locals at: key put: value ]
  67. !
  68. initializeLocals
  69. locals := Dictionary new.
  70. locals at: 'thisContext' put: self.
  71. ! !
  72. !AIContext methodsFor: 'testing'!
  73. isBlockContext
  74. ^ methodContext isBlockContext
  75. ! !
  76. !AIContext class methodsFor: 'instance creation'!
  77. fromMethodContext: aMethodContext
  78. ^ self new
  79. initializeFromMethodContext: aMethodContext;
  80. yourself
  81. ! !
  82. Object subclass: #ASTDebugger
  83. instanceVariableNames: 'interpreter context'
  84. package: 'Compiler-Interpreter'!
  85. !ASTDebugger commentStamp!
  86. I am a stepping debugger interface for Amber code.
  87. I internally use an instance of `ASTSteppingInterpreter` to actually step through node and interpret them.
  88. My instances are created from a `MethodContext` with `ASTDebugger class >> context:`.
  89. They hold an `AIContext` instance internally, recursive copy of the `MethodContext`.
  90. ## API
  91. Use the methods of the `'stepping'` protocol to do stepping.!
  92. !ASTDebugger methodsFor: 'accessing'!
  93. context
  94. ^ context
  95. !
  96. context: aContext
  97. context := aContext
  98. !
  99. interpreter
  100. ^ interpreter ifNil: [ interpreter := self defaultInterpreterClass new ]
  101. !
  102. interpreter: anInterpreter
  103. interpreter := anInterpreter
  104. !
  105. method
  106. ^ self context method
  107. !
  108. nextNode
  109. ^ self interpreter nextNode
  110. ! !
  111. !ASTDebugger methodsFor: 'defaults'!
  112. defaultInterpreterClass
  113. ^ ASTSteppingInterpreter
  114. ! !
  115. !ASTDebugger methodsFor: 'initialization'!
  116. buildAST
  117. "Build the AST tree from the method source code.
  118. The AST is annotated with a SemanticAnalyzer,
  119. to know the semantics and bindings of each node needed for later debugging"
  120. | ast |
  121. ast := Smalltalk current parse: self method source.
  122. (SemanticAnalyzer on: self context receiver class)
  123. visit: ast.
  124. ^ ast
  125. !
  126. initializeInterpreter
  127. | ast next |
  128. ast := self buildAST.
  129. next := ASTPCNodeVisitor new
  130. context: self context;
  131. visit: ast;
  132. currentNode.
  133. self interpreter interpret: next
  134. !
  135. initializeWithContext: aContext
  136. "TODO: do we need to handle block contexts?"
  137. self context: aContext.
  138. self initializeInterpreter
  139. ! !
  140. !ASTDebugger methodsFor: 'stepping'!
  141. proceed
  142. self shouldBeImplemented
  143. !
  144. restart
  145. self shouldBeImplemented
  146. !
  147. step
  148. "The ASTSteppingInterpreter stops at each node interpretation.
  149. One step will interpret nodes until:
  150. - we get at the end
  151. - the next node is a stepping node (send, assignment, etc.)"
  152. [ (self interpreter nextNode notNil and: [ self interpreter nextNode stopOnStepping ])
  153. or: [ self interpreter atEnd not ] ]
  154. whileFalse: [
  155. self interpreter step.
  156. self step ]
  157. !
  158. stepInto
  159. self shouldBeImplemented
  160. !
  161. stepOver
  162. self step
  163. ! !
  164. !ASTDebugger methodsFor: 'testing'!
  165. atEnd
  166. ^ self interpreter atEnd
  167. ! !
  168. !ASTDebugger class methodsFor: 'instance creation'!
  169. context: aContext
  170. ^ self new
  171. initializeWithContext: aContext;
  172. yourself
  173. ! !
  174. Object subclass: #ASTInterpreter
  175. instanceVariableNames: 'currentNode context shouldReturn result'
  176. package: 'Compiler-Interpreter'!
  177. !ASTInterpreter commentStamp!
  178. I am like a `NodeVisitor`, interpreting nodes one after each other.
  179. I am built using Continuation Passing Style for stepping purposes.
  180. ## Usage example:
  181. | ast interpreter |
  182. ast := Smalltalk current parse: 'foo 1+2+4'.
  183. (SemanticAnalyzer on: Object) visit: ast.
  184. ASTInterpreter new
  185. interpret: ast nodes first;
  186. result "Answers 7"!
  187. !ASTInterpreter methodsFor: 'accessing'!
  188. context
  189. ^ context ifNil: [ context := AIContext new ]
  190. !
  191. context: anAIContext
  192. context := anAIContext
  193. !
  194. currentNode
  195. ^ currentNode
  196. !
  197. result
  198. ^ result
  199. ! !
  200. !ASTInterpreter methodsFor: 'initialization'!
  201. initialize
  202. super initialize.
  203. shouldReturn := false
  204. ! !
  205. !ASTInterpreter methodsFor: 'interpreting'!
  206. interpret: aNode
  207. shouldReturn := false.
  208. self interpret: aNode continue: [ :value |
  209. result := value ]
  210. !
  211. interpret: aNode continue: aBlock
  212. shouldReturn ifTrue: [ ^ self ].
  213. aNode isNode
  214. ifTrue: [
  215. currentNode := aNode.
  216. self interpretNode: aNode continue: [ :value |
  217. self continue: aBlock value: value ] ]
  218. ifFalse: [ self continue: aBlock value: aNode ]
  219. !
  220. interpretAssignmentNode: aNode continue: aBlock
  221. self interpret: aNode right continue: [ :value |
  222. self
  223. continue: aBlock
  224. value: (self assign: aNode left to: value) ]
  225. !
  226. interpretBlockNode: aNode continue: aBlock
  227. self
  228. continue: aBlock
  229. value: [
  230. self withBlockContext: [
  231. self interpret: aNode nodes first; result ] ]
  232. !
  233. interpretBlockSequenceNode: aNode continue: aBlock
  234. self interpretSequenceNode: aNode continue: aBlock
  235. !
  236. interpretCascadeNode: aNode continue: aBlock
  237. "TODO: Handle super sends"
  238. self interpret: aNode receiver continue: [ :receiver |
  239. "Only interpret the receiver once"
  240. aNode nodes do: [ :each | each receiver: receiver ].
  241. self
  242. interpretAll: aNode nodes allButLast
  243. continue: [
  244. self
  245. interpret: aNode nodes last
  246. continue: [ :val | self continue: aBlock value: val ] ] ]
  247. !
  248. interpretClassReferenceNode: aNode continue: aBlock
  249. self continue: aBlock value: (Smalltalk current at: aNode value)
  250. !
  251. interpretDynamicArrayNode: aNode continue: aBlock
  252. self interpretAll: aNode nodes continue: [ :array |
  253. self
  254. continue: aBlock
  255. value: array ]
  256. !
  257. interpretDynamicDictionaryNode: aNode continue: aBlock
  258. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  259. hashedCollection := HashedCollection new.
  260. array do: [ :each | hashedCollection add: each ].
  261. self
  262. continue: aBlock
  263. value: hashedCollection ]
  264. !
  265. interpretJSStatementNode: aNode continue: aBlock
  266. shouldReturn := true.
  267. self continue: aBlock value: (self eval: aNode source)
  268. !
  269. interpretMethodNode: aNode continue: aBlock
  270. self interpretAll: aNode nodes continue: [ :array |
  271. self continue: aBlock value: array first ]
  272. !
  273. interpretNode: aNode continue: aBlock
  274. aNode interpreter: self continue: aBlock
  275. !
  276. interpretReturnNode: aNode continue: aBlock
  277. self interpret: aNode nodes first continue: [ :value |
  278. shouldReturn := true.
  279. self continue: aBlock value: value ]
  280. !
  281. interpretSendNode: aNode continue: aBlock
  282. self interpret: aNode receiver continue: [ :receiver |
  283. self interpretAll: aNode arguments continue: [ :args |
  284. self
  285. messageFromSendNode: aNode
  286. arguments: args
  287. do: [ :message |
  288. self context pc: self context pc + 1.
  289. self
  290. continue: aBlock
  291. value: (self sendMessage: message to: receiver superSend: aNode superSend) ] ] ]
  292. !
  293. interpretSequenceNode: aNode continue: aBlock
  294. self interpretAll: aNode nodes continue: [ :array |
  295. self continue: aBlock value: array last ]
  296. !
  297. interpretValueNode: aNode continue: aBlock
  298. self continue: aBlock value: aNode value
  299. !
  300. interpretVariableNode: aNode continue: aBlock
  301. self
  302. continue: aBlock
  303. value: (aNode binding isInstanceVar
  304. ifTrue: [ self context receiver instVarAt: aNode value ]
  305. ifFalse: [ self context localAt: aNode value ])
  306. ! !
  307. !ASTInterpreter methodsFor: 'private'!
  308. assign: aNode to: anObject
  309. ^ aNode binding isInstanceVar
  310. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  311. ifFalse: [ self context localAt: aNode value put: anObject ]
  312. !
  313. continue: aBlock value: anObject
  314. result := anObject.
  315. aBlock value: anObject
  316. !
  317. eval: aString
  318. "Evaluate aString as JS source inside an JS function.
  319. aString is not sandboxed."
  320. | source function |
  321. source := String streamContents: [ :str |
  322. str nextPutAll: '(function('.
  323. self context locals keys
  324. do: [ :each | str nextPutAll: each ]
  325. separatedBy: [ str nextPutAll: ',' ].
  326. str
  327. nextPutAll: '){ return (function() {';
  328. nextPutAll: aString;
  329. nextPutAll: '})() })' ].
  330. function := Compiler new eval: source.
  331. ^ function valueWithPossibleArguments: self context locals values
  332. !
  333. interpretAll: aCollection continue: aBlock
  334. self
  335. interpretAll: aCollection
  336. continue: aBlock
  337. result: OrderedCollection new
  338. !
  339. interpretAll: nodes continue: aBlock result: aCollection
  340. nodes isEmpty
  341. ifTrue: [ self continue: aBlock value: aCollection ]
  342. ifFalse: [
  343. self interpret: nodes first continue: [:value |
  344. self
  345. interpretAll: nodes allButFirst
  346. continue: aBlock
  347. result: aCollection, { value } ] ]
  348. !
  349. messageFromSendNode: aSendNode arguments: aCollection do: aBlock
  350. self
  351. continue: aBlock
  352. value: (Message new
  353. selector: aSendNode selector;
  354. arguments: aCollection;
  355. yourself)
  356. !
  357. sendMessage: aMessage to: anObject superSend: aBoolean
  358. | method |
  359. aBoolean ifFalse: [ ^ aMessage sendTo: anObject ].
  360. anObject class superclass ifNil: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  361. method := anObject class superclass methodDictionary
  362. at: aMessage selector
  363. ifAbsent: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
  364. ^ method fn applyTo: anObject arguments: aMessage arguments
  365. !
  366. withBlockContext: aBlock
  367. "Evaluate aBlock with a BlockContext:
  368. - a context is pushed before aBlock evaluation.
  369. - the context is poped after aBlock evaluation
  370. - the result of aBlock evaluation is answered"
  371. | blockResult |
  372. self context: (AIContext new
  373. outerContext: self context;
  374. yourself).
  375. blockResult := aBlock value.
  376. self context: self context outerContext.
  377. ^ blockResult
  378. ! !
  379. !ASTInterpreter methodsFor: 'testing'!
  380. shouldReturn
  381. ^ shouldReturn ifNil: [ false ]
  382. ! !
  383. ASTInterpreter subclass: #ASTSteppingInterpreter
  384. instanceVariableNames: 'continuation nextNode'
  385. package: 'Compiler-Interpreter'!
  386. !ASTSteppingInterpreter commentStamp!
  387. 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.
  388. ## API
  389. Use `#step` to actually interpret the next node. Interpretation stops at each node evaluation, weither it's a message node or not.
  390. ## Usage example:
  391. | ast interpreter |
  392. ast := Smalltalk current parse: 'foo 1+2+4'.
  393. (SemanticAnalyzer on: Object) visit: ast.
  394. interpreter := ASTSteppingInterpreter new
  395. interpret: ast nodes first;
  396. yourself.
  397. interpreter step; step.
  398. interpreter step; step.
  399. interpreter result."Answers 1"
  400. interpreter step.
  401. interpreter result. "Answers 3"
  402. interpreter step.
  403. interpreter result. "Answers 7"!
  404. !ASTSteppingInterpreter methodsFor: 'accessing'!
  405. nextNode
  406. ^ nextNode
  407. ! !
  408. !ASTSteppingInterpreter methodsFor: 'initialization'!
  409. initialize
  410. super initialize.
  411. continuation := []
  412. ! !
  413. !ASTSteppingInterpreter methodsFor: 'interpreting'!
  414. interpret: aNode continue: aBlock
  415. nextNode := aNode.
  416. continuation := [
  417. super interpret: aNode continue: aBlock ]
  418. ! !
  419. !ASTSteppingInterpreter methodsFor: 'stepping'!
  420. step
  421. continuation value
  422. ! !
  423. !ASTSteppingInterpreter methodsFor: 'testing'!
  424. atEnd
  425. ^ self shouldReturn or: [ self nextNode == self currentNode ]
  426. ! !
  427. NodeVisitor subclass: #ASTPCNodeVisitor
  428. instanceVariableNames: 'useInlinings pc context currentNode'
  429. package: 'Compiler-Interpreter'!
  430. !ASTPCNodeVisitor commentStamp!
  431. I visit an AST until I get to the current pc node and answer it.
  432. ## API
  433. My instances must be filled with a context object using `#context:`.
  434. After visiting the AST the current node corresponding to the `pc` is answered by `#currentNode`!
  435. !ASTPCNodeVisitor methodsFor: 'accessing'!
  436. context
  437. ^ context
  438. !
  439. context: aContext
  440. context := aContext
  441. !
  442. currentNode
  443. ^ currentNode
  444. !
  445. pc
  446. ^ pc ifNil: [ 0 ]
  447. !
  448. pc: anInteger
  449. pc := anInteger
  450. !
  451. useInlinings
  452. ^ useInlinings ifNil: [ true ]
  453. !
  454. useInlinings: aBoolean
  455. useInlinings := aBoolean
  456. ! !
  457. !ASTPCNodeVisitor methodsFor: 'visiting'!
  458. visitJSStatementNode: aNode
  459. currentNode := aNode
  460. !
  461. visitSendNode: aNode
  462. super visitSendNode: aNode.
  463. self pc = self context pc ifFalse: [
  464. aNode shouldBeInlined ifFalse: [
  465. self pc: self pc + 1.
  466. currentNode := aNode ] ]
  467. ! !
  468. !Node methodsFor: '*Compiler-Interpreter'!
  469. interpreter: anInterpreter continue: aBlock
  470. ^ anInterpreter interpretNode: self continue: aBlock
  471. !
  472. isSteppingNode
  473. ^ false
  474. ! !
  475. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  476. interpreter: anInterpreter continue: aBlock
  477. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  478. !
  479. isSteppingNode
  480. ^ true
  481. ! !
  482. !BlockNode methodsFor: '*Compiler-Interpreter'!
  483. interpreter: anInterpreter continue: aBlock
  484. ^ anInterpreter interpretBlockNode: self continue: aBlock
  485. !
  486. isSteppingNode
  487. ^ true
  488. ! !
  489. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  490. interpreter: anInterpreter continue: aBlock
  491. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  492. ! !
  493. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  494. interpreter: anInterpreter continue: aBlock
  495. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  496. !
  497. isSteppingNode
  498. ^ true
  499. ! !
  500. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  501. interpreter: anInterpreter continue: aBlock
  502. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  503. !
  504. isSteppingNode
  505. ^ true
  506. ! !
  507. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  508. interpreter: anInterpreter continue: aBlock
  509. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  510. !
  511. isSteppingNode
  512. ^ true
  513. ! !
  514. !MethodNode methodsFor: '*Compiler-Interpreter'!
  515. interpreter: anInterpreter continue: aBlock
  516. ^ anInterpreter interpretMethodNode: self continue: aBlock
  517. ! !
  518. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  519. interpreter: anInterpreter continue: aBlock
  520. ^ anInterpreter interpretReturnNode: self continue: aBlock
  521. ! !
  522. !SendNode methodsFor: '*Compiler-Interpreter'!
  523. interpreter: anInterpreter continue: aBlock
  524. ^ anInterpreter interpretSendNode: self continue: aBlock
  525. !
  526. isSteppingNode
  527. ^ true
  528. ! !
  529. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  530. interpreter: anInterpreter continue: aBlock
  531. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  532. ! !
  533. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  534. interpreter: anInterpreter continue: aBlock
  535. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  536. ! !
  537. !ValueNode methodsFor: '*Compiler-Interpreter'!
  538. interpreter: anInterpreter continue: aBlock
  539. ^ anInterpreter interpretValueNode: self continue: aBlock
  540. ! !
  541. !VariableNode methodsFor: '*Compiler-Interpreter'!
  542. interpreter: anInterpreter continue: aBlock
  543. ^ anInterpreter interpretVariableNode: self continue: aBlock
  544. ! !
  545. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  546. interpreter: anInterpreter continue: aBlock
  547. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  548. ! !