15-enums.ha (4210B)
1 use rt::{compile, exited, EXIT_SUCCESS}; 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) == size(u16)); 59 assert(size(uintptr_storage) == size(uintptr)); 60 assert(align(explicit_values) == align(int)); 61 assert(align(with_storage) == align(u16)); 62 assert(align(uintptr_storage) == align(uintptr)); 63 64 const val = 0xBEEFu16; 65 const is_little = (&val: *[2]u8)[0] == 0xEF; 66 assert(with_storage::CAFE: u8 == (if (is_little) 0xFEu8 else 0xCAu8)); 67 assert(with_storage::BABE: u8 == (if (is_little) 0xBEu8 else 0xBAu8)); 68 assert(with_storage::DEAD: u8 == (if (is_little) 0xADu8 else 0xDEu8)); 69 assert(with_storage::BEEF: u8 == (if (is_little) 0xEFu8 else 0xBEu8)); 70 assert(char_storage::FOO == 0 && char_storage::BAR == 1); 71 assert(rune_storage::FOO == '0' && rune_storage::BAR == '1'); 72 }; 73 74 fn reject() void = { 75 // enum type definition used outside type declaration 76 assert(compile("export let a: enum { A, B } = 0;") as exited != EXIT_SUCCESS); 77 assert(compile("export let a: int = 0: enum{A, B}: int;") as exited != EXIT_SUCCESS); 78 79 // enum circular dependencies 80 assert(compile("type a = enum { A = B, B = A };") as exited != EXIT_SUCCESS); 81 assert(compile("type a = enum { A = b::B }, 82 b = enum { B = a::A };") as exited != EXIT_SUCCESS); 83 assert(compile(" 84 def a: int = e::VAL1; 85 type e = enum { VAL1 = a }; 86 ") as exited != EXIT_SUCCESS); 87 assert(compile(" 88 def a: int = e::VAL1; 89 type e = enum { VAL1 = VAL2, VAL2 = a }; 90 ") as exited != EXIT_SUCCESS); 91 }; 92 93 type interdependent1 = enum { 94 A = 0, 95 B = interdependent2::A + 1, 96 C = interdependent2::B + 1, 97 }; 98 99 type interdependent2 = enum { 100 A = interdependent1::A + 1, 101 B = interdependent1::B + 1, 102 C = interdependent1::C + 1, 103 }; 104 105 fn interdependent() void = { 106 assert(interdependent1::A == 0); 107 assert(interdependent2::A == 1); 108 assert(interdependent1::B == 2); 109 assert(interdependent2::B == 3); 110 assert(interdependent1::C == 4); 111 assert(interdependent2::C == 5); 112 }; 113 114 type e1 = enum { a, b, c, d }, a1 = e1; 115 type a2 = e2, e2 = enum u8 { a, b, c, d }; // reverse 116 117 type imported_alias = testmod::_enum; 118 119 type imported_double_alias = testmod::enum_alias; 120 121 fn aliases() void = { 122 assert(size(a1) == size(e1)); 123 assert(a1::a == e1::a); 124 assert(a1::b == e1::b); 125 assert(a1::c == e1::c); 126 assert(a1::d == e1::d); 127 128 assert(size(a2) == size(e2)); 129 assert(a2::a == e2::a); 130 assert(a2::b == e2::b); 131 assert(a2::c == e2::c); 132 assert(a2::d == e2::d); 133 134 // test with alias of imported enum 135 assert(imported_alias::ONE == testmod::_enum::ONE); 136 assert(imported_alias::TWO == testmod::_enum::TWO); 137 assert(imported_alias::THREE == testmod::_enum::THREE); 138 139 assert(imported_double_alias::ONE == testmod::_enum::ONE); 140 assert(imported_double_alias::TWO == testmod::_enum::TWO); 141 assert(imported_double_alias::THREE == testmod::_enum::THREE); 142 }; 143 144 // Force T2 to be resolved before t2::T3 and t2::T3 before t2::T1 145 type t1 = enum { 146 I1 = t2::T1, 147 I2 = t2::T3, 148 I3 = T2: int, 149 }; 150 151 def T2: uint = 0; 152 153 type t2 = enum { 154 T1, 155 T2 = 1, 156 T3 = T2 + 1, 157 }; 158 159 fn resolution_order() void = { 160 assert(t2::T1 == 0); 161 assert(t2::T2 == 1); 162 assert(t2::T3 == 2); 163 assert(t1::I1 == 0); 164 assert(t1::I2 == 2); 165 assert(t1::I3 == 0); 166 assert(T2 == 0); 167 }; 168 169 export fn main() void = { 170 implicit(); 171 explicit(); 172 storage(); 173 reject(); 174 interdependent(); 175 aliases(); 176 resolution_order(); 177 };