1
0

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