demo002.odin 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. // Demo 002
  2. export "core:fmt.odin";
  3. export "core:math.odin";
  4. export "core:mem.odin";
  5. // export "game.odin"
  6. #thread_local tls_int: int;
  7. main :: proc() {
  8. // Forenotes
  9. // Semicolons are now optional
  10. // Rule for when a semicolon is expected after a statement
  11. // - If the next token is not on the same line
  12. // - if the next token is a closing brace }
  13. // - Otherwise, a semicolon is needed
  14. //
  15. // Expections:
  16. // for, if, match
  17. // if x := thing(); x < 123 {}
  18. // for i := 0; i < 123; i++ {}
  19. // Q: Should I use the new rule or go back to the old one without optional semicolons?
  20. // #thread_local - see runtime.odin and above at `tls_int`
  21. // #foreign_system_library - see win32.odin
  22. // struct_compound_literals();
  23. // enumerations();
  24. // variadic_procedures();
  25. // new_builtins();
  26. // match_statement();
  27. // namespacing();
  28. // subtyping();
  29. // tagged_unions();
  30. }
  31. struct_compound_literals :: proc() {
  32. Thing :: struct {
  33. id: int,
  34. x: f32,
  35. name: string,
  36. };
  37. {
  38. t1: Thing;
  39. t1.id = 1;
  40. t3 := Thing{};
  41. t4 := Thing{1, 2, "Fred"};
  42. // t5 := Thing{1, 2};
  43. t6 := Thing{
  44. name = "Tom",
  45. x = 23,
  46. };
  47. }
  48. }
  49. enumerations :: proc() {
  50. {
  51. Fruit :: enum {
  52. APPLE, // 0
  53. BANANA, // 1
  54. PEAR, // 2
  55. };
  56. f := Fruit.APPLE;
  57. // g12: int = Fruit.BANANA
  58. g: int = cast(int)Fruit.BANANA;
  59. // However, you can use enums are index values as _any_ integer allowed
  60. }
  61. {
  62. Fruit1 :: enum int {
  63. APPLE,
  64. BANANA,
  65. PEAR,
  66. }
  67. Fruit2 :: enum u8 {
  68. APPLE,
  69. BANANA,
  70. PEAR,
  71. }
  72. Fruit3 :: enum u8 {
  73. APPLE = 1,
  74. BANANA, // 2
  75. PEAR = 5,
  76. TOMATO, // 6
  77. }
  78. }
  79. // Q: remove the need for `type` if it's a record (struct/enum/raw_union/union)?
  80. }
  81. variadic_procedures :: proc() {
  82. print_ints :: proc(args: ..int) {
  83. for arg, i in args {
  84. if i > 0 do print(", ");
  85. print(arg);
  86. }
  87. }
  88. print_ints(); // nl()
  89. print_ints(1); nl();
  90. print_ints(1, 2, 3); nl();
  91. print_prefix_f32s :: proc(prefix: string, args: ..f32) {
  92. print(prefix);
  93. print(": ");
  94. for arg, i in args {
  95. if i > 0 do print(", ");
  96. print(arg);
  97. }
  98. }
  99. print_prefix_f32s("a"); nl();
  100. print_prefix_f32s("b", 1); nl();
  101. print_prefix_f32s("c", 1, 2, 3); nl();
  102. // Internally, the variadic procedures get allocated to an array on the stack,
  103. // and this array is passed a slice
  104. // This is first step for a `print` procedure but I do not have an `any` type
  105. // yet as this requires a few other things first - i.e. introspection
  106. // NOTE(bill): I haven't yet added the feature of expanding a slice or array into
  107. // a variadic a parameter but it's pretty trivial to add
  108. }
  109. new_builtins :: proc() {
  110. {
  111. a := new(int);
  112. b := make([]int, 12);
  113. c := make([]int, 12, 16);
  114. defer free(a);
  115. defer free(b);
  116. defer free(c);
  117. // NOTE(bill): These use the current context's allocator not the default allocator
  118. // see runtime.odin
  119. // Q: Should this be `free` rather than `free` and should I overload it for slices too?
  120. push_allocator default_allocator() {
  121. a := new(int);
  122. defer free(a);
  123. // Do whatever
  124. }
  125. }
  126. {
  127. a: int = 123;
  128. b: type_of(a) = 321;
  129. // NOTE(bill): This matches the current naming scheme
  130. // size_of
  131. // align_of
  132. // offset_of
  133. //
  134. // size_of_val
  135. // align_of_val
  136. // offset_of_val
  137. // type_of_val
  138. }
  139. {
  140. // Compile time assert
  141. COND :: true;
  142. #assert(COND);
  143. // #assert(!COND)
  144. // Runtime assert
  145. x := true;
  146. assert(x);
  147. // assert(!x);
  148. }
  149. {
  150. x: ^u32 = nil;
  151. y := x+100;
  152. z := y-x;
  153. w := slice_ptr(x, 12);
  154. t := slice_ptr(x, 12, 16);
  155. // NOTE(bill): These are here because I've removed:
  156. // pointer arithmetic
  157. // pointer indexing
  158. // pointer slicing
  159. // Reason
  160. a: [16]int;
  161. a[1] = 1;
  162. b := &a;
  163. // Auto pointer deref
  164. // consistent with record members
  165. assert(b[1] == 1);
  166. // Q: Should I add them back in at the cost of inconsitency?
  167. }
  168. {
  169. a, b := -1, 2;
  170. print(min(a, b)); nl();
  171. print(max(a, b)); nl();
  172. print(abs(a)); nl();
  173. // These work at compile time too
  174. A :: -1;
  175. B :: 2;
  176. C :: min(A, B);
  177. D :: max(A, B);
  178. E :: abs(A);
  179. print(C); nl();
  180. print(D); nl();
  181. print(E); nl();
  182. }
  183. }
  184. match_statement :: proc() {
  185. // NOTE(bill): `match` statements are similar to `switch` statements
  186. // in other languages but there are few differences
  187. {
  188. match x := 5; x {
  189. case 1: // cases must be constant expression
  190. print("1!\n");
  191. // break by default
  192. case 2:
  193. s := "2!\n"; // Each case has its own scope
  194. print(s);
  195. break; // explicit break
  196. case 3, 4: // multiple cases
  197. print("3 or 4!\n");
  198. case 5:
  199. print("5!\n");
  200. fallthrough; // explicit fallthrough
  201. case:
  202. print("default!\n");
  203. }
  204. match x := 1.5; x {
  205. case 1.5:
  206. print("1.5!\n");
  207. // break by default
  208. case TAU:
  209. print("τ!\n");
  210. case:
  211. print("default!\n");
  212. }
  213. match x := "Hello"; x {
  214. case "Hello":
  215. print("greeting\n");
  216. // break by default
  217. case "Goodbye":
  218. print("farewell\n");
  219. case:
  220. print("???\n");
  221. }
  222. a := 53;
  223. match {
  224. case a == 1:
  225. print("one\n");
  226. case a == 2:
  227. print("a couple\n");
  228. case a < 7, a == 7:
  229. print("a few\n");
  230. case a < 12: // intentional bug
  231. print("several\n");
  232. case a >= 12 && a < 100:
  233. print("dozens\n");
  234. case a >= 100 && a < 1000:
  235. print("hundreds\n");
  236. case:
  237. print("a fuck ton\n");
  238. }
  239. // Identical to this
  240. b := 53;
  241. if b == 1 {
  242. print("one\n");
  243. } else if b == 2 {
  244. print("a couple\n");
  245. } else if b < 7 || b == 7 {
  246. print("a few\n");
  247. } else if b < 12 { // intentional bug
  248. print("several\n");
  249. } else if b >= 12 && b < 100 {
  250. print("dozens\n");
  251. } else if b >= 100 && b < 1000 {
  252. print("hundreds\n");
  253. } else {
  254. print("a fuck ton\n");
  255. }
  256. // However, match statements allow for `break` and `fallthrough` unlike
  257. // an if statement
  258. }
  259. }
  260. Vector3 :: struct {x, y, z: f32}
  261. print_floats :: proc(args: ..f32) {
  262. for arg, i in args {
  263. if i > 0 do print(", ");
  264. print(arg);
  265. }
  266. println();
  267. }
  268. namespacing :: proc() {
  269. {
  270. Thing :: #type struct {
  271. x: f32,
  272. name: string,
  273. };
  274. a: Thing;
  275. a.x = 3;
  276. {
  277. Thing :: #type struct {
  278. y: int,
  279. test: bool,
  280. };
  281. b: Thing; // Uses this scope's Thing
  282. b.test = true;
  283. }
  284. }
  285. /*
  286. {
  287. Entity :: struct {
  288. Guid :: int
  289. Nested :: struct {
  290. MyInt :: int
  291. i: int
  292. }
  293. CONSTANT :: 123
  294. guid: Guid
  295. name: string
  296. pos: Vector3
  297. vel: Vector3
  298. nested: Nested
  299. }
  300. guid: Entity.Guid = Entity.CONSTANT
  301. i: Entity.Nested.MyInt
  302. {
  303. using Entity
  304. guid: Guid = CONSTANT
  305. using Nested
  306. i: MyInt
  307. }
  308. {
  309. using Entity.Nested
  310. guid: Entity.Guid = Entity.CONSTANT
  311. i: MyInt
  312. }
  313. {
  314. e: Entity
  315. using e
  316. guid = 27832
  317. name = "Bob"
  318. print(e.guid as int); nl()
  319. print(e.name); nl()
  320. }
  321. {
  322. using e: Entity
  323. guid = 78456
  324. name = "Thing"
  325. print(e.guid as int); nl()
  326. print(e.name); nl()
  327. }
  328. }
  329. {
  330. Entity :: struct {
  331. Guid :: int
  332. Nested :: struct {
  333. MyInt :: int
  334. i: int
  335. }
  336. CONSTANT :: 123
  337. guid: Guid
  338. name: string
  339. using pos: Vector3
  340. vel: Vector3
  341. using nested: ^Nested
  342. }
  343. e := Entity{nested = new(Entity.Nested)}
  344. e.x = 123
  345. e.i = Entity.CONSTANT
  346. }
  347. */
  348. {
  349. Entity :: struct {
  350. position: Vector3
  351. }
  352. print_pos_1 :: proc(entity: ^Entity) {
  353. print("print_pos_1: ");
  354. print_floats(entity.position.x, entity.position.y, entity.position.z);
  355. }
  356. print_pos_2 :: proc(entity: ^Entity) {
  357. using entity;
  358. print("print_pos_2: ");
  359. print_floats(position.x, position.y, position.z);
  360. }
  361. print_pos_3 :: proc(using entity: ^Entity) {
  362. print("print_pos_3: ");
  363. print_floats(position.x, position.y, position.z);
  364. }
  365. print_pos_4 :: proc(using entity: ^Entity) {
  366. using position;
  367. print("print_pos_4: ");
  368. print_floats(x, y, z);
  369. }
  370. e := Entity{position = Vector3{1, 2, 3}};
  371. print_pos_1(&e);
  372. print_pos_2(&e);
  373. print_pos_3(&e);
  374. print_pos_4(&e);
  375. // This is similar to C++'s `this` pointer that is implicit and only available in methods
  376. }
  377. }
  378. subtyping :: proc() {
  379. {
  380. // C way for subtyping/subclassing
  381. Entity :: struct {
  382. position: Vector3,
  383. }
  384. Frog :: struct {
  385. entity: Entity,
  386. jump_height: f32,
  387. }
  388. f: Frog;
  389. f.entity.position = Vector3{1, 2, 3};
  390. using f.entity;
  391. position = Vector3{1, 2, 3};
  392. }
  393. {
  394. // C++ way for subtyping/subclassing
  395. Entity :: struct {
  396. position: Vector3
  397. }
  398. Frog :: struct {
  399. using entity: Entity,
  400. jump_height: f32,
  401. }
  402. f: Frog;
  403. f.position = Vector3{1, 2, 3};
  404. print_pos :: proc(using entity: Entity) {
  405. print("print_pos: ");
  406. print_floats(position.x, position.y, position.z);
  407. }
  408. print_pos(f.entity);
  409. // print_pos(f);
  410. // Subtype Polymorphism
  411. }
  412. {
  413. // More than C++ way for subtyping/subclassing
  414. Entity :: struct {
  415. position: Vector3,
  416. }
  417. Frog :: struct {
  418. jump_height: f32,
  419. using entity: ^Entity, // Doesn't have to be first member!
  420. }
  421. f: Frog;
  422. f.entity = new(Entity);
  423. f.position = Vector3{1, 2, 3};
  424. print_pos :: proc(using entity: ^Entity) {
  425. print("print_pos: ");
  426. print_floats(position.x, position.y, position.z);
  427. }
  428. print_pos(f.entity);
  429. // print_pos(^f);
  430. // print_pos(f);
  431. }
  432. {
  433. // More efficient subtyping
  434. Entity :: struct {
  435. position: Vector3,
  436. }
  437. Frog :: struct {
  438. jump_height: f32,
  439. using entity: ^Entity,
  440. }
  441. MAX_ENTITES :: 64;
  442. entities: [MAX_ENTITES]Entity;
  443. entity_count := 0;
  444. next_entity :: proc(entities: []Entity, entity_count: ^int) -> ^Entity {
  445. e := &entities[entity_count^];
  446. entity_count^ += 1;
  447. return e;
  448. }
  449. f: Frog;
  450. f.entity = next_entity(entities[..], &entity_count);
  451. f.position = Vector3{3, 4, 6};
  452. using f.position;
  453. print_floats(x, y, z);
  454. }
  455. /*{
  456. // Down casting
  457. Entity :: struct {
  458. position: Vector3,
  459. }
  460. Frog :: struct {
  461. jump_height: f32,
  462. using entity: Entity,
  463. }
  464. f: Frog;
  465. f.jump_height = 564;
  466. e := ^f.entity;
  467. frog := down_cast(^Frog)e;
  468. print("down_cast: ");
  469. print(frog.jump_height); nl();
  470. // NOTE(bill): `down_cast` is unsafe and there are not check are compile time or run time
  471. // Q: Should I completely remove `down_cast` as I added it in about 30 minutes
  472. }*/
  473. {
  474. // Multiple "inheritance"/subclassing
  475. Entity :: struct {
  476. position: Vector3,
  477. }
  478. Climber :: struct {
  479. speed: f32,
  480. }
  481. Frog :: struct {
  482. using entity: Entity,
  483. using climber: Climber,
  484. }
  485. }
  486. }
  487. tagged_unions :: proc() {
  488. {
  489. Entity_Kind :: enum {
  490. INVALID,
  491. FROG,
  492. GIRAFFE,
  493. HELICOPTER,
  494. }
  495. Entity :: struct {
  496. kind: Entity_Kind
  497. using data: struct #raw_union {
  498. frog: struct {
  499. jump_height: f32,
  500. colour: u32,
  501. },
  502. giraffe: struct {
  503. neck_length: f32,
  504. spot_count: int,
  505. },
  506. helicopter: struct {
  507. blade_count: int,
  508. weight: f32,
  509. pilot_name: string,
  510. },
  511. }
  512. }
  513. e: Entity;
  514. e.kind = Entity_Kind.FROG;
  515. e.frog.jump_height = 12;
  516. f: type_of(e.frog);
  517. // But this is very unsafe and extremely cumbersome to write
  518. // In C++, I use macros to alleviate this but it's not a solution
  519. }
  520. {
  521. Frog :: struct {
  522. jump_height: f32,
  523. colour: u32,
  524. }
  525. Giraffe :: struct {
  526. neck_length: f32,
  527. spot_count: int,
  528. }
  529. Helicopter :: struct {
  530. blade_count: int,
  531. weight: f32,
  532. pilot_name: string,
  533. }
  534. Entity :: union {Frog, Giraffe, Helicopter};
  535. f1: Frog = Frog{12, 0xff9900};
  536. f2: Entity = Frog{12, 0xff9900}; // Implicit cast
  537. f3 := cast(Entity)Frog{12, 0xff9900}; // Explicit cast
  538. // f3.Frog.jump_height = 12 // There are "members" of a union
  539. e, f, g, h: Entity;
  540. f = Frog{12, 0xff9900};
  541. g = Giraffe{2.1, 23};
  542. h = Helicopter{4, 1000, "Frank"};
  543. // Requires a pointer to the union
  544. // `x` will be a pointer to type of the case
  545. match x in &f {
  546. case Frog:
  547. print("Frog!\n");
  548. print(x.jump_height); nl();
  549. // x.jump_height = 3;
  550. print(x.jump_height); nl();
  551. case Giraffe:
  552. print("Giraffe!\n");
  553. case Helicopter:
  554. print("ROFLCOPTER!\n");
  555. case:
  556. print("invalid entity\n");
  557. }
  558. // Q: Allow for a non pointer version with takes a copy instead?
  559. // Or it takes the pointer the data and not a copy
  560. // fp := cast(^Frog)^f; // Unsafe
  561. // print(fp.jump_height); nl();
  562. // Internals of a tagged union
  563. /*
  564. struct {
  565. data: [size_of_biggest_tag]u8,
  566. tag_index: int,
  567. }
  568. */
  569. // This is to allow for pointer casting if needed
  570. // Advantage over subtyping version
  571. MAX_ENTITES :: 64;
  572. entities: [MAX_ENTITES]Entity;
  573. entities[0] = Frog{};
  574. entities[1] = Helicopter{};
  575. // etc.
  576. }
  577. {
  578. // Transliteration of code from this actual compiler
  579. // Some stuff is missing
  580. Type :: struct {};
  581. Scope :: struct {};
  582. Token :: struct {};
  583. AstNode :: struct {};
  584. ExactValue :: struct {};
  585. Entity_Kind :: enum {
  586. Invalid,
  587. Constant,
  588. Variable,
  589. Using_Variable,
  590. TypeName,
  591. Procedure,
  592. Builtin,
  593. Count,
  594. }
  595. Guid :: i64;
  596. Entity :: struct {
  597. kind: Entity_Kind,
  598. guid: Guid,
  599. scope: ^Scope,
  600. token: Token,
  601. type_: ^Type,
  602. using data: struct #raw_union {
  603. Constant: struct {
  604. value: ExactValue,
  605. },
  606. Variable: struct {
  607. visited: bool, // Cycle detection
  608. used: bool, // Variable is used
  609. is_field: bool, // Is struct field
  610. anonymous: bool, // Variable is an anonymous
  611. },
  612. Using_Variable: struct {
  613. },
  614. TypeName: struct {
  615. },
  616. Procedure: struct {
  617. used: bool,
  618. },
  619. Builtin: struct {
  620. id: int,
  621. },
  622. },
  623. }
  624. // Plus all the constructing procedures that go along with them!!!!
  625. // It's a nightmare
  626. }
  627. {
  628. Type :: struct {};
  629. Scope :: struct {};
  630. Token :: struct {};
  631. AstNode :: struct {};
  632. ExactValue :: struct {};
  633. Guid :: i64;
  634. Entity_Base :: struct {
  635. }
  636. Constant :: struct {
  637. value: ExactValue,
  638. }
  639. Variable :: struct {
  640. visited: bool, // Cycle detection
  641. used: bool, // Variable is used
  642. is_field: bool, // Is struct field
  643. anonymous: bool, // Variable is an anonymous
  644. }
  645. Using_Variable :: struct {
  646. }
  647. TypeName :: struct {
  648. }
  649. Procedure :: struct {
  650. used: bool,
  651. }
  652. Builtin :: struct {
  653. id: int,
  654. }
  655. Entity :: struct {
  656. guid: Guid,
  657. scope: ^Scope,
  658. token: Token,
  659. type_: ^Type,
  660. variant: union {Constant, Variable, Using_Variable, TypeName, Procedure, Builtin},
  661. }
  662. e := Entity{
  663. variant = Variable{
  664. used = true,
  665. anonymous = false,
  666. },
  667. };
  668. // Q: Allow a "base" type to be added to a union?
  669. // Or even `using` on union to get the same properties?
  670. }
  671. {
  672. // `Raw` unions still have uses, especially for mathematic types
  673. Vector2 :: struct #raw_union {
  674. using xy_: struct { x, y: f32 },
  675. e: [2]f32,
  676. v: [vector 2]f32,
  677. }
  678. Vector3 :: struct #raw_union {
  679. using xyz_: struct { x, y, z: f32 },
  680. xy: Vector2,
  681. e: [3]f32,
  682. v: [vector 3]f32,
  683. }
  684. v2: Vector2;
  685. v2.x = 1;
  686. v2.e[0] = 1;
  687. v2.v[0] = 1;
  688. v3: Vector3;
  689. v3.x = 1;
  690. v3.e[0] = 1;
  691. v3.v[0] = 1;
  692. v3.xy.x = 1;
  693. }
  694. }
  695. nl :: proc() { println(); }