mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Add deferred_in_out attribute
This commit is contained in:
@@ -2337,6 +2337,22 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|||||||
}
|
}
|
||||||
error(elem, "Expected a procedure entity for '%.*s'", LIT(name));
|
error(elem, "Expected a procedure entity for '%.*s'", LIT(name));
|
||||||
return false;
|
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") {
|
} else if (name == "link_name") {
|
||||||
ExactValue ev = check_decl_attribute_value(c, value);
|
ExactValue ev = check_decl_attribute_value(c, value);
|
||||||
|
|
||||||
@@ -4379,6 +4395,9 @@ void check_parsed_files(Checker *c) {
|
|||||||
case DeferredProcedure_out:
|
case DeferredProcedure_out:
|
||||||
error(src->token, "'deferred_out' cannot be used with a polymorphic procedure");
|
error(src->token, "'deferred_out' cannot be used with a polymorphic procedure");
|
||||||
break;
|
break;
|
||||||
|
case DeferredProcedure_in_out:
|
||||||
|
error(src->token, "'deferred_in_out' cannot be used with a polymorphic procedure");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -4457,6 +4476,53 @@ void check_parsed_files(Checker *c) {
|
|||||||
gb_string_free(s);
|
gb_string_free(s);
|
||||||
continue;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ enum DeferredProcedureKind {
|
|||||||
DeferredProcedure_none,
|
DeferredProcedure_none,
|
||||||
DeferredProcedure_in,
|
DeferredProcedure_in,
|
||||||
DeferredProcedure_out,
|
DeferredProcedure_out,
|
||||||
|
DeferredProcedure_in_out,
|
||||||
};
|
};
|
||||||
struct DeferredProcedure {
|
struct DeferredProcedure {
|
||||||
DeferredProcedureKind kind;
|
DeferredProcedureKind kind;
|
||||||
|
|||||||
@@ -3319,6 +3319,14 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> const &ar
|
|||||||
case DeferredProcedure_out:
|
case DeferredProcedure_out:
|
||||||
result_as_args = ir_value_to_array(p, result);
|
result_as_args = ir_value_to_array(p, result);
|
||||||
break;
|
break;
|
||||||
|
case DeferredProcedure_in_out:
|
||||||
|
{
|
||||||
|
auto out_args = ir_value_to_array(p, result);
|
||||||
|
array_init(&result_as_args, heap_allocator(), in_args.count + out_args.count);
|
||||||
|
array_copy(&result_as_args, in_args, 0);
|
||||||
|
array_copy(&result_as_args, out_args, in_args.count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_add_defer_proc(p, p->scope_index, deferred, result_as_args);
|
ir_add_defer_proc(p, p->scope_index, deferred, result_as_args);
|
||||||
|
|||||||
@@ -7113,6 +7113,14 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
|
|||||||
case DeferredProcedure_out:
|
case DeferredProcedure_out:
|
||||||
result_as_args = lb_value_to_array(p, result);
|
result_as_args = lb_value_to_array(p, result);
|
||||||
break;
|
break;
|
||||||
|
case DeferredProcedure_in_out:
|
||||||
|
{
|
||||||
|
auto out_args = lb_value_to_array(p, result);
|
||||||
|
array_init(&result_as_args, heap_allocator(), in_args.count + out_args.count);
|
||||||
|
array_copy(&result_as_args, in_args, 0);
|
||||||
|
array_copy(&result_as_args, out_args, in_args.count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lb_add_defer_proc(p, p->scope_index, deferred, result_as_args);
|
lb_add_defer_proc(p, p->scope_index, deferred, result_as_args);
|
||||||
|
|||||||
Reference in New Issue
Block a user