Browse Source

keep track of block position in the source code

Nicolas Petton 11 years ago
parent
commit
b3b5784ac4

+ 2 - 2
js/Compiler-IR.deploy.js

@@ -2396,9 +2396,9 @@ return self._nextPutAll_(",");
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 $7=self;
 $7=self;
 _st($7)._nextPutAll_("},");
 _st($7)._nextPutAll_("},");
-$8=_st($7)._nextPutAll_(_st(_st(_st(_st(anIRClosure)._scope())._outerScope())._alias()).__comma(")})"));
+$8=_st($7)._nextPutAll_(_st(_st(_st(_st(_st(_st(anIRClosure)._scope())._outerScope())._alias()).__comma(",")).__comma(_st(_st(_st(anIRClosure)._scope())._blockIndex())._asString())).__comma(")})"));
 return self}, function($ctx1) {$ctx1.fill(self,"nextPutBlockContextFor:during:",{anIRClosure:anIRClosure,aBlock:aBlock},smalltalk.JSStream)})},
 return self}, function($ctx1) {$ctx1.fill(self,"nextPutBlockContextFor:during:",{anIRClosure:anIRClosure,aBlock:aBlock},smalltalk.JSStream)})},
-messageSends: ["nextPutAll:", ",", "alias", "scope", "lf", "value", "do:separatedBy:", "asVariableName", "locals", "outerScope"]}),
+messageSends: ["nextPutAll:", ",", "alias", "scope", "lf", "value", "do:separatedBy:", "locals", "asVariableName", "outerScope", "asString", "blockIndex"]}),
 smalltalk.JSStream);
 smalltalk.JSStream);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(

+ 3 - 3
js/Compiler-IR.js

@@ -3201,11 +3201,11 @@ return self._nextPutAll_(",");
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 $7=self;
 $7=self;
 _st($7)._nextPutAll_("},");
 _st($7)._nextPutAll_("},");
-$8=_st($7)._nextPutAll_(_st(_st(_st(_st(anIRClosure)._scope())._outerScope())._alias()).__comma(")})"));
+$8=_st($7)._nextPutAll_(_st(_st(_st(_st(_st(_st(anIRClosure)._scope())._outerScope())._alias()).__comma(",")).__comma(_st(_st(_st(anIRClosure)._scope())._blockIndex())._asString())).__comma(")})"));
 return self}, function($ctx1) {$ctx1.fill(self,"nextPutBlockContextFor:during:",{anIRClosure:anIRClosure,aBlock:aBlock},smalltalk.JSStream)})},
 return self}, function($ctx1) {$ctx1.fill(self,"nextPutBlockContextFor:during:",{anIRClosure:anIRClosure,aBlock:aBlock},smalltalk.JSStream)})},
 args: ["anIRClosure", "aBlock"],
 args: ["anIRClosure", "aBlock"],
-source: "nextPutBlockContextFor: anIRClosure during: aBlock\x0a\x09self\x0a\x09\x09nextPutAll: 'return smalltalk.withContext(function(', anIRClosure scope alias, ') {'; lf.\x0a\x09\x0a\x09aBlock value.\x0a\x09\x0a\x09self\x0a\x09\x09nextPutAll: '}, function(', anIRClosure scope alias, ') {';\x0a\x09\x09nextPutAll: anIRClosure scope alias, '.fillBlock({'.\x0a\x09\x0a\x09anIRClosure locals\x0a\x09\x09do: [ :each |\x0a\x09\x09\x09self\x0a\x09\x09\x09\x09nextPutAll: each asVariableName;\x0a\x09\x09\x09\x09nextPutAll: ':';\x0a\x09\x09\x09\x09nextPutAll: each asVariableName]\x0a\x09\x09separatedBy: [ self nextPutAll: ',' ].\x0a\x09\x0a\x09self\x0a\x09\x09nextPutAll: '},';\x0a\x09\x09nextPutAll: anIRClosure scope outerScope alias, ')})'",
-messageSends: ["nextPutAll:", ",", "alias", "scope", "lf", "value", "do:separatedBy:", "asVariableName", "locals", "outerScope"],
+source: "nextPutBlockContextFor: anIRClosure during: aBlock\x0a\x09self\x0a\x09\x09nextPutAll: 'return smalltalk.withContext(function(', anIRClosure scope alias, ') {'; lf.\x0a\x09\x0a\x09aBlock value.\x0a\x09\x0a\x09self\x0a\x09\x09nextPutAll: '}, function(', anIRClosure scope alias, ') {';\x0a\x09\x09nextPutAll: anIRClosure scope alias, '.fillBlock({'.\x0a\x09\x0a\x09anIRClosure locals\x0a\x09\x09do: [ :each |\x0a\x09\x09\x09self\x0a\x09\x09\x09\x09nextPutAll: each asVariableName;\x0a\x09\x09\x09\x09nextPutAll: ':';\x0a\x09\x09\x09\x09nextPutAll: each asVariableName]\x0a\x09\x09separatedBy: [ self nextPutAll: ',' ].\x0a\x09\x0a\x09self\x0a\x09\x09nextPutAll: '},';\x0a\x09\x09nextPutAll: anIRClosure scope outerScope alias, ',', anIRClosure scope blockIndex asString, ')})'",
+messageSends: ["nextPutAll:", ",", "alias", "scope", "lf", "value", "do:separatedBy:", "locals", "asVariableName", "outerScope", "asString", "blockIndex"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.JSStream);
 smalltalk.JSStream);

+ 42 - 70
js/Compiler-Interpreter.deploy.js

@@ -1,5 +1,5 @@
 smalltalk.addPackage('Compiler-Interpreter');
 smalltalk.addPackage('Compiler-Interpreter');
