mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
get object pointer assignmets working and some static typing as well
This commit is contained in:
parent
73f4cb4c03
commit
779174cb33
10 changed files with 173 additions and 53 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -257,6 +257,7 @@ type
|
|||
|
||||
type_name
|
||||
: TYPE { $$ = $1; }
|
||||
| class_name { $$ = $1->type; }
|
||||
;
|
||||
|
||||
function_decl
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue