1
0

Compiler-Interpreter.st 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. Smalltalk current createPackage: 'Compiler-Interpreter' properties: #{}!
  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: aContext
  74. context := AIContext new.
  75. !
  76. interpreter
  77. ^ interpreter ifNil: [ interpreter := self defaultInterpreter ]
  78. !
  79. interpreter: anInterpreter
  80. interpreter := anInterpreter
  81. !
  82. method
  83. ^ self context method
  84. ! !
  85. !ASTDebugger methodsFor: 'defaults'!
  86. defaultInterpreter
  87. ^ ASTSteppingInterpreter new
  88. ! !
  89. !ASTDebugger methodsFor: 'initialization'!
  90. initializeWithContext: aMethodContext
  91. "TODO: do we need to handle block contexts?"
  92. self context: IAContext fromMethodContext: aMethodContext
  93. ! !
  94. !ASTDebugger methodsFor: 'stepping'!
  95. restart
  96. self shouldBeImplemented
  97. !
  98. resume
  99. self shouldBeImplemented
  100. !
  101. stepInto
  102. self shouldBeImplemented
  103. !
  104. stepOver
  105. self shouldBeImplemented
  106. ! !
  107. !ASTDebugger class methodsFor: 'instance creation'!
  108. context: aMethodContext
  109. ^ self new
  110. initializeWithContext: aMethodContext;
  111. yourself
  112. ! !
  113. Object subclass: #ASTInterpreter
  114. instanceVariableNames: 'currentNode context shouldReturn result'
  115. package: 'Compiler-Interpreter'!
  116. !ASTInterpreter commentStamp!
  117. ASTIntepreter is like a `NodeVisitor`, interpreting nodes one after each other.
  118. It is built using Continuation Passing Style for stepping purposes.
  119. Usage example:
  120. | ast interpreter |
  121. ast := Smalltalk current parse: 'foo 1+2+4'.
  122. (SemanticAnalyzer on: Object) visit: ast.
  123. ASTInterpreter new
  124. interpret: ast nodes first;
  125. result "Answers 7"!
  126. !ASTInterpreter methodsFor: 'accessing'!
  127. context
  128. ^ context ifNil: [ context := AIContext new ]
  129. !
  130. context: anAIContext
  131. context := anAIContext
  132. !
  133. currentNode
  134. ^ currentNode
  135. !
  136. result
  137. ^ result
  138. ! !
  139. !ASTInterpreter methodsFor: 'initialization'!
  140. initialize
  141. super initialize.
  142. shouldReturn := false
  143. ! !
  144. !ASTInterpreter methodsFor: 'interpreting'!
  145. interpret: aNode
  146. shouldReturn := false.
  147. self interpret: aNode continue: [ :value |
  148. result := value ]
  149. !
  150. interpret: aNode continue: aBlock
  151. shouldReturn ifTrue: [ ^ self ].
  152. aNode isNode
  153. ifTrue: [
  154. currentNode := aNode.
  155. self interpretNode: aNode continue: [ :value |
  156. self continue: aBlock value: value] ]
  157. ifFalse: [ self continue: aBlock value: aNode ]
  158. !
  159. interpretAssignmentNode: aNode continue: aBlock
  160. self interpret: aNode right continue: [ :value |
  161. self
  162. continue: aBlock
  163. value: (self assign: aNode left to: value) ]
  164. !
  165. interpretBlockNode: aNode continue: aBlock
  166. "TODO: Context should be set"
  167. self
  168. continue: aBlock
  169. value: [ self interpret: aNode nodes first; result ]
  170. !
  171. interpretBlockSequenceNode: aNode continue: aBlock
  172. self interpretSequenceNode: aNode continue: aBlock
  173. !
  174. interpretCascadeNode: aNode continue: aBlock
  175. "TODO: Handle super sends"
  176. self interpret: aNode receiver continue: [ :receiver |
  177. "Only interpret the receiver once"
  178. aNode nodes do: [ :each | each receiver: receiver ].
  179. self
  180. interpretAll: aNode nodes allButLast
  181. continue: [
  182. self
  183. interpret: aNode nodes last
  184. continue: [ :val | self continue: aBlock value: val ] ] ]
  185. !
  186. interpretClassReferenceNode: aNode continue: aBlock
  187. self continue: aBlock value: (Smalltalk current at: aNode value)
  188. !
  189. interpretDynamicArrayNode: aNode continue: aBlock
  190. self interpretAll: aNode nodes continue: [ :array |
  191. self
  192. continue: aBlock
  193. value: array ]
  194. !
  195. interpretDynamicDictionaryNode: aNode continue: aBlock
  196. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  197. hashedCollection := HashedCollection new.
  198. array do: [ :each | hashedCollection add: each ].
  199. self
  200. continue: aBlock
  201. value: hashedCollection ]
  202. !
  203. interpretJSStatementNode: aNode continue: aBlock
  204. shouldReturn := true.
  205. self continue: aBlock value: (self eval: aNode source)
  206. !
  207. interpretMethodNode: aNode continue: aBlock
  208. self interpretAll: aNode nodes continue: [ :array |
  209. self continue: aBlock value: array first ]
  210. !
  211. interpretNode: aNode continue: aBlock
  212. aNode interpreter: self continue: aBlock
  213. !
  214. interpretReturnNode: aNode continue: aBlock
  215. self interpret: aNode nodes first continue: [ :value |
  216. shouldReturn := true.
  217. self continue: aBlock value: value ]
  218. !
  219. interpretSendNode: aNode continue: aBlock
  220. "TODO: Handle super sends"
  221. self interpret: aNode receiver continue: [ :receiver |
  222. self interpretAll: aNode arguments continue: [ :args |
  223. self
  224. messageFromSendNode: aNode
  225. arguments: args
  226. do: [ :message |
  227. self context pc: self context pc + 1.
  228. self
  229. continue: aBlock
  230. value: (message sendTo: receiver) ] ] ]
  231. !
  232. interpretSequenceNode: aNode continue: aBlock
  233. self interpretAll: aNode nodes continue: [ :array |
  234. self continue: aBlock value: array last ]
  235. !
  236. interpretValueNode: aNode continue: aBlock
  237. self continue: aBlock value: aNode value
  238. !
  239. interpretVariableNode: aNode continue: aBlock
  240. self
  241. continue: aBlock
  242. value: (aNode binding isInstanceVar
  243. ifTrue: [ self context receiver instVarAt: aNode value ]
  244. ifFalse: [ self context localAt: aNode value ])
  245. ! !
  246. !ASTInterpreter methodsFor: 'private'!
  247. assign: aNode to: anObject
  248. ^ aNode binding isInstanceVar
  249. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  250. ifFalse: [ self context localAt: aNode value put: anObject ]
  251. !
  252. continue: aBlock value: anObject
  253. result := anObject.
  254. aBlock value: anObject
  255. !
  256. eval: aString
  257. "Evaluate aString as JS source inside an JS function.
  258. aString is not sandboxed."
  259. | source function |
  260. source := String streamContents: [ :str |
  261. str nextPutAll: '(function('.
  262. self context locals keys
  263. do: [ :each | str nextPutAll: each ]
  264. separatedBy: [ str nextPutAll: ',' ].
  265. str
  266. nextPutAll: '){ return (function() {';
  267. nextPutAll: aString;
  268. nextPutAll: '})() })' ].
  269. function := Compiler new eval: source.
  270. ^ function valueWithPossibleArguments: self context locals values
  271. !
  272. interpretAll: aCollection continue: aBlock
  273. self
  274. interpretAll: aCollection
  275. continue: aBlock
  276. result: OrderedCollection new
  277. !
  278. interpretAll: nodes continue: aBlock result: aCollection
  279. nodes isEmpty
  280. ifTrue: [ self continue: aBlock value: aCollection ]
  281. ifFalse: [
  282. self interpret: nodes first continue: [:value |
  283. self
  284. interpretAll: nodes allButFirst
  285. continue: aBlock
  286. result: aCollection, { value } ] ]
  287. !
  288. messageFromSendNode: aSendNode arguments: aCollection do: aBlock
  289. self
  290. continue: aBlock
  291. value: (Message new
  292. selector: aSendNode selector;
  293. arguments: aCollection;
  294. yourself)
  295. ! !
  296. ASTInterpreter subclass: #ASTSteppingInterpreter
  297. instanceVariableNames: 'continuation'
  298. package: 'Compiler-Interpreter'!
  299. !ASTSteppingInterpreter commentStamp!
  300. ASTSteppingInterpreter is an interpreter with stepping capabilities.
  301. Use `#step` to actually interpret the next node.
  302. Usage example:
  303. | ast interpreter |
  304. ast := Smalltalk current parse: 'foo 1+2+4'.
  305. (SemanticAnalyzer on: Object) visit: ast.
  306. interpreter := ASTSteppingInterpreter new
  307. interpret: ast nodes first;
  308. yourself.
  309. debugger step; step.
  310. debugger step; step.
  311. debugger result."Answers 1"
  312. debugger step.
  313. debugger result. "Answers 3"
  314. debugger step.
  315. debugger result. "Answers 7"!
  316. !ASTSteppingInterpreter methodsFor: 'initialization'!
  317. initialize
  318. super initialize.
  319. continuation := [ ]
  320. ! !
  321. !ASTSteppingInterpreter methodsFor: 'interpreting'!
  322. interpret: aNode continue: aBlock
  323. continuation := [ super interpret: aNode continue: aBlock ]
  324. ! !
  325. !ASTSteppingInterpreter methodsFor: 'stepping'!
  326. step
  327. continuation value
  328. ! !
  329. !Node methodsFor: '*Compiler-Interpreter'!
  330. interpreter: anInterpreter continue: aBlock
  331. ^ anInterpreter interpretNode: self continue: aBlock
  332. ! !
  333. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  334. interpreter: anInterpreter continue: aBlock
  335. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  336. ! !
  337. !BlockNode methodsFor: '*Compiler-Interpreter'!
  338. interpreter: anInterpreter continue: aBlock
  339. ^ anInterpreter interpretBlockNode: self continue: aBlock
  340. ! !
  341. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  342. interpreter: anInterpreter continue: aBlock
  343. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  344. ! !
  345. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  346. interpreter: anInterpreter continue: aBlock
  347. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  348. ! !
  349. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  350. interpreter: anInterpreter continue: aBlock
  351. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  352. ! !
  353. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  354. interpreter: anInterpreter continue: aBlock
  355. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  356. ! !
  357. !MethodNode methodsFor: '*Compiler-Interpreter'!
  358. interpreter: anInterpreter continue: aBlock
  359. ^ anInterpreter interpretMethodNode: self continue: aBlock
  360. ! !
  361. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  362. interpreter: anInterpreter continue: aBlock
  363. ^ anInterpreter interpretReturnNode: self continue: aBlock
  364. ! !
  365. !SendNode methodsFor: '*Compiler-Interpreter'!
  366. interpreter: anInterpreter continue: aBlock
  367. ^ anInterpreter interpretSendNode: self continue: aBlock
  368. ! !
  369. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  370. interpreter: anInterpreter continue: aBlock
  371. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  372. ! !
  373. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  374. interpreter: anInterpreter continue: aBlock
  375. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  376. ! !
  377. !ValueNode methodsFor: '*Compiler-Interpreter'!
  378. interpreter: anInterpreter continue: aBlock
  379. ^ anInterpreter interpretValueNode: self continue: aBlock
  380. ! !
  381. !VariableNode methodsFor: '*Compiler-Interpreter'!
  382. interpreter: anInterpreter continue: aBlock
  383. ^ anInterpreter interpretVariableNode: self continue: aBlock
  384. ! !
  385. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  386. interpreter: anInterpreter continue: aBlock
  387. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  388. ! !