-smalltalk.addClass('AIContext', smalltalk.Object, ['outerContext', 'innerContext', 'homeContext', 'pc', 'locals', 'method', 'ast', 'interpreter', 'methodContext', 'homeMethodContext'], 'Compiler-Interpreter');
+smalltalk.addClass('AIContext', smalltalk.Object, ['outerContext', 'innerContext', 'pc', 'locals', 'method', 'index', 'ast', 'interpreter', 'methodContext'], 'Compiler-Interpreter');
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "arguments",
 selector: "arguments",
@@ -35,60 +35,40 @@ selector: "ast",
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=self["@ast"];
-if(($receiver = $1) == nil || $receiver == undefined){
+var $1,$2,$3,$4;
+$1=self._isBlockContext();
+if(smalltalk.assert($1)){
+$2=_st(self._outerContext())._ast();
+return $2;
+};
+$3=self["@ast"];
+if(($receiver = $3) == nil || $receiver == undefined){
 self._initializeAST();
 self._initializeAST();
 } else {
 } else {
-$1;
+$3;
 };
 };
-$2=self["@ast"];
-return $2;
+$4=self["@ast"];
+return $4;
 }, function($ctx1) {$ctx1.fill(self,"ast",{},smalltalk.AIContext)})},
 }, function($ctx1) {$ctx1.fill(self,"ast",{},smalltalk.AIContext)})},
-messageSends: ["ifNil:", "initializeAST"]}),
-smalltalk.AIContext);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "home",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self._homeContext();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"home",{},smalltalk.AIContext)})},
-messageSends: ["homeContext"]}),
+messageSends: ["ifTrue:", "isBlockContext", "ast", "outerContext", "ifNil:", "initializeAST"]}),
 smalltalk.AIContext);
 smalltalk.AIContext);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
-selector: "homeContext",
+selector: "index",
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
 var $2,$1;
 var $2,$1;
-$2=self["@homeContext"];
+$2=self["@index"];
 if(($receiver = $2) == nil || $receiver == undefined){
 if(($receiver = $2) == nil || $receiver == undefined){
-self["@homeContext"]=_st(self["@homeMethodContext"])._aiContext();
-$1=self["@homeContext"];
+$1=(0);
 } else {
 } else {
 $1=$2;
 $1=$2;
 };
 };
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"homeContext",{},smalltalk.AIContext)})},
-messageSends: ["ifNil:", "aiContext"]}),
-smalltalk.AIContext);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "homeContext:",
-fn: function (aContext){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self["@homeContext"]=aContext;
-return self}, function($ctx1) {$ctx1.fill(self,"homeContext:",{aContext:aContext},smalltalk.AIContext)})},
-messageSends: []}),
+}, function($ctx1) {$ctx1.fill(self,"index",{},smalltalk.AIContext)})},
+messageSends: ["ifNil:"]}),
 smalltalk.AIContext);
 smalltalk.AIContext);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
@@ -110,31 +90,32 @@ selector: "initializeFromMethodContext:",
 fn: function (aMethodContext){
 fn: function (aMethodContext){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
+var $1,$2,$3,$4;
 self["@methodContext"]=aMethodContext;
 self["@methodContext"]=aMethodContext;
-self["@homeMethodContext"]=_st(aMethodContext)._home();
-self._pc_(_st(aMethodContext)._pc());
-self._receiver_(_st(aMethodContext)._receiver());
-self._method_(_st(aMethodContext)._method());
-$1=_st(aMethodContext)._outerContext();
-if(($receiver = $1) == nil || $receiver == undefined){
-$1;
+$1=self;
+_st($1)._pc_(_st(aMethodContext)._pc());
+_st($1)._index_(_st(aMethodContext)._index());
+_st($1)._receiver_(_st(aMethodContext)._receiver());
+$2=_st($1)._method_(_st(aMethodContext)._method());
+$3=_st(aMethodContext)._outerContext();
+if(($receiver = $3) == nil || $receiver == undefined){
+$3;
 } else {
 } else {
 var outer;
 var outer;
 outer=$receiver;
 outer=$receiver;
-$2=_st(outer)._methodContext();
-if(($receiver = $2) == nil || $receiver == undefined){
-$2;
+$4=_st(outer)._methodContext();
+if(($receiver = $4) == nil || $receiver == undefined){
+$4;
 } else {
 } else {
 self._outerContext_(_st(self._class())._fromMethodContext_(_st(aMethodContext)._outerContext()));
 self._outerContext_(_st(self._class())._fromMethodContext_(_st(aMethodContext)._outerContext()));
 };
 };
 _st(_st(aMethodContext)._locals())._keysAndValuesDo_((function(key,value){
 _st(_st(aMethodContext)._locals())._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 return _st(self._locals())._at_put_(key,value);
 return _st(self._locals())._at_put_(key,value);
-}, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,3)})}));
 };
 };
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.AIContext)})},
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.AIContext)})},
-messageSends: ["home", "pc:", "pc", "receiver:", "receiver", "method:", "method", "ifNotNil:", "outerContext", "methodContext", "outerContext:", "fromMethodContext:", "class", "keysAndValuesDo:", "locals", "at:put:"]}),
+messageSends: ["pc:", "pc", "index:", "index", "receiver:", "receiver", "method:", "method", "ifNotNil:", "outerContext", "methodContext", "outerContext:", "fromMethodContext:", "class", "keysAndValuesDo:", "locals", "at:put:"]}),
 smalltalk.AIContext);
 smalltalk.AIContext);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
@@ -1424,6 +1405,16 @@ return self}, function($ctx1) {$ctx1.fill(self,"useInlinings:",{aBoolean:aBoolea
 messageSends: []}),
 messageSends: []}),
 smalltalk.ASTPCNodeVisitor);
 smalltalk.ASTPCNodeVisitor);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "visitBlockNode:",
