demo002.odin 15 KB

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