mc_message _self_response_to_h(const mo obj, const char* methodname, unsigned hashval) { //we will return a struct mc_hashitem* res; mc_message tmpmsg = {nil, nil}; if(obj == nil){ error_log("_self_response_to(obj) obj is nil. return {nil, nil}\n"); return tmpmsg; } if(obj->isa == nil){ error_log("_self_response_to(obj) obj->isa is nil. return {nil, nil}\n"); return tmpmsg; } if((res=get_item_byhash(&(obj->isa->table), hashval, methodname)) != nil){ tmpmsg.object = obj; tmpmsg.addr = res->value; runtime_log("return a message[%s/%s]\n", nameof(tmpmsg.object), methodname); return tmpmsg; }else{ runtime_log("self_response_to class[%s] can not response to method[%s]\n", nameof(obj), methodname); return tmpmsg; } }
mc_message _self_response_to_h(const mo obj, const char* methodname, MCHash hashval) { //we will return a struct mc_hashitem* res = mull; mc_message tmpmsg = {mull, mull}; if(obj == mull){ //no need to warning user return tmpmsg; } if(obj->isa == mull){ error_log("_self_response_to(obj, '%s') obj->isa is mull. return {mull, mull}\n", methodname); return tmpmsg; } if((res=get_item_byhash(obj->isa->table, hashval, methodname)) != mull){ tmpmsg.object = obj; tmpmsg.address = res->value.mcfuncptr; runtime_log("return a message[%s/%s]\n", nameof(obj), methodname); return tmpmsg; }else{ if (obj->nextResponder != mull) { return _self_response_to_h(obj->nextResponder, methodname, hashval); }else{ runtime_log("self_response_to class[%s] can not response to method[%s]\n", nameof(obj), methodname); if (MC_STRICT_MODE == 1) { exit(-1); }else{ return tmpmsg; } } } }
mc_hashitem* get_item_bykey(mc_hashtable* const table_p, const char* key) { if (table_p == null) { error_log("get_item_bykey(table_p) table_p is nil return nil\n"); return null; } //try get index return get_item_byhash(table_p, hash(key), key); }
MCInline mc_class* findclass(const char* name) { //create a class hashtable if (mc_global_classtable == null) mc_global_classtable = new_table(MCHashTableLevel1); //cache // mc_hashitem* cache = mc_global_classtable->cache; // if (cache && cache->key == name) { // return (mc_class*)(cache->value.mcvoidptr); // } mc_hashitem* item = get_item_byhash(mc_global_classtable, hash(name), name); if (item == null) return null; else runtime_log("findClass item key:%s, value:%p\n", item->key, item->value.mcvoidptr); return (mc_class*)(item->value.mcvoidptr); }
mc_message _response_to_h(const mo obj, const char* methodname, unsigned hashval, int strict) { mc_object* obj_iterator = obj; mc_object* obj_first_hit = nil; mc_hashitem* met_first_hit = nil; mc_hashitem* met_item = nil; int hit_count = 0; int iter_count = 0; //int max_iter = get_tablesize(5); int max_iter = 10000; mc_message tmpmsg = {nil, nil}; if(obj == nil || obj->isa == nil){ error_log("_response_to(obj) obj is nil or obj->isa is nil. return {nil, nil}\n"); return tmpmsg; } for(obj_iterator = obj; obj_iterator!= nil; obj_iterator = obj_iterator->super){ if(iter_count++ > max_iter){ error_log("iter_count>max but class still can not response to method\n"); break; } if((met_item=get_item_byhash(&(obj_iterator->isa->table), hashval, methodname)) != nil) { runtime_log("hit a method [%s/%d] to match [%s]\n", met_item->key, met_item->index, methodname); hit_count++; tmpmsg.object = obj_iterator; tmpmsg.addr = met_item->value; if(obj_first_hit==nil)obj_first_hit = obj_iterator; if(met_first_hit==nil)met_first_hit = met_item; //for the method key have conflicted with some super class in inherit tree if(hit_count>1){ if(hit_count==2){ //to support the "overide" feature of oop if(mc_compare_key(met_first_hit->key, methodname) == 0){ tmpmsg.object = obj_first_hit; tmpmsg.addr = met_first_hit->value; runtime_log("[first hit]return a message[%s/%s(%p/%p)]\n", tmpmsg.object->isa->item->key, methodname, tmpmsg.object, tmpmsg.addr); return tmpmsg;} } if(mc_compare_key(met_item->key, methodname) == 0){ tmpmsg.object = obj_iterator; runtime_log("[string equal]return a message[%s/%s]\n", tmpmsg.object->isa->item->key, methodname); return tmpmsg;} } } } if(hit_count==1) runtime_log("return a message[%s/%s]\n", nameof(tmpmsg.object), methodname); else if(hit_count==0) { if (strict!=2) error_log("class[%s] can not response to method[%s]\n", nameof(obj), methodname); if (strict==1) exit(1); } else { if (strict!=2) error_log("hit_count>1 but class still can not response to method\n"); if (strict==1) exit(1); } return tmpmsg; }