Skip to content

Commit

Permalink
Keep the data of TK_TYPEPARAM pointing to the original definition.
Browse files Browse the repository at this point in the history
iftype is implemented by shadowing the type parameter with a new definition
and a new constraint. Storing the pointer of the original definition
allows us to compare identity of type parameters easily.

This replaces the more complicated subtyping-based check to determine
whether a type parameter should be reified.
  • Loading branch information
plietar committed Jul 2, 2017
1 parent 2adc4e6 commit b289aa2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 18 deletions.
3 changes: 2 additions & 1 deletion src/libponyc/pass/scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ static ast_t* make_iftype_typeparam(pass_opt_t* opt, ast_t* subtype,
TREE(new_constraint)
NONE));

ast_setdata(typeparam, typeparam);
// keep data pointing to the original def
ast_setdata(typeparam, ast_data(def));

return typeparam;
}
Expand Down
28 changes: 11 additions & 17 deletions src/libponyc/type/reify.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,25 @@
#include "../ast/token.h"
#include "ponyassert.h"

static void reify_typeparamref(pass_opt_t* opt, ast_t** astp, ast_t* typeparam, ast_t* typearg)
static void reify_typeparamref(ast_t** astp, ast_t* typeparam, ast_t* typearg)
{
ast_t* ast = *astp;
pony_assert(ast_id(ast) == TK_TYPEPARAMREF);
pony_assert(ast_id(typeparam) == TK_TYPEPARAM);

ast_t* ref_def = (ast_t*)ast_data(ast);
ast_t* param_def = (ast_t*)ast_data(typeparam);

// We can't compare ref_def and typeparam, as they could be a copy or
// a iftype shadowing. However, their data points back to the original
// typeparam definition, which can be compared.
ref_def = (ast_t*)ast_data(ref_def);
typeparam = (ast_t*)ast_data(typeparam);

pony_assert(ref_def != NULL);
pony_assert(param_def != NULL);
AST_GET_CHILDREN(ref_def, ref_name, ref_constraint);
AST_GET_CHILDREN(param_def, param_name, param_constraint);
pony_assert(typeparam != NULL);

if(ref_def != param_def)
{
if(ast_name(ref_name) == ast_name(param_name))
{
if((ast_id(param_constraint) != TK_TYPEPARAMREF) &&
!is_subtype(ref_constraint, param_constraint, NULL, opt))
return;
} else {
return;
}
}
if(ref_def != typeparam)
return;

// Keep ephemerality.
switch(ast_id(ast_childidx(ast, 2)))
Expand Down Expand Up @@ -117,7 +111,7 @@ static void reify_one(pass_opt_t* opt, ast_t** astp, ast_t* typeparam, ast_t* ty
switch(ast_id(ast))
{
case TK_TYPEPARAMREF:
reify_typeparamref(opt, astp, typeparam, typearg);
reify_typeparamref(astp, typeparam, typearg);
break;

case TK_ARROW:
Expand Down
21 changes: 21 additions & 0 deletions test/libponyc/iftype.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,24 @@ TEST_F(IftypeTest, UnconstrainedTypeparam)

TEST_COMPILE(src);
}

TEST_F(IftypeTest, NestedCond)
{
const char* src =
"trait T\n"
"class C is T\n"
" fun tag c() => None\n"

"actor Main\n"
" new create(env: Env) =>\n"
" foo[C](C)\n"

" fun foo[A](x: A) =>\n"
" iftype A <: T then\n"
" iftype A <: C then\n"
" x.c()\n"
" end\n"
" end";

TEST_COMPILE(src);
}

0 comments on commit b289aa2

Please sign in to comment.