Browse Source

- Fix for DoIt protocol when evaluating expressions
- Trigger announcements when adding/removing methods

Nicolas Petton 11 years ago
parent
commit
d1a0e26c8a

+ 1 - 1
js/Benchfib.deploy.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Benchfib', {});
+smalltalk.addPackage('Benchfib');
 smalltalk.addClass('Benchfib', smalltalk.Object, [], 'Benchfib');
 
 smalltalk.addMethod(

+ 1 - 1
js/Benchfib.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Benchfib', {});
+smalltalk.addPackage('Benchfib');
 smalltalk.addClass('Benchfib', smalltalk.Object, [], 'Benchfib');
 
 smalltalk.addMethod(

+ 8 - 6
js/Compiler-Core.deploy.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Compiler-Core', {});
+smalltalk.addPackage('Compiler-Core');
 smalltalk.addClass('Compiler', smalltalk.Object, ['currentClass', 'source', 'unknownVariables', 'codeGeneratorClass'], 'Compiler-Core');
 smalltalk.addMethod(
 "_codeGeneratorClass",
@@ -133,15 +133,17 @@ smalltalk.method({
 selector: "evaluateExpression:",
 fn: function (aString){
 var self=this;
-var result;
+var result,method;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-_st((smalltalk.DoIt || DoIt))._addCompiledMethod_(_st(self)._eval_(_st(self)._compileExpression_(aString)));
+method=_st(self)._eval_(_st(self)._compileExpression_(aString));
+_st(method)._category_("doIt");
+_st((smalltalk.DoIt || DoIt))._addCompiledMethod_(method);
 result=_st(_st((smalltalk.DoIt || DoIt))._new())._doIt();
-_st((smalltalk.DoIt || DoIt))._removeCompiledMethod_(_st(_st((smalltalk.DoIt || DoIt))._methodDictionary())._at_("doIt"));
+_st((smalltalk.DoIt || DoIt))._removeCompiledMethod_(method);
 $1=result;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"evaluateExpression:",{aString:aString,result:result}, smalltalk.Compiler)})},
-messageSends: ["addCompiledMethod:", "eval:", "compileExpression:", "doIt", "new", "removeCompiledMethod:", "at:", "methodDictionary"]}),
+}, function($ctx1) {$ctx1.fill(self,"evaluateExpression:",{aString:aString,result:result,method:method}, smalltalk.Compiler)})},
+messageSends: ["eval:", "compileExpression:", "category:", "addCompiledMethod:", "doIt", "new", "removeCompiledMethod:"]}),
 smalltalk.Compiler);
 
 smalltalk.addMethod(

+ 9 - 7
js/Compiler-Core.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Compiler-Core', {});
+smalltalk.addPackage('Compiler-Core');
 smalltalk.addClass('Compiler', smalltalk.Object, ['currentClass', 'source', 'unknownVariables', 'codeGeneratorClass'], 'Compiler-Core');
 smalltalk.Compiler.comment="I provide the public interface for compiling Amber source code into JavaScript.\x0a\x0aThe code generator used to produce JavaScript can be plugged with `#codeGeneratorClass`. \x0aThe default code generator is an instance of `InlinedCodeGenerator`"
 smalltalk.addMethod(
@@ -180,17 +180,19 @@ selector: "evaluateExpression:",
 category: 'compiling',
 fn: function (aString){
 var self=this;
-var result;
+var result,method;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-_st((smalltalk.DoIt || DoIt))._addCompiledMethod_(_st(self)._eval_(_st(self)._compileExpression_(aString)));
+method=_st(self)._eval_(_st(self)._compileExpression_(aString));
+_st(method)._category_("doIt");
+_st((smalltalk.DoIt || DoIt))._addCompiledMethod_(method);
 result=_st(_st((smalltalk.DoIt || DoIt))._new())._doIt();
-_st((smalltalk.DoIt || DoIt))._removeCompiledMethod_(_st(_st((smalltalk.DoIt || DoIt))._methodDictionary())._at_("doIt"));
+_st((smalltalk.DoIt || DoIt))._removeCompiledMethod_(method);
 $1=result;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"evaluateExpression:",{aString:aString,result:result}, smalltalk.Compiler)})},
