KoheAsano / franca

Automatically exported from code.google.com/p/franca
0 stars 0 forks source link

Support Discriminated Unions in Franca #15

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I propose to introduce Discriminated Unions, as defined in the XDR: External 
Data Representation Standard, in Franca.
This serves two main purposes:
- This allows the elements of the union to be of the same type.
It is not practical if the elements are not allowed to be of the same type. 
This may be needed: e.g. if the elements can be a start time or a stop time, 
the type would be a 'date' in both cases. This is also difficult to avoid if 
types are imported and/or inheritance is used.
- Makes it possible to use a 'switch' in the code, instead of using 
'instanceof'.

See http://tools.ietf.org/html/rfc4506 for the XDR: External Data 
Representation Standard

Original issue reported on code.google.com by peter.go...@gmail.com on 20 Mar 2013 at 10:31

GoogleCodeExporter commented 9 years ago
Set type to RFC (request-for-comment). This is a language extension and 
requires a broader analysis. A workflow for handling this kind of issue will be 
published until mid of April latest.

Original comment by klaus.birken@gmail.com on 20 Mar 2013 at 4:49

GoogleCodeExporter commented 9 years ago
Hello, I'm one of the core developers working on a C++ generator for GENIVI 
based on franca. We're still struggling to understand the practical reasons 
behind the discriminated unions. Since they aren't used in any popular 
programming language, it's also kind of hard to get a clean implementation 
without compromising some aspects.

Could you please elaborate more on your use case? Are you or why are you using 
the XDR standard? What programming language are you using and how does the 
discriminated unions interface look like? Thanks!

Original comment by aleksand...@gmail.com on 21 Mar 2013 at 1:47

GoogleCodeExporter commented 9 years ago
Assume I have the following types in Franca:

    struct PointLocation {
        UInt32 attrib1
    }

    struct AreaLocation {
        UInt32 attrib1
    }

    union Location {
        AreaLocation area
        PointLocation point
    }

The D-Bus signatures for AreaLocation and PointLocation are the same, so on the 
receiving side I don't know whether I receive an area or a point.
The current solution is: make sure that the elements of a union have a 
different signature. But this is not nice. I may be importing AreaLocation from 
someone else and don't even want to know the signature.
With a discriminated union this would turn into:

    enumeration LocationType {
      POINT = "1"
      AREA = "2"
    }

    struct PointLocation {
        UInt32 attrib1
    }

    struct AreaLocation {
        UInt32 attrib1
    }

    union Location switch (LocationType locationType) {
        AreaLocation area
        PointLocation point
    }

On D-Bus this would translate to 'iv' where 'i' is the discriminator 
(locationType), providing information on the content of the variant.
The related C code would look something like:

typedef enum
{
  POINT = 1,
  AREA = 2
} LocationType;

typedef struct
{
  t_int32 attrib1;
} PointLocation;

typedef struct
{
  t_int32 attrib1;
} AreaLocation;

typedef struct
{
  LocationType locationType;
  union
  {
    PointLocation pointLocation;
    AreaLocation areaLocation;
  } data;
} Location;

So it is more or less a pattern to solve a problem.
I'm mainly referring to XDR to show that discriminated unions are not my 
invention. Also XDR is a standard to describe data, the fact that they came up 
with discriminated unions indicates that there's a need for something like this.

The other thing is, that in C++ you don't know what the actual content of a 
union is. If I receive a Location, I don't know whether it is actually a point 
or an area. Therefore I assume it is common practice (I'm no C++ expert) to 
have something like the locationType.

Original comment by peter.go...@gmail.com on 21 Mar 2013 at 4:33

GoogleCodeExporter commented 9 years ago
Franca is an abstract language and it shouldn't be mixed with the underlying 
middleware implementation. If you imagine a layer structure, then Franca is on 
top of the middlewaare. Between them a deployment model might exist, which will 
define some middleware specifics.

On the franca layer we simply have a union of types. Since this is all about 
interprocess communication, the union might be set from one application but 
used within another one. Thus, as you already said, we need to know which type 
is currently set and we cannot simply use the C/C++ union type.

We've already implemented something similar to what you described:
http://git.projects.genivi.org/?p=ipc/common-api-runtime.git;a=blob;f=src/Common
API/SerializableVariant.h

The variant template will take a list of types as parameter. The types are 
indexed and the index of the currently used type is set within the variant. 
There's a template method isType() which could be used to verify the currently 
set type. For our D-Bus middleware we also transfer this index, so that the 
other side will explicitly know which type is being set. Since the franca 
interface versions are negotiated at the beginning of the communication, the 
possible union types are already known, thus the D-Bus variant type isn't 
needed in this case.

So in summary, there is already a similar implementation to the discriminated 
unions that you described. But I think this is a middleware implementation 
detail and not much relevant to the franca language itself.

Original comment by aleksand...@gmail.com on 22 Mar 2013 at 9:31

GoogleCodeExporter commented 9 years ago
Thanks for your feedback.
It makes sense to see this as a deployment issue.
About common-api: I'm not using this, and I'd like to see a D-Bus solution 
(explanation) without a reference to common-api.
With my original 'Location' type above, a parameter of this type is translated 
to the D-Bus type 'v' (using Franca/Generate D-Bus XML file in Eclipse). The 
data on the bus will be: 'u<marshalled UINT32 value>', for both point and area 
location. So the receiving side can't tell whether it's a point or area 
location. If the generated type would be 'iv', where 'i' specifies the type, 
the receiving side could reconstruct the right type.
Or am I missing something?

Original comment by peter.go...@gmail.com on 26 Mar 2013 at 3:09

GoogleCodeExporter commented 9 years ago
Thanks for the constructive discussion. I agree that this feature does not 
require an extension of the Franca IDL. This can be implemented as a 
configuration option for the Franca=>D-Bus transformation.

It has to be decided if this option should be 
- a global flag for the transformation
- a deployment flag per interface
- a deployment flag per struct (fine-grain)

Any opinions?

Original comment by klaus.birken@gmail.com on 18 Apr 2013 at 5:01

GoogleCodeExporter commented 9 years ago

Original comment by klaus.birken@gmail.com on 14 May 2013 at 7:46