Attach protocolrefs to class types.

The protocolrefs (as protocollist_t) are attached to the type as a
qualifier.
This commit is contained in:
Bill Currie 2012-12-18 20:45:48 +09:00
parent 45c753f639
commit f181772a76
5 changed files with 74 additions and 8 deletions

View file

@ -102,9 +102,9 @@ extern class_type_t *current_class;
extern int obj_initialized;
struct dstring_s;
struct expr_s;
struct method_s;
struct protocol_s;
struct symbol_s;
class_t *extract_class (class_type_t *class_type);
@ -147,7 +147,8 @@ void protocol_add_protocols (protocol_t *protocol, protocollist_t *protocols);
struct def_s *protocol_def (protocol_t *protocol);
protocollist_t *new_protocol_list (void);
protocollist_t *add_protocol (protocollist_t *protocollist, const char *name);
int compare_protocols (protocollist_t *protos1, protocollist_t *protos2);
void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist);
struct def_s *emit_protocol (protocol_t *protocol);
struct def_s *emit_protocol_list (protocollist_t *protocols, const char *name);

View file

@ -75,6 +75,7 @@ typedef struct type_s {
struct type_s *next;
int freeable;
int allocated;
struct protocollist_s *protos;
const char *encoding; ///< Objective-QC encoding
struct def_s *type_def; ///< offset of qfo encodoing
} type_t;
@ -154,6 +155,7 @@ int is_float (const type_t *type);
int is_scalar (const type_t *type);
int is_math (const type_t *type);
int is_struct (const type_t *type);
int is_id (const type_t *type);
int is_class (const type_t *type);
int is_array (const type_t *type);
int type_assignable (const type_t *dst, const type_t *src);

View file

@ -1214,6 +1214,43 @@ add_protocol (protocollist_t *protocollist, const char *name)
return protocollist;
}
static int
procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto)
{
int i;
for (i = 0; i < protocollist->count; i++)
if (protocollist->list[i] == proto)
return 1;
return 0;
}
int
compare_protocols (protocollist_t *protos1, protocollist_t *protos2)
{
int i;
if (protos2 == protos2)
return 1;
if (!protos1 || !protos2)
return 0;
if (protos1->count != protos2->count)
return 0;
for (i = 0; i < protos1->count; i++)
if (!procollist_find_protocol (protos2, protos1->list[i]))
return 0;
return 1;
}
void
print_protocollist (dstring_t *dstr, protocollist_t *protocollist)
{
int i;
dstring_appendstr (dstr, "<");
for (i = 0; i < protocollist->count; i++)
dasprintf (dstr, "%s%s", i ? "," : "", protocollist->list[i]->name);
dstring_appendstr (dstr, ">");
}
def_t *
emit_protocol (protocol_t *protocol)
{

View file

@ -464,11 +464,23 @@ type_specifier
}
| OBJECT protocolrefs
{
$$ = make_spec (&type_id, 0, 0, 0);
if ($2) {
type_t type = *type_id.t.fldptr.type;
type.protos = $2;
$$ = make_spec (pointer_type (&type), 0, 0, 0);
} else {
$$ = make_spec (&type_id, 0, 0, 0);
}
}
| CLASS_NAME protocolrefs
{
$$ = make_spec ($1->type, 0, 0, 0);
if ($2) {
type_t type = *$1->type;
type.protos = $2;
$$ = make_spec (find_type (&type), 0, 0, 0);
} else {
$$ = make_spec ($1->type, 0, 0, 0);
}
}
// NOTE: fields don't parse the way they should. This is not a problem
// for basic types, but functions need special treatment

View file

@ -237,7 +237,7 @@ types_same (type_t *a, type_t *b)
case ev_pointer:
if (a->t.fldptr.type != b->t.fldptr.type)
return 0;
return 1;
return compare_protocols (a->protos, b->protos);
case ev_func:
if (a->t.func.type != b->t.func.type
|| a->t.func.num_params != b->t.func.num_params)
@ -443,8 +443,10 @@ print_type_str (dstring_t *str, const type_t *type)
}
break;
case ev_pointer:
if (type == &type_id) {
if (is_id (type)) {
dasprintf (str, "id");
if (type->t.fldptr.type->protos)
print_protocollist (str, type->t.fldptr.type->protos);
break;
}
if (type == &type_SEL) {
@ -692,6 +694,18 @@ is_struct (const type_t *type)
return 0;
}
int
is_id (const type_t *type)
{
if (type == &type_id)
return 1;
// type may be a qualified id
if (type->type == ev_pointer
&& type->t.fldptr.type == type_id.t.fldptr.type)
return 1;
return 0;
}
int
is_class (const type_t *type)
{
@ -720,11 +734,11 @@ type_assignable (const type_t *dst, const type_t *src)
if (dst->type == ev_field && src->type == ev_field)
return 1;
// id = any class pointer
if (dst == &type_id && src->type == ev_pointer
if (is_id (dst) && src->type == ev_pointer
&& (is_class (src->t.fldptr.type) || src == &type_Class))
return 1;
// any class pointer = id
if (src == &type_id && dst->type == ev_pointer
if (is_id (src) && dst->type == ev_pointer
&& (is_class (dst->t.fldptr.type) || dst == &type_Class))
return 1;
// pointer = array