+}, function($ctx1) {$ctx1.fill(self,"evaluateExpression:",{aString:aString,result:result,method:method}, smalltalk.Compiler)})},
 args: ["aString"],
-source: "evaluateExpression: aString\x0a\x09\x22Unlike #eval: evaluate a Smalltalk expression and answer the returned object\x22\x0a\x09| result |\x0a\x09DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).\x0a\x09result := DoIt new doIt.\x0a\x09DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').\x0a\x09^result",
-messageSends: ["addCompiledMethod:", "eval:", "compileExpression:", "doIt", "new", "removeCompiledMethod:", "at:", "methodDictionary"],
+source: "evaluateExpression: aString\x0a\x09\x22Unlike #eval: evaluate a Smalltalk expression and answer the returned object\x22\x0a\x09| result method |\x0a    method := self eval: (self compileExpression: aString).\x0a    method category: 'doIt'.\x0a\x09DoIt addCompiledMethod: method.\x0a\x09result := DoIt new doIt.\x0a\x09DoIt removeCompiledMethod: method.\x0a\x09^result",
+messageSends: ["eval:", "compileExpression:", "category:", "addCompiledMethod:", "doIt", "new", "removeCompiledMethod:"],
 referencedClasses: ["DoIt"]
 }),
 smalltalk.Compiler);

+ 27 - 19
js/Kernel-Classes.deploy.js

@@ -7,27 +7,31 @@ selector: "addCompiledMethod:",
 fn: function (aMethod){
 var self=this;
 var oldMethod,announcement;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
 oldMethod=_st(_st(self)._methodDictionary())._at_ifAbsent_(_st(aMethod)._selector(),(function(){
 return smalltalk.withContext(function($ctx2) {
return nil;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$1=_st(_st(self)._protocols())._includes_(_st(aMethod)._protocol());
+if(! smalltalk.assert($1)){
+_st(_st(self)._organization())._addElement_(_st(aMethod)._protocol());
+};
 _st(self)._basicAddCompiledMethod_(aMethod);
-$1=oldMethod;
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st((smalltalk.MethodAdded || MethodAdded))._new();
-_st($2)._method_(aMethod);
-$3=_st($2)._yourself();
-announcement=$3;
+$2=oldMethod;
+if(($receiver = $2) == nil || $receiver == undefined){
+$3=_st((smalltalk.MethodAdded || MethodAdded))._new();
+_st($3)._method_(aMethod);
+$4=_st($3)._yourself();
+announcement=$4;
 } else {
-$4=_st((smalltalk.MethodModified || MethodModified))._new();
-_st($4)._oldMethod_(oldMethod);
-_st($4)._method_(aMethod);
-$5=_st($4)._yourself();
-announcement=$5;
+$5=_st((smalltalk.MethodModified || MethodModified))._new();
+_st($5)._oldMethod_(oldMethod);
+_st($5)._method_(aMethod);
+$6=_st($5)._yourself();
+announcement=$6;
 };
 _st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_(announcement);
 return self}, function($ctx1) {$ctx1.fill(self,"addCompiledMethod:",{aMethod:aMethod,oldMethod:oldMethod,announcement:announcement}, smalltalk.Behavior)})},
-messageSends: ["at:ifAbsent:", "selector", "methodDictionary", "basicAddCompiledMethod:", "ifNil:ifNotNil:", "method:", "new", "yourself", "oldMethod:", "announce:", "current"]}),
+messageSends: ["at:ifAbsent:", "selector", "methodDictionary", "ifFalse:", "addElement:", "protocol", "organization", "includes:", "protocols", "basicAddCompiledMethod:", "ifNil:ifNotNil:", "method:", "new", "yourself", "oldMethod:", "announce:", "current"]}),
 smalltalk.Behavior);
 
 smalltalk.addMethod(
@@ -481,14 +485,18 @@ smalltalk.method({
 selector: "removeCompiledMethod:",
 fn: function (aMethod){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 _st(self)._basicRemoveCompiledMethod_(aMethod);
-$1=_st((smalltalk.MethodRemoved || MethodRemoved))._new();
-_st($1)._method_(aMethod);
-$2=_st($1)._yourself();
-_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($2);
+$1=_st(_st(self)._protocols())._includes_(_st(aMethod)._category());
+if(! smalltalk.assert($1)){
+_st(_st(self)._organization())._removeElement_(_st(aMethod)._protocol());
+};
+$2=_st((smalltalk.MethodRemoved || MethodRemoved))._new();
+_st($2)._method_(aMethod);
+$3=_st($2)._yourself();
+_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($3);
 return self}, function($ctx1) {$ctx1.fill(self,"removeCompiledMethod:",{aMethod:aMethod}, smalltalk.Behavior)})},
-messageSends: ["basicRemoveCompiledMethod:", "announce:", "method:", "new", "yourself", "current"]}),
+messageSends: ["basicRemoveCompiledMethod:", "ifFalse:", "removeElement:", "protocol", "organization", "includes:", "category", "protocols", "announce:", "method:", "new", "yourself", "current"]}),
 smalltalk.Behavior);
 
 smalltalk.addMethod(

+ 29 - 21
js/Kernel-Classes.js

@@ -9,29 +9,33 @@ category: 'compiling',
 fn: function (aMethod){
 var self=this;
 var oldMethod,announcement;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
 oldMethod=_st(_st(self)._methodDictionary())._at_ifAbsent_(_st(aMethod)._selector(),(function(){
 return smalltalk.withContext(function($ctx2) {
return nil;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$1=_st(_st(self)._protocols())._includes_(_st(aMethod)._protocol());
+if(! smalltalk.assert($1)){
+_st(_st(self)._organization())._addElement_(_st(aMethod)._protocol());
+};
 _st(self)._basicAddCompiledMethod_(aMethod);
-$1=oldMethod;
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st((smalltalk.MethodAdded || MethodAdded))._new();
-_st($2)._method_(aMethod);
-$3=_st($2)._yourself();
-announcement=$3;
+$2=oldMethod;
+if(($receiver = $2) == nil || $receiver == undefined){
+$3=_st((smalltalk.MethodAdded || MethodAdded))._new();
+_st($3)._method_(aMethod);
+$4=_st($3)._yourself();
+announcement=$4;
 } else {
-$4=_st((smalltalk.MethodModified || MethodModified))._new();
-_st($4)._oldMethod_(oldMethod);
-_st($4)._method_(aMethod);
-$5=_st($4)._yourself();
-announcement=$5;
+$5=_st((smalltalk.MethodModified || MethodModified))._new();
+_st($5)._oldMethod_(oldMethod);
+_st($5)._method_(aMethod);
+$6=_st($5)._yourself();
+announcement=$6;
 };
 _st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_(announcement);
 return self}, function($ctx1) {$ctx1.fill(self,"addCompiledMethod:",{aMethod:aMethod,oldMethod:oldMethod,announcement:announcement}, smalltalk.Behavior)})},
 args: ["aMethod"],
-source: "addCompiledMethod: aMethod\x0a\x09| oldMethod announcement |\x0a    \x0a\x09oldMethod := self methodDictionary \x0a    \x09at: aMethod selector \x0a        ifAbsent: [ nil ].\x0a    \x0a\x09self basicAddCompiledMethod: aMethod.\x0a    \x0a    announcement := oldMethod \x0a    \x09ifNil: [\x0a\x09\x09    MethodAdded new\x0a\x09\x09            method: aMethod;\x0a       \x09\x09\x09    yourself ]\x0a    \x09ifNotNil: [\x0a          \x09MethodModified new\x0a                    oldMethod: oldMethod; \x0a\x09\x09            method: aMethod;\x0a       \x09\x09\x09    yourself ].\x0a                    \x0a\x09SystemAnnouncer current\x0a\x09\x09   \x09\x09announce: announcement",
-messageSends: ["at:ifAbsent:", "selector", "methodDictionary", "basicAddCompiledMethod:", "ifNil:ifNotNil:", "method:", "new", "yourself", "oldMethod:", "announce:", "current"],
+source: "addCompiledMethod: aMethod\x0a\x09| oldMethod announcement |\x0a    \x0a\x09oldMethod := self methodDictionary \x0a    \x09at: aMethod selector \x0a        ifAbsent: [ nil ].\x0a    \x0a   (self protocols includes: aMethod protocol)\x0a   \x09\x09ifFalse: [ self organization addElement: aMethod protocol ].\x0a   \x0a\x09self basicAddCompiledMethod: aMethod.\x0a    \x0a    announcement := oldMethod \x0a    \x09ifNil: [\x0a\x09\x09    MethodAdded new\x0a\x09\x09            method: aMethod;\x0a       \x09\x09\x09    yourself ]\x0a    \x09ifNotNil: [\x0a          \x09MethodModified new\x0a                    oldMethod: oldMethod; \x0a\x09\x09            method: aMethod;\x0a       \x09\x09\x09    yourself ].\x0a                    \x0a                    \x0a\x09SystemAnnouncer current\x0a\x09\x09   \x09\x09announce: announcement",
+messageSends: ["at:ifAbsent:", "selector", "methodDictionary", "ifFalse:", "addElement:", "protocol", "organization", "includes:", "protocols", "basicAddCompiledMethod:", "ifNil:ifNotNil:", "method:", "new", "yourself", "oldMethod:", "announce:", "current"],
 referencedClasses: ["MethodAdded", "MethodModified", "SystemAnnouncer"]
 }),
 smalltalk.Behavior);
@@ -638,16 +642,20 @@ selector: "removeCompiledMethod:",
 category: 'compiling',
 fn: function (aMethod){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 _st(self)._basicRemoveCompiledMethod_(aMethod);
-$1=_st((smalltalk.MethodRemoved || MethodRemoved))._new();
-_st($1)._method_(aMethod);
-$2=_st($1)._yourself();
-_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($2);
+$1=_st(_st(self)._protocols())._includes_(_st(aMethod)._category());
+if(! smalltalk.assert($1)){
+_st(_st(self)._organization())._removeElement_(_st(aMethod)._protocol());
+};
+$2=_st((smalltalk.MethodRemoved || MethodRemoved))._new();
+_st($2)._method_(aMethod);
+$3=_st($2)._yourself();
+_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($3);
 return self}, function($ctx1) {$ctx1.fill(self,"removeCompiledMethod:",{aMethod:aMethod}, smalltalk.Behavior)})},
 args: ["aMethod"],
