From 574b82c0c7e266bcd1bc16ee709d32936625cf46 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 7 Jun 2017 22:09:16 +0100 Subject: [PATCH] v0.3.0 --- build.bat | 9 +- code/demo.odin | 201 ++++++++++++++++++++++++++++++++++++++-- core/_preload.odin | 4 +- core/_soft_numbers.odin | 4 +- core/fmt.odin | 2 +- src/build_settings.c | 2 +- src/check_expr.c | 8 ++ src/integer128.c | 26 +++--- src/ir.c | 1 + 9 files changed, 224 insertions(+), 33 deletions(-) diff --git a/build.bat b/build.bat index 51dfc84b4..b5ceccaf1 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 @@ -42,9 +42,10 @@ set linker_settings=%libs% %linker_flags% del *.pdb > NUL 2> NUL del *.ilk > NUL 2> NUL -cl %compiler_settings% "src\main.c" ^ - /link %linker_settings% -OUT:%exe_name% ^ - && odin run code/demo.odin +odin run code/demo.odin +rem cl %compiler_settings% "src\main.c" ^ + rem /link %linker_settings% -OUT:%exe_name% ^ + rem && odin run code/demo.odin rem && odin build code/metagen.odin ^ rem && call "code\metagen.exe" "src\ast_nodes.metagen" rem && odin run code/Jaze/src/main.odin diff --git a/code/demo.odin b/code/demo.odin index c67cee184..e21d689c1 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,18 +1,199 @@ +// +// Odin v0.3 Demo +// + #import "fmt.odin"; main :: proc() { - immutable program := "+ + * - /"; - accumulator := 0; +/* + Minor features + -------------- - for token in program { - match token { - case '+': accumulator += 1; - case '-': accumulator -= 1; - case '*': accumulator *= 2; - case '/': accumulator /= 2; - case: // Ignore everything else + * Lexical sugar + - ≠, ≤, ≥ + * Label syntax change + name: for { + break name; + } + * `#no_alias` (replacing keyword `no_alias`) + * `#ordered` reimplemented + * "bits.odin" + * `default:` is replaced with `case:` + * XOR for booleans + * Bug fixes + * Removed Quaternion types quaternion128 & quaternion256 + * `rune` is a core type - allowing for extra type information at runtime + * `byte` is removed - use `u8` instead (which it was an alias for) +*/ + + // 128 bit integers + { + x: u128 = 1234567890123; + y: u128 = 9876543210123; + z := (x * y) + x + y; + fmt.println(z); + + a: i128 = +1234567890123; + b: i128 = -9876543210123; + c := (a * b) + a + b; + fmt.println(c); + } + + // Divisor based modulo operator + { + x: i128 = -5; + y: i128 = 2; + + fmt.println(x % y); // Dividend based + fmt.println(x %% y); // Divisor based + + // a %% b == ((a % b) + b) % b; + } + + // Casting syntax + { + // Casting operations have had their syntax change for simplicity and consistency + // Original: + // Regular cast: `cast(type) expr` + // Bit cast: `transmute(type) expr` + // Union cast: `union_cast(type) expr` + + // Regular Cast + f: f32 = 123.321; + i := i32(f); // type(expr) + + + // Bit cast + fbits := transmute(u32, f); + + + + // Type assertion - replaces `union_cast` + Entity :: union { + id: u64, + position: [vector 2]f32, + name: string, + Tree{leaf_count: int}, + Frog{ribbit_volume: f32}, + } + + e: Entity; + e = Entity.Frog{ribbit_volume = 0.5, name = "Trevor"}; + + if frog, ok := e.(Entity.Frog); ok { + fmt.printf("%s the frog ribbit's at %f\n", frog.name, frog.ribbit_volume); + } + + // Panics if the type assertion fails + frog := e.(Entity.Frog); + + { + // Type assertion can also be applied to `any` + foo: any = 123; + if i, ok := foo.(int); ok { + fmt.println("Foo =", i); + } } } - fmt.printf("The program \"%s\" calculates the value %d\n", program, accumulator); + // Syntax changes + { + // Originally `^` was used to represent pointer types, pointer dereferencing, and addressing of variables + // The addressing of variable operation is not represented with `&` + // This is to make sure the concept of a pointer type is separate from that of a addressing + // it is also used for familiarity coming from other C-like languages + x: int = 123; + y: ^int = &x; + z: int = y^; + + // This change also allows type casting to not require parentheses around the type for pointer evaluation + // and consitency with other operations + + data := rawptr(&x); + int_ptr := ^int(data); + + array: [10]int; // Type of the left + x = array[0]; // Usage on the right + + ptr: ^int = &z; // Type of the left + x = ptr^; // Usage on the right + + + + // Minor addition - member access through number + TupleLike :: struct{int, f32, string}; // Fields all anonymous + t: TupleLike; + t.0 = 123; + t.1 = 46.432; + t.2 = "Foo"; + fmt.println(t); + } + + // Bit fields + { + BoxProps :: bit_field { + opaque: 1, + fill_colour: 3, + _: 4, + show_border: 1, + _: 3, + border_style: 2, + _: 2, + width: 4, + height: 4, + }; + + props: BoxProps; + props.fill_colour = 4; + props.show_border = 1; + props.width = 12; + props.height = 10; + + fmt.printf("Width: %d, Height: %d\n", props.width, props.height); + + + + Float32Data :: bit_field { + fraction: 23, + exponent: 8, + sign: 1, + } + + f: f32 = -123.321; + data := transmute(Float32Data, f); + bits := transmute(u32, f); + fmt.printf("%#05x %#02x %v\n", data.fraction, data.exponent, bool(data.sign)); + fmt.printf("%#08x\n", bits); + } + + // Naming convention + { + // Odin has finally chose an official naming convention + // In general, PascalCase for types and snake_case for values + + // Import Name: snake_case (but prefer single word) + // Types: PascalCase + // Union Variants: PascalCase + // Enum Values: PascalCase + // Procedures: snake_case + // Local Variables: snake_case + // Field Values: snake_case + // Constant Variables: SCREAMING_SNAKE_CASE + } + + // Goals for v0.4 and further + // * Compile as C++and use some of its constructs for sanity e.g. overloading + // - Safe array with bounds checking + // - Map type for self documentation + // - u128 i128 acting like core types + // * Context system implemented as Implicit Parameter Passing (IPP) rather than Thread Local Storage (TLS) + // * Parameter Polymorphism + // - Type parameter is procedures and types + // * Decide upon a declaration syntax + // - Current Style (name: type;) vs Prefix Style (var name: type;) + // * Import system with a "solution" for packages/modules/libraries + // * Better foreign interfacing with C (and maybe C++) + // - Foreign variables + // * Documentation Generation System for code + // * General Documentation for Odin } diff --git a/core/_preload.odin b/core/_preload.odin index c13622c4e..4e5d9e9e4 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -158,8 +158,8 @@ AllocatorMode :: enum u8 { Resize, } AllocatorProc :: #type proc(allocator_data: rawptr, mode: AllocatorMode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64) -> rawptr; + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr; Allocator :: struct #ordered { procedure: AllocatorProc, data: rawptr, diff --git a/core/_soft_numbers.odin b/core/_soft_numbers.odin index fd7dc2905..6b1a86557 100644 --- a/core/_soft_numbers.odin +++ b/core/_soft_numbers.odin @@ -27,8 +27,8 @@ __i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_nam s = a >> 127; b = (a~s) - s; - urem: u128; - uquo := __u128_quo_mod(transmute(u128, a), transmute(u128, b), &urem); + uquo: u128; + urem := __u128_quo_mod(transmute(u128, a), transmute(u128, b), &uquo); iquo := transmute(i128, uquo); irem := transmute(i128, urem); diff --git a/core/fmt.odin b/core/fmt.odin index c1057a406..e436a5e46 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -1023,7 +1023,7 @@ fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) { case i16: fmt_int(fi, u128(a), true, 16, verb); case i32: fmt_int(fi, u128(a), true, 32, verb); case i64: fmt_int(fi, u128(a), true, 64, verb); - case i128: fmt_int(fi, u128(a), false, 128, verb); + case i128: fmt_int(fi, u128(a), true, 128, verb); case uint: fmt_int(fi, u128(a), false, 8*size_of(uint), verb); case u8: fmt_int(fi, u128(a), false, 8, verb); diff --git a/src/build_settings.c b/src/build_settings.c index 1a6b8fdf5..0ba38e30f 100644 --- a/src/build_settings.c +++ b/src/build_settings.c @@ -263,7 +263,7 @@ String get_fullpath_core(gbAllocator a, String path) { void init_build_context(void) { BuildContext *bc = &build_context; bc->ODIN_VENDOR = str_lit("odin"); - bc->ODIN_VERSION = str_lit("0.2.1"); + bc->ODIN_VERSION = str_lit("0.3.0"); bc->ODIN_ROOT = odin_root_dir(); #if defined(GB_SYSTEM_WINDOWS) diff --git a/src/check_expr.c b/src/check_expr.c index 75d38f4fc..1ed7378e5 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -2643,6 +2643,14 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { return true; } + if (is_type_bit_field_value(src) && is_type_integer(dst)) { + return true; + } + + if (is_type_bit_field_value(src) && is_type_boolean(dst)) { + return src->BitFieldValue.bits == 1; + } + // Cast between pointers if (is_type_pointer(src) && is_type_pointer(dst)) { Type *s = base_type(type_deref(src)); diff --git a/src/integer128.c b/src/integer128.c index ed05a1471..6cce03143 100644 --- a/src/integer128.c +++ b/src/integer128.c @@ -554,28 +554,28 @@ i128 i128_mul(i128 a, i128 b) { return res; } -void i128_divide(i128 num, i128 den, i128 *quo, i128 *rem) { +void i128_divide(i128 a, i128 b, i128 *quo, i128 *rem) { // TODO(bill): Which one is correct?! -#if 0 - i128 s = i128_shr(den, 127); - den = i128_sub(i128_xor(den, s), s); - s = i128_shr(num, 127); - den = i128_sub(i128_xor(num, s), s); +#if 1 + i128 s = i128_shr(b, 127); + b = i128_sub(i128_xor(b, s), s); + s = i128_shr(a, 127); + b = i128_sub(i128_xor(a, s), s); u128 n, r = {0}; - u128_divide(*cast(u128 *)&num, *cast(u128 *)&den, &n, &r); + u128_divide(*cast(u128 *)&a, *cast(u128 *)&b, &n, &r); i128 ni = *cast(i128 *)&n; i128 ri = *cast(i128 *)&r; - if (quo) *quo = i128_sub(i128_xor(ni, s), s); - if (rem) *rem = i128_sub(i128_xor(ri, s), s); + if (quo) *quo = i128_sub(i128_xor(ri, s), s); + if (rem) *rem = i128_sub(i128_xor(ni, s), s); #else - if (i128_eq(den, I128_ZERO)) { - if (quo) *quo = i128_from_u64(num.lo/den.lo); + if (i128_eq(b, I128_ZERO)) { + if (quo) *quo = i128_from_u64(a.lo/b.lo); if (rem) *rem = I128_ZERO; } else { - i128 n = num; - i128 d = den; + i128 n = a; + i128 d = b; i128 x = I128_ONE; i128 r = I128_ZERO; diff --git a/src/ir.c b/src/ir.c index e014cb229..3acc78afe 100644 --- a/src/ir.c +++ b/src/ir.c @@ -3060,6 +3060,7 @@ bool ir_is_type_aggregate(Type *t) { case Type_Tuple: case Type_DynamicArray: case Type_Map: + case Type_BitField: return true; case Type_Named: