|
@@ -1,9 +1,282 @@
|
|
#import "fmt.odin";
|
|
#import "fmt.odin";
|
|
|
|
+#import "utf8.odin";
|
|
|
|
+// #import "atomic.odin";
|
|
|
|
+// #import "hash.odin";
|
|
|
|
+// #import "math.odin";
|
|
|
|
+// #import "mem.odin";
|
|
|
|
+// #import "opengl.odin";
|
|
|
|
+// #import "os.odin";
|
|
|
|
+// #import "sync.odin";
|
|
|
|
+// #import win32 "sys/windows.odin";
|
|
|
|
|
|
main :: proc() {
|
|
main :: proc() {
|
|
- fmt.println(foo("FOO"));
|
|
|
|
|
|
+ // syntax();
|
|
|
|
+ procedure_overloading();
|
|
}
|
|
}
|
|
|
|
|
|
-foo :: proc(test: string, test1: string, args: ...any) { }
|
|
|
|
|
|
+syntax :: proc() {
|
|
|
|
+ // Cyclic type checking
|
|
|
|
+ // Uncomment to see the error
|
|
|
|
+ // A :: struct {b: B};
|
|
|
|
+ // B :: struct {a: A};
|
|
|
|
|
|
-foo :: proc(test: string) { }
|
|
|
|
|
|
+ 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+count`
|
|
|
|
+ slice: []int; compile_assert(size_of_val(slice) == 2*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;
|
|
|
|
+ immutable const := Prefix_Type{1, 2, nil};
|
|
|
|
+ var.x = 123;
|
|
|
|
+ x = 123;
|
|
|
|
+ // const.x = 123; // const is immutable
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ foo :: proc(using immutable pt: Prefix_Type, immutable int_ptr: ^int) {
|
|
|
|
+ // int_ptr = nil; // Not valid
|
|
|
|
+ int_ptr^ = 123; // Is valid
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 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();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#foreign_system_library win32_user "user32.lib" when ODIN_OS == "windows";
|
|
|
|
+// 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() {
|
|
|
|
+ ShowWindow :: proc(hwnd: rawptr, cmd_show: i32) -> i32 #foreign win32_user;
|
|
|
|
+ show_window :: proc(hwnd: rawptr, cmd_show: i32) -> i32 #foreign win32_user "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...122 { // 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 {
|
|
|
|
+ compile_assert(type_of_val(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
|
|
|
|
+}
|