|
@@ -1,58 +1,4 @@
|
|
smalltalk.addPackage('Compiler-Interpreter', {});
|
|
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.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn'], 'Compiler-Interpreter');
|
|
smalltalk.addMethod(
|
|
smalltalk.addMethod(
|
|
"_blockValue_",
|
|
"_blockValue_",
|
|
@@ -184,17 +130,16 @@ selector: "visitBlockNode:",
|
|
category: 'visiting',
|
|
category: 'visiting',
|
|
fn: function (aNode){
|
|
fn: function (aNode){
|
|
var self=this;
|
|
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;
|
|
return $1;
|
|
},
|
|
},
|
|
args: ["aNode"],
|
|
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);
|
|
smalltalk.ASTInterpreter);
|
|
|
|
|
|
@@ -207,12 +152,12 @@ fn: function (aNode){
|
|
var self=this;
|
|
var self=this;
|
|
var $1;
|
|
var $1;
|
|
self["@shouldReturn"]=true;
|
|
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;
|
|
return $1;
|
|
},
|
|
},
|
|
args: ["aNode"],
|
|
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: []
|
|
referencedClasses: []
|
|
}),
|
|
}),
|
|
smalltalk.ASTInterpreter);
|
|
smalltalk.ASTInterpreter);
|
|
@@ -227,16 +172,16 @@ var self=this;
|
|
var $1;
|
|
var $1;
|
|
var receiver;
|
|
var receiver;
|
|
var arguments;
|
|
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;
|
|
return $1;
|
|
},
|
|
},
|
|
args: ["aNode"],
|
|
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: []
|
|
referencedClasses: []
|
|
}),
|
|
}),
|
|
smalltalk.ASTInterpreter);
|
|
smalltalk.ASTInterpreter);
|
|
@@ -251,22 +196,22 @@ var self=this;
|
|
var $1;
|
|
var $1;
|
|
var $early={};
|
|
var $early={};
|
|
try {
|
|
try {
|
|
-smalltalk.send(smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_allButLast",[]),"_do_",[(function(each){
|
|
|
|
|
|
+_st(_st(_st(aNode)._nodes())._allButLast())._do_((function(each){
|
|
var value;
|
|
var value;
|
|
-value=smalltalk.send(self,"_interpret_",[each]);
|
|
|
|
|
|
+value=_st(self)._interpretNode_(each);
|
|
value;
|
|
value;
|
|
if(smalltalk.assert(self["@shouldReturn"])){
|
|
if(smalltalk.assert(self["@shouldReturn"])){
|
|
throw $early=[value];
|
|
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;
|
|
return $1;
|
|
}
|
|
}
|
|
catch(e) {if(e===$early)return e[0]; throw e}
|
|
catch(e) {if(e===$early)return e[0]; throw e}
|
|
},
|
|
},
|
|
args: ["aNode"],
|
|
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: []
|
|
referencedClasses: []
|
|
}),
|
|
}),
|
|
smalltalk.ASTInterpreter);
|
|
smalltalk.ASTInterpreter);
|
|
@@ -290,44 +235,110 @@ referencedClasses: []
|
|
smalltalk.ASTInterpreter);
|
|
smalltalk.ASTInterpreter);
|
|
|
|
|
|
|
|
|
|
-smalltalk.ASTInterpreter.klass.iVarNames = ['current'];
|
|
|
|
|
|
+
|
|
|
|
+smalltalk.addClass('ASTInterpretorTest', smalltalk.TestCase, [], 'Compiler-Interpreter');
|
|
smalltalk.addMethod(
|
|
smalltalk.addMethod(
|
|
-"_current",
|
|
|
|
|
|
+"_analyze_forClass_",
|
|
smalltalk.method({
|
|
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 self=this;
|
|
var $1;
|
|
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;
|
|
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: [],
|
|
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: []
|
|
referencedClasses: []
|
|
}),
|
|
}),
|
|
-smalltalk.ASTInterpreter.klass);
|
|
|
|
|
|
+smalltalk.ASTInterpretorTest);
|
|
|
|
|
|
smalltalk.addMethod(
|
|
smalltalk.addMethod(
|
|
-"_new",
|
|
|
|
|
|
+"_testBlockLiteral",
|
|
smalltalk.method({
|
|
smalltalk.method({
|
|
-selector: "new",
|
|
|
|
-category: 'instance creation',
|
|
|
|
|
|
+selector: "testBlockLiteral",
|
|
|
|
+category: 'tests',
|
|
fn: function (){
|
|
fn: function (){
|
|
var self=this;
|
|
var self=this;
|
|
-smalltalk.send(self,"_shouldNotImplement",[]);
|
|
|
|
|
|
+_st(self)._assert_(false);
|
|
return self},
|
|
return self},
|
|
args: [],
|
|
args: [],
|
|
-source: "new\x0a\x09self shouldNotImplement",
|
|
|
|
-messageSends: ["shouldNotImplement"],
|
|
|
|
|
|
+source: "testBlockLiteral\x0a\x09self assert: false",
|
|
|
|
+messageSends: ["assert:"],
|
|
referencedClasses: []
|
|
referencedClasses: []
|
|
}),
|
|
}),
|
|
-smalltalk.ASTInterpreter.klass);
|
|
|
|
|
|
+smalltalk.ASTInterpretorTest);
|
|
|
|
+
|
|
|
|
|
|
|
|
|