Browse Source

AST Interpreter working with basic nodes

Nicolas Petton 11 years ago
parent
commit
99a5634374

+ 75 - 68
js/Compiler-Interpreter.deploy.js

@@ -1,42 +1,4 @@
 smalltalk.addPackage('Compiler-Interpreter', {});
-smalltalk.addClass('ASTBlockClosure', smalltalk.BlockClosure, ['astNode'], 'Compiler-Interpreter');
-smalltalk.addMethod(
-"_astNode",
-smalltalk.method({
-selector: "astNode",
-fn: function (){
-var self=this;
-return self["@astNode"];
-}
-}),
-smalltalk.ASTBlockClosure);
-
-smalltalk.addMethod(
-"_astNode_",
-smalltalk.method({
-selector: "astNode:",
-fn: function (aNode){
-var self=this;
-self["@astNode"]=aNode;
-return self}
-}),
-smalltalk.ASTBlockClosure);
-
-smalltalk.addMethod(
-"_value",
-smalltalk.method({
-selector: "value",
-fn: function (){
-var self=this;
-var $1;
-$1=smalltalk.send(smalltalk.send((smalltalk.ASTInterpreter || ASTInterpreter),"_current",[]),"_blockValue_",[self]);
-return $1;
-}
-}),
-smalltalk.ASTBlockClosure);
-
-
-
 smalltalk.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn'], 'Compiler-Interpreter');
 smalltalk.addMethod(
 "_blockValue_",
@@ -132,11 +94,10 @@ smalltalk.method({
 selector: "visitBlockNode:",
 fn: function (aNode){
 var self=this;
-var $2,$3,$1;
-$2=smalltalk.send((smalltalk.ASTBlockClosure || ASTBlockClosure),"_new",[]);
-smalltalk.send($2,"_astNode_",[aNode]);
-$3=smalltalk.send($2,"_yourself",[]);
-$1=$3;
+var $1;
+$1=(function(){
+return _st(self)._interpretNode_(_st(_st(aNode)._nodes())._first());
+});
 return $1;
 }
 }),
@@ -150,7 +111,7 @@ fn: function (aNode){
 var self=this;
 var $1;
 self["@shouldReturn"]=true;
-$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_first",[])]);
+$1=_st(self)._interpretNode_(_st(_st(aNode)._nodes())._first());
 return $1;
 }
 }),
@@ -165,11 +126,11 @@ var self=this;
 var $1;
 var receiver;
 var arguments;
-receiver=smalltalk.send(self,"_interpret_",[smalltalk.send(aNode,"_receiver",[])]);
-arguments=smalltalk.send(smalltalk.send(aNode,"_arguments",[]),"_collect_",[(function(each){
-return smalltalk.send(self,"_interpret_",[each]);
-})]);
-$1=smalltalk.send(self,"_send_to_arguments_",[smalltalk.send(aNode,"_selector",[]),receiver,arguments]);
+receiver=_st(self)._interpretNode_(_st(aNode)._receiver());
+arguments=_st(_st(aNode)._arguments())._collect_((function(each){
+return _st(self)._interpretNode_(each);
+}));
+$1=_st(self)._send_to_arguments_(_st(aNode)._selector(),receiver,arguments);
 return $1;
 }
 }),
@@ -184,15 +145,15 @@ var self=this;
 var $1;
 var $early={};
 try {
-smalltalk.send(smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_allButLast",[]),"_do_",[(function(each){
+_st(_st(_st(aNode)._nodes())._allButLast())._do_((function(each){
 var value;
-value=smalltalk.send(self,"_interpret_",[each]);
+value=_st(self)._interpretNode_(each);
 value;
 if(smalltalk.assert(self["@shouldReturn"])){
 throw $early=[value];
 };
-})]);
-$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_last",[])]);
+}));
+$1=_st(self)._interpretNode_(_st(_st(aNode)._nodes())._last());
 return $1;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -214,34 +175,80 @@ return $1;
 smalltalk.ASTInterpreter);
 
 
