-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proper support for extending enums #818
Comments
If the merged enum functionality was implemented, I think it would be better to represent currency codes like this:
|
Fully agree that in the case of enums, On this basis, I wonder if it's wise to use the same |
It's a good point. Especially when extending multiple enumerations, I think the keyword
|
I think that reads better than
Also do we intent to make the new super type immutable? So no adding enum values to |
I prefer the Another option is to introduce pure e.g. For enums
e.g. For types
This looks a little similar to the |
If we implemented the above simple This existing code would become invalid:
It would have to be replaced by this:
|
I don't really follow what difference you see between "pure union" types and the choice types we already have. Assuming we do the last bits necessary on choice types (#797), perhaps we don't need enum extensions at all? E.g.,
This would tackle the first two use cases (comparing currency codes of different underlying enums and concatenating multiple enums together). The third point (checking which enum a value belongs to) also becomes possible using the switch expression to switch over
However, what becomes more tedious is switching over enum values, since
Perhaps it's not too bad. What do you think? |
Proposal: use the existing feature of Some of these changes will be backwards incompatible. Therefore the following steps are split in two sections:
1. Deprecate support for extending enums.Modellers should choice types instead. E.g., the following would be deprecated:
It should be modelled using a choice type instead:
2. Implement a proper subtype relation for choice types. #797Modelling
3. Add support to directly switch on enum values of a choice type. -- OptionalGiven a
We could enhance the switch operator to allow direct enum value cases, e.g.,
The advantage is that it would be a little more concise, and the 4. Remove support for the deprecated enum extension syntax and remove "handling choices as data types". -- This is backwards incompatible.This would force modellers to use choice types instead. |
A summary of the proposal and its impact on the models (CDM, DRR, ISDA Foundations) can be found in this deck: For a full discussion of the problems and different proposals which were considered, see the comments above. The estimated amount of DSL work sums up to 5 days. |
Problem description
Rune has rudimentary support for extending enums, e.g.,
Semantically, this will "copy over" all enum values from
ISOCurrencyCodeEnum
intoCurrencyCodeEnum
, as if extending the list of ISO currency codes with other enumerated values. However, when used in expressions there are three use cases which are currently unsupported:Comparing a value of
ISOCurrencyCodeEnum
with a value ofCurrencyCodeEnum
. E.g.,isoCurrencyCode = currencyCode
. Since Rune does not define any subtype relation between these two enum types, this results in a model validation error saying that the two types are not comparable. However, they do share enum values, so it should be possible to compare them.Concatenating multiple enumerations together. Right now, one can only extend a list of enumerated values, but one cannot concatenate multiple lists into one list of enumerated values. See Support for merged enum #525 for an extended use case and discussion.
Checking if a value of
CurrencyCodeEnum
belongs toISOCurrencyCodeEnum
. Given a currency codeCurrencyCodeEnum -> GBP
it should be possible to check that this is indeed anISOCurrencyCodeEnum
, and it should be possible to convert it. (see Support for merged enum #525 (comment))These three use cases can not only be seen from the perspective of a modeller, but also from the perspective of a consumer of the generated code. For example, if we add support for comparing extended enumerations, then a Java implementer should be able to perform that same operation in a convenient way.
EDIT: the initial proposal below has been replaced by a different approach after discussion. To see the current proposal, see #818 (comment).
Proposal
I split up a proposed solution in three parts for different stakeholders: modellers (changes to the Rune syntax and type system), code generator implementers (how language changes should be handled in Java and other code generators), and Java code consumers (how consumers of the generated code can achieve the same in Java).
Changes for modellers
Changes to the subtype relation
To make extended enumerations comparable, there should be a subtype relation between the two types. However, whereas a type extension is a subtype of its parent, I argue that for enums it is the other way around, i.e., an enum extension is a supertype of its parent.
It is often convenient to consider the subtype relation as the "is a" relation. A
Cat
is anAnimal
becausetype Cat extends Animal
. In this case, we considerCat
a subtype ofAnimal
. However, consider again the example of currency codes:In this case, the statement that "a currency code is an ISO currency code" does not hold! For example,
CNH
is a currency code, but not an ISO currency code. The converse does hold: each ISO currency code is a currency code, so we can considerISOCurrencyCodeEnum
a subtype ofCurrencyCodeEnum
.I propose to enhance the type system of Rune with this subtype relation. Consequences:
ISOCurrencyCodeEnum
can be compared with aCurrencyCodeEnum
. (this addresses our first use case)ISOCurrencyCodeEnum
can be assigned to an attribute of typeCurrencyCodeEnum
.ISOCurrencyCodeEnum
can be passed to a function which expects aCurrencyCodeEnum
.Concatenating multiple enumerations into one
Taking the example from #525, a rate index can be either a floating rate index or an inflation rate index. Allowing enumerations to extend multiple others would handle this use case:
This would be a relatively easy change to the Rune language, which does not influence the implementation of code generators in any way. Note that, considering the proposed subtype relation,
RateIndexEnum
would be the supertype of bothFloatingRateIndexEnum
andInflationRateIndexEnum
.Checking if the value of an enum extension is a value of its parent enum
For the use case of converting one into the other, I propose to enhance the
to-enum
operation, so it also accepts an expression of an enum type as its left operand:This will result in the corresponding
ISOCurrencyCodeEnum
value, orempty
if no corresponding value exists. Combined with theexists
operation, it would allow a modeller to check whether a currency code is an ISO currency code:Changes for code generator implementers
The changes to the subtype relation imply type coercions in the generated Java code. When an expression of type
ISOCurrencyCodeEnum
is used in a place where a value of typeCurrencyCodeEnum
is expected, it will have to be coerced to aCurrencyCodeEnum
. Similar changes will need to be made for the Python code generator.Allowing to extend multiple enumerations does not influence the code generation for enumerations: code generators can still use the utility method
RosettaExtensions#getAllEnumValues
to iterate through all enumerated values, including those of all parent enumerations.The semantics of the
to-enum
operation will need to change appropriately if its left operand is an enum.Utilities for Java code consumers
Ideally, consumers of the generated Java code should be able to compare extended enums with a similar ease, as well as easily convert from/to extended enums. I propose to generate two methods for each enum extensions to perform these conversions:
Also notice the
extends
attribute inside the@RosettaEnum
annotation.As an example, consumers can use this to compare a value of
CurrencyCodeEnum
withISOCurrencyCodeEnum
:Everything together, I think this proposal addresses all use cases, and will significantly improve the way enumerations can be used in the CDM. Feedback is welcome!
Related:
The text was updated successfully, but these errors were encountered: