void reach(reachable_types_t* r, uint32_t* next_type_id, ast_t* type, const char* name, ast_t* typeargs) { reachable_method_stack_t* s = NULL; reachable_method(&s, r, next_type_id, type, name, typeargs); handle_stack(s, r, next_type_id); }
static void reachable_fun(reachable_method_stack_t** s, reachable_types_t* r, uint32_t* next_type_id, ast_t* ast) { AST_GET_CHILDREN(ast, receiver, method); ast_t* typeargs = NULL; // Dig through function qualification. switch(ast_id(receiver)) { case TK_NEWREF: case TK_NEWBEREF: case TK_BEREF: case TK_FUNREF: typeargs = method; AST_GET_CHILDREN_NO_DECL(receiver, receiver, method); break; default: {} } ast_t* type = ast_type(receiver); const char* method_name = ast_name(method); reachable_method(s, r, next_type_id, type, method_name, typeargs); }
static void reachable_method(reachable_method_stack_t** s, reachable_types_t* r, uint32_t* next_type_id, ast_t* type, const char* name, ast_t* typeargs) { switch(ast_id(type)) { case TK_NOMINAL: { reachable_type_t* t = add_type(s, r, next_type_id, type); add_method(s, t, name, typeargs); break; } case TK_UNIONTYPE: case TK_ISECTTYPE: { ast_t* child = ast_child(type); while(child != NULL) { ast_t* find = lookup_try(NULL, NULL, child, name); if(find != NULL) reachable_method(s, r, next_type_id, child, name, typeargs); child = ast_sibling(child); } break; } default: assert(0); } }
static void reachable_pattern(reachable_method_stack_t** s, reachable_types_t* r, uint32_t* next_type_id, ast_t* ast) { switch(ast_id(ast)) { case TK_DONTCARE: case TK_NONE: break; case TK_VAR: case TK_LET: { AST_GET_CHILDREN(ast, idseq, type); add_type(s, r, next_type_id, type); break; } case TK_TUPLE: case TK_SEQ: { ast_t* child = ast_child(ast); while(child != NULL) { reachable_pattern(s, r, next_type_id, child); child = ast_sibling(child); } break; } default: { reachable_method(s, r, next_type_id, ast_type(ast), stringtab("eq"), NULL); reachable_expr(s, r, next_type_id, ast); break; } } }
static void add_special(reach_t* r, reach_type_t* t, ast_t* type, const char* special, pass_opt_t* opt) { special = stringtab(special); ast_t* find = lookup_try(NULL, NULL, type, special); if(find != NULL) { switch(ast_id(find)) { case TK_NEW: case TK_FUN: case TK_BE: { reachable_method(r, t->ast, special, NULL, opt); ast_free_unattached(find); break; } default: {} } } }
static void reachable_fun(reach_t* r, ast_t* ast, pass_opt_t* opt) { AST_GET_CHILDREN(ast, receiver, method); ast_t* typeargs = NULL; // Dig through function qualification. switch(ast_id(receiver)) { case TK_NEWREF: case TK_NEWBEREF: case TK_BEREF: case TK_FUNREF: typeargs = method; AST_GET_CHILDREN_NO_DECL(receiver, receiver, method); break; default: {} } ast_t* type = ast_type(receiver); const char* method_name = ast_name(method); reachable_method(r, type, method_name, typeargs, opt); }
static void reachable_pattern(reach_t* r, ast_t* ast, pass_opt_t* opt) { switch(ast_id(ast)) { case TK_DONTCARE: case TK_NONE: break; case TK_MATCH_CAPTURE: { AST_GET_CHILDREN(ast, idseq, type); add_type(r, type, opt); break; } case TK_TUPLE: case TK_SEQ: { ast_t* child = ast_child(ast); while(child != NULL) { reachable_pattern(r, child, opt); child = ast_sibling(child); } break; } default: { reachable_method(r, ast_type(ast), stringtab("eq"), NULL, opt); reachable_expr(r, ast, opt); break; } } }
static void reachable_expr(reachable_method_stack_t** s, reachable_types_t* r, uint32_t* next_type_id, ast_t* ast) { // If this is a method call, mark the method as reachable. switch(ast_id(ast)) { case TK_TRUE: case TK_FALSE: case TK_INT: case TK_FLOAT: case TK_STRING: { ast_t* type = ast_type(ast); if(type != NULL) reachable_method(s, r, next_type_id, type, stringtab("create"), NULL); break; } case TK_TUPLE: { ast_t* type = ast_type(ast); add_type(s, r, next_type_id, type); break; } case TK_CASE: { AST_GET_CHILDREN(ast, pattern, guard, body); reachable_pattern(s, r, next_type_id, pattern); reachable_expr(s, r, next_type_id, guard); reachable_expr(s, r, next_type_id, body); break; } case TK_CALL: reachable_call(s, r, next_type_id, ast); break; case TK_FFICALL: reachable_ffi(s, r, next_type_id, ast); break; case TK_ADDRESS: reachable_addressof(s, r, next_type_id, ast); break; case TK_IF: { AST_GET_CHILDREN(ast, cond, then_clause, else_clause); assert(ast_id(cond) == TK_SEQ); cond = ast_child(cond); if(ast_sibling(cond) == NULL) { if(ast_id(cond) == TK_TRUE) { reachable_expr(s, r, next_type_id, then_clause); return; } else if(ast_id(cond) == TK_FALSE) { reachable_expr(s, r, next_type_id, else_clause); return; } } break; } default: {} } // Traverse all child expressions looking for calls. ast_t* child = ast_child(ast); while(child != NULL) { reachable_expr(s, r, next_type_id, child); child = ast_sibling(child); } }
static void reachable_expr(reach_t* r, ast_t* ast, pass_opt_t* opt) { // If this is a method call, mark the method as reachable. switch(ast_id(ast)) { case TK_TRUE: case TK_FALSE: case TK_INT: case TK_FLOAT: case TK_STRING: { ast_t* type = ast_type(ast); if(type != NULL) reachable_method(r, type, stringtab("create"), NULL, opt); break; } case TK_LET: case TK_VAR: case TK_TUPLE: { ast_t* type = ast_type(ast); add_type(r, type, opt); break; } case TK_CASE: { AST_GET_CHILDREN(ast, pattern, guard, body); reachable_pattern(r, pattern, opt); reachable_expr(r, guard, opt); reachable_expr(r, body, opt); break; } case TK_CALL: reachable_call(r, ast, opt); break; case TK_FFICALL: reachable_ffi(r, ast, opt); break; case TK_ADDRESS: reachable_addressof(r, ast, opt); break; case TK_IF: { AST_GET_CHILDREN(ast, cond, then_clause, else_clause); assert(ast_id(cond) == TK_SEQ); cond = ast_child(cond); ast_t* type = ast_type(ast); if(is_result_needed(ast) && !is_control_type(type)) add_type(r, type, opt); if(ast_sibling(cond) == NULL) { if(ast_id(cond) == TK_TRUE) { reachable_expr(r, then_clause, opt); return; } else if(ast_id(cond) == TK_FALSE) { reachable_expr(r, else_clause, opt); return; } } break; } case TK_MATCH: case TK_WHILE: case TK_REPEAT: case TK_TRY: { ast_t* type = ast_type(ast); if(is_result_needed(ast) && !is_control_type(type)) add_type(r, type, opt); break; } default: {} } // Traverse all child expressions looking for calls. ast_t* child = ast_child(ast); while(child != NULL) { reachable_expr(r, child, opt); child = ast_sibling(child); } }
void reach(reach_t* r, ast_t* type, const char* name, ast_t* typeargs, pass_opt_t* opt) { reachable_method(r, type, name, typeargs, opt); handle_stack(r, opt); }