stz enums

stz enums
Photo by GRIN / Unsplash

Writing out enumerated values should be as simple as listing them. For instance:

north = 1
east = 2
south = 3
west = 4

The whole point of enums though is to scope them away inside a namespace. To use the enum as a type. The problem with throwing random names out there in to the void is we don't have a syntax for that -except- when we're creating a variable and assigning to it.

To make this look more like an enum we will need the ability to list allocations with commas. So first things first, let's do that.
north = 1, east = 2, south = 3, west = 4

We also need to list these names without assigning anything to them and having the compiler fill in values for us. This is going to require some new syntax. A shame, really, because we were doing so well without adding more to the cognitive load!

May be we can cheat a little though. We already have the following syntaxes:
structure is ( name: string, number-of-arms: int )
tuple is ( string, int )
now we want to add enums which might as well be: ( name, number-of-arms )

This only works so long as neither name or number-of-arms are already variables in this scope. If they are then we're trying to make an array but one of the variables doesn't exist.

The next part of it is assignment. foo = 123 is fine and so is (foo = 123) but ( foo = 123, ) must be an enum. Because of the magic comma once more. We can even specify the type of the enum using our same syntax:( uint | north, east, south, west ).

In that case we've no definition of what the values actually are. Given it's an enumeration now that we can identify as such we can say the compiler will start with 0 if it's an integer or unsigned integer type. We can also have it increment from the previous enumeration option:
( north = 1, east, south, west )

That might be enough for now. We have enums now. That also means we have errors and we can start designing around that.

socket-receive-error = enum: ( int | no-error = 0, again = 11, bad-descriptor, connection-reset, fault, interruption, out-of-band, no-buffer, not-connected, not-a-socket, option-not-supported, timeout )

socket-receive-flag = enum-set: ( int | process-out-of-bounds, peek, waitall )

[ io receive: handle into: buffer length: length flags: flags |
    &io-manager, socket-handle, &array-of: u8, int, socket-receive-flag
    -> socket-receive-error |
  result = os.recv: (handle os-handle, buffer, length, flags)
  if result == -1 then: [ ^os.errno ]
  ^no-error ]

That's a long one but sockets are like that. I'm satisfied that enums are solved for now. There may be more to it. There's often more to everything. If we filled in the values from the C headers then this would be usable.

One thing I'm not quite happy with are the flags. It'd be nice to specify that the parameter is a socket-receive-flag 'combo'. There's quite a few C APIs where you bit-or options together. The result being an integer but it'd be nicer to know it's a enum-set.

So I set the parameter to socket-receive-flag and instead of declaring it an enum: I declared it an enum-set:. We will have to wait and see if this shakes out the way I'd hoped. It is, at least, more explicit than not stating they can be combined.