Browse Source

Compiler is now series of transformers.

Herbert Vojčík 7 years ago
parent
commit
7d0f90b257

+ 55 - 31
src/Compiler-Core.js

@@ -19,18 +19,25 @@ var self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-self._subclassResponsibility();
-return self;
+return $recv(self._transformers())._inject_into_(aNode,(function(input,transformer){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv(transformer)._visit_(input);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({input:input,transformer:transformer},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"compileNode:",{aNode:aNode},$globals.AbstractCodeGenerator)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "compileNode: aNode\x0a\x09self subclassResponsibility",
+source: "compileNode: aNode\x0a\x09^ self transformers\x0a\x09\x09inject: aNode\x0a\x09\x09into: [ :input :transformer | transformer visit: input ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
+messageSends: ["inject:into:", "transformers", "visit:"]
 }),
 $globals.AbstractCodeGenerator);
 
@@ -179,48 +186,36 @@ messageSends: []
 }),
 $globals.AbstractCodeGenerator);
 
-
-
-$core.addClass('CodeGenerator', $globals.AbstractCodeGenerator, [], 'Compiler-Core');
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.CodeGenerator.comment="I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.\x0aSee `InliningCodeGenerator` for an optimized JavaScript code generation.";
-//>>excludeEnd("ide");
 $core.addMethod(
 $core.method({
-selector: "compileNode:",
+selector: "transformers",
 protocol: 'compiling',
-fn: function (aNode){
+fn: function (){
 var self=this;
-var ir,stream;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1;
-$recv(self._semanticAnalyzer())._visit_(aNode);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["visit:"]=1;
-//>>excludeEnd("ctx");
-ir=$recv(self._translator())._visit_(aNode);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["visit:"]=2;
-//>>excludeEnd("ctx");
-$1=self._irTranslator();
-$recv($1)._currentClass_(self._currentClass());
-$recv($1)._visit_(ir);
-return $recv($1)._contents();
+self._subclassResponsibility();
+return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"compileNode:",{aNode:aNode,ir:ir,stream:stream},$globals.CodeGenerator)});
+}, function($ctx1) {$ctx1.fill(self,"transformers",{},$globals.AbstractCodeGenerator)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aNode"],
-source: "compileNode: aNode\x0a\x09| ir stream |\x0a\x09self semanticAnalyzer visit: aNode.\x0a\x09ir := self translator visit: aNode.\x0a\x09^ self irTranslator\x0a\x09\x09currentClass: self currentClass;\x0a\x09\x09visit: ir;\x0a\x09\x09contents",
+args: [],
+source: "transformers\x0a\x09self subclassResponsibility",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["visit:", "semanticAnalyzer", "translator", "currentClass:", "irTranslator", "currentClass", "contents"]
+messageSends: ["subclassResponsibility"]
 }),
-$globals.CodeGenerator);
+$globals.AbstractCodeGenerator);
+
 
+
+$core.addClass('CodeGenerator', $globals.AbstractCodeGenerator, [], 'Compiler-Core');
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.CodeGenerator.comment="I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.\x0aSee `InliningCodeGenerator` for an optimized JavaScript code generation.";
+//>>excludeEnd("ide");
 $core.addMethod(
 $core.method({
 selector: "irTranslator",
@@ -288,6 +283,35 @@ messageSends: []
 }),
 $globals.CodeGenerator);
 
