ソースを参照

ASTInterpreter cleanup

Nicolas Petton 11 年 前
コミット
9aea897f28
4 ファイル変更319 行追加2225 行削除
  1. 181 1260
      js/Compiler-Interpreter.js
  2. 46 381
      js/Compiler-Tests.js
  3. 90 423
      st/Compiler-Interpreter.st
  4. 2 161
      st/Compiler-Tests.st

ファイルの差分が大きいため隠しています
+ 181 - 1260
js/Compiler-Interpreter.js


+ 46 - 381
js/Compiler-Tests.js

@@ -322,341 +322,6 @@ smalltalk.AbstractASTInterpreterTest);
 smalltalk.addClass('ASTInterpreterTest', smalltalk.AbstractASTInterpreterTest, [], 'Compiler-Tests');
 smalltalk.addMethod(
 smalltalk.method({
-selector: "interpreter",
-category: 'accessing',
-fn: function (){
-var self=this;
-function $ASTInterpreter(){return smalltalk.ASTInterpreter||(typeof ASTInterpreter=="undefined"?nil:ASTInterpreter)}
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($ASTInterpreter())._new();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"interpreter",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "interpreter\x0a\x09^ ASTInterpreter new",
-messageSends: ["new"],
-referencedClasses: ["ASTInterpreter"]
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testBinarySend",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo 2+3+4"),(9));
-return self}, function($ctx1) {$ctx1.fill(self,"testBinarySend",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testBinarySend\x0a\x09self assert: (self interpret: 'foo 2+3+4') equals: 9",
-messageSends: ["assert:equals:", "interpret:"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testBlockLiteral",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]"),(1));
-self._assert_equals_(self._interpret_("foo true ifTrue: [ ^ 1 ] ifFalse: [ 2 ]"),(1));
-self._assert_equals_(self._interpret_("foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]"),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testBlockLiteral",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testBlockLiteral\x0a\x09self assert: (self interpret: 'foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]') equals: 1.\x0a\x09self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ] ifFalse: [ 2 ]') equals: 1.\x0a\x09self assert: (self interpret: 'foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]') equals: 2",
-messageSends: ["assert:equals:", "interpret:"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testCascade",
-category: 'tests',
-fn: function (){
-var self=this;
-function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo ^ OrderedCollection new add: 2; add: 3; yourself"),_st($OrderedCollection())._with_with_((2),(3)));
-return self}, function($ctx1) {$ctx1.fill(self,"testCascade",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testCascade\x0a\x09self assert: (self interpret: 'foo ^ OrderedCollection new add: 2; add: 3; yourself') equals: (OrderedCollection with: 2 with: 3)",
-messageSends: ["assert:equals:", "interpret:", "with:with:"],
-referencedClasses: ["OrderedCollection"]
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testDynamicArray",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo ^ {1+1. 2+2}"),[(2), (4)]);
-return self}, function($ctx1) {$ctx1.fill(self,"testDynamicArray",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testDynamicArray\x0a\x09self assert: (self interpret: 'foo ^ {1+1. 2+2}') equals: #(2 4)",
-messageSends: ["assert:equals:", "interpret:"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testDynamicDictionary",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo ^ #{1->1. 2->3}"),smalltalk.HashedCollection._from_([(1).__minus_gt((1)),(2).__minus_gt((3))]));
-return self}, function($ctx1) {$ctx1.fill(self,"testDynamicDictionary",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testDynamicDictionary\x0a\x09self assert: (self interpret: 'foo ^ #{1->1. 2->3}') equals: #{1->1. 2->3}",
-messageSends: ["assert:equals:", "interpret:", "->"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testInlinedJSStatement",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo <return 2+3>"),(5));
-self._assert_equals_(self._interpret_withArguments_("foo: anInteger <return 2 + anInteger>",smalltalk.HashedCollection._from_(["anInteger".__minus_gt((3))])),(5));
-return self}, function($ctx1) {$ctx1.fill(self,"testInlinedJSStatement",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testInlinedJSStatement\x0a\x09self assert: (self interpret: 'foo <return 2+3>') equals: 5.\x0a\x09\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo: anInteger <return 2 + anInteger>'\x0a\x09\x09\x09withArguments: #{ 'anInteger' -> 3})\x0a\x09\x09equals: 5",
-messageSends: ["assert:equals:", "interpret:", "interpret:withArguments:", "->"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testInstVarAccess",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_receiver_withArguments_("foo ^ x",(2).__at((3)),smalltalk.HashedCollection._from_([])),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testInstVarAccess",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testInstVarAccess\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo ^ x'\x0a\x09\x09\x09receiver: 2@3\x0a\x09\x09\x09withArguments: #{})\x0a\x09\x09equals: 2",
-messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "@"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testInstVarAssignment",
-category: 'tests',
-fn: function (){
-var self=this;
-function $Point(){return smalltalk.Point||(typeof Point=="undefined"?nil:Point)}
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_receiver_withArguments_("foo: anInteger x := anInteger. ^ x",_st($Point())._new(),smalltalk.HashedCollection._from_(["anInteger".__minus_gt((2))])),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testInstVarAssignment",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testInstVarAssignment\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo: anInteger x := anInteger. ^ x'\x0a\x09\x09\x09receiver: Point new\x0a\x09\x09\x09withArguments: #{'anInteger' -> 2})\x0a\x09\x09equals: 2",
-messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "new", "->"],
-referencedClasses: ["Point"]
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testNonlocalReturn",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo true ifTrue: [ ^ 1 ]. ^2"),(1));
-return self}, function($ctx1) {$ctx1.fill(self,"testNonlocalReturn",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testNonlocalReturn\x0a\x09self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ]. ^2') equals: 1",
-messageSends: ["assert:equals:", "interpret:"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testReceiver",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_receiver_withArguments_("foo ^ self",(2).__at((3)),smalltalk.HashedCollection._from_([])),(2).__at((3)));
-return self}, function($ctx1) {$ctx1.fill(self,"testReceiver",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testReceiver\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo ^ self'\x0a\x09\x09\x09receiver: 2@3\x0a\x09\x09\x09withArguments: #{})\x0a\x09\x09equals: 2@3",
-messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "@"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testSuper",
-category: 'tests',
-fn: function (){
-var self=this;
-function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_receiver_withArguments_("foo ^ super isBoolean",true,_st($Dictionary())._new()),false);
-return self}, function($ctx1) {$ctx1.fill(self,"testSuper",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testSuper\x0a\x09self \x0a\x09\x09assert: (self \x0a\x09\x09\x09interpret: 'foo ^ super isBoolean' \x0a\x09\x09\x09receiver: true \x0a\x09\x09\x09withArguments: Dictionary new) \x0a\x09\x09equals: false",
-messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "new"],
-referencedClasses: ["Dictionary"]
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testTempAssignment",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_equals_(self._interpret_("foo | a | a := 2. ^ a"),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testTempAssignment",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testTempAssignment\x0a\x09self assert: (self interpret: 'foo | a | a := 2. ^ a') equals: 2",
-messageSends: ["assert:equals:", "interpret:"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testThisContext",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._assert_(_st(_st(self._interpret_("foo ^ thisContext"))._outerContext())._isNil());
-self._assert_(_st(_st(self._interpret_("foo ^ [ thisContext ] value"))._outerContext())._notNil());
-self._assert_(self._interpret_("foo ^ [ thisContext ] value outerContext == thisContext"));
-return self}, function($ctx1) {$ctx1.fill(self,"testThisContext",{},smalltalk.ASTInterpreterTest)})},
-args: [],
-source: "testThisContext\x0a\x09self assert: (self interpret: 'foo ^ thisContext') outerContext isNil.\x0a\x09self assert: (self interpret: 'foo ^ [ thisContext ] value') outerContext notNil.\x0a\x09self assert: (self interpret: 'foo ^ [ thisContext ] value outerContext == thisContext')",
-messageSends: ["assert:", "isNil", "outerContext", "interpret:", "notNil"],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreterTest);
-
-
-
-smalltalk.addClass('ASTSteppingInterpreterTest', smalltalk.AbstractASTInterpreterTest, ['interpreter'], 'Compiler-Tests');
-smalltalk.addMethod(
-smalltalk.method({
-selector: "interpreter",
-category: 'accessing',
-fn: function (){
-var self=this;
-function $ASTSteppingInterpreter(){return smalltalk.ASTSteppingInterpreter||(typeof ASTSteppingInterpreter=="undefined"?nil:ASTSteppingInterpreter)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@interpreter"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@interpreter"]=_st($ASTSteppingInterpreter())._new();
-$1=self["@interpreter"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"interpreter",{},smalltalk.ASTSteppingInterpreterTest)})},
-args: [],
-source: "interpreter\x0a\x09^ interpreter ifNil: [ interpreter := ASTSteppingInterpreter new ]",
-messageSends: ["ifNil:", "new"],
-referencedClasses: ["ASTSteppingInterpreter"]
-}),
-smalltalk.ASTSteppingInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testAtEnd",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._interpret_("foo 1 + 2");
-self._deny_(_st(self._interpreter())._atEnd());
-_st(self._interpreter())._step();
-self._deny_(_st(self._interpreter())._atEnd());
-_st(self._interpreter())._step();
-self._deny_(_st(self._interpreter())._atEnd());
-_st(self._interpreter())._step();
-self._deny_(_st(self._interpreter())._atEnd());
-_st(self._interpreter())._step();
-self._assert_(_st(self._interpreter())._atEnd());
-return self}, function($ctx1) {$ctx1.fill(self,"testAtEnd",{},smalltalk.ASTSteppingInterpreterTest)})},
-args: [],
-source: "testAtEnd\x0a\x09self interpret: 'foo 1 + 2'.\x0a\x09self deny: self interpreter atEnd.\x0a\x0a\x09self interpreter step.\x0a\x09self deny: self interpreter atEnd.\x0a\x09\x0a\x09self interpreter step.\x0a\x09self deny: self interpreter atEnd.\x0a\x09\x0a\x09self interpreter step.\x0a\x09self deny: self interpreter atEnd.\x0a\x09\x0a\x09self interpreter step.\x0a\x09self assert: self interpreter atEnd",
-messageSends: ["interpret:", "deny:", "atEnd", "interpreter", "step", "assert:"],
-referencedClasses: []
-}),
-smalltalk.ASTSteppingInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testMessageSend",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._interpret_("foo 1 + 2");
-_st(self._interpreter())._step();
-_st(self._interpreter())._step();
-_st(self._interpreter())._step();
-self._assert_equals_(_st(_st(self._interpreter())._currentNode())._value(),(1));
-_st(self._interpreter())._step();
-self._assert_equals_(_st(_st(self._interpreter())._currentNode())._value(),(2));
-_st(self._interpreter())._step();
-self._assert_equals_(_st(self._interpreter())._result(),(3));
-return self}, function($ctx1) {$ctx1.fill(self,"testMessageSend",{},smalltalk.ASTSteppingInterpreterTest)})},
-args: [],
-source: "testMessageSend\x0a\x09self interpret: 'foo 1 + 2'.\x0a\x09\x0a\x09\x22SequenceNode\x22\x0a\x09self interpreter step.\x0a\x09\x0a\x09\x22SendNode\x22\x0a\x09self interpreter step.\x0a\x09\x0a\x09\x22ValueNode\x22\x0a\x09self interpreter step.\x0a\x09self assert: self interpreter currentNode value equals: 1.\x0a\x09\x0a\x09\x22ValueNode\x22\x0a\x09self interpreter step.\x0a\x09self assert: self interpreter currentNode value equals: 2.\x0a\x09\x0a\x09\x22Result\x22\x0a\x09self interpreter step.\x0a\x09self assert: self interpreter result equals: 3",
-messageSends: ["interpret:", "step", "interpreter", "assert:equals:", "value", "currentNode", "result"],
-referencedClasses: []
-}),
-smalltalk.ASTSteppingInterpreterTest);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testSimpleStepping",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self._interpret_("foo 1");
-_st(self._interpreter())._step();
-self._assert_(_st(_st(self._interpreter())._result())._isNil());
-_st(self._interpreter())._step();
-self._assert_equals_(_st(self._interpreter())._result(),(1));
-return self}, function($ctx1) {$ctx1.fill(self,"testSimpleStepping",{},smalltalk.ASTSteppingInterpreterTest)})},
-args: [],
-source: "testSimpleStepping\x0a\x09self interpret: 'foo 1'.\x0a\x09\x0a\x09\x22SequenceNode\x22\x0a\x09self interpreter step.\x0a\x09\x0a\x09self assert: self interpreter result isNil.\x0a\x09\x0a\x09\x22ValueNode\x22\x0a\x09self interpreter step.\x0a\x09\x0a\x09self assert: self interpreter result equals: 1",
-messageSends: ["interpret:", "step", "interpreter", "assert:", "isNil", "result", "assert:equals:"],
-referencedClasses: []
-}),
-smalltalk.ASTSteppingInterpreterTest);
-
-
-
-smalltalk.addClass('InterpreterTest', smalltalk.AbstractASTInterpreterTest, [], 'Compiler-Tests');
-smalltalk.addMethod(
-smalltalk.method({
 selector: "interpret:receiver:withArguments:",
 category: 'interpreting',
 fn: function (aString,anObject,aDictionary){
@@ -682,13 +347,13 @@ _st($4)._proceed();
 $5=_st($4)._result();
 $3=$5;
 return $3;
-}, function($ctx1) {$ctx1.fill(self,"interpret:receiver:withArguments:",{aString:aString,anObject:anObject,aDictionary:aDictionary,ctx:ctx,interpreter:interpreter},smalltalk.InterpreterTest)})},
+}, function($ctx1) {$ctx1.fill(self,"interpret:receiver:withArguments:",{aString:aString,anObject:anObject,aDictionary:aDictionary,ctx:ctx,interpreter:interpreter},smalltalk.ASTInterpreterTest)})},
 args: ["aString", "anObject", "aDictionary"],
 source: "interpret: aString receiver: anObject withArguments: aDictionary\x0a\x09\x22The food is a methodNode. Interpret the sequenceNode only\x22\x0a\x09\x0a\x09| ctx interpreter |\x0a\x09\x0a\x09interpreter := self interpreter.\x0a\x09\x0a\x09ctx := AIContext new\x0a\x09\x09receiver: anObject;\x0a\x09\x09interpreter: interpreter;\x0a\x09\x09yourself.\x0a\x09aDictionary keysAndValuesDo: [ :key :value |\x0a\x09\x09ctx localAt: key put: value ].\x0a\x09\x0a\x09^ interpreter\x0a\x09\x09context: ctx;\x0a\x09\x09interpret: (self parse: aString forClass: anObject class) nextChild;\x0a\x09\x09proceed;\x0a\x09\x09result",
 messageSends: ["interpreter", "receiver:", "new", "interpreter:", "yourself", "keysAndValuesDo:", "localAt:put:", "context:", "interpret:", "nextChild", "parse:forClass:", "class", "proceed", "result"],
 referencedClasses: ["AIContext"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -696,18 +361,18 @@ selector: "interpreter",
 category: 'accessing',
 fn: function (){
 var self=this;
-function $Interpreter(){return smalltalk.Interpreter||(typeof Interpreter=="undefined"?nil:Interpreter)}
+function $ASTInterpreter(){return smalltalk.ASTInterpreter||(typeof ASTInterpreter=="undefined"?nil:ASTInterpreter)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st($Interpreter())._new();
+$1=_st($ASTInterpreter())._new();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"interpreter",{},smalltalk.InterpreterTest)})},
+}, function($ctx1) {$ctx1.fill(self,"interpreter",{},smalltalk.ASTInterpreterTest)})},
 args: [],
