get object pointer assignmets working and some static typing as well

This commit is contained in:
Bill Currie 2002-05-16 20:20:23 +00:00
parent 73f4cb4c03
commit 779174cb33
10 changed files with 173 additions and 53 deletions

View file

@ -41,8 +41,12 @@ typedef struct class_s {
struct methodlist_s *methods;
struct protocollist_s *protocols;
struct def_s *def;
struct type_s *type;
} class_t;
extern class_t class_id;
struct expr_s;
struct method_s;
struct protocol_s;
struct type_s;
@ -54,6 +58,7 @@ void class_add_protocol (class_t *class, struct protocol_s *protocol);
void class_check_ivars (class_t *class, struct type_s *ivars);
void class_finish (class_t *class);
struct method_s *class_find_method (class_t *class, struct method_s *method);
struct method_s *class_message_response (class_t *class, struct expr_s *sel);
struct def_s *class_def (class_t *class);
class_t *get_category (const char *class_name, const char *category_name,
int create);

View file

@ -41,6 +41,8 @@ typedef struct method_s {
param_t *params;
type_t *type;
def_t *def;
char *name;
char *types;
} method_t;
typedef struct methodlist_s {
@ -70,7 +72,7 @@ int method_compare (method_t *m1, method_t *m2);
keywordarg_t *new_keywordarg (const char *selector, struct expr_s *expr);
struct expr_s *send_message (void);
struct expr_s *send_message (int super);
void selector_name (struct dstring_s *sel_id, keywordarg_t *selector);
void selector_types (struct dstring_s *sel_types, keywordarg_t *selector);

View file

@ -294,6 +294,7 @@ typedef struct type_s
struct hashtab_s *struct_fields;
struct struct_field_s *struct_head;
struct struct_field_s **struct_tail;
struct class_s *class; // for ev_class
} type_t;
typedef struct statref_s {

View file

@ -66,6 +66,7 @@ type_t *get_typedef (const char *name);
type_t *pointer_type (type_t *aux);
void print_type (type_t *type);
void encode_type (struct dstring_s *encodking, type_t *type);
int type_assignable (type_t *dst, type_t *src);
int type_size (type_t *type);
void init_types (void);

View file

@ -46,6 +46,8 @@ static hashtab_t *class_hash;
static hashtab_t *category_hash;
static hashtab_t *protocol_hash;
class_t class_id = {1, "id", 0, 0, 0, 0, 0, 0, &type_id};
static const char *
class_get_key (void *class, void *unused)
{
@ -62,6 +64,7 @@ class_t *
get_class (const char *name, int create)
{
class_t *c;
type_t new;
if (!class_hash)
class_hash = Hash_NewTable (1021, class_get_key, 0, 0);
@ -73,6 +76,9 @@ get_class (const char *name, int create)
c = calloc (sizeof (class_t), 1);
c->class_name = name;
new = *type_Class.aux_type;
new.class = c;
c->type = pointer_type (find_type (&new));
if (name)
Hash_Add (class_hash, c);
return c;
@ -183,6 +189,31 @@ class_find_method (class_t *class, method_t *method)
return method;
}
method_t *
class_message_response (class_t *class, expr_t *sel)
{
pr_sel_t *selector;
char *sel_name;
method_t *m;
class_t *c = class;
if (sel->type != ex_pointer && sel->e.pointer.type != type_SEL.aux_type) {
error (sel, "not a selector");
return 0;
}
selector = &G_STRUCT (pr_sel_t, sel->e.pointer.val);
sel_name = strings + selector->sel_id;
while (c) {
for (m = c->methods->head; m; m = m->next) {
if (strcmp (sel_name, m->name) == 0)
return m;
}
c = c->super_class;
}
warning (sel, "%s does not respond to %s", class->class_name, sel_name);
return 0;
}
static unsigned long
category_get_hash (void *_c, void *unused)
{
@ -236,7 +267,7 @@ get_category (const char *class_name, const char *category_name, int create)
def_t *
class_def (class_t *class)
{
return PR_GetDef (&type_Class, class->class_name, 0, &numpr_globals);
return PR_GetDef (class->type, class->class_name, 0, &numpr_globals);
}
protocol_t *

View file

@ -353,6 +353,14 @@ new_label_name (void)
return lname;
}
expr_t *
new_error_expr ()
{
expr_t *e = new_expr ();
e->type = ex_error;
return e;
}
expr_t *
new_label_expr (void)
{
@ -1521,7 +1529,7 @@ function_expr (expr_t *e1, expr_t *e2)
t = ftype->parm_types[i];
e->type = expr_types[t->type];
}
if (t != ftype->parm_types[i]) {
if (!type_assignable (ftype->parm_types[i], t)) {
print_type (ftype->parm_types[i]); puts("");
print_type (t); puts("");
err = error (e, "type mismatch for parameter %d of %s",
@ -1831,14 +1839,12 @@ assign_expr (expr_t *e1, expr_t *e2)
e2->rvalue = 1;
if (t1 != t2) {
if (!type_assignable (t1, t2)) {
if (!options.traditional || t1->type != ev_func || t2->type != ev_func)
return type_mismatch (e1, e2, op);
warning (e1, "assignment between disparate function types");
type = t1;
} else {
type = t1;
}
type = t1;
if (is_indirect (e1) && is_indirect (e2)) {
expr_t *temp = new_temp_def_expr (t1);
@ -1976,8 +1982,26 @@ message_expr (expr_t *receiver, keywordarg_t *message)
{
expr_t *args = 0, **a = &args;
expr_t *selector = selector_expr (message);
expr_t *call;
keywordarg_t *m;
int super = 0;
type_t *rec_type;
class_t *class;
method_t *method;
if (receiver->type == ex_name
&& strcmp (receiver->e.string_val, "super") == 0) {
super = 1;
}
rec_type = get_type (receiver);
if (rec_type->type != ev_pointer || rec_type->aux_type->type != ev_class)
return error (receiver, "not a class object");
class = rec_type->aux_type->class;
if (rec_type != &type_id) {
method = class_message_response (class, selector);
if (method)
rec_type = method->type->aux_type;
}
for (m = message; m; m = m->next) {
*a = m->expr;
while ((*a))
@ -1986,5 +2010,7 @@ message_expr (expr_t *receiver, keywordarg_t *message)
*a = selector;
a = &(*a)->next;
*a = receiver;
return function_expr (send_message (), args);
call = function_expr (send_message (super), args);
call->e.block.result->e.def->type = rec_type;
return call;
}

View file

@ -44,6 +44,8 @@ static const char rcsid[] =
static def_t *send_message_def;
static function_t *send_message_func;
static def_t *send_message_super_def;
static function_t *send_message_super_func;
method_t *
new_method (type_t *ret_type, param_t *selector, param_t *opt_parms)
@ -51,6 +53,8 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_parms)
method_t *meth = malloc (sizeof (method_t));
param_t *cmd = new_param (0, &type_pointer, "_cmd");
param_t *self = new_param (0, &type_id, "self");
dstring_t *name = dstring_newstr ();
dstring_t *types = dstring_newstr ();
opt_parms = reverse_params (opt_parms);
selector = _reverse_params (selector, opt_parms);
@ -62,6 +66,14 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_parms)
meth->selector = selector;
meth->params = self;
meth->type = parse_params (ret_type, meth->params);
selector_name (name, (keywordarg_t *)selector);
selector_types (types, (keywordarg_t *)selector);
meth->name = name->str;
meth->types = types->str;
free (name);
free (types);
//print_type (meth->type); puts ("");
meth->def = 0;
return meth;
@ -83,24 +95,21 @@ def_t *
method_def (class_t *class, method_t *method)
{
dstring_t *str = dstring_newstr ();
dstring_t *sel = dstring_newstr ();
def_t *def;
char *s;
selector_name (sel, (keywordarg_t *)method->selector);
dsprintf (str, "_%c_%s_%s_%s",
method->instance ? 'i' : 'c',
class->class_name,
class->category_name ? class->category_name : "",
sel->str);
method->name);
for (s = str->str; *s; s++)
if (*s == ':')
*s = '_';
//printf ("%s\n", str->str);
//printf ("%s %s %s\n", method->name, method->types, str->str);
// FIXME need a file scope
def = PR_GetDef (method->type, str->str, 0, &numpr_globals);
dstring_delete (str);
dstring_delete (sel);
return def;
}
@ -129,24 +138,10 @@ copy_methods (methodlist_t *dst, methodlist_t *src)
int
method_compare (method_t *m1, method_t *m2)
{
dstring_t *s1 = dstring_newstr ();
dstring_t *s2 = dstring_newstr ();
dstring_t *t1 = dstring_newstr ();
dstring_t *t2 = dstring_newstr ();
int res;
selector_name (s1, (keywordarg_t *)m1->selector);
selector_name (s2, (keywordarg_t *)m2->selector);
selector_types (t1, (keywordarg_t *)m1->selector);
selector_types (t2, (keywordarg_t *)m2->selector);
res = strcmp (s1->str, s2->str) == 0
&& strcmp (t1->str, t2->str) == 0;
dstring_delete (s1);
dstring_delete (s2);
dstring_delete (t1);
dstring_delete (t2);
res = strcmp (m1->name, m2->name) == 0
&& strcmp (m1->types, m2->types) == 0;
return res;
}
@ -162,23 +157,32 @@ new_keywordarg (const char *selector, struct expr_s *expr)
return k;
}
static void
make_message_def (const char *name, def_t **def, function_t **func)
{
*def = PR_GetDef (&type_IMP, "obj_msgSend",
0, &numpr_globals);
*func = new_function ();
(*func)->builtin = 0;
(*func)->def = *def;
build_function (*func);
finish_function (*func);
}
expr_t *
send_message (void)
send_message (int super)
{
expr_t *e;
if (!send_message_def) {
send_message_def = PR_GetDef (&type_IMP, "obj_msgSend",
0, &numpr_globals);
send_message_func = new_function ();
send_message_func->builtin = 0;
send_message_func->def = send_message_def;
build_function (send_message_func);
finish_function (send_message_func);
make_message_def ("obj_msgSend",
&send_message_def, &send_message_func);
make_message_def ("obj_msgSend_super",
&send_message_super_def, &send_message_super_func);
}
e = new_expr ();
e->type = ex_def;
e->e.def = send_message_def;
e->e.def = super ? send_message_super_def : send_message_def;
return e;
}
@ -213,8 +217,8 @@ sel_def_get_hash (void *_sel_def, void *unused)
sel_def_t *sel_def = (sel_def_t*)_sel_def;
unsigned long hash;
hash = Hash_String (G_STRING (sel_def->sel_id))
^ Hash_String (G_STRING (sel_def->sel_types));
hash = Hash_String (strings + sel_def->sel_id)
^ Hash_String (strings + sel_def->sel_types);
return hash;
}
@ -225,10 +229,10 @@ sel_def_compare (void *_sd1, void *_sd2, void *unused)
sel_def_t *sd2 = (sel_def_t*)_sd2;
int cmp;
cmp = strcmp (G_STRING (sd1->sel_id), G_STRING (sd2->sel_id)) == 0;
cmp = strcmp (strings + sd1->sel_id, strings + sd2->sel_id) == 0;
if (cmp)
cmp = strcmp (G_STRING (sd1->sel_types),
G_STRING (sd2->sel_types)) == 0;
cmp = strcmp (strings + sd1->sel_types,
strings + sd2->sel_types) == 0;
return cmp;
}
@ -267,7 +271,6 @@ emit_methods (methodlist_t *_methods, const char *name, int instance)
def_t *methods_def;
pr_method_list_t *methods;
type_t *method_list;
dstring_t *tmp = dstring_newstr ();
for (count = 0, method = _methods->head; method; method = method->next)
if (!method->instance == !instance)
@ -285,14 +288,12 @@ emit_methods (methodlist_t *_methods, const char *name, int instance)
for (i = 0, method = _methods->head; method; method = method->next) {
if (!method->instance != !instance)
continue;
selector_name (tmp, (keywordarg_t *)method->selector);
methods->method_list[i].method_name.sel_id = ReuseString (tmp->str);
selector_name (tmp, (keywordarg_t *)method->selector);
methods->method_list[i].method_name.sel_types = ReuseString (tmp->str);
methods->method_list[i].method_name.sel_id = ReuseString (method->name);
methods->method_list[i].method_name.sel_types =
ReuseString (method->types);
methods->method_list[i].method_types =
methods->method_list[i].method_name.sel_types;
methods->method_list[i].method_imp = method->def->ofs;
}
dstring_delete (tmp);
return methods_def->ofs;
}

View file

@ -257,6 +257,7 @@ type
type_name
: TYPE { $$ = $1; }
| class_name { $$ = $1->type; }
;
function_decl

View file

@ -176,15 +176,21 @@ emit_struct(type_t *strct, const char *name)
pr_ivar_list_t *ivars;
type_t *ivar_list;
dstring_t *encoding = dstring_newstr ();
dstring_t *ivars_name = dstring_newstr ();
if (!strct)
return 0;
for (count = 0, field = strct->struct_head; field; field = field->next)
count++;
ivar_list = new_struct (0);
new_struct_field (ivar_list, &type_integer, "ivar_count", vis_public);
for (i = 0; i < count; i++)
new_struct_field (ivar_list, type_ivar, 0, vis_public);
ivars_def = PR_GetDef (ivar_list, va ("_OBJ_INSTANCE_VARIABLES_%s", name),
0, &numpr_globals);
dsprintf (ivars_name, "_OBJ_INSTANCE_VARIABLES_%s", name);
ivars_def = PR_GetDef (ivar_list, ivars_name->str, 0, 0);
if (ivars_def)
goto done;
ivars_def = PR_GetDef (ivar_list, ivars_name->str, 0, &numpr_globals);
ivars = &G_STRUCT (pr_ivar_list_t, ivars_def->ofs);
ivars->ivar_count = count;
for (i = 0, field = strct->struct_head; field; i++, field = field->next) {
@ -194,7 +200,9 @@ emit_struct(type_t *strct, const char *name)
ivars->ivar_list[i].ivar_offset = field->offset;
dstring_clearstr (encoding);
}
done:
dstring_delete (encoding);
dstring_delete (ivars_name);
return ivars_def->ofs;
}

