// Process the provides list for the given entity. // Stage 1. static bool provides_list(ast_t* entity, pass_opt_t* options) { assert(entity != NULL); ast_t* provides = ast_childidx(entity, 3); assert(provides != NULL); bool r = true; for(ast_t* p = ast_child(provides); p != NULL; p = ast_sibling(p)) { if(ast_id(p) != TK_NOMINAL) { ast_error(p, "provides list may only contain traits and interfaces"); return false; } // Check type is a trait or interface ast_t* def = (ast_t*)ast_data(p); assert(def != NULL); if(ast_id(def) != TK_TRAIT && ast_id(def) != TK_INTERFACE) { ast_error(p, "can only provide traits and interfaces"); return false; } // Now process provided type if(!trait_entity(def, options)) r = false; } return r; }
ast_result_t pass_traits(ast_t** astp, pass_opt_t* options) { ast_t* ast = *astp; switch(ast_id(ast)) { case TK_PRIMITIVE: case TK_CLASS: case TK_ACTOR: case TK_INTERFACE: case TK_TRAIT: if(!trait_entity(ast, options)) return AST_ERROR; break; case TK_LET: case TK_VAR: local_types(ast); break; default: break; } return AST_OK; }
// Process the methods provided to the given entity from all traits in its // provides list. static bool provided_methods(ast_t* entity, pass_opt_t* opt) { assert(entity != NULL); ast_t* provides = ast_childidx(entity, 3); bool r = true; // Run through our provides list for(ast_t* trait_ref = ast_child(provides); trait_ref != NULL; trait_ref = ast_sibling(trait_ref)) { ast_t* trait = (ast_t*)ast_data(trait_ref); assert(trait != NULL); if(!trait_entity(trait, opt)) return false; ast_t* members = ast_childidx(trait, 4); // Run through the methods of each provided type. for(ast_t* method = ast_child(members); method != NULL; method = ast_sibling(method)) { assert(is_method(method)); ast_t* reified = reify_provides_type(method, trait_ref, opt); if(reified == NULL) { // Reification error, already reported. r = false; } else { if(!add_method_from_trait(entity, reified, trait_ref, opt)) r = false; ast_free_unattached(reified); } } } return r; }
// Process the methods required for delegation to all the fields in the given // entity. static bool delegated_methods(ast_t* entity, pass_opt_t* opt) { assert(entity != NULL); bool r = true; // Check all fields. for(ast_t* field = ast_child(ast_childidx(entity, 4)); field != NULL; field = ast_sibling(field)) { if(is_field(field)) { AST_GET_CHILDREN(field, id, f_type, value, delegates); // Check all delegates for field. for(ast_t* trait_ref = ast_child(delegates); trait_ref != NULL; trait_ref = ast_sibling(trait_ref)) { ast_t* trait = (ast_t*)ast_data(trait_ref); assert(trait != NULL); if(!trait_entity(trait, opt)) return false; // Run through the methods of each delegated type. for(ast_t* method = ast_child(ast_childidx(trait, 4)); method != NULL; method = ast_sibling(method)) { if(!delegated_method(entity, method, field, trait_ref, opt)) r = false; } } } } return r; }