-source: "interpreter\x0a\x09^ Interpreter new",
+source: "interpreter\x0a\x09^ ASTInterpreter new",
 messageSends: ["new"],
-referencedClasses: ["Interpreter"]
+referencedClasses: ["ASTInterpreter"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -717,13 +382,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ 2+3+4"),(9));
-return self}, function($ctx1) {$ctx1.fill(self,"testBinarySend",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testBinarySend",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testBinarySend\x0a\x09self assert: (self interpret: 'foo ^ 2+3+4') equals: 9",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -734,13 +399,13 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ true ifTrue: [ 1 asString, '2' ]"),"12");
 self._assert_equals_(self._interpret_("foo ^ #(1 2 3) collect: [ :each | each + 3 ]"),[(4), (5), (6)]);
-return self}, function($ctx1) {$ctx1.fill(self,"testBlockEvaluation",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testBlockEvaluation",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testBlockEvaluation\x0a\x09self assert: (self interpret: 'foo ^ true ifTrue: [ 1 asString, ''2'' ]') equals: '12'.\x0a\x09self assert: (self interpret: 'foo ^ #(1 2 3) collect: [ :each | each + 3 ]') equals: #(4 5 6).",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -752,13 +417,13 @@ return smalltalk.withContext(function($ctx1) {
 self._assert_equals_(self._interpret_("foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]"),(1));
 self._assert_equals_(self._interpret_("foo true ifTrue: [ ^ 1 ] ifFalse: [ 2 ]"),(1));
 self._assert_equals_(self._interpret_("foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]"),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testBlockLiteral",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testBlockLiteral",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testBlockLiteral\x0a\x09self assert: (self interpret: 'foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]') equals: 1.\x0a\x09self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ] ifFalse: [ 2 ]') equals: 1.\x0a\x09self assert: (self interpret: 'foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]') equals: 2",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -769,13 +434,13 @@ var self=this;
 function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ OrderedCollection new add: 2; add: 3; yourself"),_st($OrderedCollection())._with_with_((2),(3)));
-return self}, function($ctx1) {$ctx1.fill(self,"testCascade",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testCascade",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testCascade\x0a\x09self assert: (self interpret: 'foo ^ OrderedCollection new add: 2; add: 3; yourself') equals: (OrderedCollection with: 2 with: 3)",
 messageSends: ["assert:equals:", "interpret:", "with:with:"],
 referencedClasses: ["OrderedCollection"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -785,13 +450,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ {1+1. 2+2}"),[(2), (4)]);
-return self}, function($ctx1) {$ctx1.fill(self,"testDynamicArray",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testDynamicArray",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testDynamicArray\x0a\x09self assert: (self interpret: 'foo ^ {1+1. 2+2}') equals: #(2 4)",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -801,13 +466,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ #{1->1. 2->3}"),smalltalk.HashedCollection._from_([(1).__minus_gt((1)),(2).__minus_gt((3))]));
-return self}, function($ctx1) {$ctx1.fill(self,"testDynamicDictionary",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testDynamicDictionary",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testDynamicDictionary\x0a\x09self assert: (self interpret: 'foo ^ #{1->1. 2->3}') equals: #{1->1. 2->3}",
 messageSends: ["assert:equals:", "interpret:", "->"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -820,13 +485,13 @@ return smalltalk.withContext(function($ctx1) {
 self._assert_equals_(self._interpret_("foo ^ eval class"),$BlockClosure());
 self._assert_equals_(self._interpret_("foo ^ Math cos: 0"),(1));
 self._assert_equals_(self._interpret_("foo ^ NonExistingVar"),nil);
-return self}, function($ctx1) {$ctx1.fill(self,"testGlobalVar",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testGlobalVar",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testGlobalVar\x0a\x09self assert: (self interpret: 'foo ^ eval class') equals: BlockClosure.\x0a\x09self assert: (self interpret: 'foo ^ Math cos: 0') equals: 1.\x0a\x09self assert: (self interpret: 'foo ^ NonExistingVar') equals: nil.",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: ["BlockClosure"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -837,13 +502,13 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo <return 2+3>"),(5));
 self._assert_equals_(self._interpret_withArguments_("foo: anInteger <return 2 + anInteger>",smalltalk.HashedCollection._from_(["anInteger".__minus_gt((3))])),(5));
-return self}, function($ctx1) {$ctx1.fill(self,"testInlinedJSStatement",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testInlinedJSStatement",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testInlinedJSStatement\x0a\x09self assert: (self interpret: 'foo <return 2+3>') equals: 5.\x0a\x09\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo: anInteger <return 2 + anInteger>'\x0a\x09\x09\x09withArguments: #{ 'anInteger' -> 3})\x0a\x09\x09equals: 5",
 messageSends: ["assert:equals:", "interpret:", "interpret:withArguments:", "->"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -853,13 +518,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_receiver_withArguments_("foo ^ x",(2).__at((3)),smalltalk.HashedCollection._from_([])),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testInstVarAccess",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testInstVarAccess",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testInstVarAccess\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo ^ x'\x0a\x09\x09\x09receiver: 2@3\x0a\x09\x09\x09withArguments: #{})\x0a\x09\x09equals: 2",
 messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "@"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -870,13 +535,13 @@ var self=this;
 function $Point(){return smalltalk.Point||(typeof Point=="undefined"?nil:Point)}
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_receiver_withArguments_("foo: anInteger x := anInteger. ^ x",_st($Point())._new(),smalltalk.HashedCollection._from_(["anInteger".__minus_gt((2))])),(2));
-return self}, function($ctx1) {$ctx1.fill(self,"testInstVarAssignment",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testInstVarAssignment",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testInstVarAssignment\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo: anInteger x := anInteger. ^ x'\x0a\x09\x09\x09receiver: Point new\x0a\x09\x09\x09withArguments: #{'anInteger' -> 2})\x0a\x09\x09equals: 2",
 messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "new", "->"],
 referencedClasses: ["Point"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -886,13 +551,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ Point x: 1 y: 2"),(1).__at((2)));
-return self}, function($ctx1) {$ctx1.fill(self,"testKeywordSend",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testKeywordSend",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testKeywordSend\x0a\x09self assert: (self interpret: 'foo ^ Point x: 1 y: 2') equals: 1@2",
 messageSends: ["assert:equals:", "interpret:", "@"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -902,13 +567,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo | a b c | a := 2. b := 3. c := a + b. ^ c * 6"),(30));
-return self}, function($ctx1) {$ctx1.fill(self,"testMultipleSequences",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testMultipleSequences",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testMultipleSequences\x0a\x09self assert: (self interpret: 'foo | a b c | a := 2. b := 3. c := a + b. ^ c * 6') equals: 30",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -919,13 +584,13 @@ var self=this;
 function $Point(){return smalltalk.Point||(typeof Point=="undefined"?nil:Point)}
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ (Point x: (Point x: 2 y: 3) y: 4) asString"),_st(_st($Point())._x_y_((2).__at((3)),(4)))._asString());
-return self}, function($ctx1) {$ctx1.fill(self,"testNestedSends",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testNestedSends",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testNestedSends\x0a\x09self assert: (self interpret: 'foo ^ (Point x: (Point x: 2 y: 3) y: 4) asString') equals: (Point x: (2@3) y: 4) asString",
 messageSends: ["assert:equals:", "interpret:", "asString", "x:y:", "@"],
 referencedClasses: ["Point"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -935,13 +600,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo true ifTrue: [ ^ 1 ]. ^2"),(1));
-return self}, function($ctx1) {$ctx1.fill(self,"testNonlocalReturn",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testNonlocalReturn",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testNonlocalReturn\x0a\x09self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ]. ^2') equals: 1",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -951,13 +616,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_receiver_withArguments_("foo ^ self",(2).__at((3)),smalltalk.HashedCollection._from_([])),(2).__at((3)));
-return self}, function($ctx1) {$ctx1.fill(self,"testReceiver",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testReceiver",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testReceiver\x0a\x09self\x0a\x09\x09assert: (self\x0a\x09\x09\x09interpret: 'foo ^ self'\x0a\x09\x09\x09receiver: 2@3\x0a\x09\x09\x09withArguments: #{})\x0a\x09\x09equals: 2@3",
 messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "@"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -968,13 +633,13 @@ var self=this;
 function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_receiver_withArguments_("foo ^ super isBoolean",true,_st($Dictionary())._new()),false);
-return self}, function($ctx1) {$ctx1.fill(self,"testSuper",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testSuper",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testSuper\x0a\x09self \x0a\x09\x09assert: (self \x0a\x09\x09\x09interpret: 'foo ^ super isBoolean' \x0a\x09\x09\x09receiver: true \x0a\x09\x09\x09withArguments: Dictionary new) \x0a\x09\x09equals: false",
 messageSends: ["assert:equals:", "interpret:receiver:withArguments:", "new"],
 referencedClasses: ["Dictionary"]
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -985,13 +650,13 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo | a | a := 2. ^ a"),(2));
 self._assert_equals_(self._interpret_("foo | a | a := nil. ^ a"),nil);
-return self}, function($ctx1) {$ctx1.fill(self,"testTempAssignment",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testTempAssignment",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testTempAssignment\x0a\x09self assert: (self interpret: 'foo | a | a := 2. ^ a') equals: 2.\x0a\x09self assert: (self interpret: 'foo | a | a := nil. ^ a') equals: nil.",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1003,13 +668,13 @@ return smalltalk.withContext(function($ctx1) {
 self._assert_(_st(_st(self._interpret_("foo ^ thisContext"))._outerContext())._isNil());
 self._assert_(_st(_st(self._interpret_("foo ^ [ thisContext ] value"))._outerContext())._notNil());
 self._assert_(self._interpret_("foo ^ [ thisContext ] value outerContext == thisContext"));
-return self}, function($ctx1) {$ctx1.fill(self,"testThisContext",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testThisContext",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testThisContext\x0a\x09self assert: (self interpret: 'foo ^ thisContext') outerContext isNil.\x0a\x09self assert: (self interpret: 'foo ^ [ thisContext ] value') outerContext notNil.\x0a\x09self assert: (self interpret: 'foo ^ [ thisContext ] value outerContext == thisContext')",
 messageSends: ["assert:", "isNil", "outerContext", "interpret:", "notNil"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1019,13 +684,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._assert_equals_(self._interpret_("foo ^ 1 asString"),"1");
-return self}, function($ctx1) {$ctx1.fill(self,"testUnarySend",{},smalltalk.InterpreterTest)})},
+return self}, function($ctx1) {$ctx1.fill(self,"testUnarySend",{},smalltalk.ASTInterpreterTest)})},
 args: [],
 source: "testUnarySend\x0a\x09self assert: (self interpret: 'foo ^ 1 asString') equals: '1'",
 messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.InterpreterTest);
+smalltalk.ASTInterpreterTest);
 
 
 

+ 90 - 423
st/Compiler-Interpreter.st

@@ -210,7 +210,7 @@ initializeFromMethodContext: aMethodContext
 !
 
 initializeInterpreter
-	interpreter := Interpreter new
+	interpreter := ASTInterpreter new
 		context: self;
 		yourself.
 	ast ifNotNil: [ interpreter node: self retrieveNode ].
@@ -426,420 +426,11 @@ context: aContext
 		yourself
 ! !
 
-Object subclass: #ASTInterpreter
-	instanceVariableNames: 'currentNode nextNode context shouldReturn result'
-	package: 'Compiler-Interpreter'!
-!ASTInterpreter commentStamp!
-I am like a `NodeVisitor`, interpreting nodes one after each other.
-I am built using Continuation Passing Style for stepping purposes.
-
-## Usage example:
-
-	| ast interpreter |
-	ast := Smalltalk current parse: 'foo 1+2+4'.
-	(SemanticAnalyzer on: Object) visit: ast.
-
-	ASTInterpreter new
-		interpret: ast nodes first;
-		result "Answers 7"!
-
-!ASTInterpreter methodsFor: 'accessing'!
-
-context
-	^ context ifNil: [ context := AIContext new ]
-!
-
-context: anAIContext
-	context := anAIContext
-!
-
-currentNode
-	^ currentNode
-!
-
-nextNode
-	^ nextNode ifNil: [ self currentNode ]
-!
-
-nextNode: aNode
-	nextNode := aNode
-!
-
-result
-	^ result
-! !
-
-!ASTInterpreter methodsFor: 'initialization'!
-
-initialize
-	super initialize.
-	shouldReturn := false
-! !
-
-!ASTInterpreter methodsFor: 'interpreting'!
-
-interpret: aNode
-	shouldReturn := false.
-	self interpret: aNode continue: [ :value |
-		result := value ]
-!
-
-interpret: aNode continue: aBlock
-	shouldReturn ifTrue: [ ^ self ].
-
-	aNode isNode
-		ifTrue: [
-			currentNode := aNode.
-			self interpretNode: aNode continue: [ :value |
-				self continue: aBlock value: value ] ]
-		ifFalse: [ self continue: aBlock value: aNode ]
-!
-
-interpretAssignmentNode: aNode continue: aBlock
-	self interpret: aNode right continue: [ :value |
-		self
-			continue: aBlock
-			value: (self assign: aNode left to: value) ]
-!
-
-interpretBlockNode: aNode continue: aBlock
-	self
-		continue: aBlock
-		value: [ 
-			self withBlockContext: [ 
-				self interpret: aNode nodes first; result ] ]
-!
-
-interpretBlockSequenceNode: aNode continue: aBlock
-	self interpretSequenceNode: aNode continue: aBlock
-!
-
-interpretCascadeNode: aNode continue: aBlock
-	"TODO: Handle super sends"
-	
-	self interpret: aNode receiver continue: [ :receiver |
-		"Only interpret the receiver once"
-		aNode nodes do: [ :each | each receiver: receiver ].
-
-		self
-			interpretAll: aNode nodes allButLast
-			continue: [
-				self
-					interpret: aNode nodes last
-					continue: [ :val | self continue: aBlock value: val ] ] ]
-!
-
-interpretClassReferenceNode: aNode continue: aBlock
-	self continue: aBlock value: (Smalltalk current at: aNode value)
-!
-
-interpretDynamicArrayNode: aNode continue: aBlock
-	self interpretAll: aNode nodes continue: [ :array |
-		self
-			continue: aBlock
-			value: array ]
-!
-
-interpretDynamicDictionaryNode: aNode continue: aBlock
-	self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
-		hashedCollection := HashedCollection new.
-		array do: [ :each | hashedCollection add: each ].
-		self
-			continue: aBlock
-			value: hashedCollection ]
-!
-
-interpretJSStatementNode: aNode continue: aBlock
-	shouldReturn := true.
-	self continue: aBlock value: (self eval: aNode source)
-!
-
-interpretMethodNode: aNode continue: aBlock
-	self interpretAll: aNode nodes continue: [ :array |
-		self continue: aBlock value: array first ]
-!
-
-interpretNode: aNode continue: aBlock
-	aNode interpreter: self continue: aBlock
-!
-
-interpretReturnNode: aNode continue: aBlock
-	self interpret: aNode nodes first continue: [ :value |
-		shouldReturn := true.
-		self continue: aBlock value: value ]
-!
-
-interpretSendNode: aNode continue: aBlock
-	self interpret: aNode receiver continue: [ :receiver |
-		self interpretAll: aNode arguments continue: [ :args |
-			self
-				messageFromSendNode: aNode
-				arguments: args
-				do: [ :message |
-					self context pc: self context pc + 1.
-					self
-						continue: aBlock
-						value: (self sendMessage: message to: receiver superSend: aNode superSend) ] ] ]
-!
-
-interpretSequenceNode: aNode continue: aBlock
-	self interpretAll: aNode nodes continue: [ :array |
-		self continue: aBlock value: array last ]
-!
-
-interpretValueNode: aNode continue: aBlock
-	self continue: aBlock value: aNode value
-!
-
-interpretVariableNode: aNode continue: aBlock
-	self
-		continue: aBlock
-		value: (aNode binding isInstanceVar
-			ifTrue: [ self context receiver instVarAt: aNode value ]
-			ifFalse: [ self context localAt: aNode value ])
-! !
-
-!ASTInterpreter methodsFor: 'private'!
-
-assign: aNode to: anObject
-	^ aNode binding isInstanceVar
-		ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
-		ifFalse: [ self context localAt: aNode value put: anObject ]
-!
-
-continue: aBlock value: anObject
-	result := anObject.
-	aBlock value: anObject
-!
-
-eval: aString
-	"Evaluate aString as JS source inside an JS function.
-	aString is not sandboxed."
-	
-	| source function |
-	
-	source := String streamContents: [ :str |
-		str nextPutAll: '(function('.
-		self context locals keys
-			do: [ :each | str nextPutAll: each ]
-			separatedBy: [ str nextPutAll: ',' ].
-		str
-			nextPutAll: '){ return (function() {';
-			nextPutAll: aString;
-			nextPutAll: '})() })' ].
-			
-	function := Compiler new eval: source.
-	
-	^ function valueWithPossibleArguments: self context locals values
-!
-
-interpretAll: aCollection continue: aBlock
-	self
-		interpretAll: aCollection
-		continue: aBlock
-		result: OrderedCollection new
-!
-
-interpretAll: nodes continue: aBlock result: aCollection
-	nodes isEmpty
-		ifTrue: [ self continue: aBlock value: aCollection ]
-		ifFalse: [
-			self interpret: nodes first continue: [:value |
-				self
-					interpretAll: nodes allButFirst
-					continue: aBlock
-					result: aCollection, { value } ] ]
-!
-
-messageFromSendNode: aSendNode arguments: aCollection do: aBlock
-	self
-		continue: aBlock
-		value: (Message new
-			selector: aSendNode selector;
-			arguments: aCollection;
-			yourself)
-!
-
-sendMessage: aMessage to: anObject superSend: aBoolean
-	| method |
-	
-	aBoolean ifFalse: [ ^ aMessage sendTo: anObject ].
-	anObject class superclass ifNil: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
-	
-	method := anObject class superclass methodDictionary
-		at: aMessage selector
-		ifAbsent: [ ^ self messageNotUnderstood: aMessage receiver: anObject ].
-		
-	^ method fn applyTo: anObject arguments: aMessage arguments
-!
-
-withBlockContext: aBlock
-	"Evaluate aBlock with a BlockContext:
-	- a context is pushed before aBlock evaluation.
-	- the context is poped after aBlock evaluation
-	- the result of aBlock evaluation is answered"
-	
-	| blockResult |
-			
-	self context: (AIContext new
-		outerContext: self context;
-		yourself).
-	
-	blockResult := aBlock value.
-	
-	self context: self context outerContext.
-	^ blockResult
-! !
-
-!ASTInterpreter methodsFor: 'testing'!
-
-shouldReturn
-	^ shouldReturn ifNil: [ false ]
-! !
-
-ASTInterpreter subclass: #ASTSteppingInterpreter
-	instanceVariableNames: 'continuation nextNode'
-	package: 'Compiler-Interpreter'!
-!ASTSteppingInterpreter commentStamp!
-I am an interpreter with stepping capabilities. The higher level `ASTDebugger` class should be used as a debugger model, as it provides convenience methods for debugging.
-
-## API
-
-Use `#step` to actually interpret the next node. Interpretation stops at each node evaluation, weither it's a message node or not.
-
-
-## Usage example:
-
-	| ast interpreter |
-	ast := Smalltalk current parse: 'foo 1+2+4'.
-	(SemanticAnalyzer on: Object) visit: ast.
-
-	interpreter := ASTSteppingInterpreter new
-		interpret: ast nodes first;
-		yourself.
-		
-	interpreter step; step.
-	interpreter step; step.
-	interpreter result."Answers 1"
-	interpreter step.
-	interpreter result. "Answers 3"
-	interpreter step.
-	interpreter result. "Answers 7"!
-
-!ASTSteppingInterpreter methodsFor: 'accessing'!
-
-nextNode
-	^ nextNode
-! !
-
-!ASTSteppingInterpreter methodsFor: 'initialization'!
-
-initialize
-	super initialize.
-	continuation := []
-! !
-
-!ASTSteppingInterpreter methodsFor: 'interpreting'!
-
-interpret: aNode continue: aBlock
-	nextNode := aNode.
-	continuation := [
-		super interpret: aNode continue: aBlock ]
-! !
-
-!ASTSteppingInterpreter methodsFor: 'stepping'!
-
-step
-	continuation value
-! !
-
-!ASTSteppingInterpreter methodsFor: 'testing'!
-
-atEnd
-	^ self shouldReturn or: [ self nextNode == self currentNode ]
-! !
-
-NodeVisitor subclass: #ASTPCNodeVisitor
-	instanceVariableNames: 'useInlinings pc context blockIndex currentNode'
-	package: 'Compiler-Interpreter'!
-!ASTPCNodeVisitor commentStamp!
-I visit an AST until I get to the current pc node and answer it.
-
-## API
-
-My instances must be filled with a context object using `#context:`.
-
-After visiting the AST the current node corresponding to the `pc` is answered by `#currentNode`!
-
-!ASTPCNodeVisitor methodsFor: 'accessing'!
-
-blockIndex
-	^ blockIndex ifNil: [ blockIndex := 0 ]
-!
-
-context
-	^ context
-!
-
-context: aContext
-	context := aContext
-!
-
-currentNode
-	^ currentNode
-!
-
-increaseBlockIndex
-	blockIndex := self blockIndex + 1
-!
-
-pc
-	^ pc ifNil: [ 0 ]
-!
-
-pc: anInteger
-	pc := anInteger
-!
-
-useInlinings
-	^ useInlinings ifNil: [ true ]
-!
-
-useInlinings: aBoolean
-	useInlinings := aBoolean
-! !
-
-!ASTPCNodeVisitor methodsFor: 'visiting'!
-
-visitBlockNode: aNode
-	"Inlined send node. Assume that the block is inlined"
-	(aNode parent isSendNode and: [ aNode parent shouldBeInlined ])
-		ifFalse: [
-			self blockIndex >= self context index ifFalse: [
-				self increaseBlockIndex.
-				super visitBlockNode: aNode ] ]
-		ifTrue: [ super visitBlockNode: aNode ]
-!
-
-visitJSStatementNode: aNode
-	currentNode := aNode
-!
-
-visitSendNode: aNode
-	super visitSendNode: aNode.
-	
-	self pc = self context pc ifFalse: [
-		aNode shouldBeInlined ifFalse: [
-			self blockIndex = self context index ifTrue: [
-				self pc: self pc + 1.
-				currentNode := aNode ] ] ]
-! !
-
-NodeVisitor subclass: #Interpreter
+NodeVisitor subclass: #ASTInterpreter
 	instanceVariableNames: 'node context stack returnValue returned'
 	package: 'Compiler-Interpreter'!
 
-!Interpreter methodsFor: 'accessing'!
+!ASTInterpreter methodsFor: 'accessing'!
 
 context
 	^ context
@@ -877,7 +468,7 @@ stack
 	^ stack ifNil: [ stack := OrderedCollection new ]
 ! !
 
-!Interpreter methodsFor: 'interpreting'!
+!ASTInterpreter methodsFor: 'interpreting'!
 
 interpret
 	"Interpret the next node to be evaluated"
@@ -905,6 +496,12 @@ restart
 	self node: self context ast nextChild
 !
 
+setNonLocalReturnFromContext: aContext
+	aContext interpreter hasReturned ifTrue: [
+		returned := true.
+		self returnValue: aContext interpreter returnValue ]
+!
+
 skip
 	self next
 !
@@ -920,15 +517,9 @@ stepOver
 	
 	[ self node isSteppingNode ] whileFalse: [ 
 		self step ]
-!
-
-setNonLocalReturnFromContext: aContext
-	aContext interpreter hasReturned ifTrue: [
-		returned := true.
-		self returnValue: aContext interpreter returnValue ]
 ! !
 
-!Interpreter methodsFor: 'private'!
+!ASTInterpreter methodsFor: 'private'!
 
 assign: aNode to: anObject
 	aNode binding isInstanceVar
@@ -984,7 +575,7 @@ sendMessage: aMessage to: anObject superSend: aBoolean
 	^ method sendTo: anObject arguments: aMessage arguments
 ! !
 
-!Interpreter methodsFor: 'stack'!
+!ASTInterpreter methodsFor: 'stack'!
 
 peek
 	"Peek the top object of the context stack"
@@ -1010,7 +601,7 @@ push: anObject
 	^ self stack add: anObject
 ! !
 
-!Interpreter methodsFor: 'testing'!
+!ASTInterpreter methodsFor: 'testing'!
 
 atEnd
 	^ self hasReturned or: [ self node isNil ]
@@ -1020,7 +611,7 @@ hasReturned
 	^ returned ifNil: [ false ]
 ! !
 
-!Interpreter methodsFor: 'visiting'!
+!ASTInterpreter methodsFor: 'visiting'!
 
 visit: aNode
 	self hasReturned ifFalse: [ super visit: aNode ]
@@ -1123,6 +714,82 @@ visitVariableNode: aNode
 		ifFalse: [ self context localAt: aNode value ])
 ! !
 
+NodeVisitor subclass: #ASTPCNodeVisitor
+	instanceVariableNames: 'useInlinings pc context blockIndex currentNode'
+	package: 'Compiler-Interpreter'!
+!ASTPCNodeVisitor commentStamp!
+I visit an AST until I get to the current pc node and answer it.
+
+## API
+
+My instances must be filled with a context object using `#context:`.
+
+After visiting the AST the current node corresponding to the `pc` is answered by `#currentNode`!
+
+!ASTPCNodeVisitor methodsFor: 'accessing'!
+
+blockIndex
+	^ blockIndex ifNil: [ blockIndex := 0 ]
+!
+
+context
+	^ context
+!
+
+context: aContext
+	context := aContext
+!
+
+currentNode
+	^ currentNode
+!
+
+increaseBlockIndex
+	blockIndex := self blockIndex + 1
+!
+
+pc
+	^ pc ifNil: [ 0 ]
+!
+
+pc: anInteger
+	pc := anInteger
+!
+
+useInlinings
+	^ useInlinings ifNil: [ true ]
+!
+
+useInlinings: aBoolean
+	useInlinings := aBoolean
+! !
+
+!ASTPCNodeVisitor methodsFor: 'visiting'!
+
+visitBlockNode: aNode
+	"Inlined send node. Assume that the block is inlined"
+	(aNode parent isSendNode and: [ aNode parent shouldBeInlined ])
+		ifFalse: [
+			self blockIndex >= self context index ifFalse: [
+				self increaseBlockIndex.
+				super visitBlockNode: aNode ] ]
+		ifTrue: [ super visitBlockNode: aNode ]
+!
+
+visitJSStatementNode: aNode
+	currentNode := aNode
+!
+
+visitSendNode: aNode
+	super visitSendNode: aNode.
+	
+	self pc = self context pc ifFalse: [
+		aNode shouldBeInlined ifFalse: [
+			self blockIndex = self context index ifTrue: [
+				self pc: self pc + 1.
+				currentNode := aNode ] ] ]
+! !
+
 !Node methodsFor: '*Compiler-Interpreter'!
 
 interpreter: anInterpreter continue: aBlock

+ 2 - 161
st/Compiler-Tests.st

@@ -143,166 +143,7 @@ interpreter
 	^ ASTInterpreter new
 ! !
 
-!ASTInterpreterTest methodsFor: 'tests'!
-
-testBinarySend
-	self assert: (self interpret: 'foo 2+3+4') equals: 9
-!
-
-testBlockLiteral
-	self assert: (self interpret: 'foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]') equals: 1.
-	self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ] ifFalse: [ 2 ]') equals: 1.
-	self assert: (self interpret: 'foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]') equals: 2
-!
-
-testCascade
-	self assert: (self interpret: 'foo ^ OrderedCollection new add: 2; add: 3; yourself') equals: (OrderedCollection with: 2 with: 3)
-!
-
-testDynamicArray
-	self assert: (self interpret: 'foo ^ {1+1. 2+2}') equals: #(2 4)
-!
-
-testDynamicDictionary
-	self assert: (self interpret: 'foo ^ #{1->1. 2->3}') equals: #{1->1. 2->3}
-!
-
-testInlinedJSStatement
-	self assert: (self interpret: 'foo <return 2+3>') equals: 5.
-	
-	self
-		assert: (self
-			interpret: 'foo: anInteger <return 2 + anInteger>'
-			withArguments: #{ 'anInteger' -> 3})
-		equals: 5
-!
-
-testInstVarAccess
-	self
-		assert: (self
-			interpret: 'foo ^ x'
-			receiver: 2@3
-			withArguments: #{})
-		equals: 2
-!
-
-testInstVarAssignment
-	self
-		assert: (self
-			interpret: 'foo: anInteger x := anInteger. ^ x'
-			receiver: Point new
-			withArguments: #{'anInteger' -> 2})
-		equals: 2
-!
-
-testNonlocalReturn
-	self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ]. ^2') equals: 1
-!
-
-testReceiver
-	self
-		assert: (self
-			interpret: 'foo ^ self'
-			receiver: 2@3
-			withArguments: #{})
-		equals: 2@3
-!
-
-testSuper
-	self 
-		assert: (self 
-			interpret: 'foo ^ super isBoolean' 
-			receiver: true 
-			withArguments: Dictionary new) 
-		equals: false
-!
-
-testTempAssignment
-	self assert: (self interpret: 'foo | a | a := 2. ^ a') equals: 2
-!
-
-testThisContext
-	self assert: (self interpret: 'foo ^ thisContext') outerContext isNil.
-	self assert: (self interpret: 'foo ^ [ thisContext ] value') outerContext notNil.
-	self assert: (self interpret: 'foo ^ [ thisContext ] value outerContext == thisContext')
-! !
-
-AbstractASTInterpreterTest subclass: #ASTSteppingInterpreterTest
-	instanceVariableNames: 'interpreter'
-	package: 'Compiler-Tests'!
-
-!ASTSteppingInterpreterTest methodsFor: 'accessing'!
-
-interpreter
-	^ interpreter ifNil: [ interpreter := ASTSteppingInterpreter new ]
-! !
-
-!ASTSteppingInterpreterTest methodsFor: 'tests'!
-
-testAtEnd
-	self interpret: 'foo 1 + 2'.
-	self deny: self interpreter atEnd.
-
-	self interpreter step.
-	self deny: self interpreter atEnd.
-	
-	self interpreter step.
-	self deny: self interpreter atEnd.
-	
-	self interpreter step.
-	self deny: self interpreter atEnd.
-	
-	self interpreter step.
-	self assert: self interpreter atEnd
-!
-
-testMessageSend
-	self interpret: 'foo 1 + 2'.
-	
-	"SequenceNode"
-	self interpreter step.
-	
-	"SendNode"
-	self interpreter step.
-	
-	"ValueNode"
-	self interpreter step.
-	self assert: self interpreter currentNode value equals: 1.
-	
-	"ValueNode"
-	self interpreter step.
-	self assert: self interpreter currentNode value equals: 2.
-	
-	"Result"
-	self interpreter step.
-	self assert: self interpreter result equals: 3
-!
-
-testSimpleStepping
-	self interpret: 'foo 1'.
-	
-	"SequenceNode"
-	self interpreter step.
-	
-	self assert: self interpreter result isNil.
-	
-	"ValueNode"
-	self interpreter step.
-	
-	self assert: self interpreter result equals: 1
-! !
-
-AbstractASTInterpreterTest subclass: #InterpreterTest
-	instanceVariableNames: ''
-	package: 'Compiler-Tests'!
-
-!InterpreterTest methodsFor: 'accessing'!
-
-interpreter
-	^ Interpreter new
-! !
-
-!InterpreterTest methodsFor: 'interpreting'!
+!ASTInterpreterTest methodsFor: 'interpreting'!
 
 interpret: aString receiver: anObject withArguments: aDictionary
 	"The food is a methodNode. Interpret the sequenceNode only"
@@ -325,7 +166,7 @@ interpret: aString receiver: anObject withArguments: aDictionary
 		result
 ! !
 
-!InterpreterTest methodsFor: 'tests'!
+!ASTInterpreterTest methodsFor: 'tests'!
 
 testBinarySend
 	self assert: (self interpret: 'foo ^ 2+3+4') equals: 9

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません