demo002.odin 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. // Demo 002
  2. #load "basic.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 :: type 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 :: type enum {
  51. APPLE, // 0
  52. BANANA, // 1
  53. PEAR, // 2
  54. }
  55. f := Fruit.APPLE
  56. // g12: int = Fruit.BANANA
  57. g: int = Fruit.BANANA as int
  58. // However, you can use enums are index values as _any_ integer allowed
  59. }
  60. {
  61. Fruit1 :: type enum int {
  62. APPLE,
  63. BANANA,
  64. PEAR,
  65. }
  66. Fruit2 :: type enum u8 {
  67. APPLE,
  68. BANANA,
  69. PEAR,
  70. }
  71. Fruit3 :: type 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 i := 0; i < len(args); i++ {
  83. if i > 0 {
  84. print_string(", ")
  85. }
  86. print_int(args[i])
  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_string(prefix)
  94. print_string(": ")
  95. for i := 0; i < len(args); i++ {
  96. if i > 0 {
  97. print_string(", ")
  98. }
  99. print_f32(args[i])
  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 := new_slice(int, 12)
  116. c := new_slice(int, 12, 16)
  117. defer delete(a)
  118. defer delete(b)
  119. defer delete(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 `delete` 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 delete(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 = null;
  158. y := ptr_offset(x, 100)
  159. z := ptr_sub(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_int(min(a, b)); nl()
  178. print_int(max(a, b)); nl()
  179. print_int(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_int(C); nl()
  187. print_int(D); nl()
  188. print_int(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_string("1!\n")
  198. // break by default
  199. case 2:
  200. s := "2!\n"; // Each case has its own scope
  201. print_string(s)
  202. break // explicit break
  203. case 3, 4: // multiple cases
  204. print_string("3 or 4!\n")
  205. case 5:
  206. print_string("5!\n")
  207. fallthrough // explicit fallthrough
  208. default:
  209. print_string("default!\n")
  210. }
  211. match x := 1.5; x {
  212. case 1.5:
  213. print_string("1.5!\n")
  214. // break by default
  215. case MATH_TAU:
  216. print_string("τ!\n")
  217. default:
  218. print_string("default!\n")
  219. }
  220. match x := "Hello"; x {
  221. case "Hello":
  222. print_string("greeting\n")
  223. // break by default
  224. case "Goodbye":
  225. print_string("farewell\n")
  226. default:
  227. print_string("???\n")
  228. }
  229. a := 53
  230. match {
  231. case a == 1:
  232. print_string("one\n")
  233. case a == 2:
  234. print_string("a couple\n")
  235. case a < 7, a == 7:
  236. print_string("a few\n")
  237. case a < 12: // intentional bug
  238. print_string("several\n")
  239. case a >= 12 && a < 100:
  240. print_string("dozens\n")
  241. case a >= 100 && a < 1000:
  242. print_string("hundreds\n")
  243. default:
  244. print_string("a fuck ton\n")
  245. }
  246. // Identical to this
  247. b := 53
  248. if b == 1 {
  249. print_string("one\n")
  250. } else if b == 2 {
  251. print_string("a couple\n")
  252. } else if b < 7 || b == 7 {
  253. print_string("a few\n")
  254. } else if b < 12 { // intentional bug
  255. print_string("several\n")
  256. } else if b >= 12 && b < 100 {
  257. print_string("dozens\n")
  258. } else if b >= 100 && b < 1000 {
  259. print_string("hundreds\n")
  260. } else {
  261. print_string("a fuck ton\n")
  262. }
  263. // However, match statements allow for `break` and `fallthrough` unlike
  264. // an if statement
  265. }
  266. }
  267. Vector3 :: type struct {
  268. x, y, z: f32
  269. }
  270. print_floats :: proc(args: ..f32) {
  271. for i := 0; i < len(args); i++ {
  272. if i > 0 {
  273. print_string(", ")
  274. }
  275. print_f32(args[i])
  276. }
  277. print_nl()
  278. }
  279. namespacing :: proc() {
  280. {
  281. Thing :: type struct {
  282. x: f32
  283. name: string
  284. }
  285. a: Thing
  286. a.x = 3
  287. {
  288. Thing :: type struct {
  289. y: int
  290. test: bool
  291. }
  292. b: Thing // Uses this scope's Thing
  293. b.test = true
  294. }
  295. }
  296. {
  297. Entity :: type struct {
  298. Guid :: type int
  299. Nested :: type struct {
  300. MyInt :: type int
  301. i: int
  302. }
  303. CONSTANT :: 123
  304. guid: Guid
  305. name: string
  306. pos: Vector3
  307. vel: Vector3
  308. nested: Nested
  309. }
  310. guid: Entity.Guid = Entity.CONSTANT
  311. i: Entity.Nested.MyInt
  312. {
  313. using Entity
  314. guid: Guid = CONSTANT
  315. using Nested
  316. i: MyInt
  317. }
  318. {
  319. using Entity.Nested
  320. guid: Entity.Guid = Entity.CONSTANT
  321. i: MyInt
  322. }
  323. {
  324. e: Entity
  325. using e
  326. guid = 27832
  327. name = "Bob"
  328. print_int(e.guid as int); nl()
  329. print_string(e.name); nl()
  330. }
  331. {
  332. using e: Entity
  333. guid = 78456
  334. name = "Thing"
  335. print_int(e.guid as int); nl()
  336. print_string(e.name); nl()
  337. }
  338. }
  339. {
  340. Entity :: type struct {
  341. Guid :: type int
  342. Nested :: type struct {
  343. MyInt :: type int
  344. i: int
  345. }
  346. CONSTANT :: 123
  347. guid: Guid
  348. name: string
  349. using pos: Vector3
  350. vel: Vector3
  351. using nested: ^Nested
  352. }
  353. e := Entity{nested = new(Entity.Nested)}
  354. e.x = 123
  355. e.i = Entity.CONSTANT
  356. }
  357. {
  358. Entity :: type struct {
  359. position: Vector3
  360. }
  361. print_pos_1 :: proc(entity: ^Entity) {
  362. print_string("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_string("print_pos_2: ")
  368. print_floats(position.x, position.y, position.z)
  369. }
  370. print_pos_3 :: proc(using entity: ^Entity) {
  371. print_string("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_string("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 :: type struct {
  391. position: Vector3
  392. }
  393. Frog :: type 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 :: type struct {
  405. position: Vector3
  406. }
  407. Frog :: type 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_string("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 :: type struct {
  424. position: Vector3
  425. }
  426. Frog :: type 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_string("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 :: type struct {
  444. position: Vector3
  445. }
  446. Frog :: type 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 :: type struct {
  467. position: Vector3
  468. }
  469. Frog :: type struct {
  470. jump_height: f32
  471. using entity: Entity
  472. }
  473. f: Frog
  474. f.jump_height = 564
  475. e := ^f.entity
  476. frog := e down_cast ^Frog
  477. print_string("down_cast: ")
  478. print_f32(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 :: type struct {
  485. position: Vector3
  486. }
  487. Climber :: type struct {
  488. speed: f32
  489. }
  490. Frog :: type struct {
  491. using entity: Entity
  492. using climber: Climber
  493. }
  494. }
  495. }
  496. tagged_unions :: proc() {
  497. {
  498. EntityKind :: type enum {
  499. INVALID,
  500. FROG,
  501. GIRAFFE,
  502. HELICOPTER,
  503. }
  504. Entity :: type 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 :: type union {
  531. Frog: struct {
  532. jump_height: f32
  533. colour: u32
  534. }
  535. Giraffe: struct {
  536. neck_length: f32
  537. spot_count: int
  538. }
  539. Helicopter: struct {
  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 := Frog{12, 0xff9900} as Entity // 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 type x : ^f {
  557. case Frog:
  558. print_string("Frog!\n")
  559. print_f32(x.jump_height); nl()
  560. x.jump_height = 3
  561. print_f32(x.jump_height); nl()
  562. case Giraffe:
  563. print_string("Giraffe!\n")
  564. case Helicopter:
  565. print_string("ROFLCOPTER!\n")
  566. default:
  567. print_string("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 := ^f as ^Frog // Unsafe
  572. print_f32(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 :: type struct {}
  592. Scope :: type struct {}
  593. Token :: type struct {}
  594. AstNode :: type struct {}
  595. ExactValue :: type struct {}
  596. EntityKind :: type enum {
  597. Invalid,
  598. Constant,
  599. Variable,
  600. UsingVariable,
  601. TypeName,
  602. Procedure,
  603. Builtin,
  604. Count,
  605. }
  606. Entity :: type struct {
  607. Guid :: type i64
  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 :: type struct {}
  640. Scope :: type struct {}
  641. Token :: type struct {}
  642. AstNode :: type struct {}
  643. ExactValue :: type struct {}
  644. Entity :: type union {
  645. Base :: type struct {
  646. Guid :: type i64
  647. guid: Guid
  648. scope: ^Scope
  649. token: Token
  650. type_: ^Type
  651. }
  652. Constant: struct {
  653. using base: Base
  654. value: ExactValue
  655. }
  656. Variable: struct {
  657. using base: Base
  658. visited: bool // Cycle detection
  659. used: bool // Variable is used
  660. is_field: bool // Is struct field
  661. anonymous: bool // Variable is an anonymous
  662. }
  663. UsingVariable: struct {
  664. using base: Base
  665. }
  666. TypeName: struct {
  667. using base: Base
  668. }
  669. Procedure: struct {
  670. using base: Base
  671. used: bool
  672. }
  673. Builtin: struct {
  674. using base: Base
  675. id: int
  676. }
  677. }
  678. using Entity
  679. e: Entity
  680. e = Variable{
  681. base = Base{},
  682. used = true,
  683. anonymous = false,
  684. }
  685. // Q: Allow a "base" type to be added to a union?
  686. // Or even `using` on union to get the same properties?
  687. }
  688. {
  689. // `Raw` unions still have uses, especially for mathematic types
  690. Vector2 :: type raw_union {
  691. using xy_: struct { x, y: f32 }
  692. e: [2]f32
  693. v: {2}f32
  694. }
  695. Vector3 :: type raw_union {
  696. using xyz_: struct { x, y, z: f32 }
  697. xy: Vector2
  698. e: [3]f32
  699. v: {3}f32
  700. }
  701. v2: Vector2
  702. v2.x = 1
  703. v2.e[0] = 1
  704. v2.v[0] = 1
  705. v3: Vector3
  706. v3.x = 1
  707. v3.e[0] = 1
  708. v3.v[0] = 1
  709. v3.xy.x = 1
  710. }
  711. }
  712. nl :: proc() { print_nl() }