+fn: function (aNode){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode},smalltalk.ASTPCNodeVisitor)})},
+messageSends: []}),
+smalltalk.ASTPCNodeVisitor);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "visitJSStatementNode:",
 selector: "visitJSStatementNode:",
@@ -2078,25 +2069,6 @@ smalltalk.Interpreter);
 
 
 
 
 
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "aiContext",
-fn: function (){
-var self=this;
-function $AIContext(){return smalltalk.AIContext||(typeof AIContext=="undefined"?nil:AIContext)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self._basicAt_("aiContext");
-if(($receiver = $2) == nil || $receiver == undefined){
-$1=self._basicAt_put_("aiContext",_st($AIContext())._fromMethodContext_(self));
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"aiContext",{},smalltalk.MethodContext)})},
-messageSends: ["ifNil:", "basicAt:", "basicAt:put:", "fromMethodContext:"]}),
-smalltalk.MethodContext);
-
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "interpreter:continue:",
 selector: "interpreter:continue:",

+ 50 - 88
js/Compiler-Interpreter.js

@@ -1,5 +1,5 @@
 smalltalk.addPackage('Compiler-Interpreter');
 smalltalk.addPackage('Compiler-Interpreter');
-smalltalk.addClass('AIContext', smalltalk.Object, ['outerContext', 'innerContext', 'homeContext', 'pc', 'locals', 'method', 'ast', 'interpreter', 'methodContext', 'homeMethodContext'], 'Compiler-Interpreter');
+smalltalk.addClass('AIContext', smalltalk.Object, ['outerContext', 'innerContext', 'pc', 'locals', 'method', 'index', 'ast', 'interpreter', 'methodContext'], 'Compiler-Interpreter');
 smalltalk.AIContext.comment="I am like a `MethodContext`, used by the `ASTInterpreter`.\x0aUnlike a `MethodContext`, my instances are not read-only.\x0a\x0aWhen debugging, my instances are created by copying the current `MethodContext` (thisContext)";
 smalltalk.AIContext.comment="I am like a `MethodContext`, used by the `ASTInterpreter`.\x0aUnlike a `MethodContext`, my instances are not read-only.\x0a\x0aWhen debugging, my instances are created by copying the current `MethodContext` (thisContext)";
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -47,77 +47,47 @@ category: 'interpreting',
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=self["@ast"];
-if(($receiver = $1) == nil || $receiver == undefined){
+var $1,$2,$3,$4;
+$1=self._isBlockContext();
+if(smalltalk.assert($1)){
+$2=_st(self._outerContext())._ast();
+return $2;
+};
+$3=self["@ast"];
+if(($receiver = $3) == nil || $receiver == undefined){
 self._initializeAST();
 self._initializeAST();
 } else {
 } else {
-$1;
+$3;
 };
 };
-$2=self["@ast"];
-return $2;
+$4=self["@ast"];
+return $4;
 }, function($ctx1) {$ctx1.fill(self,"ast",{},smalltalk.AIContext)})},
 }, function($ctx1) {$ctx1.fill(self,"ast",{},smalltalk.AIContext)})},
 args: [],
 args: [],
-source: "ast\x0a\x09ast ifNil: [ self initializeAST ].\x0a\x09^ ast",
-messageSends: ["ifNil:", "initializeAST"],
-referencedClasses: []
-}),
-smalltalk.AIContext);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "home",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self._homeContext();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"home",{},smalltalk.AIContext)})},
-args: [],
-source: "home\x0a\x09^ self homeContext",
-messageSends: ["homeContext"],
+source: "ast\x0a\x09self isBlockContext ifTrue: [ ^ self outerContext ast ].\x0a\x0a\x09ast ifNil: [ self initializeAST ].\x0a\x09^ ast",
+messageSends: ["ifTrue:", "isBlockContext", "ast", "outerContext", "ifNil:", "initializeAST"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.AIContext);
 smalltalk.AIContext);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
-selector: "homeContext",
+selector: "index",
 category: 'accessing',
 category: 'accessing',
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
 var $2,$1;
 var $2,$1;
-$2=self["@homeContext"];
+$2=self["@index"];
 if(($receiver = $2) == nil || $receiver == undefined){
 if(($receiver = $2) == nil || $receiver == undefined){
-self["@homeContext"]=_st(self["@homeMethodContext"])._aiContext();
-$1=self["@homeContext"];
+$1=(0);
 } else {
 } else {
 $1=$2;
 $1=$2;
 };
 };
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"homeContext",{},smalltalk.AIContext)})},
+}, function($ctx1) {$ctx1.fill(self,"index",{},smalltalk.AIContext)})},
 args: [],
 args: [],
-source: "homeContext\x0a\x09^ homeContext ifNil: [ homeContext := homeMethodContext aiContext ]",
-messageSends: ["ifNil:", "aiContext"],
-referencedClasses: []
-}),
-smalltalk.AIContext);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "homeContext:",
-category: 'accessing',
-fn: function (aContext){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self["@homeContext"]=aContext;
-return self}, function($ctx1) {$ctx1.fill(self,"homeContext:",{aContext:aContext},smalltalk.AIContext)})},
-args: ["aContext"],
-source: "homeContext: aContext\x0a\x09homeContext := aContext",
-messageSends: [],
+source: "index\x0a\x09^ index ifNil: [ 0 ]",
+messageSends: ["ifNil:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.AIContext);
 smalltalk.AIContext);
@@ -147,33 +117,34 @@ category: 'initialization',
 fn: function (aMethodContext){
 fn: function (aMethodContext){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
+var $1,$2,$3,$4;
 self["@methodContext"]=aMethodContext;
 self["@methodContext"]=aMethodContext;
-self["@homeMethodContext"]=_st(aMethodContext)._home();
-self._pc_(_st(aMethodContext)._pc());
-self._receiver_(_st(aMethodContext)._receiver());
-self._method_(_st(aMethodContext)._method());
-$1=_st(aMethodContext)._outerContext();
-if(($receiver = $1) == nil || $receiver == undefined){
-$1;
+$1=self;
+_st($1)._pc_(_st(aMethodContext)._pc());
+_st($1)._index_(_st(aMethodContext)._index());
+_st($1)._receiver_(_st(aMethodContext)._receiver());
+$2=_st($1)._method_(_st(aMethodContext)._method());
+$3=_st(aMethodContext)._outerContext();
+if(($receiver = $3) == nil || $receiver == undefined){
+$3;
 } else {
 } else {
 var outer;
 var outer;
 outer=$receiver;
 outer=$receiver;
-$2=_st(outer)._methodContext();
-if(($receiver = $2) == nil || $receiver == undefined){
-$2;
+$4=_st(outer)._methodContext();
+if(($receiver = $4) == nil || $receiver == undefined){
+$4;
 } else {
 } else {
 self._outerContext_(_st(self._class())._fromMethodContext_(_st(aMethodContext)._outerContext()));
 self._outerContext_(_st(self._class())._fromMethodContext_(_st(aMethodContext)._outerContext()));
 };
 };
 _st(_st(aMethodContext)._locals())._keysAndValuesDo_((function(key,value){
 _st(_st(aMethodContext)._locals())._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 return _st(self._locals())._at_put_(key,value);
 return _st(self._locals())._at_put_(key,value);
-}, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,3)})}));
 };
 };
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.AIContext)})},
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.AIContext)})},
 args: ["aMethodContext"],
 args: ["aMethodContext"],
-source: "initializeFromMethodContext: aMethodContext\x0a\x09methodContext := aMethodContext.\x0a\x09homeMethodContext := aMethodContext home.\x0a\x0a\x09self pc: aMethodContext pc.\x0a\x09self receiver: aMethodContext receiver.\x0a\x09self method: aMethodContext method.\x0a\x09aMethodContext outerContext ifNotNil: [ :outer |\x0a\x09\x09\x22If the method context is nil, the block was defined in JS, so ignore it\x22\x0a\x09\x09outer methodContext ifNotNil: [\x0a\x09\x09\x09self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].\x0a\x09\x09\x09aMethodContext locals keysAndValuesDo: [ :key :value |\x0a\x09\x09\x09\x09self locals at: key put: value ] ]",
-messageSends: ["home", "pc:", "pc", "receiver:", "receiver", "method:", "method", "ifNotNil:", "outerContext", "methodContext", "outerContext:", "fromMethodContext:", "class", "keysAndValuesDo:", "locals", "at:put:"],
+source: "initializeFromMethodContext: aMethodContext\x0a\x09methodContext := aMethodContext.\x0a\x0a\x09self \x0a\x09\x09pc: aMethodContext pc;\x0a\x09\x09index: aMethodContext index;\x0a\x09\x09receiver: aMethodContext receiver;\x0a\x09\x09method: aMethodContext method.\x0a\x09\x09\x0a\x09aMethodContext outerContext ifNotNil: [ :outer |\x0a\x09\x09\x22If the method context is nil, the block was defined in JS, so ignore it\x22\x0a\x09\x09outer methodContext ifNotNil: [\x0a\x09\x09\x09self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].\x0a\x09\x09\x09aMethodContext locals keysAndValuesDo: [ :key :value |\x0a\x09\x09\x09\x09self locals at: key put: value ] ]",
+messageSends: ["pc:", "pc", "index:", "index", "receiver:", "receiver", "method:", "method", "ifNotNil:", "outerContext", "methodContext", "outerContext:", "fromMethodContext:", "class", "keysAndValuesDo:", "locals", "at:put:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.AIContext);
 smalltalk.AIContext);
@@ -1884,6 +1855,21 @@ referencedClasses: []
 }),
 }),
 smalltalk.ASTPCNodeVisitor);
 smalltalk.ASTPCNodeVisitor);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "visitBlockNode:",
+category: 'visiting',
+fn: function (aNode){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode},smalltalk.ASTPCNodeVisitor)})},
+args: ["aNode"],
+source: "visitBlockNode: aNode",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ASTPCNodeVisitor);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "visitJSStatementNode:",
 selector: "visitJSStatementNode:",
@@ -2738,30 +2724,6 @@ smalltalk.Interpreter);
 
 
 
 
 
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "aiContext",
-category: '*Compiler-Interpreter',
-fn: function (){
-var self=this;
-function $AIContext(){return smalltalk.AIContext||(typeof AIContext=="undefined"?nil:AIContext)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self._basicAt_("aiContext");
-if(($receiver = $2) == nil || $receiver == undefined){
-$1=self._basicAt_put_("aiContext",_st($AIContext())._fromMethodContext_(self));
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"aiContext",{},smalltalk.MethodContext)})},
-args: [],
-source: "aiContext\x0a\x09^ (self basicAt: 'aiContext') ifNil: [\x0a\x09\x09self basicAt: 'aiContext' put: (AIContext fromMethodContext: self) ]",
-messageSends: ["ifNil:", "basicAt:", "basicAt:put:", "fromMethodContext:"],
-referencedClasses: ["AIContext"]
-}),
-smalltalk.MethodContext);
-
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "interpreter:continue:",
 selector: "interpreter:continue:",

+ 54 - 3
js/Compiler-Semantic.deploy.js

@@ -1,5 +1,5 @@
 smalltalk.addPackage('Compiler-Semantic');
 smalltalk.addPackage('Compiler-Semantic');
-smalltalk.addClass('LexicalScope', smalltalk.Object, ['node', 'instruction', 'temps', 'args', 'outerScope'], 'Compiler-Semantic');
+smalltalk.addClass('LexicalScope', smalltalk.Object, ['node', 'instruction', 'temps', 'args', 'outerScope', 'blockIndex'], 'Compiler-Semantic');
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "addArg:",
 selector: "addArg:",
@@ -94,6 +94,35 @@ return $1;
 messageSends: ["at:ifAbsent:", "pseudoVars", "value", "args", "temps"]}),
 messageSends: ["at:ifAbsent:", "pseudoVars", "value", "args", "temps"]}),
 smalltalk.LexicalScope);
 smalltalk.LexicalScope);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "blockIndex",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@blockIndex"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(0);
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"blockIndex",{},smalltalk.LexicalScope)})},
+messageSends: ["ifNil:"]}),
+smalltalk.LexicalScope);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "blockIndex:",
+fn: function (anInteger){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@blockIndex"]=anInteger;
+return self}, function($ctx1) {$ctx1.fill(self,"blockIndex:",{anInteger:anInteger},smalltalk.LexicalScope)})},
+messageSends: []}),
+smalltalk.LexicalScope);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "canInlineNonLocalReturns",
 selector: "canInlineNonLocalReturns",
@@ -898,7 +927,7 @@ smalltalk.UnknownVar);
 
 
 
 
 
 
-smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends', 'superSends'], 'Compiler-Semantic');
+smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends', 'superSends', 'blockIndex'], 'Compiler-Semantic');
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "classReferences",
 selector: "classReferences",
@@ -1035,6 +1064,27 @@ return $1;
 messageSends: ["outerScope:", "new", "yourself"]}),
 messageSends: ["outerScope:", "new", "yourself"]}),
 smalltalk.SemanticAnalyzer);
 smalltalk.SemanticAnalyzer);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "nextBlockIndex",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=self["@blockIndex"];
+if(($receiver = $1) == nil || $receiver == undefined){
+self["@blockIndex"]=(0);
+self["@blockIndex"];
+} else {
+$1;
+};
+self["@blockIndex"]=_st(self["@blockIndex"]).__plus((1));
+$2=self["@blockIndex"];
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"nextBlockIndex",{},smalltalk.SemanticAnalyzer)})},
+messageSends: ["ifNil:", "+"]}),
+smalltalk.SemanticAnalyzer);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "popScope",
 selector: "popScope",
@@ -1147,6 +1197,7 @@ return smalltalk.withContext(function($ctx1) {
 self._pushScope_(self._newBlockScope());
 self._pushScope_(self._newBlockScope());
 _st(aNode)._scope_(self["@currentScope"]);
 _st(aNode)._scope_(self["@currentScope"]);
 _st(self["@currentScope"])._node_(aNode);
 _st(self["@currentScope"])._node_(aNode);
+_st(self["@currentScope"])._blockIndex_(self._nextBlockIndex());
 _st(_st(aNode)._parameters())._do_((function(each){
 _st(_st(aNode)._parameters())._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 self._validateVariableScope_(each);
 self._validateVariableScope_(each);
@@ -1155,7 +1206,7 @@ return _st(self["@currentScope"])._addArg_(each);
 smalltalk.NodeVisitor.fn.prototype._visitBlockNode_.apply(_st(self), [aNode]);
 smalltalk.NodeVisitor.fn.prototype._visitBlockNode_.apply(_st(self), [aNode]);
 self._popScope();
 self._popScope();
 return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode},smalltalk.SemanticAnalyzer)})},
 return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode},smalltalk.SemanticAnalyzer)})},
-messageSends: ["pushScope:", "newBlockScope", "scope:", "node:", "do:", "parameters", "validateVariableScope:", "addArg:", "visitBlockNode:", "popScope"]}),
+messageSends: ["pushScope:", "newBlockScope", "scope:", "node:", "blockIndex:", "nextBlockIndex", "do:", "parameters", "validateVariableScope:", "addArg:", "visitBlockNode:", "popScope"]}),
 smalltalk.SemanticAnalyzer);
 smalltalk.SemanticAnalyzer);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(

+ 70 - 4
js/Compiler-Semantic.js

@@ -1,5 +1,5 @@
 smalltalk.addPackage('Compiler-Semantic');
 smalltalk.addPackage('Compiler-Semantic');
-smalltalk.addClass('LexicalScope', smalltalk.Object, ['node', 'instruction', 'temps', 'args', 'outerScope'], 'Compiler-Semantic');
+smalltalk.addClass('LexicalScope', smalltalk.Object, ['node', 'instruction', 'temps', 'args', 'outerScope', 'blockIndex'], 'Compiler-Semantic');
 smalltalk.LexicalScope.comment="I represent a lexical scope where variable names are associated with ScopeVars\x0aInstances are used for block scopes. Method scopes are instances of MethodLexicalScope.\x0a\x0aI am attached to a ScopeVar and method/block nodes.\x0aEach context (method/closure) get a fresh scope that inherits from its outer scope.";
 smalltalk.LexicalScope.comment="I represent a lexical scope where variable names are associated with ScopeVars\x0aInstances are used for block scopes. Method scopes are instances of MethodLexicalScope.\x0a\x0aI am attached to a ScopeVar and method/block nodes.\x0aEach context (method/closure) get a fresh scope that inherits from its outer scope.";
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -125,6 +125,45 @@ referencedClasses: []
 }),
 }),
 smalltalk.LexicalScope);
 smalltalk.LexicalScope);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "blockIndex",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@blockIndex"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(0);
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"blockIndex",{},smalltalk.LexicalScope)})},
+args: [],
+source: "blockIndex\x0a\x09^ blockIndex ifNil: [ 0 ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.LexicalScope);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "blockIndex:",
+category: 'accessing',
+fn: function (anInteger){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@blockIndex"]=anInteger;
+return self}, function($ctx1) {$ctx1.fill(self,"blockIndex:",{anInteger:anInteger},smalltalk.LexicalScope)})},
+args: ["anInteger"],
+source: "blockIndex: anInteger \x0a\x09blockIndex := anInteger",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.LexicalScope);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "canInlineNonLocalReturns",
 selector: "canInlineNonLocalReturns",
