demo006.odin 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. // import "core:atomic.odin";
  2. import "core:hash.odin";
  3. import "core:mem.odin";
  4. import "core:opengl.odin";
  5. import "core:strconv.odin";
  6. import "core:sync.odin";
  7. import win32 "core:sys/windows.odin";
  8. import "core:fmt.odin";
  9. import "core:os.odin";
  10. import "core:math.odin";
  11. main :: proc() {
  12. when true {
  13. /*
  14. Added:
  15. * Unexported entities and fields using an underscore prefix
  16. - See `sync.odin` and explain
  17. Removed:
  18. * Maybe/option types
  19. * Remove `type` keyword and other "reserved" keywords
  20. * ..< and .. removed and replace with .. (half-closed range)
  21. Changed:
  22. * `#assert` and `assert` return the value of the condition for semantic reasons
  23. * thread_local -> #thread_local
  24. * #include -> #load
  25. * Files only get checked if they are actually used
  26. * match x in y {} // For type match statements
  27. * Version numbering now starts from 0.1.0 and uses the convention:
  28. - major.minor.patch
  29. * Core library additions to Windows specific stuff
  30. */
  31. {
  32. Fruit :: enum {
  33. APPLE,
  34. BANANA,
  35. COCONUT,
  36. }
  37. fmt.println(Fruit.names);
  38. }
  39. {
  40. A :: struct {x, y: f32};
  41. B :: struct #align 16 {x, y: f32};
  42. fmt.println("align_of(A) =", align_of(A));
  43. fmt.println("align_of(B) =", align_of(B));
  44. }
  45. {
  46. // Removal of ..< and ..
  47. for i in 0..16 {
  48. }
  49. // Is similar to
  50. for i := 0; i < 16; i += 1 {
  51. }
  52. }
  53. {
  54. thing: for i in 0..10 {
  55. for j in i+1..10 {
  56. if j == 2 {
  57. fmt.println(i, j);
  58. continue thing;
  59. }
  60. if j == 3 {
  61. break thing;
  62. }
  63. }
  64. }
  65. // Works with, `for`, `for in`, `match`, `match in`
  66. // NOTE(bill): This solves most of the problems I need `goto` for
  67. }
  68. {
  69. t := type_info_of(int);
  70. match i in t.variant {
  71. case Type_Info_Integer, Type_Info_Float:
  72. fmt.println("It's a number");
  73. }
  74. x: any = 123;
  75. foo: match i in x {
  76. case int, f32:
  77. fmt.println("It's an int or f32");
  78. break foo;
  79. }
  80. }
  81. {
  82. cond := true;
  83. x: int;
  84. if cond {
  85. x = 3;
  86. } else {
  87. x = 4;
  88. }
  89. // Ternary operator
  90. y := cond ? 3 : 4;
  91. FOO :: true ? 123 : 432; // Constant ternary expression
  92. fmt.println("Ternary values:", y, FOO);
  93. }
  94. {
  95. // Slices now store a capacity
  96. buf: [256]u8;
  97. s: []u8;
  98. s = buf[..0]; // == buf[0..0];
  99. fmt.println("count =", len(s));
  100. fmt.println("capacity =", cap(s));
  101. append(&s, 1, 2, 3);
  102. fmt.println(s);
  103. s = buf[1..2..3];
  104. fmt.println("count =", len(s));
  105. fmt.println("capacity =", cap(s));
  106. fmt.println(s);
  107. clear(&s); // Sets count to zero
  108. }
  109. {
  110. Foo :: struct {
  111. x, y, z: f32,
  112. ok: bool,
  113. flags: u32,
  114. }
  115. foo_array: [256]Foo;
  116. foo_as_bytes: []u8 = mem.slice_to_bytes(foo_array[..]);
  117. // Useful for things like
  118. // os.write(handle, foo_as_bytes);
  119. foo_slice := mem.slice_ptr(cast(^Foo)&foo_as_bytes[0], len(foo_as_bytes)/size_of(Foo), cap(foo_as_bytes)/size_of(Foo));
  120. // Question: Should there be a bytes_to_slice procedure or is it clearer to do this even if it is error prone?
  121. // And if so what would the syntax be?
  122. // slice_transmute([]Foo, foo_as_bytes);
  123. }
  124. {
  125. Vec3 :: [vector 3]f32;
  126. x := Vec3{1, 2, 3};
  127. y := Vec3{4, 5, 6};
  128. fmt.println(x < y);
  129. fmt.println(x + y);
  130. fmt.println(x - y);
  131. fmt.println(x * y);
  132. fmt.println(x / y);
  133. for i in x {
  134. fmt.println(i);
  135. }
  136. #assert(size_of([vector 7]bool) >= size_of([7]bool));
  137. #assert(size_of([vector 7]i32) >= size_of([7]i32));
  138. // align_of([vector 7]i32) != align_of([7]i32) // this may be the case
  139. }
  140. {
  141. // fmt.* changes
  142. // bprint* returns `string`
  143. data: [256]u8;
  144. str := fmt.bprintf(data[..], "Hellope %d %s %c", 123, "others", '!');
  145. fmt.println(str);
  146. }
  147. {
  148. x: [dynamic]f64;
  149. reserve(&x, 16);
  150. defer free(x); // `free` is overloaded for numerous types
  151. // Number literals can have underscores in them for readability
  152. append(&x, 2_000_000.500_000, 123, 5, 7); // variadic append
  153. for p, i in x {
  154. if i > 0 { fmt.print(", "); }
  155. fmt.print(p);
  156. }
  157. fmt.println();
  158. }
  159. {
  160. // Dynamic array "literals"
  161. x := [dynamic]f64{2_000_000.500_000, 3, 5, 7};
  162. defer free(x);
  163. fmt.println(x); // fmt.print* supports printing of dynamic types
  164. clear(&x);
  165. fmt.println(x);
  166. }
  167. {
  168. m: map[f32]int;
  169. reserve(&m, 16);
  170. defer free(m);
  171. m[1.0] = 1278;
  172. m[2.0] = 7643;
  173. m[3.0] = 564;
  174. _, ok := m[3.0];
  175. c := m[3.0];
  176. assert(ok && c == 564);
  177. fmt.print("map[");
  178. i := 0;
  179. for val, key in m {
  180. if i > 0 {
  181. fmt.print(", ");
  182. }
  183. fmt.printf("%v=%v", key, val);
  184. i += 1;
  185. }
  186. fmt.println("]");
  187. }
  188. {
  189. m := map[string]u32{
  190. "a" = 56,
  191. "b" = 13453,
  192. "c" = 7654,
  193. };
  194. defer free(m);
  195. c := m["c"];
  196. _, ok := m["c"];
  197. assert(ok && c == 7654);
  198. fmt.println(m);
  199. delete(&m, "c"); // deletes entry with key "c"
  200. _, found := m["c"];
  201. assert(!found);
  202. fmt.println(m);
  203. clear(&m);
  204. fmt.println(m);
  205. // NOTE: Fixed size maps are planned but we have not yet implemented
  206. // them as we have had no need for them as of yet
  207. }
  208. {
  209. Vector3 :: struct{x, y, z: f32};
  210. Quaternion :: struct{x, y, z, w: f32};
  211. // Variants
  212. Frog :: struct {
  213. ribbit_volume: f32,
  214. jump_height: f32,
  215. }
  216. Door :: struct {
  217. openness: f32,
  218. }
  219. Map :: struct {
  220. width, height: f32,
  221. place_positions: []Vector3,
  222. place_names: []string,
  223. }
  224. Entity :: struct {
  225. // Common Fields
  226. id: u64,
  227. name: string,
  228. using position: Vector3,
  229. orientation: Quaternion,
  230. flags: u32,
  231. variant: union { Frog, Door, Map },
  232. }
  233. entity: Entity;
  234. entity.id = 1337;
  235. // implicit conversion from variant to base type
  236. entity.variant = Frog{
  237. ribbit_volume = 0.5,
  238. jump_height = 2.1,
  239. /*other data */
  240. };
  241. entity.name = "Frank";
  242. entity.position = Vector3{1, 4, 9};
  243. match e in entity.variant {
  244. case Frog:
  245. fmt.println("Ribbit");
  246. case Door:
  247. fmt.println("Creak");
  248. case Map:
  249. fmt.println("Rustle");
  250. case:
  251. fmt.println("Just a normal entity");
  252. }
  253. if frog, ok := entity.variant.(Frog); ok {
  254. fmt.printf("The frog jumps %f feet high at %v\n", frog.jump_height, entity.position);
  255. }
  256. // Panics if not the correct type
  257. frog: Frog;
  258. frog = entity.variant.(Frog);
  259. frog, _ = entity.variant.(Frog); // ignore error and force cast
  260. }
  261. }
  262. }