Browse Source

* $NAMESPACES directive

Michael VAN CANNEYT 2 years ago
parent
commit
64feb6a5cd
5 changed files with 113 additions and 21 deletions
  1. 23 0
      compiler/fmodule.pas
  2. 30 20
      compiler/fppu.pas
  3. 10 1
      compiler/globals.pas
  4. 16 0
      compiler/pmodules.pas
  5. 34 0
      compiler/scandir.pas

+ 23 - 0
compiler/fmodule.pas

@@ -174,6 +174,7 @@ interface
         loaded_from   : tmodule;
         _exports      : tlinkedlist;
         dllscannerinputlist : TFPHashList;
+        localnamespacelist,
         resourcefiles,
         linkorderedsymbols : TCmdStrList;
         linkunitofiles,
@@ -241,6 +242,7 @@ interface
         constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
         destructor destroy;override;
         procedure reset;virtual;
+        procedure loadlocalnamespacelist;
         procedure adddependency(callermodule:tmodule);
         procedure flagdependent(callermodule:tmodule);
         procedure addimportedsym(sym:TSymEntry);
@@ -572,6 +574,7 @@ implementation
         localframeworksearchpath:=TSearchPathList.Create;
         used_units:=TLinkedList.Create;
         dependent_units:=TLinkedList.Create;
+        localnamespacelist:=TCmdStrList.Create;
         resourcefiles:=TCmdStrList.Create;
         linkorderedsymbols:=TCmdStrList.Create;
         linkunitofiles:=TLinkContainer.Create;
@@ -946,6 +949,26 @@ implementation
         }
       end;
 
+    procedure tmodule.loadlocalnamespacelist;
+
+    var
+      nsitem : TCmdStrListItem;
+
+    begin
+      // Copying local namespace list
+      if premodule_namespacelist.Count>0 then
+        begin
+        nsitem:=TCmdStrListItem(premodule_namespacelist.First);
+        while assigned(nsItem) do
+          begin
+          localnamespacelist.Concat(nsitem.Str);
+          nsItem:=TCmdStrListItem(nsitem.Next);
+          end;
+        premodule_namespacelist.Clear;
+        end;
+      current_namespacelist:=localnamespacelist;
+    end;
+
 
     procedure tmodule.adddependency(callermodule:tmodule);
       begin

+ 30 - 20
compiler/fppu.pas

@@ -562,10 +562,35 @@ var
              result:=SearchPathList(UnitSearchPath,prefix);
          end;
 
+         function SearchNamespaceList(const prefixes:TCmdStrList):boolean;
+         var
+           nsitem : TCmdStrListItem;
+           res : Boolean;
+         begin
+           res:=false;
+           nsitem:=TCmdStrListItem(prefixes.first);
+           while assigned(nsitem) do
+             begin
+               if not onlysource then
+                 begin
+                   res:=SearchPPUPaths(nsitem.str);
+                   if res then
+                     break;
+                 end;
+               res:=SearchSourcePaths(nsitem.str);
+               if res then
+                 break;
+               nsitem:=TCmdStrListItem(nsitem.next);
+             end;
+           if assigned(nsitem) then
+             nsprefix:=nsitem.str;
+           result:=res;
+         end;
+
+
        var
          fnd : boolean;
          hs : TPathStr;
-         nsitem : TCmdStrListItem;
        begin
          if shortname then
           filename:=FixFileName(Copy(realmodulename^,1,8))
@@ -618,26 +643,11 @@ var
          if not fnd then
            begin
              fnd:=SearchSourcePaths('');
+             // current_namespacelist is set to the current module's namespacelist.
+             if not fnd and assigned(current_namespacelist) and (current_namespacelist.count>0) then
+               fnd:=SearchNameSpaceList(current_namespacelist);
              if not fnd and (namespacelist.count>0) then
-               begin
-                 nsitem:=TCmdStrListItem(namespacelist.first);
-                 while assigned(nsitem) do
-                   begin
-                     if not onlysource then
-                       begin
-                         fnd:=SearchPPUPaths(nsitem.str);
-                         if fnd then
-                           break;
-                       end;
-                     fnd:=SearchSourcePaths(nsitem.str);
-                     if fnd then
-                       break;
-
-                     nsitem:=TCmdStrListItem(nsitem.next);
-                   end;
-                 if assigned(nsitem) then
-                   nsprefix:=nsitem.str;
-               end;
+               fnd:=SearchNameSpaceList(namespacelist);
            end;
          search_unit:=fnd;
       end;

+ 10 - 1
compiler/globals.pas

@@ -316,8 +316,13 @@ interface
        includesearchpath,
        frameworksearchpath  : TSearchPathList;
        packagesearchpath     : TSearchPathList;
+
        { list of default namespaces }
        namespacelist : TCmdStrList;
+       // During scanning/parsing, a module may not yet be available.
+       // Scanner checks first current_namespacelist, then local_namespacelist
+       premodule_namespacelist,                    // always set: used as long as current_namespacelist is not correctly set.
+       current_namespacelist : TCmdStrList;        // Set when parsing module to the current module's namespace.
        { contains tpackageentry entries }
        packagelist : TFPHashList;
        autoloadunits      : string;
@@ -378,6 +383,7 @@ interface
        LinkLibraryAliases : TLinkStrMap;
        LinkLibraryOrder   : TLinkStrMap;
 
+
        init_settings,
        current_settings   : tsettings;
 
@@ -1653,6 +1659,8 @@ implementation
        LinkLibraryOrder.Free;
        packagesearchpath.Free;
        namespacelist.Free;
+       premodule_namespacelist.Free;
+       current_namespacelist:=Nil;
      end;
 
    procedure InitGlobals;
@@ -1694,7 +1702,8 @@ implementation
         frameworksearchpath:=TSearchPathList.Create;
         packagesearchpath:=TSearchPathList.Create;
         namespacelist:=TCmdStrList.Create;
-
+        premodule_namespacelist:=TCmdStrList.Create;
+        current_namespacelist:=Nil;
         { Def file }
         usewindowapi:=false;
         description:='Compiled by FPC '+version_string+' - '+target_cpu_string;

+ 16 - 0
compiler/pmodules.pas

@@ -1018,6 +1018,11 @@ type
          if not(cs_compilesystem in current_settings.moduleswitches) and
             (token=_USES) then
            begin
+             // We do this as late as possible.
+             if Assigned(current_module) then
+               current_module.Loadlocalnamespacelist
+             else
+               current_namespacelist:=Nil;
              loadunits(nil);
              { has it been compiled at a higher level ?}
              if current_module.state=ms_compiled then
@@ -1640,6 +1645,12 @@ type
          { ensure that no packages are picked up from the options }
          packagelist.clear;
 
+         // There should always be a requires, except for the system package. So we load here
+         if Assigned(current_module) then
+           current_module.Loadlocalnamespacelist
+         else
+           current_namespacelist:=Nil;
+
          {Read the packages used by the package we compile.}
          if (token=_ID) and (idtoken=_REQUIRES) then
            begin
@@ -2188,6 +2199,11 @@ type
          { Load the units used by the program we compile. }
          if token=_USES then
            begin
+             // We can do this here: if there is no uses then the namespace directive makes no sense.
+             if Assigned(current_module) then
+               current_module.Loadlocalnamespacelist
+             else
+               current_namespacelist:=Nil;
              loadunits(nil);
              consume_semicolon_after_uses:=true;
            end

+ 34 - 0
compiler/scandir.pas

@@ -1019,6 +1019,39 @@ unit scandir;
       end;
 
 
+    procedure dir_namespaces;
+
+    { add namespaces to the local namespace list }
+      var
+        s : string;
+
+    begin
+      if not current_module.in_global then
+        Message(scan_w_switch_is_global)
+      else
+        begin
+          current_scanner.skipspace;
+          current_scanner.readstring;
+          s:=orgpattern;
+          While (s<>'') do
+            begin
+              // We may not yet have a correct module namespacelist.
+              if assigned(current_namespacelist) then
+                current_namespacelist.Insert(s)
+              else // copied when correct module is activated
+                premodule_namespacelist.Insert(s);
+              s:='';  
+              if c=',' then
+                begin
+                  current_scanner.readchar;
+                  current_scanner.skipspace;
+                  current_scanner.readstring;
+                  s:=orgpattern;
+                end;
+            end;
+        end;
+    end;
+
     procedure dir_namespace;
       var
         s : string;
@@ -2029,6 +2062,7 @@ unit scandir;
         AddDirective('MODE',directive_all, @dir_mode);
         AddDirective('MODESWITCH',directive_all, @dir_modeswitch);
         AddDirective('NAMESPACE',directive_all, @dir_namespace);
+        AddDirective('NAMESPACES',directive_all, @dir_namespaces);
         AddDirective('NODEFINE',directive_all, @dir_nodefine);
         AddDirective('NOTE',directive_all, @dir_note);
         AddDirective('NOTES',directive_all, @dir_notes);