-source: "removeCompiledMethod: aMethod\x0a\x09self basicRemoveCompiledMethod: aMethod.\x0a    \x0a    SystemAnnouncer current\x0a   \x09\x09announce: (MethodRemoved new\x0a            method: aMethod;\x0a            yourself)",
-messageSends: ["basicRemoveCompiledMethod:", "announce:", "method:", "new", "yourself", "current"],
+source: "removeCompiledMethod: aMethod\x0a\x09self basicRemoveCompiledMethod: aMethod.\x0a    \x0a    (self protocols includes: aMethod category)\x0a    \x09ifFalse: [ self organization removeElement: aMethod protocol ].\x0a    \x0a    SystemAnnouncer current\x0a   \x09\x09announce: (MethodRemoved new\x0a            method: aMethod;\x0a            yourself)",
+messageSends: ["basicRemoveCompiledMethod:", "ifFalse:", "removeElement:", "protocol", "organization", "includes:", "category", "protocols", "announce:", "method:", "new", "yourself", "current"],
 referencedClasses: ["MethodRemoved", "SystemAnnouncer"]
 }),
 smalltalk.Behavior);

+ 14 - 3
js/Kernel-Methods.deploy.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Kernel-Methods', {});
+smalltalk.addPackage('Kernel-Methods');
 smalltalk.addClass('BlockClosure', smalltalk.Object, [], 'Kernel-Methods');
 smalltalk.addMethod(
 "_applyTo_arguments_",
@@ -315,13 +315,13 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
 $2=_st(self)._basicAt_("category");
 if(($receiver = $2) == nil || $receiver == undefined){
-$1="";
+$1=_st(self)._defaultCategory();
 } else {
 $1=$2;
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"category",{}, smalltalk.CompiledMethod)})},
-messageSends: ["ifNil:", "basicAt:"]}),
+messageSends: ["ifNil:", "defaultCategory", "basicAt:"]}),
 smalltalk.CompiledMethod);
 
 smalltalk.addMethod(
@@ -349,6 +349,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"category:",{aString:aString,oldC
 messageSends: ["category", "basicAt:put:", "ifNotNil:", "addElement:", "organization", "methodClass", "ifEmpty:", "removeElement:", "select:", "=", "methods"]}),
 smalltalk.CompiledMethod);
 
