get [super ...] working correctly

This commit is contained in:
Bill Currie 2003-05-15 05:58:31 +00:00
parent bfaa07c726
commit dedb2fa6bf
12 changed files with 124 additions and 53 deletions

View File

@ -160,4 +160,9 @@ typedef struct pr_module_s {
pointer_t symtab; // pr_symtab_t
} pr_module_t;
typedef struct pr_super_s {
pointer_t self;
pointer_t class;
} pr_super_t;
#endif//__pr_obj_h

View File

@ -283,19 +283,15 @@ obj_msg_lookup (progs_t *pr, pr_id_t *receiver, pr_sel_t *op)
}
static func_t
obj_msg_lookup_super (progs_t *pr, pr_id_t *receiver, pr_sel_t *op)
obj_msg_lookup_super (progs_t *pr, pr_super_t *super, pr_sel_t *op)
{
pr_class_t *class;
pr_class_t *super = 0;
if (!receiver)
if (!super->self)
return 0;
class = &G_STRUCT (pr, pr_class_t, receiver->class_pointer);
if (class->super_class)
super = &G_STRUCT (pr, pr_class_t, class->super_class);
if (!super)
PR_RunError (pr, "%s has no super class",
PR_GetString (pr, class->name));
return obj_find_message (pr, super, op);
class = &G_STRUCT (pr, pr_class_t, super->class);
return obj_find_message (pr, class, op);
}
static void
@ -339,9 +335,10 @@ pr_obj_msg_lookup (progs_t *pr)
static void
pr_obj_msg_lookup_super (progs_t *pr)
{
pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0);
pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1);
R_INT (pr) = obj_msg_lookup_super (pr, receiver, op);
pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0);
pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1);
R_INT (pr) = obj_msg_lookup_super (pr, super, _cmd);
}
static void
@ -450,21 +447,18 @@ pr_obj_msgSend (progs_t *pr)
static void
pr_obj_msgSend_super (progs_t *pr)
{
pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0);
pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0);
pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1);
func_t imp;
if (!self) {
R_INT (pr) = R_INT (pr);
return;
}
if (!_cmd)
PR_RunError (pr, "null selector");
imp = obj_msg_lookup_super (pr, self, _cmd);
if (!imp)
imp = obj_msg_lookup_super (pr, super, _cmd);
if (!imp) {
pr_id_t *self = &G_STRUCT (pr, pr_id_t, super->self);
PR_RunError (pr, "%s does not respond to %s",
PR_GetString (pr, object_get_class_name (pr, self)),
PR_GetString (pr, _cmd->sel_id));
}
P_POINTER (pr, 0) = super->self;
call_function (pr, imp);
}

View File

@ -10,7 +10,7 @@ typedef enum {
@extern void (id object, integer code, string fmt, @va_list args) obj_verror;
//obj_error_handler (objc_error_handler func) obj_set_error_handler = #0;
@extern IMP (id receiver, SEL op) obj_msg_lookup;
@extern IMP (id receiver, SEL op) obj_msg_lookup_super;
@extern IMP (Super class, SEL op) obj_msg_lookup_super;
//retval_t (id receiver, SEL op, @va_list args) obj_msg_sendv;
@extern (void []) (integer size) obj_malloc;
@extern (void []) (integer size) obj_atomic_malloc;

View File

@ -5,9 +5,9 @@ void (id object, integer code, string fmt, ...) obj_error = #0;
void (id object, integer code, string fmt, @va_list args) obj_verror = #0;
//obj_error_handler (objc_error_handler func) obj_set_error_handler = #0;
IMP (id receiver, SEL op) obj_msg_lookup = #0;
IMP (id receiver, SEL op) obj_msg_lookup_super = #0;
IMP (Super class, SEL op) obj_msg_lookup_super = #0;
id (id receiver, SEL op, ...) obj_msgSend = #0;
id (id receiver, SEL op, ...) obj_msgSend_super = #0;
id (Super class, SEL op, ...) obj_msgSend_super = #0;
//retval_t (id receiver, SEL op, @va_list args) obj_msg_sendv = #0;
(void []) (integer size) obj_malloc = #0;
(void []) (integer size) obj_atomic_malloc = #0;

View File

@ -83,6 +83,8 @@ typedef struct {
struct def_s *def;
} ex_pointer_t;
#define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val)
typedef struct expr_s {
struct expr_s *next;
expr_type type;
@ -193,9 +195,11 @@ const char *get_op_string (int op);
extern int lineno_base;
struct keywordarg_s;
struct class_type_s;
expr_t *selector_expr (struct keywordarg_s *selector);
expr_t *protocol_expr (const char *protocol);
expr_t *encode_expr (struct type_s *type);
expr_t *super_expr (struct class_type_s *class_type);
expr_t *message_expr (expr_t *receiver, struct keywordarg_s *message);
expr_t *sizeof_expr (expr_t *expr, struct type_s *type);

View File

@ -67,11 +67,13 @@ extern type_t type_Class;
extern type_t type_Protocol;
extern type_t type_SEL;
extern type_t type_IMP;
extern type_t type_supermsg;
extern type_t type_obj_exec_class;
extern type_t type_Method;
extern type_t *type_category;
extern type_t *type_ivar;
extern type_t *type_module;
extern type_t type_Super;
extern type_t type_va_list;
extern type_t type_param;
extern type_t type_zero;

View File

@ -432,7 +432,7 @@ class_message_response (class_t *class, expr_t *sel)
error (sel, "not a selector");
return 0;
}
selector = &G_STRUCT (pr_sel_t, sel->e.pointer.val);
selector = &G_STRUCT (pr_sel_t, POINTER_VAL (sel->e.pointer));
sel_name = G_GETSTR (selector->sel_id);
while (c) {
if (c->methods) {

View File

@ -386,8 +386,9 @@ emit_deref_expr (expr_t *e, def_t *dest)
if (e->e.pointer.def) {
d = new_def (e->e.pointer.type, 0, current_scope);
d->local = e->e.pointer.def->local;
d->ofs = e->e.pointer.def->ofs;
d->alias = e->e.pointer.def;
d->ofs = POINTER_VAL (e->e.pointer);
if (d->ofs == e->e.pointer.def->ofs)
d->alias = e->e.pointer.def;
} else if (e->e.pointer.val >= 0 && e->e.pointer.val < 65536) {
d = new_def (e->e.pointer.type, 0, current_scope);
d->ofs = e->e.pointer.val;
@ -400,9 +401,7 @@ emit_deref_expr (expr_t *e, def_t *dest)
}
return d;
}
if (!dest && (e->type != ex_pointer
|| !(e->e.pointer.val > 0
&& e->e.pointer.val < 65536))) {
if (!dest) {
dest = get_tempdef (type, current_scope);
dest->users += 2;
}

View File

@ -1125,6 +1125,7 @@ field_expr (expr_t *e1, expr_t *e2)
t1 = get_type (e1);
switch (t1->type) {
case ev_struct:
case ev_class:
check_initialized (e1);
if (e2->type != ex_name)
return error (e2, "structure field name expected");
@ -1225,7 +1226,7 @@ field_expr (expr_t *e1, expr_t *e2)
e = new_expr ();
e->type = ex_pointer;
e1 = e1->e.expr.e1;
i = e1->e.pointer.val;
i = POINTER_VAL (e1->e.pointer);
e->e.pointer.val = i + field->offset;
e->e.pointer.type = field->type;
return unary_expr ('.', e);
@ -2065,17 +2066,20 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
case ex_def:
{
def_t *def = e1->e.def;
def->used = 1;
type = def->type;
if (type->type == ev_struct) {
e = e1;
if (type->type == ev_struct || type->type == ev_class) {
e = new_expr ();
e->line = e1->line;
e->file = e1->file;
e->type = ex_pointer;
e->e.pointer.val = def->ofs;
e->e.pointer.val = 0;
e->e.pointer.type = t;
e->e.pointer.def = def;
} else if (type->type == ev_array) {
e = e1;
e->type = ex_pointer;
e->e.pointer.val = def->ofs;
e->e.pointer.val = 0;
e->e.pointer.type = t;
e->e.pointer.def = def;
} else {
@ -2135,8 +2139,10 @@ is_indirect (expr_t *e)
return 0;
e = e->e.expr.e1;
if (e->type != ex_pointer
|| !(e->e.pointer.val > 0 && e->e.pointer.val < 65536))
|| !(POINTER_VAL (e->e.pointer) >= 0
&& POINTER_VAL (e->e.pointer) < 65536)) {
return 1;
}
return 0;
}
@ -2215,7 +2221,8 @@ assign_expr (expr_t *e1, expr_t *e2)
} else {
e = e1->e.expr.e1;
if (e->type != ex_pointer
|| !(e->e.pointer.val > 0 && e->e.pointer.val < 65536)) {
|| !(POINTER_VAL (e->e.pointer) > 0
&& POINTER_VAL (e->e.pointer) < 65536)) {
e1 = e;
op = PAS;
}
@ -2228,7 +2235,8 @@ assign_expr (expr_t *e1, expr_t *e2)
if (e2->type == ex_uexpr) {
e = e2->e.expr.e1;
if (e->type != ex_pointer
|| !(e->e.pointer.val > 0 && e->e.pointer.val < 65536)) {
|| !(POINTER_VAL (e->e.pointer) > 0
&& POINTER_VAL (e->e.pointer) < 65536)) {
if (e->type == ex_expr && e->e.expr.op == '&'
&& e->e.expr.type->type == ev_pointer
&& e->e.expr.e1->type < ex_string) {
@ -2390,6 +2398,40 @@ encode_expr (type_t *type)
return e;
}
expr_t *
super_expr (class_type_t *class)
{
def_t *super_d;
expr_t *super;
expr_t *e;
expr_t *super_block;
if (!class)
return error (0, "`super' used outside of class implementation");
//if (!class->super_class)
// return error (0, "%s has no super class", class->name);
super_d = get_def (type_Super.aux_type, ".super", current_func->scope,
st_local);
def_initialized (super_d);
super = new_def_expr (super_d);
super_block = new_block_expr ();
e = assign_expr (binary_expr ('.', super, new_name_expr ("self")),
new_name_expr ("self"));
append_expr (super_block, e);
e = new_def_expr (class_def (class, 1));
e = assign_expr (binary_expr ('.', super, new_name_expr ("class")),
binary_expr ('.', e, new_name_expr ("super_class")));
append_expr (super_block, e);
e = address_expr (super, 0, 0);
super_block->e.block.result = e;
return super_block;
}
expr_t *
message_expr (expr_t *receiver, keywordarg_t *message)
{
@ -2405,18 +2447,28 @@ message_expr (expr_t *receiver, keywordarg_t *message)
if (receiver->type == ex_name
&& strcmp (receiver->e.string_val, "super") == 0) {
super = 1;
receiver->e.string_val = "self";
receiver = super_expr (current_class);
if (receiver->type == ex_error)
return receiver;
if (current_class->is_class)
class = current_class->c.class;
else
class = current_class->c.category->class;
rec_type = class->type;
} else {
rec_type = get_type (receiver);
if (receiver->type == ex_error)
return receiver;
if (rec_type->type != ev_pointer
|| (rec_type->aux_type->type != ev_object
&& rec_type->aux_type->type != ev_class))
return error (receiver, "not a class/object");
class = rec_type->aux_type->class;
}
rec_type = get_type (receiver);
if (receiver->type == ex_error)
return receiver;
if (rec_type->type != ev_pointer
|| (rec_type->aux_type->type != ev_object
&& 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)

View File

@ -193,9 +193,12 @@ copy_keywordargs (const keywordarg_t *kwargs)
expr_t *
send_message (int super)
{
return new_def_expr (get_def (&type_IMP,
super ? "obj_msgSend_super" : "obj_msgSend",
pr.scope, st_extern));
if (super)
return new_def_expr (get_def (&type_supermsg, "obj_msgSend_super",
pr.scope, st_extern));
else
return new_def_expr (get_def (&type_IMP, "obj_msgSend", pr.scope,
st_extern));
}
void

View File

@ -300,6 +300,7 @@ static keyword_t keywords[] = {
{"Class", TYPE, &type_Class, 0, PROG_VERSION},
{"Protocol", TYPE, &type_Protocol, 0, PROG_VERSION},
{"Method", TYPE, &type_Method, 0, PROG_VERSION},
{"Super", TYPE, &type_Super, 0, PROG_VERSION},
{"SEL", TYPE, &type_SEL, 0, PROG_VERSION},
{"IMP", TYPE, &type_IMP, 0, PROG_VERSION},
{"local", LOCAL, 0, 1, PROG_ID_VERSION},

View File

@ -86,8 +86,11 @@ type_t type_Protocol = { ev_pointer, "Protocol" };
type_t type_SEL = { ev_pointer, "SEL" };
type_t type_IMP = { ev_func, "IMP", NULL, &type_id, -3, { &type_id,
&type_SEL }};
type_t type_supermsg = { ev_func, ".supermsg", NULL, &type_id, -3,
{ 0, &type_SEL }};
type_t type_obj_exec_class = { ev_func, "function", NULL, &type_void, 1, { 0 }};
type_t type_Method = { ev_pointer, "Method" };
type_t type_Super = { ev_pointer, "Super" };
type_t *type_category;
type_t *type_ivar;
type_t *type_module;
@ -684,6 +687,10 @@ init_types (void)
new_struct_field (&type_va_list, &type_integer, "count", vis_public);
new_struct_field (&type_va_list, pointer_type (&type_param), "list",
vis_public);
type = type_Super.aux_type = new_struct ("Super");
new_struct_field (type, &type_id, "self", vis_public);
new_struct_field (type, &type_Class, "class", vis_public);
#if 0
type = type_module = new_struct ("obj_module_t");
new_struct_field (type, &type_integer, "version", vis_public);
@ -718,6 +725,7 @@ chain_initial_types (void)
chain_type (&type_short);
chain_type (&type_struct);
chain_type (&type_IMP);
chain_type (&type_Super);
chain_type (&type_SEL);
chain_type (&type_Method);
@ -727,6 +735,9 @@ chain_initial_types (void)
chain_type (type_category);
chain_type (type_ivar);
type_supermsg.parm_types[0] = &type_Super;
chain_type (&type_supermsg);
type_module = new_struct ("obj_module_t");
new_struct_field (type_module, &type_integer, "version", vis_public);
new_struct_field (type_module, &type_integer, "size", vis_public);