Skip to content

Commit

Permalink
Create a new AST node for iftype clauses.
Browse files Browse the repository at this point in the history
This creates a new scope with both the constraint and the body of the
iftype, but without the else clause.
  • Loading branch information
plietar committed Jul 2, 2017
1 parent b289aa2 commit 327e99b
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/libponyc/ast/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ bool frame_push(typecheck_t* t, ast_t* ast)
break;
}

case TK_IFTYPE:
case TK_IFTYPE_CLAUSE:
{
AST_GET_CHILDREN(parent, l_type, r_type, body);

Expand Down
27 changes: 15 additions & 12 deletions src/libponyc/ast/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,31 +738,34 @@ DEF(ifdef);
REORDER(0, 2, 3, 1);
DONE();

// ELSEIF [annotations] type <: type THEN seq [elseiftype | (ELSE seq)]
DEF(elseiftype);
AST_NODE(TK_IFTYPE);
// type <: type THEN seq
DEF(iftypeclause);
AST_NODE(TK_IFTYPE_CLAUSE);
SCOPE();
SKIP(NULL, TK_ELSEIF);
ANNOTATE(annotations);
RULE("type", type);
SKIP(NULL, TK_SUBTYPE);
RULE("type", type);
SKIP(NULL, TK_THEN);
RULE("then value", seq);
DONE();

// ELSEIF [annotations] iftypeclause [elseiftype | (ELSE seq)]
DEF(elseiftype);
AST_NODE(TK_IFTYPE);
SKIP(NULL, TK_ELSEIF);
ANNOTATE(annotations);
SCOPE();
RULE("iftype clause", iftypeclause);
OPT RULE("else clause", elseiftype, elseclause);
DONE();

// IFTYPE [annotations] type <: type THEN seq [elseiftype | (ELSE seq)] END
// IFTYPE [annotations] iftypeclause [elseiftype | (ELSE seq)] END
DEF(iftype);
PRINT_INLINE();
TOKEN(NULL, TK_IFTYPE);
ANNOTATE(annotations);
SCOPE();
RULE("type", type);
SKIP(NULL, TK_SUBTYPE);
RULE("type", type);
SKIP(NULL, TK_THEN);
RULE("then value", seq);
ANNOTATE(annotations);
RULE("iftype clause", iftypeclause);
OPT RULE("else clause", elseiftype, elseclause);
TERMINATE("iftype expression", TK_END);
DONE();
Expand Down
1 change: 1 addition & 0 deletions src/libponyc/ast/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ typedef enum token_id
TK_IF,
TK_IFDEF,
TK_IFTYPE,
TK_IFTYPE_CLAUSE,
TK_THEN,
TK_ELSE,
TK_ELSEIF,
Expand Down
3 changes: 2 additions & 1 deletion src/libponyc/codegen/gencontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ LLVMValueRef gen_if(compile_t* c, ast_t* ast)

LLVMValueRef gen_iftype(compile_t* c, ast_t* ast)
{
AST_GET_CHILDREN(ast, subtype, supertype, left, right);
AST_GET_CHILDREN(ast, left_clause, right);
AST_GET_CHILDREN(left_clause, subtype, supertype, left);

if(is_subtype_constraint(subtype, supertype, NULL, c->opt))
return gen_expr(c, left);
Expand Down
3 changes: 2 additions & 1 deletion src/libponyc/expr/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ bool expr_if(pass_opt_t* opt, ast_t* ast)
bool expr_iftype(pass_opt_t* opt, ast_t* ast)
{
pony_assert(ast_id(ast) == TK_IFTYPE);
AST_GET_CHILDREN(ast, sub, super, left, right);
AST_GET_CHILDREN(ast, left_control, right);
AST_GET_CHILDREN(left_control, sub, super, left);

ast_t* type = NULL;

Expand Down
8 changes: 5 additions & 3 deletions src/libponyc/pass/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ bool is_result_needed(ast_t* ast)

return is_result_needed(parent);

case TK_IFTYPE:
// Sub/supertype not needed, body/else needed only if parent needed.
case TK_IFTYPE_CLAUSE:
// Sub/supertype not needed, body needed only if parent needed.
if((ast_child(parent) == ast) || (ast_childidx(parent, 1) == ast))
return false;

Expand All @@ -78,6 +78,7 @@ bool is_result_needed(ast_t* ast)
return is_result_needed(parent);

case TK_CASES:
case TK_IFTYPE:
case TK_TRY:
case TK_TRY_NO_CHECK:
case TK_RECOVER:
Expand Down Expand Up @@ -135,7 +136,7 @@ bool is_method_result(typecheck_t* t, ast_t* ast)
return false;
break;

case TK_IFTYPE:
case TK_IFTYPE_CLAUSE:
// The subtype and the supertype are not the result.
if((ast_child(parent) == ast) || (ast_childidx(parent, 1) == ast))
return false;
Expand All @@ -154,6 +155,7 @@ bool is_method_result(typecheck_t* t, ast_t* ast)
break;

case TK_CASES:
case TK_IFTYPE:
case TK_RECOVER:
// These can be results.
break;
Expand Down
4 changes: 3 additions & 1 deletion src/libponyc/pass/refer.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,9 @@ static bool refer_iftype(pass_opt_t* opt, ast_t* ast)
{
(void)opt;
pony_assert(ast_id(ast) == TK_IFTYPE);
AST_GET_CHILDREN(ast, sub, super, left, right);

AST_GET_CHILDREN(ast, left_clause, right);
AST_GET_CHILDREN(left_clause, sub, super, left);

size_t branch_count = 0;

Expand Down
19 changes: 10 additions & 9 deletions src/libponyc/pass/scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,25 +199,26 @@ static ast_t* make_iftype_typeparam(pass_opt_t* opt, ast_t* subtype,
return typeparam;
}

static ast_result_t scope_iftype(pass_opt_t* opt, ast_t* ast)
static ast_result_t scope_iftype_clause(pass_opt_t* opt, ast_t* ast)
{
AST_GET_CHILDREN(ast, subtype, supertype, then_clause);
pony_assert(ast_id(ast) == TK_IFTYPE_CLAUSE);

AST_GET_CHILDREN(ast, subtype, supertype, body);

ast_t* typeparams = ast_from(ast, TK_TYPEPARAMS);

switch(ast_id(subtype))
{
case TK_NOMINAL:
{
ast_t* typeparam = make_iftype_typeparam(opt, subtype, supertype,
then_clause);
ast_t* typeparam = make_iftype_typeparam(opt, subtype, supertype, body);
if(typeparam == NULL)
{
ast_free_unattached(typeparams);
return AST_ERROR;
}

if(!set_scope(opt, then_clause, ast_child(typeparam), typeparam, true))
if(!set_scope(opt, body, ast_child(typeparam), typeparam, true))
{
ast_free_unattached(typeparams);
return AST_ERROR;
Expand Down Expand Up @@ -252,14 +253,14 @@ static ast_result_t scope_iftype(pass_opt_t* opt, ast_t* ast)
while(sub_child != NULL)
{
ast_t* typeparam = make_iftype_typeparam(opt, sub_child, super_child,
then_clause);
body);
if(typeparam == NULL)
{
ast_free_unattached(typeparams);
return AST_ERROR;
}

if(!set_scope(opt, then_clause, ast_child(typeparam), typeparam, true))
if(!set_scope(opt, body, ast_child(typeparam), typeparam, true))
{
ast_free_unattached(typeparams);
return AST_ERROR;
Expand Down Expand Up @@ -322,8 +323,8 @@ ast_result_t pass_scope(ast_t** astp, pass_opt_t* options)
ast_setdata(ast, ast);
break;

case TK_IFTYPE:
return scope_iftype(options, ast);
case TK_IFTYPE_CLAUSE:
return scope_iftype_clause(options, ast);

default: {}
}
Expand Down
2 changes: 1 addition & 1 deletion src/libponyc/pass/sugar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@ ast_result_t pass_sugar(ast_t** astp, pass_opt_t* options)
case TK_IF:
case TK_WHILE:
case TK_REPEAT: return sugar_else(ast, 2);
case TK_IFTYPE: return sugar_else(ast, 3);
case TK_IFTYPE: return sugar_else(ast, 1);
case TK_TRY: return sugar_try(ast);
case TK_FOR: return sugar_for(options, astp);
case TK_WITH: return sugar_with(options, astp);
Expand Down
3 changes: 2 additions & 1 deletion src/libponyc/reach/reach.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,8 @@ static void reachable_expr(reach_t* r, ast_t* ast, pass_opt_t* opt)

case TK_IFTYPE:
{
AST_GET_CHILDREN(ast, sub, super, left, right);
AST_GET_CHILDREN(ast, left_clause, right);
AST_GET_CHILDREN(left_clause, sub, super, left);

ast_t* type = ast_type(ast);

Expand Down

0 comments on commit 327e99b

Please sign in to comment.