fix a snafu with current_class and get ivar access working properly (cross

fingers:)
This commit is contained in:
Bill Currie 2002-05-17 19:35:26 +00:00
parent d8c66aef76
commit 451bfbddfe
4 changed files with 76 additions and 38 deletions

View file

@ -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);

View file

@ -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 *

View file

@ -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 ();

View file

@ -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); }