mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
get [super ...] working correctly
This commit is contained in:
parent
bfaa07c726
commit
dedb2fa6bf
12 changed files with 124 additions and 53 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue