2
0
Эх сурвалжийг харах

pastojs: jsglobalalias: references in init to elements from implementation uses

git-svn-id: trunk@46854 -
Mattias Gaertner 4 жил өмнө
parent
commit
96cb396d56

+ 42 - 23
packages/pastojs/src/fppas2js.pp

@@ -1744,8 +1744,12 @@ type
 
 
   TInterfaceSectionContext = Class(TSectionContext)
   TInterfaceSectionContext = Class(TSectionContext)
   public
   public
+    ImplContext: TSectionContext;
     ImplHeaderStatements: TFPList;
     ImplHeaderStatements: TFPList;
+    ImplSrcElements: TJSSourceElements;
+    ImplHeaderIndex: integer; // index in TJSSourceElements(JSElement).Statements
     destructor Destroy; override;
     destructor Destroy; override;
+    procedure AddImplHeaderStatement(JS: TJSElement);
   end;
   end;
 
 
   { TDotContext - used for converting eopSubIdent }
   { TDotContext - used for converting eopSubIdent }
@@ -1994,7 +1998,7 @@ type
       Full: boolean = false; Ref: TResolvedReference = nil): TJSElement; virtual;
       Full: boolean = false; Ref: TResolvedReference = nil): TJSElement; virtual;
     Function CreateGlobalTypePath(El: TPasType; AContext : TConvertContext): string; virtual;
     Function CreateGlobalTypePath(El: TPasType; AContext : TConvertContext): string; virtual;
     // section
     // section
