Compiler-Interpreter.st 13 KB

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