Compiler-Interpreter.st 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. console log: aNode.
  90. self interpretNode: aNode continue: [ :value |
  91. self continue: aBlock value: value] ]
  92. ifFalse: [ self continue: aBlock value: aNode ]
  93. !
  94. interpretAssignmentNode: aNode continue: aBlock
  95. self interpret: aNode right continue: [ :value |
  96. self
  97. continue: aBlock
  98. value: (self assign: aNode left to: value) ]
  99. !
  100. interpretBlockNode: aNode continue: aBlock
  101. "TODO: Context should be set"
  102. self
  103. continue: aBlock
  104. value: [ self interpret: aNode nodes first; result ]
  105. !
  106. interpretBlockSequenceNode: aNode continue: aBlock
  107. self interpretSequenceNode: aNode continue: aBlock
  108. !
  109. interpretCascadeNode: aNode continue: aBlock
  110. "TODO: Handle super sends"
  111. self interpret: aNode receiver continue: [ :receiver |
  112. "Only interpret the receiver once"
  113. aNode nodes do: [ :each | each receiver: receiver ].
  114. self
  115. interpretAll: aNode nodes allButLast
  116. continue: [
  117. self
  118. interpret: aNode nodes last
  119. continue: [ :val | self continue: aBlock value: val ] ] ]
  120. !
  121. interpretClassReferenceNode: aNode continue: aBlock
  122. self continue: aBlock value: (Smalltalk current at: aNode value)
  123. !
  124. interpretDynamicArrayNode: aNode continue: aBlock
  125. self interpretAll: aNode nodes continue: [ :array |
  126. self
  127. continue: aBlock
  128. value: array ]
  129. !
  130. interpretDynamicDictionaryNode: aNode continue: aBlock
  131. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  132. hashedCollection := HashedCollection new.
  133. array do: [ :each | hashedCollection add: each ].
  134. self
  135. continue: aBlock
  136. value: hashedCollection ]
  137. !
  138. interpretJSStatementNode: aNode continue: aBlock
  139. shouldReturn := true.
  140. self continue: aBlock value: (self eval: aNode source)
  141. !
  142. interpretMethodNode: aNode continue: aBlock
  143. self interpretAll: aNode nodes continue: [ :array |
  144. self continue: aBlock value: array first ]
  145. !
  146. interpretNode: aNode continue: aBlock
  147. aNode interpreter: self continue: aBlock
  148. !
  149. interpretReturnNode: aNode continue: aBlock
  150. self interpret: aNode nodes first continue: [ :value |
  151. shouldReturn := true.
  152. self continue: aBlock value: value ]
  153. !
  154. interpretSendNode: aNode continue: aBlock
  155. "TODO: Handle super sends"
  156. self interpret: aNode receiver continue: [ :receiver |
  157. self interpretAll: aNode arguments continue: [ :args |
  158. self
  159. messageFromSendNode: aNode
  160. arguments: args
  161. do: [ :message |
  162. self context pc: self context pc + 1.
  163. self
  164. continue: aBlock
  165. value: (message sendTo: receiver) ] ] ]
  166. !
  167. interpretSequenceNode: aNode continue: aBlock
  168. self interpretAll: aNode nodes continue: [ :array |
  169. self continue: aBlock value: array last ]
  170. !
  171. interpretValueNode: aNode continue: aBlock
  172. self continue: aBlock value: aNode value
  173. !
  174. interpretVariableNode: aNode continue: aBlock
  175. self
  176. continue: aBlock
  177. value: (aNode binding isInstanceVar
  178. ifTrue: [ self context receiver instVarAt: aNode value ]
  179. ifFalse: [ self context localAt: aNode value ])
  180. ! !
  181. !ASTInterpreter methodsFor: 'private'!
  182. assign: aNode to: anObject
  183. ^ aNode binding isInstanceVar
  184. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  185. ifFalse: [ self context localAt: aNode value put: anObject ]
  186. !
  187. continue: aBlock value: anObject
  188. result := anObject.
  189. aBlock value: anObject
  190. !
  191. eval: aString
  192. "Evaluate aString as JS source inside an JS function.
  193. aString is not sandboxed."
  194. | source function |
  195. source := String streamContents: [ :str |
  196. str nextPutAll: '(function('.
  197. self context locals keys
  198. do: [ :each | str nextPutAll: each ]
  199. separatedBy: [ str nextPutAll: ',' ].
  200. str
  201. nextPutAll: '){ return (function() {';
  202. nextPutAll: aString;
  203. nextPutAll: '})() })' ].
  204. function := Compiler new eval: source.
  205. ^ function valueWithPossibleArguments: self context locals values
  206. !
  207. interpretAll: aCollection continue: aBlock
  208. self
  209. interpretAll: aCollection
  210. continue: aBlock
  211. result: OrderedCollection new
  212. !
  213. interpretAll: nodes continue: aBlock result: aCollection
  214. nodes isEmpty
  215. ifTrue: [ self continue: aBlock value: aCollection ]
  216. ifFalse: [
  217. self interpret: nodes first continue: [:value |
  218. self
  219. interpretAll: nodes allButFirst
  220. continue: aBlock
  221. result: aCollection, { value } ] ]
  222. !
  223. messageFromSendNode: aSendNode arguments: aCollection do: aBlock
  224. self
  225. continue: aBlock
  226. value: (Message new
  227. selector: aSendNode selector;
  228. arguments: aCollection;
  229. yourself)
  230. ! !
  231. ASTInterpreter subclass: #ASTSteppingInterpreter
  232. instanceVariableNames: 'continuation'
  233. package: 'Compiler-Interpreter'!
  234. !ASTSteppingInterpreter commentStamp!
  235. ASTSteppingInterpreter is an interpreter with stepping capabilities.
  236. Use `#step` to actually interpret the next node.
  237. Usage example:
  238. | ast interpreter |
  239. ast := Smalltalk current parse: 'foo 1+2+4'.
  240. (SemanticAnalyzer on: Object) visit: ast.
  241. interpreter := ASTSteppingInterpreter new
  242. interpret: ast nodes first;
  243. yourself.
  244. debugger step; step.
  245. debugger step; step.
  246. debugger result."Answers 1"
  247. debugger step.
  248. debugger result. "Answers 3"
  249. debugger step.
  250. debugger result. "Answers 7"!
  251. !ASTSteppingInterpreter methodsFor: 'initialization'!
  252. initialize
  253. super initialize.
  254. continuation := [ ]
  255. ! !
  256. !ASTSteppingInterpreter methodsFor: 'interpreting'!
  257. interpret: aNode continue: aBlock
  258. continuation := [ super interpret: aNode continue: aBlock ]
  259. ! !
  260. !ASTSteppingInterpreter methodsFor: 'stepping'!
  261. step
  262. continuation value
  263. ! !
  264. !Node methodsFor: '*Compiler-Interpreter'!
  265. interpreter: anInterpreter continue: aBlock
  266. ^ anInterpreter interpretNode: self continue: aBlock
  267. ! !
  268. !AssignmentNode methodsFor: '*Compiler-Interpreter'!
  269. interpreter: anInterpreter continue: aBlock
  270. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  271. ! !
  272. !BlockNode methodsFor: '*Compiler-Interpreter'!
  273. interpreter: anInterpreter continue: aBlock
  274. ^ anInterpreter interpretBlockNode: self continue: aBlock
  275. ! !
  276. !CascadeNode methodsFor: '*Compiler-Interpreter'!
  277. interpreter: anInterpreter continue: aBlock
  278. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  279. ! !
  280. !DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
  281. interpreter: anInterpreter continue: aBlock
  282. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  283. ! !
  284. !DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
  285. interpreter: anInterpreter continue: aBlock
  286. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  287. ! !
  288. !JSStatementNode methodsFor: '*Compiler-Interpreter'!
  289. interpreter: anInterpreter continue: aBlock
  290. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  291. ! !
  292. !MethodNode methodsFor: '*Compiler-Interpreter'!
  293. interpreter: anInterpreter continue: aBlock
  294. ^ anInterpreter interpretMethodNode: self continue: aBlock
  295. ! !
  296. !ReturnNode methodsFor: '*Compiler-Interpreter'!
  297. interpreter: anInterpreter continue: aBlock
  298. ^ anInterpreter interpretReturnNode: self continue: aBlock
  299. ! !
  300. !SendNode methodsFor: '*Compiler-Interpreter'!
  301. interpreter: anInterpreter continue: aBlock
  302. ^ anInterpreter interpretSendNode: self continue: aBlock
  303. ! !
  304. !SequenceNode methodsFor: '*Compiler-Interpreter'!
  305. interpreter: anInterpreter continue: aBlock
  306. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  307. ! !
  308. !BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
  309. interpreter: anInterpreter continue: aBlock
  310. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  311. ! !
  312. !ValueNode methodsFor: '*Compiler-Interpreter'!
  313. interpreter: anInterpreter continue: aBlock
  314. ^ anInterpreter interpretValueNode: self continue: aBlock
  315. ! !
  316. !VariableNode methodsFor: '*Compiler-Interpreter'!
  317. interpreter: anInterpreter continue: aBlock
  318. ^ anInterpreter interpretVariableNode: self continue: aBlock
  319. ! !
  320. !ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
  321. interpreter: anInterpreter continue: aBlock
  322. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  323. ! !