demo_backup.odin 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. import (
  2. "fmt.odin";
  3. "atomics.odin";
  4. "bits.odin";
  5. "decimal.odin";
  6. "hash.odin";
  7. "math.odin";
  8. "mem.odin";
  9. "opengl.odin";
  10. "os.odin";
  11. "raw.odin";
  12. "strconv.odin";
  13. "strings.odin";
  14. "sync.odin";
  15. "sort.odin";
  16. "types.odin";
  17. "utf8.odin";
  18. "utf16.odin";
  19. /*
  20. */
  21. )
  22. general_stuff :: proc() {
  23. // Complex numbers
  24. a := 3 + 4i;
  25. b: complex64 = 3 + 4i;
  26. c: complex128 = 3 + 4i;
  27. d := complex(2, 3);
  28. e := a / conj(a);
  29. fmt.println("(3+4i)/(3-4i) =", e);
  30. fmt.println(real(e), "+", imag(e), "i");
  31. // C-style variadic procedures
  32. foreign __llvm_core {
  33. // The variadic part allows for extra type checking too which C does not provide
  34. c_printf :: proc(fmt: ^u8, #c_vararg args: ..any) -> i32 #link_name "printf" ---;
  35. }
  36. str := "%d\n\x00";
  37. // c_printf(&str[0], i32(789456123));
  38. Foo :: struct {
  39. x: int;
  40. y: f32;
  41. z: string;
  42. }
  43. foo := Foo{123, 0.513, "A string"};
  44. x, y, z := expand_to_tuple(foo);
  45. fmt.println(x, y, z);
  46. #assert(type_of(x) == int);
  47. #assert(type_of(y) == f32);
  48. #assert(type_of(z) == string);
  49. // By default, all variables are zeroed
  50. // This can be overridden with the "uninitialized value"
  51. // This is similar to `nil` but applied to everything
  52. undef_int: int = ---;
  53. // Context system is now implemented using Implicit Parameter Passing (IPP)
  54. // The previous implementation was Thread Local Storage (TLS)
  55. // IPP has the advantage that it works on systems without TLS and that you can
  56. // link the context to the stack frame and thus look at previous contexts
  57. //
  58. // It does mean that a pointer is implicitly passed procedures with the default
  59. // Odin calling convention (#cc_odin)
  60. // This can be overridden with something like #cc_contextless or #cc_c if performance
  61. // is worried about
  62. }
  63. foreign_blocks :: proc() {
  64. // See sys/windows.odin
  65. }
  66. default_arguments :: proc() {
  67. hello :: proc(a: int = 9, b: int = 9) do fmt.printf("a is %d; b is %d\n", a, b);
  68. fmt.println("\nTesting default arguments:");
  69. hello(1, 2);
  70. hello(1);
  71. hello();
  72. }
  73. named_arguments :: proc() {
  74. Colour :: enum {
  75. Red,
  76. Orange,
  77. Yellow,
  78. Green,
  79. Blue,
  80. Octarine,
  81. };
  82. using Colour;
  83. make_character :: proc(name, catch_phrase: string, favourite_colour, least_favourite_colour: Colour) {
  84. fmt.println();
  85. fmt.printf("My name is %v and I like %v. %v\n", name, favourite_colour, catch_phrase);
  86. }
  87. make_character("Frank", "¡Ay, caramba!", Blue, Green);
  88. // As the procedures have more and more parameters, it is very easy
  89. // to get many of the arguments in the wrong order especialy if the
  90. // types are the same
  91. make_character("¡Ay, caramba!", "Frank", Green, Blue);
  92. // Named arguments help to disambiguate this problem
  93. make_character(catch_phrase = "¡Ay, caramba!", name = "Frank",
  94. least_favourite_colour = Green, favourite_colour = Blue);
  95. // The named arguments can be specifed in any order.
  96. make_character(favourite_colour = Octarine, catch_phrase = "U wot m8!",
  97. least_favourite_colour = Green, name = "Dennis");
  98. // NOTE: You cannot mix named arguments with normal values
  99. /*
  100. make_character("Dennis",
  101. favourite_colour = Octarine, catch_phrase = "U wot m8!",
  102. least_favourite_colour = Green);
  103. */
  104. // Named arguments can also aid with default arguments
  105. numerous_things :: proc(s: string, a := 1, b := 2, c := 3.14,
  106. d := "The Best String!", e := false, f := 10.3/3.1, g := false) {
  107. g_str := g ? "true" : "false";
  108. fmt.printf("How many?! %s: %v\n", s, g_str);
  109. }
  110. numerous_things("First");
  111. numerous_things(s = "Second", g = true);
  112. // Default values can be placed anywhere, not just at the end like in other languages
  113. weird :: proc(pre: string, mid: int = 0, post: string) {
  114. fmt.println(pre, mid, post);
  115. }
  116. weird("How many things", 42, "huh?");
  117. weird(pre = "Prefix", post = "Pat");
  118. }
  119. default_return_values :: proc() {
  120. foo :: proc(x: int) -> (first: string = "Hellope", second := "world!") {
  121. match x {
  122. case 0: return;
  123. case 1: return "Goodbye";
  124. case 2: return "Goodbye", "cruel world..";
  125. case 3: return second = "cruel world..", first = "Goodbye";
  126. }
  127. return second = "my old friend.";
  128. }
  129. fmt.printf("%s %s\n", foo(0));
  130. fmt.printf("%s %s\n", foo(1));
  131. fmt.printf("%s %s\n", foo(2));
  132. fmt.printf("%s %s\n", foo(3));
  133. fmt.printf("%s %s\n", foo(4));
  134. fmt.println();
  135. // A more "real" example
  136. Error :: enum {
  137. None,
  138. WhyTheNumberThree,
  139. TenIsTooBig,
  140. };
  141. Entity :: struct {
  142. name: string;
  143. id: u32;
  144. }
  145. some_thing :: proc(input: int) -> (result: ^Entity = nil, err := Error.None) {
  146. match {
  147. case input == 3: return err = Error.WhyTheNumberThree;
  148. case input >= 10: return err = Error.TenIsTooBig;
  149. }
  150. e := new(Entity);
  151. e.id = u32(input);
  152. return result = e;
  153. }
  154. }
  155. call_location :: proc() {
  156. amazing :: proc(n: int, using loc := #caller_location) {
  157. fmt.printf("%s(%d:%d) just asked to do something amazing.\n",
  158. fully_pathed_filename, line, column);
  159. fmt.printf("Normal -> %d\n", n);
  160. fmt.printf("Amazing -> %d\n", n+1);
  161. fmt.println();
  162. }
  163. loc := #location(main);
  164. fmt.println("`main` is located at", loc);
  165. fmt.println("This line is located at", #location());
  166. fmt.println();
  167. amazing(3);
  168. amazing(4, #location(call_location));
  169. // See _preload.odin for the implementations of `assert` and `panic`
  170. }
  171. explicit_parametric_polymorphic_procedures :: proc() {
  172. // This is how `new` is actually implemented, see _preload.odin
  173. alloc_type :: proc(T: type) -> ^T do return cast(^T)alloc(size_of(T), align_of(T));
  174. int_ptr := alloc_type(int);
  175. defer free(int_ptr);
  176. int_ptr^ = 137;
  177. fmt.println(int_ptr, int_ptr^);
  178. // Named arguments work too!
  179. another_ptr := alloc_type(T = f32);
  180. defer free(another_ptr);
  181. add :: proc(T: type, args: ..T) -> T {
  182. res: T;
  183. for arg in args do res += arg;
  184. return res;
  185. }
  186. fmt.println("add =", add(int, 1, 2, 3, 4, 5, 6));
  187. swap :: proc(T: type, a, b: ^T) {
  188. tmp := a^;
  189. a^ = b^;
  190. b^ = tmp;
  191. }
  192. a, b: int = 3, 4;
  193. fmt.println("Pre-swap:", a, b);
  194. swap(int, &a, &b);
  195. fmt.println("Post-swap:", a, b);
  196. a, b = b, a; // Or use this syntax for this silly example case
  197. Vector2 :: struct {x, y: f32;};
  198. {
  199. // A more complicated example using subtyping
  200. // Something like this could be used in a game
  201. Entity :: struct {
  202. using position: Vector2;
  203. flags: u64;
  204. id: u64;
  205. derived: any;
  206. }
  207. Rock :: struct {
  208. using entity: Entity;
  209. heavy: bool;
  210. }
  211. Door :: struct {
  212. using entity: Entity;
  213. open: bool;
  214. }
  215. Monster :: struct {
  216. using entity: Entity;
  217. is_robot: bool;
  218. is_zombie: bool;
  219. }
  220. new_entity :: proc(T: type, x, y: f32) -> ^T {
  221. result := new(T);
  222. result.derived = result^;
  223. result.x = x;
  224. result.y = y;
  225. return result;
  226. }
  227. entities: [dynamic]^Entity;
  228. rock := new_entity(Rock, 3, 5);
  229. // Named arguments work too!
  230. door := new_entity(T = Door, x = 3, y = 6);
  231. // And named arguments can be any order
  232. monster := new_entity(
  233. y = 1,
  234. x = 2,
  235. T = Monster,
  236. );
  237. append(&entities, rock, door, monster);
  238. fmt.println("Subtyping");
  239. for entity in entities {
  240. match e in entity.derived {
  241. case Rock: fmt.println("Rock", e.x, e.y);
  242. case Door: fmt.println("Door", e.x, e.y);
  243. case Monster: fmt.println("Monster", e.x, e.y);
  244. }
  245. }
  246. }
  247. {
  248. Entity :: struct {
  249. using position: Vector2;
  250. flags: u64;
  251. id: u64;
  252. variant: union { Rock, Door, Monster };
  253. }
  254. Rock :: struct {
  255. using entity: ^Entity;
  256. heavy: bool;
  257. }
  258. Door :: struct {
  259. using entity: ^Entity;
  260. open: bool;
  261. }
  262. Monster :: struct {
  263. using entity: ^Entity;
  264. is_robot: bool;
  265. is_zombie: bool;
  266. }
  267. new_entity :: proc(T: type, x, y: f32) -> ^T {
  268. result := new(Entity);
  269. result.variant = T{entity = result};
  270. result.x = x;
  271. result.y = y;
  272. return cast(^T)&result.variant;
  273. }
  274. entities: [dynamic]^Entity;
  275. rock := new_entity(Rock, 3, 5);
  276. // Named arguments work too!
  277. door := new_entity(T = Door, x = 3, y = 6);
  278. // And named arguments can be any order
  279. monster := new_entity(
  280. y = 1,
  281. x = 2,
  282. T = Monster,
  283. );
  284. append(&entities, rock, door, monster);
  285. fmt.println("Union");
  286. for entity in entities {
  287. match e in entity.variant {
  288. case Rock: fmt.println("Rock", e.x, e.y);
  289. case Door: fmt.println("Door", e.x, e.y);
  290. case Monster: fmt.println("Monster", e.x, e.y);
  291. }
  292. }
  293. }
  294. }
  295. implicit_polymorphic_assignment :: proc() {
  296. yep :: proc(p: proc(x: int)) {
  297. p(123);
  298. }
  299. frank :: proc(x: $T) do fmt.println("frank ->", x);
  300. tim :: proc(x, y: $T) do fmt.println("tim ->", x, y);
  301. yep(frank);
  302. // yep(tim);
  303. }
  304. main :: proc() {
  305. /*
  306. foo :: proc(x: i64, y: f32) do fmt.println("#1", x, y);
  307. foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y);
  308. foo :: proc(x: type) do fmt.println("#3", type_info(x));
  309. f :: foo;
  310. f(y = 3785.1546, x = 123);
  311. f(x = int, y = 897.513);
  312. f(x = f32);
  313. general_stuff();
  314. foreign_blocks();
  315. default_arguments();
  316. named_arguments();
  317. default_return_values();
  318. call_location();
  319. explicit_parametric_polymorphic_procedures();
  320. implicit_polymorphic_assignment();
  321. // Command line argument(s)!
  322. // -opt=0,1,2,3
  323. */
  324. /*
  325. program := "+ + * - /";
  326. accumulator := 0;
  327. for token in program {
  328. match token {
  329. case '+': accumulator += 1;
  330. case '-': accumulator -= 1;
  331. case '*': accumulator *= 2;
  332. case '/': accumulator /= 2;
  333. case: // Ignore everything else
  334. }
  335. }
  336. fmt.printf("The program \"%s\" calculates the value %d\n",
  337. program, accumulator);
  338. */
  339. }