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