aboutsummaryrefslogtreecommitdiff
path: root/code
diff options
context:
space:
mode:
Diffstat (limited to 'code')
-rw-r--r--code/demo.odin445
-rw-r--r--code/demo_backup.odin430
2 files changed, 452 insertions, 423 deletions
diff --git a/code/demo.odin b/code/demo.odin
index 8eeaeb357..6e0ae84fa 100644
--- a/code/demo.odin
+++ b/code/demo.odin
@@ -1,430 +1,29 @@
-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);
- compile_assert(type_of(x) == int);
- compile_assert(type_of(y) == f32);
- compile_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";
+import "fmt.odin";
+
+Vector :: struct(N: int, T: type) {
+ using _: raw_union {
+ using e: [N]T;
+ when 0 < N && N <= 4 {
+ using v: struct {
+ when N >= 1 do x: T;
+ when N >= 2 do y: T;
+ when N >= 3 do z: T;
+ when N >= 4 do w: T;
+ };
}
-
- 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);
-}
-
-
-
+Vector3 :: Vector(3, f32);
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);
-*/
+ v: Vector3;
+ v[0] = 1;
+ v[1] = 4;
+ v[2] = 9;
+ fmt.println(v.e);
+ v.x = 4;
+ v.y = 9;
+ v.z = 16;
+ fmt.println(v.v);
}
diff --git a/code/demo_backup.odin b/code/demo_backup.odin
new file mode 100644
index 000000000..8eeaeb357
--- /dev/null
+++ b/code/demo_backup.odin
@@ -0,0 +1,430 @@
+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);
+ compile_assert(type_of(x) == int);
+ compile_assert(type_of(y) == f32);
+ compile_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);
+*/
+}