+smalltalk.addMethod(
+"_defaultCategory",
+smalltalk.method({
+selector: "defaultCategory",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "as yet unclassified";
+}, function($ctx1) {$ctx1.fill(self,"defaultCategory",{}, smalltalk.CompiledMethod)})},
+messageSends: []}),
+smalltalk.CompiledMethod);
+
 smalltalk.addMethod(
 "_fn",
 smalltalk.method({

+ 20 - 4
js/Kernel-Methods.js

@@ -1,4 +1,4 @@
-smalltalk.addPackage('Kernel-Methods', {});
+smalltalk.addPackage('Kernel-Methods');
 smalltalk.addClass('BlockClosure', smalltalk.Object, [], 'Kernel-Methods');
 smalltalk.BlockClosure.comment="A BlockClosure is a lexical closure.\x0aThe JavaScript representation is a function.\x0a\x0aA BlockClosure is evaluated with the `#value*` methods in the 'evaluating' protocol."
 smalltalk.addMethod(
@@ -443,15 +443,15 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
 $2=_st(self)._basicAt_("category");
 if(($receiver = $2) == nil || $receiver == undefined){
-$1="";
+$1=_st(self)._defaultCategory();
 } else {
 $1=$2;
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"category",{}, smalltalk.CompiledMethod)})},
 args: [],
-source: "category\x0a\x09^(self basicAt: 'category') ifNil: ['']",
-messageSends: ["ifNil:", "basicAt:"],
+source: "category\x0a\x09^(self basicAt: 'category') ifNil: [ self defaultCategory ]",
+messageSends: ["ifNil:", "defaultCategory", "basicAt:"],
 referencedClasses: []
 }),
 smalltalk.CompiledMethod);
@@ -486,6 +486,22 @@ referencedClasses: []
 }),
 smalltalk.CompiledMethod);
 
