// Process the given provides type static bool flatten_provided_type(pass_opt_t* opt, ast_t* provides_type, ast_t* error_at, ast_t* list_parent, ast_t** list_end) { pony_assert(error_at != NULL); pony_assert(provides_type != NULL); pony_assert(list_parent != NULL); pony_assert(list_end != NULL); switch(ast_id(provides_type)) { case TK_PROVIDES: case TK_ISECTTYPE: // Flatten all children for(ast_t* p = ast_child(provides_type); p != NULL; p = ast_sibling(p)) { if(!flatten_provided_type(opt, p, error_at, list_parent, list_end)) return false; } return true; case TK_NOMINAL: { // Check type is a trait or interface ast_t* def = (ast_t*)ast_data(provides_type); pony_assert(def != NULL); if(ast_id(def) != TK_TRAIT && ast_id(def) != TK_INTERFACE) { ast_error(opt->check.errors, error_at, "can only provide traits and interfaces"); ast_error_continue(opt->check.errors, provides_type, "invalid type here"); return false; } // Add type to new provides list ast_list_append(list_parent, list_end, provides_type); ast_setdata(*list_end, ast_data(provides_type)); return true; } default: ast_error(opt->check.errors, error_at, "provides type may only be an intersect of traits and interfaces"); ast_error_continue(opt->check.errors, provides_type, "invalid type here"); return false; } }
// Flatten a provides type into a list, checking all types are traits or // interfaces static ast_result_t flatten_provides_list(ast_t* provider, int index) { assert(provider != NULL); ast_t* provides = ast_childidx(provider, index); ast_t* list = ast_from(provides, TK_PROVIDES); ast_t* list_end = NULL; if(ast_id(provides) != TK_NONE && !flatten_provided_type(provides, provider, list, &list_end)) { ast_free(list); return AST_ERROR; } ast_replace(&provides, list); return AST_OK; }