harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

15-enums.ha (3875B)


      1 use rt;
      2 use testmod;
      3 
      4 type implicit_values = enum {
      5 	ZERO,
      6 	ONE,
      7 	TWO,
      8 };
      9 
     10 fn implicit() void = {
     11 	assert(implicit_values::ZERO == 0);
     12 	assert(implicit_values::ONE == 1);
     13 	assert(implicit_values::TWO == 2);
     14 };
     15 
     16 type explicit_values = enum {
     17 	NEGONE = -1,
     18 	SIXTEEN = 16,
     19 	SEVENTEEN,
     20 	EIGHTEEN,
     21 	FIFTY = 50,
     22 };
     23 
     24 fn explicit() void = {
     25 	assert(explicit_values::NEGONE == -1);
     26 	assert(explicit_values::SIXTEEN == 16);
     27 	assert(explicit_values::SEVENTEEN == 17);
     28 	assert(explicit_values::EIGHTEEN == 18);
     29 	assert(explicit_values::FIFTY == 50);
     30 };
     31 
     32 type with_storage = enum u16 {
     33 	CAFE = 0xCAFE,
     34 	BABE = 0xBABE,
     35 	DEAD = 0xDEAD,
     36 	BEEF = 0xBEEF,
     37 };
     38 
     39 type char_storage = enum char {
     40 	FOO = 0,
     41 	BAR = 1,
     42 };
     43 
     44 type rune_storage = enum rune {
     45 	FOO = '0',
     46 	BAR = '1',
     47 };
     48 
     49 type uintptr_storage = enum uintptr {
     50 	FOO = 0,
     51 	BAR = 1,
     52 };
     53 
     54 let global_uintptr: uintptr_storage = uintptr_storage::FOO;
     55 
     56 fn storage() void = {
     57 	assert(size(explicit_values) == size(int));
     58 	assert(size(with_storage) == 2);
     59 	const val = 0xBEEFu16;
     60 	const is_little = (&val: *[2]u8)[0] == 0xEF;
     61 	assert(with_storage::CAFE: u8 == (if (is_little) 0xFEu8 else 0xCAu8));
     62 	assert(with_storage::BABE: u8 == (if (is_little) 0xBEu8 else 0xBAu8));
     63 	assert(with_storage::DEAD: u8 == (if (is_little) 0xADu8 else 0xDEu8));
     64 	assert(with_storage::BEEF: u8 == (if (is_little) 0xEFu8 else 0xBEu8));
     65 	assert(char_storage::FOO == 0 && char_storage::BAR == 1);
     66 	assert(rune_storage::FOO == '0' && rune_storage::BAR == '1');
     67 };
     68 
     69 fn reject() void = {
     70 	// enum type definition used outside type declaration
     71 	assert(rt::compile("export let a: enum { A, B } = 0;") != 0);
     72 	assert(rt::compile("export let a: int = 0: enum{A, B}: int;") != 0);
     73 
     74 	// enum circular dependencies
     75 	assert(rt::compile("type a = enum { A = B, B = A };") != 0);
     76 	assert(rt::compile("type a = enum { A = b::B },
     77 				b = enum { B = a::A };") != 0);
     78 	assert(rt::compile("
     79 		def a: int = e::VAL1;
     80 		type e = enum { VAL1 = a };
     81 	") != 0);
     82 	assert(rt::compile("
     83 		def a: int = e::VAL1;
     84 		type e = enum { VAL1 = VAL2, VAL2 = a };
     85 	") != 0);
     86 };
     87 
     88 type interdependent1 = enum {
     89 	A = 0,
     90 	B = interdependent2::A + 1,
     91 	C = interdependent2::B + 1,
     92 };
     93 
     94 type interdependent2 = enum {
     95 	A = interdependent1::A + 1,
     96 	B = interdependent1::B + 1,
     97 	C = interdependent1::C + 1,
     98 };
     99 
    100 fn interdependent() void = {
    101 	assert(interdependent1::A == 0);
    102 	assert(interdependent2::A == 1);
    103 	assert(interdependent1::B == 2);
    104 	assert(interdependent2::B == 3);
    105 	assert(interdependent1::C == 4);
    106 	assert(interdependent2::C == 5);
    107 };
    108 
    109 type e1 = enum { a, b, c, d }, a1 = e1;
    110 type a2 = e2, e2 = enum u8 { a, b, c, d }; // reverse
    111 
    112 type imported_alias = testmod::_enum;
    113 
    114 type imported_double_alias = testmod::enum_alias;
    115 
    116 fn aliases() void = {
    117 	assert(size(a1) == size(e1));
    118 	assert(a1::a == e1::a);
    119 	assert(a1::b == e1::b);
    120 	assert(a1::c == e1::c);
    121 	assert(a1::d == e1::d);
    122 
    123 	assert(size(a2) == size(e2));
    124 	assert(a2::a == e2::a);
    125 	assert(a2::b == e2::b);
    126 	assert(a2::c == e2::c);
    127 	assert(a2::d == e2::d);
    128 
    129 	// test with alias of imported enum
    130 	assert(imported_alias::ONE == testmod::_enum::ONE);
    131 	assert(imported_alias::TWO == testmod::_enum::TWO);
    132 	assert(imported_alias::THREE == testmod::_enum::THREE);
    133 
    134 	assert(imported_double_alias::ONE == testmod::_enum::ONE);
    135 	assert(imported_double_alias::TWO == testmod::_enum::TWO);
    136 	assert(imported_double_alias::THREE == testmod::_enum::THREE);
    137 };
    138 
    139 // Force T2 to be resolved before t2::T3 and t2::T3 before t2::T1
    140 type t1 = enum {
    141 	I1 = t2::T1,
    142 	I2 = t2::T3,
    143 	I3 = T2: int,
    144 };
    145 
    146 def T2: uint = 0;
    147 
    148 type t2 = enum {
    149 	T1,
    150 	T2 = 1,
    151 	T3 = T2 + 1,
    152 };
    153 
    154 fn resolution_order() void = {
    155 	assert(t2::T1 == 0);
    156 	assert(t2::T2 == 1);
    157 	assert(t2::T3 == 2);
    158 	assert(t1::I1 == 0);
    159 	assert(t1::I2 == 2);
    160 	assert(t1::I3 == 0);
    161 	assert(T2 == 0);
    162 };
    163 
    164 export fn main() void = {
    165 	implicit();
    166 	explicit();
    167 	storage();
    168 	reject();
    169 	interdependent();
    170 	aliases();
    171 	resolution_order();
    172 };