mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
fix a snafu with current_class and get ivar access working properly (cross
fingers:)
This commit is contained in:
parent
d8c66aef76
commit
451bfbddfe
4 changed files with 76 additions and 38 deletions
|
@ -48,6 +48,8 @@ extern class_t class_id;
|
|||
extern class_t class_Class;
|
||||
extern class_t class_Protocol;
|
||||
|
||||
extern class_t *current_class;
|
||||
|
||||
struct expr_s;
|
||||
struct method_s;
|
||||
struct protocol_s;
|
||||
|
@ -63,6 +65,7 @@ void class_begin (class_t *class);
|
|||
void class_finish (class_t *class);
|
||||
struct struct_field_s *class_find_ivar (class_t *class, int protected,
|
||||
const char *name);
|
||||
expr_t *class_ivar_expr (class_t *class, const char *name);
|
||||
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);
|
||||
|
|
|
@ -130,6 +130,7 @@ class_add_protocol (class_t *class, protocol_t *protocol)
|
|||
void
|
||||
class_begin (class_t *class)
|
||||
{
|
||||
current_class = class;
|
||||
if (class->def)
|
||||
return;
|
||||
if (class->class_name && class->category_name) {
|
||||
|
@ -204,22 +205,52 @@ class_find_ivar (class_t *class, int protected, const char *name)
|
|||
class_t *c;
|
||||
|
||||
ivar = struct_find_field (class->ivars, name);
|
||||
if (ivar)
|
||||
if (ivar) {
|
||||
if (protected && ivar->visibility != vis_public)
|
||||
goto access_error;
|
||||
return ivar;
|
||||
}
|
||||
for (c = class->super_class; c; c = c->super_class) {
|
||||
ivar = struct_find_field (c->ivars, name);
|
||||
if (ivar) {
|
||||
if (ivar->visibility == vis_private
|
||||
|| (protected && ivar->visibility == vis_protected)) {
|
||||
error (0, "%s.%s is not accessable here",
|
||||
class->class_name, name);
|
||||
return 0;
|
||||
}
|
||||
|| (protected && ivar->visibility == vis_protected))
|
||||
goto access_error;
|
||||
return ivar;
|
||||
}
|
||||
}
|
||||
error (0, "%s.%s does not exist", class->class_name, name);
|
||||
return 0;
|
||||
access_error:
|
||||
error (0, "%s.%s is not accessable here", class->class_name, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
class_ivar_expr (class_t *class, const char *name)
|
||||
{
|
||||
struct_field_t *ivar;
|
||||
class_t *c;
|
||||
|
||||
if (!class)
|
||||
return 0;
|
||||
|
||||
ivar = struct_find_field (class->ivars, name);
|
||||
if (!ivar) {
|
||||
for (c = class->super_class; c; c = c->super_class) {
|
||||
ivar = struct_find_field (c->ivars, name);
|
||||
if (ivar)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ivar)
|
||||
return 0;
|
||||
if (ivar->visibility == vis_private) {
|
||||
error (0, "%s.%s is not accessable here",
|
||||
class->class_name, name);
|
||||
return 0;
|
||||
}
|
||||
return binary_expr ('.', new_name_expr ("self"), new_name_expr (name));
|
||||
}
|
||||
|
||||
method_t *
|
||||
|
|
|
@ -112,7 +112,7 @@ convert_name (expr_t *e)
|
|||
if (e->type == ex_name) {
|
||||
const char *name = e->e.string_val;
|
||||
def_t *d;
|
||||
expr_t *enm;
|
||||
expr_t *new;
|
||||
class_t *class;
|
||||
|
||||
class = get_class (name, 0);
|
||||
|
@ -123,17 +123,26 @@ convert_name (expr_t *e)
|
|||
}
|
||||
d = PR_GetDef (NULL, name, pr_scope, 0);
|
||||
if (d) {
|
||||
if (!d->scope) {
|
||||
new = class_ivar_expr (current_class, name);
|
||||
if (new)
|
||||
goto convert;
|
||||
}
|
||||
e->type = ex_def;
|
||||
e->e.def = d;
|
||||
return;
|
||||
}
|
||||
enm = get_enum (name);
|
||||
if (enm) {
|
||||
e->type = ex_integer;
|
||||
e->e.integer_val = enm->e.integer_val;
|
||||
return;
|
||||
}
|
||||
new = class_ivar_expr (current_class, name);
|
||||
if (new)
|
||||
goto convert;
|
||||
new = get_enum (name);
|
||||
if (new)
|
||||
goto convert;
|
||||
error (e, "Undeclared variable \"%s\".", name);
|
||||
return;
|
||||
convert:
|
||||
e->type = new->type;
|
||||
e->e = new->e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -957,6 +966,7 @@ field_expr (expr_t *e1, expr_t *e2)
|
|||
type_t *t1, *t2;
|
||||
expr_t *e;
|
||||
struct_field_t *field;
|
||||
class_t *class;
|
||||
|
||||
t1 = get_type (e1);
|
||||
switch (t1->type) {
|
||||
|
@ -988,8 +998,8 @@ field_expr (expr_t *e1, expr_t *e2)
|
|||
case ev_object:
|
||||
case ev_class:
|
||||
if (e2->type == ex_name) {
|
||||
field = class_find_ivar (t1->aux_type->class,
|
||||
0,
|
||||
class = t1->aux_type->class;
|
||||
field = class_find_ivar (class, current_class != class,
|
||||
e2->e.string_val);
|
||||
if (!field)
|
||||
return new_error_expr ();
|
||||
|
|
|
@ -891,7 +891,6 @@ class_name
|
|||
error (0, "undefined symbol `%s'", $1);
|
||||
$$ = get_class (0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -903,7 +902,6 @@ new_class_name
|
|||
error (0, "redefinition of `%s'", $1);
|
||||
$$ = get_class (0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
|
||||
class_with_super
|
||||
|
@ -913,7 +911,6 @@ class_with_super
|
|||
error (0, "%s is not a super class of %s",
|
||||
$3->class_name, $1->class_name);
|
||||
$$ = $1;
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -922,7 +919,6 @@ new_class_with_super
|
|||
{
|
||||
$1->super_class = $3;
|
||||
$$ = $1;
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -934,7 +930,6 @@ category_name
|
|||
error (0, "undefined category `%s (%s)'", $1, $3);
|
||||
$$ = get_category (0, 0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -946,7 +941,6 @@ new_category_name
|
|||
error (0, "redefinition of category `%s (%s)'", $1, $3);
|
||||
$$ = get_category (0, 0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -963,27 +957,27 @@ protocol_name
|
|||
}
|
||||
|
||||
classdef
|
||||
: INTERFACE new_class_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $3);}
|
||||
'{' ivar_decl_list '}' { class_add_ivars ($2, $6); }
|
||||
methodprotolist { class_add_methods ($2, $9); }
|
||||
: INTERFACE new_class_name { current_class = $2; }
|
||||
protocolrefs { class_add_protocol_methods ($2, $4);}
|
||||
'{' ivar_decl_list '}' { class_add_ivars ($2, $7); }
|
||||
methodprotolist { class_add_methods ($2, $10); }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_class_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $3);}
|
||||
methodprotolist { class_add_methods ($2, $5); }
|
||||
| INTERFACE new_class_name { current_class = $2; }
|
||||
protocolrefs { class_add_protocol_methods ($2, $4);}
|
||||
methodprotolist { class_add_methods ($2, $6); }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_class_with_super
|
||||
protocolrefs { class_add_protocol_methods ($2, $3);}
|
||||
'{' ivar_decl_list '}' { class_add_ivars ($2, $6); }
|
||||
methodprotolist { class_add_methods ($2, $9); }
|
||||
| INTERFACE new_class_with_super { current_class = $2; }
|
||||
protocolrefs { class_add_protocol_methods ($2, $4);}
|
||||
'{' ivar_decl_list '}' { class_add_ivars ($2, $7); }
|
||||
methodprotolist { class_add_methods ($2, $10); }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_class_with_super
|
||||
protocolrefs { class_add_protocol_methods ($2, $3);}
|
||||
methodprotolist { class_add_methods ($2, $5); }
|
||||
| INTERFACE new_class_with_super { current_class = $2; }
|
||||
protocolrefs { class_add_protocol_methods ($2, $4);}
|
||||
methodprotolist { class_add_methods ($2, $6); }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_category_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $3);}
|
||||
methodprotolist { class_add_methods ($2, $5); }
|
||||
| INTERFACE new_category_name { current_class = $2; }
|
||||
protocolrefs { class_add_protocol_methods ($2, $4);}
|
||||
methodprotolist { class_add_methods ($2, $6); }
|
||||
END { current_class = 0; }
|
||||
| IMPLEMENTATION class_name { class_begin ($2); }
|
||||
'{' ivar_decl_list '}' { class_check_ivars ($2, $5); }
|
||||
|
|
Loading…
Reference in a new issue