@@ -1213,7 +1252,7 @@ smalltalk.UnknownVar);
 
 
 
 
 
 
-smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends', 'superSends'], 'Compiler-Semantic');
+smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends', 'superSends', 'blockIndex'], 'Compiler-Semantic');
 smalltalk.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.";
 smalltalk.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.";
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1391,6 +1430,32 @@ referencedClasses: []
 }),
 }),
 smalltalk.SemanticAnalyzer);
 smalltalk.SemanticAnalyzer);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "nextBlockIndex",
+category: 'private',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=self["@blockIndex"];
+if(($receiver = $1) == nil || $receiver == undefined){
+self["@blockIndex"]=(0);
+self["@blockIndex"];
+} else {
+$1;
+};
+self["@blockIndex"]=_st(self["@blockIndex"]).__plus((1));
+$2=self["@blockIndex"];
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"nextBlockIndex",{},smalltalk.SemanticAnalyzer)})},
+args: [],
+source: "nextBlockIndex\x0a\x09blockIndex ifNil: [ blockIndex := 0 ].\x0a\x09\x0a\x09blockIndex := blockIndex + 1.\x0a\x09^ blockIndex",
+messageSends: ["ifNil:", "+"],
+referencedClasses: []
+}),
+smalltalk.SemanticAnalyzer);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "popScope",
 selector: "popScope",
@@ -1539,6 +1604,7 @@ return smalltalk.withContext(function($ctx1) {
 self._pushScope_(self._newBlockScope());
 self._pushScope_(self._newBlockScope());
 _st(aNode)._scope_(self["@currentScope"]);
 _st(aNode)._scope_(self["@currentScope"]);
 _st(self["@currentScope"])._node_(aNode);
 _st(self["@currentScope"])._node_(aNode);
+_st(self["@currentScope"])._blockIndex_(self._nextBlockIndex());
 _st(_st(aNode)._parameters())._do_((function(each){
 _st(_st(aNode)._parameters())._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 self._validateVariableScope_(each);
 self._validateVariableScope_(each);
@@ -1548,8 +1614,8 @@ smalltalk.NodeVisitor.fn.prototype._visitBlockNode_.apply(_st(self), [aNode]);
 self._popScope();
 self._popScope();
 return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode},smalltalk.SemanticAnalyzer)})},
 return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode},smalltalk.SemanticAnalyzer)})},
 args: ["aNode"],
 args: ["aNode"],
-source: "visitBlockNode: aNode\x0a\x09self pushScope: self newBlockScope.\x0a\x09aNode scope: currentScope.\x0a\x09currentScope node: aNode.\x0a\x09\x0a\x09aNode parameters do: [ :each |\x0a\x09\x09self validateVariableScope: each.\x0a\x09\x09currentScope addArg: each ].\x0a\x0a\x09super visitBlockNode: aNode.\x0a\x09self popScope",
-messageSends: ["pushScope:", "newBlockScope", "scope:", "node:", "do:", "parameters", "validateVariableScope:", "addArg:", "visitBlockNode:", "popScope"],
+source: "visitBlockNode: aNode\x0a\x09self pushScope: self newBlockScope.\x0a\x09aNode scope: currentScope.\x0a\x09currentScope node: aNode.\x0a\x09currentScope blockIndex: self nextBlockIndex.\x0a\x09\x0a\x09aNode parameters do: [ :each |\x0a\x09\x09self validateVariableScope: each.\x0a\x09\x09currentScope addArg: each ].\x0a\x0a\x09super visitBlockNode: aNode.\x0a\x09self popScope",
+messageSends: ["pushScope:", "newBlockScope", "scope:", "node:", "blockIndex:", "nextBlockIndex", "do:", "parameters", "validateVariableScope:", "addArg:", "visitBlockNode:", "popScope"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.SemanticAnalyzer);
 smalltalk.SemanticAnalyzer);

+ 3 - 2
js/Helios-Debugger.deploy.js

@@ -541,11 +541,12 @@ smalltalk.method({
 selector: "initializeFromContext:",
 selector: "initializeFromContext:",
 fn: function (aMethodContext){
 fn: function (aMethodContext){
 var self=this;
 var self=this;
+function $AIContext(){return smalltalk.AIContext||(typeof AIContext=="undefined"?nil:AIContext)}
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
-self["@rootContext"]=_st(aMethodContext)._aiContext();
+self["@rootContext"]=_st($AIContext())._fromMethodContext_(aMethodContext);
 self._initializeContexts();
 self._initializeContexts();
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel)})},
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel)})},
-messageSends: ["aiContext", "initializeContexts"]}),
+messageSends: ["fromMethodContext:", "initializeContexts"]}),
 smalltalk.HLDebuggerModel);
 smalltalk.HLDebuggerModel);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(

+ 5 - 4
js/Helios-Debugger.js

@@ -709,14 +709,15 @@ selector: "initializeFromContext:",
 category: 'initialization',
 category: 'initialization',
 fn: function (aMethodContext){
 fn: function (aMethodContext){
 var self=this;
 var self=this;
+function $AIContext(){return smalltalk.AIContext||(typeof AIContext=="undefined"?nil:AIContext)}
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
-self["@rootContext"]=_st(aMethodContext)._aiContext();
+self["@rootContext"]=_st($AIContext())._fromMethodContext_(aMethodContext);
 self._initializeContexts();
 self._initializeContexts();
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel)})},
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel)})},
 args: ["aMethodContext"],
 args: ["aMethodContext"],