View file

@ -32,11 +32,13 @@ static const char rcsid[] =
#include <stdlib.h>
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/sys.h"
#include "QF/dstring.h"
#include "QF/va.h"
#include "qfcc.h"
#include "class.h"
#include "function.h"
#include "struct.h"
#include "type.h"
@ -101,7 +103,8 @@ find_type (type_t *type)
for (check = pr.types; check; check = check->next) {
if (check->type != type->type
|| check->aux_type != type->aux_type
|| check->num_parms != type->num_parms)
|| check->num_parms != type->num_parms
|| check->class != type->class)
continue;
if (check->type != ev_func)
@ -196,6 +199,8 @@ array_type (type_t *aux, int size)
void
print_type (type_t *type)
{
class_t *class;
if (!type) {
printf (" (null)");
return;
@ -232,6 +237,12 @@ print_type (type_t *type)
else
printf ("[]");
break;
case ev_class:
class = type->class;
printf (" %s %s%s", pr_type_name[type->type],
class->class_name,
class->category_name ? va (" (%s)", class->category_name)
: "");
default:
printf(" %s", pr_type_name[type->type]);
break;
@ -319,6 +330,34 @@ encode_type (dstring_t *encoding, type_t *type)
_encode_type (encoding, type, 0);
}
int
type_assignable (type_t *dst, type_t *src)
{
class_t *dst_class, *src_class;
if (dst == src)
return 1;
if (dst->type != ev_pointer || src->type != ev_pointer)
return 0;
dst = dst->aux_type;
src = src->aux_type;
if (dst->type != ev_class || src->type != ev_class)
return 0;
dst_class = dst->class;
src_class = src->class;
//printf ("%s %s\n", dst_class->class_name, src_class->class_name);
if (!dst_class || dst_class == &class_id)
return 1;
while (dst_class != src_class && src_class) {
src_class = src_class->super_class;
//if (src_class)
// printf ("%s %s\n", dst_class->class_name, src_class->class_name);
}
if (dst_class == src_class)
return 1;
return 0;
}
int
type_size (type_t *type)
{
@ -388,6 +427,7 @@ init_types (void)
chain_type (type_method);
type = type_Class.aux_type = new_struct ("Class");
type->type = ev_class;
new_struct_field (type, &type_Class, "class_pointer", vis_public);
new_struct_field (type, &type_Class, "super_class", vis_public);
new_struct_field (type, &type_string, "name", vis_public);
@ -404,6 +444,7 @@ init_types (void)
chain_type (&type_Class);
type = type_Protocol.aux_type = new_struct ("Protocol");
type->type = ev_class;
new_struct_field (type, &type_Class, "class_pointer", vis_public);
new_struct_field (type, &type_string, "protocol_name", vis_public);
new_struct_field (type, &type_pointer, "protocol_list", vis_public);
@ -412,6 +453,9 @@ init_types (void)
chain_type (&type_Protocol);
type = type_id.aux_type = new_struct ("id");
type->type = ev_class;
type->class = &class_id;
class_id.ivars = type_id.aux_type;
new_struct_field (type, &type_Class, "class_pointer", vis_public);
chain_type (&type_id);