1
0

Compiler-Interpreter.st 13 KB

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