diff options
| author | Ginger Bill <github@gingerbill.org> | 2016-08-19 15:35:48 +0100 |
|---|---|---|
| committer | Ginger Bill <github@gingerbill.org> | 2016-08-19 15:35:48 +0100 |
| commit | 745237459abb3fa91405fdba3895bd9f810bc9d2 (patch) | |
| tree | 63b2396f1bea12a4cfdf3a334f82a31c9dd28ec0 /examples | |
| parent | ddb15e73c0f378b5d65675ba242e505fb1a3b2f2 (diff) | |
Initial Demo001 code for tour of language
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/demo001.odin | 525 | ||||
| -rw-r--r-- | examples/game.odin (renamed from examples/main.odin) | 8 |
2 files changed, 527 insertions, 6 deletions
diff --git a/examples/demo001.odin b/examples/demo001.odin new file mode 100644 index 000000000..fb08ffa8e --- /dev/null +++ b/examples/demo001.odin @@ -0,0 +1,525 @@ +#load "basic.odin" +#load "math.odin" +// #load "game.odin" + +main :: proc() { + _ = hellope(); + procedures(); + variables(); + constants(); + types(); + data_control(); + // run_game(); +} + +hellope :: proc() -> int { + print_string("Hellope, 世界\n"); + return 1; +} + +apple, banana, carrot: bool; +box, carboard: bool = true, false; +hellope_value := hellope(); + +variables :: proc() { + i: int; // initialized with zero value + j: int = 1; + x, y: int = 1, 2; + + // Type inference + apple, banana, carrot := true, 123, "carrot"; + + + // Basic Types of the Language + // + // bool + // + // i8 i16 i32 i64 i128 + // u8 u16 u32 u64 u128 + // + // f32 f64 + // + // int uint (size_of(int) = size_of(rawptr)) + // + // rawptr + // + // string + // + // byte - alias for u8 + // rune - alias for i32 // Unicode Codepoint + // + // untyped bool - "untyped" types can implicitly convert to any of the "typed" types + // untyped integer + // untyped float + // untyped pointer + // untyped string + // untyped rune + + + // // Zero values + zero_numeric := 0; + zero_boolean := false; + zero_pointer := null; + zero_string1 := ""; // Escaped string + zero_string2 := ``; // Raw string + + // Unary operators + // +a + // -a + // ~a + // !a + + // Binary operators + // a + b + // a - b + // a ~ b + // a | b + + // a * b + // a / b + // a % b + // a & b + // a &~ b == a & (~b) + // a << b + // a >> b + + // a as Type + // a transmute Type + + // a == b + // a != b + // a < b + // a > b + // a <= b + // a >= b + +} + +procedures :: proc() { + add :: proc(x: int, y: int) -> int { + return x + y; + } + print_int(add(3, 4)); // 7 + print_rune('\n'); + + add_v2 :: proc(x, y: int) -> int { + return x + y; + } + + + swap_strings :: proc(x, y: string) -> (string, string) { + return y, x; + } + a, b := swap_strings("Hellope\n", "World\n"); + print_string(a); + print_string(b); + + a, b = b, a; // Quirk of grammar the of multiple assignments + print_string(a); + print_string(b); + + // Not hints, it's mandatory + proc1 :: proc(a, b: int) #inline { + print_int(a + b); + } + proc2 :: proc(a, b: int) #no_inline { + print_int(a + b); + } +} + + +TAU :: 6.28318530718; + +constants :: proc() { + TAU :: 6.28318530718; // untyped float + WORLD_JAPANESE :: "世界"; // untyped string + + TAU_32 : f32 : 6.28318530718; + TAU_AS_32 :: 6.28318530718 as f32; +} + +nl :: proc() { print_rune('\n'); } + +types :: proc() { + + x: int = 123; + y := x; // y: int = x; + // z: f32 = x; // invalid + z: f32 = x as f32; + + ptr_z := ^z; // Pascal notation + ptr_z^ = 123; // Derefence Notation + print_f32(z); nl(); + + // ^z - pointer to z + // z^ - z from pointer + + f32_array: [12]f32; // Array of 12 f32 + f32_array[0] = 2; + f32_array[1] = 3; + // f32_array[-1] = 2; // Error - compile time check + // f32_array[13] = 2; // Error - compile time check + f32_array_len := len(f32_array); // builtin procedure + f32_array_cap := cap(f32_array); // == len(f32_array) + + api: [2]^f32; + papi: ^[2]^f32; + + f32_slice: []f32; // Array reference + f32_slice = f32_array[0:5]; + f32_slice = f32_array[:5]; + f32_slice = f32_array[:]; // f32_array[0:len(f32_array)-1]; + + f32_slice = f32_array[1:5:7]; // low:1, high:5, capacity:7 + + append_success := append(^f32_slice, 1); + _ = append(^f32_slice, 2); + + _ = copy(f32_array[0:2], f32_array[2:4]); // You can use memcpy/memmove if you want + + + s := "Hellope World"; + sub_string := s[5:10]; + + v0: {4}f32; // Vector of 4 f32 + v0[0] = 1; + v0[1] = 3; + v0[2] = 6; + v0[3] = 10; + + v1 := v0 + v0; // Simd Arithmetic + v1 = v1 - v0; + v1 *= v0; // i.e. hadamard product + v1 /= v0; + + // builtin procedure + v2 := swizzle(v0, 3, 2, 1, 0); // {10, 6, 3, 1} + + v3: {4}bool = v0 == v2; + // LLVM rant? + + + type Vec4: {4}f32; + type Array3Int: [3]int; + + type Vec3: struct { + x, y, z: f32 + } + + type BinaryNode: struct { + left, right: ^BinaryNode, // same format as procedure argument + data: rawptr, + } + + type AddProc: proc(a, b: int) -> int + + type Packed: struct #packed { + a: u8, + b: u16, + c: u32, + } + static_assert(size_of(Packed) == 7); + + + { + type MyInt: int + x: int = 1; + y: MyInt = 2; + // z := x + y; // Failure - types cannot implicit convert* + z := x as MyInt + y; // Type cast using `as` + } + + + { + // From: Quake III Arena + Q_rsqrt :: proc(number: f32) -> f32 { + i: i32; + x2, y: f32; + THREE_HALFS :: 1.5; + + x2 = number * 0.5; + y = number; + i = (^y as ^i32)^; // evil floating point bit level hacking + i = 0x5f3759df - i>>1; // what the fuck? + y = (^i as ^f32)^; + y = y * (THREE_HALFS - (x2 * y *y)); // 1st iteration + // y = y * (THREE_HALFS - (x2 * y *y)); // 2nd iteration, this can be removed + return y; + } + + Q_rsqrt_v2 :: proc(number: f32) -> f32 { + THREE_HALFS :: 1.5; + + x2 := number * 0.5; + y := number; + i := y transmute i32; // evil floating point bit level hacking + i = 0x5f3759df - i>>1; // what the fuck? + y = i transmute f32; + y = y * (THREE_HALFS - (x2 * y *y)); // 1st iteration + // y = y * (THREE_HALFS - (x2 * y *y)); // 2nd iteration, this can be removed + return y; + } + + // transmute only works if the size of the types are equal + /{ + // in C + union { + i32 i; + f32 y; + }; + }/ + } + + { // Compound Literals + a := [3]int{1, 2, 3}; + b := [3]int{}; + c := [..]int{1, 2, 3}; + + d := []int{1, 2, 3}; // slice + + e := {4}f32{1, 2, 3, 4}; + f := {4}f32{1}; // broadcasts to all + // g := {4}f32{1, 2}; // require either 1 or 4 elements + + type Vec2: {2}f32; + + h := Vec2{1, 2}; + + i := Vec2{5} * h; // For strong type safety + // FORENOTE: 5 * h was originally allowed but it was an edge case in the + // compiler I didn't think it was enough to justify have it it. + + print_f32(i[0]); print_rune(','); + print_f32(i[1]); print_rune('\n'); + } + + { + do_thing :: proc(p: proc(a, b: int) -> int) { + print_int(p(3, 4)); nl(); + } + + add :: proc(a, b: int) -> int { + return a + b; + } + + + add_lambda := proc(a, b: int) -> int { + return a - b; + }; // note semicolon + + do_thing(add); + do_thing(add_lambda); + do_thing(proc(a, b: int) -> int { + return a * b; + }); + } + + { // strings and runes + escaped := "Hellope World\n"; + raw := `Hellope World\n`; + print_string(escaped); + print_string(raw); nl(); + + // Crap shader example + shader_string := +`#version 410 + +layout (location = 0) in vec3 a_position; +layout (location = 1) in vec3 a_normal; +layout (location = 2) in vec2 a_tex_coord; + +out vec3 v_position; +out vec3 v_normal; +out vec2 v_tex_coord; + +uniform mat4 u_model_view; +uniform mat3 u_normal; +uniform mat4 u_proj; +uniform mat4 u_mvp; + +void main() { + v_tex_coord = a_tex_coord; + v_normal = normalize(u_normal * a_normal); + v_position = vec3(u_model_view * vec4(a_position, 1.0)); + + gl_Position = u_mvp * vec4(a_position, 1.0); +}`; + + + knot1 := '⌘'; + knot2 := '\u2318'; // 16 bit + knot3 := '\U00002318'; // 32 bit + knot4 := "\xe2\x8c\x98"; // Note it's a string, should I allow untyped string -> untyped rune casts? + + // String ideas "nicked" from Go, so far. I think I might change how some of it works later. + } + + + { // size, align, offset + type Thing: struct { + a: u8, + b: u16, + c, d, e: u32, + } + + s := size_of(Thing); + a := align_of(Thing); + o := offset_of(Thing, b); + + t: Thing; + + sv := size_of_val(t); + av := align_of_val(t); + ov := offset_of_val(t.b); + } +} + +data_control :: proc() { + sum := 0; + for i := 0; i < 12; i++ { + sum += 1; + } + print_string("sum = "); print_int(sum); nl(); + + sum = 1; + for ; sum < 1000000; { + sum += sum; + } + print_string("sum = "); print_int(sum); nl(); + + sum = 1; + for sum < 1000000 { + sum += sum; + } + print_string("sum = "); print_int(sum); nl(); + + // loop + // for { } == for true {} + + // Question: Should I separate all these concepts and rename it? + // + // range - iterable + // for - c style + // while + // loop - while true + + // Notes: + // conditions _must_ a boolean expression + // i++ and i-- are statements, not expressions + + + x := 2; + if x < 3 { + print_string("x < 2\n"); + } + + // Unified initializer syntax - same as for statements + if x := 2; x < 3 { + print_string("x < 2\n"); + } + + if x := 4; x < 3 { + print_string("Never called\n"); + } else { + print_string("This is called\n"); + } + + { // String comparison + a := "Hellope"; + b := "World"; + if a < b { + print_string("a < b\n"); + } + if a != b { + print_string("a != b\n"); + } + + } + + + + + { + defer print_string("日本語\n"); + print_string("Japanese\n"); + } + + { + defer print_string("1\n"); + defer print_string("2\n"); + defer print_string("3\n"); + } + + { + // C strings, yuk! + to_c_string :: proc(s: string) -> ^u8 { + c := heap_alloc(len(s)+1) as ^u8; + mem_copy(c, ^s[0], len(s)); + c[len(s)] = 0; + return c; + } + + fopen :: proc(filename, mode: ^u8) -> rawptr #foreign + fclose :: proc(f: rawptr) -> i32 #foreign + + filename := to_c_string("../examples/base.odin"); + mode := to_c_string("rb"); + defer heap_free(filename); + defer heap_free(mode); + + f := fopen(filename, mode); + if f == null { + // handle error + } + defer if f != null { + _ = fclose(f); + } + + // rest of code + + // Better version + /{ + type File: struct { filename: string } + type FileError: int + open_file :: proc(filename: string) -> (File, FileError) { ... } + close_file :: proc(f: ^File) { ... } + f, err := open_file("Test"); + if err != 0 { + // handle error + } + defer close_file(^f); + + }/ + + + } + + for i := 0; i < 100; i++ { + blah := heap_alloc(100 * size_of(int)) as ^int; + defer { + defer print_string("!"); + defer print_string("heap_free"); + heap_free(blah); + } + + if i == 3 { + // defers called + continue; + } + + if i == 5 { + // defers called + return; + } + + if i == 8 { + // defers called + break; // never happens + } + } + + defer print_string("It'll never happen, mate 1"); + print_string("It'll never happen, mate 2"); + print_string("It'll never happen, mate 3"); +} + diff --git a/examples/main.odin b/examples/game.odin index 0f8662728..54076af39 100644 --- a/examples/main.odin +++ b/examples/game.odin @@ -125,8 +125,7 @@ display_window :: proc(w: ^Window) { - -main :: proc() { +run_game :: proc() { win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline { if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT { ExitProcess(0); @@ -134,9 +133,7 @@ main :: proc() { } return DefWindowProcA(hwnd, msg, wparam, lparam); } - print_f64(13.37); - print_rune('\n'); -/* + window, window_success := make_window("Odin Language Demo", 854, 480, win32_proc); if !window_success { return; @@ -189,5 +186,4 @@ main :: proc() { sleep_ms(ms_to_sleep); } } -*/ } |