+$core.addMethod(
+$core.method({
+selector: "transformers",
+protocol: 'compiling',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$4,$3;
+$1=self._semanticAnalyzer();
+$2=self._translator();
+$4=self._irTranslator();
+$recv($4)._currentClass_(self._currentClass());
+$3=$recv($4)._yourself();
+return [$1,$2,$3];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"transformers",{},$globals.CodeGenerator)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "transformers\x0a\x09^ {\x0a\x09\x09self semanticAnalyzer.\x0a\x09\x09self translator.\x0a\x09\x09self irTranslator currentClass: self currentClass; yourself\x0a\x09}",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["semanticAnalyzer", "translator", "currentClass:", "irTranslator", "currentClass", "yourself"]
+}),
+$globals.CodeGenerator);
+
 $core.addMethod(
 $core.method({
 selector: "translator",

+ 14 - 10
src/Compiler-Core.st

@@ -38,6 +38,12 @@ source: aString
 !AbstractCodeGenerator methodsFor: 'compiling'!
 
 compileNode: aNode
+	^ self transformers
+		inject: aNode
+		into: [ :input :transformer | transformer visit: input ]
+!
+
+transformers
 	self subclassResponsibility
 ! !
 
@@ -50,16 +56,6 @@ See `InliningCodeGenerator` for an optimized JavaScript code generation.!
 
 !CodeGenerator methodsFor: 'compiling'!
 
-compileNode: aNode
-	| ir stream |
-	self semanticAnalyzer visit: aNode.
-	ir := self translator visit: aNode.
-	^ self irTranslator
-		currentClass: self currentClass;
-		visit: ir;
-		contents
-!
-
 irTranslator
 	^ IRJSTranslator new
 !
@@ -74,6 +70,14 @@ semanticAnalyzerClass
 	^ SemanticAnalyzer
 !
 
+transformers
+	^ {
+		self semanticAnalyzer.
+		self translator.
+		self irTranslator currentClass: self currentClass; yourself
+	}
+!
+
 translator
 	^ IRASTTranslator new
 		source: self source;

+ 3 - 3
src/Compiler-IR.js

@@ -3816,17 +3816,17 @@ $ctx4.supercall = false;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
 //>>excludeEnd("ctx");
 }));
-return self;
+return self._contents();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"visitIRMethod:",{anIRMethod:anIRMethod},$globals.IRJSTranslator)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["anIRMethod"],
-source: "visitIRMethod: anIRMethod\x0a\x0a\x09self stream\x0a\x09\x09nextPutMethodDeclaration: anIRMethod\x0a\x09\x09with: [ self stream\x0a\x09\x09\x09nextPutFunctionWith: [\x0a\x09\x09\x09\x09self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |\x0a\x09\x09\x09\x09\x09each name asVariableName ]).\x0a\x09\x09\x09\x09self stream nextPutContextFor: anIRMethod during: [\x0a\x09\x09\x09\x09\x09anIRMethod internalVariables ifNotEmpty: [ :internalVars |\x0a\x09\x09\x09\x09\x09\x09self stream nextPutVars: \x0a\x09\x09\x09\x09\x09\x09\x09(internalVars asSet collect: [ :each | each variable alias ]) ].\x0a\x09\x09\x09\x09anIRMethod scope hasNonLocalReturn\x0a\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09self stream nextPutNonLocalReturnHandlingWith: [\x0a\x09\x09\x09\x09\x09\x09\x09super visitIRMethod: anIRMethod ] ]\x0a\x09\x09\x09\x09\x09ifFalse: [ super visitIRMethod: anIRMethod ] ]]\x0a\x09\x09\x09arguments: anIRMethod arguments ]",
+source: "visitIRMethod: anIRMethod\x0a\x0a\x09self stream\x0a\x09\x09nextPutMethodDeclaration: anIRMethod\x0a\x09\x09with: [ self stream\x0a\x09\x09\x09nextPutFunctionWith: [\x0a\x09\x09\x09\x09self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |\x0a\x09\x09\x09\x09\x09each name asVariableName ]).\x0a\x09\x09\x09\x09self stream nextPutContextFor: anIRMethod during: [\x0a\x09\x09\x09\x09\x09anIRMethod internalVariables ifNotEmpty: [ :internalVars |\x0a\x09\x09\x09\x09\x09\x09self stream nextPutVars: \x0a\x09\x09\x09\x09\x09\x09\x09(internalVars asSet collect: [ :each | each variable alias ]) ].\x0a\x09\x09\x09\x09anIRMethod scope hasNonLocalReturn\x0a\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09self stream nextPutNonLocalReturnHandlingWith: [\x0a\x09\x09\x09\x09\x09\x09\x09super visitIRMethod: anIRMethod ] ]\x0a\x09\x09\x09\x09\x09ifFalse: [ super visitIRMethod: anIRMethod ] ]]\x0a\x09\x09\x09arguments: anIRMethod arguments ].\x0a\x09^ self contents",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["nextPutMethodDeclaration:with:", "stream", "nextPutFunctionWith:arguments:", "nextPutVars:", "collect:", "tempDeclarations", "asVariableName", "name", "nextPutContextFor:during:", "ifNotEmpty:", "internalVariables", "asSet", "alias", "variable", "ifTrue:ifFalse:", "hasNonLocalReturn", "scope", "nextPutNonLocalReturnHandlingWith:", "visitIRMethod:", "arguments"]
+messageSends: ["nextPutMethodDeclaration:with:", "stream", "nextPutFunctionWith:arguments:", "nextPutVars:", "collect:", "tempDeclarations", "asVariableName", "name", "nextPutContextFor:during:", "ifNotEmpty:", "internalVariables", "asSet", "alias", "variable", "ifTrue:ifFalse:", "hasNonLocalReturn", "scope", "nextPutNonLocalReturnHandlingWith:", "visitIRMethod:", "arguments", "contents"]
 }),
 $globals.IRJSTranslator);
 

