aboutsummaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2023-03-28 15:14:02 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2023-03-28 15:14:02 +0200
commit3c493194c99f01ec6f3f5f8cde5ee7cba49c671d (patch)
tree3be45a0ae3897f2b2a05432ad547693f2f9c52bd /misc
parent692764aad334aa99e7dafd117d14b9a331a13e22 (diff)
Remove old deprecated demos
They're so outdated they'll likely lead to confusion now.
Diffstat (limited to 'misc')
-rw-r--r--misc/old_demos/demo001.odin337
-rw-r--r--misc/old_demos/demo002.odin879
-rw-r--r--misc/old_demos/demo004.odin66
-rw-r--r--misc/old_demos/demo005.odin283
-rw-r--r--misc/old_demos/demo006.odin310
-rw-r--r--misc/old_demos/demo007.odin570
-rw-r--r--misc/old_demos/demo008.odin778
-rw-r--r--misc/old_demos/old_runtime.odin412
-rw-r--r--misc/old_stuff/demo_backup.odin430
9 files changed, 0 insertions, 4065 deletions
diff --git a/misc/old_demos/demo001.odin b/misc/old_demos/demo001.odin
deleted file mode 100644
index a3aea1cb7..000000000
--- a/misc/old_demos/demo001.odin
+++ /dev/null
@@ -1,337 +0,0 @@
-import "core:fmt.odin";
-import "core:os.odin";
-import "core:mem.odin";
-// import "http_test.odin" as ht;
-// import "game.odin" as game;
-// import "punity.odin" as pn;
-
-main :: proc() {
- struct_padding();
- bounds_checking();
- type_introspection();
- any_type();
- crazy_introspection();
- namespaces_and_files();
- miscellany();
-
- /*
- ht.run();
- game.run();
- {
- init :: proc(c: ^pn.Core) {}
- step :: proc(c: ^pn.Core) {}
-
- pn.run(init, step);
- }
- */
-}
-
-struct_padding :: proc() {
- {
- A :: struct {
- a: u8,
- b: u32,
- c: u16,
- }
-
- B :: struct {
- a: [7]u8,
- b: [3]u16,
- c: u8,
- d: u16,
- }
-
- fmt.println("size_of(A):", size_of(A));
- fmt.println("size_of(B):", size_of(B));
-
- // n.b. http://cbloomrants.blogspot.co.uk/2012/07/07-23-12-structs-are-not-what-you-want.html
- }
- {
- A :: struct #ordered {
- a: u8,
- b: u32,
- c: u16,
- }
-
- B :: struct #ordered {
- a: [7]u8,
- b: [3]u16,
- c: u8,
- d: u16,
- }
-
- fmt.println("size_of(A):", size_of(A));
- fmt.println("size_of(B):", size_of(B));
-
- // C-style structure layout
- }
- {
- A :: struct #packed {
- a: u8,
- b: u32,
- c: u16,
- }
-
- B :: struct #packed {
- a: [7]u8,
- b: [3]u16,
- c: u8,
- d: u16,
- }
-
- fmt.println("size_of(A):", size_of(A));
- fmt.println("size_of(B):", size_of(B));
-
- // Useful for explicit layout
- }
-
- // Member sorting by priority
- // Alignment desc.
- // Size desc.
- // source order asc.
-
- /*
- A :: struct {
- a: u8
- b: u32
- c: u16
- }
-
- B :: struct {
- a: [7]u8
- b: [3]u16
- c: u8
- d: u16
- }
-
- Equivalent too
-
- A :: struct #ordered {
- b: u32
- c: u16
- a: u8
- }
-
- B :: struct #ordered {
- b: [3]u16
- d: u16
- a: [7]u8
- c: u8
- }
- */
-}
-
-bounds_checking :: proc() {
- x: [4]int;
- // x[-1] = 0; // Compile Time
- // x[4] = 0; // Compile Time
-
- {
- a, b := -1, 4;
- // x[a] = 0; // Runtime Time
- // x[b] = 0; // Runtime Time
- }
-
- // Works for arrays, strings, slices, and related procedures & operations
-
- {
- base: [10]int;
- s := base[2..6];
- a, b := -1, 6;
-
- #no_bounds_check {
- s[a] = 0;
- // #bounds_check s[b] = 0;
- }
-
- #no_bounds_check
- if s[a] == 0 {
- // Do whatever
- }
-
- // Bounds checking can be toggled explicit
- // on a per statement basis.
- // _any statement_
- }
-}
-
-type_introspection :: proc() {
- {
- info: ^Type_Info;
- x: int;
-
- info = type_info_of(int); // by type
- info = type_info_of(x); // by value
- // See: runtime.odin
-
- match i in info.variant {
- case Type_Info_Integer:
- fmt.println("integer!");
- case Type_Info_Float:
- fmt.println("float!");
- case:
- fmt.println("potato!");
- }
-
- // Unsafe cast
- integer_info := cast(^Type_Info_Integer)cast(rawptr)info;
- }
-
- {
- Vector2 :: struct { x, y: f32 }
- Vector3 :: struct { x, y, z: f32 }
-
- v1: Vector2;
- v2: Vector3;
- v3: Vector3;
-
- t1 := type_info_of(v1);
- t2 := type_info_of(v2);
- t3 := type_info_of(v3);
-
- fmt.println();
- fmt.print("Type of v1 is:\n\t", t1);
-
- fmt.println();
- fmt.print("Type of v2 is:\n\t", t2);
-
- fmt.println("\n");
- fmt.println("t1 == t2:", t1 == t2);
- fmt.println("t2 == t3:", t2 == t3);
- }
-}
-
-any_type :: proc() {
- a: any;
-
- x: int = 123;
- y: f64 = 6.28;
- z: string = "Yo-Yo Ma";
- // All types can be implicit cast to `any`
- a = x;
- a = y;
- a = z;
- a = a; // This the "identity" type, it doesn't get converted
-
- a = 123; // Literals are copied onto the stack first
-
- // any has two members
- // data - rawptr to the data
- // type_info - pointer to the type info
-
- fmt.println(x, y, z);
- // See: fmt.odin
- // For variadic any procedures in action
-}
-
-crazy_introspection :: proc() {
- {
- Fruit :: enum {
- APPLE,
- BANANA,
- GRAPE,
- MELON,
- PEACH,
- TOMATO,
- }
-
- s: string;
- // s = enum_to_string(Fruit.PEACH);
- fmt.println(s);
-
- f := Fruit.GRAPE;
- // s = enum_to_string(f);
- fmt.println(s);
-
- fmt.println(f);
- // See: runtime.odin
- }
-
-
- {
- // NOTE(bill): This is not safe code and I would not recommend this at all
- // I'd recommend you use `match type` to get the subtype rather than
- // casting pointers
-
- Fruit :: enum {
- APPLE,
- BANANA,
- GRAPE,
- MELON,
- PEACH,
- TOMATO,
- }
-
- fruit_ti := type_info_of(Fruit);
- name := fruit_ti.variant.(Type_Info_Named).name;
- info, _ := type_info_base(fruit_ti).variant.(Type_Info_Enum);
-
- fmt.printf("%s :: enum %T {\n", name, info.base);
- for _, i in info.values {
- fmt.printf("\t%s\t= %v,\n", info.names[i], info.values[i]);
- }
- fmt.printf("}\n");
-
- // NOTE(bill): look at that type-safe printf!
- }
-
- {
- Vector3 :: struct {x, y, z: f32}
-
- a := Vector3{x = 1, y = 4, z = 9};
- fmt.println(a);
- b := Vector3{x = 9, y = 3, z = 1};
- fmt.println(b);
-
- // NOTE(bill): See fmt.odin
- }
-
- // n.b. This pretty much "solves" serialization (to strings)
-}
-
-// #import "test.odin"
-
-namespaces_and_files :: proc() {
-
- // test.thing()
- // test.format.println()
- // test.println()
- /*
- // Non-exporting import
- #import "file.odin"
- #import "file.odin" as file
- #import "file.odin" as .
- #import "file.odin" as _
-
- // Exporting import
- #include "file.odin"
- */
-
- // Talk about scope rules and diagram
-}
-
-miscellany :: proc() {
- /*
- win32 `__imp__` prefix
- #dll_import
- #dll_export
-
- Change exported name/symbol for linking
- #link_name
-
- Custom calling conventions
- #stdcall
- #fastcall
-
- Runtime stuff
- #shared_global_scope
- */
-
- // assert(false)
- // #assert(false)
- // panic("Panic message goes here")
-}
-
-
-
-
diff --git a/misc/old_demos/demo002.odin b/misc/old_demos/demo002.odin
deleted file mode 100644
index a790aadf3..000000000
--- a/misc/old_demos/demo002.odin
+++ /dev/null
@@ -1,879 +0,0 @@
-// Demo 002
-export "core:fmt.odin";
-export "core:math.odin";
-export "core:mem.odin";
-// export "game.odin"
-
-#thread_local tls_int: int;
-
-main :: proc() {
- // Forenotes
-
- // Semicolons are now optional
- // Rule for when a semicolon is expected after a statement
- // - If the next token is not on the same line
- // - if the next token is a closing brace }
- // - Otherwise, a semicolon is needed
- //
- // Expections:
- // for, if, match
- // if x := thing(); x < 123 {}
- // for i := 0; i < 123; i++ {}
-
- // Q: Should I use the new rule or go back to the old one without optional semicolons?
-
-
- // #thread_local - see runtime.odin and above at `tls_int`
- // #foreign_system_library - see win32.odin
-
- // struct_compound_literals();
- // enumerations();
- // variadic_procedures();
- // new_builtins();
- // match_statement();
- // namespacing();
- // subtyping();
- // tagged_unions();
-}
-
-struct_compound_literals :: proc() {
- Thing :: struct {
- id: int,
- x: f32,
- name: string,
- };
- {
- t1: Thing;
- t1.id = 1;
-
- t3 := Thing{};
- t4 := Thing{1, 2, "Fred"};
- // t5 := Thing{1, 2};
-
- t6 := Thing{
- name = "Tom",
- x = 23,
- };
- }
-}
-
-enumerations :: proc() {
- {
- Fruit :: enum {
- APPLE, // 0
- BANANA, // 1
- PEAR, // 2
- };
-
- f := Fruit.APPLE;
- // g12: int = Fruit.BANANA
- g: int = cast(int)Fruit.BANANA;
- // However, you can use enums are index values as _any_ integer allowed
- }
- {
- Fruit1 :: enum int {
- APPLE,
- BANANA,
- PEAR,
- }
-
- Fruit2 :: enum u8 {
- APPLE,
- BANANA,
- PEAR,
- }
-
- Fruit3 :: enum u8 {
- APPLE = 1,
- BANANA, // 2
- PEAR = 5,
- TOMATO, // 6
- }
- }
-
- // Q: remove the need for `type` if it's a record (struct/enum/raw_union/union)?
-}
-
-variadic_procedures :: proc() {
- print_ints :: proc(args: ..int) {
- for arg, i in args {
- if i > 0 do print(", ");
- print(arg);
- }
- }
-
- print_ints(); // nl()
- print_ints(1); nl();
- print_ints(1, 2, 3); nl();
-
- print_prefix_f32s :: proc(prefix: string, args: ..f32) {
- print(prefix);
- print(": ");
- for arg, i in args {
- if i > 0 do print(", ");
- print(arg);
- }
- }
-
- print_prefix_f32s("a"); nl();
- print_prefix_f32s("b", 1); nl();
- print_prefix_f32s("c", 1, 2, 3); nl();
-
- // Internally, the variadic procedures get allocated to an array on the stack,
- // and this array is passed a slice
-
- // This is first step for a `print` procedure but I do not have an `any` type
- // yet as this requires a few other things first - i.e. introspection
-
- // NOTE(bill): I haven't yet added the feature of expanding a slice or array into
- // a variadic a parameter but it's pretty trivial to add
-}
-
-new_builtins :: proc() {
- {
- a := new(int);
- b := make([]int, 12);
- c := make([]int, 12, 16);
-
- defer free(a);
- defer free(b);
- defer free(c);
-
- // NOTE(bill): These use the current context's allocator not the default allocator
- // see runtime.odin
-
- // Q: Should this be `free` rather than `free` and should I overload it for slices too?
-
- push_allocator default_allocator() {
- a := new(int);
- defer free(a);
-
- // Do whatever
-
- }
- }
-
- {
- a: int = 123;
- b: type_of(a) = 321;
-
- // NOTE(bill): This matches the current naming scheme
- // size_of
- // align_of
- // offset_of
- //
- // size_of_val
- // align_of_val
- // offset_of_val
- // type_of_val
- }
-
- {
- // Compile time assert
- COND :: true;
- #assert(COND);
- // #assert(!COND)
-
- // Runtime assert
- x := true;
- assert(x);
- // assert(!x);
- }
-
- {
- x: ^u32 = nil;
- y := x+100;
- z := y-x;
- w := slice_ptr(x, 12);
- t := slice_ptr(x, 12, 16);
-
- // NOTE(bill): These are here because I've removed:
- // pointer arithmetic
- // pointer indexing
- // pointer slicing
-
- // Reason
-
- a: [16]int;
- a[1] = 1;
- b := &a;
- // Auto pointer deref
- // consistent with record members
- assert(b[1] == 1);
-
- // Q: Should I add them back in at the cost of inconsitency?
- }
-
- {
- a, b := -1, 2;
- print(min(a, b)); nl();
- print(max(a, b)); nl();
- print(abs(a)); nl();
-
- // These work at compile time too
- A :: -1;
- B :: 2;
- C :: min(A, B);
- D :: max(A, B);
- E :: abs(A);
-
- print(C); nl();
- print(D); nl();
- print(E); nl();
- }
-}
-
-
-match_statement :: proc() {
- // NOTE(bill): `match` statements are similar to `switch` statements
- // in other languages but there are few differences
-
- {
- match x := 5; x {
- case 1: // cases must be constant expression
- print("1!\n");
- // break by default
-
- case 2:
- s := "2!\n"; // Each case has its own scope
- print(s);
- break; // explicit break
-
- case 3, 4: // multiple cases
- print("3 or 4!\n");
-
- case 5:
- print("5!\n");
- fallthrough; // explicit fallthrough
-
- case:
- print("default!\n");
- }
-
-
-
- match x := 1.5; x {
- case 1.5:
- print("1.5!\n");
- // break by default
- case TAU:
- print("τ!\n");
- case:
- print("default!\n");
- }
-
-
-
- match x := "Hello"; x {
- case "Hello":
- print("greeting\n");
- // break by default
- case "Goodbye":
- print("farewell\n");
- case:
- print("???\n");
- }
-
-
-
-
-
-
- a := 53;
- match {
- case a == 1:
- print("one\n");
- case a == 2:
- print("a couple\n");
- case a < 7, a == 7:
- print("a few\n");
- case a < 12: // intentional bug
- print("several\n");
- case a >= 12 && a < 100:
- print("dozens\n");
- case a >= 100 && a < 1000:
- print("hundreds\n");
- case:
- print("a fuck ton\n");
- }
-
- // Identical to this
-
- b := 53;
- if b == 1 {
- print("one\n");
- } else if b == 2 {
- print("a couple\n");
- } else if b < 7 || b == 7 {
- print("a few\n");
- } else if b < 12 { // intentional bug
- print("several\n");
- } else if b >= 12 && b < 100 {
- print("dozens\n");
- } else if b >= 100 && b < 1000 {
- print("hundreds\n");
- } else {
- print("a fuck ton\n");
- }
-
- // However, match statements allow for `break` and `fallthrough` unlike
- // an if statement
- }
-}
-
-Vector3 :: struct {x, y, z: f32}
-
-print_floats :: proc(args: ..f32) {
- for arg, i in args {
- if i > 0 do print(", ");
- print(arg);
- }
- println();
-}
-
-namespacing :: proc() {
- {
- Thing :: #type struct {
- x: f32,
- name: string,
- };
-
- a: Thing;
- a.x = 3;
- {
- Thing :: #type struct {
- y: int,
- test: bool,
- };
-
- b: Thing; // Uses this scope's Thing
- b.test = true;
- }
- }
-/*
- {
- Entity :: struct {
- Guid :: int
- Nested :: struct {
- MyInt :: int
- i: int
- }
-
- CONSTANT :: 123
-
-
- guid: Guid
- name: string
- pos: Vector3
- vel: Vector3
- nested: Nested
- }
-
- guid: Entity.Guid = Entity.CONSTANT
- i: Entity.Nested.MyInt
-
-
-
- {
- using Entity
- guid: Guid = CONSTANT
- using Nested
- i: MyInt
- }
-
-
- {
- using Entity.Nested
- guid: Entity.Guid = Entity.CONSTANT
- i: MyInt
- }
-
-
- {
- e: Entity
- using e
- guid = 27832
- name = "Bob"
-
- print(e.guid as int); nl()
- print(e.name); nl()
- }
-
- {
- using e: Entity
- guid = 78456
- name = "Thing"
-
- print(e.guid as int); nl()
- print(e.name); nl()
- }
- }
-
- {
- Entity :: struct {
- Guid :: int
- Nested :: struct {
- MyInt :: int
- i: int
- }
-
- CONSTANT :: 123
-
-
- guid: Guid
- name: string
- using pos: Vector3
- vel: Vector3
- using nested: ^Nested
- }
-
- e := Entity{nested = new(Entity.Nested)}
- e.x = 123
- e.i = Entity.CONSTANT
- }
-
-*/
-
- {
- Entity :: struct {
- position: Vector3
- }
-
- print_pos_1 :: proc(entity: ^Entity) {
- print("print_pos_1: ");
- print_floats(entity.position.x, entity.position.y, entity.position.z);
- }
-
- print_pos_2 :: proc(entity: ^Entity) {
- using entity;
- print("print_pos_2: ");
- print_floats(position.x, position.y, position.z);
- }
-
- print_pos_3 :: proc(using entity: ^Entity) {
- print("print_pos_3: ");
- print_floats(position.x, position.y, position.z);
- }
-
- print_pos_4 :: proc(using entity: ^Entity) {
- using position;
- print("print_pos_4: ");
- print_floats(x, y, z);
- }
-
- e := Entity{position = Vector3{1, 2, 3}};
- print_pos_1(&e);
- print_pos_2(&e);
- print_pos_3(&e);
- print_pos_4(&e);
-
- // This is similar to C++'s `this` pointer that is implicit and only available in methods
- }
-}
-
-subtyping :: proc() {
- {
- // C way for subtyping/subclassing
-
- Entity :: struct {
- position: Vector3,
- }
-
- Frog :: struct {
- entity: Entity,
- jump_height: f32,
- }
-
- f: Frog;
- f.entity.position = Vector3{1, 2, 3};
-
- using f.entity;
- position = Vector3{1, 2, 3};
-
- }
-
- {
- // C++ way for subtyping/subclassing
-
- Entity :: struct {
- position: Vector3
- }
-
- Frog :: struct {
- using entity: Entity,
- jump_height: f32,
- }
-
- f: Frog;
- f.position = Vector3{1, 2, 3};
-
-
- print_pos :: proc(using entity: Entity) {
- print("print_pos: ");
- print_floats(position.x, position.y, position.z);
- }
-
- print_pos(f.entity);
- // print_pos(f);
-
- // Subtype Polymorphism
- }
-
- {
- // More than C++ way for subtyping/subclassing
-
- Entity :: struct {
- position: Vector3,
- }
-
- Frog :: struct {
- jump_height: f32,
- using entity: ^Entity, // Doesn't have to be first member!
- }
-
- f: Frog;
- f.entity = new(Entity);
- f.position = Vector3{1, 2, 3};
-
-
- print_pos :: proc(using entity: ^Entity) {
- print("print_pos: ");
- print_floats(position.x, position.y, position.z);
- }
-
- print_pos(f.entity);
- // print_pos(^f);
- // print_pos(f);
- }
-
- {
- // More efficient subtyping
-
- Entity :: struct {
- position: Vector3,
- }
-
- Frog :: struct {
- jump_height: f32,
- using entity: ^Entity,
- }
-
- MAX_ENTITES :: 64;
- entities: [MAX_ENTITES]Entity;
- entity_count := 0;
-
- next_entity :: proc(entities: []Entity, entity_count: ^int) -> ^Entity {
- e := &entities[entity_count^];
- entity_count^ += 1;
- return e;
- }
-
- f: Frog;
- f.entity = next_entity(entities[..], &entity_count);
- f.position = Vector3{3, 4, 6};
-
- using f.position;
- print_floats(x, y, z);
- }
-
- /*{
- // Down casting
-
- Entity :: struct {
- position: Vector3,
- }
-
- Frog :: struct {
- jump_height: f32,
- using entity: Entity,
- }
-
- f: Frog;
- f.jump_height = 564;
- e := ^f.entity;
-
- frog := down_cast(^Frog)e;
- print("down_cast: ");
- print(frog.jump_height); nl();
-
- // NOTE(bill): `down_cast` is unsafe and there are not check are compile time or run time
- // Q: Should I completely remove `down_cast` as I added it in about 30 minutes
- }*/
-
- {
- // Multiple "inheritance"/subclassing
-
- Entity :: struct {
- position: Vector3,
- }
- Climber :: struct {
- speed: f32,
- }
-
- Frog :: struct {
- using entity: Entity,
- using climber: Climber,
- }
- }
-}
-
-tagged_unions :: proc() {
- {
- Entity_Kind :: enum {
- INVALID,
- FROG,
- GIRAFFE,
- HELICOPTER,
- }
-
- Entity :: struct {
- kind: Entity_Kind
- using data: struct #raw_union {
- frog: struct {
- jump_height: f32,
- colour: u32,
- },
- giraffe: struct {
- neck_length: f32,
- spot_count: int,
- },
- helicopter: struct {
- blade_count: int,
- weight: f32,
- pilot_name: string,
- },
- }
- }
-
- e: Entity;
- e.kind = Entity_Kind.FROG;
- e.frog.jump_height = 12;
-
- f: type_of(e.frog);
-
- // But this is very unsafe and extremely cumbersome to write
- // In C++, I use macros to alleviate this but it's not a solution
- }
-
- {
- Frog :: struct {
- jump_height: f32,
- colour: u32,
- }
- Giraffe :: struct {
- neck_length: f32,
- spot_count: int,
- }
- Helicopter :: struct {
- blade_count: int,
- weight: f32,
- pilot_name: string,
- }
- Entity :: union {Frog, Giraffe, Helicopter};
-
- f1: Frog = Frog{12, 0xff9900};
- f2: Entity = Frog{12, 0xff9900}; // Implicit cast
- f3 := cast(Entity)Frog{12, 0xff9900}; // Explicit cast
-
- // f3.Frog.jump_height = 12 // There are "members" of a union
-
-
-
- e, f, g, h: Entity;
- f = Frog{12, 0xff9900};
- g = Giraffe{2.1, 23};
- h = Helicopter{4, 1000, "Frank"};
-
-
-
-
- // Requires a pointer to the union
- // `x` will be a pointer to type of the case
-
- match x in &f {
- case Frog:
- print("Frog!\n");
- print(x.jump_height); nl();
- // x.jump_height = 3;
- print(x.jump_height); nl();
- case Giraffe:
- print("Giraffe!\n");
- case Helicopter:
- print("ROFLCOPTER!\n");
- case:
- print("invalid entity\n");
- }
-
-
- // Q: Allow for a non pointer version with takes a copy instead?
- // Or it takes the pointer the data and not a copy
-
-
- // fp := cast(^Frog)^f; // Unsafe
- // print(fp.jump_height); nl();
-
-
- // Internals of a tagged union
- /*
- struct {
- data: [size_of_biggest_tag]u8,
- tag_index: int,
- }
- */
- // This is to allow for pointer casting if needed
-
-
- // Advantage over subtyping version
- MAX_ENTITES :: 64;
- entities: [MAX_ENTITES]Entity;
-
- entities[0] = Frog{};
- entities[1] = Helicopter{};
- // etc.
- }
-
-
- {
- // Transliteration of code from this actual compiler
- // Some stuff is missing
- Type :: struct {};
- Scope :: struct {};
- Token :: struct {};
- AstNode :: struct {};
- ExactValue :: struct {};
-
- Entity_Kind :: enum {
- Invalid,
- Constant,
- Variable,
- Using_Variable,
- TypeName,
- Procedure,
- Builtin,
- Count,
- }
-
- Guid :: i64;
- Entity :: struct {
-
- kind: Entity_Kind,
- guid: Guid,
-
- scope: ^Scope,
- token: Token,
- type_: ^Type,
-
- using data: struct #raw_union {
- Constant: struct {
- value: ExactValue,
- },
- Variable: struct {
- visited: bool, // Cycle detection
- used: bool, // Variable is used
- is_field: bool, // Is struct field
- anonymous: bool, // Variable is an anonymous
- },
- Using_Variable: struct {
- },
- TypeName: struct {
- },
- Procedure: struct {
- used: bool,
- },
- Builtin: struct {
- id: int,
- },
- },
- }
-
- // Plus all the constructing procedures that go along with them!!!!
- // It's a nightmare
- }
-
- {
- Type :: struct {};
- Scope :: struct {};
- Token :: struct {};
- AstNode :: struct {};
- ExactValue :: struct {};
-
-
- Guid :: i64;
- Entity_Base :: struct {
- }
-
-
- Constant :: struct {
- value: ExactValue,
- }
- Variable :: struct {
- visited: bool, // Cycle detection
- used: bool, // Variable is used
- is_field: bool, // Is struct field
- anonymous: bool, // Variable is an anonymous
- }
- Using_Variable :: struct {
- }
- TypeName :: struct {
- }
- Procedure :: struct {
- used: bool,
- }
- Builtin :: struct {
- id: int,
- }
-
- Entity :: struct {
- guid: Guid,
-
- scope: ^Scope,
- token: Token,
- type_: ^Type,
-
- variant: union {Constant, Variable, Using_Variable, TypeName, Procedure, Builtin},
- }
-
- e := Entity{
- variant = Variable{
- used = true,
- anonymous = false,
- },
- };
-
-
-
- // Q: Allow a "base" type to be added to a union?
- // Or even `using` on union to get the same properties?
- }
-
-
- {
- // `Raw` unions still have uses, especially for mathematic types
-
- Vector2 :: struct #raw_union {
- using xy_: struct { x, y: f32 },
- e: [2]f32,
- v: [vector 2]f32,
- }
-
- Vector3 :: struct #raw_union {
- using xyz_: struct { x, y, z: f32 },
- xy: Vector2,
- e: [3]f32,
- v: [vector 3]f32,
- }
-
- v2: Vector2;
- v2.x = 1;
- v2.e[0] = 1;
- v2.v[0] = 1;
-
- v3: Vector3;
- v3.x = 1;
- v3.e[0] = 1;
- v3.v[0] = 1;
- v3.xy.x = 1;
- }
-}
-
-nl :: proc() { println(); }
diff --git a/misc/old_demos/demo004.odin b/misc/old_demos/demo004.odin
deleted file mode 100644
index c9acc9a15..000000000
--- a/misc/old_demos/demo004.odin
+++ /dev/null
@@ -1,66 +0,0 @@
-import "core:fmt.odin";
-import "core:utf8.odin";
-import "core:hash.odin";
-import "core:mem.odin";
-
-main :: proc() {
- { // New Standard Library stuff
- s := "Hello";
- fmt.println(s,
- utf8.valid_string(s),
- hash.murmur64(cast([]u8)s));
-
- // utf8.odin
- // hash.odin
- // - crc, fnv, fnva, murmur
- // mem.odin
- // - Custom allocators
- // - Helpers
- }
-
- {
- arena: mem.Arena;
- mem.init_arena_from_context(&arena, mem.megabytes(16)); // Uses default allocator
- defer mem.destroy_arena(&arena);
-
- push_allocator mem.arena_allocator(&arena) {
- x := new(int);
- x^ = 1337;
-
- fmt.println(x^);
- }
-
- /*
- push_allocator x {
- ..
- }
-
- is equivalent to:
-
- {
- prev_allocator := __context.allocator
- __context.allocator = x
- defer __context.allocator = prev_allocator
-
- ..
- }
- */
-
- // You can also "push" a context
-
- c := context; // Create copy of the allocator
- c.allocator = mem.arena_allocator(&arena);
-
- push_context c {
- x := new(int);
- x^ = 365;
-
- fmt.println(x^);
- }
- }
-
- // Backend improvements
- // - Minimal dependency building (only build what is needed)
- // - Numerous bugs fixed
- // - Mild parsing recovery after bad syntax error
-}
diff --git a/misc/old_demos/demo005.odin b/misc/old_demos/demo005.odin
deleted file mode 100644
index c8273b03b..000000000
--- a/misc/old_demos/demo005.odin
+++ /dev/null
@@ -1,283 +0,0 @@
-import "core:fmt.odin";
-import "core:utf8.odin";
-// import "core:atomic.odin";
-// import "core:hash.odin";
-// import "core:math.odin";
-// import "core:mem.odin";
-// import "core:opengl.odin";
-// import "core:os.odin";
-// import "core:sync.odin";
-// import win32 "core:sys/windows.odin";
-
-main :: proc() {
- // syntax();
- procedure_overloading();
-}
-
-syntax :: proc() {
- // Cyclic type checking
- // Uncomment to see the error
- // A :: struct {b: B};
- // B :: struct {a: A};
-
- x: int;
- y := cast(f32)x;
- z := transmute(u32)y;
- // down_cast, union_cast are similar too
-
-
-
- // Basic directives
- fmt.printf("Basic directives = %s(%d): %s\n", #file, #line, #procedure);
- // NOTE: new and improved `printf`
- // TODO: It does need accurate float printing
-
-
-
- // record fields use the same syntax a procedure signatures
- Thing1 :: struct {
- x: f32,
- y: int,
- z: ^[]int,
- };
- Thing2 :: struct {x: f32, y: int, z: ^[]int};
-
- // Slice interals are now just a `ptr+len+cap`
- slice: []int; #assert(size_of(slice) == 3*size_of(int));
-
- // Helper type - Help the reader understand what it is quicker
- My_Int :: #type int;
- My_Proc :: #type proc(int) -> f32;
-
-
- // All declarations with : are either variable or constant
- // To make these declarations syntactically consistent
- v_variable := 123;
- c_constant :: 123;
- c_type1 :: int;
- c_type2 :: []int;
- c_proc :: proc() { /* code here */ };
-
-
-/*
- x += 1;
- x -= 1;
- // ++ and -- have been removed
- // x++;
- // x--;
- // Question: Should they be added again?
- // They were removed as they are redundant and statements, not expressions
- // like in C/C++
-*/
-
- // You can now build files as a `.dll`
- // `odin build_dll demo.odin`
-
-
- // New vector syntax
- u, v: [vector 3]f32;
- v[0] = 123;
- v.x = 123; // valid for all vectors with count 1 to 4
-
- // Next part
- prefixes();
-}
-
-
-Prefix_Type :: struct {x: int, y: f32, z: rawptr};
-
-#thread_local my_tls: Prefix_Type;
-
-prefixes :: proc() {
- using var: Prefix_Type;
- var.x = 123;
- x = 123;
-
-
- foo :: proc(using pt: Prefix_Type) {
- }
-
-
-
- // Same as C99's `restrict`
- bar :: proc(#no_alias a, b: ^int) {
- // Assumes a never equals b so it can perform optimizations with that fact
- }
-
-
- when_statements();
-}
-
-
-
-
-
-when_statements :: proc() {
- X :: 123 + 12;
- Y :: X/5;
- COND :: Y > 0;
-
- when COND {
- fmt.println("Y > 0");
- } else {
- fmt.println("Y <= 0");
- }
-
-
- when false {
- this_code_does_not_exist(123, 321);
- but_its_syntax_is_valid();
- x :: ^^^^int;
- }
-
- foreign_procedures();
-}
-
-when ODIN_OS == "windows" {
- foreign_system_library win32_user "user32.lib";
-}
-// NOTE: This is done on purpose for two reasons:
-// * Makes it clear where the platform specific stuff is
-// * Removes the need to solve the travelling salesman problem when importing files :P
-
-foreign_procedures :: proc() {
- foreign win32_user {
- ShowWindow :: proc(hwnd: rawptr, cmd_show: i32) -> i32 ---;
- show_window :: proc(hwnd: rawptr, cmd_show: i32) -> i32 #link_name "ShowWindow" ---;
- }
- // NOTE: If that library doesn't get used, it doesn't get linked with
- // NOTE: There is not link checking yet to see if that procedure does come from that library
-
- // See sys/windows.odin for more examples
-
- special_expressions();
-}
-
-special_expressions :: proc() {
-/*
- // Block expression
- x := {
- a: f32 = 123;
- b := a-123;
- c := b/a;
- give c;
- }; // semicolon is required as it's an expression
-
- y := if x < 50 {
- give x;
- } else {
- // TODO: Type cohesion is not yet finished
- give 123;
- }; // semicolon is required as it's an expression
-*/
-
- // This is allows for inline blocks of code and will be a useful feature to have when
- // macros will be implemented into the language
-
- loops();
-}
-
-loops :: proc() {
- // The C-style for loop
- for i := 0; i < 123; i += 1 {
- break;
- }
- for i := 0; i < 123; {
- break;
- }
- for false {
- break;
- }
- for {
- break;
- }
-
- for i in 0..123 { // 123 exclusive
- }
-
- for i in 0..123-1 { // 122 inclusive
- }
-
- for val, idx in 12..16 {
- fmt.println(val, idx);
- }
-
- primes := [?]int{2, 3, 5, 7, 11, 13, 17, 19};
-
- for p in primes {
- fmt.println(p);
- }
-
- // Pointers to arrays, slices, or strings are allowed
- for _ in &primes {
- // ignore the value and just iterate across it
- }
-
-
-
- name := "你好,世界";
- fmt.println(name);
- for r in name {
- #assert(type_of(r) == rune);
- fmt.printf("%r\n", r);
- }
-
- when false {
- for i, size := 0; i < name.count; i += size {
- r: rune;
- r, size = utf8.decode_rune(name[i..]);
- fmt.printf("%r\n", r);
- }
- }
-
- procedure_overloading();
-}
-
-
-procedure_overloading :: proc() {
- THINGF :: 14451.1;
- THINGI :: 14451;
-
- foo :: proc() {
- fmt.printf("Zero args\n");
- }
- foo :: proc(i: int) {
- fmt.printf("int arg, i=%d\n", i);
- }
- foo :: proc(f: f64) {
- i := cast(int)f;
- fmt.printf("f64 arg, f=%d\n", i);
- }
-
- foo();
- foo(THINGF);
- // foo(THINGI); // 14451 is just a number so it could go to either procedures
- foo(cast(int)THINGI);
-
-
-
-
- foo :: proc(x: ^i32) -> (int, int) {
- fmt.println("^int");
- return 123, cast(int)(x^);
- }
- foo :: proc(x: rawptr) {
- fmt.println("rawptr");
- }
-
-
- a: i32 = 123;
- b: f32;
- c: rawptr;
- fmt.println(foo(&a));
- foo(&b);
- foo(c);
- // foo(nil); // nil could go to numerous types thus the ambiguity
-
- f: proc();
- f = foo; // The correct `foo` to chosen
- f();
-
-
- // See math.odin and atomic.odin for more examples
-}
diff --git a/misc/old_demos/demo006.odin b/misc/old_demos/demo006.odin
deleted file mode 100644
index c2f64151b..000000000
--- a/misc/old_demos/demo006.odin
+++ /dev/null
@@ -1,310 +0,0 @@
-// import "core:atomic.odin";
-import "core:hash.odin";
-import "core:mem.odin";
-import "core:opengl.odin";
-import "core:strconv.odin";
-import "core:sync.odin";
-import win32 "core:sys/windows.odin";
-
-import "core:fmt.odin";
-import "core:os.odin";
-import "core:math.odin";
-
-
-main :: proc() {
-when true {
-/*
- Added:
- * Unexported entities and fields using an underscore prefix
- - See `sync.odin` and explain
-
- Removed:
- * Maybe/option types
- * Remove `type` keyword and other "reserved" keywords
- * ..< and .. removed and replace with .. (half-closed range)
-
- Changed:
- * `#assert` and `assert` return the value of the condition for semantic reasons
- * thread_local -> #thread_local
- * #include -> #load
- * Files only get checked if they are actually used
- * match x in y {} // For type match statements
- * Version numbering now starts from 0.1.0 and uses the convention:
- - major.minor.patch
- * Core library additions to Windows specific stuff
- */
-
- {
- Fruit :: enum {
- APPLE,
- BANANA,
- COCONUT,
- }
- fmt.println(Fruit.names);
- }
-
- {
- A :: struct {x, y: f32};
- B :: struct #align 16 {x, y: f32};
- fmt.println("align_of(A) =", align_of(A));
- fmt.println("align_of(B) =", align_of(B));
- }
-
- {
- // Removal of ..< and ..
- for i in 0..16 {
- }
- // Is similar to
- for i := 0; i < 16; i += 1 {
- }
- }
-
- {
- thing: for i in 0..10 {
- for j in i+1..10 {
- if j == 2 {
- fmt.println(i, j);
- continue thing;
- }
- if j == 3 {
- break thing;
- }
- }
- }
-
- // Works with, `for`, `for in`, `match`, `match in`
- // NOTE(bill): This solves most of the problems I need `goto` for
- }
-
- {
- t := type_info_of(int);
- match i in t.variant {
- case Type_Info_Integer, Type_Info_Float:
- fmt.println("It's a number");
- }
-
-
- x: any = 123;
- foo: match i in x {
- case int, f32:
- fmt.println("It's an int or f32");
- break foo;
- }
- }
-
- {
- cond := true;
- x: int;
- if cond {
- x = 3;
- } else {
- x = 4;
- }
-
-
- // Ternary operator
- y := cond ? 3 : 4;
-
- FOO :: true ? 123 : 432; // Constant ternary expression
- fmt.println("Ternary values:", y, FOO);
- }
-
- {
- // Slices now store a capacity
- buf: [256]u8;
- s: []u8;
- s = buf[..0]; // == buf[0..0];
- fmt.println("count =", len(s));
- fmt.println("capacity =", cap(s));
- append(&s, 1, 2, 3);
- fmt.println(s);
-
- s = buf[1..2..3];
- fmt.println("count =", len(s));
- fmt.println("capacity =", cap(s));
- fmt.println(s);
-
- clear(&s); // Sets count to zero
- }
-
- {
- Foo :: struct {
- x, y, z: f32,
- ok: bool,
- flags: u32,
- }
- foo_array: [256]Foo;
- foo_as_bytes: []u8 = mem.slice_to_bytes(foo_array[..]);
- // Useful for things like
- // os.write(handle, foo_as_bytes);
-
- 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));
- // Question: Should there be a bytes_to_slice procedure or is it clearer to do this even if it is error prone?
- // And if so what would the syntax be?
- // slice_transmute([]Foo, foo_as_bytes);
- }
-
- {
- Vec3 :: [vector 3]f32;
-
- x := Vec3{1, 2, 3};
- y := Vec3{4, 5, 6};
- fmt.println(x < y);
- fmt.println(x + y);
- fmt.println(x - y);
- fmt.println(x * y);
- fmt.println(x / y);
-
- for i in x {
- fmt.println(i);
- }
-
- #assert(size_of([vector 7]bool) >= size_of([7]bool));
- #assert(size_of([vector 7]i32) >= size_of([7]i32));
- // align_of([vector 7]i32) != align_of([7]i32) // this may be the case
- }
-
- {
- // fmt.* changes
- // bprint* returns `string`
-
- data: [256]u8;
- str := fmt.bprintf(data[..], "Hellope %d %s %c", 123, "others", '!');
- fmt.println(str);
- }
-
- {
- x: [dynamic]f64;
- reserve(&x, 16);
- defer free(x); // `free` is overloaded for numerous types
- // Number literals can have underscores in them for readability
- append(&x, 2_000_000.500_000, 123, 5, 7); // variadic append
-
- for p, i in x {
- if i > 0 { fmt.print(", "); }
- fmt.print(p);
- }
- fmt.println();
- }
-
- {
- // Dynamic array "literals"
- x := [dynamic]f64{2_000_000.500_000, 3, 5, 7};
- defer free(x);
- fmt.println(x); // fmt.print* supports printing of dynamic types
- clear(&x);
- fmt.println(x);
- }
-
- {
- m: map[f32]int;
- reserve(&m, 16);
- defer free(m);
-
- m[1.0] = 1278;
- m[2.0] = 7643;
- m[3.0] = 564;
- _, ok := m[3.0];
- c := m[3.0];
- assert(ok && c == 564);
-
- fmt.print("map[");
- i := 0;
- for val, key in m {
- if i > 0 {
- fmt.print(", ");
- }
- fmt.printf("%v=%v", key, val);
- i += 1;
- }
- fmt.println("]");
- }
- {
- m := map[string]u32{
- "a" = 56,
- "b" = 13453,
- "c" = 7654,
- };
- defer free(m);
-
- c := m["c"];
- _, ok := m["c"];
- assert(ok && c == 7654);
- fmt.println(m);
-
- delete(&m, "c"); // deletes entry with key "c"
- _, found := m["c"];
- assert(!found);
-
- fmt.println(m);
- clear(&m);
- fmt.println(m);
-
- // NOTE: Fixed size maps are planned but we have not yet implemented
- // them as we have had no need for them as of yet
- }
-
- {
- Vector3 :: struct{x, y, z: f32};
- Quaternion :: struct{x, y, z, w: f32};
-
- // Variants
- Frog :: struct {
- ribbit_volume: f32,
- jump_height: f32,
- }
- Door :: struct {
- openness: f32,
- }
- Map :: struct {
- width, height: f32,
- place_positions: []Vector3,
- place_names: []string,
- }
-
- Entity :: struct {
- // Common Fields
- id: u64,
- name: string,
- using position: Vector3,
- orientation: Quaternion,
- flags: u32,
-
- variant: union { Frog, Door, Map },
- }
-
- entity: Entity;
- entity.id = 1337;
- // implicit conversion from variant to base type
- entity.variant = Frog{
- ribbit_volume = 0.5,
- jump_height = 2.1,
- /*other data */
- };
-
- entity.name = "Frank";
- entity.position = Vector3{1, 4, 9};
-
- match e in entity.variant {
- case Frog:
- fmt.println("Ribbit");
- case Door:
- fmt.println("Creak");
- case Map:
- fmt.println("Rustle");
- case:
- fmt.println("Just a normal entity");
- }
-
- if frog, ok := entity.variant.(Frog); ok {
- fmt.printf("The frog jumps %f feet high at %v\n", frog.jump_height, entity.position);
- }
-
- // Panics if not the correct type
- frog: Frog;
- frog = entity.variant.(Frog);
- frog, _ = entity.variant.(Frog); // ignore error and force cast
- }
-}
-}
-
diff --git a/misc/old_demos/demo007.odin b/misc/old_demos/demo007.odin
deleted file mode 100644
index d19446ecb..000000000
--- a/misc/old_demos/demo007.odin
+++ /dev/null
@@ -1,570 +0,0 @@
-import "core:fmt.odin"
-import "core:strconv.odin"
-import "core:mem.odin"
-import "core:bits.odin"
-import "core:hash.odin"
-import "core:math.odin"
-import "core:os.odin"
-import "core:raw.odin"
-import "core:sort.odin"
-import "core:strings.odin"
-import "core:types.odin"
-import "core:utf16.odin"
-import "core:utf8.odin"
-
-when ODIN_OS == "windows" {
- import "core:atomics.odin"
- import "core:opengl.odin"
- import "core:thread.odin"
- import win32 "core:sys/windows.odin"
-}
-
-general_stuff :: proc() {
- { // `do` for inline statmes rather than block
- foo :: proc() do fmt.println("Foo!");
- if false do foo();
- for false do foo();
- when false do foo();
-
- if false do foo();
- else do foo();
- }
-
- { // Removal of `++` and `--` (again)
- x: int;
- x += 1;
- x -= 1;
- }
- { // Casting syntaxes
- i := i32(137);
- ptr := &i;
-
- fp1 := (^f32)(ptr);
- // ^f32(ptr) == ^(f32(ptr))
- fp2 := cast(^f32)ptr;
-
- f1 := (^f32)(ptr)^;
- f2 := (cast(^f32)ptr)^;
-
- // Questions: Should there be two ways to do it?
- }
-
- /*
- * Remove *_val_of built-in procedures
- * size_of, align_of, offset_of
- * type_of, type_info_of
- */
-
- { // `expand_to_tuple` built-in procedure
- Foo :: struct {
- x: int,
- b: bool,
- }
- f := Foo{137, true};
- x, b := expand_to_tuple(f);
- fmt.println(f);
- fmt.println(x, b);
- fmt.println(expand_to_tuple(f));
- }
-
- {
- // .. half-closed range
- // .. open range
-
- for in 0..2 {} // 0, 1
- for in 0..2 {} // 0, 1, 2
- }
-}
-
-default_struct_values :: proc() {
- {
- Vector3 :: struct {
- x: f32,
- y: f32,
- z: f32,
- }
- v: Vector3;
- fmt.println(v);
- }
- {
- // Default values must be constants
- Vector3 :: struct {
- x: f32 = 1,
- y: f32 = 4,
- z: f32 = 9,
- }
- v: Vector3;
- fmt.println(v);
-
- v = Vector3{};
- fmt.println(v);
-
- // Uses the same semantics as a default values in a procedure
- v = Vector3{137};
- fmt.println(v);
-
- v = Vector3{z = 137};
- fmt.println(v);
- }
-
- {
- Vector3 :: struct {
- x := 1.0,
- y := 4.0,
- z := 9.0,
- }
- stack_default: Vector3;
- stack_literal := Vector3{};
- heap_one := new(Vector3); defer free(heap_one);
- heap_two := new_clone(Vector3{}); defer free(heap_two);
-
- fmt.println("stack_default - ", stack_default);
- fmt.println("stack_literal - ", stack_literal);
- fmt.println("heap_one - ", heap_one^);
- fmt.println("heap_two - ", heap_two^);
-
-
- N :: 4;
- stack_array: [N]Vector3;
- heap_array := new([N]Vector3); defer free(heap_array);
- heap_slice := make([]Vector3, N); defer free(heap_slice);
- fmt.println("stack_array[1] - ", stack_array[1]);
- fmt.println("heap_array[1] - ", heap_array[1]);
- fmt.println("heap_slice[1] - ", heap_slice[1]);
- }
-}
-
-
-
-
-union_type :: proc() {
- {
- val: union{int, bool};
- val = 137;
- if i, ok := val.(int); ok {
- fmt.println(i);
- }
- val = true;
- fmt.println(val);
-
- val = nil;
-
- switch v in val {
- case int: fmt.println("int", v);
- case bool: fmt.println("bool", v);
- case: fmt.println("nil");
- }
- }
- {
- // There is a duality between `any` and `union`
- // An `any` has a pointer to the data and allows for any type (open)
- // A `union` has as binary blob to store the data and allows only certain types (closed)
- // The following code is with `any` but has the same syntax
- val: any;
- val = 137;
- if i, ok := val.(int); ok {
- fmt.println(i);
- }
- val = true;
- fmt.println(val);
-
- val = nil;
-
- switch v in val {
- case int: fmt.println("int", v);
- case bool: fmt.println("bool", v);
- case: fmt.println("nil");
- }
- }
-
- Vector3 :: struct {x, y, z: f32};
- Quaternion :: struct {x, y, z: f32, w: f32 = 1};
-
- // More realistic examples
- {
- // NOTE(bill): For the above basic examples, you may not have any
- // particular use for it. However, my main use for them is not for these
- // simple cases. My main use is for hierarchical types. Many prefer
- // subtyping, embedding the base data into the derived types. Below is
- // an example of this for a basic game Entity.
-
- Entity :: struct {
- id: u64,
- name: string,
- position: Vector3,
- orientation: Quaternion,
-
- derived: any,
- }
-
- Frog :: struct {
- using entity: Entity,
- jump_height: f32,
- }
-
- Monster :: struct {
- using entity: Entity,
- is_robot: bool,
- is_zombie: bool,
- }
-
- // See `parametric_polymorphism` procedure for details
- new_entity :: proc(T: type) -> ^Entity {
- t := new(T);
- t.derived = t^;
- return t;
- }
-
- entity := new_entity(Monster);
-
- switch e in entity.derived {
- case Frog:
- fmt.println("Ribbit");
- case Monster:
- if e.is_robot do fmt.println("Robotic");
- if e.is_zombie do fmt.println("Grrrr!");
- }
- }
-
- {
- // NOTE(bill): A union can be used to achieve something similar. Instead
- // of embedding the base data into the derived types, the derived data
- // in embedded into the base type. Below is the same example of the
- // basic game Entity but using an union.
-
- Entity :: struct {
- id: u64,
- name: string,
- position: Vector3,
- orientation: Quaternion,
-
- derived: union {Frog, Monster},
- }
-
- Frog :: struct {
- using entity: ^Entity,
- jump_height: f32,
- }
-
- Monster :: struct {
- using entity: ^Entity,
- is_robot: bool,
- is_zombie: bool,
- }
-
- // See `parametric_polymorphism` procedure for details
- new_entity :: proc(T: type) -> ^Entity {
- t := new(Entity);
- t.derived = T{entity = t};
- return t;
- }
-
- entity := new_entity(Monster);
-
- switch e in entity.derived {
- case Frog:
- fmt.println("Ribbit");
- case Monster:
- if e.is_robot do fmt.println("Robotic");
- if e.is_zombie do fmt.println("Grrrr!");
- }
-
- // NOTE(bill): As you can see, the usage code has not changed, only its
- // memory layout. Both approaches have their own advantages but they can
- // be used together to achieve different results. The subtyping approach
- // can allow for a greater control of the memory layout and memory
- // allocation, e.g. storing the derivatives together. However, this is
- // also its disadvantage. You must either preallocate arrays for each
- // derivative separation (which can be easily missed) or preallocate a
- // bunch of "raw" memory; determining the maximum size of the derived
- // types would require the aid of metaprogramming. Unions solve this
- // particular problem as the data is stored with the base data.
- // Therefore, it is possible to preallocate, e.g. [100]Entity.
-
- // It should be noted that the union approach can have the same memory
- // layout as the any and with the same type restrictions by using a
- // pointer type for the derivatives.
-
- /*
- Entity :: struct {
- ..
- derived: union{^Frog, ^Monster};
- }
-
- Frog :: struct {
- using entity: Entity;
- ..
- }
- Monster :: struct {
- using entity: Entity;
- ..
-
- }
- new_entity :: proc(T: type) -> ^Entity {
- t := new(T);
- t.derived = t;
- return t;
- }
- */
- }
-}
-
-parametric_polymorphism :: proc() {
- print_value :: proc(value: $T) {
- fmt.printf("print_value: %T %v\n", value, value);
- }
-
- v1: int = 1;
- v2: f32 = 2.1;
- v3: f64 = 3.14;
- v4: string = "message";
-
- print_value(v1);
- print_value(v2);
- print_value(v3);
- print_value(v4);
-
- fmt.println();
-
- add :: proc(p, q: $T) -> T {
- x: T = p + q;
- return x;
- }
-
- a := add(3, 4);
- fmt.printf("a: %T = %v\n", a, a);
-
- b := add(3.2, 4.3);
- fmt.printf("b: %T = %v\n", b, b);
-
- // This is how `new` is implemented
- alloc_type :: proc(T: type) -> ^T {
- t := cast(^T)alloc(size_of(T), align_of(T));
- t^ = T{}; // Use default initialization value
- return t;
- }
-
- copy_slice :: proc(dst, src: []$T) -> int {
- n := min(len(dst), len(src));
- if n > 0 {
- mem.copy(&dst[0], &src[0], n*size_of(T));
- }
- return n;
- }
-
- double_params :: proc(a: $A, b: $B) -> A {
- return a + A(b);
- }
-
- fmt.println(double_params(12, 1.345));
-
-
-
- { // Polymorphic Types and Type Specialization
- Table_Slot :: struct(Key, Value: type) {
- occupied: bool,
- hash: u32,
- key: Key,
- value: Value,
- }
- TABLE_SIZE_MIN :: 32;
- Table :: struct(Key, Value: type) {
- count: int,
- allocator: Allocator,
- slots: []Table_Slot(Key, Value),
- }
-
- // Only allow types that are specializations of a (polymorphic) slice
- make_slice :: proc(T: type/[]$E, len: int) -> T {
- return make(T, len);
- }
-
-
- // Only allow types that are specializations of `Table`
- allocate :: proc(table: ^$T/Table, capacity: int) {
- c := context;
- if table.allocator.procedure != nil do c.allocator = table.allocator;
-
- push_context c {
- table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
- }
- }
-
- expand :: proc(table: ^$T/Table) {
- c := context;
- if table.allocator.procedure != nil do c.allocator = table.allocator;
-
- push_context c {
- old_slots := table.slots;
-
- cap := max(2*cap(table.slots), TABLE_SIZE_MIN);
- allocate(table, cap);
-
- for s in old_slots do if s.occupied {
- put(table, s.key, s.value);
- }
-
- free(old_slots);
- }
- }
-
- // Polymorphic determination of a polymorphic struct
- // put :: proc(table: ^$T/Table, key: T.Key, value: T.Value) {
- put :: proc(table: ^Table($Key, $Value), key: Key, value: Value) {
- hash := get_hash(key); // Ad-hoc method which would fail in a different scope
- index := find_index(table, key, hash);
- if index < 0 {
- if f64(table.count) >= 0.75*f64(cap(table.slots)) {
- expand(table);
- }
- assert(table.count <= cap(table.slots));
-
- hash := get_hash(key);
- index = int(hash % u32(cap(table.slots)));
-
- for table.slots[index].occupied {
- if index += 1; index >= cap(table.slots) {
- index = 0;
- }
- }
-
- table.count += 1;
- }
-
- slot := &table.slots[index];
- slot.occupied = true;
- slot.hash = hash;
- slot.key = key;
- slot.value = value;
- }
-
-
- // find :: proc(table: ^$T/Table, key: T.Key) -> (T.Value, bool) {
- find :: proc(table: ^Table($Key, $Value), key: Key) -> (Value, bool) {
- hash := get_hash(key);
- index := find_index(table, key, hash);
- if index < 0 {
- return Value{}, false;
- }
- return table.slots[index].value, true;
- }
-
- find_index :: proc(table: ^Table($Key, $Value), key: Key, hash: u32) -> int {
- if cap(table.slots) <= 0 do return -1;
-
- index := int(hash % u32(cap(table.slots)));
- for table.slots[index].occupied {
- if table.slots[index].hash == hash {
- if table.slots[index].key == key {
- return index;
- }
- }
-
- if index += 1; index >= cap(table.slots) {
- index = 0;
- }
- }
-
- return -1;
- }
-
- get_hash :: proc(s: string) -> u32 { // fnv32a
- h: u32 = 0x811c9dc5;
- for i in 0..len(s) {
- h = (h ~ u32(s[i])) * 0x01000193;
- }
- return h;
- }
-
-
- table: Table(string, int);
-
- for i in 0..36 do put(&table, "Hellope", i);
- for i in 0..42 do put(&table, "World!", i);
-
- found, _ := find(&table, "Hellope");
- fmt.printf("`found` is %v\n", found);
-
- found, _ = find(&table, "World!");
- fmt.printf("`found` is %v\n", found);
-
- // I would not personally design a hash table like this in production
- // but this is a nice basic example
- // A better approach would either use a `u64` or equivalent for the key
- // and let the user specify the hashing function or make the user store
- // the hashing procedure with the table
- }
-}
-
-
-
-
-prefix_table := [?]string{
- "White",
- "Red",
- "Green",
- "Blue",
- "Octarine",
- "Black",
-};
-
-threading_example :: proc() {
- when ODIN_OS == "windows" {
- unordered_remove :: proc(array: ^[]$T, index: int, loc := #caller_location) {
- __bounds_check_error_loc(loc, index, len(array));
- array[index] = array[len(array)-1];
- pop(array);
- }
- ordered_remove :: proc(array: ^[]$T, index: int, loc := #caller_location) {
- __bounds_check_error_loc(loc, index, len(array));
- copy(array[index..], array[index+1..]);
- pop(array);
- }
-
- worker_proc :: proc(t: ^thread.Thread) -> int {
- for iteration in 1..5 {
- fmt.printf("Thread %d is on iteration %d\n", t.user_index, iteration);
- fmt.printf("`%s`: iteration %d\n", prefix_table[t.user_index], iteration);
- // win32.sleep(1);
- }
- return 0;
- }
-
- threads := make([]^thread.Thread, 0, len(prefix_table));
- defer free(threads);
-
- for i in 0..len(prefix_table) {
- if t := thread.create(worker_proc); t != nil {
- t.init_context = context;
- t.use_init_context = true;
- t.user_index = len(threads);
- append(&threads, t);
- thread.start(t);
- }
- }
-
- for len(threads) > 0 {
- for i := 0; i < len(threads); /**/ {
- if t := threads[i]; thread.is_done(t) {
- fmt.printf("Thread %d is done\n", t.user_index);
- thread.destroy(t);
-
- ordered_remove(&threads, i);
- } else {
- i += 1;
- }
- }
- }
- }
-}
-
-main :: proc() {
- when false {
- fmt.println("\n# general_stuff"); general_stuff();
- fmt.println("\n# default_struct_values"); default_struct_values();
- fmt.println("\n# union_type"); union_type();
- fmt.println("\n# parametric_polymorphism"); parametric_polymorphism();
- fmt.println("\n# threading_example"); threading_example();
- }
-}
-
diff --git a/misc/old_demos/demo008.odin b/misc/old_demos/demo008.odin
deleted file mode 100644
index a122414e7..000000000
--- a/misc/old_demos/demo008.odin
+++ /dev/null
@@ -1,778 +0,0 @@
-import "core:fmt.odin"
-import "core:strconv.odin"
-import "core:mem.odin"
-import "core:bits.odin"
-import "core:hash.odin"
-import "core:math.odin"
-import "core:math/rand.odin"
-import "core:os.odin"
-import "core:raw.odin"
-import "core:sort.odin"
-import "core:strings.odin"
-import "core:types.odin"
-import "core:utf16.odin"
-import "core:utf8.odin"
-
-// File scope `when` statements
-when ODIN_OS == "windows" {
- import "core:atomics.odin"
- import "core:thread.odin"
- import win32 "core:sys/windows.odin"
-}
-
-@(link_name="general_stuff")
-general_stuff :: proc() {
- fmt.println("# general_stuff");
- { // `do` for inline statements rather than block
- foo :: proc() do fmt.println("Foo!");
- if false do foo();
- for false do foo();
- when false do foo();
-
- if false do foo();
- else do foo();
- }
-
- { // Removal of `++` and `--` (again)
- x: int;
- x += 1;
- x -= 1;
- }
- { // Casting syntaxes
- i := i32(137);
- ptr := &i;
-
- _ = (^f32)(ptr);
- // ^f32(ptr) == ^(f32(ptr))
- _ = cast(^f32)ptr;
-
- _ = (^f32)(ptr)^;
- _ = (cast(^f32)ptr)^;
-
- // Questions: Should there be two ways to do it?
- }
-
- /*
- * Remove *_val_of built-in procedures
- * size_of, align_of, offset_of
- * type_of, type_info_of
- */
-
- { // `expand_to_tuple` built-in procedure
- Foo :: struct {
- x: int,
- b: bool,
- }
- f := Foo{137, true};
- x, b := expand_to_tuple(f);
- fmt.println(f);
- fmt.println(x, b);
- fmt.println(expand_to_tuple(f));
- }
-
- {
- // .. half-closed range
- // .. open range
-
- for in 0..2 {} // 0, 1
- for in 0..2 {} // 0, 1, 2
- }
-
- { // Multiple sized booleans
-
- x0: bool; // default
- x1: b8 = true;
- x2: b16 = false;
- x3: b32 = true;
- x4: b64 = false;
-
- fmt.printf("x1: %T = %v;\n", x1, x1);
- fmt.printf("x2: %T = %v;\n", x2, x2);
- fmt.printf("x3: %T = %v;\n", x3, x3);
- fmt.printf("x4: %T = %v;\n", x4, x4);
-
- // Having specific sized booleans is very useful when dealing with foreign code
- // and to enforce specific alignment for a boolean, especially within a struct
- }
-
- { // `distinct` types
- // Originally, all type declarations would create a distinct type unless #type_alias was present.
- // Now the behaviour has been reversed. All type declarations create a type alias unless `distinct` is present.
- // If the type expression is `struct`, `union`, `enum`, or `proc`, the types will always been distinct.
-
- Int32 :: i32;
- #assert(Int32 == i32);
-
- My_Int32 :: distinct i32;
- #assert(My_Int32 != i32);
-
- My_Struct :: struct{x: int};
- #assert(My_Struct != struct{x: int});
- }
-}
-
-default_struct_values :: proc() {
- fmt.println("# default_struct_values");
- {
- Vector3 :: struct {
- x: f32,
- y: f32,
- z: f32,
- }
- v: Vector3;
- fmt.println(v);
- }
- {
- // Default values must be constants
- Vector3 :: struct {
- x: f32 = 1,
- y: f32 = 4,
- z: f32 = 9,
- }
- v: Vector3;
- fmt.println(v);
-
- v = Vector3{};
- fmt.println(v);
-
- // Uses the same semantics as a default values in a procedure
- v = Vector3{137};
- fmt.println(v);
-
- v = Vector3{z = 137};
- fmt.println(v);
- }
-
- {
- Vector3 :: struct {
- x := 1.0,
- y := 4.0,
- z := 9.0,
- }
- stack_default: Vector3;
- stack_literal := Vector3{};
- heap_one := new(Vector3); defer free(heap_one);
- heap_two := new_clone(Vector3{}); defer free(heap_two);
-
- fmt.println("stack_default - ", stack_default);
- fmt.println("stack_literal - ", stack_literal);
- fmt.println("heap_one - ", heap_one^);
- fmt.println("heap_two - ", heap_two^);
-
-
- N :: 4;
- stack_array: [N]Vector3;
- heap_array := new([N]Vector3); defer free(heap_array);
- heap_slice := make([]Vector3, N); defer free(heap_slice);
- fmt.println("stack_array[1] - ", stack_array[1]);
- fmt.println("heap_array[1] - ", heap_array[1]);
- fmt.println("heap_slice[1] - ", heap_slice[1]);
- }
-}
-
-
-
-
-union_type :: proc() {
- fmt.println("\n# union_type");
- {
- val: union{int, bool};
- val = 137;
- if i, ok := val.(int); ok {
- fmt.println(i);
- }
- val = true;
- fmt.println(val);
-
- val = nil;
-
- switch v in val {
- case int: fmt.println("int", v);
- case bool: fmt.println("bool", v);
- case: fmt.println("nil");
- }
- }
- {
- // There is a duality between `any` and `union`
- // An `any` has a pointer to the data and allows for any type (open)
- // A `union` has as binary blob to store the data and allows only certain types (closed)
- // The following code is with `any` but has the same syntax
- val: any;
- val = 137;
- if i, ok := val.(int); ok {
- fmt.println(i);
- }
- val = true;
- fmt.println(val);
-
- val = nil;
-
- switch v in val {
- case int: fmt.println("int", v);
- case bool: fmt.println("bool", v);
- case: fmt.println("nil");
- }
- }
-
- Vector3 :: struct {x, y, z: f32};
- Quaternion :: struct {x, y, z: f32, w: f32 = 1};
-
- // More realistic examples
- {
- // NOTE(bill): For the above basic examples, you may not have any
- // particular use for it. However, my main use for them is not for these
- // simple cases. My main use is for hierarchical types. Many prefer
- // subtyping, embedding the base data into the derived types. Below is
- // an example of this for a basic game Entity.
-
- Entity :: struct {
- id: u64,
- name: string,
- position: Vector3,
- orientation: Quaternion,
-
- derived: any,
- }
-
- Frog :: struct {
- using entity: Entity,
- jump_height: f32,
- }
-
- Monster :: struct {
- using entity: Entity,
- is_robot: bool,
- is_zombie: bool,
- }
-
- // See `parametric_polymorphism` procedure for details
- new_entity :: proc(T: type) -> ^Entity {
- t := new(T);
- t.derived = t^;
- return t;
- }
-
- entity := new_entity(Monster);
-
- switch e in entity.derived {
- case Frog:
- fmt.println("Ribbit");
- case Monster:
- if e.is_robot do fmt.println("Robotic");
- if e.is_zombie do fmt.println("Grrrr!");
- }
- }
-
- {
- // NOTE(bill): A union can be used to achieve something similar. Instead
- // of embedding the base data into the derived types, the derived data
- // in embedded into the base type. Below is the same example of the
- // basic game Entity but using an union.
-
- Entity :: struct {
- id: u64,
- name: string,
- position: Vector3,
- orientation: Quaternion,
-
- derived: union {Frog, Monster},
- }
-
- Frog :: struct {
- using entity: ^Entity,
- jump_height: f32,
- }
-
- Monster :: struct {
- using entity: ^Entity,
- is_robot: bool,
- is_zombie: bool,
- }
-
- // See `parametric_polymorphism` procedure for details
- new_entity :: proc(T: type) -> ^Entity {
- t := new(Entity);
- t.derived = T{entity = t};
- return t;
- }
-
- entity := new_entity(Monster);
-
- switch e in entity.derived {
- case Frog:
- fmt.println("Ribbit");
- case Monster:
- if e.is_robot do fmt.println("Robotic");
- if e.is_zombie do fmt.println("Grrrr!");
- }
-
- // NOTE(bill): As you can see, the usage code has not changed, only its
- // memory layout. Both approaches have their own advantages but they can
- // be used together to achieve different results. The subtyping approach
- // can allow for a greater control of the memory layout and memory
- // allocation, e.g. storing the derivatives together. However, this is
- // also its disadvantage. You must either preallocate arrays for each
- // derivative separation (which can be easily missed) or preallocate a
- // bunch of "raw" memory; determining the maximum size of the derived
- // types would require the aid of metaprogramming. Unions solve this
- // particular problem as the data is stored with the base data.
- // Therefore, it is possible to preallocate, e.g. [100]Entity.
-
- // It should be noted that the union approach can have the same memory
- // layout as the any and with the same type restrictions by using a
- // pointer type for the derivatives.
-
- /*
- Entity :: struct {
- ..
- derived: union{^Frog, ^Monster},
- }
-
- Frog :: struct {
- using entity: Entity,
- ..
- }
- Monster :: struct {
- using entity: Entity,
- ..
-
- }
- new_entity :: proc(T: type) -> ^Entity {
- t := new(T);
- t.derived = t;
- return t;
- }
- */
- }
-}
-
-parametric_polymorphism :: proc() {
- fmt.println("# parametric_polymorphism");
-
- print_value :: proc(value: $T) {
- fmt.printf("print_value: %T %v\n", value, value);
- }
-
- v1: int = 1;
- v2: f32 = 2.1;
- v3: f64 = 3.14;
- v4: string = "message";
-
- print_value(v1);
- print_value(v2);
- print_value(v3);
- print_value(v4);
-
- fmt.println();
-
- add :: proc(p, q: $T) -> T {
- x: T = p + q;
- return x;
- }
-
- a := add(3, 4);
- fmt.printf("a: %T = %v\n", a, a);
-
- b := add(3.2, 4.3);
- fmt.printf("b: %T = %v\n", b, b);
-
- // This is how `new` is implemented
- alloc_type :: proc(T: type) -> ^T {
- t := cast(^T)alloc(size_of(T), align_of(T));
- t^ = T{}; // Use default initialization value
- return t;
- }
-
- copy_slice :: proc(dst, src: []$T) -> int {
- return mem.copy(&dst[0], &src[0], n*size_of(T));
- }
-
- double_params :: proc(a: $A, b: $B) -> A {
- return a + A(b);
- }
-
- fmt.println(double_params(12, 1.345));
-
-
-
- { // Polymorphic Types and Type Specialization
- Table_Slot :: struct(Key, Value: type) {
- occupied: bool,
- hash: u32,
- key: Key,
- value: Value,
- }
- TABLE_SIZE_MIN :: 32;
- Table :: struct(Key, Value: type) {
- count: int,
- allocator: Allocator,
- slots: []Table_Slot(Key, Value),
- }
-
- // Only allow types that are specializations of a (polymorphic) slice
- make_slice :: proc(T: type/[]$E, len: int) -> T {
- return make(T, len);
- }
-
-
- // Only allow types that are specializations of `Table`
- allocate :: proc(table: ^$T/Table, capacity: int) {
- c := context;
- if table.allocator.procedure != nil do c.allocator = table.allocator;
-
- context <- c {
- table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
- }
- }
-
- expand :: proc(table: ^$T/Table) {
- c := context;
- if table.allocator.procedure != nil do c.allocator = table.allocator;
-
- context <- c {
- old_slots := table.slots;
-
- cap := max(2*len(table.slots), TABLE_SIZE_MIN);
- allocate(table, cap);
-
- for s in old_slots do if s.occupied {
- put(table, s.key, s.value);
- }
-
- free(old_slots);
- }
- }
-
- // Polymorphic determination of a polymorphic struct
- // put :: proc(table: ^$T/Table, key: T.Key, value: T.Value) {
- put :: proc(table: ^Table($Key, $Value), key: Key, value: Value) {
- hash := get_hash(key); // Ad-hoc method which would fail in a different scope
- index := find_index(table, key, hash);
- if index < 0 {
- if f64(table.count) >= 0.75*f64(len(table.slots)) {
- expand(table);
- }
- assert(table.count <= len(table.slots));
-
- hash := get_hash(key);
- index = int(hash % u32(len(table.slots)));
-
- for table.slots[index].occupied {
- if index += 1; index >= len(table.slots) {
- index = 0;
- }
- }
-
- table.count += 1;
- }
-
- slot := &table.slots[index];
- slot.occupied = true;
- slot.hash = hash;
- slot.key = key;
- slot.value = value;
- }
-
-
- // find :: proc(table: ^$T/Table, key: T.Key) -> (T.Value, bool) {
- find :: proc(table: ^Table($Key, $Value), key: Key) -> (Value, bool) {
- hash := get_hash(key);
- index := find_index(table, key, hash);
- if index < 0 {
- return Value{}, false;
- }
- return table.slots[index].value, true;
- }
-
- find_index :: proc(table: ^Table($Key, $Value), key: Key, hash: u32) -> int {
- if len(table.slots) <= 0 do return -1;
-
- index := int(hash % u32(len(table.slots)));
- for table.slots[index].occupied {
- if table.slots[index].hash == hash {
- if table.slots[index].key == key {
- return index;
- }
- }
-
- if index += 1; index >= len(table.slots) {
- index = 0;
- }
- }
-
- return -1;
- }
-
- get_hash :: proc(s: string) -> u32 { // fnv32a
- h: u32 = 0x811c9dc5;
- for i in 0..len(s) {
- h = (h ~ u32(s[i])) * 0x01000193;
- }
- return h;
- }
-
-
- table: Table(string, int);
-
- for i in 0..36 do put(&table, "Hellope", i);
- for i in 0..42 do put(&table, "World!", i);
-
- found, _ := find(&table, "Hellope");
- fmt.printf("`found` is %v\n", found);
-
- found, _ = find(&table, "World!");
- fmt.printf("`found` is %v\n", found);
-
- // I would not personally design a hash table like this in production
- // but this is a nice basic example
- // A better approach would either use a `u64` or equivalent for the key
- // and let the user specify the hashing function or make the user store
- // the hashing procedure with the table
- }
-}
-
-
-
-
-prefix_table := [?]string{
- "White",
- "Red",
- "Green",
- "Blue",
- "Octarine",
- "Black",
-};
-
-threading_example :: proc() {
- when ODIN_OS == "windows" {
- fmt.println("# threading_example");
-
- unordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
- __bounds_check_error_loc(loc, index, len(array));
- array[index] = array[len(array)-1];
- pop(array);
- }
- ordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
- __bounds_check_error_loc(loc, index, len(array));
- copy(array[index..], array[index+1..]);
- pop(array);
- }
-
- worker_proc :: proc(t: ^thread.Thread) -> int {
- for iteration in 1..5 {
- fmt.printf("Thread %d is on iteration %d\n", t.user_index, iteration);
- fmt.printf("`%s`: iteration %d\n", prefix_table[t.user_index], iteration);
- // win32.sleep(1);
- }
- return 0;
- }
-
- threads := make([dynamic]^thread.Thread, 0, len(prefix_table));
- defer free(threads);
-
- for in prefix_table {
- if t := thread.create(worker_proc); t != nil {
- t.init_context = context;
- t.use_init_context = true;
- t.user_index = len(threads);
- append(&threads, t);
- thread.start(t);
- }
- }
-
- for len(threads) > 0 {
- for i := 0; i < len(threads); /**/ {
- if t := threads[i]; thread.is_done(t) {
- fmt.printf("Thread %d is done\n", t.user_index);
- thread.destroy(t);
-
- ordered_remove(&threads, i);
- } else {
- i += 1;
- }
- }
- }
- }
-}
-
-array_programming :: proc() {
- fmt.println("# array_programming");
- {
- a := [3]f32{1, 2, 3};
- b := [3]f32{5, 6, 7};
- c := a * b;
- d := a + b;
- e := 1 + (c - d) / 2;
- fmt.printf("%.1f\n", e); // [0.5, 3.0, 6.5]
- }
-
- {
- a := [3]f32{1, 2, 3};
- b := swizzle(a, 2, 1, 0);
- assert(b == [3]f32{3, 2, 1});
-
- c := swizzle(a, 0, 0);
- assert(c == [2]f32{1, 1});
- assert(c == 1);
- }
-
- {
- Vector3 :: distinct [3]f32;
- a := Vector3{1, 2, 3};
- b := Vector3{5, 6, 7};
- c := (a * b)/2 + 1;
- d := c.x + c.y + c.z;
- fmt.printf("%.1f\n", d); // 22.0
-
- cross :: proc(a, b: Vector3) -> Vector3 {
- i := swizzle(a, 1, 2, 0) * swizzle(b, 2, 0, 1);
- j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0);
- return i - j;
- }
-
- blah :: proc(a: Vector3) -> f32 {
- return a.x + a.y + a.z;
- }
-
- x := cross(a, b);
- fmt.println(x);
- fmt.println(blah(x));
- }
-}
-
-
-using println in import "core:fmt.odin"
-
-using_in :: proc() {
- fmt.println("# using in");
- using print in fmt;
-
- println("Hellope1");
- print("Hellope2\n");
-
- Foo :: struct {
- x, y: int,
- b: bool,
- }
- f: Foo;
- f.x, f.y = 123, 321;
- println(f);
- using x, y in f;
- x, y = 456, 654;
- println(f);
-}
-
-named_proc_return_parameters :: proc() {
- fmt.println("# named proc return parameters");
-
- foo0 :: proc() -> int {
- return 123;
- }
- foo1 :: proc() -> (a: int) {
- a = 123;
- return;
- }
- foo2 :: proc() -> (a, b: int) {
- // Named return values act like variables within the scope
- a = 321;
- b = 567;
- return b, a;
- }
- fmt.println("foo0 =", foo0()); // 123
- fmt.println("foo1 =", foo1()); // 123
- fmt.println("foo2 =", foo2()); // 567 321
-}
-
-
-enum_export :: proc() {
- fmt.println("# enum #export");
-
- Foo :: enum #export {A, B, C};
-
- f0 := A;
- f1 := B;
- f2 := C;
- fmt.println(f0, f1, f2);
-}
-
-explicit_procedure_overloading :: proc() {
- fmt.println("# explicit procedure overloading");
-
- add_ints :: proc(a, b: int) -> int {
- x := a + b;
- fmt.println("add_ints", x);
- return x;
- }
- add_floats :: proc(a, b: f32) -> f32 {
- x := a + b;
- fmt.println("add_floats", x);
- return x;
- }
- add_numbers :: proc(a: int, b: f32, c: u8) -> int {
- x := int(a) + int(b) + int(c);
- fmt.println("add_numbers", x);
- return x;
- }
-
- add :: proc[add_ints, add_floats, add_numbers];
-
- add(int(1), int(2));
- add(f32(1), f32(2));
- add(int(1), f32(2), u8(3));
-
- add(1, 2); // untyped ints coerce to int tighter than f32
- add(1.0, 2.0); // untyped floats coerce to f32 tighter than int
- add(1, 2, 3); // three parameters
-
- // Ambiguous answers
- // add(1.0, 2);
- // add(1, 2.0);
-}
-
-complete_switch :: proc() {
- fmt.println("# complete_switch");
- { // enum
- Foo :: enum #export {
- A,
- B,
- C,
- D,
- }
-
- b := Foo.B;
- f := Foo.A;
- #complete switch f {
- case A: fmt.println("A");
- case B: fmt.println("B");
- case C: fmt.println("C");
- case D: fmt.println("D");
- case: fmt.println("?");
- }
- }
- { // union
- Foo :: union {int, bool};
- f: Foo = 123;
- #complete switch in f {
- case int: fmt.println("int");
- case bool: fmt.println("bool");
- case:
- }
- }
-}
-
-
-main :: proc() {
- when true {
- general_stuff();
- default_struct_values();
- union_type();
- parametric_polymorphism();
- threading_example();
- array_programming();
- using_in();
- named_proc_return_parameters();
- enum_export();
- explicit_procedure_overloading();
- complete_switch();
- }
-}
diff --git a/misc/old_demos/old_runtime.odin b/misc/old_demos/old_runtime.odin
deleted file mode 100644
index e605e7820..000000000
--- a/misc/old_demos/old_runtime.odin
+++ /dev/null
@@ -1,412 +0,0 @@
-#include "win32.odin"
-
-assume :: proc(cond: bool) #foreign "llvm.assume"
-
-__debug_trap :: proc() #foreign "llvm.debugtrap"
-__trap :: proc() #foreign "llvm.trap"
-read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter"
-
-bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16"
-bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32"
-bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64"
-
-byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16"
-byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32"
-byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64"
-
-fmuladd_f32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
-fmuladd_f64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
-
-// TODO(bill): make custom heap procedures
-heap_alloc :: proc(len: int) -> rawptr #foreign "malloc"
-heap_dealloc :: proc(ptr: rawptr) #foreign "free"
-
-memory_zero :: proc(data: rawptr, len: int) {
- d := slice_ptr(data as ^byte, len)
- for i := 0; i < len; i++ {
- d[i] = 0
- }
-}
-
-memory_compare :: proc(dst, src: rawptr, len: int) -> int {
- s1, s2: ^byte = dst, src
- for i := 0; i < len; i++ {
- a := ptr_offset(s1, i)^
- b := ptr_offset(s2, i)^
- if a != b {
- return (a - b) as int
- }
- }
- return 0
-}
-
-memory_copy :: proc(dst, src: rawptr, n: int) #inline {
- if dst == src {
- return
- }
-
- v128b :: type {4}u32
- #assert(align_of(v128b) == 16)
-
- d, s: ^byte = dst, src
-
- for ; s as uint % 16 != 0 && n != 0; n-- {
- d^ = s^
- d, s = ptr_offset(d, 1), ptr_offset(s, 1)
- }
-
- if d as uint % 16 == 0 {
- for ; n >= 16; d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 {
- (d as ^v128b)^ = (s as ^v128b)^
- }
-
- if n&8 != 0 {
- (d as ^u64)^ = (s as ^u64)^
- d, s = ptr_offset(d, 8), ptr_offset(s, 8)
- }
- if n&4 != 0 {
- (d as ^u32)^ = (s as ^u32)^;
- d, s = ptr_offset(d, 4), ptr_offset(s, 4)
- }
- if n&2 != 0 {
- (d as ^u16)^ = (s as ^u16)^
- d, s = ptr_offset(d, 2), ptr_offset(s, 2)
- }
- if n&1 != 0 {
- d^ = s^
- d, s = ptr_offset(d, 1), ptr_offset(s, 1)
- }
- return;
- }
-
- // IMPORTANT NOTE(bill): Little endian only
- LS :: proc(a, b: u32) -> u32 #inline { return a << b }
- RS :: proc(a, b: u32) -> u32 #inline { return a >> b }
- /* NOTE(bill): Big endian version
- LS :: proc(a, b: u32) -> u32 #inline { return a >> b; }
- RS :: proc(a, b: u32) -> u32 #inline { return a << b; }
- */
-
- w, x: u32
-
- if d as uint % 4 == 1 {
- w = (s as ^u32)^
- d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
- d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
- d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
- n -= 3
-
- for n > 16 {
- d32 := d as ^u32
- s32 := ptr_offset(s, 1) as ^u32
- x = s32^; d32^ = LS(w, 24) | RS(x, 8)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- w = s32^; d32^ = LS(x, 24) | RS(w, 8)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- x = s32^; d32^ = LS(w, 24) | RS(x, 8)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- w = s32^; d32^ = LS(x, 24) | RS(w, 8)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-
- d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
- }
-
- } else if d as uint % 4 == 2 {
- w = (s as ^u32)^
- d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
- d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
- n -= 2
-
- for n > 17 {
- d32 := d as ^u32
- s32 := ptr_offset(s, 2) as ^u32
- x = s32^; d32^ = LS(w, 16) | RS(x, 16)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- w = s32^; d32^ = LS(x, 16) | RS(w, 16)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- x = s32^; d32^ = LS(w, 16) | RS(x, 16)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- w = s32^; d32^ = LS(x, 16) | RS(w, 16)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-
- d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
- }
-
- } else if d as uint % 4 == 3 {
- w = (s as ^u32)^
- d^ = s^
- n -= 1
-
- for n > 18 {
- d32 := d as ^u32
- s32 := ptr_offset(s, 3) as ^u32
- x = s32^; d32^ = LS(w, 8) | RS(x, 24)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- w = s32^; d32^ = LS(x, 8) | RS(w, 24)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- x = s32^; d32^ = LS(w, 8) | RS(x, 24)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
- w = s32^; d32^ = LS(x, 8) | RS(w, 24)
- d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
-
- d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
- }
- }
-
- if n&16 != 0 {
- (d as ^v128b)^ = (s as ^v128b)^
- d, s = ptr_offset(d, 16), ptr_offset(s, 16)
- }
- if n&8 != 0 {
- (d as ^u64)^ = (s as ^u64)^
- d, s = ptr_offset(d, 8), ptr_offset(s, 8)
- }
- if n&4 != 0 {
- (d as ^u32)^ = (s as ^u32)^;
- d, s = ptr_offset(d, 4), ptr_offset(s, 4)
- }
- if n&2 != 0 {
- (d as ^u16)^ = (s as ^u16)^
- d, s = ptr_offset(d, 2), ptr_offset(s, 2)
- }
- if n&1 != 0 {
- d^ = s^
- }
-}
-
-memory_move :: proc(dst, src: rawptr, n: int) #inline {
- d, s: ^byte = dst, src
- if d == s {
- return
- }
- if d >= ptr_offset(s, n) || ptr_offset(d, n) <= s {
- memory_copy(d, s, n)
- return
- }
-
- // TODO(bill): Vectorize the shit out of this
- if d < s {
- if s as int % size_of(int) == d as int % size_of(int) {
- for d as int % size_of(int) != 0 {
- if n == 0 {
- return
- }
- n--
- d^ = s^
- d, s = ptr_offset(d, 1), ptr_offset(s, 1)
- }
- di, si := d as ^int, s as ^int
- for n >= size_of(int) {
- di^ = si^
- di, si = ptr_offset(di, 1), ptr_offset(si, 1)
- n -= size_of(int)
- }
- }
- for ; n > 0; n-- {
- d^ = s^
- d, s = ptr_offset(d, 1), ptr_offset(s, 1)
- }
- } else {
- if s as int % size_of(int) == d as int % size_of(int) {
- for ptr_offset(d, n) as int % size_of(int) != 0 {
- if n == 0 {
- return
- }
- n--
- d^ = s^
- d, s = ptr_offset(d, 1), ptr_offset(s, 1)
- }
- for n >= size_of(int) {
- n -= size_of(int)
- di := ptr_offset(d, n) as ^int
- si := ptr_offset(s, n) as ^int
- di^ = si^
- }
- for ; n > 0; n-- {
- d^ = s^
- d, s = ptr_offset(d, 1), ptr_offset(s, 1)
- }
- }
- for n > 0 {
- n--
- dn := ptr_offset(d, n)
- sn := ptr_offset(s, n)
- dn^ = sn^
- }
- }
-}
-
-__string_eq :: proc(a, b: string) -> bool {
- if len(a) != len(b) {
- return false
- }
- if ^a[0] == ^b[0] {
- return true
- }
- return memory_compare(^a[0], ^b[0], len(a)) == 0
-}
-
-__string_cmp :: proc(a, b : string) -> int {
- min_len := len(a)
- if len(b) < min_len {
- min_len = len(b)
- }
- for i := 0; i < min_len; i++ {
- x := a[i]
- y := b[i]
- if x < y {
- return -1
- } else if x > y {
- return +1
- }
- }
-
- if len(a) < len(b) {
- return -1
- } else if len(a) > len(b) {
- return +1
- }
- return 0
-}
-
-__string_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) }
-__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 }
-__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 }
-__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
-__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
-
-
-
-
-Allocation_Mode :: type enum {
- ALLOC,
- DEALLOC,
- DEALLOC_ALL,
- RESIZE,
-}
-
-
-
-Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocation_Mode,
- size, alignment: int,
- old_memory: rawptr, old_size: int, flags: u64) -> rawptr
-
-Allocator :: type struct {
- procedure: Allocator_Proc;
- data: rawptr
-}
-
-
-Context :: type struct {
- thread_ptr: rawptr
-
- user_data: rawptr
- user_index: int
-
- allocator: Allocator
-}
-
-#thread_local context: Context
-
-DEFAULT_ALIGNMENT :: 2*size_of(int)
-
-
-__check_context :: proc() {
- if context.allocator.procedure == null {
- context.allocator = __default_allocator()
- }
- if context.thread_ptr == null {
- // TODO(bill):
- // context.thread_ptr = current_thread_pointer()
- }
-}
-
-
-alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT) }
-
-alloc_align :: proc(size, alignment: int) -> rawptr #inline {
- __check_context()
- a := context.allocator
- return a.procedure(a.data, Allocation_Mode.ALLOC, size, alignment, null, 0, 0)
-}
-
-dealloc :: proc(ptr: rawptr) #inline {
- __check_context()
- a := context.allocator
- _ = a.procedure(a.data, Allocation_Mode.DEALLOC, 0, 0, ptr, 0, 0)
-}
-dealloc_all :: proc(ptr: rawptr) #inline {
- __check_context()
- a := context.allocator
- _ = a.procedure(a.data, Allocation_Mode.DEALLOC_ALL, 0, 0, ptr, 0, 0)
-}
-
-
-resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT) }
-resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
- __check_context()
- a := context.allocator
- return a.procedure(a.data, Allocation_Mode.RESIZE, new_size, alignment, ptr, old_size, 0)
-}
-
-
-
-default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
- if old_memory == null {
- return alloc_align(new_size, alignment)
- }
-
- if new_size == 0 {
- dealloc(old_memory)
- return null
- }
-
- if new_size == old_size {
- return old_memory
- }
-
- new_memory := alloc_align(new_size, alignment)
- if new_memory == null {
- return null
- }
-
- memory_copy(new_memory, old_memory, min(old_size, new_size));
- dealloc(old_memory)
- return new_memory
-}
-
-
-__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocation_Mode,
- size, alignment: int,
- old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
- using Allocation_Mode
- match mode {
- case ALLOC:
- return heap_alloc(size)
- case RESIZE:
- return default_resize_align(old_memory, old_size, size, alignment)
- case DEALLOC:
- heap_dealloc(old_memory)
- case DEALLOC_ALL:
- // NOTE(bill): Does nothing
- }
-
- return null
-}
-
-__default_allocator :: proc() -> Allocator {
- return Allocator{
- __default_allocator_proc,
- null,
- }
-}
-
-
-
-
-__assert :: proc(msg: string) {
- file_write(file_get_standard(File_Standard.ERROR), msg as []byte)
- // TODO(bill): Which is better?
- // __trap()
- __debug_trap()
-}
diff --git a/misc/old_stuff/demo_backup.odin b/misc/old_stuff/demo_backup.odin
deleted file mode 100644
index b8bbbb02d..000000000
--- a/misc/old_stuff/demo_backup.odin
+++ /dev/null
@@ -1,430 +0,0 @@
-import (
- "fmt.odin";
- "atomics.odin";
- "bits.odin";
- "decimal.odin";
- "hash.odin";
- "math.odin";
- "mem.odin";
- "opengl.odin";
- "os.odin";
- "raw.odin";
- "strconv.odin";
- "strings.odin";
- "sync.odin";
- "sort.odin";
- "types.odin";
- "utf8.odin";
- "utf16.odin";
-/*
-*/
-)
-
-
-general_stuff :: proc() {
- // Complex numbers
- a := 3 + 4i;
- b: complex64 = 3 + 4i;
- c: complex128 = 3 + 4i;
- d := complex(2, 3);
-
- e := a / conj(a);
- fmt.println("(3+4i)/(3-4i) =", e);
- fmt.println(real(e), "+", imag(e), "i");
-
-
- // C-style variadic procedures
- foreign __llvm_core {
- // The variadic part allows for extra type checking too which C does not provide
- c_printf :: proc(fmt: ^u8, #c_vararg args: ..any) -> i32 #link_name "printf" ---;
- }
- str := "%d\n\x00";
- // c_printf(&str[0], i32(789456123));
-
-
- Foo :: struct {
- x: int;
- y: f32;
- z: string;
- }
- foo := Foo{123, 0.513, "A string"};
- x, y, z := expand_to_tuple(foo);
- fmt.println(x, y, z);
- #assert(type_of(x) == int);
- #assert(type_of(y) == f32);
- #assert(type_of(z) == string);
-
-
- // By default, all variables are zeroed
- // This can be overridden with the "uninitialized value"
- // This is similar to `nil` but applied to everything
- undef_int: int = ---;
-
-
- // Context system is now implemented using Implicit Parameter Passing (IPP)
- // The previous implementation was Thread Local Storage (TLS)
- // IPP has the advantage that it works on systems without TLS and that you can
- // link the context to the stack frame and thus look at previous contexts
- //
- // It does mean that a pointer is implicitly passed procedures with the default
- // Odin calling convention (#cc_odin)
- // This can be overridden with something like #cc_contextless or #cc_c if performance
- // is worried about
-
-}
-
-foreign_blocks :: proc() {
- // See sys/windows.odin
-}
-
-default_arguments :: proc() {
- hello :: proc(a: int = 9, b: int = 9) do fmt.printf("a is %d; b is %d\n", a, b);
- fmt.println("\nTesting default arguments:");
- hello(1, 2);
- hello(1);
- hello();
-}
-
-named_arguments :: proc() {
- Colour :: enum {
- Red,
- Orange,
- Yellow,
- Green,
- Blue,
- Octarine,
- };
- using Colour;
-
- make_character :: proc(name, catch_phrase: string, favourite_colour, least_favourite_colour: Colour) {
- fmt.println();
- fmt.printf("My name is %v and I like %v. %v\n", name, favourite_colour, catch_phrase);
- }
-
- make_character("Frank", "¡Ay, caramba!", Blue, Green);
-
-
- // As the procedures have more and more parameters, it is very easy
- // to get many of the arguments in the wrong order especialy if the
- // types are the same
- make_character("¡Ay, caramba!", "Frank", Green, Blue);
-
- // Named arguments help to disambiguate this problem
- make_character(catch_phrase = "¡Ay, caramba!", name = "Frank",
- least_favourite_colour = Green, favourite_colour = Blue);
-
-
- // The named arguments can be specifed in any order.
- make_character(favourite_colour = Octarine, catch_phrase = "U wot m8!",
- least_favourite_colour = Green, name = "Dennis");
-
-
- // NOTE: You cannot mix named arguments with normal values
- /*
- make_character("Dennis",
- favourite_colour = Octarine, catch_phrase = "U wot m8!",
- least_favourite_colour = Green);
- */
-
-
- // Named arguments can also aid with default arguments
- numerous_things :: proc(s: string, a := 1, b := 2, c := 3.14,
- d := "The Best String!", e := false, f := 10.3/3.1, g := false) {
- g_str := g ? "true" : "false";
- fmt.printf("How many?! %s: %v\n", s, g_str);
- }
-
- numerous_things("First");
- numerous_things(s = "Second", g = true);
-
-
- // Default values can be placed anywhere, not just at the end like in other languages
- weird :: proc(pre: string, mid: int = 0, post: string) {
- fmt.println(pre, mid, post);
- }
-
- weird("How many things", 42, "huh?");
- weird(pre = "Prefix", post = "Pat");
-
-}
-
-
-default_return_values :: proc() {
- foo :: proc(x: int) -> (first: string = "Hellope", second := "world!") {
- match x {
- case 0: return;
- case 1: return "Goodbye";
- case 2: return "Goodbye", "cruel world..";
- case 3: return second = "cruel world..", first = "Goodbye";
- }
-
- return second = "my old friend.";
- }
-
- fmt.printf("%s %s\n", foo(0));
- fmt.printf("%s %s\n", foo(1));
- fmt.printf("%s %s\n", foo(2));
- fmt.printf("%s %s\n", foo(3));
- fmt.printf("%s %s\n", foo(4));
- fmt.println();
-
-
- // A more "real" example
- Error :: enum {
- None,
- WhyTheNumberThree,
- TenIsTooBig,
- };
-
- Entity :: struct {
- name: string;
- id: u32;
- }
-
- some_thing :: proc(input: int) -> (result: ^Entity = nil, err := Error.None) {
- match {
- case input == 3: return err = Error.WhyTheNumberThree;
- case input >= 10: return err = Error.TenIsTooBig;
- }
-
- e := new(Entity);
- e.id = u32(input);
-
- return result = e;
- }
-}
-
-call_location :: proc() {
- amazing :: proc(n: int, using loc := #caller_location) {
- fmt.printf("%s(%d:%d) just asked to do something amazing.\n",
- fully_pathed_filename, line, column);
- fmt.printf("Normal -> %d\n", n);
- fmt.printf("Amazing -> %d\n", n+1);
- fmt.println();
- }
-
- loc := #location(main);
- fmt.println("`main` is located at", loc);
-
- fmt.println("This line is located at", #location());
- fmt.println();
-
- amazing(3);
- amazing(4, #location(call_location));
-
- // See _preload.odin for the implementations of `assert` and `panic`
-
-}
-
-
-explicit_parametric_polymorphic_procedures :: proc() {
- // This is how `new` is actually implemented, see _preload.odin
- alloc_type :: proc(T: type) -> ^T do return cast(^T)alloc(size_of(T), align_of(T));
-
- int_ptr := alloc_type(int);
- defer free(int_ptr);
- int_ptr^ = 137;
- fmt.println(int_ptr, int_ptr^);
-
- // Named arguments work too!
- another_ptr := alloc_type(T = f32);
- defer free(another_ptr);
-
-
- add :: proc(T: type, args: ..T) -> T {
- res: T;
- for arg in args do res += arg;
- return res;
- }
-
- fmt.println("add =", add(int, 1, 2, 3, 4, 5, 6));
-
- swap :: proc(T: type, a, b: ^T) {
- tmp := a^;
- a^ = b^;
- b^ = tmp;
- }
-
- a, b: int = 3, 4;
- fmt.println("Pre-swap:", a, b);
- swap(int, &a, &b);
- fmt.println("Post-swap:", a, b);
- a, b = b, a; // Or use this syntax for this silly example case
-
-
- Vector2 :: struct {x, y: f32;};
- {
- // A more complicated example using subtyping
- // Something like this could be used in a game
-
- Entity :: struct {
- using position: Vector2;
- flags: u64;
- id: u64;
- derived: any;
- }
-
- Rock :: struct {
- using entity: Entity;
- heavy: bool;
- }
- Door :: struct {
- using entity: Entity;
- open: bool;
- }
- Monster :: struct {
- using entity: Entity;
- is_robot: bool;
- is_zombie: bool;
- }
-
- new_entity :: proc(T: type, x, y: f32) -> ^T {
- result := new(T);
- result.derived = result^;
- result.x = x;
- result.y = y;
-
- return result;
- }
-
- entities: [dynamic]^Entity;
-
- rock := new_entity(Rock, 3, 5);
-
- // Named arguments work too!
- door := new_entity(T = Door, x = 3, y = 6);
-
- // And named arguments can be any order
- monster := new_entity(
- y = 1,
- x = 2,
- T = Monster,
- );
-
- append(&entities, rock, door, monster);
-
- fmt.println("Subtyping");
- for entity in entities {
- match e in entity.derived {
- case Rock: fmt.println("Rock", e.x, e.y);
- case Door: fmt.println("Door", e.x, e.y);
- case Monster: fmt.println("Monster", e.x, e.y);
- }
- }
- }
- {
- Entity :: struct {
- using position: Vector2;
- flags: u64;
- id: u64;
- variant: union { Rock, Door, Monster };
- }
-
- Rock :: struct {
- using entity: ^Entity;
- heavy: bool;
- }
- Door :: struct {
- using entity: ^Entity;
- open: bool;
- }
- Monster :: struct {
- using entity: ^Entity;
- is_robot: bool;
- is_zombie: bool;
- }
-
- new_entity :: proc(T: type, x, y: f32) -> ^T {
- result := new(Entity);
- result.variant = T{entity = result};
- result.x = x;
- result.y = y;
-
- return cast(^T)&result.variant;
- }
-
- entities: [dynamic]^Entity;
-
- rock := new_entity(Rock, 3, 5);
-
- // Named arguments work too!
- door := new_entity(T = Door, x = 3, y = 6);
-
- // And named arguments can be any order
- monster := new_entity(
- y = 1,
- x = 2,
- T = Monster,
- );
-
- append(&entities, rock, door, monster);
-
- fmt.println("Union");
- for entity in entities {
- match e in entity.variant {
- case Rock: fmt.println("Rock", e.x, e.y);
- case Door: fmt.println("Door", e.x, e.y);
- case Monster: fmt.println("Monster", e.x, e.y);
- }
- }
- }
-}
-
-
-implicit_polymorphic_assignment :: proc() {
- yep :: proc(p: proc(x: int)) {
- p(123);
- }
-
- frank :: proc(x: $T) do fmt.println("frank ->", x);
- tim :: proc(x, y: $T) do fmt.println("tim ->", x, y);
- yep(frank);
- // yep(tim);
-}
-
-
-
-
-main :: proc() {
-/*
- foo :: proc(x: i64, y: f32) do fmt.println("#1", x, y);
- foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y);
- foo :: proc(x: type) do fmt.println("#3", type_info(x));
-
- f :: foo;
-
- f(y = 3785.1546, x = 123);
- f(x = int, y = 897.513);
- f(x = f32);
-
- general_stuff();
- foreign_blocks();
- default_arguments();
- named_arguments();
- default_return_values();
- call_location();
- explicit_parametric_polymorphic_procedures();
- implicit_polymorphic_assignment();
-
-
- // Command line argument(s)!
- // -opt=0,1,2,3
-*/
-/*
- program := "+ + * - /";
- accumulator := 0;
-
- for token in program {
- match token {
- case '+': accumulator += 1;
- case '-': accumulator -= 1;
- case '*': accumulator *= 2;
- case '/': accumulator /= 2;
- case: // Ignore everything else
- }
- }
-
- fmt.printf("The program \"%s\" calculates the value %d\n",
- program, accumulator);
-*/
-}