no semantic changes: factored some of the complexity of begin_func() into a pair of static functions for clarity

This commit is contained in:
Vern Paxson 2021-01-04 13:40:37 -08:00
parent 9cb506ad97
commit 98529ae4ec

View file

@ -486,43 +486,27 @@ static bool canonical_arg_types_match(const FuncType* decl, const FuncType* impl
return true;
}
void begin_func(IDPtr id, const char* module_name,
FunctionFlavor flavor, bool is_redef,
FuncTypePtr t,
std::unique_ptr<std::vector<AttrPtr>> attrs)
{
if ( flavor == FUNC_FLAVOR_EVENT )
{
const auto& yt = t->Yield();
if ( yt && yt->Tag() != TYPE_VOID )
id->Error("event cannot yield a value", t.get());
t->ClearYieldType(flavor);
}
std::optional<FuncType::Prototype> prototype;
if ( id->GetType() )
static auto get_prototype(IDPtr id, FuncTypePtr t)
{
auto decl = id->GetType()->AsFuncType();
prototype = func_type_check(decl, t.get());
auto prototype = func_type_check(decl, t.get());
if ( prototype )
{
if ( decl->Flavor() == FUNC_FLAVOR_FUNCTION )
{
// If a previous declaration of the function had &default
// params, automatically transfer any that are missing
// (convenience so that implementations don't need to specify
// the &default expression again).
// If a previous declaration of the function had
// &default params, automatically transfer any that
// are missing (convenience so that implementations
// don't need to specify the &default expression again).
transfer_arg_defaults(prototype->args.get(), t->Params().get());
}
else
{
// Warn for trying to use &default parameters in hook/event
// handler body when it already has a declaration since only
// &default in the declaration has any effect.
// Warn for trying to use &default parameters in
// hook/event handler body when it already has a
// declaration since only &default in the declaration
// has any effect.
const auto& args = t->Params();
for ( int i = 0; i < args->NumFields(); ++i )
@ -551,6 +535,7 @@ void begin_func(IDPtr id, const char* module_name,
prototype->args.get(), true);
}
}
else
{
// Allow renaming arguments, but only for the canonical
@ -560,8 +545,80 @@ void begin_func(IDPtr id, const char* module_name,
else
t->Error("use of undeclared alternate prototype", id.get());
}
return prototype;
}
static bool check_params(int i, std::optional<FuncType::Prototype> prototype,
const RecordTypePtr& args,
const RecordTypePtr& canon_args,
const char* module_name)
{
TypeDecl* arg_i;
bool hide = false;
if ( prototype )
{
auto it = prototype->offsets.find(i);
if ( it == prototype->offsets.end() )
{
// Alternate prototype hides this param
hide = true;
arg_i = canon_args->FieldDecl(i);
}
else
{
// Alternate prototype maps this param to another index
arg_i = args->FieldDecl(it->second);
}
}
else
{
if ( i < args->NumFields() )
arg_i = args->FieldDecl(i);
else
return false;
}
auto arg_id = lookup_ID(arg_i->id, module_name);
if ( arg_id && ! arg_id->IsGlobal() )
arg_id->Error("argument name used twice");
const char* local_name = arg_i->id;
if ( hide )
// Note the illegal '-' in hidden name implies we haven't
// clobbered any local variable names.
local_name = util::fmt("%s-hidden", local_name);
arg_id = install_ID(local_name, module_name, false, false);
arg_id->SetType(arg_i->type);
return true;
}
void begin_func(IDPtr id, const char* module_name,
FunctionFlavor flavor, bool is_redef,
FuncTypePtr t,
std::unique_ptr<std::vector<AttrPtr>> attrs)
{
if ( flavor == FUNC_FLAVOR_EVENT )
{
const auto& yt = t->Yield();
if ( yt && yt->Tag() != TYPE_VOID )
id->Error("event cannot yield a value", t.get());
t->ClearYieldType(flavor);
}
std::optional<FuncType::Prototype> prototype;
if ( id->GetType() )
prototype = get_prototype(id, t);
else if ( is_redef )
id->Error("redef of not-previously-declared value");
@ -604,49 +661,8 @@ void begin_func(IDPtr id, const char* module_name,
push_scope(std::move(id), std::move(attrs));
for ( int i = 0; i < canon_args->NumFields(); ++i )
{
TypeDecl* arg_i;
bool hide = false;
if ( prototype )
{
auto it = prototype->offsets.find(i);
if ( it == prototype->offsets.end() )
{
// Alternate prototype hides this param
hide = true;
arg_i = canon_args->FieldDecl(i);
}
else
{
// Alternate prototype maps this param to another index
arg_i = args->FieldDecl(it->second);
}
}
else
{
if ( i < args->NumFields() )
arg_i = args->FieldDecl(i);
else
if ( ! check_params(i, prototype, args, canon_args, module_name) )
break;
}
auto arg_id = lookup_ID(arg_i->id, module_name);
if ( arg_id && ! arg_id->IsGlobal() )
arg_id->Error("argument name used twice");
const char* local_name = arg_i->id;
if ( hide )
// Note the illegal '-' in hidden name implies we haven't
// clobbered any local variable names.
local_name = util::fmt("%s-hidden", local_name);
arg_id = install_ID(local_name, module_name, false, false);
arg_id->SetType(arg_i->type);
}
if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) )
current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());