reflect.odin 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. package reflect
  2. import "core:runtime"
  3. import "core:mem"
  4. Type_Info :: runtime.Type_Info;
  5. Type_Info_Named :: runtime.Type_Info_Named;
  6. Type_Info_Integer :: runtime.Type_Info_Integer;
  7. Type_Info_Rune :: runtime.Type_Info_Rune;
  8. Type_Info_Float :: runtime.Type_Info_Float;
  9. Type_Info_Complex :: runtime.Type_Info_Complex;
  10. Type_Info_Quaternion :: runtime.Type_Info_Quaternion;
  11. Type_Info_String :: runtime.Type_Info_String;
  12. Type_Info_Boolean :: runtime.Type_Info_Boolean;
  13. Type_Info_Any :: runtime.Type_Info_Any;
  14. Type_Info_Type_Id :: runtime.Type_Info_Type_Id;
  15. Type_Info_Pointer :: runtime.Type_Info_Pointer;
  16. Type_Info_Procedure :: runtime.Type_Info_Procedure;
  17. Type_Info_Array :: runtime.Type_Info_Array;
  18. Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array;
  19. Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array;
  20. Type_Info_Slice :: runtime.Type_Info_Slice;
  21. Type_Info_Tuple :: runtime.Type_Info_Tuple;
  22. Type_Info_Struct :: runtime.Type_Info_Struct;
  23. Type_Info_Union :: runtime.Type_Info_Union;
  24. Type_Info_Enum :: runtime.Type_Info_Enum;
  25. Type_Info_Map :: runtime.Type_Info_Map;
  26. Type_Info_Bit_Field :: runtime.Type_Info_Bit_Field;
  27. Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set;
  28. Type_Info_Opaque :: runtime.Type_Info_Opaque;
  29. Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector;
  30. Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer;
  31. Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice;
  32. Type_Kind :: enum {
  33. Invalid,
  34. Named,
  35. Integer,
  36. Rune,
  37. Float,
  38. Complex,
  39. Quaternion,
  40. String,
  41. Boolean,
  42. Any,
  43. Type_Id,
  44. Pointer,
  45. Procedure,
  46. Array,
  47. Enumerated_Array,
  48. Dynamic_Array,
  49. Slice,
  50. Tuple,
  51. Struct,
  52. Union,
  53. Enum,
  54. Map,
  55. Bit_Field,
  56. Bit_Set,
  57. Opaque,
  58. Simd_Vector,
  59. Relative_Pointer,
  60. Relative_Slice,
  61. }
  62. type_kind :: proc(T: typeid) -> Type_Kind {
  63. ti := type_info_of(T);
  64. if ti != nil {
  65. switch _ in ti.variant {
  66. case Type_Info_Named: return .Named;
  67. case Type_Info_Integer: return .Integer;
  68. case Type_Info_Rune: return .Rune;
  69. case Type_Info_Float: return .Float;
  70. case Type_Info_Complex: return .Complex;
  71. case Type_Info_Quaternion: return .Quaternion;
  72. case Type_Info_String: return .String;
  73. case Type_Info_Boolean: return .Boolean;
  74. case Type_Info_Any: return .Any;
  75. case Type_Info_Type_Id: return .Type_Id;
  76. case Type_Info_Pointer: return .Pointer;
  77. case Type_Info_Procedure: return .Procedure;
  78. case Type_Info_Array: return .Array;
  79. case Type_Info_Enumerated_Array: return .Enumerated_Array;
  80. case Type_Info_Dynamic_Array: return .Dynamic_Array;
  81. case Type_Info_Slice: return .Slice;
  82. case Type_Info_Tuple: return .Tuple;
  83. case Type_Info_Struct: return .Struct;
  84. case Type_Info_Union: return .Union;
  85. case Type_Info_Enum: return .Enum;
  86. case Type_Info_Map: return .Map;
  87. case Type_Info_Bit_Field: return .Bit_Field;
  88. case Type_Info_Bit_Set: return .Bit_Set;
  89. case Type_Info_Opaque: return .Opaque;
  90. case Type_Info_Simd_Vector: return .Simd_Vector;
  91. case Type_Info_Relative_Pointer: return .Relative_Pointer;
  92. case Type_Info_Relative_Slice: return .Relative_Slice;
  93. }
  94. }
  95. return .Invalid;
  96. }
  97. // TODO(bill): Better name
  98. underlying_type_kind :: proc(T: typeid) -> Type_Kind {
  99. return type_kind(runtime.typeid_base(T));
  100. }
  101. // TODO(bill): Better name
  102. backing_type_kind :: proc(T: typeid) -> Type_Kind {
  103. return type_kind(runtime.typeid_core(T));
  104. }
  105. type_info_base :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
  106. if info == nil do return nil;
  107. base := info;
  108. loop: for {
  109. #partial switch i in base.variant {
  110. case Type_Info_Named: base = i.base;
  111. case: break loop;
  112. }
  113. }
  114. return base;
  115. }
  116. type_info_core :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
  117. if info == nil do return nil;
  118. base := info;
  119. loop: for {
  120. #partial switch i in base.variant {
  121. case Type_Info_Named: base = i.base;
  122. case Type_Info_Enum: base = i.base;
  123. case Type_Info_Opaque: base = i.elem;
  124. case: break loop;
  125. }
  126. }
  127. return base;
  128. }
  129. type_info_base_without_enum :: type_info_core;
  130. typeid_base :: proc(id: typeid) -> typeid {
  131. ti := type_info_of(id);
  132. ti = type_info_base(ti);
  133. return ti.id;
  134. }
  135. typeid_core :: proc(id: typeid) -> typeid {
  136. ti := type_info_base_without_enum(type_info_of(id));
  137. return ti.id;
  138. }
  139. typeid_base_without_enum :: typeid_core;
  140. typeid_elem :: proc(id: typeid) -> typeid {
  141. ti := type_info_of(id);
  142. if ti == nil do return nil;
  143. bits := 8*ti.size;
  144. #partial switch v in ti.variant {
  145. case Type_Info_Complex:
  146. switch bits {
  147. case 64: return f32;
  148. case 128: return f64;
  149. }
  150. case Type_Info_Quaternion:
  151. switch bits {
  152. case 128: return f32;
  153. case 256: return f64;
  154. }
  155. case Type_Info_Pointer: return v.elem.id;
  156. case Type_Info_Opaque: return v.elem.id;
  157. case Type_Info_Array: return v.elem.id;
  158. case Type_Info_Enumerated_Array: return v.elem.id;
  159. case Type_Info_Slice: return v.elem.id;
  160. case Type_Info_Dynamic_Array: return v.elem.id;
  161. }
  162. return id;
  163. }
  164. size_of_typeid :: proc(T: typeid) -> int {
  165. if ti := type_info_of(T); ti != nil {
  166. return ti.size;
  167. }
  168. return 0;
  169. }
  170. align_of_typeid :: proc(T: typeid) -> int {
  171. if ti := type_info_of(T); ti != nil {
  172. return ti.align;
  173. }
  174. return 1;
  175. }
  176. as_bytes :: proc(v: any) -> []byte {
  177. if v != nil {
  178. sz := size_of_typeid(v.id);
  179. return mem.slice_ptr((^byte)(v.data), sz);
  180. }
  181. return nil;
  182. }
  183. any_data :: inline proc(v: any) -> (data: rawptr, id: typeid) {
  184. return v.data, v.id;
  185. }
  186. is_nil :: proc(v: any) -> bool {
  187. if v == nil {
  188. return true;
  189. }
  190. data := as_bytes(v);
  191. if data != nil {
  192. return true;
  193. }
  194. for v in data do if v != 0 {
  195. return false;
  196. }
  197. return true;
  198. }
  199. length :: proc(val: any) -> int {
  200. if val == nil do return 0;
  201. #partial switch a in type_info_of(val.id).variant {
  202. case Type_Info_Named:
  203. return length({val.data, a.base.id});
  204. case Type_Info_Pointer:
  205. return length({val.data, a.elem.id});
  206. case Type_Info_Array:
  207. return a.count;
  208. case Type_Info_Enumerated_Array:
  209. return a.count;
  210. case Type_Info_Slice:
  211. return (^mem.Raw_Slice)(val.data).len;
  212. case Type_Info_Dynamic_Array:
  213. return (^mem.Raw_Dynamic_Array)(val.data).len;
  214. case Type_Info_Map:
  215. return (^mem.Raw_Map)(val.data).entries.len;
  216. case Type_Info_String:
  217. if a.is_cstring {
  218. return len((^cstring)(val.data)^);
  219. } else {
  220. return (^mem.Raw_String)(val.data).len;
  221. }
  222. }
  223. return 0;
  224. }
  225. capacity :: proc(val: any) -> int {
  226. if val == nil do return 0;
  227. #partial switch a in type_info_of(val.id).variant {
  228. case Type_Info_Named:
  229. return capacity({val.data, a.base.id});
  230. case Type_Info_Pointer:
  231. return capacity({val.data, a.elem.id});
  232. case Type_Info_Array:
  233. return a.count;
  234. case Type_Info_Enumerated_Array:
  235. return a.count;
  236. case Type_Info_Dynamic_Array:
  237. return (^mem.Raw_Dynamic_Array)(val.data).cap;
  238. case Type_Info_Map:
  239. return (^mem.Raw_Map)(val.data).entries.cap;
  240. }
  241. return 0;
  242. }
  243. index :: proc(val: any, i: int, loc := #caller_location) -> any {
  244. if val == nil do return nil;
  245. #partial switch a in type_info_of(val.id).variant {
  246. case Type_Info_Named:
  247. return index({val.data, a.base.id}, i, loc);
  248. case Type_Info_Pointer:
  249. ptr := (^rawptr)(val.data)^;
  250. if ptr == nil {
  251. return nil;
  252. }
  253. return index({ptr, a.elem.id}, i, loc);
  254. case Type_Info_Array:
  255. runtime.bounds_check_error_loc(loc, i, a.count);
  256. offset := uintptr(a.elem.size * i);
  257. data := rawptr(uintptr(val.data) + offset);
  258. return any{data, a.elem.id};
  259. case Type_Info_Enumerated_Array:
  260. runtime.bounds_check_error_loc(loc, i, a.count);
  261. offset := uintptr(a.elem.size * i);
  262. data := rawptr(uintptr(val.data) + offset);
  263. return any{data, a.elem.id};
  264. case Type_Info_Slice:
  265. raw := (^mem.Raw_Slice)(val.data);
  266. runtime.bounds_check_error_loc(loc, i, raw.len);
  267. offset := uintptr(a.elem.size * i);
  268. data := rawptr(uintptr(raw.data) + offset);
  269. return any{data, a.elem.id};
  270. case Type_Info_Dynamic_Array:
  271. raw := (^mem.Raw_Dynamic_Array)(val.data);
  272. runtime.bounds_check_error_loc(loc, i, raw.len);
  273. offset := uintptr(a.elem.size * i);
  274. data := rawptr(uintptr(raw.data) + offset);
  275. return any{data, a.elem.id};
  276. case Type_Info_String:
  277. if a.is_cstring do return nil;
  278. raw := (^mem.Raw_String)(val.data);
  279. runtime.bounds_check_error_loc(loc, i, raw.len);
  280. offset := uintptr(size_of(u8) * i);
  281. data := rawptr(uintptr(raw.data) + offset);
  282. return any{data, typeid_of(u8)};
  283. }
  284. return nil;
  285. }
  286. Struct_Tag :: distinct string;
  287. Struct_Field :: struct {
  288. name: string,
  289. type: typeid,
  290. tag: Struct_Tag,
  291. offset: uintptr,
  292. }
  293. struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) {
  294. ti := runtime.type_info_base(type_info_of(T));
  295. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  296. if 0 <= i && i < len(s.names) {
  297. field.name = s.names[i];
  298. field.type = s.types[i].id;
  299. field.tag = Struct_Tag(s.tags[i]);
  300. field.offset = s.offsets[i];
  301. }
  302. }
  303. return;
  304. }
  305. struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) {
  306. ti := runtime.type_info_base(type_info_of(T));
  307. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  308. for fname, i in s.names {
  309. if fname == name {
  310. field.name = s.names[i];
  311. field.type = s.types[i].id;
  312. field.tag = Struct_Tag(s.tags[i]);
  313. field.offset = s.offsets[i];
  314. break;
  315. }
  316. }
  317. }
  318. return;
  319. }
  320. struct_field_value_by_name :: proc(a: any, field: string, recurse := false) -> any {
  321. if a == nil do return nil;
  322. ti := runtime.type_info_base(type_info_of(a.id));
  323. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  324. for name, i in s.names {
  325. if name == field {
  326. return any{
  327. rawptr(uintptr(a.data) + s.offsets[i]),
  328. s.types[i].id,
  329. };
  330. }
  331. if recurse && s.usings[i] {
  332. f := any{
  333. rawptr(uintptr(a.data) + s.offsets[i]),
  334. s.types[i].id,
  335. };
  336. if res := struct_field_value_by_name(f, field, recurse); res != nil {
  337. return res;
  338. }
  339. }
  340. }
  341. }
  342. return nil;
  343. }
  344. struct_field_names :: proc(T: typeid) -> []string {
  345. ti := runtime.type_info_base(type_info_of(T));
  346. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  347. return s.names;
  348. }
  349. return nil;
  350. }
  351. struct_field_types :: proc(T: typeid) -> []^runtime.Type_Info {
  352. ti := runtime.type_info_base(type_info_of(T));
  353. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  354. return s.types;
  355. }
  356. return nil;
  357. }
  358. struct_field_tags :: proc(T: typeid) -> []Struct_Tag {
  359. ti := runtime.type_info_base(type_info_of(T));
  360. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  361. return transmute([]Struct_Tag)s.tags;
  362. }
  363. return nil;
  364. }
  365. struct_field_offsets :: proc(T: typeid) -> []uintptr {
  366. ti := runtime.type_info_base(type_info_of(T));
  367. if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
  368. return s.offsets;
  369. }
  370. return nil;
  371. }
  372. struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) {
  373. value, _ = struct_tag_lookup(tag, key);
  374. return;
  375. }
  376. struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, ok: bool) {
  377. for t := tag; t != ""; /**/ {
  378. i := 0;
  379. for i < len(t) && t[i] == ' ' { // Skip whitespace
  380. i += 1;
  381. }
  382. t = t[i:];
  383. if len(t) == 0 do break;
  384. i = 0;
  385. loop: for i < len(t) {
  386. switch t[i] {
  387. case ':', '"':
  388. break loop;
  389. case 0x00 ..< ' ', 0x7f .. 0x9f: // break if control character is found
  390. break loop;
  391. }
  392. i += 1;
  393. }
  394. if i == 0 do break;
  395. if i+1 >= len(t) do break;
  396. if t[i] != ':' || t[i+1] != '"' {
  397. break;
  398. }
  399. name := string(t[:i]);
  400. t = t[i+1:];
  401. i = 1;
  402. for i < len(t) && t[i] != '"' { // find closing quote
  403. if t[i] == '\\' do i += 1; // Skip escaped characters
  404. i += 1;
  405. }
  406. if i >= len(t) do break;
  407. val := string(t[:i+1]);
  408. t = t[i+1:];
  409. if key == name {
  410. return Struct_Tag(val[1:i]), true;
  411. }
  412. }
  413. return;
  414. }
  415. enum_string :: proc(a: any) -> string {
  416. if a == nil do return "";
  417. ti := runtime.type_info_base(type_info_of(a.id));
  418. if e, ok := ti.variant.(runtime.Type_Info_Enum); ok {
  419. v, _ := as_i64(a);
  420. for value, i in e.values {
  421. if value == runtime.Type_Info_Enum_Value(v) {
  422. return e.names[i];
  423. }
  424. }
  425. } else {
  426. panic("expected an enum to reflect.enum_string");
  427. }
  428. return "";
  429. }
  430. // Given a enum type and a value name, get the enum value.
  431. enum_from_name :: proc($EnumType: typeid, name: string) -> (value: EnumType, ok: bool) {
  432. ti := type_info_base(type_info_of(EnumType));
  433. if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
  434. for value_name, i in eti.names {
  435. if value_name != name do continue;
  436. v := eti.values[i];
  437. value = EnumType(v);
  438. ok = true;
  439. return;
  440. }
  441. } else {
  442. panic("expected enum type to reflect.enum_from_name");
  443. }
  444. return;
  445. }
  446. union_variant_type_info :: proc(a: any) -> ^runtime.Type_Info {
  447. id := union_variant_typeid(a);
  448. return type_info_of(id);
  449. }
  450. union_variant_typeid :: proc(a: any) -> typeid {
  451. if a == nil do return nil;
  452. ti := runtime.type_info_base(type_info_of(a.id));
  453. if info, ok := ti.variant.(runtime.Type_Info_Union); ok {
  454. tag_ptr := uintptr(a.data) + info.tag_offset;
  455. tag_any := any{rawptr(tag_ptr), info.tag_type.id};
  456. tag: i64 = ---;
  457. switch i in tag_any {
  458. case u8: tag = i64(i);
  459. case i8: tag = i64(i);
  460. case u16: tag = i64(i);
  461. case i16: tag = i64(i);
  462. case u32: tag = i64(i);
  463. case i32: tag = i64(i);
  464. case u64: tag = i64(i);
  465. case i64: tag = i64(i);
  466. case: unimplemented();
  467. }
  468. if a.data != nil && tag != 0 {
  469. return info.variants[tag-1].id;
  470. }
  471. } else {
  472. panic("expected a union to reflect.union_variant_typeid");
  473. }
  474. return nil;
  475. }
  476. as_int :: proc(a: any) -> (value: int, valid: bool) {
  477. v: i64;
  478. v, valid = as_i64(a);
  479. value = int(v);
  480. return;
  481. }
  482. as_uint :: proc(a: any) -> (value: uint, valid: bool) {
  483. v: u64;
  484. v, valid = as_u64(a);
  485. value = uint(v);
  486. return;
  487. }
  488. as_i64 :: proc(a: any) -> (value: i64, valid: bool) {
  489. if a == nil do return;
  490. a := a;
  491. ti := runtime.type_info_core(type_info_of(a.id));
  492. a.id = ti.id;
  493. #partial switch info in ti.variant {
  494. case Type_Info_Integer:
  495. valid = true;
  496. switch v in a {
  497. case i8: value = i64(v);
  498. case i16: value = i64(v);
  499. case i32: value = i64(v);
  500. case i64: value = i64(v);
  501. case i128: value = i64(v);
  502. case int: value = i64(v);
  503. case u8: value = i64(v);
  504. case u16: value = i64(v);
  505. case u32: value = i64(v);
  506. case u64: value = i64(v);
  507. case u128: value = i64(v);
  508. case uint: value = i64(v);
  509. case uintptr: value = i64(v);
  510. case u16le: value = i64(v);
  511. case u32le: value = i64(v);
  512. case u64le: value = i64(v);
  513. case u128le: value = i64(v);
  514. case i16le: value = i64(v);
  515. case i32le: value = i64(v);
  516. case i64le: value = i64(v);
  517. case i128le: value = i64(v);
  518. case u16be: value = i64(v);
  519. case u32be: value = i64(v);
  520. case u64be: value = i64(v);
  521. case u128be: value = i64(v);
  522. case i16be: value = i64(v);
  523. case i32be: value = i64(v);
  524. case i64be: value = i64(v);
  525. case i128be: value = i64(v);
  526. case: valid = false;
  527. }
  528. case Type_Info_Rune:
  529. r := a.(rune);
  530. value = i64(r);
  531. valid = true;
  532. case Type_Info_Float:
  533. valid = true;
  534. switch v in a {
  535. case f32: value = i64(f32(v));
  536. case f64: value = i64(f64(v));
  537. case f32le: value = i64(f32(v));
  538. case f64le: value = i64(f64(v));
  539. case f32be: value = i64(f32(v));
  540. case f64be: value = i64(f64(v));
  541. case: valid = false;
  542. }
  543. case Type_Info_Boolean:
  544. valid = true;
  545. switch v in a {
  546. case bool: value = i64(bool(v));
  547. case b8: value = i64(bool(v));
  548. case b16: value = i64(bool(v));
  549. case b32: value = i64(bool(v));
  550. case b64: value = i64(bool(v));
  551. case: valid = false;
  552. }
  553. case Type_Info_Complex:
  554. switch v in a {
  555. case complex64:
  556. if imag(v) == 0 {
  557. value = i64(real(v));
  558. valid = true;
  559. }
  560. case complex128:
  561. if imag(v) == 0 {
  562. value = i64(real(v));
  563. valid = true;
  564. }
  565. }
  566. case Type_Info_Quaternion:
  567. switch v in a {
  568. case quaternion128:
  569. if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 {
  570. value = i64(real(v));
  571. valid = true;
  572. }
  573. case quaternion256:
  574. if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 {
  575. value = i64(real(v));
  576. valid = true;
  577. }
  578. }
  579. }
  580. return;
  581. }
  582. as_u64 :: proc(a: any) -> (value: u64, valid: bool) {
  583. if a == nil do return;
  584. a := a;
  585. ti := runtime.type_info_core(type_info_of(a.id));
  586. a.id = ti.id;
  587. #partial switch info in ti.variant {
  588. case Type_Info_Integer:
  589. valid = true;
  590. switch v in a {
  591. case i8: value = u64(v);
  592. case i16: value = u64(v);
  593. case i32: value = u64(v);
  594. case i64: value = u64(v);
  595. case i128: value = u64(v);
  596. case int: value = u64(v);
  597. case u8: value = u64(v);
  598. case u16: value = u64(v);
  599. case u32: value = u64(v);
  600. case u64: value = u64(v);
  601. case u128: value = u64(v);
  602. case uint: value = u64(v);
  603. case uintptr:value = u64(v);
  604. case u16le: value = u64(v);
  605. case u32le: value = u64(v);
  606. case u64le: value = u64(v);
  607. case u128le: value = u64(v);
  608. case i16le: value = u64(v);
  609. case i32le: value = u64(v);
  610. case i64le: value = u64(v);
  611. case i128le: value = u64(v);
  612. case u16be: value = u64(v);
  613. case u32be: value = u64(v);
  614. case u64be: value = u64(v);
  615. case u128be: value = u64(v);
  616. case i16be: value = u64(v);
  617. case i32be: value = u64(v);
  618. case i64be: value = u64(v);
  619. case i128be: value = u64(v);
  620. case: valid = false;
  621. }
  622. case Type_Info_Rune:
  623. r := a.(rune);
  624. value = u64(r);
  625. valid = true;
  626. case Type_Info_Float:
  627. valid = true;
  628. switch v in a {
  629. case f32: value = u64(f32(v));
  630. case f64: value = u64(f64(v));
  631. case f32le: value = u64(f32(v));
  632. case f64le: value = u64(f64(v));
  633. case f32be: value = u64(f32(v));
  634. case f64be: value = u64(f64(v));
  635. case: valid = false;
  636. }
  637. case Type_Info_Boolean:
  638. valid = true;
  639. switch v in a {
  640. case bool: value = u64(bool(v));
  641. case b8: value = u64(bool(v));
  642. case b16: value = u64(bool(v));
  643. case b32: value = u64(bool(v));
  644. case b64: value = u64(bool(v));
  645. case: valid = false;
  646. }
  647. case Type_Info_Complex:
  648. switch v in a {
  649. case complex64:
  650. if imag(v) == 0 {
  651. value = u64(real(v));
  652. valid = true;
  653. }
  654. case complex128:
  655. if imag(v) == 0 {
  656. value = u64(real(v));
  657. valid = true;
  658. }
  659. }
  660. case Type_Info_Quaternion:
  661. switch v in a {
  662. case quaternion128:
  663. if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 {
  664. value = u64(real(v));
  665. valid = true;
  666. }
  667. case quaternion256:
  668. if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 {
  669. value = u64(real(v));
  670. valid = true;
  671. }
  672. }
  673. }
  674. return;
  675. }
  676. as_f64 :: proc(a: any) -> (value: f64, valid: bool) {
  677. if a == nil do return;
  678. a := a;
  679. ti := runtime.type_info_core(type_info_of(a.id));
  680. a.id = ti.id;
  681. #partial switch info in ti.variant {
  682. case Type_Info_Integer:
  683. valid = true;
  684. switch v in a {
  685. case i8: value = f64(v);
  686. case i16: value = f64(v);
  687. case i32: value = f64(v);
  688. case i64: value = f64(v);
  689. case i128: value = f64(v);
  690. case u8: value = f64(v);
  691. case u16: value = f64(v);
  692. case u32: value = f64(v);
  693. case u64: value = f64(v);
  694. case u128: value = f64(v);
  695. case u16le: value = f64(v);
  696. case u32le: value = f64(v);
  697. case u64le: value = f64(v);
  698. case u128le:value = f64(v);
  699. case i16le: value = f64(v);
  700. case i32le: value = f64(v);
  701. case i64le: value = f64(v);
  702. case i128le:value = f64(v);
  703. case u16be: value = f64(v);
  704. case u32be: value = f64(v);
  705. case u64be: value = f64(v);
  706. case u128be:value = f64(v);
  707. case i16be: value = f64(v);
  708. case i32be: value = f64(v);
  709. case i64be: value = f64(v);
  710. case i128be:value = f64(v);
  711. case: valid = false;
  712. }
  713. case Type_Info_Rune:
  714. r := a.(rune);
  715. value = f64(i32(r));
  716. valid = true;
  717. case Type_Info_Float:
  718. valid = true;
  719. switch v in a {
  720. case f32: value = f64(f32(v));
  721. case f64: value = f64(f64(v));
  722. case f32le: value = f64(f32(v));
  723. case f64le: value = f64(f64(v));
  724. case f32be: value = f64(f32(v));
  725. case f64be: value = f64(f64(v));
  726. case: valid = false;
  727. }
  728. case Type_Info_Boolean:
  729. valid = true;
  730. switch v in a {
  731. case bool: value = f64(i32(bool(v)));
  732. case b8: value = f64(i32(bool(v)));
  733. case b16: value = f64(i32(bool(v)));
  734. case b32: value = f64(i32(bool(v)));
  735. case b64: value = f64(i32(bool(v)));
  736. case: valid = false;
  737. }
  738. case Type_Info_Complex:
  739. switch v in a {
  740. case complex64:
  741. if imag(v) == 0 {
  742. value = f64(real(v));
  743. valid = true;
  744. }
  745. case complex128:
  746. if imag(v) == 0 {
  747. value = f64(real(v));
  748. valid = true;
  749. }
  750. }
  751. case Type_Info_Quaternion:
  752. switch v in a {
  753. case quaternion128:
  754. if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 {
  755. value = f64(real(v));
  756. valid = true;
  757. }
  758. case quaternion256:
  759. if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 {
  760. value = f64(real(v));
  761. valid = true;
  762. }
  763. }
  764. }
  765. return;
  766. }