From 781395ada1883203582adec70e5ab1a2eda316bb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 16 Jun 2020 16:21:44 +0100 Subject: Add `deferred_in_out` attribute --- src/checker.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 2ca4d794f..df15ffc67 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2337,6 +2337,22 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } error(elem, "Expected a procedure entity for '%.*s'", LIT(name)); return false; + } else if (name == "deferred_in_out") { + if (value != nullptr) { + Operand o = {}; + check_expr(c, &o, value); + Entity *e = entity_of_node(o.expr); + if (e != nullptr && e->kind == Entity_Procedure) { + if (ac->deferred_procedure.entity != nullptr) { + error(elem, "Previous usage of a 'deferred_*' attribute"); + } + ac->deferred_procedure.kind = DeferredProcedure_in_out; + ac->deferred_procedure.entity = e; + return true; + } + } + error(elem, "Expected a procedure entity for '%.*s'", LIT(name)); + return false; } else if (name == "link_name") { ExactValue ev = check_decl_attribute_value(c, value); @@ -4379,6 +4395,9 @@ void check_parsed_files(Checker *c) { case DeferredProcedure_out: error(src->token, "'deferred_out' cannot be used with a polymorphic procedure"); break; + case DeferredProcedure_in_out: + error(src->token, "'deferred_in_out' cannot be used with a polymorphic procedure"); + break; } continue; } @@ -4457,6 +4476,53 @@ void check_parsed_files(Checker *c) { gb_string_free(s); continue; } + } else if (dst_kind == DeferredProcedure_in_out) { + if (src_params == nullptr && src_results == nullptr && dst_params == nullptr) { + // Okay + continue; + } + + GB_ASSERT(dst_params->kind == Type_Tuple); + + Type *tsrc = alloc_type_tuple(); + auto &sv = tsrc->Tuple.variables; + auto const &dv = dst_params->Tuple.variables; + + isize len = 0; + if (src_params != nullptr) { + GB_ASSERT(src_params->kind == Type_Tuple); + len += src_params->Tuple.variables.count; + } + if (src_results != nullptr) { + GB_ASSERT(src_results->kind == Type_Tuple); + len += src_results->Tuple.variables.count; + } + array_init(&sv, heap_allocator(), 0, len); + if (src_params != nullptr) { + for_array(i, src_params->Tuple.variables) { + array_add(&sv, src_params->Tuple.variables[i]); + } + } + if (src_results != nullptr) { + for_array(i, src_results->Tuple.variables) { + array_add(&sv, src_results->Tuple.variables[i]); + } + } + + + if (are_types_identical(tsrc, dst_params)) { + // Okay! + } else { + gbString s = type_to_string(tsrc); + gbString d = type_to_string(dst_params); + error(src->token, "Deferred procedure '%.*s' parameters do not match the results of initial procedure '%.*s':\n\t(%s) =/= (%s)", + LIT(src->token.string), LIT(dst->token.string), + s, d + ); + gb_string_free(d); + gb_string_free(s); + continue; + } } } -- cgit v1.2.3