Compiler-Interpreter.st 5.8 KB

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