demo.odin 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. package main
  2. import "core:fmt"
  3. import "core:mem"
  4. import "core:os"
  5. when os.OS == "windows" {
  6. import "core:runtime"
  7. import "core:thread"
  8. }
  9. @(link_name="general_stuff")
  10. general_stuff :: proc() {
  11. fmt.println("# general_stuff");
  12. { // `do` for inline statements rather than block
  13. foo :: proc() do fmt.println("Foo!");
  14. if false do foo();
  15. for false do foo();
  16. when false do foo();
  17. if false do foo();
  18. else do foo();
  19. }
  20. { // Removal of `++` and `--` (again)
  21. x: int;
  22. x += 1;
  23. x -= 1;
  24. }
  25. { // Casting syntaxes
  26. i := i32(137);
  27. ptr := &i;
  28. _ = (^f32)(ptr);
  29. // ^f32(ptr) == ^(f32(ptr))
  30. _ = cast(^f32)ptr;
  31. _ = (^f32)(ptr)^;
  32. _ = (cast(^f32)ptr)^;
  33. // Questions: Should there be two ways to do it?
  34. }
  35. /*
  36. * Remove *_val_of built-in procedures
  37. * size_of, align_of, offset_of
  38. * type_of, type_info_of, typeid_of
  39. */
  40. { // `expand_to_tuple` built-in procedure
  41. Foo :: struct {
  42. x: int,
  43. b: bool,
  44. }
  45. f := Foo{137, true};
  46. x, b := expand_to_tuple(f);
  47. fmt.println(f);
  48. fmt.println(x, b);
  49. fmt.println(expand_to_tuple(f));
  50. }
  51. {
  52. // .. open range
  53. for in 0..2 {} // 0, 1, 2
  54. }
  55. { // Multiple sized booleans
  56. x0: bool; // default
  57. x1: b8 = true;
  58. x2: b16 = false;
  59. x3: b32 = true;
  60. x4: b64 = false;
  61. fmt.printf("x0: %T = %v;\n", x0, x0);
  62. fmt.printf("x1: %T = %v;\n", x1, x1);
  63. fmt.printf("x2: %T = %v;\n", x2, x2);
  64. fmt.printf("x3: %T = %v;\n", x3, x3);
  65. fmt.printf("x4: %T = %v;\n", x4, x4);
  66. // Having specific sized booleans is very useful when dealing with foreign code
  67. // and to enforce specific alignment for a boolean, especially within a struct
  68. }
  69. { // `distinct` types
  70. // Originally, all type declarations would create a distinct type unless #type_alias was present.
  71. // Now the behaviour has been reversed. All type declarations create a type alias unless `distinct` is present.
  72. // If the type expression is `struct`, `union`, `enum`, `proc`, or `bit_field`, the types will always been distinct.
  73. Int32 :: i32;
  74. #assert(Int32 == i32);
  75. My_Int32 :: distinct i32;
  76. #assert(My_Int32 != i32);
  77. My_Struct :: struct{x: int};
  78. #assert(My_Struct != struct{x: int});
  79. My_Struct2 :: My_Struct;
  80. #assert(My_Struct2 == My_Struct);
  81. }
  82. {
  83. X :: 123;
  84. when #defined(X) {
  85. fmt.println("X is defined");
  86. } else {
  87. fmt.println("X is not defined");
  88. }
  89. when #defined(Y) {
  90. fmt.println("Y is defined");
  91. } else {
  92. fmt.println("Y is not defined");
  93. }
  94. }
  95. { // Labelled control blocks
  96. block: {
  97. if true {
  98. fmt.println("break block;");
  99. break block;
  100. }
  101. }
  102. {
  103. branch: if true {
  104. fmt.println("break branch;");
  105. break branch;
  106. }
  107. }
  108. {
  109. loop: for true {
  110. fmt.println("break loop;");
  111. break loop;
  112. }
  113. }
  114. {
  115. cases: switch {
  116. case:
  117. fmt.println("break cases;");
  118. break cases;
  119. }
  120. }
  121. }
  122. }
  123. union_type :: proc() {
  124. fmt.println("\n# union_type");
  125. {
  126. val: union{int, bool};
  127. val = 137;
  128. if i, ok := val.(int); ok {
  129. fmt.println(i);
  130. }
  131. val = true;
  132. fmt.println(val);
  133. val = nil;
  134. switch v in val {
  135. case int: fmt.println("int", v);
  136. case bool: fmt.println("bool", v);
  137. case: fmt.println("nil");
  138. }
  139. }
  140. {
  141. // There is a duality between `any` and `union`
  142. // An `any` has a pointer to the data and allows for any type (open)
  143. // A `union` has as binary blob to store the data and allows only certain types (closed)
  144. // The following code is with `any` but has the same syntax
  145. val: any;
  146. val = 137;
  147. if i, ok := val.(int); ok {
  148. fmt.println(i);
  149. }
  150. val = true;
  151. fmt.println(val);
  152. val = nil;
  153. switch v in val {
  154. case int: fmt.println("int", v);
  155. case bool: fmt.println("bool", v);
  156. case: fmt.println("nil");
  157. }
  158. }
  159. Vector3 :: struct {x, y, z: f32};
  160. Quaternion :: struct {x, y, z, w: f32};
  161. // More realistic examples
  162. {
  163. // NOTE(bill): For the above basic examples, you may not have any
  164. // particular use for it. However, my main use for them is not for these
  165. // simple cases. My main use is for hierarchical types. Many prefer
  166. // subtyping, embedding the base data into the derived types. Below is
  167. // an example of this for a basic game Entity.
  168. Entity :: struct {
  169. id: u64,
  170. name: string,
  171. position: Vector3,
  172. orientation: Quaternion,
  173. derived: any,
  174. }
  175. Frog :: struct {
  176. using entity: Entity,
  177. jump_height: f32,
  178. }
  179. Monster :: struct {
  180. using entity: Entity,
  181. is_robot: bool,
  182. is_zombie: bool,
  183. }
  184. // See `parametric_polymorphism` procedure for details
  185. new_entity :: proc($T: typeid) -> ^Entity {
  186. t := new(T);
  187. t.derived = t^;
  188. return t;
  189. }
  190. entity := new_entity(Monster);
  191. switch e in entity.derived {
  192. case Frog:
  193. fmt.println("Ribbit");
  194. case Monster:
  195. if e.is_robot do fmt.println("Robotic");
  196. if e.is_zombie do fmt.println("Grrrr!");
  197. fmt.println("I'm a monster");
  198. }
  199. }
  200. {
  201. // NOTE(bill): A union can be used to achieve something similar. Instead
  202. // of embedding the base data into the derived types, the derived data
  203. // in embedded into the base type. Below is the same example of the
  204. // basic game Entity but using an union.
  205. Entity :: struct {
  206. id: u64,
  207. name: string,
  208. position: Vector3,
  209. orientation: Quaternion,
  210. derived: union {Frog, Monster},
  211. }
  212. Frog :: struct {
  213. using entity: ^Entity,
  214. jump_height: f32,
  215. }
  216. Monster :: struct {
  217. using entity: ^Entity,
  218. is_robot: bool,
  219. is_zombie: bool,
  220. }
  221. // See `parametric_polymorphism` procedure for details
  222. new_entity :: proc($T: typeid) -> ^Entity {
  223. t := new(Entity);
  224. t.derived = T{entity = t};
  225. return t;
  226. }
  227. entity := new_entity(Monster);
  228. switch e in entity.derived {
  229. case Frog:
  230. fmt.println("Ribbit");
  231. case Monster:
  232. if e.is_robot do fmt.println("Robotic");
  233. if e.is_zombie do fmt.println("Grrrr!");
  234. }
  235. // NOTE(bill): As you can see, the usage code has not changed, only its
  236. // memory layout. Both approaches have their own advantages but they can
  237. // be used together to achieve different results. The subtyping approach
  238. // can allow for a greater control of the memory layout and memory
  239. // allocation, e.g. storing the derivatives together. However, this is
  240. // also its disadvantage. You must either preallocate arrays for each
  241. // derivative separation (which can be easily missed) or preallocate a
  242. // bunch of "raw" memory; determining the maximum size of the derived
  243. // types would require the aid of metaprogramming. Unions solve this
  244. // particular problem as the data is stored with the base data.
  245. // Therefore, it is possible to preallocate, e.g. [100]Entity.
  246. // It should be noted that the union approach can have the same memory
  247. // layout as the any and with the same type restrictions by using a
  248. // pointer type for the derivatives.
  249. /*
  250. Entity :: struct {
  251. ..
  252. derived: union{^Frog, ^Monster},
  253. }
  254. Frog :: struct {
  255. using entity: Entity,
  256. ..
  257. }
  258. Monster :: struct {
  259. using entity: Entity,
  260. ..
  261. }
  262. new_entity :: proc(T: type) -> ^Entity {
  263. t := new(T);
  264. t.derived = t;
  265. return t;
  266. }
  267. */
  268. }
  269. }
  270. parametric_polymorphism :: proc() {
  271. fmt.println("# parametric_polymorphism");
  272. print_value :: proc(value: $T) {
  273. fmt.printf("print_value: %T %v\n", value, value);
  274. }
  275. v1: int = 1;
  276. v2: f32 = 2.1;
  277. v3: f64 = 3.14;
  278. v4: string = "message";
  279. print_value(v1);
  280. print_value(v2);
  281. print_value(v3);
  282. print_value(v4);
  283. fmt.println();
  284. add :: proc(p, q: $T) -> T {
  285. x: T = p + q;
  286. return x;
  287. }
  288. a := add(3, 4);
  289. fmt.printf("a: %T = %v\n", a, a);
  290. b := add(3.2, 4.3);
  291. fmt.printf("b: %T = %v\n", b, b);
  292. // This is how `new` is implemented
  293. alloc_type :: proc($T: typeid) -> ^T {
  294. t := cast(^T)alloc(size_of(T), align_of(T));
  295. t^ = T{}; // Use default initialization value
  296. return t;
  297. }
  298. copy_slice :: proc(dst, src: []$T) -> int {
  299. n := min(len(dst), len(src));
  300. if n > 0 {
  301. mem.copy(&dst[0], &src[0], n*size_of(T));
  302. }
  303. return n;
  304. }
  305. double_params :: proc(a: $A, b: $B) -> A {
  306. return a + A(b);
  307. }
  308. fmt.println(double_params(12, 1.345));
  309. { // Polymorphic Types and Type Specialization
  310. Table_Slot :: struct(Key, Value: typeid) {
  311. occupied: bool,
  312. hash: u32,
  313. key: Key,
  314. value: Value,
  315. }
  316. TABLE_SIZE_MIN :: 32;
  317. Table :: struct(Key, Value: typeid) {
  318. count: int,
  319. allocator: mem.Allocator,
  320. slots: []Table_Slot(Key, Value),
  321. }
  322. // Only allow types that are specializations of a (polymorphic) slice
  323. make_slice :: proc($T: typeid/[]$E, len: int) -> T {
  324. return make(T, len);
  325. }
  326. // Only allow types that are specializations of `Table`
  327. allocate :: proc(table: ^$T/Table, capacity: int) {
  328. c := context;
  329. if table.allocator.procedure != nil do c.allocator = table.allocator;
  330. context = c;
  331. table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
  332. }
  333. expand :: proc(table: ^$T/Table) {
  334. c := context;
  335. if table.allocator.procedure != nil do c.allocator = table.allocator;
  336. context = c;
  337. old_slots := table.slots;
  338. defer delete(old_slots);
  339. cap := max(2*len(table.slots), TABLE_SIZE_MIN);
  340. allocate(table, cap);
  341. for s in old_slots do if s.occupied {
  342. put(table, s.key, s.value);
  343. }
  344. }
  345. // Polymorphic determination of a polymorphic struct
  346. // put :: proc(table: ^$T/Table, key: T.Key, value: T.Value) {
  347. put :: proc(table: ^Table($Key, $Value), key: Key, value: Value) {
  348. hash := get_hash(key); // Ad-hoc method which would fail in a different scope
  349. index := find_index(table, key, hash);
  350. if index < 0 {
  351. if f64(table.count) >= 0.75*f64(len(table.slots)) {
  352. expand(table);
  353. }
  354. assert(table.count <= len(table.slots));
  355. index = int(hash % u32(len(table.slots)));
  356. for table.slots[index].occupied {
  357. if index += 1; index >= len(table.slots) {
  358. index = 0;
  359. }
  360. }
  361. table.count += 1;
  362. }
  363. slot := &table.slots[index];
  364. slot.occupied = true;
  365. slot.hash = hash;
  366. slot.key = key;
  367. slot.value = value;
  368. }
  369. // find :: proc(table: ^$T/Table, key: T.Key) -> (T.Value, bool) {
  370. find :: proc(table: ^Table($Key, $Value), key: Key) -> (Value, bool) {
  371. hash := get_hash(key);
  372. index := find_index(table, key, hash);
  373. if index < 0 {
  374. return Value{}, false;
  375. }
  376. return table.slots[index].value, true;
  377. }
  378. find_index :: proc(table: ^Table($Key, $Value), key: Key, hash: u32) -> int {
  379. if len(table.slots) <= 0 do return -1;
  380. index := int(hash % u32(len(table.slots)));
  381. for table.slots[index].occupied {
  382. if table.slots[index].hash == hash {
  383. if table.slots[index].key == key {
  384. return index;
  385. }
  386. }
  387. if index += 1; index >= len(table.slots) {
  388. index = 0;
  389. }
  390. }
  391. return -1;
  392. }
  393. get_hash :: proc(s: string) -> u32 { // fnv32a
  394. h: u32 = 0x811c9dc5;
  395. for i in 0..len(s)-1 {
  396. h = (h ~ u32(s[i])) * 0x01000193;
  397. }
  398. return h;
  399. }
  400. table: Table(string, int);
  401. for i in 0..36 do put(&table, "Hellope", i);
  402. for i in 0..42 do put(&table, "World!", i);
  403. found, _ := find(&table, "Hellope");
  404. fmt.printf("`found` is %v\n", found);
  405. found, _ = find(&table, "World!");
  406. fmt.printf("`found` is %v\n", found);
  407. // I would not personally design a hash table like this in production
  408. // but this is a nice basic example
  409. // A better approach would either use a `u64` or equivalent for the key
  410. // and let the user specify the hashing function or make the user store
  411. // the hashing procedure with the table
  412. }
  413. { // Parametric polymorphic union
  414. Error :: enum {
  415. Foo0,
  416. Foo1,
  417. Foo2,
  418. Foo3,
  419. }
  420. Para_Union :: union(T: typeid) {T, Error};
  421. r: Para_Union(int);
  422. fmt.println(typeid_of(type_of(r)));
  423. fmt.println(r);
  424. r = 123;
  425. fmt.println(r);
  426. r = Error.Foo0;
  427. fmt.println(r);
  428. }
  429. { // Polymorphic names
  430. foo :: proc($N: $I, $T: typeid) -> (res: [N]T) {
  431. // `N` is the constant value passed
  432. // `I` is the type of N
  433. // `T` is the type passed
  434. fmt.printf("Generating an array of type %v from the value %v of type %v\n",
  435. typeid_of(type_of(res)), N, typeid_of(I));
  436. for i in 0..N-1 {
  437. res[i] = T(i*i);
  438. }
  439. return;
  440. }
  441. T :: int;
  442. array := foo(4, T);
  443. for v, i in array {
  444. assert(v == T(i*i));
  445. }
  446. }
  447. }
  448. prefix_table := [?]string{
  449. "White",
  450. "Red",
  451. "Green",
  452. "Blue",
  453. "Octarine",
  454. "Black",
  455. };
  456. threading_example :: proc() {
  457. when os.OS == "windows" {
  458. fmt.println("# threading_example");
  459. unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
  460. runtime.bounds_check_error_loc(loc, index, len(array));
  461. n := len(array)-1;
  462. if index != n {
  463. array[index] = array[n];
  464. }
  465. pop(array);
  466. }
  467. ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
  468. runtime.bounds_check_error_loc(loc, index, len(array));
  469. copy(array[index:], array[index+1:]);
  470. pop(array);
  471. }
  472. worker_proc :: proc(t: ^thread.Thread) -> int {
  473. for iteration in 1..5 {
  474. fmt.printf("Thread %d is on iteration %d\n", t.user_index, iteration);
  475. fmt.printf("`%s`: iteration %d\n", prefix_table[t.user_index], iteration);
  476. // win32.sleep(1);
  477. }
  478. return 0;
  479. }
  480. threads := make([dynamic]^thread.Thread, 0, len(prefix_table));
  481. defer delete(threads);
  482. for in prefix_table {
  483. if t := thread.create(worker_proc); t != nil {
  484. t.init_context = context;
  485. t.use_init_context = true;
  486. t.user_index = len(threads);
  487. append(&threads, t);
  488. thread.start(t);
  489. }
  490. }
  491. for len(threads) > 0 {
  492. for i := 0; i < len(threads); /**/ {
  493. if t := threads[i]; thread.is_done(t) {
  494. fmt.printf("Thread %d is done\n", t.user_index);
  495. thread.destroy(t);
  496. ordered_remove(&threads, i);
  497. } else {
  498. i += 1;
  499. }
  500. }
  501. }
  502. }
  503. }
  504. array_programming :: proc() {
  505. fmt.println("# array_programming");
  506. {
  507. a := [3]f32{1, 2, 3};
  508. b := [3]f32{5, 6, 7};
  509. c := a * b;
  510. d := a + b;
  511. e := 1 + (c - d) / 2;
  512. fmt.printf("%.1f\n", e); // [0.5, 3.0, 6.5]
  513. }
  514. {
  515. a := [3]f32{1, 2, 3};
  516. b := swizzle(a, 2, 1, 0);
  517. assert(b == [3]f32{3, 2, 1});
  518. c := swizzle(a, 0, 0);
  519. assert(c == [2]f32{1, 1});
  520. assert(c == 1);
  521. }
  522. {
  523. Vector3 :: distinct [3]f32;
  524. a := Vector3{1, 2, 3};
  525. b := Vector3{5, 6, 7};
  526. c := (a * b)/2 + 1;
  527. d := c.x + c.y + c.z;
  528. fmt.printf("%.1f\n", d); // 22.0
  529. cross :: proc(a, b: Vector3) -> Vector3 {
  530. i := swizzle(a, 1, 2, 0) * swizzle(b, 2, 0, 1);
  531. j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0);
  532. return i - j;
  533. }
  534. blah :: proc(a: Vector3) -> f32 {
  535. return a.x + a.y + a.z;
  536. }
  537. x := cross(a, b);
  538. fmt.println(x);
  539. fmt.println(blah(x));
  540. }
  541. }
  542. named_proc_return_parameters :: proc() {
  543. fmt.println("# named proc return parameters");
  544. foo0 :: proc() -> int {
  545. return 123;
  546. }
  547. foo1 :: proc() -> (a: int) {
  548. a = 123;
  549. return;
  550. }
  551. foo2 :: proc() -> (a, b: int) {
  552. // Named return values act like variables within the scope
  553. a = 321;
  554. b = 567;
  555. return b, a;
  556. }
  557. fmt.println("foo0 =", foo0()); // 123
  558. fmt.println("foo1 =", foo1()); // 123
  559. fmt.println("foo2 =", foo2()); // 567 321
  560. }
  561. using_enum :: proc() {
  562. fmt.println("# using enum");
  563. using Foo :: enum {A, B, C};
  564. f0 := A;
  565. f1 := B;
  566. f2 := C;
  567. fmt.println(f0, f1, f2);
  568. fmt.println(len(Foo));
  569. }
  570. map_type :: proc() {
  571. fmt.println("# map type");
  572. // enums of type u16, u32, i16 & i32 also work
  573. Enum_u8 :: enum u8 {
  574. A = 0,
  575. B = 1 << 8 - 1,
  576. }
  577. Enum_u64 :: enum u64 {
  578. A = 0,
  579. B = 1 << 64 - 1,
  580. }
  581. Enum_i8 :: enum i8 {
  582. A = 0,
  583. B = -(1 << 7),
  584. }
  585. Enum_i64 :: enum i64 {
  586. A = 0,
  587. B = -(1 << 63),
  588. }
  589. map_u8: map[Enum_u8]u8;
  590. map_u8[Enum_u8.A] = u8(Enum_u8.B);
  591. assert(map_u8[Enum_u8.A] == u8(Enum_u8.B));
  592. fmt.println(map_u8);
  593. map_u64: map[Enum_u64]u64;
  594. map_u64[Enum_u64.A] = u64(Enum_u64.B);
  595. assert(map_u64[Enum_u64.A] == u64(Enum_u64.B));
  596. fmt.println(map_u64);
  597. map_i8: map[Enum_i8]i8;
  598. map_i8[Enum_i8.A] = i8(Enum_i8.B);
  599. assert(map_i8[Enum_i8.A] == i8(Enum_i8.B));
  600. fmt.println(map_i8);
  601. map_i64: map[Enum_i64]i64;
  602. map_i64[Enum_i64.A] = i64(Enum_i64.B);
  603. assert(map_i64[Enum_i64.A] == i64(Enum_i64.B));
  604. fmt.println(map_i64);
  605. demo_struct :: struct {
  606. member: Enum_i64,
  607. }
  608. map_string: map[string]demo_struct;
  609. map_string["Hellope!"] = demo_struct{Enum_i64.B};
  610. assert(map_string["Hellope!"].member == Enum_i64.B);
  611. assert("Hellope?" notin map_string);
  612. fmt.println(map_string);
  613. fmt.println("Hellope! in map_string:", "Hellope!" in map_string);
  614. fmt.println("Hellope? in map_string:", "Hellope?" in map_string);
  615. }
  616. explicit_procedure_overloading :: proc() {
  617. fmt.println("# explicit procedure overloading");
  618. add_ints :: proc(a, b: int) -> int {
  619. x := a + b;
  620. fmt.println("add_ints", x);
  621. return x;
  622. }
  623. add_floats :: proc(a, b: f32) -> f32 {
  624. x := a + b;
  625. fmt.println("add_floats", x);
  626. return x;
  627. }
  628. add_numbers :: proc(a: int, b: f32, c: u8) -> int {
  629. x := int(a) + int(b) + int(c);
  630. fmt.println("add_numbers", x);
  631. return x;
  632. }
  633. add :: proc{add_ints, add_floats, add_numbers};
  634. add(int(1), int(2));
  635. add(f32(1), f32(2));
  636. add(int(1), f32(2), u8(3));
  637. add(1, 2); // untyped ints coerce to int tighter than f32
  638. add(1.0, 2.0); // untyped floats coerce to f32 tighter than int
  639. add(1, 2, 3); // three parameters
  640. // Ambiguous answers
  641. // add(1.0, 2);
  642. // add(1, 2.0);
  643. }
  644. complete_switch :: proc() {
  645. fmt.println("# complete_switch");
  646. { // enum
  647. using Foo :: enum {
  648. A,
  649. B,
  650. C,
  651. D,
  652. }
  653. b := Foo.B;
  654. f := Foo.A;
  655. #complete switch f {
  656. case A: fmt.println("A");
  657. case B: fmt.println("B");
  658. case C: fmt.println("C");
  659. case D: fmt.println("D");
  660. case: fmt.println("?");
  661. }
  662. _ = b;
  663. }
  664. { // union
  665. Foo :: union {int, bool};
  666. f: Foo = 123;
  667. #complete switch in f {
  668. case int: fmt.println("int");
  669. case bool: fmt.println("bool");
  670. case:
  671. }
  672. }
  673. }
  674. cstring_example :: proc() {
  675. W :: "Hellope";
  676. X :: cstring(W);
  677. Y :: string(X);
  678. w := W;
  679. _ = w;
  680. x: cstring = X;
  681. y: string = Y;
  682. z := string(x);
  683. fmt.println(x, y, z);
  684. fmt.println(len(x), len(y), len(z));
  685. fmt.println(len(W), len(X), len(Y));
  686. // IMPORTANT NOTE for cstring variables
  687. // len(cstring) is O(N)
  688. // cast(cstring)string is O(N)
  689. }
  690. deprecated_attribute :: proc() {
  691. @(deprecated="Use foo_v2 instead")
  692. foo_v1 :: proc(x: int) {
  693. fmt.println("foo_v1");
  694. }
  695. foo_v2 :: proc(x: int) {
  696. fmt.println("foo_v2");
  697. }
  698. // NOTE: Uncomment to see the warning messages
  699. // foo_v1(1);
  700. }
  701. bit_set_type :: proc() {
  702. {
  703. using Day :: enum {
  704. Sunday,
  705. Monday,
  706. Tuesday,
  707. Wednesday,
  708. Thursday,
  709. Friday,
  710. Saturday,
  711. }
  712. Days :: distinct bit_set[Day];
  713. WEEKEND :: Days{Sunday, Saturday};
  714. d: Days;
  715. d = {Sunday, Monday};
  716. e := d | WEEKEND;
  717. e |= {Monday};
  718. fmt.println(d, e);
  719. ok := Saturday in e; // `in` is only allowed for `map` and `bit_set` types
  720. fmt.println(ok);
  721. if Saturday in e {
  722. fmt.println("Saturday in", e);
  723. }
  724. X :: Saturday in WEEKEND; // Constant evaluation
  725. fmt.println(X);
  726. fmt.println("Cardinality:", card(e));
  727. }
  728. {
  729. x: bit_set['A'..'Z'];
  730. #assert(size_of(x) == size_of(u32));
  731. y: bit_set[0..8; u16];
  732. fmt.println(typeid_of(type_of(x))); // bit_set[A..Z]
  733. fmt.println(typeid_of(type_of(y))); // bit_set[0..8; u16]
  734. incl(&x, 'F');
  735. assert('F' in x);
  736. excl(&x, 'F');
  737. assert('F' notin x);
  738. y |= {1, 4, 2};
  739. assert(2 in y);
  740. }
  741. {
  742. Letters :: bit_set['A'..'Z'];
  743. a := Letters{'A', 'B'};
  744. b := Letters{'A', 'B', 'C', 'D', 'F'};
  745. c := Letters{'A', 'B'};
  746. assert(a <= b); // 'a' is a subset of 'b'
  747. assert(b >= a); // 'b' is a superset of 'a'
  748. assert(a < b); // 'a' is a strict subset of 'b'
  749. assert(b > a); // 'b' is a strict superset of 'a'
  750. assert(!(a < c)); // 'a' is a not strict subset of 'c'
  751. assert(!(c > a)); // 'c' is a not strict superset of 'a'
  752. }
  753. }
  754. diverging_procedures :: proc() {
  755. // Diverging procedures may never return
  756. foo :: proc() -> ! {
  757. fmt.println("I'm a diverging procedure");
  758. }
  759. foo();
  760. }
  761. deferred_procedure_associations :: proc() {
  762. @(deferred_out=closure)
  763. open :: proc(s: string) -> bool {
  764. fmt.println(s);
  765. return true;
  766. }
  767. closure :: proc(ok: bool) {
  768. fmt.println("Goodbye?", ok);
  769. }
  770. if open("Welcome") {
  771. fmt.println("Something in the middle, mate.");
  772. }
  773. }
  774. main :: proc() {
  775. when true {
  776. general_stuff();
  777. union_type();
  778. parametric_polymorphism();
  779. threading_example();
  780. array_programming();
  781. named_proc_return_parameters();
  782. using_enum();
  783. map_type();
  784. explicit_procedure_overloading();
  785. complete_switch();
  786. cstring_example();
  787. deprecated_attribute();
  788. bit_set_type();
  789. diverging_procedures();
  790. deferred_procedure_associations();
  791. }
  792. }