diff --git a/include/QF/pr_obj.h b/include/QF/pr_obj.h index 3dad660d7..46fed75d0 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/pr_obj.h @@ -34,6 +34,49 @@ #include "QF/pr_comp.h" +#define PR_BITS_PER_INT (sizeof (int) * 8) + +#define __PR_CLS_INFO(cls) ((cls)->info) +#define __PR_CLS_ISINFO(cls, mask) ((__PR_CLS_INFO (cls) & (mask)) == (mask)) +#define __PR_CLS_SETINFO(cls, mask) (__PR_CLS_INFO (cls) |= (mask)) + +/* + The structure is of type MetaClass +*/ +#define _PR_CLS_META 0x2 +#define PR_CLS_ISMETA(cls) ((cls) && __PR_CLS_ISINFO (cls, _PR_CLS_META)) + +/* + The structure is of type Class +*/ +#define _PR_CLS_CLASS 0x1 +#define PR_CLS_ISCLASS(cls) ((cls) && __PR_CLS_ISINFO (cls, _PR_CLS_CLASS)) + +/* + The class is initialized within the runtime. This means that + it has had correct super and sublinks assigned +*/ +#define _PR_CLS_RESOLV 0x8 +#define PR_CLS_ISRESOLV(cls) __PR_CLS_ISINFO (cls, _PR_CLS_RESOLV) +#define PR_CLS_SETRESOLV(cls) __PR_CLS_SETINFO (cls, _PR_CLS_RESOLV) + +/* + The class has been sent a +initialize message or such is not + defined for this class +*/ +#define _PR_CLS_INITIALIZED 0x8 +#define PR_CLS_ISINITIALIZED(cls) __PR_CLS_ISINFO (cls, _PR_CLS_INITIALIZED) +#define PR_CLS_SETINITIALIZED(cls) __PR_CLS_SETINFO (cls, _PR_CLS_INITIALIZED) + +/* + The class number of this class. This must be the same for both the + class and its meta class boject +*/ +#define PR_CLS_GETNUMBER(cls) (__CLS_INFO (cls) >> (PR_BITS_PER_INT / 2)) +#define PR_CLS_SETNUMBER(cls, num) \ + (__PR_CLS_INFO (cls) = __PR_CLS_INFO (cls) & (~0U >> (PR_BITS_PER_INT / 2)) \ + | (num) << (PR_BITS_PER_INT / 2)) + typedef struct pr_sel_s { pointer_t sel_id; string_t sel_types; @@ -48,7 +91,7 @@ typedef struct pr_class_s { pointer_t super_class; // pr_class_t string_t name; int version; - int info; + unsigned int info; int instance_size; pointer_t ivars; // pr_ivar_list_t pointer_t methods; // pr_method_list_t diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 696d5ce07..56e0f8b13 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -119,6 +119,8 @@ extern etype_t qc_types[]; extern struct type_s *types[]; extern expr_type expr_types[]; +extern expr_t *local_expr; + type_t *get_type (expr_t *e); etype_t extract_type (expr_t *e); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index df1a25370..37c5126a4 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -151,9 +151,11 @@ class_begin (class_t *class) 0, &numpr_globals); meta_def->initialized = meta_def->constant = 1; meta = &G_STRUCT (pr_class_t, meta_def->ofs); - memset (meta, 0, sizeof (*meta)); meta->class_pointer = ReuseString (class->class_name); + if (class->super_class) + meta->super_class = ReuseString (class->super_class->class_name); meta->name = meta->class_pointer; + meta->info = _PR_CLS_META; meta->instance_size = type_size (type_Class.aux_type); meta->ivars = emit_struct (type_Class.aux_type, "Class"); meta->protocols = emit_protocol_list (class->protocols, @@ -165,10 +167,9 @@ class_begin (class_t *class) class->def->initialized = class->def->constant = 1; cls = &G_STRUCT (pr_class_t, class->def->ofs); cls->class_pointer = meta_def->ofs; - if (class->super_class - && class->super_class->def) //FIXME implementation only - cls->super_class = class->super_class->def->ofs; + cls->super_class = meta->super_class; cls->name = meta->name; + meta->info = _PR_CLS_CLASS; cls->protocols = meta->protocols; } } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 183de5a4a..7a5dff338 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -100,7 +100,10 @@ expr_type expr_types[] = { ex_integer, // ev_integer ex_uinteger, // ev_uinteger ex_short, // ev_short - ex_nil, // ev_struct FIXME??? + ex_nil, // ev_struct + ex_nil, // ev_object + ex_nil, // ev_class + ex_nil, // ev_sel }; void @@ -982,6 +985,7 @@ field_expr (expr_t *e1, expr_t *e2) t1 = pointer_type (field->type); } break; + case ev_object: case ev_class: if (e2->type == ex_name) { field = class_find_ivar (t1->aux_type->class, @@ -2013,8 +2017,14 @@ message_expr (expr_t *receiver, keywordarg_t *message) receiver->e.string_val = "self"; } rec_type = get_type (receiver); - if (rec_type->type != ev_pointer || rec_type->aux_type->type != ev_class) - return error (receiver, "not a class object"); + + 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); @@ -2030,6 +2040,10 @@ message_expr (expr_t *receiver, keywordarg_t *message) a = &(*a)->next; *a = receiver; call = function_expr (send_message (super), args); + + if (call->type == ex_error) + return receiver; + call->e.block.result->e.def->type = rec_type; return call; } diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c index 41dd8892f..58c00083c 100644 --- a/tools/qfcc/source/pr_def.c +++ b/tools/qfcc/source/pr_def.c @@ -30,8 +30,6 @@ static const char rcsid[] = #include "struct.h" #include "type.h" -extern expr_t *local_expr; // FIXME just where should this go? - typedef struct locref_s { struct locref_s *next; int ofs; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 7d047d053..dc72cfa84 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -237,6 +237,7 @@ print_type (type_t *type) else printf ("[]"); break; + case ev_object: case ev_class: class = type->class; printf (" %s %s%s", pr_type_name[type->type], @@ -341,7 +342,8 @@ type_assignable (type_t *dst, type_t *src) return 0; dst = dst->aux_type; src = src->aux_type; - if (dst->type != ev_class || src->type != ev_class) + if ((dst->type != ev_object && dst->type != ev_class) + || (src->type != ev_object && src->type != ev_class)) return 0; dst_class = dst->class; src_class = src->class; @@ -457,7 +459,7 @@ init_types (void) chain_type (&type_Protocol); type = type_id.aux_type = new_struct ("id"); - type->type = ev_class; + type->type = ev_object; type->class = &class_id; class_id.ivars = type_id.aux_type; new_struct_field (type, &type_Class, "class_pointer", vis_public);