Fix old_demos; Fix when bug; Fix enum .names

This commit is contained in:
Ginger Bill
2017-09-29 21:11:16 +01:00
parent 793bc8c585
commit 11614c2649
13 changed files with 285 additions and 286 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ del *.ilk > NUL 2> NUL
cl %compiler_settings% "src\main.cpp" ^ cl %compiler_settings% "src\main.cpp" ^
/link %linker_settings% -OUT:%exe_name% ^ /link %linker_settings% -OUT:%exe_name% ^
&& odin run examples/demo.odin -opt=0 && odin run examples/old_demos/demo006.odin -opt=0
rem && odin docs core/fmt.odin rem && odin docs core/fmt.odin
del *.obj > NUL 2> NUL del *.obj > NUL 2> NUL
+1 -1
View File
@@ -1,4 +1,4 @@
import "fmt.odin"; import "core:fmt.odin";
main :: proc() { main :: proc() {
recursive_factorial :: proc(i: u64) -> u64 { recursive_factorial :: proc(i: u64) -> u64 {
+12 -12
View File
@@ -1,9 +1,9 @@
import win32 "sys/windows.odin" when ODIN_OS == "windows"; import win32 "core:sys/windows.odin" when ODIN_OS == "windows";
import wgl "sys/wgl.odin" when ODIN_OS == "windows"; import wgl "core:sys/wgl.odin" when ODIN_OS == "windows";
import "fmt.odin"; import "core:fmt.odin";
import "math.odin"; import "core:math.odin";
import "os.odin"; import "core:os.odin";
import gl "opengl.odin"; import gl "core:opengl.odin";
TWO_HEARTS :: '💕'; TWO_HEARTS :: '💕';
@@ -32,12 +32,12 @@ to_c_string :: proc(s: string) -> []u8 {
Window :: struct { Window :: struct {
width, height: int; width, height: int,
wc: win32.Wnd_Class_Ex_A; wc: win32.Wnd_Class_Ex_A,
dc: win32.Hdc; dc: win32.Hdc,
hwnd: win32.Hwnd; hwnd: win32.Hwnd,
opengl_context, rc: wgl.Hglrc; opengl_context, rc: wgl.Hglrc,
c_title: []u8; c_title: []u8,
} }
make_window :: proc(title: string, msg, height: int, window_proc: win32.Wnd_Proc) -> (Window, bool) { make_window :: proc(title: string, msg, height: int, window_proc: win32.Wnd_Proc) -> (Window, bool) {
+1 -1
View File
@@ -1,4 +1,4 @@
import "fmt.odin"; import "core:fmt.odin";
main :: proc() { main :: proc() {
fmt.println("Hellope, world!"); fmt.println("Hellope, world!");
+20 -20
View File
@@ -1,9 +1,9 @@
#import "fmt.odin"; import "core:fmt.odin";
#import "os.odin"; import "core:os.odin";
#import "mem.odin"; import "core:mem.odin";
// #import "http_test.odin" as ht; // import "http_test.odin" as ht;
// #import "game.odin" as game; // import "game.odin" as game;
// #import "punity.odin" as pn; // import "punity.odin" as pn;
main :: proc() { main :: proc() {
struct_padding(); struct_padding();
@@ -160,21 +160,21 @@ type_introspection :: proc() {
info: ^Type_Info; info: ^Type_Info;
x: int; x: int;
info = type_info(int); // by type info = type_info_of(int); // by type
info = type_info_of_val(x); // by value info = type_info_of(x); // by value
// See: runtime.odin // See: runtime.odin
match i in info { match i in info.variant {
case Type_Info.Integer: case Type_Info_Integer:
fmt.println("integer!"); fmt.println("integer!");
case Type_Info.Float: case Type_Info_Float:
fmt.println("float!"); fmt.println("float!");
default: case:
fmt.println("potato!"); fmt.println("potato!");
} }
// Unsafe cast // Unsafe cast
integer_info := cast(^Type_Info.Integer)cast(rawptr)info; integer_info := cast(^Type_Info_Integer)cast(rawptr)info;
} }
{ {
@@ -185,9 +185,9 @@ type_introspection :: proc() {
v2: Vector3; v2: Vector3;
v3: Vector3; v3: Vector3;
t1 := type_info_of_val(v1); t1 := type_info_of(v1);
t2 := type_info_of_val(v2); t2 := type_info_of(v2);
t3 := type_info_of_val(v3); t3 := type_info_of(v3);
fmt.println(); fmt.println();
fmt.print("Type of v1 is:\n\t", t1); fmt.print("Type of v1 is:\n\t", t1);
@@ -262,12 +262,12 @@ crazy_introspection :: proc() {
TOMATO, TOMATO,
} }
fruit_ti := type_info(Fruit); fruit_ti := type_info_of(Fruit);
name := (union_cast(^Type_Info.Named)fruit_ti).name; // Unsafe casts name := fruit_ti.variant.(Type_Info_Named).name;
info, _ := union_cast(^Type_Info.Enum)type_info_base(fruit_ti); // Unsafe casts info, _ := type_info_base(fruit_ti).variant.(Type_Info_Enum);
fmt.printf("%s :: enum %T {\n", name, info.base); fmt.printf("%s :: enum %T {\n", name, info.base);
for i := 0; i < len(info.values); i++ { for _, i in info.values {
fmt.printf("\t%s\t= %v,\n", info.names[i], info.values[i]); fmt.printf("\t%s\t= %v,\n", info.names[i], info.values[i]);
} }
fmt.printf("}\n"); fmt.printf("}\n");
+82 -95
View File
@@ -1,7 +1,8 @@
// Demo 002 // Demo 002
#load "fmt.odin"; export "core:fmt.odin";
#load "math.odin"; export "core:math.odin";
// #load "game.odin" export "core:mem.odin";
// export "game.odin"
#thread_local tls_int: int; #thread_local tls_int: int;
@@ -94,11 +95,9 @@ enumerations :: proc() {
} }
variadic_procedures :: proc() { variadic_procedures :: proc() {
print_ints :: proc(args: ..int) { print_ints :: proc(args: ...int) {
for arg, i in args { for arg, i in args {
if i > 0 { if i > 0 do print(", ");
print(", ");
}
print(arg); print(arg);
} }
} }
@@ -107,13 +106,11 @@ variadic_procedures :: proc() {
print_ints(1); nl(); print_ints(1); nl();
print_ints(1, 2, 3); nl(); print_ints(1, 2, 3); nl();
print_prefix_f32s :: proc(prefix: string, args: ..f32) { print_prefix_f32s :: proc(prefix: string, args: ...f32) {
print(prefix); print(prefix);
print(": "); print(": ");
for arg, i in args { for arg, i in args {
if i > 0 { if i > 0 do print(", ");
print(", ");
}
print(arg); print(arg);
} }
} }
@@ -147,13 +144,7 @@ new_builtins :: proc() {
// Q: Should this be `free` rather than `free` and should I overload it for slices too? // Q: Should this be `free` rather than `free` and should I overload it for slices too?
{ push_allocator default_allocator() {
prev_context := context;
defer __context = prev_context;
// Q: Should I add a `push_context` feature to the language?
__context.allocator = default_allocator();
a := new(int); a := new(int);
defer free(a); defer free(a);
@@ -164,7 +155,7 @@ new_builtins :: proc() {
{ {
a: int = 123; a: int = 123;
b: type_of_val(a) = 321; b: type_of(a) = 321;
// NOTE(bill): This matches the current naming scheme // NOTE(bill): This matches the current naming scheme
// size_of // size_of
@@ -205,7 +196,7 @@ new_builtins :: proc() {
a: [16]int; a: [16]int;
a[1] = 1; a[1] = 1;
b := ^a; b := &a;
// Auto pointer deref // Auto pointer deref
// consistent with record members // consistent with record members
assert(b[1] == 1); assert(b[1] == 1);
@@ -255,7 +246,7 @@ match_statement :: proc() {
print("5!\n"); print("5!\n");
fallthrough; // explicit fallthrough fallthrough; // explicit fallthrough
default: case:
print("default!\n"); print("default!\n");
} }
@@ -267,7 +258,7 @@ match_statement :: proc() {
// break by default // break by default
case TAU: case TAU:
print("τ!\n"); print("τ!\n");
default: case:
print("default!\n"); print("default!\n");
} }
@@ -279,7 +270,7 @@ match_statement :: proc() {
// break by default // break by default
case "Goodbye": case "Goodbye":
print("farewell\n"); print("farewell\n");
default: case:
print("???\n"); print("???\n");
} }
@@ -302,7 +293,7 @@ match_statement :: proc() {
print("dozens\n"); print("dozens\n");
case a >= 100 && a < 1000: case a >= 100 && a < 1000:
print("hundreds\n"); print("hundreds\n");
default: case:
print("a fuck ton\n"); print("a fuck ton\n");
} }
@@ -332,11 +323,9 @@ match_statement :: proc() {
Vector3 :: struct {x, y, z: f32} Vector3 :: struct {x, y, z: f32}
print_floats :: proc(args: ..f32) { print_floats :: proc(args: ...f32) {
for arg, i in args { for arg, i in args {
if i > 0 { if i > 0 do print(", ");
print(", ");
}
print(arg); print(arg);
} }
println(); println();
@@ -355,7 +344,7 @@ namespacing :: proc() {
Thing :: #type struct { Thing :: #type struct {
y: int, y: int,
test: bool, test: bool,
} };
b: Thing; // Uses this scope's Thing b: Thing; // Uses this scope's Thing
b.test = true; b.test = true;
@@ -473,10 +462,10 @@ namespacing :: proc() {
} }
e := Entity{position = Vector3{1, 2, 3}}; e := Entity{position = Vector3{1, 2, 3}};
print_pos_1(^e); print_pos_1(&e);
print_pos_2(^e); print_pos_2(&e);
print_pos_3(^e); print_pos_3(&e);
print_pos_4(^e); print_pos_4(&e);
// This is similar to C++'s `this` pointer that is implicit and only available in methods // This is similar to C++'s `this` pointer that is implicit and only available in methods
} }
@@ -574,20 +563,20 @@ subtyping :: proc() {
entity_count := 0; entity_count := 0;
next_entity :: proc(entities: []Entity, entity_count: ^int) -> ^Entity { next_entity :: proc(entities: []Entity, entity_count: ^int) -> ^Entity {
e := ^entities[entity_count^]; e := &entities[entity_count^];
entity_count^++; entity_count^ += 1;
return e; return e;
} }
f: Frog; f: Frog;
f.entity = next_entity(entities[..], ^entity_count); f.entity = next_entity(entities[..], &entity_count);
f.position = Vector3{3, 4, 6}; f.position = Vector3{3, 4, 6};
using f.position; using f.position;
print_floats(x, y, z); print_floats(x, y, z);
} }
{ /*{
// Down casting // Down casting
Entity :: struct { Entity :: struct {
@@ -609,7 +598,7 @@ subtyping :: proc() {
// NOTE(bill): `down_cast` is unsafe and there are not check are compile time or run time // NOTE(bill): `down_cast` is unsafe and there are not check are compile time or run time
// Q: Should I completely remove `down_cast` as I added it in about 30 minutes // Q: Should I completely remove `down_cast` as I added it in about 30 minutes
} }*/
{ {
// Multiple "inheritance"/subclassing // Multiple "inheritance"/subclassing
@@ -630,7 +619,7 @@ subtyping :: proc() {
tagged_unions :: proc() { tagged_unions :: proc() {
{ {
EntityKind :: enum { Entity_Kind :: enum {
INVALID, INVALID,
FROG, FROG,
GIRAFFE, GIRAFFE,
@@ -638,8 +627,8 @@ tagged_unions :: proc() {
} }
Entity :: struct { Entity :: struct {
kind: EntityKind kind: Entity_Kind
using data: raw_union { using data: struct #raw_union {
frog: struct { frog: struct {
jump_height: f32, jump_height: f32,
colour: u32, colour: u32,
@@ -657,33 +646,31 @@ tagged_unions :: proc() {
} }
e: Entity; e: Entity;
e.kind = EntityKind.FROG; e.kind = Entity_Kind.FROG;
e.frog.jump_height = 12; e.frog.jump_height = 12;
f: type_of_val(e.frog); f: type_of(e.frog);
// But this is very unsafe and extremely cumbersome to write // But this is very unsafe and extremely cumbersome to write
// In C++, I use macros to alleviate this but it's not a solution // In C++, I use macros to alleviate this but it's not a solution
} }
{ {
Entity :: union { Frog :: struct {
Frog{ jump_height: f32,
jump_height: f32, colour: u32,
colour: u32,
},
Giraffe{
neck_length: f32,
spot_count: int,
},
Helicopter{
blade_count: int,
weight: f32,
pilot_name: string,
},
} }
Giraffe :: struct {
neck_length: f32,
spot_count: int,
}
Helicopter :: struct {
blade_count: int,
weight: f32,
pilot_name: string,
}
Entity :: union {Frog, Giraffe, Helicopter};
using Entity;
f1: Frog = Frog{12, 0xff9900}; f1: Frog = Frog{12, 0xff9900};
f2: Entity = Frog{12, 0xff9900}; // Implicit cast f2: Entity = Frog{12, 0xff9900}; // Implicit cast
f3 := cast(Entity)Frog{12, 0xff9900}; // Explicit cast f3 := cast(Entity)Frog{12, 0xff9900}; // Explicit cast
@@ -703,7 +690,7 @@ tagged_unions :: proc() {
// Requires a pointer to the union // Requires a pointer to the union
// `x` will be a pointer to type of the case // `x` will be a pointer to type of the case
match x in ^f { match x in &f {
case Frog: case Frog:
print("Frog!\n"); print("Frog!\n");
print(x.jump_height); nl(); print(x.jump_height); nl();
@@ -713,7 +700,7 @@ tagged_unions :: proc() {
print("Giraffe!\n"); print("Giraffe!\n");
case Helicopter: case Helicopter:
print("ROFLCOPTER!\n"); print("ROFLCOPTER!\n");
default: case:
print("invalid entity\n"); print("invalid entity\n");
} }
@@ -755,11 +742,11 @@ tagged_unions :: proc() {
AstNode :: struct {}; AstNode :: struct {};
ExactValue :: struct {}; ExactValue :: struct {};
EntityKind :: enum { Entity_Kind :: enum {
Invalid, Invalid,
Constant, Constant,
Variable, Variable,
UsingVariable, Using_Variable,
TypeName, TypeName,
Procedure, Procedure,
Builtin, Builtin,
@@ -769,14 +756,14 @@ tagged_unions :: proc() {
Guid :: i64; Guid :: i64;
Entity :: struct { Entity :: struct {
kind: EntityKind, kind: Entity_Kind,
guid: Guid, guid: Guid,
scope: ^Scope, scope: ^Scope,
token: Token, token: Token,
type_: ^Type, type_: ^Type,
using data: raw_union { using data: struct #raw_union {
Constant: struct { Constant: struct {
value: ExactValue, value: ExactValue,
}, },
@@ -786,7 +773,7 @@ tagged_unions :: proc() {
is_field: bool, // Is struct field is_field: bool, // Is struct field
anonymous: bool, // Variable is an anonymous anonymous: bool, // Variable is an anonymous
}, },
UsingVariable: struct { Using_Variable: struct {
}, },
TypeName: struct { TypeName: struct {
}, },
@@ -813,44 +800,44 @@ tagged_unions :: proc() {
Guid :: i64; Guid :: i64;
Entity_Base :: struct { Entity_Base :: struct {
} }
Entity :: union {
Constant :: struct {
value: ExactValue,
}
Variable :: struct {
visited: bool, // Cycle detection
used: bool, // Variable is used
is_field: bool, // Is struct field
anonymous: bool, // Variable is an anonymous
}
Using_Variable :: struct {
}
TypeName :: struct {
}
Procedure :: struct {
used: bool,
}
Builtin :: struct {
id: int,
}
Entity :: struct {
guid: Guid, guid: Guid,
scope: ^Scope, scope: ^Scope,
token: Token, token: Token,
type_: ^Type, type_: ^Type,
Constant{ variant: union {Constant, Variable, Using_Variable, TypeName, Procedure, Builtin},
value: ExactValue,
},
Variable{
visited: bool, // Cycle detection
used: bool, // Variable is used
is_field: bool, // Is struct field
anonymous: bool, // Variable is an anonymous
},
UsingVariable{
},
TypeName{
},
Procedure{
used: bool,
},
Builtin{
id: int,
},
} }
using Entity; e := Entity{
variant = Variable{
e: Entity; used = true,
anonymous = false,
e = Variable{ },
used = true,
anonymous = false,
}; };
@@ -863,13 +850,13 @@ tagged_unions :: proc() {
{ {
// `Raw` unions still have uses, especially for mathematic types // `Raw` unions still have uses, especially for mathematic types
Vector2 :: raw_union { Vector2 :: struct #raw_union {
using xy_: struct { x, y: f32 }, using xy_: struct { x, y: f32 },
e: [2]f32, e: [2]f32,
v: [vector 2]f32, v: [vector 2]f32,
} }
Vector3 :: raw_union { Vector3 :: struct #raw_union {
using xyz_: struct { x, y, z: f32 }, using xyz_: struct { x, y, z: f32 },
xy: Vector2, xy: Vector2,
e: [3]f32, e: [3]f32,
+9 -9
View File
@@ -1,14 +1,14 @@
#import "fmt.odin"; import "core:fmt.odin";
#import "utf8.odin"; import "core:utf8.odin";
#import "hash.odin"; import "core:hash.odin";
#import "mem.odin"; import "core:mem.odin";
main :: proc() { main :: proc() {
{ // New Standard Library stuff { // New Standard Library stuff
s := "Hello"; s := "Hello";
fmt.println(s, fmt.println(s,
utf8.valid_string(s), utf8.valid_string(s),
hash.murmur64(cast([]byte)s)); hash.murmur64(cast([]u8)s));
// utf8.odin // utf8.odin
// hash.odin // hash.odin
@@ -20,10 +20,10 @@ main :: proc() {
{ {
arena: mem.Arena; arena: mem.Arena;
mem.init_arena_from_context(^arena, mem.megabytes(16)); // Uses default allocator mem.init_arena_from_context(&arena, mem.megabytes(16)); // Uses default allocator
defer mem.free_arena(^arena); defer mem.destroy_arena(&arena);
push_allocator mem.arena_allocator(^arena) { push_allocator mem.arena_allocator(&arena) {
x := new(int); x := new(int);
x^ = 1337; x^ = 1337;
@@ -49,7 +49,7 @@ main :: proc() {
// You can also "push" a context // You can also "push" a context
c := context; // Create copy of the allocator c := context; // Create copy of the allocator
c.allocator = mem.arena_allocator(^arena); c.allocator = mem.arena_allocator(&arena);
push_context c { push_context c {
x := new(int); x := new(int);
+25 -26
View File
@@ -1,13 +1,13 @@
#import "fmt.odin"; import "core:fmt.odin";
#import "utf8.odin"; import "core:utf8.odin";
// #import "atomic.odin"; // import "core:atomic.odin";
// #import "hash.odin"; // import "core:hash.odin";
// #import "math.odin"; // import "core:math.odin";
// #import "mem.odin"; // import "core:mem.odin";
// #import "opengl.odin"; // import "core:opengl.odin";
// #import "os.odin"; // import "core:os.odin";
// #import "sync.odin"; // import "core:sync.odin";
// #import win32 "sys/windows.odin"; // import win32 "core:sys/windows.odin";
main :: proc() { main :: proc() {
// syntax(); // syntax();
@@ -43,7 +43,7 @@ syntax :: proc() {
Thing2 :: struct {x: f32, y: int, z: ^[]int}; Thing2 :: struct {x: f32, y: int, z: ^[]int};
// Slice interals are now just a `ptr+len+cap` // Slice interals are now just a `ptr+len+cap`
slice: []int; compile_assert(size_of_val(slice) == 3*size_of(int)); slice: []int; compile_assert(size_of(slice) == 3*size_of(int));
// Helper type - Help the reader understand what it is quicker // Helper type - Help the reader understand what it is quicker
My_Int :: #type int; My_Int :: #type int;
@@ -90,22 +90,17 @@ Prefix_Type :: struct {x: int, y: f32, z: rawptr};
prefixes :: proc() { prefixes :: proc() {
using var: Prefix_Type; using var: Prefix_Type;
immutable const := Prefix_Type{1, 2, nil};
var.x = 123; var.x = 123;
x = 123; x = 123;
// const.x = 123; // const is immutable
foo :: proc(using pt: Prefix_Type) {
foo :: proc(using immutable pt: Prefix_Type, immutable int_ptr: ^int) {
// int_ptr = nil; // Not valid
// int_ptr^ = 123; // Not valid
} }
// Same as C99's `restrict` // Same as C99's `restrict`
bar :: proc(no_alias a, b: ^int) { bar :: proc(#no_alias a, b: ^int) {
// Assumes a never equals b so it can perform optimizations with that fact // Assumes a never equals b so it can perform optimizations with that fact
} }
@@ -138,14 +133,18 @@ when_statements :: proc() {
foreign_procedures(); foreign_procedures();
} }
#foreign_system_library win32_user "user32.lib" when ODIN_OS == "windows"; when ODIN_OS == "windows" {
foreign_system_library win32_user "user32.lib";
}
// NOTE: This is done on purpose for two reasons: // NOTE: This is done on purpose for two reasons:
// * Makes it clear where the platform specific stuff is // * Makes it clear where the platform specific stuff is
// * Removes the need to solve the travelling salesman problem when importing files :P // * Removes the need to solve the travelling salesman problem when importing files :P
foreign_procedures :: proc() { foreign_procedures :: proc() {
ShowWindow :: proc(hwnd: rawptr, cmd_show: i32) -> i32 #foreign win32_user; foreign win32_user {
show_window :: proc(hwnd: rawptr, cmd_show: i32) -> i32 #foreign win32_user "ShowWindow"; ShowWindow :: proc(hwnd: rawptr, cmd_show: i32) -> i32 ---;
show_window :: proc(hwnd: rawptr, cmd_show: i32) -> i32 #link_name "ShowWindow" ---;
}
// NOTE: If that library doesn't get used, it doesn't get linked with // 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 // NOTE: There is not link checking yet to see if that procedure does come from that library
@@ -203,14 +202,14 @@ loops :: proc() {
fmt.println(val, idx); fmt.println(val, idx);
} }
primes := [..]int{2, 3, 5, 7, 11, 13, 17, 19}; primes := [...]int{2, 3, 5, 7, 11, 13, 17, 19};
for p in primes { for p in primes {
fmt.println(p); fmt.println(p);
} }
// Pointers to arrays, slices, or strings are allowed // Pointers to arrays, slices, or strings are allowed
for _ in ^primes { for _ in &primes {
// ignore the value and just iterate across it // ignore the value and just iterate across it
} }
@@ -219,7 +218,7 @@ loops :: proc() {
name := "你好,世界"; name := "你好,世界";
fmt.println(name); fmt.println(name);
for r in name { for r in name {
compile_assert(type_of_val(r) == rune); compile_assert(type_of(r) == rune);
fmt.printf("%r\n", r); fmt.printf("%r\n", r);
} }
@@ -270,8 +269,8 @@ procedure_overloading :: proc() {
a: i32 = 123; a: i32 = 123;
b: f32; b: f32;
c: rawptr; c: rawptr;
fmt.println(foo(^a)); fmt.println(foo(&a));
foo(^b); foo(&b);
foo(c); foo(c);
// foo(nil); // nil could go to numerous types thus the ambiguity // foo(nil); // nil could go to numerous types thus the ambiguity
+60 -68
View File
@@ -1,14 +1,14 @@
#import "atomic.odin"; // import "core:atomic.odin";
#import "hash.odin"; import "core:hash.odin";
#import "mem.odin"; import "core:mem.odin";
#import "opengl.odin"; import "core:opengl.odin";
#import "strconv.odin"; import "core:strconv.odin";
#import "sync.odin"; import "core:sync.odin";
#import win32 "sys/windows.odin"; import win32 "core:sys/windows.odin";
#import "fmt.odin"; import "core:fmt.odin";
#import "os.odin"; import "core:os.odin";
#import "math.odin"; import "core:math.odin";
main :: proc() { main :: proc() {
@@ -55,7 +55,7 @@ when true {
for i in 0..16 { for i in 0..16 {
} }
// Is similar to // Is similar to
for _i := 0; _i < 16; _i++ { immutable i := _i; for i := 0; i < 16; i += 1 {
} }
} }
@@ -77,16 +77,15 @@ when true {
} }
{ {
t := type_info(int); t := type_info_of(int);
using Type_Info; match i in t.variant {
match i in t { case Type_Info_Integer, Type_Info_Float:
case Integer, Float:
fmt.println("It's a number"); fmt.println("It's a number");
} }
x: any = 123; x: any = 123;
foo match i in x { foo: match i in x {
case int, f32: case int, f32:
fmt.println("It's an int or f32"); fmt.println("It's an int or f32");
break foo; break foo;
@@ -112,21 +111,20 @@ when true {
{ {
// Slices now store a capacity // Slices now store a capacity
buf: [256]byte; buf: [256]u8;
s: []byte; s: []u8;
s = buf[..0]; // == buf[0..0]; s = buf[..0]; // == buf[0..0];
fmt.println("count =", s.count); fmt.println("count =", len(s));
fmt.println("capacity =", s.capacity); fmt.println("capacity =", cap(s));
append(s, 1, 2, 3); append(&s, 1, 2, 3);
fmt.println(s); fmt.println(s);
s = buf[1..2..3]; s = buf[1..2..3];
fmt.println("count =", s.count); fmt.println("count =", len(s));
fmt.println("capacity =", s.capacity); fmt.println("capacity =", cap(s));
fmt.println(s); fmt.println(s);
clear(s); // Sets count to zero clear(&s); // Sets count to zero
s.count = 0; // Equivalent
} }
{ {
@@ -136,11 +134,11 @@ when true {
flags: u32, flags: u32,
} }
foo_array: [256]Foo; foo_array: [256]Foo;
foo_as_bytes: []byte = slice_to_bytes(foo_array[..]); foo_as_bytes: []u8 = mem.slice_to_bytes(foo_array[..]);
// Useful for things like // Useful for things like
// os.write(handle, foo_as_bytes); // os.write(handle, foo_as_bytes);
foo_slice := slice_ptr(cast(^Foo)foo_as_bytes.data, foo_as_bytes.count/size_of(Foo), foo_as_bytes.capacity/size_of(Foo)); foo_slice := mem.slice_ptr(cast(^Foo)&foo_as_bytes[0], len(foo_as_bytes)/size_of(Foo), cap(foo_as_bytes)/size_of(Foo));
// Question: Should there be a bytes_to_slice procedure or is it clearer to do this even if it is error prone? // Question: Should there be a bytes_to_slice procedure or is it clearer to do this even if it is error prone?
// And if so what would the syntax be? // And if so what would the syntax be?
// slice_transmute([]Foo, foo_as_bytes); // slice_transmute([]Foo, foo_as_bytes);
@@ -161,33 +159,26 @@ when true {
fmt.println(i); fmt.println(i);
} }
compile_assert(size_of([vector 7]bool) == size_of([7]bool)); compile_assert(size_of([vector 7]bool) >= size_of([7]bool));
compile_assert(size_of([vector 7]i32) == size_of([7]i32)); compile_assert(size_of([vector 7]i32) >= size_of([7]i32));
// align_of([vector 7]i32) != align_of([7]i32) // this may be the case // align_of([vector 7]i32) != align_of([7]i32) // this may be the case
} }
{ {
// fmt.* changes // fmt.* changes
// bprint* returns `int` (bytes written) // bprint* returns `string`
// sprint* returns `string` (bytes written as a string)
data: [256]byte; data: [256]u8;
str := fmt.sprintf(data[..0], "Hellope %d %s %c", 123, "others", '!'); str := fmt.bprintf(data[..], "Hellope %d %s %c", 123, "others", '!');
fmt.println(str); fmt.println(str);
buf := data[..0];
count := fmt.bprintf(^buf, "Hellope %d %s %c", 321, "y'all", '!');
fmt.println(cast(string)buf[..count]);
// NOTE(bill): We may change this but because this is a library feature, I am not that bothered yet
} }
{ {
x: [dynamic]f64; x: [dynamic]f64;
reserve(x, 16); reserve(&x, 16);
defer free(x); // `free` is overloaded for numerous types defer free(x); // `free` is overloaded for numerous types
// Number literals can have underscores in them for readability // Number literals can have underscores in them for readability
append(x, 2_000_000.500_000, 123, 5, 7); // variadic append append(&x, 2_000_000.500_000, 123, 5, 7); // variadic append
for p, i in x { for p, i in x {
if i > 0 { fmt.print(", "); } if i > 0 { fmt.print(", "); }
@@ -201,13 +192,13 @@ when true {
x := [dynamic]f64{2_000_000.500_000, 3, 5, 7}; x := [dynamic]f64{2_000_000.500_000, 3, 5, 7};
defer free(x); defer free(x);
fmt.println(x); // fmt.print* supports printing of dynamic types fmt.println(x); // fmt.print* supports printing of dynamic types
clear(x); clear(&x);
fmt.println(x); fmt.println(x);
} }
{ {
m: map[f32]int; m: map[f32]int;
reserve(m, 16); reserve(&m, 16);
defer free(m); defer free(m);
m[1.0] = 1278; m[1.0] = 1278;
@@ -241,12 +232,12 @@ when true {
assert(ok && c == 7654); assert(ok && c == 7654);
fmt.println(m); fmt.println(m);
delete(m, "c"); // deletes entry with key "c" delete(&m, "c"); // deletes entry with key "c"
_, found := m["c"]; _, found := m["c"];
assert(!found); assert(!found);
fmt.println(m); fmt.println(m);
clear(m); clear(&m);
fmt.println(m); fmt.println(m);
// NOTE: Fixed size maps are planned but we have not yet implemented // NOTE: Fixed size maps are planned but we have not yet implemented
@@ -257,7 +248,21 @@ when true {
Vector3 :: struct{x, y, z: f32}; Vector3 :: struct{x, y, z: f32};
Quaternion :: struct{x, y, z, w: f32}; Quaternion :: struct{x, y, z, w: f32};
Entity :: union { // Variants
Frog :: struct {
ribbit_volume: f32,
jump_height: f32,
}
Door :: struct {
openness: f32,
}
Map :: struct {
width, height: f32,
place_positions: []Vector3,
place_names: []string,
}
Entity :: struct {
// Common Fields // Common Fields
id: u64, id: u64,
name: string, name: string,
@@ -265,25 +270,13 @@ when true {
orientation: Quaternion, orientation: Quaternion,
flags: u32, flags: u32,
// Variants variant: union { Frog, Door, Map },
Frog{
ribbit_volume: f32,
jump_height: f32,
},
Door{
openness: f32,
},
Map{
width, height: f32,
place_positions: []Vector3,
place_names: []string,
},
} }
entity: Entity; entity: Entity;
entity.id = 1337;
// implicit conversion from variant to base type // implicit conversion from variant to base type
entity = Entity.Frog{ entity.variant = Frog{
id = 1337,
ribbit_volume = 0.5, ribbit_volume = 0.5,
jump_height = 2.1, jump_height = 2.1,
/*other data */ /*other data */
@@ -292,26 +285,25 @@ when true {
entity.name = "Frank"; entity.name = "Frank";
entity.position = Vector3{1, 4, 9}; entity.position = Vector3{1, 4, 9};
using Entity; match e in entity.variant {
match e in entity {
case Frog: case Frog:
fmt.println("Ribbit"); fmt.println("Ribbit");
case Door: case Door:
fmt.println("Creak"); fmt.println("Creak");
case Map: case Map:
fmt.println("Rustle"); fmt.println("Rustle");
default: case:
fmt.println("Just a normal entity"); fmt.println("Just a normal entity");
} }
if frog, ok := union_cast(Frog)entity; ok { if frog, ok := entity.variant.(Frog); ok {
fmt.printf("The frog jumps %f feet high at %v\n", frog.jump_height, frog.position); fmt.printf("The frog jumps %f feet high at %v\n", frog.jump_height, entity.position);
} }
// Panics if not the correct type // Panics if not the correct type
frog: Frog; frog: Frog;
frog = union_cast(Frog)entity; frog = entity.variant.(Frog);
frog, _ = union_cast(Frog)entity; // ignore error and force cast frog, _ = entity.variant.(Frog); // ignore error and force cast
} }
} }
} }
+40 -40
View File
@@ -1,7 +1,7 @@
import win32 "sys/windows.odin"; import win32 "core:sys/windows.odin";
import "fmt.odin"; import "core:fmt.odin";
import "os.odin"; import "core:os.odin";
import "mem.odin"; import "core:mem.odin";
CANVAS_WIDTH :: 128; CANVAS_WIDTH :: 128;
@@ -25,13 +25,13 @@ DRAW_LIST_RESERVE :: 128;
MAX_KEYS :: 256; MAX_KEYS :: 256;
Core :: struct { Core :: struct {
stack: ^Bank; stack: ^Bank,
storage: ^Bank; storage: ^Bank,
running: bool; running: bool,
key_modifiers: u32; key_modifiers: u32,
key_states: [MAX_KEYS]u8; key_states: [MAX_KEYS]u8,
key_deltas: [MAX_KEYS]u8; key_deltas: [MAX_KEYS]u8,
perf_frame, perf_frame,
perf_frame_inner, perf_frame_inner,
@@ -39,66 +39,66 @@ Core :: struct {
perf_audio, perf_audio,
perf_blit, perf_blit,
perf_blit_cvt, perf_blit_cvt,
perf_blit_gdi: Perf_Span; perf_blit_gdi: Perf_Span,
frame: i64; frame: i64,
canvas: Canvas; canvas: Canvas,
draw_list: ^Draw_List; draw_list: ^Draw_List,
} }
Perf_Span :: struct { Perf_Span :: struct {
stamp: f64; stamp: f64,
delta: f32; delta: f32,
} }
Bank :: struct { Bank :: struct {
memory: []u8; memory: []u8,
cursor: int; cursor: int,
} }
Bank_State :: struct { Bank_State :: struct {
state: Bank; state: Bank,
bank: ^Bank; bank: ^Bank,
} }
Color :: struct #raw_union { Color :: struct #raw_union {
using channels: struct{a, b, g, r: u8}; using channels: struct{a, b, g, r: u8},
rgba: u32; rgba: u32,
} }
Palette :: struct { Palette :: struct {
colors: [256]Color; colors: [256]Color,
colors_count: u8; colors_count: u8,
} }
Rect :: struct #raw_union { Rect :: struct #raw_union {
using minmax: struct {min_x, min_y, max_x, max_y: int}; using minmax: struct {min_x, min_y, max_x, max_y: int},
using pos: struct {left, top, right, bottom: int}; using pos: struct {left, top, right, bottom: int},
e: [4]int; e: [4]int,
} }
Bitmap :: struct { Bitmap :: struct {
pixels: []u8; pixels: []u8,
width: int; width: int,
height: int; height: int,
} }
Font :: struct { Font :: struct {
using bitmap: Bitmap; using bitmap: Bitmap,
char_width: int; char_width: int,
char_height: int; char_height: int,
} }
Canvas :: struct { Canvas :: struct {
using bitmap: ^Bitmap; using bitmap: ^Bitmap,
palette: Palette; palette: Palette,
translate_x: int; translate_x: int,
translate_y: int; translate_y: int,
clip: Rect; clip: Rect,
font: ^Font; font: ^Font,
} }
DrawFlag :: enum { DrawFlag :: enum {
@@ -110,7 +110,7 @@ DrawFlag :: enum {
Draw_Item :: struct {} Draw_Item :: struct {}
Draw_List :: struct { Draw_List :: struct {
items: []Draw_Item; items: []Draw_Item,
} }
Key :: enum { Key :: enum {
+3
View File
@@ -4823,6 +4823,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
if (entity != nullptr && (entity->flags&EntityFlag_TypeField)) { if (entity != nullptr && (entity->flags&EntityFlag_TypeField)) {
add_type_info_type(c, operand->type); add_type_info_type(c, operand->type);
} }
if (is_type_enum(operand->type)) {
add_type_info_type(c, operand->type);
}
} }
if (entity == nullptr && selector->kind == AstNode_BasicLit) { if (entity == nullptr && selector->kind == AstNode_BasicLit) {
if (is_type_struct(operand->type) || is_type_tuple(operand->type)) { if (is_type_struct(operand->type) || is_type_tuple(operand->type)) {
-1
View File
@@ -393,7 +393,6 @@ struct TypeAndToken {
}; };
void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) { void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
flags &= ~Stmt_CheckScopeDecls;
Operand operand = {Addressing_Invalid}; Operand operand = {Addressing_Invalid};
check_expr(c, &operand, ws->cond); check_expr(c, &operand, ws->cond);
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
+31 -12
View File
@@ -853,10 +853,19 @@ String ir_get_global_name(irModule *m, irValue *v) {
String *found = map_get(&m->entity_names, hash_entity(e)); String *found = map_get(&m->entity_names, hash_entity(e));
if (found != nullptr) { if (found != nullptr) {
name = *found; name = *found;
} else {
GB_ASSERT(name.len > 0);
} }
return name; return name;
} }
void ir_add_entity_name(irModule *m, Entity *e, String name) {
GB_ASSERT(name.len > 0);
map_set(&m->entity_names, hash_entity(e), name);
}
irValue *ir_instr_local(irProcedure *p, Entity *e, bool zero_initialized) { irValue *ir_instr_local(irProcedure *p, Entity *e, bool zero_initialized) {
@@ -1153,14 +1162,21 @@ irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefi
gbAllocator a = m->allocator; gbAllocator a = m->allocator;
Token token = {Token_Ident}; Token token = {Token_Ident};
isize name_len = prefix.len + 10; isize name_len = prefix.len + 10;
token.string.text = gb_alloc_array(a, u8, name_len);
token.string.len = gb_snprintf(cast(char *)token.string.text, name_len, char *text = gb_alloc_array(a, char, name_len);
"%.*s-%llx", LIT(prefix), cast(unsigned long long)id)-1; gb_snprintf(text, name_len,
Entity *e = make_entity_variable(a, nullptr, token, make_type_array(a, elem_type, count), false); "%.*s-%llx", LIT(prefix), cast(unsigned long long)id);
String s = make_string_c(text);
Entity *e = make_entity_variable(a, nullptr,
make_token_ident(s),
make_type_array(a, elem_type, count),
false);
irValue *value = ir_value_global(a, e, nullptr); irValue *value = ir_value_global(a, e, nullptr);
value->Global.is_private = true; value->Global.is_private = true;
ir_module_add_value(m, e, value); ir_module_add_value(m, e, value);
map_set(&m->members, hash_string(token.string), value); map_set(&m->members, hash_string(s), value);
return value; return value;
} }
@@ -3436,6 +3452,7 @@ irValue *ir_type_info(irProcedure *proc, Type *type) {
type = default_type(type); type = default_type(type);
i32 entry_index = cast(i32)type_info_index(info, type); i32 entry_index = cast(i32)type_info_index(info, type);
GB_ASSERT(entry_index >= 0);
// gb_printf_err("%d %s\n", entry_index, type_to_string(type)); // gb_printf_err("%d %s\n", entry_index, type_to_string(type));
@@ -3639,7 +3656,8 @@ void ir_mangle_add_sub_type_name(irModule *m, Entity *field, String parent) {
"%.*s.%.*s", LIT(parent), LIT(cn)); "%.*s.%.*s", LIT(parent), LIT(cn));
String child = {text, new_name_len-1}; String child = {text, new_name_len-1};
map_set(&m->entity_names, hash_entity(field), child); GB_ASSERT(child.len > 0);
ir_add_entity_name(m, field, child);
ir_gen_global_type_name(m, field, child); ir_gen_global_type_name(m, field, child);
} }
@@ -5148,15 +5166,16 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
String name = e->token.string; String name = e->token.string;
if (name == "names") { if (name == "names") {
irValue *ti_ptr = ir_type_info(proc, type); irValue *ti_ptr = ir_type_info(proc, type);
irValue *variant = ir_emit_struct_ep(proc, ti_ptr, 2);
irValue *names_ptr = nullptr; irValue *names_ptr = nullptr;
if (is_type_enum(type)) { if (is_type_enum(type)) {
irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr); irValue *enum_info = ir_emit_conv(proc, variant, t_type_info_enum_ptr);
names_ptr = ir_emit_struct_ep(proc, enum_info, 3); names_ptr = ir_emit_struct_ep(proc, enum_info, 1);
} else if (type->kind == Type_Struct) { } else if (type->kind == Type_Struct) {
irValue *struct_info = ir_emit_conv(proc, ti_ptr, t_type_info_struct_ptr); irValue *struct_info = ir_emit_conv(proc, variant, t_type_info_struct_ptr);
names_ptr = ir_emit_struct_ep(proc, struct_info, 3); names_ptr = ir_emit_struct_ep(proc, struct_info, 1);
} }
return ir_addr(names_ptr); return ir_addr(names_ptr);
} else { } else {
@@ -7641,7 +7660,7 @@ void ir_gen_tree(irGen *s) {
if (!e->scope->is_global) { if (!e->scope->is_global) {
name = ir_mangle_name(s, e->token.pos.file, e); name = ir_mangle_name(s, e->token.pos.file, e);
} }
map_set(&m->entity_names, hash_entity(e), name); ir_add_entity_name(m, e, name);
irValue *g = ir_value_global(a, e, nullptr); irValue *g = ir_value_global(a, e, nullptr);
g->Global.name = name; g->Global.name = name;
@@ -7716,7 +7735,7 @@ void ir_gen_tree(irGen *s) {
} else if (check_is_entity_overloaded(e)) { } else if (check_is_entity_overloaded(e)) {
name = ir_mangle_name(s, e->token.pos.file, e); name = ir_mangle_name(s, e->token.pos.file, e);
} }
map_set(&m->entity_names, hash_entity(e), name); ir_add_entity_name(m, e, name);
switch (e->kind) { switch (e->kind) {
case Entity_TypeName: case Entity_TypeName: