|
@@ -0,0 +1,333 @@
|
|
|
+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_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "blockValue:",
|
|
|
+category: 'interpreting',
|
|
|
+fn: function (anASTBlockClosure){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(smalltalk.send(anASTBlockClosure,"_astNode",[]),"_nodes",[]),"_first",[])]);
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["anASTBlockClosure"],
|
|
|
+source: "blockValue: anASTBlockClosure\x0a\x09^ self interpret: anASTBlockClosure astNode nodes first",
|
|
|
+messageSends: ["interpret:", "first", "nodes", "astNode"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_context",
|
|
|
+smalltalk.method({
|
|
|
+selector: "context",
|
|
|
+category: 'accessing',
|
|
|
+fn: function (){
|
|
|
+var self=this;
|
|
|
+return self["@context"];
|
|
|
+},
|
|
|
+args: [],
|
|
|
+source: "context\x0a\x09^ context",
|
|
|
+messageSends: [],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_context_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "context:",
|
|
|
+category: 'accessing',
|
|
|
+fn: function (aMethodContext){
|
|
|
+var self=this;
|
|
|
+self["@context"]=aMethodContext;
|
|
|
+return self},
|
|
|
+args: ["aMethodContext"],
|
|
|
+source: "context: aMethodContext\x0a\x09context := aMethodContext",
|
|
|
+messageSends: [],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_initialize",
|
|
|
+smalltalk.method({
|
|
|
+selector: "initialize",
|
|
|
+category: 'initialization',
|
|
|
+fn: function (){
|
|
|
+var self=this;
|
|
|
+smalltalk.send(self,"_initialize",[],smalltalk.NodeVisitor);
|
|
|
+self["@shouldReturn"]=false;
|
|
|
+return self},
|
|
|
+args: [],
|
|
|
+source: "initialize\x0a\x09super initialize.\x0a shouldReturn := false",
|
|
|
+messageSends: ["initialize"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_interpret_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "interpret:",
|
|
|
+category: 'interpreting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+self["@shouldReturn"]=false;
|
|
|
+$1=smalltalk.send(self,"_interpretNode_",[aNode]);
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["aNode"],
|
|
|
+source: "interpret: aNode\x0a\x09shouldReturn := false.\x0a ^ self interpretNode: aNode",
|
|
|
+messageSends: ["interpretNode:"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_interpretNode_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "interpretNode:",
|
|
|
+category: 'interpreting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+self["@currentNode"]=aNode;
|
|
|
+$1=smalltalk.send(self,"_visit_",[aNode]);
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["aNode"],
|
|
|
+source: "interpretNode: aNode\x0a\x09currentNode := aNode.\x0a ^ self visit: aNode",
|
|
|
+messageSends: ["visit:"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_send_to_arguments_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "send:to:arguments:",
|
|
|
+category: 'interpreting',
|
|
|
+fn: function (aSelector,anObject,aCollection){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+$1=smalltalk.send(anObject,"_perform_withArguments_",[aSelector,aCollection]);
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["aSelector", "anObject", "aCollection"],
|
|
|
+source: "send: aSelector to: anObject arguments: aCollection\x0a\x09^ anObject perform: aSelector withArguments: aCollection",
|
|
|
+messageSends: ["perform:withArguments:"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_visitBlockNode_",
|
|
|
+smalltalk.method({
|
|
|
+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;
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitBlockNode: aNode\x0a\x09^ ASTBlockClosure new\x0a \x09astNode: aNode;\x0a yourself",
|
|
|
+messageSends: ["astNode:", "new", "yourself"],
|
|
|
+referencedClasses: ["ASTBlockClosure"]
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_visitReturnNode_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "visitReturnNode:",
|
|
|
+category: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+self["@shouldReturn"]=true;
|
|
|
+$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_first",[])]);
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitReturnNode: aNode\x0a\x09shouldReturn := true.\x0a ^ self interpret: aNode nodes first",
|
|
|
+messageSends: ["interpret:", "first", "nodes"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_visitSendNode_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "visitSendNode:",
|
|
|
+category: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+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]);
|
|
|
+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"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_visitSequenceNode_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "visitSequenceNode:",
|
|
|
+category: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+var $early={};
|
|
|
+try {
|
|
|
+smalltalk.send(smalltalk.send(smalltalk.send(aNode,"_nodes",[]),"_allButLast",[]),"_do_",[(function(each){
|
|
|
+var value;
|
|
|
+value=smalltalk.send(self,"_interpret_",[each]);
|
|
|
+value;
|
|
|
+if(smalltalk.assert(self["@shouldReturn"])){
|
|
|
+throw $early=[value];
|
|
|
+};
|
|
|
+})]);
|
|
|
+$1=smalltalk.send(self,"_interpret_",[smalltalk.send(smalltalk.send(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"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_visitValueNode_",
|
|
|
+smalltalk.method({
|
|
|
+selector: "visitValueNode:",
|
|
|
+category: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var $1;
|
|
|
+$1=smalltalk.send(aNode,"_value",[]);
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitValueNode: aNode\x0a\x09^ aNode value",
|
|
|
+messageSends: ["value"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter);
|
|
|
+
|
|
|
+
|
|
|
+smalltalk.ASTInterpreter.klass.iVarNames = ['current'];
|
|
|
+smalltalk.addMethod(
|
|
|
+"_current",
|
|
|
+smalltalk.method({
|
|
|
+selector: "current",
|
|
|
+category: 'instance creation',
|
|
|
+fn: function (){
|
|
|
+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"];
|
|
|
+};
|
|
|
+return $1;
|
|
|
+},
|
|
|
+args: [],
|
|
|
+source: "current\x0a\x09^ current ifNil: [ current := super new ]",
|
|
|
+messageSends: ["ifNil:", "new"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter.klass);
|
|
|
+
|
|
|
+smalltalk.addMethod(
|
|
|
+"_new",
|
|
|
+smalltalk.method({
|
|
|
+selector: "new",
|
|
|
+category: 'instance creation',
|
|
|
+fn: function (){
|
|
|
+var self=this;
|
|
|
+smalltalk.send(self,"_shouldNotImplement",[]);
|
|
|
+return self},
|
|
|
+args: [],
|
|
|
+source: "new\x0a\x09self shouldNotImplement",
|
|
|
+messageSends: ["shouldNotImplement"],
|
|
|
+referencedClasses: []
|
|
|
+}),
|
|
|
+smalltalk.ASTInterpreter.klass);
|
|
|
+
|
|
|
+
|