Browse Source

- IAContext for the AST interpreter
- JSObjectProxy >> keysAndValuesDo:

Nicolas Petton 11 years ago
parent
commit
6ddb40ebca

+ 166 - 3
js/Compiler-Interpreter.deploy.js

@@ -1,4 +1,167 @@
 smalltalk.addPackage('Compiler-Interpreter', {});
+smalltalk.addClass('AIContext', smalltalk.NodeVisitor, ['outerContext', 'pc', 'locals', 'receiver', 'selector'], 'Compiler-Interpreter');
+smalltalk.addMethod(
+"_initializeFromMethodContext_",
+smalltalk.method({
+selector: "initializeFromMethodContext:",
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st(self)._pc_(_st(aMethodContext)._pc());
+_st(self)._receiver_(_st(aMethodContext)._receiver());
+_st(self)._selector_(_st(aMethodContext)._selector());
+$1=_st(aMethodContext)._outerContext();
+if(($receiver = $1) == nil || $receiver == undefined){
+$1;
+} else {
+_st(self)._outerContext_(_st(_st(self)._class())._fromMethodContext_(_st(aMethodContext)._outerContext()));
+};
+_st(_st(aMethodContext)._locals())._keysAndValuesDo_((function(key,value){
+return smalltalk.withContext(function($ctx2) { 
return _st(_st(self)._locals())._at_put_(key,value);
+})}));
+return self}, self, "initializeFromMethodContext:", [aMethodContext], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_locals",
+smalltalk.method({
+selector: "locals",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@locals"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@locals"]=_st((smalltalk.Dictionary || Dictionary))._new();
+$1=self["@locals"];
+} else {
+$1=$2;
+};
+return $1;
+}, self, "locals", [], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_outerContext",
+smalltalk.method({
+selector: "outerContext",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@outerContext"];
+return $1;
+}, self, "outerContext", [], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_outerContext_",
+smalltalk.method({
+selector: "outerContext:",
+fn: function (anAIContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@outerContext"]=anAIContext;
+return self}, self, "outerContext:", [anAIContext], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_pc",
+smalltalk.method({
+selector: "pc",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@pc"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@pc"]=(0);
+$1=self["@pc"];
+} else {
+$1=$2;
+};
+return $1;
+}, self, "pc", [], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_pc_",
+smalltalk.method({
+selector: "pc:",
+fn: function (anInteger){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@pc"]=anInteger;
+return self}, self, "pc:", [anInteger], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_receiver",
+smalltalk.method({
+selector: "receiver",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@receiver"];
+return $1;
+}, self, "receiver", [], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_receiver_",
+smalltalk.method({
+selector: "receiver:",
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@receiver"]=anObject;
+return self}, self, "receiver:", [anObject], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_selector",
+smalltalk.method({
+selector: "selector",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@selector"];
+return $1;
+}, self, "selector", [], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_selector_",
+smalltalk.method({
+selector: "selector:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@selector"]=aString;
+return self}, self, "selector:", [aString], smalltalk.AIContext)}
+}),
+smalltalk.AIContext);
+
+
+smalltalk.addMethod(
+"_fromMethodContext_",
+smalltalk.method({
+selector: "fromMethodContext:",
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromMethodContext_(aMethodContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, self, "fromMethodContext:", [aMethodContext], smalltalk.AIContext.klass)}
+}),
+smalltalk.AIContext.klass);
+
+
 smalltalk.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn'], 'Compiler-Interpreter');
 smalltalk.addMethod(
 "_context",
@@ -15,10 +178,10 @@ smalltalk.addMethod(
 "_context_",
 smalltalk.method({
 selector: "context:",
-fn: function (aMethodContext){
+fn: function (anAIContext){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@context"]=aMethodContext;
-return self}, self, "context:", [aMethodContext], smalltalk.ASTInterpreter)}
+return smalltalk.withContext(function($ctx1) { 
self["@context"]=anAIContext;
+return self}, self, "context:", [anAIContext], smalltalk.ASTInterpreter)}
 }),
 smalltalk.ASTInterpreter);
 

+ 223 - 5
js/Compiler-Interpreter.js

@@ -1,4 +1,222 @@
 smalltalk.addPackage('Compiler-Interpreter', {});
+smalltalk.addClass('AIContext', smalltalk.NodeVisitor, ['outerContext', 'pc', 'locals', 'receiver', 'selector'], 'Compiler-Interpreter');
+smalltalk.addMethod(
+"_initializeFromMethodContext_",
+smalltalk.method({
+selector: "initializeFromMethodContext:",
+category: 'accessing',
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st(self)._pc_(_st(aMethodContext)._pc());
+_st(self)._receiver_(_st(aMethodContext)._receiver());
+_st(self)._selector_(_st(aMethodContext)._selector());
+$1=_st(aMethodContext)._outerContext();
+if(($receiver = $1) == nil || $receiver == undefined){
+$1;
+} else {
+_st(self)._outerContext_(_st(_st(self)._class())._fromMethodContext_(_st(aMethodContext)._outerContext()));
+};
+_st(_st(aMethodContext)._locals())._keysAndValuesDo_((function(key,value){
+return smalltalk.withContext(function($ctx2) { 
return _st(_st(self)._locals())._at_put_(key,value);
+})}));
+return self}, self, "initializeFromMethodContext:", [aMethodContext], smalltalk.AIContext)},
+args: ["aMethodContext"],
+source: "initializeFromMethodContext: aMethodContext\x0a\x09self pc: aMethodContext pc.\x0a    self receiver: aMethodContext receiver.\x0a    self selector: aMethodContext selector.\x0a    aMethodContext outerContext ifNotNil: [\x0a\x09\x09self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].\x0a    aMethodContext locals keysAndValuesDo: [ :key :value |\x0a    \x09self locals at: key put: value ]\x0a    ",
+messageSends: ["pc:", "pc", "receiver:", "receiver", "selector:", "selector", "ifNotNil:", "outerContext:", "fromMethodContext:", "outerContext", "class", "keysAndValuesDo:", "at:put:", "locals"],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_locals",
+smalltalk.method({
+selector: "locals",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@locals"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@locals"]=_st((smalltalk.Dictionary || Dictionary))._new();
+$1=self["@locals"];
+} else {
+$1=$2;
+};
+return $1;
+}, self, "locals", [], smalltalk.AIContext)},
+args: [],
+source: "locals\x0a\x09^ locals ifNil: [ locals := Dictionary new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["Dictionary"]
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_outerContext",
+smalltalk.method({
+selector: "outerContext",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@outerContext"];
+return $1;
+}, self, "outerContext", [], smalltalk.AIContext)},
+args: [],
+source: "outerContext\x0a\x09^ outerContext",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_outerContext_",
+smalltalk.method({
+selector: "outerContext:",
+category: 'accessing',
+fn: function (anAIContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@outerContext"]=anAIContext;
+return self}, self, "outerContext:", [anAIContext], smalltalk.AIContext)},
+args: ["anAIContext"],
+source: "outerContext: anAIContext\x0a\x09outerContext := anAIContext",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_pc",
+smalltalk.method({
+selector: "pc",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@pc"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@pc"]=(0);
+$1=self["@pc"];
+} else {
+$1=$2;
+};
+return $1;
+}, self, "pc", [], smalltalk.AIContext)},
+args: [],
+source: "pc\x0a\x09^ pc ifNil: [ pc := 0 ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_pc_",
+smalltalk.method({
+selector: "pc:",
+category: 'accessing',
+fn: function (anInteger){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@pc"]=anInteger;
+return self}, self, "pc:", [anInteger], smalltalk.AIContext)},
+args: ["anInteger"],
+source: "pc: anInteger\x0a\x09pc := anInteger",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_receiver",
+smalltalk.method({
+selector: "receiver",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@receiver"];
+return $1;
+}, self, "receiver", [], smalltalk.AIContext)},
+args: [],
+source: "receiver\x0a\x09^ receiver",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_receiver_",
+smalltalk.method({
+selector: "receiver:",
+category: 'accessing',
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@receiver"]=anObject;
+return self}, self, "receiver:", [anObject], smalltalk.AIContext)},
+args: ["anObject"],
+source: "receiver: anObject\x0a\x09receiver := anObject",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_selector",
+smalltalk.method({
+selector: "selector",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@selector"];
+return $1;
+}, self, "selector", [], smalltalk.AIContext)},
+args: [],
+source: "selector\x0a\x09^ selector",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+"_selector_",
+smalltalk.method({
+selector: "selector:",
+category: 'accessing',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@selector"]=aString;
+return self}, self, "selector:", [aString], smalltalk.AIContext)},
+args: ["aString"],
+source: "selector: aString\x0a\x09selector := aString",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+
+smalltalk.addMethod(
+"_fromMethodContext_",
+smalltalk.method({
+selector: "fromMethodContext:",
+category: 'instance creation',
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromMethodContext_(aMethodContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, self, "fromMethodContext:", [aMethodContext], smalltalk.AIContext.klass)},
+args: ["aMethodContext"],
+source: "fromMethodContext: aMethodContext\x0a\x09^ self new \x0a    \x09initializeFromMethodContext: aMethodContext;\x0a        yourself",
+messageSends: ["initializeFromMethodContext:", "new", "yourself"],
+referencedClasses: []
+}),
+smalltalk.AIContext.klass);
+
+
 smalltalk.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn'], 'Compiler-Interpreter');
 smalltalk.addMethod(
 "_context",
@@ -21,12 +239,12 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: "context:",
 category: 'accessing',
-fn: function (aMethodContext){
+fn: function (anAIContext){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@context"]=aMethodContext;
-return self}, self, "context:", [aMethodContext], smalltalk.ASTInterpreter)},
-args: ["aMethodContext"],
-source: "context: aMethodContext\x0a\x09context := aMethodContext",
+return smalltalk.withContext(function($ctx1) { 
self["@context"]=anAIContext;
+return self}, self, "context:", [anAIContext], smalltalk.ASTInterpreter)},
+args: ["anAIContext"],
+source: "context: anAIContext\x0a\x09context := anAIContext",
 messageSends: [],
 referencedClasses: []
 }),

+ 20 - 1
js/Kernel-Methods.deploy.js

@@ -713,6 +713,19 @@ return self}, self, "locals", [], smalltalk.MethodContext)}
 }),
 smalltalk.MethodContext);
 
+smalltalk.addMethod(
+"_outerContext",
+smalltalk.method({
+selector: "outerContext",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._home();
+return $1;
+}, self, "outerContext", [], smalltalk.MethodContext)}
+}),
+smalltalk.MethodContext);
+
 smalltalk.addMethod(
 "_pc",
 smalltalk.method({
@@ -756,7 +769,13 @@ smalltalk.method({
 selector: "selector",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return smalltalk.convertSelector(self.selector);
+return smalltalk.withContext(function($ctx1) { 
+    	if(self.selector) {
+        	return smalltalk.convertSelector(self.selector);
+        } else {
+        	return nil;
+        }
+    ;
 ;
 return self}, self, "selector", [], smalltalk.MethodContext)}
 }),

+ 26 - 2
js/Kernel-Methods.js

@@ -977,6 +977,24 @@ referencedClasses: []
 }),
 smalltalk.MethodContext);
 
+smalltalk.addMethod(
+"_outerContext",
+smalltalk.method({
+selector: "outerContext",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._home();
+return $1;
+}, self, "outerContext", [], smalltalk.MethodContext)},
+args: [],
+source: "outerContext\x0a\x09^ self home",
+messageSends: ["home"],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
 smalltalk.addMethod(
 "_pc",
 smalltalk.method({
@@ -1036,11 +1054,17 @@ selector: "selector",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return smalltalk.convertSelector(self.selector);
+return smalltalk.withContext(function($ctx1) { 
+    	if(self.selector) {
+        	return smalltalk.convertSelector(self.selector);
+        } else {
+        	return nil;
+        }
+    ;
 ;
 return self}, self, "selector", [], smalltalk.MethodContext)},
 args: [],
-source: "selector\x0a\x09<return smalltalk.convertSelector(self.selector)>",
+source: "selector\x0a\x09<\x0a    \x09if(self.selector) {\x0a        \x09return smalltalk.convertSelector(self.selector);\x0a        } else {\x0a        \x09return nil;\x0a        }\x0a    >",
 messageSends: [],
 referencedClasses: []
 }),

+ 16 - 0
js/Kernel-Objects.deploy.js

@@ -1719,6 +1719,22 @@ return self}, self, "jsObject:", [aJSObject], smalltalk.JSObjectProxy)}
 }),
 smalltalk.JSObjectProxy);
 
+smalltalk.addMethod(
+"_keysAndValuesDo_",
+smalltalk.method({
+selector: "keysAndValuesDo:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+    	for(var i in self['@jsObject']) {
+			aBlock._value_(i, self['@jsObject'][i]);
+		}
+    ;
+;
+return self}, self, "keysAndValuesDo:", [aBlock], smalltalk.JSObjectProxy)}
+}),
+smalltalk.JSObjectProxy);
+
 smalltalk.addMethod(
 "_printString",
 smalltalk.method({

+ 21 - 0
js/Kernel-Objects.js

@@ -2384,6 +2384,27 @@ referencedClasses: []
 }),
 smalltalk.JSObjectProxy);
 
+smalltalk.addMethod(
+"_keysAndValuesDo_",
+smalltalk.method({
+selector: "keysAndValuesDo:",
+category: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+    	for(var i in self['@jsObject']) {
+			aBlock._value_(i, self['@jsObject'][i]);
+		}
+    ;
+;
+return self}, self, "keysAndValuesDo:", [aBlock], smalltalk.JSObjectProxy)},
+args: ["aBlock"],
+source: "keysAndValuesDo: aBlock\x0a\x09<\x0a    \x09for(var i in self['@jsObject']) {\x0a\x09\x09\x09aBlock._value_(i, self['@jsObject'][i]);\x0a\x09\x09}\x0a    >",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy);
+
 smalltalk.addMethod(
 "_printString",
 smalltalk.method({

+ 62 - 2
st/Compiler-Interpreter.st

@@ -1,4 +1,64 @@
 Smalltalk current createPackage: 'Compiler-Interpreter' properties: #{}!
+NodeVisitor subclass: #AIContext
+	instanceVariableNames: 'outerContext pc locals receiver selector'
+	package: 'Compiler-Interpreter'!
+
+!AIContext methodsFor: 'accessing'!
+
+initializeFromMethodContext: aMethodContext
+	self pc: aMethodContext pc.
+    self receiver: aMethodContext receiver.
+    self selector: aMethodContext selector.
+    aMethodContext outerContext ifNotNil: [
+		self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
+    aMethodContext locals keysAndValuesDo: [ :key :value |
+    	self locals at: key put: value ]
+!
+
+locals
+	^ locals ifNil: [ locals := Dictionary new ]
+!
+
+outerContext
+	^ outerContext
+!
+
+outerContext: anAIContext
+	outerContext := anAIContext
+!
+
+pc
+	^ pc ifNil: [ pc := 0 ]
+!
+
+pc: anInteger
+	pc := anInteger
+!
+
+receiver
+	^ receiver
+!
+
+receiver: anObject
+	receiver := anObject
+!
+
+selector
+	^ selector
+!
+
+selector: aString
+	selector := aString
+! !
+
+!AIContext class methodsFor: 'instance creation'!
+
+fromMethodContext: aMethodContext
+	^ self new 
+    	initializeFromMethodContext: aMethodContext;
+        yourself
+! !
+
 NodeVisitor subclass: #ASTInterpreter
 	instanceVariableNames: 'currentNode context shouldReturn'
 	package: 'Compiler-Interpreter'!
@@ -9,8 +69,8 @@ context
 	^ context
 !
 
-context: aMethodContext
-	context := aMethodContext
+context: anAIContext
+	context := anAIContext
 ! !
 
 !ASTInterpreter methodsFor: 'initialization'!

+ 11 - 1
st/Kernel-Methods.st

@@ -340,6 +340,10 @@ locals
 	<return self.locals>
 !
 
+outerContext
+	^ self home
+!
+
 pc
 	<return self.pc>
 !
@@ -353,7 +357,13 @@ receiver
 !
 
 selector
-	<return smalltalk.convertSelector(self.selector)>
+	<
+    	if(self.selector) {
+        	return smalltalk.convertSelector(self.selector);
+        } else {
+        	return nil;
+        }
+    >
 !
 
 temps

+ 10 - 0
st/Kernel-Objects.st

@@ -749,6 +749,16 @@ jsObject: aJSObject
 	jsObject := aJSObject
 ! !
 
+!JSObjectProxy methodsFor: 'enumerating'!
+
+keysAndValuesDo: aBlock
+	<
+    	for(var i in self['@jsObject']) {
+			aBlock._value_(i, self['@jsObject'][i]);
+		}
+    >
+! !
+
 !JSObjectProxy methodsFor: 'proxy'!
 
 addObjectVariablesTo: aDictionary