Compiler-Interpreter.st 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. Smalltalk current createPackage: 'Compiler-Interpreter' properties: #{}!
  2. NodeVisitor subclass: #AIContext
  3. instanceVariableNames: 'outerContext pc locals selector'
  4. package: 'Compiler-Interpreter'!
  5. !AIContext methodsFor: 'accessing'!
  6. localAt: aString
  7. ^ self locals at: aString ifAbsent: [ nil ]
  8. !
  9. localAt: aString put: anObject
  10. self locals at: aString put: anObject
  11. !
  12. locals
  13. ^ locals ifNil: [ locals := Dictionary new ]
  14. !
  15. outerContext
  16. ^ outerContext
  17. !
  18. outerContext: anAIContext
  19. outerContext := anAIContext
  20. !
  21. pc
  22. ^ pc ifNil: [ pc := 0 ]
  23. !
  24. pc: anInteger
  25. pc := anInteger
  26. !
  27. receiver
  28. ^ self localAt: 'self'
  29. !
  30. receiver: anObject
  31. self localAt: 'self' put: anObject
  32. ! !
  33. !AIContext methodsFor: 'initialization'!
  34. initializeFromMethodContext: aMethodContext
  35. self pc: aMethodContext pc.
  36. self receiver: aMethodContext receiver.
  37. self selector: aMethodContext selector.
  38. aMethodContext outerContext ifNotNil: [
  39. self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
  40. aMethodContext locals keysAndValuesDo: [ :key :value |
  41. self locals at: key put: value ]
  42. ! !
  43. NodeVisitor subclass: #ASTInterpreter
  44. instanceVariableNames: 'currentNode context shouldReturn currentValue'
  45. package: 'Compiler-Interpreter'!
  46. !ASTInterpreter methodsFor: 'accessing'!
  47. context
  48. ^ context ifNil: [ context := AIContext new ]
  49. !
  50. context: anAIContext
  51. context := anAIContext
  52. !
  53. currentValue
  54. ^ currentValue
  55. ! !
  56. !ASTInterpreter methodsFor: 'initialization'!
  57. initialize
  58. super initialize.
  59. shouldReturn := false
  60. ! !
  61. !ASTInterpreter methodsFor: 'interpreting'!
  62. assign: aNode to: anObject
  63. ^ aNode binding isInstanceVar
  64. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  65. ifFalse: [ self context localAt: aNode value put: anObject ]
  66. !
  67. continue: anObject
  68. currentValue := anObject
  69. !
  70. eval: aString
  71. "Evaluate aString as JS source inside an JS function.
  72. aString is not sandboxed."
  73. | source function |
  74. source := String streamContents: [ :str |
  75. str nextPutAll: '(function('.
  76. self context locals keys
  77. do: [ :each | str nextPutAll: each ]
  78. separatedBy: [ str nextPutAll: ',' ].
  79. str
  80. nextPutAll: '){ return (function() {';
  81. nextPutAll: aString;
  82. nextPutAll: '})() })' ].
  83. function := Compiler new eval: source.
  84. ^ function valueWithPossibleArguments: self context locals values
  85. !
  86. interpret: aNode
  87. shouldReturn := false.
  88. self interpret: aNode continue: [ :value |
  89. currentValue := value ]
  90. !
  91. interpret: aNode continue: aBlock
  92. shouldReturn ifTrue: [ ^ self ].
  93. aNode isNode
  94. ifTrue: [ self visit: aNode ]
  95. ifFalse: [ currentValue := aNode ].
  96. aBlock value: self currentValue
  97. !
  98. interpretAll: aCollection continue: aBlock
  99. self
  100. interpretAll: aCollection
  101. continue: aBlock
  102. result: OrderedCollection new
  103. !
  104. interpretAll: nodes continue: aBlock result: aCollection
  105. nodes isEmpty
  106. ifTrue: [ aBlock value: aCollection ]
  107. ifFalse: [
  108. self interpret: nodes first continue: [:value |
  109. self
  110. interpretAll: nodes allButFirst
  111. continue: aBlock
  112. result: aCollection, { value } ] ]
  113. !
  114. messageFromSendNode: aSendNode do: aBlock
  115. self interpretAll: aSendNode arguments continue: [ :args |
  116. aBlock value: (Message new
  117. selector: aSendNode selector;
  118. arguments: args;
  119. yourself) ]
  120. ! !
  121. !ASTInterpreter methodsFor: 'visiting'!
  122. visitAssignmentNode: aNode
  123. self interpret: aNode right continue: [ :value |
  124. self continue: (self assign: aNode left to: value) ]
  125. !
  126. visitBlockNode: aNode
  127. "TODO: Context should be set"
  128. self continue: [ self interpret: aNode nodes first; currentValue ]
  129. !
  130. visitCascadeNode: aNode
  131. "TODO: Handle super sends"
  132. self interpret: aNode receiver continue: [ :receiver |
  133. "Only interpret the receiver once"
  134. aNode nodes do: [ :each | each receiver: receiver ].
  135. self
  136. interpretAll: aNode nodes allButLast
  137. continue: [
  138. self
  139. interpret: aNode nodes last
  140. continue: [ :val | self continue: val ] ] ]
  141. !
  142. visitClassReferenceNode: aNode
  143. self continue: (Smalltalk current at: aNode value)
  144. !
  145. visitDynamicArrayNode: aNode
  146. self interpretAll: aNode nodes continue: [ :array |
  147. self continue: array ]
  148. !
  149. visitDynamicDictionaryNode: aNode
  150. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  151. hashedCollection := HashedCollection new.
  152. array do: [ :each | hashedCollection add: each ].
  153. self continue: hashedCollection ]
  154. !
  155. visitJSStatementNode: aNode
  156. shouldReturn := true.
  157. self continue: (self eval: aNode source)
  158. !
  159. visitReturnNode: aNode
  160. self interpret: aNode nodes first continue: [ :value |
  161. shouldReturn := true.
  162. self continue: value ]
  163. !
  164. visitSendNode: aNode
  165. "TODO: Handle super sends"
  166. self interpret: aNode receiver continue: [ :receiver |
  167. self messageFromSendNode: aNode do: [ :message |
  168. self context pc: self context pc + 1.
  169. self continue: (message sendTo: receiver) ] ]
  170. !
  171. visitSequenceNode: aNode
  172. self interpretAll: aNode nodes continue: [ :array |
  173. self continue: array last ]
  174. !
  175. visitValueNode: aNode
  176. self continue: aNode value
  177. !
  178. visitVariableNode: aNode
  179. self continue: (aNode binding isInstanceVar
  180. ifTrue: [ self context receiver instVarAt: aNode value ]
  181. ifFalse: [ self context localAt: aNode value ])
  182. ! !
  183. ASTInterpreter subclass: #ASTDebugger
  184. instanceVariableNames: 'continuation'
  185. package: 'Compiler-Interpreter'!
  186. !ASTDebugger methodsFor: 'initialization'!
  187. initialize
  188. super initialize.
  189. continuation := [ ]
  190. ! !
  191. !ASTDebugger methodsFor: 'interpreting'!
  192. interpret: aNode continue: aBlock
  193. continuation := [ super interpret: aNode continue: aBlock ]
  194. ! !
  195. !ASTDebugger methodsFor: 'stepping'!
  196. stepOver
  197. continuation value
  198. ! !