cab
cab

Reputation: 385

Ada interface casting?

I am trying to model a set of Parsers in Ada based on interface below:

package Parsers is

   type Parser is interface;
   type DataArray is array(Integer range <>) of String(1..100);

   function Parse(Object : access Parser; FilePath : String) return DataArray is abstract;

end Parsers;

The first Parser interface member is a text parser show below:

with Parsers;

package TextParsers is
   type Parser is new Parsers.Parser with null record;

   overriding function Parse(Object : access Parser; FilePath : String) return Parsers.DataArray;
   end TextParsers;                                       

with Parsers;
use Parsers;

package body TextParsers is

   overriding function Parse(Object : access Parser; FilePath : String) return Parsers.DataArray is
      Data : Parsers.DataArray (0..144);
   begin
      -- just stubbed out
      return Data;
   end Parse;
end TextParsers;

And finally, I would like to have a factory method create these Parsers based on the path provided, like detecting if it was a txt file or maybe a csv, etc. Here is the factory code:

with Parsers;
use Parsers;

package ParserFactories is
   function GetParser(Path : String) return Parsers.Parser;
end ParserFactories;


with Parsers, TextParsers;

package body ParserFactories is
   function  GetParser(Path : String) return Parsers.Parser is
      Text : TextParsers.Parser;
      Parse : Parsers.Parser'Class := Text;
   begin
      return Parse;
   end GetParser;
end ParserFactories;

I keep getting a "dynamically tagged expression not allowed" compilier error, and I cannot figure out how I can create these objects that implement the Parser interface and return it out of this function. Is there a way to do this in Ada?

Upvotes: 1

Views: 1031

Answers (2)

Shark8
Shark8

Reputation: 4198

The answer is that you don't return the interface's type, but the type that the object is... or else you can return the interface'class to indicate that you're going to assign it to that abstract-typed variable.

Procedure Testing is

package Interface_Test is
    Type IBob is interface;
    Function Make Return IBob is abstract;
    Function Image( Object : In IBob ) Return String is abstract;

    Generic
        Type Data is (<>);
        Default_Data : In Data;
    Package Container is
        Type Data_Container is NEW IBob with private;
    private
        Type Data_Container is new IBob with record
        Info  : Data:= Default_Data;
        end record;

        Overriding Function Make Return Data_Container;
        Overriding Function Image(Object : In Data_Container) Return String;
    end Container;
end Interface_Test;

package Body Interface_Test is
    Package Body Container is

        Function Make Return Data_Container is
        begin
        Return Result : Data_Container;
        end Make;

        Function Image( Object : Data_Container ) Return String is 
        begin
        return Data'Image( Object.Info );
        end image;

    end Container;
end Interface_Test;


package J is new Interface_Test.Container( Integer, 1 );
use type J.Data_Container;
Test : J.Data_Container:= J.Make;

Use Ada.Text_IO;

Begin
  put_line( Test.Image );
End;

Upvotes: 1

Rommudoh
Rommudoh

Reputation: 1804

You are trying to return a Parsers.Parser type. This is not allowed (and not what you intend to do). Change it to Parsers.Parser'Class instead.

Upvotes: 2

Related Questions