+smalltalk.addMethod(
+"_defaultCategory",
+smalltalk.method({
+selector: "defaultCategory",
+category: 'defaults',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "as yet unclassified";
+}, function($ctx1) {$ctx1.fill(self,"defaultCategory",{}, smalltalk.CompiledMethod)})},
+args: [],
+source: "defaultCategory\x0a\x09^ 'as yet unclassified'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
 smalltalk.addMethod(
 "_fn",
 smalltalk.method({

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

@@ -2307,15 +2307,20 @@ smalltalk.method({
 selector: "addElement:",
 fn: function (aString){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+var alreadyExisting;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+alreadyExisting=_st(_st(self)._elements())._includes_(aString);
 smalltalk.Organizer.fn.prototype._addElement_.apply(_st(self), [aString]);
-$1=_st((smalltalk.ProtocolAdded || ProtocolAdded))._new();
-_st($1)._protocol_(aString);
-_st($1)._theClass_(_st(self)._theClass());
-$2=_st($1)._yourself();
-_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"addElement:",{aString:aString}, smalltalk.ClassOrganizer)})},
-messageSends: ["addElement:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"]}),
+$1=alreadyExisting;
+if(! smalltalk.assert($1)){
+$2=_st((smalltalk.ProtocolAdded || ProtocolAdded))._new();
+_st($2)._protocol_(aString);
+_st($2)._theClass_(_st(self)._theClass());
+$3=_st($2)._yourself();
+_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($3);
+};
+return self}, function($ctx1) {$ctx1.fill(self,"addElement:",{aString:aString,alreadyExisting:alreadyExisting}, smalltalk.ClassOrganizer)})},
+messageSends: ["includes:", "elements", "addElement:", "ifFalse:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"]}),
 smalltalk.ClassOrganizer);
 
 smalltalk.addMethod(
@@ -2324,15 +2329,20 @@ smalltalk.method({
 selector: "removeElement:",
 fn: function (aString){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+var alreadyExisting;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+alreadyExisting=_st(_st(self)._elements())._includes_(aString);
 smalltalk.Organizer.fn.prototype._removeElement_.apply(_st(self), [aString]);
-$1=_st((smalltalk.ProtocolRemoved || ProtocolRemoved))._new();
-_st($1)._protocol_(aString);
-_st($1)._theClass_(_st(self)._theClass());
-$2=_st($1)._yourself();
-_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"removeElement:",{aString:aString}, smalltalk.ClassOrganizer)})},
-messageSends: ["removeElement:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"]}),
+$1=alreadyExisting;
+if(smalltalk.assert($1)){
+$2=_st((smalltalk.ProtocolRemoved || ProtocolRemoved))._new();
+_st($2)._protocol_(aString);
+_st($2)._theClass_(_st(self)._theClass());
+$3=_st($2)._yourself();
+_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($3);
+};
+return self}, function($ctx1) {$ctx1.fill(self,"removeElement:",{aString:aString,alreadyExisting:alreadyExisting}, smalltalk.ClassOrganizer)})},
+messageSends: ["includes:", "elements", "removeElement:", "ifTrue:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"]}),
 smalltalk.ClassOrganizer);
 
 smalltalk.addMethod(

+ 28 - 18
js/Kernel-Objects.js

@@ -3193,17 +3193,22 @@ selector: "addElement:",
 category: 'accessing',
 fn: function (aString){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+var alreadyExisting;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+alreadyExisting=_st(_st(self)._elements())._includes_(aString);
 smalltalk.Organizer.fn.prototype._addElement_.apply(_st(self), [aString]);
-$1=_st((smalltalk.ProtocolAdded || ProtocolAdded))._new();
-_st($1)._protocol_(aString);
-_st($1)._theClass_(_st(self)._theClass());
-$2=_st($1)._yourself();
-_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"addElement:",{aString:aString}, smalltalk.ClassOrganizer)})},
+$1=alreadyExisting;
+if(! smalltalk.assert($1)){
+$2=_st((smalltalk.ProtocolAdded || ProtocolAdded))._new();
+_st($2)._protocol_(aString);
+_st($2)._theClass_(_st(self)._theClass());
+$3=_st($2)._yourself();
+_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($3);
+};
+return self}, function($ctx1) {$ctx1.fill(self,"addElement:",{aString:aString,alreadyExisting:alreadyExisting}, smalltalk.ClassOrganizer)})},
 args: ["aString"],
-source: "addElement: aString\x0a\x09super addElement: aString.\x0a\x0a\x09SystemAnnouncer current announce: (ProtocolAdded new\x0a    \x09protocol: aString;\x0a        theClass: self theClass;\x0a        yourself)",
-messageSends: ["addElement:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"],
+source: "addElement: aString\x0a\x09| alreadyExisting |\x0a    \x0a    alreadyExisting := self elements includes: aString.\x0a\x09super addElement: aString.\x0a\x09\x0a    alreadyExisting\x0a    \x09ifFalse: [\x0a          SystemAnnouncer current announce: (ProtocolAdded new\x0a              protocol: aString;\x0a              theClass: self theClass;\x0a              yourself) ]",
+messageSends: ["includes:", "elements", "addElement:", "ifFalse:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"],
 referencedClasses: ["ProtocolAdded", "SystemAnnouncer"]
 }),
 smalltalk.ClassOrganizer);
