mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-14 15:11:25 -07:00
distinct keyword for type declarations
This commit is contained in:
+56
-17
@@ -170,22 +170,57 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||
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 (;;) {
|
||||
if (node == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (node->kind == AstNode_ParenExpr) {
|
||||
node = node->ParenExpr.expr;
|
||||
} else if (node->kind == AstNode_AliasType) {
|
||||
node = node->AliasType.type;
|
||||
} else if (node->kind == AstNode_DistinctType) {
|
||||
node = node->DistinctType.type;
|
||||
} else {
|
||||
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);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
String name = e->token.string;
|
||||
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);
|
||||
named->Named.base = base_type(bt);
|
||||
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);
|
||||
}
|
||||
if (!is_distinct) {
|
||||
e->type = bt;
|
||||
e->TypeName.is_type_alias = true;
|
||||
}
|
||||
// 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) {
|
||||
@@ -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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
break;
|
||||
case Entity_TypeName: {
|
||||
bool is_alias = unparen_expr(d->type_expr)->kind == AstNode_AliasType;
|
||||
check_type_decl(c, e, d->type_expr, named_type, is_alias);
|
||||
check_type_decl(c, e, d->type_expr, named_type);
|
||||
break;
|
||||
}
|
||||
case Entity_Procedure:
|
||||
|
||||
+3
-4
@@ -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);
|
||||
Type * check_type (Checker *c, AstNode *expression, Type *named_type = nullptr);
|
||||
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_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);
|
||||
@@ -6255,12 +6255,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
str = write_expr_to_string(str, ht->type);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ht, AliasType, node);
|
||||
str = gb_string_appendc(str, "#type_alias ");
|
||||
case_ast_node(ht, DistinctType, node);
|
||||
str = gb_string_appendc(str, "distinct ");
|
||||
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);
|
||||
|
||||
+3
-3
@@ -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);
|
||||
case_end;
|
||||
|
||||
case_ast_node(at, AliasType, e);
|
||||
error(e, "Invalid use of '#type_alias'");
|
||||
case_ast_node(dt, DistinctType, e);
|
||||
error(e, "Invalid use of a distinct type");
|
||||
// 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_ast_node(pt, PolyType, e);
|
||||
|
||||
+16
-13
@@ -80,7 +80,7 @@ Token ast_node_token(AstNode *node) {
|
||||
|
||||
case AstNode_TypeType: return node->TypeType.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_ProcType: return node->ProcType.token;
|
||||
case AstNode_PointerType: return node->PointerType.token;
|
||||
@@ -321,8 +321,8 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
||||
case AstNode_HelperType:
|
||||
n->HelperType.type = clone_ast_node(a, n->HelperType.type);
|
||||
break;
|
||||
case AstNode_AliasType:
|
||||
n->AliasType.type = clone_ast_node(a, n->AliasType.type);
|
||||
case AstNode_DistinctType:
|
||||
n->DistinctType.type = clone_ast_node(a, n->DistinctType.type);
|
||||
break;
|
||||
case AstNode_ProcType:
|
||||
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;
|
||||
}
|
||||
|
||||
AstNode *ast_alias_type(AstFile *f, Token token, AstNode *type) {
|
||||
AstNode *result = make_ast_node(f, AstNode_AliasType);
|
||||
result->AliasType.token = token;
|
||||
result->AliasType.type = type;
|
||||
AstNode *ast_distinct_type(AstFile *f, Token token, AstNode *type) {
|
||||
AstNode *result = make_ast_node(f, AstNode_DistinctType);
|
||||
result->DistinctType.token = token;
|
||||
result->DistinctType.type = type;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_poly_type(AstFile *f, Token token, AstNode *type, AstNode *specialization) {
|
||||
AstNode *result = make_ast_node(f, AstNode_PolyType);
|
||||
result->PolyType.token = token;
|
||||
@@ -1277,8 +1276,8 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
|
||||
case AstNode_HelperType:
|
||||
return is_semicolon_optional_for_node(f, s->HelperType.type);
|
||||
case AstNode_AliasType:
|
||||
return is_semicolon_optional_for_node(f, s->AliasType.type);
|
||||
case AstNode_DistinctType:
|
||||
return is_semicolon_optional_for_node(f, s->DistinctType.type);
|
||||
|
||||
case AstNode_PointerType:
|
||||
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);
|
||||
}
|
||||
|
||||
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: {
|
||||
Token token = expect_token(f, Token_Hash);
|
||||
if (allow_token(f, Token_type)) {
|
||||
return ast_helper_type(f, token, parse_type(f));
|
||||
}
|
||||
Token name = expect_token(f, Token_Ident);
|
||||
if (name.string == "type_alias") {
|
||||
return ast_alias_type(f, token, parse_type(f));
|
||||
} else if (name.string == "run") {
|
||||
if (name.string == "run") {
|
||||
AstNode *expr = parse_expr(f, false);
|
||||
operand = ast_run_expr(f, token, name, expr);
|
||||
if (unparen_expr(expr)->kind != AstNode_CallExpr) {
|
||||
|
||||
+1
-1
@@ -408,7 +408,7 @@ AST_NODE_KIND(_TypeBegin, "", struct {}) \
|
||||
Token token; \
|
||||
AstNode *type; \
|
||||
}) \
|
||||
AST_NODE_KIND(AliasType, "alias type", struct { \
|
||||
AST_NODE_KIND(DistinctType, "distinct type", struct { \
|
||||
Token token; \
|
||||
AstNode *type; \
|
||||
}) \
|
||||
|
||||
@@ -110,6 +110,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
||||
TOKEN_KIND(Token_cast, "cast"), \
|
||||
TOKEN_KIND(Token_transmute, "transmute"), \
|
||||
TOKEN_KIND(Token_distinct, "distinct"), \
|
||||
TOKEN_KIND(Token_using, "using"), \
|
||||
TOKEN_KIND(Token_inline, "inline"), \
|
||||
TOKEN_KIND(Token_no_inline, "no_inline"), \
|
||||
|
||||
Reference in New Issue
Block a user