-source: "initializeFromContext: aMethodContext\x0a\x09rootContext := aMethodContext aiContext.\x0a\x09self initializeContexts",
-messageSends: ["aiContext", "initializeContexts"],
-referencedClasses: []
+source: "initializeFromContext: aMethodContext\x0a\x09rootContext := AIContext fromMethodContext: aMethodContext.\x0a\x09self initializeContexts",
+messageSends: ["fromMethodContext:", "initializeContexts"],
+referencedClasses: ["AIContext"]
 }),
 }),
 smalltalk.HLDebuggerModel);
 smalltalk.HLDebuggerModel);
 
 

+ 11 - 0
js/Kernel-Methods.deploy.js

@@ -1094,6 +1094,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"home",{},smalltalk.MethodContext
 messageSends: []}),
 messageSends: []}),
 smalltalk.MethodContext);
 smalltalk.MethodContext);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "index",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self.index || 0;
+return self}, function($ctx1) {$ctx1.fill(self,"index",{},smalltalk.MethodContext)})},
+messageSends: []}),
+smalltalk.MethodContext);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "isBlockContext",
 selector: "isBlockContext",

+ 16 - 0
js/Kernel-Methods.js

@@ -1485,6 +1485,22 @@ referencedClasses: []
 }),
 }),
 smalltalk.MethodContext);
 smalltalk.MethodContext);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "index",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self.index || 0;
+return self}, function($ctx1) {$ctx1.fill(self,"index",{},smalltalk.MethodContext)})},
+args: [],
+source: "index\x0a\x09<return self.index || 0>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "isBlockContext",
 selector: "isBlockContext",

+ 5 - 5
js/boot.js

@@ -556,10 +556,10 @@ function Smalltalk() {
 		}
 		}
 	};
 	};
 
 
