-
-
Notifications
You must be signed in to change notification settings - Fork 9
Unions
IsaacShelton edited this page Mar 21, 2022
·
2 revisions
Unions allow for multiple data types to share the same piece of memory
Unions are declared by using the union
keyword, an identifier, and a field list
union IntOrFloat32 (i int, f float)
import basics
struct CatInfo (furriness int)
struct DogInfo (is_energetic bool)
enum AnimalKind (CAT, DOG)
union AnimalInfo (cat CatInfo, dog DogInfo)
struct Animal (kind AnimalKind, info AnimalInfo)
func main {
animal Animal
animal.kind = AnimalKind::DOG
animal.info.dog.is_energetic = true
print(animal)
animal.kind = AnimalKind::CAT
animal.info.cat.furriness = 10
print(animal)
}
func toString(animal Animal) String {
exhaustive switch animal.kind {
case AnimalKind::CAT, return "Cat, " + toString(animal.info.cat.furriness)
case AnimalKind::DOG, return "Dog, " + toString(animal.info.dog.is_energetic)
}
return "Invalid Animal"
}
The __defer__
and __pass__
management procedures are not automatically generated for union types, since it cannot be known which fields require operations.
import basics
union StringOrInt (s String, i int)
func main {
soi StringOrInt
soi.s = "Hello".clone()
// DANGEROUS: soi.s never freed, since StringOrInt.__defer__() doesn't exist
}
Because of this, __defer__
must be manually called on fields when applicable.
import basics
union StringOrInt (s String, i int)
func main {
soi StringOrInt
soi.s = "Hello".clone()
// OK: soi.s is always assumed to be valid, and will be freed
// This is only required since 'String' has a '__defer__' method
// that is used to clean up
soi.s.__defer__()
}
When using a different type within a union, the same process applies. Otherwise, dynamic memory references inside the previously used type could be overwritten and then be leaked or incorrectly freed.
import basics
union StringOrInt (s String, i int)
func main {
soi StringOrInt
soi.s = "Hello".clone()
// We must clean up the string before using 'soi' as a different type
soi.s.__defer__()
soi.i = 10
// We don't need to clean up here, since we know that 'soi' is only an 'int',
// which doesn't need to be freed
}
Unions can be used anonymously just like structures.
struct FloatOrInt (is_float bool, union (f float, i int))
union Vec3d (
struct (
x double,
y double,
z double
),
raw 3 double
)
func exampleFunction {
floating_int union (as_float float, as_int int)
floating_int.as_float = 1.0
printf("%d\n", floating_int.as_int)
}
See section in structures for more information