-smalltalk.ASTInterpreter.klass.iVarNames = ['current'];
+
+smalltalk.addClass('ASTInterpretorTest', smalltalk.TestCase, [], 'Compiler-Interpreter');
 smalltalk.addMethod(
-"_current",
+"_analyze_forClass_",
 smalltalk.method({
-selector: "current",
-fn: function (){
+selector: "analyze:forClass:",
+fn: function (aNode,aClass){
+var self=this;
+_st(_st((smalltalk.SemanticAnalyzer || SemanticAnalyzer))._on_(aClass))._visit_(aNode);
+return aNode;
+}
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_interpret_",
+smalltalk.method({
+selector: "interpret:",
+fn: function (aString){
 var self=this;
 var $1;
-if(($receiver = self["@current"]) == nil || $receiver == undefined){
-self["@current"]=smalltalk.send(self,"_new",[],smalltalk.NodeVisitor.klass);
-$1=self["@current"];
-} else {
-$1=self["@current"];
-};
+$1=_st(_st((smalltalk.ASTInterpreter || ASTInterpreter))._new())._interpret_(_st(_st(_st(self)._parse_forClass_(aString,(smalltalk.Object || Object)))._nodes())._first());
+return $1;
+}
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_parse_",
+smalltalk.method({
+selector: "parse:",
+fn: function (aString){
+var self=this;
+var $1;
+$1=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._parse_(aString);
+return $1;
+}
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_parse_forClass_",
+smalltalk.method({
+selector: "parse:forClass:",
+fn: function (aString,aClass){
+var self=this;
+var $1;
+$1=_st(self)._analyze_forClass_(_st(self)._parse_(aString),aClass);
 return $1;
 }
 }),
-smalltalk.ASTInterpreter.klass);
+smalltalk.ASTInterpretorTest);
 
 smalltalk.addMethod(
-"_new",
+"_testBinarySend",
 smalltalk.method({
-selector: "new",
+selector: "testBinarySend",
 fn: function (){
 var self=this;
-smalltalk.send(self,"_shouldNotImplement",[]);
+_st(self)._assert_equals_(_st(self)._interpret_("foo 2+3+4"),(9));
 return self}
 }),
-smalltalk.ASTInterpreter.klass);
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_testBlockLiteral",
+smalltalk.method({
+selector: "testBlockLiteral",
+fn: function (){
+var self=this;
+_st(self)._assert_(false);
+return self}
+}),
+smalltalk.ASTInterpretorTest);
+
 
 

+ 110 - 99
js/Compiler-Interpreter.js

@@ -1,58 +1,4 @@
 smalltalk.addPackage('Compiler-Interpreter', {});
-smalltalk.addClass('ASTBlockClosure', smalltalk.BlockClosure, ['astNode'], 'Compiler-Interpreter');
-smalltalk.ASTBlockClosure.comment="ASTBlockClosure is polymorph with BlockClosure. \x0aAn ASTBlockClosure is used to interpret a BlockNode, and override all \x22primitive\x22 methods (#value and co)."
-smalltalk.addMethod(
-"_astNode",
-smalltalk.method({
-selector: "astNode",
-category: 'accessing',
-fn: function (){
-var self=this;
-return self["@astNode"];
-},
-args: [],
-source: "astNode\x0a\x09^ astNode",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.ASTBlockClosure);
-
-smalltalk.addMethod(
-"_astNode_",
-smalltalk.method({
-selector: "astNode:",
-category: 'accessing',
-fn: function (aNode){
-var self=this;
-self["@astNode"]=aNode;
-return self},
-args: ["aNode"],
-source: "astNode: aNode\x0a\x09astNode := aNode",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.ASTBlockClosure);
-
-smalltalk.addMethod(
-"_value",
-smalltalk.method({
-selector: "value",
-category: 'evaluating',
-fn: function (){
-var self=this;
-var $1;
-$1=smalltalk.send(smalltalk.send((smalltalk.ASTInterpreter || ASTInterpreter),"_current",[]),"_blockValue_",[self]);
-return $1;
-},
-args: [],
-source: "value\x0a\x09^ ASTInterpreter current blockValue: self",
-messageSends: ["blockValue:", "current"],
-referencedClasses: ["ASTInterpreter"]
-}),
-smalltalk.ASTBlockClosure);
-
-
-
 smalltalk.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn'], 'Compiler-Interpreter');
 smalltalk.addMethod(
 "_blockValue_",
@@ -184,17 +130,16 @@ selector: "visitBlockNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-var $2,$3,$1;
-$2=smalltalk.send((smalltalk.ASTBlockClosure || ASTBlockClosure),"_new",[]);
-smalltalk.send($2,"_astNode_",[aNode]);
-$3=smalltalk.send($2,"_yourself",[]);
-$1=$3;
+var $1;
+$1=(function(){
+return _st(self)._interpretNode_(_st(_st(aNode)._nodes())._first());
+});
 return $1;
 },
 args: ["aNode"],
-source: "visitBlockNode: aNode\x0a\x09^ ASTBlockClosure new\x0a    \x09astNode: aNode;\x0a        yourself",
-messageSends: ["astNode:", "new", "yourself"],
-referencedClasses: ["ASTBlockClosure"]
+source: "visitBlockNode: aNode\x0a    ^ [ self interpretNode: aNode nodes first ]",
+messageSends: ["interpretNode:", "first", "nodes"],
+referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
@@ -207,12 +152,12 @@ fn: function (aNode){
 var self=this;
 var $1;
 self["@shouldReturn"]=true;
-$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_first",[])]);
+$1=_st(self)._interpretNode_(_st(_st(aNode)._nodes())._first());
 return $1;
 },
 args: ["aNode"],
-source: "visitReturnNode: aNode\x0a\x09shouldReturn := true.\x0a    ^ self interpret: aNode nodes first",
-messageSends: ["interpret:", "first", "nodes"],
+source: "visitReturnNode: aNode\x0a\x09shouldReturn := true.\x0a    ^ self interpretNode: aNode nodes first",
+messageSends: ["interpretNode:", "first", "nodes"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
@@ -227,16 +172,16 @@ var self=this;
 var $1;
 var receiver;
 var arguments;
-receiver=smalltalk.send(self,"_interpret_",[smalltalk.send(aNode,"_receiver",[])]);
-arguments=smalltalk.send(smalltalk.send(aNode,"_arguments",[]),"_collect_",[(function(each){
-return smalltalk.send(self,"_interpret_",[each]);
-})]);
-$1=smalltalk.send(self,"_send_to_arguments_",[smalltalk.send(aNode,"_selector",[]),receiver,arguments]);
+receiver=_st(self)._interpretNode_(_st(aNode)._receiver());
+arguments=_st(_st(aNode)._arguments())._collect_((function(each){
+return _st(self)._interpretNode_(each);
+}));
+$1=_st(self)._send_to_arguments_(_st(aNode)._selector(),receiver,arguments);
 return $1;
 },
 args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x09\x22TODO: Handle super sends\x22\x0a\x09| receiver arguments |\x0a    \x0a    receiver := self interpret: aNode receiver.\x0a    arguments := aNode arguments collect: [ :each |\x0a\x09\x09self interpret: each ].\x0a    \x0a    ^ self send: aNode selector to: receiver arguments: arguments",
-messageSends: ["interpret:", "receiver", "collect:", "arguments", "send:to:arguments:", "selector"],
+source: "visitSendNode: aNode\x0a\x09\x22TODO: Handle super sends\x22\x0a\x09| receiver arguments |\x0a    \x0a    receiver := self interpretNode: aNode receiver.\x0a    arguments := aNode arguments collect: [ :each |\x0a\x09\x09self interpretNode: each ].\x0a    \x0a    ^ self send: aNode selector to: receiver arguments: arguments",
+messageSends: ["interpretNode:", "receiver", "collect:", "arguments", "send:to:arguments:", "selector"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
@@ -251,22 +196,22 @@ var self=this;
 var $1;
 var $early={};
 try {
-smalltalk.send(smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_allButLast",[]),"_do_",[(function(each){
+_st(_st(_st(aNode)._nodes())._allButLast())._do_((function(each){
 var value;
-value=smalltalk.send(self,"_interpret_",[each]);
+value=_st(self)._interpretNode_(each);
 value;
 if(smalltalk.assert(self["@shouldReturn"])){
 throw $early=[value];
 };
-})]);
-$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_last",[])]);
+}));
+$1=_st(self)._interpretNode_(_st(_st(aNode)._nodes())._last());
 return $1;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
 },
 args: ["aNode"],
-source: "visitSequenceNode: aNode\x0a\x09aNode nodes allButLast do: [ :each | | value |\x0a        value := self interpret: each.\x0a\x09\x09shouldReturn ifTrue: [ ^ value ] ].\x0a    ^ self interpret: aNode nodes last",
-messageSends: ["do:", "interpret:", "ifTrue:", "allButLast", "nodes", "last"],
+source: "visitSequenceNode: aNode\x0a\x09aNode nodes allButLast do: [ :each | | value |\x0a        value := self interpretNode: each.\x0a\x09\x09shouldReturn ifTrue: [ ^ value ] ].\x0a    ^ self interpretNode: aNode nodes last",
+messageSends: ["do:", "interpretNode:", "ifTrue:", "allButLast", "nodes", "last"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
@@ -290,44 +235,110 @@ referencedClasses: []
 smalltalk.ASTInterpreter);
 
 
-smalltalk.ASTInterpreter.klass.iVarNames = ['current'];
+
+smalltalk.addClass('ASTInterpretorTest', smalltalk.TestCase, [], 'Compiler-Interpreter');
 smalltalk.addMethod(
-"_current",
+"_analyze_forClass_",
 smalltalk.method({
-selector: "current",
-category: 'instance creation',
-fn: function (){
+selector: "analyze:forClass:",
+category: 'accessing',
+fn: function (aNode,aClass){
+var self=this;
+_st(_st((smalltalk.SemanticAnalyzer || SemanticAnalyzer))._on_(aClass))._visit_(aNode);
+return aNode;
+},
+args: ["aNode", "aClass"],
+source: "analyze: aNode forClass: aClass\x0a\x09(SemanticAnalyzer on: aClass) visit: aNode.\x0a    ^ aNode",
+messageSends: ["visit:", "on:"],
+referencedClasses: ["SemanticAnalyzer"]
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_interpret_",
+smalltalk.method({
+selector: "interpret:",
+category: 'accessing',
+fn: function (aString){
 var self=this;
 var $1;
-if(($receiver = self["@current"]) == nil || $receiver == undefined){
-self["@current"]=smalltalk.send(self,"_new",[],smalltalk.NodeVisitor.klass);
-$1=self["@current"];
-} else {
-$1=self["@current"];
-};
+$1=_st(_st((smalltalk.ASTInterpreter || ASTInterpreter))._new())._interpret_(_st(_st(_st(self)._parse_forClass_(aString,(smalltalk.Object || Object)))._nodes())._first());
+return $1;
+},
+args: ["aString"],
+source: "interpret: aString\x0a\x09\x22the food is a methodNode. Interpret the sequenceNode only\x22\x0a    ^ ASTInterpreter new\x0a    \x09interpret: (self parse: aString forClass: Object) \x0a        \x09nodes first",
+messageSends: ["interpret:", "first", "nodes", "parse:forClass:", "new"],
+referencedClasses: ["Object", "ASTInterpreter"]
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_parse_",
+smalltalk.method({
+selector: "parse:",
+category: 'accessing',
+fn: function (aString){
+var self=this;
+var $1;
+$1=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._parse_(aString);
+return $1;
+},
+args: ["aString"],
+source: "parse: aString\x0a\x09^ Smalltalk current parse: aString",
+messageSends: ["parse:", "current"],
+referencedClasses: ["Smalltalk"]
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_parse_forClass_",
+smalltalk.method({
+selector: "parse:forClass:",
+category: 'accessing',
+fn: function (aString,aClass){
+var self=this;
+var $1;
+$1=_st(self)._analyze_forClass_(_st(self)._parse_(aString),aClass);
 return $1;
 },
+args: ["aString", "aClass"],
+source: "parse: aString forClass: aClass\x0a\x09^ self analyze: (self parse: aString) forClass: aClass",
+messageSends: ["analyze:forClass:", "parse:"],
+referencedClasses: []
+}),
+smalltalk.ASTInterpretorTest);
+
+smalltalk.addMethod(
+"_testBinarySend",
+smalltalk.method({
+selector: "testBinarySend",
+category: 'tests',
+fn: function (){
+var self=this;
+_st(self)._assert_equals_(_st(self)._interpret_("foo 2+3+4"),(9));
+return self},
 args: [],
-source: "current\x0a\x09^ current ifNil: [ current := super new ]",
-messageSends: ["ifNil:", "new"],
+source: "testBinarySend\x0a\x09self assert: (self interpret: 'foo 2+3+4') equals: 9",
+messageSends: ["assert:equals:", "interpret:"],
 referencedClasses: []
 }),
-smalltalk.ASTInterpreter.klass);
+smalltalk.ASTInterpretorTest);
 
 smalltalk.addMethod(
-"_new",
+"_testBlockLiteral",
 smalltalk.method({
-selector: "new",
-category: 'instance creation',
+selector: "testBlockLiteral",
+category: 'tests',
 fn: function (){
 var self=this;
-smalltalk.send(self,"_shouldNotImplement",[]);
+_st(self)._assert_(false);
 return self},
 args: [],
-source: "new\x0a\x09self shouldNotImplement",
-messageSends: ["shouldNotImplement"],
+source: "testBlockLiteral\x0a\x09self assert: false",
+messageSends: ["assert:"],
 referencedClasses: []
 }),
-smalltalk.ASTInterpreter.klass);
+smalltalk.ASTInterpretorTest);
+
 
 

File diff suppressed because it is too large
+ 392 - 334
js/Compiler-Tests.deploy.js


File diff suppressed because it is too large
+ 414 - 325
js/Compiler-Tests.js


+ 207 - 17
js/Kernel-Objects.deploy.js

@@ -697,7 +697,7 @@ fn: function () {
 smalltalk.Object);
 
 smalltalk.addMethod(
-"_~_eq",
+"__tild_eq",
 smalltalk.method({
 selector: "~=",
 fn: function (anObject) {
@@ -710,7 +710,7 @@ fn: function (anObject) {
 smalltalk.Object);
 
 smalltalk.addMethod(
-"_~~",
+"__tild_tild",
 smalltalk.method({
 selector: "~~",
 fn: function (anObject) {
@@ -737,7 +737,7 @@ smalltalk.Object.klass);
 
 smalltalk.addClass('Boolean', smalltalk.Object, [], 'Kernel-Objects');
 smalltalk.addMethod(
-"_&",
+"__and",
 smalltalk.method({
 selector: "&",
 fn: function (aBoolean) {
@@ -924,7 +924,7 @@ fn: function () {
 smalltalk.Boolean);
 
 smalltalk.addMethod(
-"_|",
+"__or",
 smalltalk.method({
 selector: "|",
 fn: function (aBoolean) {
@@ -941,6 +941,196 @@ smalltalk.Boolean);
 
 
 
+smalltalk.addClass('CompiledMethod', smalltalk.Object, [], 'Kernel-Methods');
+smalltalk.addMethod(
+"_arguments",
+smalltalk.method({
+selector: "arguments",
+fn: function () {
+    var self = this;
+    return self.args || [];
+    return self;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_category",
+smalltalk.method({
+selector: "category",
+fn: function () {
+    var self = this;
+    var $2, $1;
+    $2 = smalltalk.send(self, "_basicAt_", ["category"]);
+    if (($receiver = $2) == nil || $receiver == undefined) {
+        $1 = "";
+    } else {
+        $1 = $2;
+    }
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_category_",
+smalltalk.method({
+selector: "category:",
+fn: function (aString){
+var self=this;
+var $1;
+var oldCategory;
+oldCategory=smalltalk.send(self,"_category",[]);
+smalltalk.send(self,"_basicAt_put_",["category",aString]);
+$1=smalltalk.send(self,"_methodClass",[]);
+if(($receiver = $1) == nil || $receiver == undefined){
+$1;
+} else {
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_methodClass",[]),"_organization",[]),"_addElement_",[aString]);
+smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self,"_methodClass",[]),"_methods",[]),"_select_",[(function(each){
+return smalltalk.send(smalltalk.send(each,"_category",[]),"__eq",[oldCategory]);
+})]),"_ifEmpty_",[(function(){
+return smalltalk.send(smalltalk.send(smalltalk.send(self,"_methodClass",[]),"_organization",[]),"_removeElement_",[oldCategory]);
+})]);
+};
+return self}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_fn",
+smalltalk.method({
+selector: "fn",
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["fn"]);
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_fn_",
+smalltalk.method({
+selector: "fn:",
+fn: function (aBlock) {
+    var self = this;
+    smalltalk.send(self, "_basicAt_put_", ["fn", aBlock]);
+    return self;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_messageSends",
+smalltalk.method({
+selector: "messageSends",
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["messageSends"]);
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_methodClass",
+smalltalk.method({
+selector: "methodClass",
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["methodClass"]);
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_protocol",
+smalltalk.method({
+selector: "protocol",
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_category", []);
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_referencedClasses",
+smalltalk.method({
+selector: "referencedClasses",
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["referencedClasses"]);
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_selector",
+smalltalk.method({
+selector: "selector",
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["selector"]);
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_selector_",
+smalltalk.method({
+selector: "selector:",
+fn: function (aString) {
+    var self = this;
+    smalltalk.send(self, "_basicAt_put_", ["selector", aString]);
+    return self;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_source",
+smalltalk.method({
+selector: "source",
+fn: function () {
+    var self = this;
+    var $2, $1;
+    $2 = smalltalk.send(self, "_basicAt_", ["source"]);
+    if (($receiver = $2) == nil || $receiver == undefined) {
+        $1 = "";
+    } else {
+        $1 = $2;
+    }
+    return $1;
+}
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_source_",
+smalltalk.method({
+selector: "source:",
+fn: function (aString) {
+    var self = this;
+    smalltalk.send(self, "_basicAt_put_", ["source", aString]);
+    return self;
+}
+}),
+smalltalk.CompiledMethod);
+
+
+
 smalltalk.addClass('Date', smalltalk.Object, [], 'Kernel-Objects');
 smalltalk.addMethod(
 "__plus",
@@ -1564,7 +1754,7 @@ smalltalk.JSObjectProxy.klass);
 
 smalltalk.addClass('Number', smalltalk.Object, [], 'Kernel-Objects');
 smalltalk.addMethod(
-"_&",
+"__and",
 smalltalk.method({
 selector: "&",
 fn: function (aNumber) {
@@ -1702,7 +1892,7 @@ fn: function (aNumber) {
 smalltalk.Number);
 
 smalltalk.addMethod(
-"_\x5c\x5c",
+"__backslash_backslash",
 smalltalk.method({
 selector: "\x5c\x5c",
 fn: function (aNumber) {
@@ -2146,7 +2336,7 @@ fn: function () {
 smalltalk.Number);
 
 smalltalk.addMethod(
-"_|",
+"__or",
 smalltalk.method({
 selector: "|",
 fn: function (aNumber) {
@@ -2176,11 +2366,11 @@ smalltalk.addMethod(
 "_addElement_",
 smalltalk.method({
 selector: "addElement:",
-fn: function (anObject) {
-    var self = this;
-    self.addElement(anObject);
-    return self;
-}
+fn: function (anObject){
+var self=this;
+self.elements.addElement(anObject);
+;
+return self}
 }),
 smalltalk.Organizer);
 
@@ -2201,11 +2391,11 @@ smalltalk.addMethod(
 "_removeElement_",
 smalltalk.method({
 selector: "removeElement:",
-fn: function (anObject) {
-    var self = this;
-    self.removeElement(anObject);
-    return self;
-}
+fn: function (anObject){
+var self=this;
+self.elements.removeElement(anObject);
+;
+return self}
 }),
 smalltalk.Organizer);
 

+ 275 - 19
js/Kernel-Objects.js

@@ -968,7 +968,7 @@ referencedClasses: []
 smalltalk.Object);
 
 smalltalk.addMethod(
-"_~_eq",
+"__tild_eq",
 smalltalk.method({
 selector: "~=",
 category: 'comparing',
@@ -986,7 +986,7 @@ referencedClasses: []
 smalltalk.Object);
 
 smalltalk.addMethod(
-"_~~",
+"__tild_tild",
 smalltalk.method({
 selector: "~~",
 category: 'comparing',
@@ -1024,7 +1024,7 @@ smalltalk.Object.klass);
 smalltalk.addClass('Boolean', smalltalk.Object, [], 'Kernel-Objects');
 smalltalk.Boolean.comment="Boolean wraps the JavaScript `Boolean()` constructor. The `true` and `false` objects are the JavaScript boolean objects.\x0a\x0aBoolean defines the protocol for logic testing operations and conditional control structures for the logical values.\x0aBoolean instances are weither `true` or `false`."
 smalltalk.addMethod(
-"_&",
+"__and",
 smalltalk.method({
 selector: "&",
 category: 'controlling',
@@ -1281,7 +1281,7 @@ referencedClasses: []
 smalltalk.Boolean);
 
 smalltalk.addMethod(
-"_|",
+"__or",
 smalltalk.method({
 selector: "|",
 category: 'controlling',
@@ -1303,6 +1303,262 @@ smalltalk.Boolean);
 
 
 
+smalltalk.addClass('CompiledMethod', smalltalk.Object, [], 'Kernel-Methods');
+smalltalk.CompiledMethod.comment="CompiledMethod hold the source and compiled code of a class method.\x0a\x0aYou can get a CompiledMethod using `Behavior>>methodAt:`\x0a\x0a\x09String methodAt: 'lines'\x0a\x0aand read the source code\x0a\x0a\x09(String methodAt: 'lines') source\x0a\x0aSee referenced classes:\x0a\x0a\x09(String methodAt: 'lines') referencedClasses\x0a\x0aor messages sent from this method:\x0a\x09\x0a\x09(String methodAt: 'lines')  messageSends"
+smalltalk.addMethod(
+"_arguments",
+smalltalk.method({
+selector: "arguments",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    return self.args || [];
+    return self;
+},
+args: [],
+source: "arguments\x0a\x09<return self.args || []>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_category",
+smalltalk.method({
+selector: "category",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $2, $1;
+    $2 = smalltalk.send(self, "_basicAt_", ["category"]);
+    if (($receiver = $2) == nil || $receiver == undefined) {
+        $1 = "";
+    } else {
+        $1 = $2;
+    }
+    return $1;
+},
+args: [],
+source: "category\x0a\x09^(self basicAt: 'category') ifNil: ['']",
+messageSends: ["ifNil:", "basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_category_",
+smalltalk.method({
+selector: "category:",
+category: 'accessing',
+fn: function (aString){
+var self=this;
+var $1;
+var oldCategory;
+oldCategory=smalltalk.send(self,"_category",[]);
+smalltalk.send(self,"_basicAt_put_",["category",aString]);
+$1=smalltalk.send(self,"_methodClass",[]);
+if(($receiver = $1) == nil || $receiver == undefined){
+$1;
+} else {
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_methodClass",[]),"_organization",[]),"_addElement_",[aString]);
+smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self,"_methodClass",[]),"_methods",[]),"_select_",[(function(each){
+return smalltalk.send(smalltalk.send(each,"_category",[]),"__eq",[oldCategory]);
+})]),"_ifEmpty_",[(function(){
+return smalltalk.send(smalltalk.send(smalltalk.send(self,"_methodClass",[]),"_organization",[]),"_removeElement_",[oldCategory]);
+})]);
+};
+return self},
+args: ["aString"],
+source: "category: aString\x0a\x09| oldCategory |\x0a    oldCategory := self category.\x0a\x09self basicAt: 'category' put: aString.\x0a    \x0a    self methodClass ifNotNil: [\x0a    \x09self methodClass organization addElement: aString.\x0a    \x0a\x09\x09(self methodClass methods \x0a    \x09\x09select: [ :each | each category = oldCategory ])\x0a        \x09ifEmpty: [ self methodClass organization removeElement: oldCategory ] ]",
+messageSends: ["category", "basicAt:put:", "ifNotNil:", "addElement:", "organization", "methodClass", "ifEmpty:", "removeElement:", "select:", "=", "methods"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_fn",
+smalltalk.method({
+selector: "fn",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["fn"]);
+    return $1;
+},
+args: [],
+source: "fn\x0a\x09^self basicAt: 'fn'",
+messageSends: ["basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_fn_",
+smalltalk.method({
+selector: "fn:",
+category: 'accessing',
+fn: function (aBlock) {
+    var self = this;
+    smalltalk.send(self, "_basicAt_put_", ["fn", aBlock]);
+    return self;
+},
+args: ["aBlock"],
+source: "fn: aBlock\x0a\x09self basicAt: 'fn' put: aBlock",
+messageSends: ["basicAt:put:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_messageSends",
+smalltalk.method({
+selector: "messageSends",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["messageSends"]);
+    return $1;
+},
+args: [],
+source: "messageSends\x0a\x09^self basicAt: 'messageSends'",
+messageSends: ["basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_methodClass",
+smalltalk.method({
+selector: "methodClass",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["methodClass"]);
+    return $1;
+},
+args: [],
+source: "methodClass\x0a\x09^self basicAt: 'methodClass'",
+messageSends: ["basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_protocol",
+smalltalk.method({
+selector: "protocol",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_category", []);
+    return $1;
+},
+args: [],
+source: "protocol\x0a\x09^ self category",
+messageSends: ["category"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_referencedClasses",
+smalltalk.method({
+selector: "referencedClasses",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["referencedClasses"]);
+    return $1;
+},
+args: [],
+source: "referencedClasses\x0a\x09^self basicAt: 'referencedClasses'",
+messageSends: ["basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_selector",
+smalltalk.method({
+selector: "selector",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $1;
+    $1 = smalltalk.send(self, "_basicAt_", ["selector"]);
+    return $1;
+},
+args: [],
+source: "selector\x0a\x09^self basicAt: 'selector'",
+messageSends: ["basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_selector_",
+smalltalk.method({
+selector: "selector:",
+category: 'accessing',
+fn: function (aString) {
+    var self = this;
+    smalltalk.send(self, "_basicAt_put_", ["selector", aString]);
+    return self;
+},
+args: ["aString"],
+source: "selector: aString\x0a\x09self basicAt: 'selector' put: aString",
+messageSends: ["basicAt:put:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_source",
+smalltalk.method({
+selector: "source",
+category: 'accessing',
+fn: function () {
+    var self = this;
+    var $2, $1;
+    $2 = smalltalk.send(self, "_basicAt_", ["source"]);
+    if (($receiver = $2) == nil || $receiver == undefined) {
+        $1 = "";
+    } else {
+        $1 = $2;
+    }
+    return $1;
+},
+args: [],
+source: "source\x0a\x09^(self basicAt: 'source') ifNil: ['']",
+messageSends: ["ifNil:", "basicAt:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+smalltalk.addMethod(
+"_source_",
+smalltalk.method({
+selector: "source:",
+category: 'accessing',
+fn: function (aString) {
+    var self = this;
+    smalltalk.send(self, "_basicAt_put_", ["source", aString]);
+    return self;
+},
+args: ["aString"],
+source: "source: aString\x0a\x09self basicAt: 'source' put: aString",
+messageSends: ["basicAt:put:"],
+referencedClasses: []
+}),
+smalltalk.CompiledMethod);
+
+
+
 smalltalk.addClass('Date', smalltalk.Object, [], 'Kernel-Objects');
 smalltalk.Date.comment="The Date class is used to work with dates and times. Therefore `Date today` and `Date now` are both valid in\x0aAmber and answer the same date object.\x0a\x0aDate wraps the `Date()` JavaScript constructor, and Smalltalk date objects are JavaScript date objects."
 smalltalk.addMethod(
@@ -2169,7 +2425,7 @@ smalltalk.JSObjectProxy.klass);
 smalltalk.addClass('Number', smalltalk.Object, [], 'Kernel-Objects');
 smalltalk.Number.comment="Number holds the most general methods for dealing with numbers.  \x0aNumber is directly mapped to JavaScript Number.\x0a\x0aMost arithmetic methods like `#+` `#/` `#-` `#max:` are directly inlined into javascript. \x0a\x0a##Enumerating\x0aA Number can be used to evaluate a Block a fixed number of times:\x0a\x0a\x095 timesRepeat: [Transcript show: 'This will be printed 5 times'; cr].\x0a\x09\x0a\x091 to: 5 do: [:aNumber| Transcript show: aNumber asString; cr].\x0a\x09\x0a\x091 to: 10 by: 2 do: [:aNumber| Transcript show: aNumber asString; cr]."
 smalltalk.addMethod(
-"_&",
+"__and",
 smalltalk.method({
 selector: "&",
 category: 'converting',
@@ -2362,7 +2618,7 @@ referencedClasses: ["Point"]
 smalltalk.Number);
 
 smalltalk.addMethod(
-"_\x5c\x5c",
+"__backslash_backslash",
 smalltalk.method({
 selector: "\x5c\x5c",
 category: 'arithmetic',
@@ -2966,7 +3222,7 @@ referencedClasses: []
 smalltalk.Number);
 
 smalltalk.addMethod(
-"_|",
+"__or",
 smalltalk.method({
 selector: "|",
 category: 'converting',
@@ -3007,13 +3263,13 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: "addElement:",
 category: 'accessing',
-fn: function (anObject) {
-    var self = this;
-    self.addElement(anObject);
-    return self;
-},
+fn: function (anObject){
+var self=this;
+self.elements.addElement(anObject);
+;
+return self},
 args: ["anObject"],
-source: "addElement: anObject\x0a\x09<self.addElement(anObject)>",
+source: "addElement: anObject\x0a\x09<self.elements.addElement(anObject)>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -3042,13 +3298,13 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: "removeElement:",
 category: 'accessing',
-fn: function (anObject) {
-    var self = this;
-    self.removeElement(anObject);
-    return self;
-},
+fn: function (anObject){
+var self=this;
+self.elements.removeElement(anObject);
+;
+return self},
 args: ["anObject"],
-source: "removeElement: anObject\x0a\x09<self.removeElement(anObject)>",
+source: "removeElement: anObject\x0a\x09<self.elements.removeElement(anObject)>",
 messageSends: [],
 referencedClasses: []
 }),

+ 1 - 1
js/amber.js

@@ -87,12 +87,12 @@ amber = (function() {
 				'SUnit',
 				'Importer-Exporter',
 				'Compiler-Exceptions',
-				'Compiler-Interpreter',
 				'Compiler-Core',
 				'Compiler-AST',
 				'Compiler-Semantic',
 				'Compiler-IR',
 				'Compiler-Inlining',
+				'Compiler-Interpreter',
 				'Compiler-Tests',
 				'parser',
 				'IDE',

+ 24 - 13
js/boot.js

@@ -534,11 +534,11 @@ function Smalltalk() {
 		}
 	}
 
-	st.withContext = function(fn, receiver, selector, args) {
+	st.withContext = function(fn, receiver, selector, args, lookupClass) {
 		if(st.thisContext) {
-			return inContext(fn, receiver, selector, args);
+			return inContext(fn, receiver, selector, args, lookupClass);
 		} else {
-			try {return inContext(fn, receiver, selector, args)}
+			try {return inContext(fn, receiver, selector, args, lookupClass)}
 			catch(error) {
 				// Reset the context stack in any case
 				st.thisContext = undefined;
@@ -552,9 +552,9 @@ function Smalltalk() {
 		}
 	};
 
-	function inContext(fn, receiver, selector, args) {
-		var context = pushContext(receiver, selector, args);
-		var result = fn();
+	function inContext(fn, receiver, selector, args, lookupClass) {
+		var context = pushContext(receiver, selector, args, lookupClass);
+		var result = fn(context);
 		popContext(context);
 		return result;
 	}
@@ -580,10 +580,10 @@ function Smalltalk() {
 		   Object>>doesNotUnderstand: */
 
 		return receiver._doesNotUnderstand_(
-				st.Message._new()
+			st.Message._new()
 				._selector_(st.convertSelector(selector))
 				._arguments_(args)
-				);
+		);
 	}
 
 	/* Call a method of a JS object, or answer a property if it exists.
@@ -627,10 +627,10 @@ function Smalltalk() {
 		return st.thisContext ? st.thisContext.copy() : nil;
 	};
 
-	function pushContext(receiver, selector, temps) {
+	function pushContext(receiver, selector, locals, lookupClass) {
 		var c = st.oldContext, tc = st.thisContext;
 		if(!c) {
-			return st.thisContext = new SmalltalkMethodContext(receiver, selector, temps, tc);
+			return st.thisContext = new SmalltalkMethodContext(receiver, selector, locals, tc, lookupClass);
 
 		}
 		st.oldContext = null;
@@ -638,7 +638,7 @@ function Smalltalk() {
         c.pc          = 1;
 		c.receiver    = receiver;
         c.selector    = selector || "";
-		c.temps       = temps || {};
+		c.locals      = locals || {};
 		return st.thisContext = c;
 	}
 
@@ -751,11 +751,12 @@ function Smalltalk() {
 
 inherits(Smalltalk, SmalltalkObject);
 
-function SmalltalkMethodContext(receiver, selector, temps, home) {
+function SmalltalkMethodContext(receiver, selector, locals, home, lookupClass) {
 	this.receiver    = receiver;
     this.selector    = selector;
-	this.temps       = temps || {};
+	this.locals      = locals || {};
 	this.homeContext = home;
+    this.lookupClass = lookupClass;
 }
 
 inherits(SmalltalkMethodContext, SmalltalkObject);
@@ -771,6 +772,16 @@ SmalltalkMethodContext.prototype.copy = function() {
 	);
 };
 
+SmalltalkMethodContext.prototype.method = function() {
+    var method;
+    var lookup = this.lookupClass || this.receiver.klass;
+    while(!method && lookup) {
+        method = lookup.methods[smalltalk.convertSelector(this.selector)];
+        lookup = lookup.superclass
+    }
+    return method;
+};
+
 SmalltalkMethodContext.prototype.resume = function() {
     //Brutally set the receiver as thisContext, then re-enter the function
     smalltalk.thisContext = this;

+ 36 - 37
st/Compiler-Interpreter.st

@@ -1,27 +1,4 @@
 Smalltalk current createPackage: 'Compiler-Interpreter' properties: #{}!
-BlockClosure subclass: #ASTBlockClosure
-	instanceVariableNames: 'astNode'
-	package: 'Compiler-Interpreter'!
-!ASTBlockClosure commentStamp!
-ASTBlockClosure is polymorph with BlockClosure. 
-An ASTBlockClosure is used to interpret a BlockNode, and override all "primitive" methods (#value and co).!
-
-!ASTBlockClosure methodsFor: 'accessing'!
-
-astNode
-	^ astNode
-!
-
-astNode: aNode
-	astNode := aNode
-! !
-
-!ASTBlockClosure methodsFor: 'evaluating'!
-
-value
-	^ ASTInterpreter current blockValue: self
-! !
-
 NodeVisitor subclass: #ASTInterpreter
 	instanceVariableNames: 'currentNode context shouldReturn'
 	package: 'Compiler-Interpreter'!
@@ -66,47 +43,69 @@ send: aSelector to: anObject arguments: aCollection
 !ASTInterpreter methodsFor: 'visiting'!
 
 visitBlockNode: aNode
-	^ ASTBlockClosure new
-    	astNode: aNode;
-        yourself
+    ^ [ self interpretNode: aNode nodes first ]
 !
 
 visitReturnNode: aNode
 	shouldReturn := true.
-    ^ self interpret: aNode nodes first
+    ^ self interpretNode: aNode nodes first
 !
 
 visitSendNode: aNode
 	"TODO: Handle super sends"
 	| receiver arguments |
     
-    receiver := self interpret: aNode receiver.
+    receiver := self interpretNode: aNode receiver.
     arguments := aNode arguments collect: [ :each |
-		self interpret: each ].
+		self interpretNode: each ].
     
     ^ self send: aNode selector to: receiver arguments: arguments
 !
 
 visitSequenceNode: aNode
 	aNode nodes allButLast do: [ :each | | value |
-        value := self interpret: each.
+        value := self interpretNode: each.
 		shouldReturn ifTrue: [ ^ value ] ].
-    ^ self interpret: aNode nodes last
+    ^ self interpretNode: aNode nodes last
 !
 
 visitValueNode: aNode
 	^ aNode value
 ! !
 
-ASTInterpreter class instanceVariableNames: 'current'!
+TestCase subclass: #ASTInterpretorTest
+	instanceVariableNames: ''
+	package: 'Compiler-Interpreter'!
+
+!ASTInterpretorTest methodsFor: 'accessing'!
+
+analyze: aNode forClass: aClass
+	(SemanticAnalyzer on: aClass) visit: aNode.
+    ^ aNode
+!
+
+interpret: aString
+	"the food is a methodNode. Interpret the sequenceNode only"
+    ^ ASTInterpreter new
+    	interpret: (self parse: aString forClass: Object) 
+        	nodes first
+!
+
+parse: aString
+	^ Smalltalk current parse: aString
+!
+
+parse: aString forClass: aClass
+	^ self analyze: (self parse: aString) forClass: aClass
+! !
 
-!ASTInterpreter class methodsFor: 'instance creation'!
+!ASTInterpretorTest methodsFor: 'tests'!
 
-current
-	^ current ifNil: [ current := super new ]
+testBinarySend
+	self assert: (self interpret: 'foo 2+3+4') equals: 9
 !
 
-new
-	self shouldNotImplement
+testBlockLiteral
+	self assert: false
 ! !
 

+ 36 - 0
st/Compiler-Tests.st

@@ -1,4 +1,40 @@
 Smalltalk current createPackage: 'Compiler-Tests' properties: #{}!
+TestCase subclass: #ASTInterpretorTest
+	instanceVariableNames: ''
+	package: 'Compiler-Interpreter'!
+
+!ASTInterpretorTest methodsFor: 'accessing'!
+
+analyze: aNode forClass: aClass
+	(SemanticAnalyzer on: aClass) visit: aNode.
+    ^ aNode
+!
+
+interpret: aString
+	"the food is a methodNode. Interpret the sequenceNode only"
+    ^ ASTInterpreter new
+    	interpret: (self parse: aString forClass: Object) 
+        	nodes first
+!
+
+parse: aString
+	^ Smalltalk current parse: aString
+!
+
+parse: aString forClass: aClass
+	^ self analyze: (self parse: aString) forClass: aClass
+! !
+
+!ASTInterpretorTest methodsFor: 'tests'!
+
+testBinarySend
+	self assert: (self interpret: 'foo 2+3+4') equals: 9
+!
+
+testBlockLiteral
+	self assert: false
+! !
+
 TestCase subclass: #CodeGeneratorTest
 	instanceVariableNames: 'receiver'
 	package: 'Compiler-Tests'!

+ 87 - 2
st/Kernel-Objects.st

@@ -442,6 +442,91 @@ printString
 	<return self.toString()>
 ! !
 
+Object subclass: #CompiledMethod
+	instanceVariableNames: ''
+	package: 'Kernel-Methods'!
+!CompiledMethod commentStamp!
+CompiledMethod hold the source and compiled code of a class method.
+
+You can get a CompiledMethod using `Behavior>>methodAt:`
+
+	String methodAt: 'lines'
+
+and read the source code
+
+	(String methodAt: 'lines') source
+
+See referenced classes:
+
+	(String methodAt: 'lines') referencedClasses
+
+or messages sent from this method:
+	
+	(String methodAt: 'lines')  messageSends!
+
+!CompiledMethod methodsFor: 'accessing'!
+
+arguments
+	<return self.args || []>
+!
+
+category
+	^(self basicAt: 'category') ifNil: ['']
+!
+
+category: aString
+	| oldCategory |
+    oldCategory := self category.
+	self basicAt: 'category' put: aString.
+    
+    self methodClass ifNotNil: [
+    	self methodClass organization addElement: aString.
+    
+		(self methodClass methods 
+    		select: [ :each | each category = oldCategory ])
+        	ifEmpty: [ self methodClass organization removeElement: oldCategory ] ]
+!
+
+fn
+	^self basicAt: 'fn'
+!
+
+fn: aBlock
+	self basicAt: 'fn' put: aBlock
+!
+
+messageSends
+	^self basicAt: 'messageSends'
+!
+
+methodClass
+	^self basicAt: 'methodClass'
+!
+
+protocol
+	^ self category
+!
+
+referencedClasses
+	^self basicAt: 'referencedClasses'
+!
+
+selector
+	^self basicAt: 'selector'
+!
+
+selector: aString
+	self basicAt: 'selector' put: aString
+!
+
+source
+	^(self basicAt: 'source') ifNil: ['']
+!
+
+source: aString
+	self basicAt: 'source' put: aString
+! !
+
 Object subclass: #Date
 	instanceVariableNames: ''
 	package: 'Kernel-Objects'!
@@ -997,7 +1082,7 @@ Object subclass: #Organizer
 !Organizer methodsFor: 'accessing'!
 
 addElement: anObject
-	<self.addElement(anObject)>
+	<self.elements.addElement(anObject)>
 !
 
 elements
@@ -1005,7 +1090,7 @@ elements
 !
 
 removeElement: anObject
-	<self.removeElement(anObject)>
+	<self.elements.removeElement(anObject)>
 ! !
 
 Object subclass: #Package

Some files were not shown because too many files changed in this diff