From ec9c8fb8a49cb6f9fe8f6df806dfb5a6fcb2e148 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 29 Jan 2017 14:45:12 +0000 Subject: [PATCH] Update README.md --- README.md | 37 ++--- build.bat | 2 +- code/demo.odin | 279 ++++++++++++++++++++++++++++++++++- code/old_demos/demo005.odin | 282 ++++++++++++++++++++++++++++++++++++ 4 files changed, 578 insertions(+), 22 deletions(-) create mode 100644 code/old_demos/demo005.odin diff --git a/README.md b/README.md index bcead4de927..7e717e18e01 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # The Odin Programming Language -Odin is fast, concise, readable, pragmatic and open sourced. It is designed with the intent of replacing C with the following goals: +The Odin programming language is fast, concise, readable, pragmatic and open sourced. It is designed with the intent of replacing C with the following goals: * simplicity * high performance * built for modern systems @@ -18,6 +18,7 @@ Odin is fast, concise, readable, pragmatic and open sourced. It is designed with * [Composition & Refactorability](https://www.youtube.com/watch?v=n1wemZfcbXM) * [Introspection, Modules, and Record Layout](https://www.youtube.com/watch?v=UFq8rhWhx4s) * [push_allocator & Minimal Dependency Building](https://www.youtube.com/watch?v=f_LGVOAMb78) +* [when, for, & procedure overloading](https://www.youtube.com/watch?v=OzeOekzyZK8) ## Requirements to build and run @@ -30,27 +31,27 @@ Odin is fast, concise, readable, pragmatic and open sourced. It is designed with ## Warnings * This is still highly in development and the language's design is quite volatile. -* Syntax is definitely not fixed +* Syntax is not fixed. ## Roadmap Not in any particular order -* Custom backend to replace LLVM - - Improve SSA design to accommodate for lowering to a "bytecode" - - SSA optimizations - - COFF generation - - linker -* Type safe "macros" -* Documentation generator for "Entities" -* Multiple architecture support -* Inline assembly -* Linking options - - Executable - - Static/Dynamic Library -* Debug information +* Compile Time Execution (CTE) + - More metaprogramming madness + - Compiler as a library + - AST inspection and modification +* CTE-based build system +* Replace LLVM backend with my own custom backend +* Improve SSA design to accommodate for lowering to a "bytecode" +* SSA optimizations +* Parametric Polymorphism ("Generics") +* Documentation Generator for "Entities" +* Multiple Architecture support +* Language level atomics and concurrency support +* Debug Information - pdb format too -* Command line tooling -* Compiler internals: +* Command Line Tooling +* Compiler Internals: - Big numbers library - + - Multithreading for performance increase diff --git a/build.bat b/build.bat index bddb6ebf19c..bf007f574c8 100644 --- a/build.bat +++ b/build.bat @@ -4,7 +4,7 @@ set exe_name=odin.exe :: Debug = 0, Release = 1 -set release_mode=0 +set release_mode=1 set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR- if %release_mode% EQU 0 ( rem Debug diff --git a/code/demo.odin b/code/demo.odin index a24126d9da4..4198cffb608 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,9 +1,282 @@ #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() { - 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 +} diff --git a/code/old_demos/demo005.odin b/code/old_demos/demo005.odin new file mode 100644 index 00000000000..4198cffb608 --- /dev/null +++ b/code/old_demos/demo005.odin @@ -0,0 +1,282 @@ +#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() { + // syntax(); + procedure_overloading(); +} + +syntax :: proc() { + // Cyclic type checking + // Uncomment to see the error + // A :: struct {b: B}; + // B :: struct {a: A}; + + 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 +}