+ 2 - 1
src/Compiler-IR.st

@@ -935,7 +935,8 @@ visitIRMethod: anIRMethod
 						self stream nextPutNonLocalReturnHandlingWith: [
 							super visitIRMethod: anIRMethod ] ]
 					ifFalse: [ super visitIRMethod: anIRMethod ] ]]
-			arguments: anIRMethod arguments ]
+			arguments: anIRMethod arguments ].
+	^ self contents
 !
 
 visitIRNonLocalReturn: anIRNonLocalReturn

+ 30 - 40
src/Compiler-Inlining.js

@@ -2071,46 +2071,6 @@ $core.addClass('InliningCodeGenerator', $globals.CodeGenerator, [], 'Compiler-In
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.InliningCodeGenerator.comment="I am a specialized code generator that uses inlining to produce more optimized JavaScript output";
 //>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "compileNode:",
-protocol: 'compiling',
-fn: function (aNode){
-var self=this;
-var ir,stream;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1;
-$recv(self._semanticAnalyzer())._visit_(aNode);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["visit:"]=1;
-//>>excludeEnd("ctx");
-ir=$recv(self._translator())._visit_(aNode);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["visit:"]=2;
-//>>excludeEnd("ctx");
-$recv(self._inliner())._visit_(ir);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["visit:"]=3;
-//>>excludeEnd("ctx");
-$1=self._irTranslator();
-$recv($1)._currentClass_(self._currentClass());
-$recv($1)._visit_(ir);
-return $recv($1)._contents();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"compileNode:",{aNode:aNode,ir:ir,stream:stream},$globals.InliningCodeGenerator)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aNode"],
-source: "compileNode: aNode\x0a\x09| ir stream |\x0a\x0a\x09self semanticAnalyzer visit: aNode.\x0a\x09ir := self translator visit: aNode.\x0a\x09self inliner visit: ir.\x0a\x0a\x09^ self irTranslator\x0a\x09\x09currentClass: self currentClass;\x0a\x09\x09visit: ir;\x0a\x09\x09contents",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["visit:", "semanticAnalyzer", "translator", "inliner", "currentClass:", "irTranslator", "currentClass", "contents"]
-}),
-$globals.InliningCodeGenerator);
-
 $core.addMethod(
 $core.method({
 selector: "inliner",
@@ -2175,6 +2135,36 @@ messageSends: []
 }),
 $globals.InliningCodeGenerator);
 
+$core.addMethod(
+$core.method({
+selector: "transformers",
+protocol: 'compiling',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$3,$5,$4;
+$1=self._semanticAnalyzer();
+$2=self._translator();
+$3=self._inliner();
+$5=self._irTranslator();
+$recv($5)._currentClass_(self._currentClass());
+$4=$recv($5)._yourself();
+return [$1,$2,$3,$4];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"transformers",{},$globals.InliningCodeGenerator)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "transformers\x0a\x09^ {\x0a\x09\x09self semanticAnalyzer.\x0a\x09\x09self translator.\x0a\x09\x09self inliner.\x0a\x09\x09self irTranslator currentClass: self currentClass; yourself\x0a\x09}",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["semanticAnalyzer", "translator", "inliner", "currentClass:", "irTranslator", "currentClass", "yourself"]
+}),
+$globals.InliningCodeGenerator);
+
 
 
 $core.addClass('InliningError', $globals.SemanticError, [], 'Compiler-Inlining');

+ 9 - 13
src/Compiler-Inlining.st

@@ -544,19 +544,6 @@ I am a specialized code generator that uses inlining to produce more optimized J
 
 !InliningCodeGenerator methodsFor: 'compiling'!
 
-compileNode: aNode
-	| ir stream |
-
-	self semanticAnalyzer visit: aNode.
-	ir := self translator visit: aNode.
-	self inliner visit: ir.
-
-	^ self irTranslator
-		currentClass: self currentClass;
-		visit: ir;
-		contents
-!
-
 inliner
 	^ IRInliner new
 !
@@ -567,6 +554,15 @@ irTranslator
 
 semanticAnalyzerClass
 	^ InliningSemanticAnalyzer
+!
+
+transformers
+	^ {
+		self semanticAnalyzer.
+		self translator.
+		self inliner.
+		self irTranslator currentClass: self currentClass; yourself
+	}
 ! !
 
 SemanticError subclass: #InliningError

+ 2 - 2
src/Compiler-Semantic.js

@@ -2316,14 +2316,14 @@ $ctx1.supercall = false;
 $recv(aNode)._classReferences_(self._classReferences());
 $recv(aNode)._sendIndexes_(self._messageSends());
 self._popScope();
-return self;
+return aNode;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"visitMethodNode:",{aNode:aNode},$globals.SemanticAnalyzer)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitMethodNode: aNode\x0a\x09self pushScope: self newMethodScope.\x0a\x09aNode scope: currentScope.\x0a\x09currentScope node: aNode.\x0a\x0a\x09self theClass allInstanceVariableNames do: [ :each |\x0a\x09\x09currentScope addIVar: each ].\x0a\x09aNode arguments do: [ :each |\x0a\x09\x09self validateVariableScope: each.\x0a\x09\x09currentScope addArg: each ].\x0a\x0a\x09super visitMethodNode: aNode.\x0a\x0a\x09aNode\x0a\x09\x09classReferences: self classReferences;\x0a\x09\x09sendIndexes: self messageSends.\x0a\x09self popScope",
+source: "visitMethodNode: aNode\x0a\x09self pushScope: self newMethodScope.\x0a\x09aNode scope: currentScope.\x0a\x09currentScope node: aNode.\x0a\x0a\x09self theClass allInstanceVariableNames do: [ :each |\x0a\x09\x09currentScope addIVar: each ].\x0a\x09aNode arguments do: [ :each |\x0a\x09\x09self validateVariableScope: each.\x0a\x09\x09currentScope addArg: each ].\x0a\x0a\x09super visitMethodNode: aNode.\x0a\x0a\x09aNode\x0a\x09\x09classReferences: self classReferences;\x0a\x09\x09sendIndexes: self messageSends.\x0a\x09self popScope.\x0a\x09^ aNode",
 referencedClasses: [],
 //>>excludeEnd("ide");
 messageSends: ["pushScope:", "newMethodScope", "scope:", "node:", "do:", "allInstanceVariableNames", "theClass", "addIVar:", "arguments", "validateVariableScope:", "addArg:", "visitMethodNode:", "classReferences:", "classReferences", "sendIndexes:", "messageSends", "popScope"]

+ 2 - 1
src/Compiler-Semantic.st

@@ -570,7 +570,8 @@ visitMethodNode: aNode
 	aNode
 		classReferences: self classReferences;
 		sendIndexes: self messageSends.
-	self popScope
+	self popScope.
+	^ aNode
 !
 
 visitReturnNode: aNode