Compiler-Interpreter.st 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. Smalltalk current createPackage: 'Compiler-Interpreter' properties: #{}!
  2. NodeVisitor subclass: #AIContext
  3. instanceVariableNames: 'outerContext pc locals selector'
  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. outerContext
  20. ^ outerContext
  21. !
  22. outerContext: anAIContext
  23. outerContext := anAIContext
  24. !
  25. pc
  26. ^ pc ifNil: [ pc := 0 ]
  27. !
  28. pc: anInteger
  29. pc := anInteger
  30. !
  31. receiver
  32. ^ self localAt: 'self'
  33. !
  34. receiver: anObject
  35. self localAt: 'self' put: anObject
  36. ! !
  37. !AIContext methodsFor: 'initialization'!
  38. initializeFromMethodContext: aMethodContext
  39. self pc: aMethodContext pc.
  40. self receiver: aMethodContext receiver.
  41. self selector: aMethodContext selector.
  42. aMethodContext outerContext ifNotNil: [
  43. self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
  44. aMethodContext locals keysAndValuesDo: [ :key :value |
  45. self locals at: key put: value ]
  46. ! !
  47. Object subclass: #ASTInterpreter
  48. instanceVariableNames: 'currentNode context shouldReturn result'
  49. package: 'Compiler-Interpreter'!
  50. !ASTInterpreter commentStamp!
  51. ASTIntepreter is like a `NodeVisitor`, interpreting nodes one after each other.
  52. It is built using Continuation Passing Style for stepping purposes.
  53. Usage example:
  54. | ast interpreter |
  55. ast := Smalltalk current parse: 'foo 1+2+4'.
  56. (SemanticAnalyzer on: Object) visit: ast.
  57. ASTInterpreter new
  58. interpret: ast nodes first;
  59. result "Answers 7"!
  60. !ASTInterpreter methodsFor: 'accessing'!
  61. context
  62. ^ context ifNil: [ context := AIContext new ]
  63. !
  64. context: anAIContext
  65. context := anAIContext
  66. !
  67. currentNode
  68. ^ currentNode
  69. !
  70. result
  71. ^ result
  72. ! !
  73. !ASTInterpreter methodsFor: 'initialization'!
  74. initialize
  75. super initialize.
  76. shouldReturn := false
  77. ! !
  78. !ASTInterpreter methodsFor: 'interpreting'!
  79. interpret: aNode
  80. shouldReturn := false.
  81. self interpret: aNode continue: [ :value |
  82. result := value ]
  83. !
  84. interpret: aNode continue: aBlock
  85. shouldReturn ifTrue: [ ^ self ].
  86. aNode isNode
  87. ifTrue: [
  88. currentNode := aNode.
  89. self interpretNode: aNode continue: [ :value |
  90. self continue: aBlock value: value] ]
  91. ifFalse: [ self continue: aBlock value: aNode ]
  92. !
  93. interpretAssignmentNode: aNode continue: aBlock
  94. self interpret: aNode right continue: [ :value |
  95. self
  96. continue: aBlock
  97. value: (self assign: aNode left to: value) ]
  98. !
  99. interpretBlockNode: aNode continue: aBlock
  100. "TODO: Context should be set"
  101. self
  102. continue: aBlock
  103. value: [ self interpret: aNode nodes first; result ]
  104. !
  105. interpretBlockSequenceNode: aNode continue: aBlock
  106. self interpretSequenceNode: aNode continue: aBlock
  107. !
  108. interpretCascadeNode: aNode continue: aBlock
  109. "TODO: Handle super sends"
  110. self interpret: aNode receiver continue: [ :receiver |
  111. "Only interpret the receiver once"
  112. aNode nodes do: [ :each | each receiver: receiver ].
  113. self
  114. interpretAll: aNode nodes allButLast
  115. continue: [
  116. self
  117. interpret: aNode nodes last
  118. continue: [ :val | self continue: aBlock value: val ] ] ]
  119. !
  120. interpretClassReferenceNode: aNode continue: aBlock
  121. self continue: aBlock value: (Smalltalk current at: aNode value)
  122. !
  123. interpretDynamicArrayNode: aNode continue: aBlock
  124. self interpretAll: aNode nodes continue: [ :array |
  125. self
  126. continue: aBlock
  127. value: array ]
  128. !
  129. interpretDynamicDictionaryNode: aNode continue: aBlock
  130. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  131. hashedCollection := HashedCollection new.
  132. array do: [ :each | hashedCollection add: each ].
  133. self
  134. continue: aBlock
  135. value: hashedCollection ]
  136. !
  137. interpretJSStatementNode: aNode continue: aBlock
  138. shouldReturn := true.
  139. self continue: aBlock value: (self eval: aNode source)
  140. !
  141. interpretMethodNode: aNode continue: aBlock
  142. self interpretAll: aNode nodes continue: [ :array |
  143. self continue: aBlock value: array first ]
  144. !
  145. interpretNode: aNode continue: aBlock
  146. aNode interpreter: self continue: aBlock
  147. !
  148. interpretReturnNode: aNode continue: aBlock
  149. self interpret: aNode nodes first continue: [ :value |
  150. shouldReturn := true.
  151. self continue: aBlock value: value ]
  152. !
  153. interpretSendNode: aNode continue: aBlock
  154. "TODO: Handle super sends"
  155. self interpret: aNode receiver continue: [ :receiver |
  156. self interpretAll: aNode arguments continue: [ :args |
  157. self
  158. messageFromSendNode: aNode
  159. arguments: args
  160. do: [ :message |
  161. self context pc: self context pc + 1.
  162. self
  163. continue: aBlock
  164. value: (message sendTo: receiver) ] ] ]
  165. !
  166. interpretSequenceNode: aNode continue: aBlock
  167. self interpretAll: aNode nodes continue: [ :array |
  168. self continue: aBlock value: array last ]
  169. !
  170. interpretValueNode: aNode continue: aBlock
  171. self continue: aBlock value: aNode value
  172. !
  173. interpretVariableNode: aNode continue: aBlock
  174. self
  175. continue: aBlock
  176. value: (aNode binding isInstanceVar
  177. ifTrue: [ self context receiver instVarAt: aNode value ]
  178. ifFalse: [ self context localAt: aNode value ])
  179. ! !
  180. !ASTInterpreter methodsFor: 'private'!
  181. assign: aNode to: anObject
  182. ^ aNode binding isInstanceVar
  183. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  184. ifFalse: [ self context localAt: aNode value put: anObject ]
  185. !
  186. continue: aBlock value: anObject
  187. result := anObject.
  188. aBlock value: anObject
  189. !
  190. eval: aString
  191. "Evaluate aString as JS source inside an JS function.
  192. aString is not sandboxed."
  193. | source function |
  194. source := String streamContents: [ :str |
  195. str nextPutAll: '(function('.
  196. self context locals keys
  197. do: [ :each | str nextPutAll: each ]
  198. separatedBy: [ str nextPutAll: ',' ].
  199. str
  200. nextPutAll: '){ return (function() {';
  201. nextPutAll: aString;
  202. nextPutAll: '})() })' ].
  203. function := Compiler new eval: source.
  204. ^ function valueWithPossibleArguments: self context locals values
  205. !
  206. interpretAll: aCollection continue: aBlock
  207. self
  208. interpretAll: aCollection
  209. continue: aBlock
  210. result: OrderedCollection new
  211. !
  212. interpretAll: nodes continue: aBlock result: aCollection
  213. nodes isEmpty
  214. ifTrue: [ self continue: aBlock value: aCollection ]
  215. ifFalse: [
  216. self interpret: nodes first continue: [:value |
  217. self
  218. interpretAll: nodes allButFirst
  219. continue: aBlock
  220. result: aCollection, { value } ] ]
  221. !
  222. messageFromSendNode: aSendNode arguments: aCollection do: aBlock
  223. self
  224. continue: aBlock
  225. value: (Message new
  226. selector: aSendNode selector;
  227. arguments: aCollection;
  228. yourself)
  229. ! !
  230. ASTInterpreter subclass: #ASTSteppingInterpreter
  231. instanceVariableNames: 'continuation'
  232. package: 'Compiler-Interpreter'!
  233. !ASTSteppingInterpreter commentStamp!
  234. ASTSteppingInterpreter is an interpreter with stepping capabilities.
  235. Use `#step` to actually interpret the next node.
  236. Usage example:
  237. | ast interpreter |
  238. ast := Smalltalk current parse: 'foo 1+2+4'.
  239. (SemanticAnalyzer on: Object) visit: ast.
  240. interpreter := ASTSteppingInterpreter new
  241. interpret: ast nodes first;
  242. yourself.
  243. debugger step; step.
  244. debugger step; step.
  245. debugger result."Answers 1"
  246. debugger step.
  247. debugger result. "Answers 3"
  248. debugger step.
  249. debugger result. "Answers 7"!
  250. !ASTSteppingInterpreter methodsFor: 'initialization'!
  251. initialize
  252. super initialize.
  253. continuation := [ ]
  254. ! !
  255. !ASTSteppingInterpreter methodsFor: 'interpreting'!
  256. interpret: aNode continue: aBlock
  257. continuation := [ super interpret: aNode continue: aBlock ]
  258. ! !
  259. !ASTSteppingInterpreter methodsFor: 'stepping'!
  260. step
  261. continuation value
  262. ! !
  263. !Node methodsFor: '*Compiler-Interpreter'!
  264. interpreter: anInterpreter continue: aBlock
  265. ^ anInterpreter interpretNode: self continue: aBlock
  266. ! !
  267. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  268. interpreter: anInterpreter continue: aBlock
  269. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  270. ! !
  271. !BlockNode methodsFor: '*Compiler-Interpreter'!
  272. interpreter: anInterpreter continue: aBlock
  273. ^ anInterpreter interpretBlockNode: self continue: aBlock
  274. ! !
  275. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  276. interpreter: anInterpreter continue: aBlock
  277. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  278. ! !
  279. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  280. interpreter: anInterpreter continue: aBlock
  281. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  282. ! !
  283. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  284. interpreter: anInterpreter continue: aBlock
  285. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  286. ! !
  287. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  288. interpreter: anInterpreter continue: aBlock
  289. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  290. ! !
  291. !MethodNode methodsFor: '*Compiler-Interpreter'!
  292. interpreter: anInterpreter continue: aBlock
  293. ^ anInterpreter interpretMethodNode: self continue: aBlock
  294. ! !
  295. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  296. interpreter: anInterpreter continue: aBlock
  297. ^ anInterpreter interpretReturnNode: self continue: aBlock
  298. ! !
  299. !SendNode methodsFor: '*Compiler-Interpreter'!
  300. interpreter: anInterpreter continue: aBlock
  301. ^ anInterpreter interpretSendNode: self continue: aBlock
  302. ! !
  303. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  304. interpreter: anInterpreter continue: aBlock
  305. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  306. ! !
  307. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  308. interpreter: anInterpreter continue: aBlock
  309. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  310. ! !
  311. !ValueNode methodsFor: '*Compiler-Interpreter'!
  312. interpreter: anInterpreter continue: aBlock
  313. ^ anInterpreter interpretValueNode: self continue: aBlock
  314. ! !
  315. !VariableNode methodsFor: '*Compiler-Interpreter'!
  316. interpreter: anInterpreter continue: aBlock
  317. ^ anInterpreter interpretVariableNode: self continue: aBlock
  318. ! !
  319. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  320. interpreter: anInterpreter continue: aBlock
  321. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  322. ! !