123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- 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);
- */
- }
|