-    Function CreateImplementationSection(El: TPasModule; AContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement; virtual;
+    Function CreateImplementationSection(El: TPasModule; IntfContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement; virtual;
     Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
     Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
     Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
@@ -2393,6 +2397,29 @@ begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
+procedure TInterfaceSectionContext.AddImplHeaderStatement(JS: TJSElement);
+begin
+  if JS=nil then exit;
+  if ImplContext<>nil then
+    begin
+    // unit impl is currently created
+    ImplContext.AddHeaderStatement(JS);
+    end
+  else if ImplSrcElements<>nil then
+    begin
+    // unit impl finished -> e.g. during the initialization section
+    ImplSrcElements.Statements.InsertNode(ImplHeaderIndex).Node:=JS;
+    inc(ImplHeaderIndex);
+    end
+  else
+    begin
+    // unit impl not yet created
+    if ImplHeaderStatements=nil then
+      ImplHeaderStatements:=TFPList.Create;
+    ImplHeaderStatements.Add(JS);
+    end;
+end;
+
 { TPas2JSResolverHub }
 { TPas2JSResolverHub }
 
 
 function TPas2JSResolverHub.GetJSDelaySpecializes(Index: integer
 function TPas2JSResolverHub.GetJSDelaySpecializes(Index: integer
@@ -16771,7 +16798,7 @@ begin
 end;
 end;
 
 
 function TPasToJSConverter.CreateImplementationSection(El: TPasModule;
 function TPasToJSConverter.CreateImplementationSection(El: TPasModule;
-  AContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement;
+  IntfContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement;
 var
 var
   Src: TJSSourceElements;
   Src: TJSSourceElements;
   ImplContext: TSectionContext;
   ImplContext: TSectionContext;
@@ -16784,33 +16811,37 @@ begin
   // create function(){}
   // create function(){}
   FunDecl:=CreateFunctionSt(El.ImplementationSection,true,true);
   FunDecl:=CreateFunctionSt(El.ImplementationSection,true,true);
   Src:=TJSSourceElements(FunDecl.AFunction.Body.A);
   Src:=TJSSourceElements(FunDecl.AFunction.Body.A);
+  IntfContext.ImplSrcElements:=Src;
 
 
   // create section context (a function)
   // create section context (a function)
-  ImplContext:=TSectionContext.Create(El.ImplementationSection,Src,AContext);
+  ImplContext:=TSectionContext.Create(El.ImplementationSection,Src,IntfContext);
   try
   try
+    IntfContext.ImplContext:=ImplContext;
     // ToDo: IntfContext.ThisPas:=El;
     // ToDo: IntfContext.ThisPas:=El;
     // ToDo: IntfContext.ThisKind:=cctkGlobal;
     // ToDo: IntfContext.ThisKind:=cctkGlobal;
 
 
     // add pending impl header statements
     // add pending impl header statements
-    if AContext.ImplHeaderStatements<>nil then
+    if IntfContext.ImplHeaderStatements<>nil then
       begin
       begin
-      for i:=0 to AContext.ImplHeaderStatements.Count-1 do
+      for i:=0 to IntfContext.ImplHeaderStatements.Count-1 do
         begin
         begin
-        JS:=TJSElement(AContext.ImplHeaderStatements[i]);
+        JS:=TJSElement(IntfContext.ImplHeaderStatements[i]);
         ImplContext.AddHeaderStatement(JS);
         ImplContext.AddHeaderStatement(JS);
-        AContext.ImplHeaderStatements[i]:=nil;
+        IntfContext.ImplHeaderStatements[i]:=nil;
         end;
         end;
-      FreeAndNil(AContext.ImplHeaderStatements);
+      FreeAndNil(IntfContext.ImplHeaderStatements);
       end;
       end;
 
 
     // create implementation declarations
     // create implementation declarations
     ImplDecl:=ConvertDeclarations(El.ImplementationSection,ImplContext);
     ImplDecl:=ConvertDeclarations(El.ImplementationSection,ImplContext);
     if ImplDecl<>nil then
     if ImplDecl<>nil then
       RaiseInconsistency(20170910175032,El); // elements should have been added directly
       RaiseInconsistency(20170910175032,El); // elements should have been added directly
+    IntfContext.ImplHeaderIndex:=ImplContext.HeaderIndex;
     if Src.Statements.Count=0 then
     if Src.Statements.Count=0 then
       exit; // no implementation
       exit; // no implementation
     Result:=FunDecl;
     Result:=FunDecl;
   finally
   finally
+    IntfContext.ImplContext:=nil;
     ImplContext.Free;
     ImplContext.Free;
     if Result=nil then
     if Result=nil then
       FunDecl.Free;
       FunDecl.Free;
@@ -16849,25 +16880,13 @@ end;
 procedure TPasToJSConverter.AddImplHeaderStatement(JS: TJSElement;
 procedure TPasToJSConverter.AddImplHeaderStatement(JS: TJSElement;
   PosEl: TPasElement; aContext: TConvertContext);
   PosEl: TPasElement; aContext: TConvertContext);
 var
 var
-  SectionCtx: TSectionContext;
   IntfSec: TInterfaceSectionContext;
   IntfSec: TInterfaceSectionContext;
 begin
 begin
   if JS=nil then exit;
   if JS=nil then exit;
-  SectionCtx:=TSectionContext(aContext.GetContextOfType(TSectionContext));
-  if SectionCtx=nil then
+  IntfSec:=TInterfaceSectionContext(aContext.GetContextOfType(TInterfaceSectionContext));
+  if IntfSec=nil then
     RaiseNotSupported(PosEl,aContext,20200606142555);
     RaiseNotSupported(PosEl,aContext,20200606142555);
-  if SectionCtx.PasElement is TImplementationSection then
-    SectionCtx.AddHeaderStatement(JS)
-  else if SectionCtx is TInterfaceSectionContext then
-    begin
-    // add pending impl header statement
-    IntfSec:=TInterfaceSectionContext(SectionCtx);
-    if IntfSec.ImplHeaderStatements=nil then
-      IntfSec.ImplHeaderStatements:=TFPList.Create;
-    IntfSec.ImplHeaderStatements.Add(JS);
-    end
-  else
-    RaiseNotSupported(PosEl,aContext,20200911165632);
+  IntfSec.AddImplHeaderStatement(JS);
 end;
 end;
 
 
 procedure TPasToJSConverter.AddDelayedInits(El: TPasProgram;
 procedure TPasToJSConverter.AddDelayedInits(El: TPasProgram;

+ 6 - 0
packages/pastojs/tests/tcoptimizations.pas

@@ -303,6 +303,8 @@ begin
     '  end;',
     '  end;',
     '  TBear = class',
     '  TBear = class',
     '  end;',
     '  end;',
+    '  TFrog = class',
+    '  end;',
     'var Ant: TAnt;',
     'var Ant: TAnt;',
     '']),
     '']),
   LinesToStr([
   LinesToStr([
@@ -347,6 +349,7 @@ begin
   '  Ant:=TAnt.Create;', // init to impl-uses
   '  Ant:=TAnt.Create;', // init to impl-uses
   '  Bird:=TBird.Create;', // init to intf-uses
   '  Bird:=TBird.Create;', // init to intf-uses
   '  Eagle:=TEagle.Create;', // init to intf-JS
   '  Eagle:=TEagle.Create;', // init to intf-JS
+  '  TFrog.Create;', // only in init to impl-uses
   '  Eagle.Fly;',
   '  Eagle.Fly;',
   '  RedAnt.Run;',
   '  RedAnt.Run;',
   '']);
   '']);
@@ -359,6 +362,7 @@ begin
     'var $lm1 = null;',
     'var $lm1 = null;',
     'var $lt1 = null;',
     'var $lt1 = null;',
     'var $lt2 = null;',
     'var $lt2 = null;',
+    'var $lt3 = null;',
     'rtl.createClass($mod, "TEagle", $lt, function () {',
     'rtl.createClass($mod, "TEagle", $lt, function () {',
     '  this.Fly = function () {',
     '  this.Fly = function () {',
     '    $impl.TRedAnt.$create("Create");',
     '    $impl.TRedAnt.$create("Create");',
@@ -373,6 +377,7 @@ begin
     '$impl.Ant = $lt1.$create("Create");',
     '$impl.Ant = $lt1.$create("Create");',
     '$impl.Bird = $lt.$create("Create");',
     '$impl.Bird = $lt.$create("Create");',
     '$impl.Eagle = $mod.TEagle.$create("Create");',
     '$impl.Eagle = $mod.TEagle.$create("Create");',
+    '$lt3.$create("Create");',
     '$impl.Eagle.Fly();',
     '$impl.Eagle.Fly();',
     '$impl.RedAnt.Run();',
     '$impl.RedAnt.Run();',
     '']),
     '']),
@@ -380,6 +385,7 @@ begin
     '$lm1 = pas.UnitB;',
     '$lm1 = pas.UnitB;',
     '$lt1 = $lm1.TAnt;',
     '$lt1 = $lm1.TAnt;',
     '$lt2 = $lm1.TBear;',
     '$lt2 = $lm1.TBear;',
+    '$lt3 = $lm1.TFrog;',
     'rtl.createClass($impl, "TRedAnt", $lt1, function () {',
     'rtl.createClass($impl, "TRedAnt", $lt1, function () {',
     '  this.Run = function () {',
     '  this.Run = function () {',
     '    $impl.TRedAnt.$create("Create");',
     '    $impl.TRedAnt.$create("Create");',