distinct keyword for type declarations

This commit is contained in:
gingerBill
2018-02-05 22:46:30 +00:00
parent 2891988d3b
commit 92780e2683
17 changed files with 177 additions and 121 deletions
+24 -24
View File
@@ -1,38 +1,38 @@
CHAR_BIT :: 8; CHAR_BIT :: 8;
c_bool :: #alias bool; c_bool :: bool;
c_char :: #alias u8; c_char :: u8;
c_byte :: #alias u8; c_byte :: u8;
c_schar :: #alias i8; c_schar :: i8;
c_uchar :: #alias u8; c_uchar :: u8;
c_short :: #alias i16; c_short :: i16;
c_ushort :: #alias u16; c_ushort :: u16;
c_int :: #alias i32; c_int :: i32;
c_uint :: #alias u32; c_uint :: u32;
when ODIN_OS == "windows" || size_of(rawptr) == 4 { when ODIN_OS == "windows" || size_of(rawptr) == 4 {
c_long :: #alias i32; c_long :: i32;
} else { } else {
c_long :: #alias i64; c_long :: i64;
} }
when ODIN_OS == "windows" || size_of(rawptr) == 4 { when ODIN_OS == "windows" || size_of(rawptr) == 4 {
c_ulong :: #alias u32; c_ulong :: u32;
} else { } else {
c_ulong :: #alias u64; c_ulong :: u64;
} }
c_longlong :: #alias i64; c_longlong :: i64;
c_ulonglong :: #alias u64; c_ulonglong :: u64;
c_float :: #alias f32; c_float :: f32;
c_double :: #alias f64; c_double :: f64;
c_complex_float :: #alias complex64; c_complex_float :: complex64;
c_complex_double :: #alias complex128; c_complex_double :: complex128;
_ :: compile_assert(size_of(uintptr) == size_of(int)); _ :: compile_assert(size_of(uintptr) == size_of(int));
c_size_t :: #alias uint; c_size_t :: uint;
c_ssize_t :: #alias int; c_ssize_t :: int;
c_ptrdiff_t :: #alias int; c_ptrdiff_t :: int;
c_uintptr_t :: #alias uintptr; c_uintptr_t :: uintptr;
c_intptr_t :: #alias int; c_intptr_t :: int;
+1 -1
View File
@@ -8,7 +8,7 @@ import "core:raw.odin"
_BUFFER_SIZE :: 1<<12; _BUFFER_SIZE :: 1<<12;
String_Buffer :: [dynamic]byte; String_Buffer :: distinct [dynamic]byte;
Fmt_Info :: struct { Fmt_Info :: struct {
minus: bool, minus: bool,
+6 -6
View File
@@ -14,14 +14,14 @@ EPSILON :: 1.19209290e-7;
τ :: TAU; τ :: TAU;
π :: PI; π :: PI;
Vec2 :: [2]f32; Vec2 :: distinct [2]f32;
Vec3 :: [3]f32; Vec3 :: distinct [3]f32;
Vec4 :: [4]f32; Vec4 :: distinct [4]f32;
// Column major // Column major
Mat2 :: [2][2]f32; Mat2 :: distinct [2][2]f32;
Mat3 :: [3][3]f32; Mat3 :: distinct [3][3]f32;
Mat4 :: [4][4]f32; Mat4 :: distinct [4][4]f32;
Quat :: struct {x, y, z: f32, w: f32 = 1}; Quat :: struct {x, y, z: f32, w: f32 = 1};
+1 -1
View File
@@ -84,7 +84,7 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
} }
Fixed_Byte_Buffer :: [dynamic]byte; Fixed_Byte_Buffer :: distinct [dynamic]byte;
make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer { make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer {
s := transmute(raw.Slice)backing; s := transmute(raw.Slice)backing;
+2 -2
View File
@@ -1,7 +1,7 @@
foreign import api "system:api" foreign import api "system:api"
Handle :: int; Handle :: distinct int;
Errno :: int; Errno :: distinct int;
O_RDONLY :: 1; O_RDONLY :: 1;
O_WRONLY :: 2; O_WRONLY :: 2;
+3 -3
View File
@@ -4,9 +4,9 @@ foreign import libc "system:c"
import "core:strings.odin" import "core:strings.odin"
import "core:mem.odin" import "core:mem.odin"
Handle :: i32; Handle :: distinct i32;
File_Time :: u64; File_Time :: distinct u64;
Errno :: i32; Errno :: distinct i32;
O_RDONLY :: 0x00000; O_RDONLY :: 0x00000;
+3 -3
View File
@@ -1,8 +1,9 @@
import win32 "core:sys/windows.odin" import win32 "core:sys/windows.odin"
import "core:mem.odin" import "core:mem.odin"
Handle :: uintptr; Handle :: distinct uintptr;
File_Time :: u64; File_Time :: distinct u64;
Errno :: distinct int;
INVALID_HANDLE :: ~Handle(0); INVALID_HANDLE :: ~Handle(0);
@@ -22,7 +23,6 @@ O_SYNC :: 0x01000;
O_ASYNC :: 0x02000; O_ASYNC :: 0x02000;
O_CLOEXEC :: 0x80000; O_CLOEXEC :: 0x80000;
Errno :: int;
ERROR_NONE: Errno : 0; ERROR_NONE: Errno : 0;
ERROR_FILE_NOT_FOUND: Errno : 2; ERROR_FILE_NOT_FOUND: Errno : 2;
+3 -3
View File
@@ -4,9 +4,9 @@ foreign import libc "system:c"
import "core:strings.odin" import "core:strings.odin"
import "core:mem.odin" import "core:mem.odin"
Handle :: i32; Handle :: distinct i32;
File_Time :: u64; File_Time :: distinct u64;
Errno :: int; Errno :: distinct int;
O_RDONLY :: 0x00000; O_RDONLY :: 0x00000;
+2 -2
View File
@@ -12,8 +12,8 @@ CONTEXT_FORWARD_COMPATIBLE_BIT_ARB :: 0x0002;
CONTEXT_CORE_PROFILE_BIT_ARB :: 0x00000001; CONTEXT_CORE_PROFILE_BIT_ARB :: 0x00000001;
CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x00000002; CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x00000002;
Hglrc :: Handle; Hglrc :: distinct Handle;
Color_Ref :: u32; Color_Ref :: distinct u32;
Layer_Plane_Descriptor :: struct { Layer_Plane_Descriptor :: struct {
size: u16, size: u16,
+20 -20
View File
@@ -6,27 +6,27 @@ when ODIN_OS == "windows" {
foreign import "system:shell32.lib" foreign import "system:shell32.lib"
} }
Handle :: rawptr; Handle :: distinct rawptr;
Hwnd :: Handle; Hwnd :: distinct Handle;
Hdc :: Handle; Hdc :: distinct Handle;
Hinstance :: Handle; Hinstance :: distinct Handle;
Hicon :: Handle; Hicon :: distinct Handle;
Hcursor :: Handle; Hcursor :: distinct Handle;
Hmenu :: Handle; Hmenu :: distinct Handle;
Hbrush :: Handle; Hbrush :: distinct Handle;
Hgdiobj :: Handle; Hgdiobj :: distinct Handle;
Hmodule :: Handle; Hmodule :: distinct Handle;
Hmonitor :: Handle; Hmonitor :: distinct Handle;
Hrawinput :: Handle; Hrawinput :: distinct Handle;
HKL :: Handle; HKL :: distinct Handle;
Wparam :: uint; Wparam :: distinct uint;
Lparam :: int; Lparam :: distinct int;
Lresult :: int; Lresult :: distinct int;
Wnd_Proc :: #type proc "c" (Hwnd, u32, Wparam, Lparam) -> Lresult; Wnd_Proc :: distinct #type proc "c" (Hwnd, u32, Wparam, Lparam) -> Lresult;
Long_Ptr :: int; Long_Ptr :: distinct int;
Bool :: b32; Bool :: distinct b32;
Point :: struct { Point :: struct {
x, y: i32, x, y: i32,
@@ -471,7 +471,7 @@ PFD_DEPTH_DONTCARE :: 0x20000000;
PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000; PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000;
PFD_STEREO_DONTCARE :: 0x80000000; PFD_STEREO_DONTCARE :: 0x80000000;
GET_FILEEX_INFO_LEVELS :: i32; GET_FILEEX_INFO_LEVELS :: distinct i32;
GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0; GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0;
GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1; GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
+18 -4
View File
@@ -22,7 +22,7 @@ when ODIN_OS == "windows" {
@(link_name="general_stuff") @(link_name="general_stuff")
general_stuff :: proc() { general_stuff :: proc() {
fmt.println("# general_stuff"); fmt.println("# general_stuff");
{ // `do` for inline statmes rather than block { // `do` for inline statments rather than block
foo :: proc() do fmt.println("Foo!"); foo :: proc() do fmt.println("Foo!");
if false do foo(); if false do foo();
for false do foo(); for false do foo();
@@ -93,6 +93,21 @@ general_stuff :: proc() {
// Having specific sized booleans is very useful when dealing with foreign code // Having specific sized booleans is very useful when dealing with foreign code
// and to enforce specific alignment for a boolean, especially within a struct // and to enforce specific alignment for a boolean, especially within a struct
} }
{ // `distinct` types
// Originally, all type declarations would create a distinct type unless #type_alias was present.
// Now the behaviour has been reversed. All type declarations create a type alias unless `distinct` is present.
// If the type expression is `struct`, `union`, `enum`, `proc`, or `bit_field`, the types will always been distinct.
Int32 :: i32;
compile_assert(Int32 == i32);
My_Int32 :: distinct i32;
compile_assert(My_Int32 != i32);
My_Struct :: struct{x: int};
compile_assert(My_Struct != struct{x: int});
}
} }
default_struct_values :: proc() { default_struct_values :: proc() {
@@ -601,7 +616,7 @@ array_programming :: proc() {
} }
{ {
Vector3 :: [3]f32; Vector3 :: distinct [3]f32;
a := Vector3{1, 2, 3}; a := Vector3{1, 2, 3};
b := Vector3{5, 6, 7}; b := Vector3{5, 6, 7};
c := (a * b)/2 + 1; c := (a * b)/2 + 1;
@@ -675,7 +690,7 @@ enum_export :: proc() {
} }
main :: proc() { main :: proc() {
when true { when false {
general_stuff(); general_stuff();
default_struct_values(); default_struct_values();
union_type(); union_type();
@@ -687,4 +702,3 @@ main :: proc() {
enum_export(); enum_export();
} }
} }
+56 -17
View File
@@ -170,22 +170,57 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
e->Constant.value = operand->value; e->Constant.value = operand->value;
} }
AstNode *remove_type_alias(AstNode *node) {
bool is_type_distinct(AstNode *node) {
for (;;) {
if (node == nullptr) {
return false;
}
if (node->kind == AstNode_ParenExpr) {
node = node->ParenExpr.expr;
} else if (node->kind == AstNode_HelperType) {
node = node->HelperType.type;
} else {
break;
}
}
switch (node->kind) {
case AstNode_DistinctType:
return true;
case AstNode_StructType:
case AstNode_UnionType:
case AstNode_EnumType:
case AstNode_BitFieldType:
case AstNode_ProcType:
return true;
case AstNode_PointerType:
case AstNode_ArrayType:
case AstNode_DynamicArrayType:
case AstNode_MapType:
return true;
}
return false;
}
AstNode *remove_type_alias_clutter(AstNode *node) {
for (;;) { for (;;) {
if (node == nullptr) { if (node == nullptr) {
return nullptr; return nullptr;
} }
if (node->kind == AstNode_ParenExpr) { if (node->kind == AstNode_ParenExpr) {
node = node->ParenExpr.expr; node = node->ParenExpr.expr;
} else if (node->kind == AstNode_AliasType) { } else if (node->kind == AstNode_DistinctType) {
node = node->AliasType.type; node = node->DistinctType.type;
} else { } else {
return node; return node;
} }
} }
} }
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool is_alias) { void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
GB_ASSERT(e->type == nullptr); GB_ASSERT(e->type == nullptr);
DeclInfo *decl = decl_info_of_entity(&c->info, e); DeclInfo *decl = decl_info_of_entity(&c->info, e);
@@ -193,7 +228,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool
error(decl->attributes[0], "Attributes are not allowed on type declarations"); error(decl->attributes[0], "Attributes are not allowed on type declarations");
} }
AstNode *te = remove_type_alias(type_expr); bool is_distinct = is_type_distinct(type_expr);
AstNode *te = remove_type_alias_clutter(type_expr);
e->type = t_invalid; e->type = t_invalid;
String name = e->token.string; String name = e->token.string;
Type *named = make_type_named(c->allocator, name, nullptr, e); Type *named = make_type_named(c->allocator, name, nullptr, e);
@@ -205,16 +241,20 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool
Type *bt = check_type(c, te, named); Type *bt = check_type(c, te, named);
named->Named.base = base_type(bt); named->Named.base = base_type(bt);
if (is_alias) { if (!is_distinct) {
if (is_type_named(bt)) { e->type = bt;
e->type = bt; e->TypeName.is_type_alias = true;
e->TypeName.is_type_alias = true;
} else {
gbString str = type_to_string(bt);
error(type_expr, "Type alias declaration with a non-named type '%s'", str);
gb_string_free(str);
}
} }
// if (is_alias) {
// if (is_type_named(bt)) {
// e->type = bt;
// e->TypeName.is_type_alias = true;
// } else {
// gbString str = type_to_string(bt);
// error(type_expr, "Type alias declaration with a non-named type '%s'", str);
// gb_string_free(str);
// }
// }
} }
void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, Type *named_type) { void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, Type *named_type) {
@@ -261,7 +301,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
error(e->token, "A type declaration cannot have an type parameter"); error(e->token, "A type declaration cannot have an type parameter");
} }
d->type_expr = d->init_expr; d->type_expr = d->init_expr;
check_type_decl(c, e, d->type_expr, named_type, false); check_type_decl(c, e, d->type_expr, named_type);
return; return;
} }
@@ -866,8 +906,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
check_const_decl(c, e, d->type_expr, d->init_expr, named_type); check_const_decl(c, e, d->type_expr, d->init_expr, named_type);
break; break;
case Entity_TypeName: { case Entity_TypeName: {
bool is_alias = unparen_expr(d->type_expr)->kind == AstNode_AliasType; check_type_decl(c, e, d->type_expr, named_type);
check_type_decl(c, e, d->type_expr, named_type, is_alias);
break; break;
} }
case Entity_Procedure: case Entity_Procedure:
+3 -4
View File
@@ -57,7 +57,7 @@ ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *
void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t); void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t);
Type * check_type (Checker *c, AstNode *expression, Type *named_type = nullptr); Type * check_type (Checker *c, AstNode *expression, Type *named_type = nullptr);
Type * make_optional_ok_type (gbAllocator a, Type *value); Type * make_optional_ok_type (gbAllocator a, Type *value);
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def, bool alias); void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def);
Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint); Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
Entity * check_ident (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name); Entity * check_ident (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name);
Entity * find_polymorphic_struct_entity (Checker *c, Type *original_type, isize param_count, Array<Operand> ordered_operands); Entity * find_polymorphic_struct_entity (Checker *c, Type *original_type, isize param_count, Array<Operand> ordered_operands);
@@ -6255,12 +6255,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, ht->type); str = write_expr_to_string(str, ht->type);
case_end; case_end;
case_ast_node(ht, AliasType, node); case_ast_node(ht, DistinctType, node);
str = gb_string_appendc(str, "#type_alias "); str = gb_string_appendc(str, "distinct ");
str = write_expr_to_string(str, ht->type); str = write_expr_to_string(str, ht->type);
case_end; case_end;
case_ast_node(pt, PolyType, node); case_ast_node(pt, PolyType, node);
str = gb_string_append_rune(str, '$'); str = gb_string_append_rune(str, '$');
str = write_expr_to_string(str, pt->type); str = write_expr_to_string(str, pt->type);
+3 -3
View File
@@ -1963,10 +1963,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
return check_type_internal(c, ht->type, type, named_type); return check_type_internal(c, ht->type, type, named_type);
case_end; case_end;
case_ast_node(at, AliasType, e); case_ast_node(dt, DistinctType, e);
error(e, "Invalid use of '#type_alias'"); error(e, "Invalid use of a distinct type");
// NOTE(bill): Treat it as a HelperType to remove errors // NOTE(bill): Treat it as a HelperType to remove errors
return check_type_internal(c, at->type, type, named_type); return check_type_internal(c, dt->type, type, named_type);
case_end; case_end;
case_ast_node(pt, PolyType, e); case_ast_node(pt, PolyType, e);
+16 -13
View File
@@ -80,7 +80,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_TypeType: return node->TypeType.token; case AstNode_TypeType: return node->TypeType.token;
case AstNode_HelperType: return node->HelperType.token; case AstNode_HelperType: return node->HelperType.token;
case AstNode_AliasType: return node->AliasType.token; case AstNode_DistinctType: return node->DistinctType.token;
case AstNode_PolyType: return node->PolyType.token; case AstNode_PolyType: return node->PolyType.token;
case AstNode_ProcType: return node->ProcType.token; case AstNode_ProcType: return node->ProcType.token;
case AstNode_PointerType: return node->PointerType.token; case AstNode_PointerType: return node->PointerType.token;
@@ -321,8 +321,8 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
case AstNode_HelperType: case AstNode_HelperType:
n->HelperType.type = clone_ast_node(a, n->HelperType.type); n->HelperType.type = clone_ast_node(a, n->HelperType.type);
break; break;
case AstNode_AliasType: case AstNode_DistinctType:
n->AliasType.type = clone_ast_node(a, n->AliasType.type); n->DistinctType.type = clone_ast_node(a, n->DistinctType.type);
break; break;
case AstNode_ProcType: case AstNode_ProcType:
n->ProcType.params = clone_ast_node(a, n->ProcType.params); n->ProcType.params = clone_ast_node(a, n->ProcType.params);
@@ -837,14 +837,13 @@ AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
return result; return result;
} }
AstNode *ast_alias_type(AstFile *f, Token token, AstNode *type) { AstNode *ast_distinct_type(AstFile *f, Token token, AstNode *type) {
AstNode *result = make_ast_node(f, AstNode_AliasType); AstNode *result = make_ast_node(f, AstNode_DistinctType);
result->AliasType.token = token; result->DistinctType.token = token;
result->AliasType.type = type; result->DistinctType.type = type;
return result; return result;
} }
AstNode *ast_poly_type(AstFile *f, Token token, AstNode *type, AstNode *specialization) { AstNode *ast_poly_type(AstFile *f, Token token, AstNode *type, AstNode *specialization) {
AstNode *result = make_ast_node(f, AstNode_PolyType); AstNode *result = make_ast_node(f, AstNode_PolyType);
result->PolyType.token = token; result->PolyType.token = token;
@@ -1277,8 +1276,8 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
case AstNode_HelperType: case AstNode_HelperType:
return is_semicolon_optional_for_node(f, s->HelperType.type); return is_semicolon_optional_for_node(f, s->HelperType.type);
case AstNode_AliasType: case AstNode_DistinctType:
return is_semicolon_optional_for_node(f, s->AliasType.type); return is_semicolon_optional_for_node(f, s->DistinctType.type);
case AstNode_PointerType: case AstNode_PointerType:
return is_semicolon_optional_for_node(f, s->PointerType.type); return is_semicolon_optional_for_node(f, s->PointerType.type);
@@ -1614,15 +1613,19 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
return ast_paren_expr(f, operand, open, close); return ast_paren_expr(f, operand, open, close);
} }
case Token_distinct: {
Token token = expect_token(f, Token_distinct);
AstNode *type = parse_type(f);
return ast_distinct_type(f, token, type);
}
case Token_Hash: { case Token_Hash: {
Token token = expect_token(f, Token_Hash); Token token = expect_token(f, Token_Hash);
if (allow_token(f, Token_type)) { if (allow_token(f, Token_type)) {
return ast_helper_type(f, token, parse_type(f)); return ast_helper_type(f, token, parse_type(f));
} }
Token name = expect_token(f, Token_Ident); Token name = expect_token(f, Token_Ident);
if (name.string == "type_alias") { if (name.string == "run") {
return ast_alias_type(f, token, parse_type(f));
} else if (name.string == "run") {
AstNode *expr = parse_expr(f, false); AstNode *expr = parse_expr(f, false);
operand = ast_run_expr(f, token, name, expr); operand = ast_run_expr(f, token, name, expr);
if (unparen_expr(expr)->kind != AstNode_CallExpr) { if (unparen_expr(expr)->kind != AstNode_CallExpr) {
+1 -1
View File
@@ -408,7 +408,7 @@ AST_NODE_KIND(_TypeBegin, "", struct {}) \
Token token; \ Token token; \
AstNode *type; \ AstNode *type; \
}) \ }) \
AST_NODE_KIND(AliasType, "alias type", struct { \ AST_NODE_KIND(DistinctType, "distinct type", struct { \
Token token; \ Token token; \
AstNode *type; \ AstNode *type; \
}) \ }) \
+1
View File
@@ -110,6 +110,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_dynamic, "dynamic"), \ TOKEN_KIND(Token_dynamic, "dynamic"), \
TOKEN_KIND(Token_cast, "cast"), \ TOKEN_KIND(Token_cast, "cast"), \
TOKEN_KIND(Token_transmute, "transmute"), \ TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_distinct, "distinct"), \
TOKEN_KIND(Token_using, "using"), \ TOKEN_KIND(Token_using, "using"), \
TOKEN_KIND(Token_inline, "inline"), \ TOKEN_KIND(Token_inline, "inline"), \
TOKEN_KIND(Token_no_inline, "no_inline"), \ TOKEN_KIND(Token_no_inline, "no_inline"), \