Implement direct ivar access in methods.

A warning needs to be generated for access to ivars in a class method, but
it seems to work (unable to check due to other errors).
This commit is contained in:
Bill Currie 2011-02-07 08:32:52 +09:00
parent 3025e04ac5
commit 76034861c9
3 changed files with 47 additions and 17 deletions

View file

@ -123,7 +123,11 @@ void class_begin (class_type_t *class_type);
void class_finish (class_type_t *class_type);
int class_access (class_type_t *current_class, class_t *class);
struct symbol_s *class_find_ivar (class_t *class, int vis, const char *name);
struct expr_s *class_ivar_expr (class_type_t *class_type, const char *name);
struct symtab_s *class_ivar_scope (class_type_t *class_type,
struct symtab_s *parent);
void class_finish_ivar_scope (class_type_t *class_type,
struct symtab_s *ivar_scope,
struct symtab_s *param_scope);
struct method_s *class_find_method (class_type_t *class_type,
struct method_s *method);
struct method_s *class_message_response (class_t *class, int class_msg,

View file

@ -731,21 +731,6 @@ access_error:
return 0;
}
expr_t *
class_ivar_expr (class_type_t *class_type, const char *name)
{
symbol_t *ivar;
class_t *class;
if (!class_type || !(class = extract_class (class_type)))
return 0;
ivar = symtab_lookup (class->ivars, name);
if (!ivar)
return 0;
return binary_expr ('.', new_name_expr ("self"), new_name_expr (name));
}
method_t *
class_find_method (class_type_t *class_type, method_t *method)
{
@ -1314,3 +1299,38 @@ class_to_struct (class_t *class, symtab_t *symtab)
symtab->parent = parent;
return symtab;
}
symtab_t *
class_ivar_scope (class_type_t *class_type, symtab_t *parent)
{
class_t *class = extract_class (class_type);
return symtab_flat_copy (class->ivars, parent);
}
void
class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope,
symtab_t *param_scope)
{
class_t *class = extract_class (class_type);
type_t *class_ptr = pointer_type (class->type);
symbol_t *sym;
symbol_t *self;
expr_t *self_expr;
self = symtab_lookup (param_scope, "self");
if (!self)
internal_error (0, "I've lost my self!");
self_expr = new_symbol_expr (self);
if (self->type != class_ptr) {
debug (0, "class method scope");
//FIXME should generate a warning on access
self_expr = cast_expr (class_ptr, self_expr);
}
for (sym = ivar_scope->symbols; sym; sym = sym->next) {
if (sym->sy_type != sy_var)
continue;
sym->sy_type = sy_expr;
sym->s.expr = binary_expr ('.', copy_expr (self_expr),
new_symbol_expr (new_symbol (sym->name)));
}
}

View file

@ -1433,8 +1433,14 @@ methoddef
method_t *method = $2;
const char *nicename = method_name (method);
symbol_t *sym = $<symbol>4;
symtab_t *ivar_scope;
$<symtab>$ = current_symtab;
current_func = begin_function (sym, nicename, current_symtab);
ivar_scope = class_ivar_scope (current_class, current_symtab);
current_func = begin_function (sym, nicename, ivar_scope);
class_finish_ivar_scope (current_class, ivar_scope,
current_func->symtab);
method->def = sym->s.func->def;
current_symtab = current_func->symtab;
}