-	st.withContext = function(worker, setup, index) {
+	st.withContext = function(worker, setup) {
 		if(st.thisContext) {
 		if(st.thisContext) {
             st.thisContext.pc++;
             st.thisContext.pc++;
-			return inContext(worker, setup, index);
+			return inContext(worker, setup);
 		} else {
 		} else {
 			try {
 			try {
 				return inContext(worker, setup);
 				return inContext(worker, setup);
@@ -582,9 +582,8 @@ function Smalltalk() {
 		}
 		}
 	};
 	};
 
 
-	function inContext(worker, setup, index) {
+	function inContext(worker, setup) {
 		var context = pushContext(setup);
 		var context = pushContext(setup);
-        context.index = index || 0;
 		var result = worker(context);
 		var result = worker(context);
 		popContext(context);
 		popContext(context);
 		return result;
 		return result;
@@ -793,9 +792,10 @@ SmalltalkMethodContext.prototype.fill = function(receiver, selector, locals, loo
 	this.lookupClass = lookupClass;
 	this.lookupClass = lookupClass;
 };
 };
 
 
-SmalltalkMethodContext.prototype.fillBlock = function(locals, ctx) {
+SmalltalkMethodContext.prototype.fillBlock = function(locals, ctx, index) {
 	this.locals        = locals || {};
 	this.locals        = locals || {};
 	this.outerContext  = ctx;
 	this.outerContext  = ctx;
+    this.index         = index || 0;
 };
 };
 
 
 SmalltalkMethodContext.prototype.init = function() {
 SmalltalkMethodContext.prototype.init = function() {

+ 1 - 1
st/Compiler-IR.st

@@ -1076,7 +1076,7 @@ nextPutBlockContextFor: anIRClosure during: aBlock
 	
 	
 	self
 	self
 		nextPutAll: '},';
 		nextPutAll: '},';
-		nextPutAll: anIRClosure scope outerScope alias, ')})'
+		nextPutAll: anIRClosure scope outerScope alias, ',', anIRClosure scope blockIndex asString, ')})'
 !
 !
 
 
 nextPutClassRefFunction: aString
 nextPutClassRefFunction: aString

+ 14 - 22
st/Compiler-Interpreter.st

@@ -1,6 +1,6 @@
 Smalltalk current createPackage: 'Compiler-Interpreter'!
 Smalltalk current createPackage: 'Compiler-Interpreter'!
 Object subclass: #AIContext
 Object subclass: #AIContext
-	instanceVariableNames: 'outerContext innerContext homeContext pc locals method ast interpreter methodContext homeMethodContext'
+	instanceVariableNames: 'outerContext innerContext pc locals method index ast interpreter methodContext'
 	package: 'Compiler-Interpreter'!
 	package: 'Compiler-Interpreter'!
 !AIContext commentStamp!
 !AIContext commentStamp!
 I am like a `MethodContext`, used by the `ASTInterpreter`.
 I am like a `MethodContext`, used by the `ASTInterpreter`.
@@ -10,16 +10,8 @@ When debugging, my instances are created by copying the current `MethodContext`
 
 
 !AIContext methodsFor: 'accessing'!
 !AIContext methodsFor: 'accessing'!
 
 
-home
-	^ self homeContext
-!
-
-homeContext
-	^ homeContext ifNil: [ homeContext := homeMethodContext aiContext ]
-!
-
-homeContext: aContext
-	homeContext := aContext
+index
+	^ index ifNil: [ 0 ]
 !
 !
 
 
 innerContext
 innerContext
@@ -82,11 +74,13 @@ initializeAST
 
 
 initializeFromMethodContext: aMethodContext
 initializeFromMethodContext: aMethodContext
 	methodContext := aMethodContext.
 	methodContext := aMethodContext.
-	homeMethodContext := aMethodContext home.
 
 
-	self pc: aMethodContext pc.
-	self receiver: aMethodContext receiver.
-	self method: aMethodContext method.
+	self 
+		pc: aMethodContext pc;
+		index: aMethodContext index;
+		receiver: aMethodContext receiver;
+		method: aMethodContext method.
+		
 	aMethodContext outerContext ifNotNil: [ :outer |
 	aMethodContext outerContext ifNotNil: [ :outer |
 		"If the method context is nil, the block was defined in JS, so ignore it"
 		"If the method context is nil, the block was defined in JS, so ignore it"
 		outer methodContext ifNotNil: [
 		outer methodContext ifNotNil: [
@@ -117,6 +111,8 @@ arguments
 !
 !
 
 
 ast
 ast
+	self isBlockContext ifTrue: [ ^ self outerContext ast ].
+
 	ast ifNil: [ self initializeAST ].
 	ast ifNil: [ self initializeAST ].
 	^ ast
 	^ ast
 !
 !
@@ -673,6 +669,9 @@ useInlinings: aBoolean
 
 
 !ASTPCNodeVisitor methodsFor: 'visiting'!
 !ASTPCNodeVisitor methodsFor: 'visiting'!
 
 
+visitBlockNode: aNode
+!
+
 visitJSStatementNode: aNode
 visitJSStatementNode: aNode
 	currentNode := aNode
 	currentNode := aNode
 !
 !
@@ -982,13 +981,6 @@ visitVariableNode: aNode
 		ifFalse: [ self context localAt: aNode value ])
 		ifFalse: [ self context localAt: aNode value ])
 ! !
 ! !
 
 
-!MethodContext methodsFor: '*Compiler-Interpreter'!
-
-aiContext
-	^ (self basicAt: 'aiContext') ifNil: [
-		self basicAt: 'aiContext' put: (AIContext fromMethodContext: self) ]
-! !
-
 !Node methodsFor: '*Compiler-Interpreter'!
 !Node methodsFor: '*Compiler-Interpreter'!
 
 
 interpreter: anInterpreter continue: aBlock
 interpreter: anInterpreter continue: aBlock

+ 20 - 2
st/Compiler-Semantic.st

@@ -1,6 +1,6 @@
 Smalltalk current createPackage: 'Compiler-Semantic'!
 Smalltalk current createPackage: 'Compiler-Semantic'!
 Object subclass: #LexicalScope
 Object subclass: #LexicalScope
-	instanceVariableNames: 'node instruction temps args outerScope'
+	instanceVariableNames: 'node instruction temps args outerScope blockIndex'
 	package: 'Compiler-Semantic'!
 	package: 'Compiler-Semantic'!
 !LexicalScope commentStamp!
 !LexicalScope commentStamp!
 I represent a lexical scope where variable names are associated with ScopeVars
 I represent a lexical scope where variable names are associated with ScopeVars
@@ -29,6 +29,14 @@ bindingFor: aStringOrNode
 			self temps at: aStringOrNode value ifAbsent: [ nil ]]]
 			self temps at: aStringOrNode value ifAbsent: [ nil ]]]
 !
 !
 
 
+blockIndex
+	^ blockIndex ifNil: [ 0 ]
+!
+
+blockIndex: anInteger 
+	blockIndex := anInteger
+!
+
 instruction
 instruction
 	^ instruction
 	^ instruction
 !
 !
@@ -380,7 +388,7 @@ isUnknownVar
 ! !
 ! !
 
 
 NodeVisitor subclass: #SemanticAnalyzer
 NodeVisitor subclass: #SemanticAnalyzer
-	instanceVariableNames: 'currentScope theClass classReferences messageSends superSends'
+	instanceVariableNames: 'currentScope theClass classReferences messageSends superSends blockIndex'
 	package: 'Compiler-Semantic'!
 	package: 'Compiler-Semantic'!
 !SemanticAnalyzer commentStamp!
 !SemanticAnalyzer commentStamp!
 I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
 I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
@@ -452,6 +460,15 @@ newScopeOfClass: aLexicalScopeClass
 		yourself
 		yourself
 ! !
 ! !
 
 
+!SemanticAnalyzer methodsFor: 'private'!
+
+nextBlockIndex
+	blockIndex ifNil: [ blockIndex := 0 ].
+	
+	blockIndex := blockIndex + 1.
+	^ blockIndex
+! !
+
 !SemanticAnalyzer methodsFor: 'scope'!
 !SemanticAnalyzer methodsFor: 'scope'!
 
 
 popScope
 popScope
@@ -488,6 +505,7 @@ visitBlockNode: aNode
 	self pushScope: self newBlockScope.
 	self pushScope: self newBlockScope.
 	aNode scope: currentScope.
 	aNode scope: currentScope.
 	currentScope node: aNode.
 	currentScope node: aNode.
+	currentScope blockIndex: self nextBlockIndex.
 	
 	
 	aNode parameters do: [ :each |
 	aNode parameters do: [ :each |
 		self validateVariableScope: each.
 		self validateVariableScope: each.

+ 1 - 1
st/Helios-Debugger.st

@@ -314,7 +314,7 @@ initializeContexts
 !
 !
 
 
 initializeFromContext: aMethodContext
 initializeFromContext: aMethodContext
-	rootContext := aMethodContext aiContext.
+	rootContext := AIContext fromMethodContext: aMethodContext.
 	self initializeContexts
 	self initializeContexts
 ! !
 ! !
 
 

+ 4 - 0
st/Kernel-Methods.st

@@ -564,6 +564,10 @@ home
 	<return self.homeContext>
 	<return self.homeContext>
 !
 !
 
 
+index
+	<return self.index || 0>
+!
+
 locals
 locals
 	<return self.locals || {}>
 	<return self.locals || {}>
 !
 !