mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
v0.3.0
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
set exe_name=odin.exe
|
set exe_name=odin.exe
|
||||||
|
|
||||||
:: Debug = 0, Release = 1
|
:: 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-
|
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
||||||
|
|
||||||
if %release_mode% EQU 0 ( rem Debug
|
if %release_mode% EQU 0 ( rem Debug
|
||||||
@@ -42,9 +42,10 @@ set linker_settings=%libs% %linker_flags%
|
|||||||
del *.pdb > NUL 2> NUL
|
del *.pdb > NUL 2> NUL
|
||||||
del *.ilk > NUL 2> NUL
|
del *.ilk > NUL 2> NUL
|
||||||
|
|
||||||
cl %compiler_settings% "src\main.c" ^
|
odin run code/demo.odin
|
||||||
/link %linker_settings% -OUT:%exe_name% ^
|
rem cl %compiler_settings% "src\main.c" ^
|
||||||
&& odin run code/demo.odin
|
rem /link %linker_settings% -OUT:%exe_name% ^
|
||||||
|
rem && odin run code/demo.odin
|
||||||
rem && odin build code/metagen.odin ^
|
rem && odin build code/metagen.odin ^
|
||||||
rem && call "code\metagen.exe" "src\ast_nodes.metagen"
|
rem && call "code\metagen.exe" "src\ast_nodes.metagen"
|
||||||
rem && odin run code/Jaze/src/main.odin
|
rem && odin run code/Jaze/src/main.odin
|
||||||
|
|||||||
+191
-10
@@ -1,18 +1,199 @@
|
|||||||
|
//
|
||||||
|
// Odin v0.3 Demo
|
||||||
|
//
|
||||||
|
|
||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
immutable program := "+ + * - /";
|
/*
|
||||||
accumulator := 0;
|
Minor features
|
||||||
|
--------------
|
||||||
|
|
||||||
for token in program {
|
* Lexical sugar
|
||||||
match token {
|
- ≠, ≤, ≥
|
||||||
case '+': accumulator += 1;
|
* Label syntax change
|
||||||
case '-': accumulator -= 1;
|
name: for {
|
||||||
case '*': accumulator *= 2;
|
break name;
|
||||||
case '/': accumulator /= 2;
|
}
|
||||||
case: // Ignore everything else
|
* `#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
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -158,8 +158,8 @@ AllocatorMode :: enum u8 {
|
|||||||
Resize,
|
Resize,
|
||||||
}
|
}
|
||||||
AllocatorProc :: #type proc(allocator_data: rawptr, mode: AllocatorMode,
|
AllocatorProc :: #type proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||||
size, alignment: int,
|
size, alignment: int,
|
||||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
||||||
Allocator :: struct #ordered {
|
Allocator :: struct #ordered {
|
||||||
procedure: AllocatorProc,
|
procedure: AllocatorProc,
|
||||||
data: rawptr,
|
data: rawptr,
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ __i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_nam
|
|||||||
s = a >> 127;
|
s = a >> 127;
|
||||||
b = (a~s) - s;
|
b = (a~s) - s;
|
||||||
|
|
||||||
urem: u128;
|
uquo: u128;
|
||||||
uquo := __u128_quo_mod(transmute(u128, a), transmute(u128, b), &urem);
|
urem := __u128_quo_mod(transmute(u128, a), transmute(u128, b), &uquo);
|
||||||
iquo := transmute(i128, uquo);
|
iquo := transmute(i128, uquo);
|
||||||
irem := transmute(i128, urem);
|
irem := transmute(i128, urem);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1023,7 +1023,7 @@ fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
|||||||
case i16: fmt_int(fi, u128(a), true, 16, verb);
|
case i16: fmt_int(fi, u128(a), true, 16, verb);
|
||||||
case i32: fmt_int(fi, u128(a), true, 32, verb);
|
case i32: fmt_int(fi, u128(a), true, 32, verb);
|
||||||
case i64: fmt_int(fi, u128(a), true, 64, 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 uint: fmt_int(fi, u128(a), false, 8*size_of(uint), verb);
|
||||||
case u8: fmt_int(fi, u128(a), false, 8, verb);
|
case u8: fmt_int(fi, u128(a), false, 8, verb);
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ String get_fullpath_core(gbAllocator a, String path) {
|
|||||||
void init_build_context(void) {
|
void init_build_context(void) {
|
||||||
BuildContext *bc = &build_context;
|
BuildContext *bc = &build_context;
|
||||||
bc->ODIN_VENDOR = str_lit("odin");
|
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();
|
bc->ODIN_ROOT = odin_root_dir();
|
||||||
|
|
||||||
#if defined(GB_SYSTEM_WINDOWS)
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
|||||||
@@ -2643,6 +2643,14 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
|||||||
return true;
|
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
|
// Cast between pointers
|
||||||
if (is_type_pointer(src) && is_type_pointer(dst)) {
|
if (is_type_pointer(src) && is_type_pointer(dst)) {
|
||||||
Type *s = base_type(type_deref(src));
|
Type *s = base_type(type_deref(src));
|
||||||
|
|||||||
+13
-13
@@ -554,28 +554,28 @@ i128 i128_mul(i128 a, i128 b) {
|
|||||||
return res;
|
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?!
|
// TODO(bill): Which one is correct?!
|
||||||
#if 0
|
#if 1
|
||||||
i128 s = i128_shr(den, 127);
|
i128 s = i128_shr(b, 127);
|
||||||
den = i128_sub(i128_xor(den, s), s);
|
b = i128_sub(i128_xor(b, s), s);
|
||||||
s = i128_shr(num, 127);
|
s = i128_shr(a, 127);
|
||||||
den = i128_sub(i128_xor(num, s), s);
|
b = i128_sub(i128_xor(a, s), s);
|
||||||
|
|
||||||
u128 n, r = {0};
|
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 ni = *cast(i128 *)&n;
|
||||||
i128 ri = *cast(i128 *)&r;
|
i128 ri = *cast(i128 *)&r;
|
||||||
|
|
||||||
if (quo) *quo = i128_sub(i128_xor(ni, s), s);
|
if (quo) *quo = i128_sub(i128_xor(ri, s), s);
|
||||||
if (rem) *rem = i128_sub(i128_xor(ri, s), s);
|
if (rem) *rem = i128_sub(i128_xor(ni, s), s);
|
||||||
#else
|
#else
|
||||||
if (i128_eq(den, I128_ZERO)) {
|
if (i128_eq(b, I128_ZERO)) {
|
||||||
if (quo) *quo = i128_from_u64(num.lo/den.lo);
|
if (quo) *quo = i128_from_u64(a.lo/b.lo);
|
||||||
if (rem) *rem = I128_ZERO;
|
if (rem) *rem = I128_ZERO;
|
||||||
} else {
|
} else {
|
||||||
i128 n = num;
|
i128 n = a;
|
||||||
i128 d = den;
|
i128 d = b;
|
||||||
i128 x = I128_ONE;
|
i128 x = I128_ONE;
|
||||||
i128 r = I128_ZERO;
|
i128 r = I128_ZERO;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user