civboot / fngi

a readable language that grows from the silicon
The Unlicense
59 stars 3 forks source link

Enum #12

Open vitiral opened 1 year ago

vitiral commented 1 year ago

Enum's are a fairly interesting problem. I want to have true sum types (aka rust enums), not just integer constants (aka C enums).

Handling the type checker provides some complexity, but I think I have a decent path forward

enum MyEnum [ U: U4, I: I2, S: &CStr ]

var e: MyEnum = doSomething()
unwrap e
\ u is a temporary "alias variable" created in a temporary sub-dictionary
\ The "type" (U) must be the _name_ (not type) of a MyEnum variant.
\ 'u' has the same offset as 'e' (note:variant info is at the end)
\ but it's type is U4
case u: U do ( ... do something with u ... )
case i: I do ( ... do something with i, u is not accessible ... )
case s: S do ( ... do something with s ... )
\ if not all variants are used
else ( ... do something without type information ... )

For the tyDb, all branches must return the same type (or be TyDb_done). All variants must be used or have an else

enum types are basically represented the same as struct fields except they have a special field at the end named :variant (global CStr). Note that this is an illegal token. The special field is the only value with an offset, and is the offset of the largest struct WITHOUT padding. Therefore the E below only uses 4 bytes:

struct A [ a1: U2, a2: U1 ]
enum E [ A, b: U2 ]

Reference types are handled appropriately (u would be a reference type) instead.

Above is how you access a TyVar (local/global). To access a value on the stack you use stk: in unwrap

unwrap doSomething()
case stk: U do ( ... U is the type on the stack. Note that the variant was dropped! ... )

I will have to add the TBL instruction to support enum... that will be fun!