BTW, I don't think you need to create the vtable on the fly in that
case.  The Pkg.Print function will need a static link, but the vtable
doesn't need to encode that.  I just checked our Ada compiler.  We
stopped development on this compiler after Ada 95, but the only change I
had to make to your example to make it Ada 95-friendly, was the call to
Print: Pkg.Print(Object).  (They were avoiding the Object.Function
syntax in Ada 95, but I assume they relented and added some syntactic
sugar in Ada 2005 or 2012.)  Our compiler does indeed generate a static
vtable.



Interesting: this indeed works if Main.Pkg.Print calls take a static
link, but how can the caller find the static link to pass in the
general case? This is obvious in my previous example (the call happens
in the same scope that owns the static link), but thanks to type
derivation, calls to Main.Pkg.Print can actually appear in other
places. For instance:

package Base is
   type T is abstract tagged null record;
   procedure Print (Self : T) is abstract;
   procedure Call_Print (Self : T'Class);
   function Get_Msg return String;
end Base;

package body Base is
   procedure Call_Print (Self : T'Class) is
   begin
      Print (Self);
   end Call_Print;

   function Get_Msg return String is
   begin
      return "Hello world";
   end Get_Msg;
end Base;

with Ada.Text_IO; use Ada.Text_IO;
with Base;

procedure Main is
   Msg : constant String := Base.Get_Msg;

   package Pkg is
      type T is new Base.T with null record;
      overriding procedure Print (Self : T);
   end Pkg;

   package body Pkg is
      overriding procedure Print (Self : T) is
      begin
         Put_Line (Msg);
      end Print;
   end Pkg;

   Object : Pkg.T;
begin
   Base.Call_Print (Object);
end Main;

Since Main.Pkg.Print overrides a library-level primitive, it can’t
take a static link so the only way for it to have access to the
Main.Msg local is through Self. I guess a compiler could decide to put
the static link in each Main.Pkg.T object rather than in their vtable
(and thus have a static vtable), but as far as I can tell, GNAT stores
the static link in the vtable instead, so the vtable cannot be static.



That looks like the more compelling reason, then.

I tried this in our Ada 95 compiler, and it's rejected because of accessibility 
rules (13.9.1(3)).  And it looks like a legit rejection.  Those usually are 
designed to avoid dangling references of access types, but they used the same 
concept for type extensions (derived tagged types).  I don't know if the 
rationale was to avoid static link issues specifically, or if that was just a 
happy side effect.  But evidently they loosened the rules in a later language 
revision.

BTW, I sure hope objects of Main.Pkg.T cannot escape the invocation of Main!  
If so, it seems like you're moving into lambda closure territory.

Todd

-- 
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss

Reply via email to