C2 forum

General Category => Ideas => Topic started by: lerno on October 29, 2018, 01:13:13 AM

Title: Enum improvements
Post by: lerno on October 29, 2018, 01:13:13 AM
1. Allow an automated conversion of enum value => char*

90% of my X Macros are making a mapping of enums to strings for debugging purposes. The easiest would be to make this like a struct function.

TheEnum.to_string(my_enum_value)

Also, consider making enum_max / enum_min the same:

TheEnum.max_val

TheEnum.min_val

2. Allow associated values with enums.

This is a bigger feature. An example:

Code: [Select]
type enum State [char* name, i8 bit] i32  {
   START("begin!", 0x01) = 0,
   END("end it!", 0x10)
}

State.bit(State.START) // returns 1
State.bit(State.END) // returns 16
State.name(State.START) // returns "begin!"

The associated values simply generate these new functions which are switch cases.

3. Store a list of all enum values.

This relies on fixed arrays to be useful.

Code: [Select]
// Following the example above:
State.all // returns i32[] = { 0, 1 }

Title: Re: Enum improvements
Post by: bas on November 08, 2018, 10:25:53 AM

Thinking this through, we could also use the same method for sizeof(). So MyType.sizeof() instead of sizeof(MyType). Although it might be harder to replace sizeof(Type*). Maybe use Type.ptrsize() ?
And replace elemsof(array) with array.elemsof(). This would require changing the analyser to understand that every Type or variable can have some 'members'. The advantage would remove so global
keywords and maybe make the code more readable:

Code: [Select]
for (u32 i = enum_min(State); i <= enum_max(State); i++) {}
// vs
for (u32 i = State.min; i <= State.max; i++) {}
Title: Re: Enum improvements
Post by: lerno on November 08, 2018, 01:27:52 PM
.min / .max raises a larger question:

Should there be struct "constants"?

So
Code: [Select]
type Foo struct {
  ...
}

const Foo.pi = 3.0;

...

func f64 Foo.pie_c(f64 r) { return Foo.pi * r * 2; }

If so, then enums simply emit const TheEnum.min = ...; const TheEnum.max = ...;

Regarding the enum values... it's extremely common to use X macros to actually do that anyway - to generate the switch automatically with whatever you want. For example you might define:

Code: [Select]
#define types \
  X(i8, 8, true) \
  X(u8, 8, false) \
  X(i16, 16, true) \
  X(u16, 16, false) \
/* ... etc */


bool isSigned(type t) {
  switch (t) {
#define X(a, b, c) case a: return c;
    types;
#undef X
  }
   

This occurs a lot when writing protocols or parsers, but also when describing simple state machines. Anytime you have enums really.

Associated values is the simplest way I know to express this (and it's a fairly small addition that has extremely powerful effects, consider

Code: [Select]
type enum State [char*(int) action] i32  {
   START(startFunction) = 0,
   END(endFunction)
}

state.action(10); // Calls startFunction(10)

It's not really important HOW it is implemented, just that it is there. The downside of the X macro solution in C is that it's very messy for IDEs to parse and it's also hard to read the code to know what happens (just look at Clang!)
Title: Re: Enum improvements
Post by: bas on November 12, 2018, 10:04:46 AM
I can see why developers would want struct constants as a way to 'scope' a constant and connect
it to a struct. But I think modules already give us some grouping/scoping for this and adding struct
constants just adds complexity. It is currently already possible to indeed add a struct function that
is compile time constant, so that would already allow some scoping/grouping..
Title: Re: Enum improvements
Post by: lerno on November 13, 2018, 08:46:26 PM
It's more of a practical question. If there are struct constants, then we can emit those additional ones during enum generation. It feels like there are less "special cases" if it's like that. I don't think people will add lots of enum constants...