@@ -3215,17 +3220,22 @@ selector: "removeElement:",
 category: 'accessing',
 fn: function (aString){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+var alreadyExisting;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+alreadyExisting=_st(_st(self)._elements())._includes_(aString);
 smalltalk.Organizer.fn.prototype._removeElement_.apply(_st(self), [aString]);
-$1=_st((smalltalk.ProtocolRemoved || ProtocolRemoved))._new();
-_st($1)._protocol_(aString);
-_st($1)._theClass_(_st(self)._theClass());
-$2=_st($1)._yourself();
-_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"removeElement:",{aString:aString}, smalltalk.ClassOrganizer)})},
+$1=alreadyExisting;
+if(smalltalk.assert($1)){
+$2=_st((smalltalk.ProtocolRemoved || ProtocolRemoved))._new();
+_st($2)._protocol_(aString);
+_st($2)._theClass_(_st(self)._theClass());
+$3=_st($2)._yourself();
+_st(_st((smalltalk.SystemAnnouncer || SystemAnnouncer))._current())._announce_($3);
+};
+return self}, function($ctx1) {$ctx1.fill(self,"removeElement:",{aString:aString,alreadyExisting:alreadyExisting}, smalltalk.ClassOrganizer)})},
 args: ["aString"],
-source: "removeElement: aString\x0a\x09super removeElement: aString.\x0a\x0a\x09SystemAnnouncer current announce: (ProtocolRemoved new\x0a    \x09protocol: aString;\x0a        theClass: self theClass;\x0a        yourself)",
-messageSends: ["removeElement:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"],
+source: "removeElement: aString\x0a\x09| alreadyExisting |\x0a    \x0a    alreadyExisting := self elements includes: aString.\x0a    super removeElement: aString.\x0a\x0a\x09alreadyExisting \x0a    \x09ifTrue: [\x0a        \x09SystemAnnouncer current announce: (ProtocolRemoved new\x0a          \x09\x09protocol: aString;\x0a                theClass: self theClass;\x0a                yourself) ]",
+messageSends: ["includes:", "elements", "removeElement:", "ifTrue:", "announce:", "protocol:", "new", "theClass:", "theClass", "yourself", "current"],
 referencedClasses: ["ProtocolRemoved", "SystemAnnouncer"]
 }),
 smalltalk.ClassOrganizer);

+ 3 - 1
js/boot.js

@@ -475,7 +475,9 @@ function Smalltalk() {
         delete st[klass.className];
     };
 
-	/* Add/remove a method to/from a class */
+	/* 
+     * Add/remove a method to/from a class 
+     */
 
 	st.addMethod = function(jsSelector, method, klass) {
 		method.jsSelector = jsSelector;

+ 5 - 3
st/Compiler-Core.st

@@ -77,10 +77,12 @@ eval: aString
 
 evaluateExpression: aString
 	"Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
-	| result |
-	DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
+	| result method |
+    method := self eval: (self compileExpression: aString).
+    method category: 'doIt'.
+	DoIt addCompiledMethod: method.
 	result := DoIt new doIt.
-	DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').
+	DoIt removeCompiledMethod: method.
 	^result
 !
 

+ 7 - 0
st/Kernel-Classes.st

@@ -180,6 +180,9 @@ addCompiledMethod: aMethod
     	at: aMethod selector 
         ifAbsent: [ nil ].
     
+   (self protocols includes: aMethod protocol)
+   		ifFalse: [ self organization addElement: aMethod protocol ].
+   
 	self basicAddCompiledMethod: aMethod.
     
     announcement := oldMethod 
@@ -193,6 +196,7 @@ addCompiledMethod: aMethod
 		            method: aMethod;
        			    yourself ].
                     
+                    
 	SystemAnnouncer current
 		   		announce: announcement
 !
@@ -211,6 +215,9 @@ compile: aString category: anotherString
 removeCompiledMethod: aMethod
 	self basicRemoveCompiledMethod: aMethod.
     
+    (self protocols includes: aMethod category)
+    	ifFalse: [ self organization removeElement: aMethod protocol ].
+    
     SystemAnnouncer current
    		announce: (MethodRemoved new
             method: aMethod;