1
0

Compiler-Interpreter.st 10 KB

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