On 09/23/2015 02:19 PM, Rowan Collins wrote:
The internal implementation can never be quite as simple as an IS_LONG
zval if we want to provide anything at all beyond a C-style enum. I for
one do not want Days::MONDAY === Months::JANUARY to return true, and nor
should typeof(Days::MONDAY) return "long"; this requires at the very
least a struct with type name (enum "class") and value.
Right, if we think of the implementation as a class with constant
properties, then the Days enum would hold an array/hash of associative
zvals, the zvals structure should include a pointer to a
zend_enum_struct, this zend_enum_struct may hold a pointer to the parent
zend_class_entry/zend_enum_entry, a pointer to its name as stored on the
zend_class_entry/zend_enum_entry properties table, and the
ordinal/numerical value. So:
function something(Days $day);
something(Days::Monday);
would be a matter of comparing the zend_class_entry/zend_enum_entry
pointer referenced on Monday with that of the Days enum.
Again comparing Days::MONDAY === Months::JANUARY should be fast if we
only compare the pointer of the zend_enum_entry.
Memory efficiency is only trivially different, since all possible
instances exist in memory only once, so each zval pointing at
Days::MONDAY would just be a single pointer to the single instance of
that structure. Initial creation of the enum instances would be slower,
but again only needs to happen once when the enum is declared, so is
unlikely to be a major concern.
Initializing a zend_enum_struct that only holds a pointer to parent
enum, pointer to name, and ordinal value would be faster and require
less memory than initializing a new class for each enum value. It is
true that this only happens once but every bit counts for better
performance. After all php model for every request is Execute/Die,
Execute/Die... it doesn't keeps everything initialized and ready for use.
- Getting the name of a class constant based on its definition (e.g. to
display an Exception's code in human-readable form) requires extremely
inefficient use of reflection. An int-based enum implementation would
have to do something similar, an object-based one could cache the
information in the instance.
As I said before, if we store a pointer to the property name of the
zend_class_entry/zend_enum_entry directly on the zend_enum_struct we can
retrieve its name rapidly without going into the
zend_class_entry/zend_enum_entry and doing a properties lookup.
- Absolutely any other additional behaviour or fields would be either
impossible with an int-based representation, or require exactly the same
lookups as an object-based implementation would provide anyway.
Any other fancy stuff like Days::Monday->Something() would be in my
opinion over engineering the typical use of enumerations.
Looking at Levi's PoC branch, the actual approach taken is a hybrid
anyway: the _zend_enum struct directly holds the name and an "ordinal"
z_long directly, and only access the object representation if these two
pieces of information are not sufficient.
Nice that theres already work on some implementation :), I have missed
this feature so much on PHP.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php