aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-11-11 17:08:30 +0000
committergingerBill <bill@gingerbill.org>2018-11-11 17:08:30 +0000
commitb55b1ffe14bc4a7459cd9b9bdb8b9b0c8f7f8091 (patch)
tree77df172a7e387801f9f43999dcc412a6fb5b71be /src
parent620d5d34f7c5712be27a92e1ab6ab48119f0a4c6 (diff)
`opaque` keyword and type
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp3
-rw-r--r--src/check_expr.cpp12
-rw-r--r--src/check_type.cpp7
-rw-r--r--src/checker.cpp6
-rw-r--r--src/ir.cpp12
-rw-r--r--src/ir_print.cpp4
-rw-r--r--src/parser.cpp17
-rw-r--r--src/parser.hpp4
-rw-r--r--src/tokenizer.cpp1
-rw-r--r--src/types.cpp48
10 files changed, 110 insertions, 4 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index de0aa572d..3fb53bb19 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -198,6 +198,9 @@ bool is_type_distinct(Ast *node) {
case Ast_DynamicArrayType:
case Ast_MapType:
return false;
+
+ case Ast_OpaqueType:
+ return true;
}
return false;
}
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 6b2a07a86..61bf9eeca 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1911,6 +1911,13 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
return true;
}
+ if (is_type_opaque(src)) {
+ return are_types_identical(dst, src->Opaque.elem);
+ }
+ if (is_type_opaque(dst)) {
+ return are_types_identical(dst->Opaque.elem, src);
+ }
+
return false;
}
@@ -6602,6 +6609,11 @@ gbString write_expr_to_string(gbString str, Ast *node) {
str = write_expr_to_string(str, ht->type);
case_end;
+ case_ast_node(ht, OpaqueType, node);
+ str = gb_string_appendc(str, "opaque ");
+ str = write_expr_to_string(str, ht->type);
+ case_end;
+
case_ast_node(pt, PolyType, node);
str = gb_string_append_rune(str, '$');
str = write_expr_to_string(str, pt->type);
diff --git a/src/check_type.cpp b/src/check_type.cpp
index f38826a25..5bb404ae8 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -2341,6 +2341,13 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
return true;
case_end;
+ case_ast_node(ot, OpaqueType, e);
+ Type *elem = strip_opaque_type(check_type(ctx, ot->type));
+ *type = alloc_type_opaque(elem);
+ set_base_type(named_type, *type);
+ return true;
+ case_end;
+
case_ast_node(at, ArrayType, e);
if (at->count != nullptr) {
Operand o = {};
diff --git a/src/checker.cpp b/src/checker.cpp
index 5daefc896..d289d236c 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -1064,6 +1064,10 @@ void add_type_info_type(CheckerContext *c, Type *t) {
add_type_info_type(c, bt->BitSet.elem);
break;
+ case Type_Opaque:
+ add_type_info_type(c, bt->Opaque.elem);
+ break;
+
case Type_Union:
add_type_info_type(c, t_int);
add_type_info_type(c, t_type_info_ptr);
@@ -1626,6 +1630,7 @@ void init_core_type_info(Checker *c) {
t_type_info_map = find_core_type(c, str_lit("Type_Info_Map"));
t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field"));
t_type_info_bit_set = find_core_type(c, str_lit("Type_Info_Bit_Set"));
+ t_type_info_opaque = find_core_type(c, str_lit("Type_Info_Opaque"));
t_type_info_named_ptr = alloc_type_pointer(t_type_info_named);
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
@@ -1648,6 +1653,7 @@ void init_core_type_info(Checker *c) {
t_type_info_map_ptr = alloc_type_pointer(t_type_info_map);
t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field);
t_type_info_bit_set_ptr = alloc_type_pointer(t_type_info_bit_set);
+ t_type_info_opaque_ptr = alloc_type_pointer(t_type_info_opaque);
}
void init_mem_allocator(Checker *c) {
diff --git a/src/ir.cpp b/src/ir.cpp
index 6f1637b7a..39c7eb25c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -2273,6 +2273,10 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
return di;
}
+ if (is_type_opaque(type)) {
+ return ir_add_debug_info_type(module, strip_opaque_type(type), e, scope, file);
+ }
+
if (is_type_struct(type) ||
is_type_union(type) || is_type_enum(type) || is_type_tuple(type)) {
if (type->kind == Type_Named) {
@@ -9455,10 +9459,14 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_const_i64(t->BitSet.upper));
break;
-
-
+ case Type_Opaque:
+ ir_emit_comment(proc, str_lit("Type_Opaque"));
+ tag = ir_emit_conv(proc, variant_ptr, t_type_info_opaque_ptr);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->Opaque.elem));
+ break;
}
+
if (tag != nullptr) {
Type *tag_type = type_deref(ir_type(tag));
GB_ASSERT(is_type_named(tag_type));
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index c8b255d2f..1879e6d78 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -512,6 +512,10 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
ir_print_type(f, m, bit_set_to_int(t));
return;
}
+
+ case Type_Opaque:
+ ir_print_type(f, m, strip_opaque_type(t));
+ return;
}
}
diff --git a/src/parser.cpp b/src/parser.cpp
index 38678a6dc..e7181bfbb 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -80,6 +80,7 @@ Token ast_token(Ast *node) {
case Ast_TypeidType: return node->TypeidType.token;
case Ast_HelperType: return node->HelperType.token;
case Ast_DistinctType: return node->DistinctType.token;
+ case Ast_OpaqueType: return node->OpaqueType.token;
case Ast_PolyType: return node->PolyType.token;
case Ast_ProcType: return node->ProcType.token;
case Ast_PointerType: return node->PointerType.token;
@@ -319,6 +320,9 @@ Ast *clone_ast(Ast *node) {
case Ast_DistinctType:
n->DistinctType.type = clone_ast(n->DistinctType.type);
break;
+ case Ast_OpaqueType:
+ n->OpaqueType.type = clone_ast(n->OpaqueType.type);
+ break;
case Ast_ProcType:
n->ProcType.params = clone_ast(n->ProcType.params);
n->ProcType.results = clone_ast(n->ProcType.results);
@@ -849,6 +853,13 @@ Ast *ast_distinct_type(AstFile *f, Token token, Ast *type) {
return result;
}
+Ast *ast_opaque_type(AstFile *f, Token token, Ast *type) {
+ Ast *result = alloc_ast_node(f, Ast_OpaqueType);
+ result->OpaqueType.token = token;
+ result->OpaqueType.type = type;
+ return result;
+}
+
Ast *ast_poly_type(AstFile *f, Token token, Ast *type, Ast *specialization) {
Ast *result = alloc_ast_node(f, Ast_PolyType);
result->PolyType.token = token;
@@ -1654,6 +1665,12 @@ Ast *parse_operand(AstFile *f, bool lhs) {
return ast_distinct_type(f, token, type);
}
+ case Token_opaque: {
+ Token token = expect_token(f, Token_opaque);
+ Ast *type = parse_type(f);
+ return ast_opaque_type(f, token, type);
+ }
+
case Token_Hash: {
Token token = expect_token(f, Token_Hash);
Token name = expect_token(f, Token_Ident);
diff --git a/src/parser.hpp b/src/parser.hpp
index 825e26f32..6a59f05a6 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -434,6 +434,10 @@ AST_KIND(_TypeBegin, "", bool) \
Token token; \
Ast *type; \
}) \
+ AST_KIND(OpaqueType, "opaque type", struct { \
+ Token token; \
+ Ast *type; \
+ }) \
AST_KIND(PolyType, "polymorphic type", struct { \
Token token; \
Ast * type; \
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 3ec491fa7..e2a5827ac 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -113,6 +113,7 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
TOKEN_KIND(Token_cast, "cast"), \
TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_distinct, "distinct"), \
+ TOKEN_KIND(Token_opaque, "opaque"), \
TOKEN_KIND(Token_using, "using"), \
TOKEN_KIND(Token_inline, "inline"), \
TOKEN_KIND(Token_no_inline, "no_inline"), \
diff --git a/src/types.cpp b/src/types.cpp
index f5d1bb4a9..74cc264da 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -127,6 +127,7 @@ struct TypeUnion {
Scope *scope; \
}) \
TYPE_KIND(Pointer, struct { Type *elem; }) \
+ TYPE_KIND(Opaque, struct { Type *elem; }) \
TYPE_KIND(Array, struct { \
Type *elem; \
i64 count; \
@@ -400,6 +401,7 @@ gb_global Type *t_type_info_enum = nullptr;
gb_global Type *t_type_info_map = nullptr;
gb_global Type *t_type_info_bit_field = nullptr;
gb_global Type *t_type_info_bit_set = nullptr;
+gb_global Type *t_type_info_opaque = nullptr;
gb_global Type *t_type_info_named_ptr = nullptr;
gb_global Type *t_type_info_integer_ptr = nullptr;
@@ -423,6 +425,7 @@ gb_global Type *t_type_info_enum_ptr = nullptr;
gb_global Type *t_type_info_map_ptr = nullptr;
gb_global Type *t_type_info_bit_field_ptr = nullptr;
gb_global Type *t_type_info_bit_set_ptr = nullptr;
+gb_global Type *t_type_info_opaque_ptr = nullptr;
gb_global Type *t_allocator = nullptr;
gb_global Type *t_allocator_ptr = nullptr;
@@ -461,6 +464,19 @@ Type *base_type(Type *t) {
return t;
}
+Type *strip_opaque_type(Type *t) {
+ for (;;) {
+ if (t == nullptr) {
+ break;
+ }
+ if (t->kind != Type_Opaque) {
+ break;
+ }
+ t = t->Opaque.elem;
+ }
+ return t;
+}
+
Type *base_enum_type(Type *t) {
Type *bt = base_type(t);
if (bt != nullptr &&
@@ -486,6 +502,9 @@ Type *core_type(Type *t) {
case Type_Enum:
t = t->Enum.base_type;
continue;
+ case Type_Opaque:
+ t = t->Opaque.elem;
+ continue;
}
break;
}
@@ -519,6 +538,12 @@ Type *alloc_type_generic(Scope *scope, i64 id, String name, Type *specialized) {
return t;
}
+Type *alloc_type_opaque(Type *elem) {
+ Type *t = alloc_type(Type_Opaque);
+ t->Opaque.elem = elem;
+ return t;
+}
+
Type *alloc_type_pointer(Type *elem) {
Type *t = alloc_type(Type_Pointer);
t->Pointer.elem = elem;
@@ -819,8 +844,10 @@ bool is_type_tuple(Type *t) {
t = base_type(t);
return t->kind == Type_Tuple;
}
-
-
+bool is_type_opaque(Type *t) {
+ t = base_type(t);
+ return t->kind == Type_Opaque;
+}
bool is_type_uintptr(Type *t) {
if (t->kind == Type_Basic) {
return (t->Basic.kind == Basic_uintptr);
@@ -1212,6 +1239,8 @@ bool type_has_nil(Type *t) {
return true;
case Type_Struct:
return false;
+ case Type_Opaque:
+ return true;
}
return false;
}
@@ -1257,6 +1286,9 @@ bool is_type_comparable(Type *t) {
case Type_BitSet:
return true;
+
+ case Type_Opaque:
+ return is_type_comparable(t->Opaque.elem);
}
return false;
}
@@ -1294,6 +1326,12 @@ bool are_types_identical(Type *x, Type *y) {
}
break;
+ case Type_Opaque:
+ if (y->kind == Type_Opaque) {
+ return are_types_identical(x->Opaque.elem, y->Opaque.elem);
+ }
+ break;
+
case Type_Basic:
if (y->kind == Type_Basic) {
return x->Basic.kind == y->Basic.kind;
@@ -2061,6 +2099,9 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
return align;
}
+ case Type_Opaque:
+ return type_align_of_internal(t->Opaque.elem, path);
+
case Type_DynamicArray:
// data, count, capacity, allocator
return build_context.word_size;
@@ -2265,6 +2306,9 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
case Type_Pointer:
return build_context.word_size;
+ case Type_Opaque:
+ return type_size_of_internal(t->Opaque.elem, path);
+
case Type_Array: {
i64 count, align, size, alignment;
count = t->Array.count;