mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-25 05:09:53 +00:00
Be more thorough in detecting generic procedure types
This commit is contained in:
@@ -2199,6 +2199,57 @@ parse_proc_tags :: proc(p: ^Parser) -> (tags: ast.Proc_Tags) {
|
||||
return
|
||||
}
|
||||
|
||||
is_expr_generic :: proc(expr : ^ast.Expr) -> bool {
|
||||
is_generic := false
|
||||
if expr != nil {
|
||||
#partial switch e in expr.derived_expr {
|
||||
case ^ast.Typeid_Type:
|
||||
is_generic = e.specialization != nil
|
||||
case ^ast.Poly_Type:
|
||||
is_generic = true
|
||||
case ^ast.Proc_Type:
|
||||
is_generic = e.generic
|
||||
case ^ast.Pointer_Type:
|
||||
is_generic = is_expr_generic(e.elem)
|
||||
case ^ast.Multi_Pointer_Type:
|
||||
is_generic = is_expr_generic(e.elem)
|
||||
case ^ast.Array_Type:
|
||||
is_generic = is_expr_generic(e.len) || is_expr_generic(e.elem)
|
||||
case ^ast.Dynamic_Array_Type:
|
||||
is_generic = is_expr_generic(e.elem)
|
||||
case ^ast.Fixed_Capacity_Dynamic_Array_Type:
|
||||
is_generic = is_expr_generic(e.capacity) || is_expr_generic(e.elem)
|
||||
case ^ast.Bit_Set_Type:
|
||||
is_generic = is_expr_generic(e.elem)
|
||||
case ^ast.Map_Type:
|
||||
is_generic = is_expr_generic(e.key) || is_expr_generic(e.value)
|
||||
case ^ast.Matrix_Type:
|
||||
is_generic = is_expr_generic(e.row_count) || is_expr_generic(e.column_count) || is_expr_generic(e.elem)
|
||||
}
|
||||
}
|
||||
return is_generic
|
||||
}
|
||||
|
||||
is_field_list_generic :: proc(field_list : ^ast.Field_List, check_names : bool) -> bool {
|
||||
is_generic := false
|
||||
loop: for param in field_list.list {
|
||||
if is_expr_generic(param.type) {
|
||||
is_generic = true
|
||||
break loop
|
||||
}
|
||||
if !check_names || param.type == nil {
|
||||
continue
|
||||
}
|
||||
for name in param.names {
|
||||
if _, ok := name.derived.(^ast.Poly_Type); ok {
|
||||
is_generic = true
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
return is_generic
|
||||
}
|
||||
|
||||
parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type {
|
||||
cc: ast.Proc_Calling_Convention
|
||||
if p.curr_tok.kind == .String {
|
||||
@@ -2220,21 +2271,9 @@ parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type {
|
||||
expect_closing_parentheses_of_field_list(p)
|
||||
results, diverging := parse_results(p)
|
||||
|
||||
is_generic := false
|
||||
|
||||
loop: for param in params.list {
|
||||
if param.type != nil {
|
||||
if _, ok := param.type.derived.(^ast.Poly_Type); ok {
|
||||
is_generic = true
|
||||
break loop
|
||||
}
|
||||
for name in param.names {
|
||||
if _, ok := name.derived.(^ast.Poly_Type); ok {
|
||||
is_generic = true
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
is_generic := is_field_list_generic(params, true)
|
||||
if !is_generic && results != nil {
|
||||
is_generic = is_field_list_generic(results, false)
|
||||
}
|
||||
|
||||
end := end_pos(p.prev_tok)
|
||||
|
||||
@@ -4106,6 +4106,71 @@ gb_internal ProcCallingConvention string_to_calling_convention(String const &s)
|
||||
return ProcCC_Invalid;
|
||||
}
|
||||
|
||||
gb_internal bool is_ast_generic(Ast *a) {
|
||||
bool is_generic = false;
|
||||
if (a != nullptr) {
|
||||
switch (a->kind) {
|
||||
case Ast_TypeidType:
|
||||
is_generic = a->TypeidType.specialization != nullptr;
|
||||
break;
|
||||
case Ast_PolyType:
|
||||
is_generic = true;
|
||||
break;
|
||||
case Ast_ProcType:
|
||||
is_generic = a->ProcType.generic;
|
||||
break;
|
||||
case Ast_PointerType:
|
||||
is_generic = is_ast_generic(a->PointerType.type);
|
||||
break;
|
||||
case Ast_MultiPointerType:
|
||||
is_generic = is_ast_generic(a->MultiPointerType.type);
|
||||
break;
|
||||
case Ast_ArrayType:
|
||||
is_generic = is_ast_generic(a->ArrayType.elem) || is_ast_generic(a->ArrayType.count);
|
||||
break;
|
||||
case Ast_DynamicArrayType:
|
||||
is_generic = is_ast_generic(a->DynamicArrayType.elem);
|
||||
break;
|
||||
case Ast_FixedCapacityDynamicArrayType:
|
||||
is_generic = is_ast_generic(a->FixedCapacityDynamicArrayType.elem) || is_ast_generic(a->FixedCapacityDynamicArrayType.capacity);
|
||||
break;
|
||||
case Ast_BitSetType:
|
||||
is_generic = is_ast_generic(a->BitSetType.elem);
|
||||
break;
|
||||
case Ast_MapType:
|
||||
is_generic = is_ast_generic(a->MapType.key) || is_ast_generic(a->MapType.value);
|
||||
break;
|
||||
case Ast_MatrixType:
|
||||
is_generic = is_ast_generic(a->MatrixType.row_count) || is_ast_generic(a->MatrixType.column_count) || is_ast_generic(a->MatrixType.elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return is_generic;
|
||||
}
|
||||
|
||||
gb_internal bool is_field_list_generic(AstFieldList *field_list, bool check_names) {
|
||||
bool is_generic = false;
|
||||
|
||||
for (Ast *param : field_list->list) {
|
||||
ast_node(field, Field, param);
|
||||
if (is_ast_generic(field->type)) {
|
||||
is_generic = true;
|
||||
goto end;
|
||||
}
|
||||
if (!check_names || field->type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (Ast *name : field->names) {
|
||||
if (name->kind == Ast_PolyType) {
|
||||
is_generic = true;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
return is_generic;
|
||||
}
|
||||
|
||||
gb_internal Ast *parse_proc_type(AstFile *f, Token proc_token) {
|
||||
Ast *params = nullptr;
|
||||
Ast *results = nullptr;
|
||||
@@ -4141,24 +4206,11 @@ gb_internal Ast *parse_proc_type(AstFile *f, Token proc_token) {
|
||||
results = parse_results(f, &diverging);
|
||||
|
||||
u64 tags = 0;
|
||||
bool is_generic = false;
|
||||
|
||||
for (Ast *param : params->FieldList.list) {
|
||||
ast_node(field, Field, param);
|
||||
if (field->type != nullptr) {
|
||||
if (field->type->kind == Ast_PolyType) {
|
||||
is_generic = true;
|
||||
goto end;
|
||||
}
|
||||
for (Ast *name : field->names) {
|
||||
if (name->kind == Ast_PolyType) {
|
||||
is_generic = true;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool is_generic = is_field_list_generic(¶ms->FieldList, true);
|
||||
if (!is_generic && (results != nullptr)) {
|
||||
is_generic = is_field_list_generic(&results->FieldList, false);
|
||||
}
|
||||
end:
|
||||
|
||||
return ast_proc_type(f, proc_token, params, results, tags, cc, is_generic, diverging);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user