2002-05-08 21:24:24 +00:00
|
|
|
|
/*
|
2002-10-22 14:53:18 +00:00
|
|
|
|
class.c
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2002-10-22 14:53:18 +00:00
|
|
|
|
QC class support code
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2002-07-05 20:02:10 +00:00
|
|
|
|
Copyright (C) 2002 Bill Currie
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
|
Date: 2002/5/7
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
|
|
*/
|
2002-06-01 04:41:25 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include "config.h"
|
|
|
|
|
#endif
|
2003-01-15 15:31:36 +00:00
|
|
|
|
|
2002-06-01 04:41:25 +00:00
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
|
# include <string.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
|
# include <strings.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
#include "QF/dstring.h"
|
2002-05-10 00:00:23 +00:00
|
|
|
|
#include "QF/hash.h"
|
2002-05-15 23:24:19 +00:00
|
|
|
|
#include "QF/va.h"
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2022-01-08 15:26:52 +00:00
|
|
|
|
#include "QF/progs/pr_obj.h"
|
|
|
|
|
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/qfcc.h"
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/codespace.h"
|
|
|
|
|
#include "tools/qfcc/include/class.h"
|
|
|
|
|
#include "tools/qfcc/include/def.h"
|
|
|
|
|
#include "tools/qfcc/include/defspace.h"
|
|
|
|
|
#include "tools/qfcc/include/diagnostic.h"
|
|
|
|
|
#include "tools/qfcc/include/emit.h"
|
|
|
|
|
#include "tools/qfcc/include/expr.h"
|
|
|
|
|
#include "tools/qfcc/include/method.h"
|
|
|
|
|
#include "tools/qfcc/include/options.h"
|
|
|
|
|
#include "tools/qfcc/include/reloc.h"
|
|
|
|
|
#include "tools/qfcc/include/shared.h"
|
|
|
|
|
#include "tools/qfcc/include/strpool.h"
|
|
|
|
|
#include "tools/qfcc/include/struct.h"
|
|
|
|
|
#include "tools/qfcc/include/symtab.h"
|
|
|
|
|
#include "tools/qfcc/include/type.h"
|
|
|
|
|
#include "tools/qfcc/include/value.h"
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
static hashtab_t *class_hash;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
static hashtab_t *category_hash;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
static hashtab_t *protocol_hash;
|
2020-03-02 01:48:51 +00:00
|
|
|
|
static hashtab_t *static_instances;
|
|
|
|
|
static hashtab_t *static_instance_classes;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
|
2011-02-04 03:07:32 +00:00
|
|
|
|
// these will be built up further
|
2022-01-30 01:54:07 +00:00
|
|
|
|
type_t type_selector = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_SEL = {
|
|
|
|
|
.type = ev_ptr,
|
|
|
|
|
.name = "SEL",
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_selector}},
|
|
|
|
|
};
|
|
|
|
|
type_t *IMP_params[] = { &type_id, &type_SEL };
|
|
|
|
|
type_t type_IMP = {
|
|
|
|
|
.type = ev_func,
|
|
|
|
|
.name = "IMP",
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
2022-02-05 09:49:40 +00:00
|
|
|
|
{{&type_id, -3, IMP_params, .no_va_list = 1}},
|
2022-01-30 01:54:07 +00:00
|
|
|
|
};
|
|
|
|
|
type_t type_super = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
};
|
|
|
|
|
type_t type_SuperPtr = {
|
|
|
|
|
.type = ev_ptr,
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_super}},
|
|
|
|
|
};
|
|
|
|
|
type_t *supermsg_params[] = { &type_SuperPtr, &type_SEL };
|
|
|
|
|
type_t type_supermsg = {
|
|
|
|
|
.type = ev_func,
|
|
|
|
|
.name = ".supermsg",
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_id, -3, supermsg_params}},
|
|
|
|
|
};
|
|
|
|
|
type_t type_method = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_method_description = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_category = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_ivar = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_module = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_moduleptr = {
|
|
|
|
|
.type = ev_ptr,
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_module}},
|
|
|
|
|
};
|
|
|
|
|
type_t *obj_exec_class_params[] = {
|
|
|
|
|
&type_moduleptr,
|
|
|
|
|
};
|
|
|
|
|
type_t type_exec_class = {
|
|
|
|
|
.type = ev_func,
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_void, 1, obj_exec_class_params}},
|
|
|
|
|
};
|
2020-03-27 08:29:42 +00:00
|
|
|
|
// the cast of 1 in the init is to ensure pointers to incomplete types
|
|
|
|
|
// are never misidentified as id. It will be set to the correct value
|
|
|
|
|
// when the obj system is initialized.
|
2022-01-30 01:54:07 +00:00
|
|
|
|
type_t type_object = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
{{(type_t *)1}},
|
|
|
|
|
};
|
|
|
|
|
type_t type_id = {
|
|
|
|
|
.type = ev_ptr,
|
|
|
|
|
.name = "id",
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_object}},
|
|
|
|
|
};
|
|
|
|
|
type_t type_class = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
|
|
|
|
type_t type_Class = {
|
|
|
|
|
.type = ev_ptr,
|
|
|
|
|
.alignment = 1,
|
|
|
|
|
.width = 1,
|
|
|
|
|
.meta = ty_basic,
|
|
|
|
|
{{&type_class}},
|
|
|
|
|
};
|
|
|
|
|
type_t type_protocol = {
|
|
|
|
|
.type = ev_invalid,
|
|
|
|
|
.meta = ty_struct,
|
|
|
|
|
};
|
2002-05-16 20:20:23 +00:00
|
|
|
|
|
2012-11-08 07:46:48 +00:00
|
|
|
|
int obj_initialized = 0;
|
|
|
|
|
|
2011-02-04 03:07:32 +00:00
|
|
|
|
static struct_def_t sel_struct[] = {
|
|
|
|
|
{"sel_id", &type_string},
|
|
|
|
|
{"sel_types", &type_string},
|
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct_def_t method_struct[] = {
|
|
|
|
|
{"method_name", &type_SEL},
|
|
|
|
|
{"method_types", &type_string},
|
|
|
|
|
{"method_imp", &type_IMP},
|
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct_def_t method_desc_struct[] = {
|
|
|
|
|
{"name", &type_string},
|
|
|
|
|
{"types", &type_string},
|
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct_def_t category_struct[] = {
|
|
|
|
|
{"category_name", &type_string},
|
|
|
|
|
{"class_name", &type_string},
|
2022-01-18 13:34:52 +00:00
|
|
|
|
{"instance_methods", &type_ptr},
|
|
|
|
|
{"class_methods", &type_ptr},
|
|
|
|
|
{"protocols", &type_ptr},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct_def_t ivar_struct[] = {
|
|
|
|
|
{"ivar_name", &type_string},
|
|
|
|
|
{"ivar_type", &type_string},
|
2022-01-18 04:21:06 +00:00
|
|
|
|
{"ivar_offset", &type_int},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct_def_t super_struct[] = {
|
|
|
|
|
{"self", &type_id},
|
2012-11-08 11:58:48 +00:00
|
|
|
|
{"class", &type_Class},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct_def_t module_struct[] = {
|
2022-01-18 04:21:06 +00:00
|
|
|
|
{"version", &type_int},
|
|
|
|
|
{"size", &type_int},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{"name", &type_string},
|
2022-01-18 13:34:52 +00:00
|
|
|
|
{"symtab", &type_ptr},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
2012-11-12 02:12:33 +00:00
|
|
|
|
static struct_def_t class_struct[] = {
|
|
|
|
|
{"class_pointer", &type_Class},
|
2012-11-08 11:58:48 +00:00
|
|
|
|
{"super_class", &type_Class},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{"name", &type_string},
|
2022-01-18 04:21:06 +00:00
|
|
|
|
{"version", &type_int},
|
|
|
|
|
{"info", &type_int},
|
|
|
|
|
{"instance_size", &type_int},
|
2022-01-18 13:34:52 +00:00
|
|
|
|
{"ivars", &type_ptr},
|
|
|
|
|
{"methods", &type_ptr},
|
|
|
|
|
{"dtable", &type_ptr},
|
|
|
|
|
{"subclass_list", &type_ptr},
|
|
|
|
|
{"sibling_class", &type_ptr},
|
|
|
|
|
{"protocols", &type_ptr},
|
|
|
|
|
{"gc_object_type", &type_ptr},
|
2011-07-30 06:01:16 +00:00
|
|
|
|
{0, 0}
|
2011-02-04 03:07:32 +00:00
|
|
|
|
};
|
|
|
|
|
|
2012-11-12 02:12:33 +00:00
|
|
|
|
static struct_def_t protocol_struct[] = {
|
|
|
|
|
{"class_pointer", &type_Class},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{"protocol_name", &type_string},
|
2022-01-18 13:34:52 +00:00
|
|
|
|
{"protocol_list", &type_ptr},
|
|
|
|
|
{"instance_methods", &type_ptr},
|
|
|
|
|
{"class_methods", &type_ptr},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
2012-11-12 02:12:33 +00:00
|
|
|
|
static struct_def_t object_struct[] = {
|
2012-11-08 11:58:48 +00:00
|
|
|
|
{"class_pointer", &type_Class},
|
2011-02-04 03:07:32 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
2020-03-02 01:48:51 +00:00
|
|
|
|
static const char *
|
|
|
|
|
static_instance_get_key (const void *instance, void *unused)
|
|
|
|
|
{
|
|
|
|
|
return ((static_instance_t *) instance)->class;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_static_instance (const char *class, def_t *instance_def)
|
|
|
|
|
{
|
|
|
|
|
static_instance_t *instance = malloc (sizeof (*instance));
|
|
|
|
|
|
|
|
|
|
if (!static_instances) {
|
2020-03-25 06:43:16 +00:00
|
|
|
|
static_instances = Hash_NewTable (1021, static_instance_get_key,
|
|
|
|
|
0, 0, 0);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
static_instance_classes = Hash_NewTable (1021, static_instance_get_key,
|
2020-03-25 06:43:16 +00:00
|
|
|
|
0, 0, 0);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
instance->class = save_string (class);
|
|
|
|
|
instance->instance = instance_def;
|
|
|
|
|
Hash_Add (static_instances, instance);
|
|
|
|
|
|
|
|
|
|
// uniqued set of class names for all static instances
|
|
|
|
|
if (!Hash_Find (static_instance_classes, class)) {
|
|
|
|
|
Hash_Add (static_instance_classes, instance);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *class_name;
|
|
|
|
|
int num_instances;
|
|
|
|
|
static_instance_t **instances;
|
|
|
|
|
} obj_static_instances_data_t;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_instance_classname (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_static_instances_data_t *da = (obj_static_instances_data_t *)data;
|
|
|
|
|
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!is_string(def->type))
|
2020-03-02 01:48:51 +00:00
|
|
|
|
internal_error (0, "%s: expected string def", __FUNCTION__);
|
|
|
|
|
EMIT_STRING (def->space, D_STRING (def), da->class_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_instance_defs (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_static_instances_data_t *da = (obj_static_instances_data_t *)data;
|
|
|
|
|
|
2022-01-18 05:36:06 +00:00
|
|
|
|
if (!is_array (def->type) || def->type->t.array.type->type != ev_ptr)
|
2020-03-02 01:48:51 +00:00
|
|
|
|
internal_error (0, "%s: expected array of pointers def", __FUNCTION__);
|
|
|
|
|
if (index < 0 || index >= da->num_instances + 1)
|
|
|
|
|
internal_error (0, "%s: out of bounds index: %d %d",
|
|
|
|
|
__FUNCTION__, index, da->num_instances + 1);
|
|
|
|
|
D_INT (def) = 0;
|
|
|
|
|
if (index < da->num_instances) {
|
|
|
|
|
EMIT_DEF (def->space, D_INT (def), da->instances[index]->instance);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static def_t *
|
|
|
|
|
emit_static_instances (const char *classname)
|
|
|
|
|
{
|
|
|
|
|
static struct_def_t instances_struct[] = {
|
|
|
|
|
{"class_name", &type_string, emit_instance_classname},
|
|
|
|
|
{"instances", 0, emit_instance_defs},
|
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
|
|
|
|
obj_static_instances_data_t data = {};
|
|
|
|
|
def_t *instances_def;
|
|
|
|
|
|
|
|
|
|
data.class_name = classname;
|
|
|
|
|
data.instances = (static_instance_t **) Hash_FindList (static_instances,
|
|
|
|
|
classname);
|
|
|
|
|
for (static_instance_t **inst = data.instances; *inst; inst++) {
|
|
|
|
|
data.num_instances++;
|
|
|
|
|
}
|
2022-01-18 13:34:52 +00:00
|
|
|
|
instances_struct[1].type = array_type (&type_ptr, data.num_instances + 1);
|
2021-01-31 07:01:20 +00:00
|
|
|
|
instances_def = emit_structure (va (0, "_OBJ_STATIC_INSTANCES_%s",
|
|
|
|
|
classname),
|
2020-03-02 01:48:51 +00:00
|
|
|
|
's', instances_struct, 0, &data,
|
2020-04-03 05:16:16 +00:00
|
|
|
|
0, sc_static);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
free (data.instances);
|
|
|
|
|
return instances_def;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static def_t *
|
|
|
|
|
emit_static_instances_list (void)
|
|
|
|
|
{
|
|
|
|
|
static_instance_t **classes;
|
|
|
|
|
int num_classes = 0;
|
|
|
|
|
def_t **instance_lists;
|
|
|
|
|
type_t *instance_lists_type;
|
|
|
|
|
symbol_t *instance_lists_sym;
|
|
|
|
|
def_t *instance_lists_def;
|
2022-01-18 03:11:14 +00:00
|
|
|
|
pr_ptr_t *list;
|
2020-03-02 01:48:51 +00:00
|
|
|
|
defspace_t *space;
|
|
|
|
|
|
|
|
|
|
if (!static_instance_classes || !static_instances) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
classes = (static_instance_t **) Hash_GetList (static_instance_classes);
|
|
|
|
|
for (static_instance_t **c = classes; *c; c++) {
|
|
|
|
|
num_classes++;
|
|
|
|
|
}
|
|
|
|
|
if (!num_classes) {
|
|
|
|
|
free (classes);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
instance_lists = alloca (num_classes * sizeof (*instance_lists));
|
|
|
|
|
for (int i = 0; i < num_classes; i++) {
|
|
|
|
|
instance_lists[i] = emit_static_instances (classes[i]->class);
|
|
|
|
|
}
|
|
|
|
|
free (classes);
|
|
|
|
|
|
|
|
|
|
// +1 for terminating null
|
2022-01-18 13:34:52 +00:00
|
|
|
|
instance_lists_type = array_type (&type_ptr, num_classes + 1);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
instance_lists_sym = make_symbol ("_OBJ_STATIC_INSTANCES",
|
|
|
|
|
instance_lists_type,
|
|
|
|
|
pr.far_data, sc_static);
|
|
|
|
|
if (!instance_lists_sym->table) {
|
|
|
|
|
symtab_addsymbol (pr.symtab, instance_lists_sym);
|
|
|
|
|
}
|
|
|
|
|
instance_lists_def = instance_lists_sym->s.def;
|
|
|
|
|
instance_lists_def->initialized = instance_lists_def->constant = 1;
|
|
|
|
|
instance_lists_def->nosave = 1;
|
|
|
|
|
|
2022-01-18 03:11:14 +00:00
|
|
|
|
list = D_POINTER (pr_ptr_t, instance_lists_def);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
space = instance_lists_def->space;
|
|
|
|
|
for (int i = 0; i < num_classes; i++, list++) {
|
|
|
|
|
EMIT_DEF (space, *list, instance_lists[i]);
|
|
|
|
|
}
|
|
|
|
|
*list = 0;
|
|
|
|
|
return instance_lists_def;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-18 11:56:23 +00:00
|
|
|
|
int
|
2020-03-27 06:16:41 +00:00
|
|
|
|
is_id (const type_t *type)
|
2012-12-18 11:56:23 +00:00
|
|
|
|
{
|
|
|
|
|
if (type == &type_id)
|
|
|
|
|
return 1;
|
2012-12-18 12:08:52 +00:00
|
|
|
|
// type may be a qualified id, in which case it will be a pointer to
|
|
|
|
|
// a qualified obj_object struct
|
2022-01-18 05:36:06 +00:00
|
|
|
|
if (type->type != ev_ptr)
|
2012-12-18 12:08:52 +00:00
|
|
|
|
return 0;
|
|
|
|
|
if (!is_struct (type->t.fldptr.type))
|
|
|
|
|
return 0;
|
|
|
|
|
// if the the symtabs match, then type is id in disguise
|
2020-03-27 06:33:53 +00:00
|
|
|
|
if (type->t.fldptr.type->t.symtab == type_object.t.symtab)
|
2012-12-18 11:56:23 +00:00
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-19 02:53:19 +00:00
|
|
|
|
int
|
2020-03-27 06:16:41 +00:00
|
|
|
|
is_class (const type_t *type)
|
2012-12-19 02:53:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (type->type == ev_invalid && type->meta == ty_class)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2020-03-27 06:16:41 +00:00
|
|
|
|
is_Class (const type_t *type)
|
2012-12-19 02:53:19 +00:00
|
|
|
|
{
|
2012-12-19 05:07:23 +00:00
|
|
|
|
if (type == &type_Class)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2012-12-19 02:53:19 +00:00
|
|
|
|
|
2012-12-19 05:07:23 +00:00
|
|
|
|
int
|
2020-03-27 06:16:41 +00:00
|
|
|
|
is_classptr (const type_t *type)
|
2012-12-19 05:07:23 +00:00
|
|
|
|
{
|
|
|
|
|
// easy cases first :)
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_id (type) || is_Class (type))
|
2012-12-19 02:53:19 +00:00
|
|
|
|
return 1;
|
2022-01-18 05:36:06 +00:00
|
|
|
|
if (type->type != ev_ptr)
|
2012-12-19 05:07:23 +00:00
|
|
|
|
return 0;
|
|
|
|
|
type = type->t.fldptr.type;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_class (type))
|
2012-12-19 02:53:19 +00:00
|
|
|
|
return 1;
|
2012-12-19 05:07:23 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2012-12-19 02:53:19 +00:00
|
|
|
|
|
2020-03-27 06:16:41 +00:00
|
|
|
|
int
|
|
|
|
|
is_SEL (const type_t *type)
|
|
|
|
|
{
|
|
|
|
|
return type == &type_SEL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
is_object (const type_t *type)
|
|
|
|
|
{
|
2020-03-27 06:33:53 +00:00
|
|
|
|
return type == &type_object;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
is_method (const type_t *type)
|
|
|
|
|
{
|
2020-03-27 06:33:53 +00:00
|
|
|
|
return type == &type_method;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
is_method_description (const type_t *type)
|
|
|
|
|
{
|
2020-03-27 06:33:53 +00:00
|
|
|
|
return type == &type_method_description;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-20 04:12:26 +00:00
|
|
|
|
static protocollist_t *
|
|
|
|
|
obj_get_class_protos (const type_t *type)
|
|
|
|
|
{
|
2022-01-19 08:48:46 +00:00
|
|
|
|
if (is_ptr (type))
|
2012-12-20 04:12:26 +00:00
|
|
|
|
type = type->t.fldptr.type;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_class (type))
|
2012-12-20 04:12:26 +00:00
|
|
|
|
return type->t.class->protocols;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static protocollist_t *
|
|
|
|
|
obj_get_protos (const type_t *type)
|
|
|
|
|
{
|
2022-01-19 08:48:46 +00:00
|
|
|
|
if (is_ptr (type))
|
2012-12-20 04:12:26 +00:00
|
|
|
|
type = type->t.fldptr.type;
|
|
|
|
|
return type->protos;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-20 04:42:19 +00:00
|
|
|
|
static category_t *
|
|
|
|
|
obj_get_categories (const type_t *type)
|
|
|
|
|
{
|
2022-01-19 08:48:46 +00:00
|
|
|
|
if (is_ptr (type))
|
2012-12-20 04:42:19 +00:00
|
|
|
|
type = type->t.fldptr.type;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_class (type))
|
2012-12-20 04:42:19 +00:00
|
|
|
|
return type->t.class->categories;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-20 04:12:26 +00:00
|
|
|
|
static const char *
|
|
|
|
|
obj_classname (const type_t *type)
|
|
|
|
|
{
|
|
|
|
|
static dstring_t *str;
|
|
|
|
|
protocollist_t *protos;
|
|
|
|
|
|
|
|
|
|
if (!str)
|
|
|
|
|
str = dstring_new ();
|
|
|
|
|
dstring_clearstr (str);
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_id (type)) {
|
2012-12-20 04:12:26 +00:00
|
|
|
|
dstring_copystr (str, "id");
|
2020-03-27 06:16:41 +00:00
|
|
|
|
} else if (is_Class (type)) {
|
2012-12-20 04:12:26 +00:00
|
|
|
|
dstring_copystr (str, "Class");
|
|
|
|
|
} else {
|
2022-01-19 08:48:46 +00:00
|
|
|
|
if (is_ptr (type))
|
2012-12-20 04:12:26 +00:00
|
|
|
|
type = type->t.fldptr.type;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_class (type))
|
2012-12-20 04:12:26 +00:00
|
|
|
|
dstring_copystr (str, type->t.class->name);
|
|
|
|
|
}
|
|
|
|
|
if ((protos = obj_get_protos (type)))
|
|
|
|
|
print_protocollist (str, protos);
|
|
|
|
|
return str->str;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-09 03:35:01 +00:00
|
|
|
|
static __attribute__((pure)) int
|
2012-12-20 04:42:19 +00:00
|
|
|
|
category_implements (category_t *cat, protocol_t *protocol)
|
|
|
|
|
{
|
|
|
|
|
for (; cat; cat = cat->next) {
|
|
|
|
|
if (!cat->protocols)
|
|
|
|
|
continue;
|
|
|
|
|
if (procollist_find_protocol (cat->protocols, protocol))
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-19 05:07:23 +00:00
|
|
|
|
int
|
|
|
|
|
obj_types_assignable (const type_t *dst, const type_t *src)
|
|
|
|
|
{
|
2021-06-09 03:08:13 +00:00
|
|
|
|
class_t *dst_class, *src_class = 0;
|
2012-12-20 04:42:19 +00:00
|
|
|
|
category_t *cat;
|
2012-12-20 04:12:26 +00:00
|
|
|
|
int dst_is_proto, src_is_proto;
|
|
|
|
|
protocollist_t *dst_protos = 0, *src_protos = 0;
|
|
|
|
|
int i;
|
2012-12-19 05:07:23 +00:00
|
|
|
|
|
2012-12-20 04:12:26 +00:00
|
|
|
|
//puts ("%$$\"$#%");
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!is_classptr (src)) {
|
2020-03-05 05:14:20 +00:00
|
|
|
|
// if dst is a class pointer, then the types are not compatible,
|
|
|
|
|
// otherwise unknown
|
2020-03-27 06:16:41 +00:00
|
|
|
|
return is_classptr (dst) - 1;
|
2020-03-05 05:14:20 +00:00
|
|
|
|
}
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!is_classptr (dst)) {
|
2012-12-19 02:53:19 +00:00
|
|
|
|
return -1;
|
2020-03-05 05:14:20 +00:00
|
|
|
|
}
|
2012-12-19 02:53:19 +00:00
|
|
|
|
|
2020-03-27 06:16:41 +00:00
|
|
|
|
dst_is_proto = is_id (dst) && (dst_protos = obj_get_protos (dst));
|
|
|
|
|
src_is_proto = is_id (src) && (src_protos = obj_get_protos (src));
|
2012-12-20 04:12:26 +00:00
|
|
|
|
|
|
|
|
|
if (dst_is_proto) {
|
|
|
|
|
if (src_is_proto) {
|
|
|
|
|
// id <protos> = id <protos>
|
|
|
|
|
for (i = 0; i < dst_protos->count; i++) {
|
|
|
|
|
if (!procollist_find_protocol (src_protos,
|
|
|
|
|
dst_protos->list[i])) {
|
|
|
|
|
warning (0, "type %s does not conform to the %s protocol",
|
|
|
|
|
obj_classname (src), dst_protos->list[i]->name);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-27 06:16:41 +00:00
|
|
|
|
} else if (!is_id (src)) {
|
2012-12-20 04:12:26 +00:00
|
|
|
|
src_protos = obj_get_class_protos (src);
|
|
|
|
|
for (i = 0; i < dst_protos->count; i++) {
|
2012-12-20 04:42:19 +00:00
|
|
|
|
if (procollist_find_protocol (src_protos, dst_protos->list[i]))
|
|
|
|
|
continue;
|
|
|
|
|
cat = obj_get_categories (src);
|
|
|
|
|
if (cat && category_implements (cat, dst_protos->list[i]))
|
|
|
|
|
continue;
|
|
|
|
|
warning (0, "class %s does not implement to the %s protocol",
|
|
|
|
|
obj_classname (src), dst_protos->list[i]->name);
|
|
|
|
|
return 1;
|
2012-12-20 04:12:26 +00:00
|
|
|
|
}
|
2012-12-20 04:42:19 +00:00
|
|
|
|
return 1;
|
2012-12-20 04:12:26 +00:00
|
|
|
|
}
|
|
|
|
|
} else if (src_is_proto) {
|
|
|
|
|
} else {
|
|
|
|
|
}
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_id (dst) || is_id (src))
|
2012-12-19 05:07:23 +00:00
|
|
|
|
return 1;
|
|
|
|
|
|
2012-12-19 02:53:19 +00:00
|
|
|
|
// check dst is a base class of src
|
|
|
|
|
dst_class = dst->t.fldptr.type->t.class;
|
2021-06-09 03:08:13 +00:00
|
|
|
|
if (src->t.fldptr.type->meta == ty_class) {
|
|
|
|
|
src_class = src->t.fldptr.type->t.class;
|
|
|
|
|
}
|
2012-12-19 02:53:19 +00:00
|
|
|
|
//printf ("%s %s\n", dst_class->name, src_class->name);
|
|
|
|
|
while (dst_class != src_class && src_class) {
|
|
|
|
|
src_class = src_class->super_class;
|
|
|
|
|
//if (src_class)
|
|
|
|
|
// printf ("%s %s\n", dst_class->name, src_class->name);
|
|
|
|
|
}
|
|
|
|
|
if (dst_class == src_class)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
static const char *
|
2012-07-18 13:34:37 +00:00
|
|
|
|
class_get_key (const void *class, void *unused)
|
2002-05-10 00:00:23 +00:00
|
|
|
|
{
|
2002-11-12 19:52:43 +00:00
|
|
|
|
return ((class_t *) class)->name;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
2012-07-18 13:34:37 +00:00
|
|
|
|
protocol_get_key (const void *protocol, void *unused)
|
2002-05-10 00:00:23 +00:00
|
|
|
|
{
|
|
|
|
|
return ((protocol_t *) protocol)->name;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
const char *
|
|
|
|
|
get_class_name (class_type_t *class_type, int pretty)
|
|
|
|
|
{
|
|
|
|
|
switch (class_type->type) {
|
|
|
|
|
case ct_class:
|
|
|
|
|
if (pretty)
|
|
|
|
|
return class_type->c.class->name;
|
|
|
|
|
else
|
2021-01-31 07:01:20 +00:00
|
|
|
|
return va (0, "%s_", class_type->c.class->name);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
case ct_category:
|
|
|
|
|
if (pretty)
|
2021-01-31 07:01:20 +00:00
|
|
|
|
return va (0, "%s (%s)", class_type->c.category->class->name,
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_type->c.category->name);
|
|
|
|
|
else
|
2021-01-31 07:01:20 +00:00
|
|
|
|
return va (0, "%s_%s", class_type->c.category->class->name,
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_type->c.category->name);
|
|
|
|
|
case ct_protocol:
|
2021-01-31 07:01:20 +00:00
|
|
|
|
return va (0, "<%s>", class_type->c.protocol->name);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
}
|
|
|
|
|
return "???";
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
|
symbol_t *
|
|
|
|
|
class_symbol (class_type_t *class_type, int external)
|
2002-07-03 20:16:32 +00:00
|
|
|
|
{
|
2010-12-31 06:44:54 +00:00
|
|
|
|
const char *name = 0;
|
|
|
|
|
type_t *type = 0;
|
2011-02-08 08:08:58 +00:00
|
|
|
|
symbol_t *sym;
|
2002-07-03 20:16:32 +00:00
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
switch (class_type->type) {
|
|
|
|
|
case ct_category:
|
2021-01-31 07:01:20 +00:00
|
|
|
|
name = va (0, "_OBJ_CATEGORY_%s_%s",
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_type->c.category->class->name,
|
|
|
|
|
class_type->c.category->name);
|
2020-03-27 06:33:53 +00:00
|
|
|
|
type = &type_category;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
break;
|
|
|
|
|
case ct_class:
|
2021-01-31 07:01:20 +00:00
|
|
|
|
name = va (0, "_OBJ_CLASS_%s", class_type->c.class->name);
|
2020-03-27 06:33:53 +00:00
|
|
|
|
type = &type_class;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
break;
|
|
|
|
|
case ct_protocol:
|
|
|
|
|
return 0; // probably in error recovery
|
2002-07-16 04:37:51 +00:00
|
|
|
|
}
|
2011-02-08 08:08:58 +00:00
|
|
|
|
sym = make_symbol (name, type, pr.far_data,
|
2012-12-02 01:11:30 +00:00
|
|
|
|
external ? sc_extern : sc_global);
|
2011-02-08 08:08:58 +00:00
|
|
|
|
if (!sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, sym);
|
|
|
|
|
return sym;
|
2002-07-03 20:16:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-10 03:56:19 +00:00
|
|
|
|
static class_t *
|
|
|
|
|
_get_class (symbol_t *sym, int create)
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2002-05-10 00:00:23 +00:00
|
|
|
|
class_t *c;
|
|
|
|
|
|
|
|
|
|
if (!class_hash)
|
2020-03-25 06:43:16 +00:00
|
|
|
|
class_hash = Hash_NewTable (1021, class_get_key, 0, 0, 0);
|
2011-01-17 13:33:33 +00:00
|
|
|
|
if (sym) {
|
|
|
|
|
c = Hash_Find (class_hash, sym->name);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
if (c || !create)
|
|
|
|
|
return c;
|
|
|
|
|
}
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
c = calloc (sizeof (class_t), 1);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
c->methods = new_methodlist ();
|
|
|
|
|
c->class_type.type = ct_class;
|
|
|
|
|
c->class_type.c.class = c;
|
|
|
|
|
if (sym) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
c->name = sym->name;
|
2012-11-10 03:56:19 +00:00
|
|
|
|
Hash_Add (class_hash, c);
|
|
|
|
|
sym->sy_type = sy_class;
|
|
|
|
|
}
|
2012-11-12 03:42:54 +00:00
|
|
|
|
|
|
|
|
|
sym = class_symbol (&c->class_type, 1);
|
|
|
|
|
c->def = sym->s.def;
|
|
|
|
|
|
2012-11-10 03:56:19 +00:00
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class_t *
|
|
|
|
|
get_class (symbol_t *sym, int create)
|
|
|
|
|
{
|
|
|
|
|
class_t *c;
|
|
|
|
|
type_t new;
|
|
|
|
|
|
|
|
|
|
if (!(c = _get_class (sym, create)))
|
|
|
|
|
return c;
|
|
|
|
|
|
2012-11-08 07:13:00 +00:00
|
|
|
|
memset (&new, 0, sizeof (new));
|
|
|
|
|
new.type = ev_invalid;
|
|
|
|
|
new.name = c->name;
|
|
|
|
|
new.meta = ty_class;
|
2011-01-09 10:41:24 +00:00
|
|
|
|
new.t.class = c;
|
|
|
|
|
c->type = find_type (&new);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
if (sym)
|
2011-02-03 06:21:09 +00:00
|
|
|
|
sym->type = c->type;
|
2002-05-08 21:24:24 +00:00
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-02 07:13:00 +00:00
|
|
|
|
static void
|
|
|
|
|
set_self_type (class_t *class, method_t *method)
|
|
|
|
|
{
|
|
|
|
|
if (method->instance)
|
2011-01-09 10:41:24 +00:00
|
|
|
|
method->params->type = pointer_type (class->type);
|
2004-11-02 07:13:00 +00:00
|
|
|
|
else
|
2012-11-08 11:58:48 +00:00
|
|
|
|
method->params->type = &type_Class;
|
2004-11-02 07:13:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
methods_set_self_type (class_t *class, methodlist_t *methods)
|
|
|
|
|
{
|
|
|
|
|
method_t *method;
|
|
|
|
|
|
|
|
|
|
for (method = methods->head; method; method = method->next)
|
|
|
|
|
set_self_type (class, method);
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
void
|
|
|
|
|
class_add_methods (class_t *class, methodlist_t *methods)
|
|
|
|
|
{
|
|
|
|
|
if (!methods)
|
|
|
|
|
return;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
|
2020-03-02 15:11:54 +00:00
|
|
|
|
merge_method_lists (class->methods, methods);
|
2004-11-02 07:13:00 +00:00
|
|
|
|
|
|
|
|
|
methods_set_self_type (class, class->methods);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-11-11 00:34:00 +00:00
|
|
|
|
class_add_protocols (class_t *class, protocollist_t *protocols)
|
2002-05-10 00:00:23 +00:00
|
|
|
|
{
|
2004-11-11 00:34:00 +00:00
|
|
|
|
int i;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
protocol_t *p;
|
2004-11-11 00:34:00 +00:00
|
|
|
|
methodlist_t *methods;
|
2020-03-05 03:52:37 +00:00
|
|
|
|
methodset_t *except;
|
|
|
|
|
class_t *super;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
if (!protocols)
|
|
|
|
|
return;
|
2002-11-12 19:52:43 +00:00
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
methods = class->methods;
|
2002-11-12 19:52:43 +00:00
|
|
|
|
|
2020-03-05 03:52:37 +00:00
|
|
|
|
except = new_methodset ();
|
|
|
|
|
for (super = class->super_class; super; super = super->super_class) {
|
|
|
|
|
methodset_add_methods (except, super->methods);
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
for (i = 0; i < protocols->count; i++) {
|
|
|
|
|
p = protocols->list[i];
|
2020-03-01 10:37:40 +00:00
|
|
|
|
if (p->methods) {
|
2020-03-05 03:52:37 +00:00
|
|
|
|
copy_methods (methods, p->methods, except);
|
2020-03-01 10:37:40 +00:00
|
|
|
|
} else {
|
|
|
|
|
warning (0, "definition of protocol `%s' not found", p->name);
|
|
|
|
|
}
|
2004-11-11 00:34:00 +00:00
|
|
|
|
if (p->protocols)
|
|
|
|
|
class_add_protocols (class, p->protocols);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
2004-11-11 00:34:00 +00:00
|
|
|
|
class->protocols = protocols;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
static void
|
|
|
|
|
begin_category (category_t *category)
|
|
|
|
|
{
|
|
|
|
|
pr_category_t *pr_category;
|
|
|
|
|
class_t *class = category->class;
|
2012-05-21 23:23:22 +00:00
|
|
|
|
symbol_t *sym;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
def_t *def;
|
|
|
|
|
defspace_t *space;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
|
|
|
|
|
current_class = &category->class_type;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
sym = class_symbol (current_class, 0);
|
|
|
|
|
category->def = def = sym->s.def;
|
|
|
|
|
def->initialized = def->constant = def->nosave = 1;
|
|
|
|
|
space = def->space;
|
|
|
|
|
|
|
|
|
|
pr_category = &D_STRUCT (pr_category_t, def);
|
|
|
|
|
EMIT_STRING (space, pr_category->category_name, category->name);
|
|
|
|
|
EMIT_STRING (space, pr_category->class_name, class->name);
|
|
|
|
|
EMIT_DEF (space, pr_category->protocols,
|
2010-12-31 06:44:54 +00:00
|
|
|
|
emit_protocol_list (category->protocols,
|
2021-01-31 07:01:20 +00:00
|
|
|
|
va (0, "%s_%s", class->name,
|
|
|
|
|
category->name)));
|
2010-12-31 06:44:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-04 06:10:47 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
int count;
|
|
|
|
|
symbol_t *ivars;
|
|
|
|
|
dstring_t *encoding;
|
|
|
|
|
} ivar_data_t;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_ivar_count (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
ivar_data_t *ivar_data = (ivar_data_t *) data;
|
|
|
|
|
|
2022-01-18 04:21:06 +00:00
|
|
|
|
if (!is_int(def->type))
|
|
|
|
|
internal_error (0, "%s: expected int def", __FUNCTION__);
|
2011-02-04 06:10:47 +00:00
|
|
|
|
D_INT (def) = ivar_data->count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_ivar_list_item (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
ivar_data_t *ivar_data = (ivar_data_t *) data;
|
|
|
|
|
symbol_t *ivar_sym;
|
|
|
|
|
pr_ivar_t *ivar;
|
|
|
|
|
defspace_t *space;
|
|
|
|
|
|
|
|
|
|
#if 0
|
2020-03-12 10:35:32 +00:00
|
|
|
|
//FIXME the type is dynamic, so need a way to pass it before it can be
|
2011-02-04 06:10:47 +00:00
|
|
|
|
//checked
|
|
|
|
|
if (def->type != &XXX)
|
|
|
|
|
internal_error (0, "%s: expected XXX def",
|
|
|
|
|
__FUNCTION__);
|
|
|
|
|
#endif
|
|
|
|
|
if (index < 0 || index >= ivar_data->count)
|
|
|
|
|
internal_error (0, "%s: out of bounds index: %d %d",
|
|
|
|
|
__FUNCTION__, index, ivar_data->count);
|
|
|
|
|
|
|
|
|
|
for (ivar_sym = ivar_data->ivars; ivar_sym; ivar_sym = ivar_sym->next) {
|
|
|
|
|
if (ivar_sym->sy_type != sy_var)
|
|
|
|
|
continue;
|
|
|
|
|
if (!index--)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivar = D_POINTER (pr_ivar_t, def);
|
|
|
|
|
space = def->space;
|
|
|
|
|
dstring_clearstr (ivar_data->encoding);
|
|
|
|
|
|
|
|
|
|
EMIT_STRING (space, ivar->ivar_name, ivar_sym->name);
|
|
|
|
|
encode_type (ivar_data->encoding, ivar_sym->type);
|
|
|
|
|
EMIT_STRING (space, ivar->ivar_type, ivar_data->encoding->str);
|
|
|
|
|
ivar->ivar_offset = ivar_sym->s.offset;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
|
static def_t *
|
|
|
|
|
emit_ivars (symtab_t *ivars, const char *name)
|
|
|
|
|
{
|
|
|
|
|
static struct_def_t ivar_list_struct[] = {
|
2022-01-18 04:21:06 +00:00
|
|
|
|
{"ivar_count", &type_int, emit_ivar_count},
|
|
|
|
|
{"ivar_list", 0, emit_ivar_list_item},
|
2011-01-24 06:41:43 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
2011-02-14 12:25:55 +00:00
|
|
|
|
ivar_data_t ivar_data = {0, 0, 0};
|
2011-01-24 06:41:43 +00:00
|
|
|
|
symbol_t *s;
|
|
|
|
|
def_t *def;
|
|
|
|
|
|
2011-02-04 06:10:47 +00:00
|
|
|
|
ivar_data.encoding = dstring_newstr ();
|
2011-02-14 12:25:55 +00:00
|
|
|
|
if (ivars) {
|
|
|
|
|
ivar_data.ivars = ivars->symbols;
|
|
|
|
|
for (s = ivars->symbols; s; s = s->next)
|
|
|
|
|
if (s->sy_type == sy_var)
|
|
|
|
|
ivar_data.count++;
|
|
|
|
|
}
|
2020-03-27 06:33:53 +00:00
|
|
|
|
ivar_list_struct[1].type = array_type (&type_ivar, ivar_data.count);
|
2011-01-24 06:41:43 +00:00
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
def = emit_structure (va (0, "_OBJ_INSTANCE_VARIABLES_%s", name), 's',
|
2020-04-03 05:16:16 +00:00
|
|
|
|
ivar_list_struct, 0, &ivar_data, 0, sc_static);
|
2011-02-04 06:10:47 +00:00
|
|
|
|
|
|
|
|
|
dstring_delete (ivar_data.encoding);
|
2011-01-24 06:41:43 +00:00
|
|
|
|
return def;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
static void
|
|
|
|
|
begin_class (class_t *class)
|
|
|
|
|
{
|
|
|
|
|
def_t *meta_def;
|
|
|
|
|
pr_class_t *meta;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
pr_class_t *pr_class;
|
2012-05-21 23:23:22 +00:00
|
|
|
|
symbol_t *sym;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
def_t *def;
|
|
|
|
|
defspace_t *space;
|
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
sym = make_symbol (va (0, "_OBJ_METACLASS_%s", class->name),
|
2020-03-27 06:33:53 +00:00
|
|
|
|
&type_class, pr.far_data, sc_static);
|
2011-01-24 06:41:43 +00:00
|
|
|
|
meta_def = sym->s.def;
|
|
|
|
|
meta_def->initialized = meta_def->constant = meta_def->nosave = 1;
|
|
|
|
|
space = meta_def->space;
|
|
|
|
|
meta = &D_STRUCT (pr_class_t, meta_def);
|
|
|
|
|
EMIT_STRING (space, meta->class_pointer, class->name);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
if (class->super_class)
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_STRING (space, meta->super_class, class->super_class->name);
|
|
|
|
|
EMIT_STRING (space, meta->name, class->name);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
meta->info = _PR_CLS_META;
|
2020-03-27 06:33:53 +00:00
|
|
|
|
meta->instance_size = type_size (&type_class);
|
2013-01-30 09:05:07 +00:00
|
|
|
|
if (!class->super_class) {
|
|
|
|
|
// The ivars list for the meta class struct get emitted only for the
|
|
|
|
|
// root class of the hierachy.
|
2020-03-27 06:33:53 +00:00
|
|
|
|
// NOTE: type_class is not actually a class
|
2013-01-30 09:05:07 +00:00
|
|
|
|
EMIT_DEF (space, meta->ivars,
|
2020-03-27 06:33:53 +00:00
|
|
|
|
emit_ivars (type_class.t.symtab, "Class"));
|
2013-01-30 09:05:07 +00:00
|
|
|
|
} else {
|
|
|
|
|
meta->ivars = 0;
|
|
|
|
|
}
|
2011-01-24 06:41:43 +00:00
|
|
|
|
current_class = &class->class_type;
|
|
|
|
|
sym = class_symbol (current_class, 0);
|
|
|
|
|
class->def = def = sym->s.def;
|
|
|
|
|
def->initialized = def->constant = def->nosave = 1;
|
|
|
|
|
space = def->space;
|
|
|
|
|
|
|
|
|
|
pr_class = &D_STRUCT (pr_class_t, def);
|
|
|
|
|
EMIT_DEF (space, pr_class->class_pointer, meta_def);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
if (class->super_class) {
|
|
|
|
|
class_type_t class_type = {ct_class, {0}};
|
|
|
|
|
class_type.c.class = class->super_class;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_STRING (space, pr_class->super_class, class->super_class->name);
|
|
|
|
|
class_symbol (&class_type, 1);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
}
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_STRING (space, pr_class->name, class->name);
|
|
|
|
|
pr_class->info = _PR_CLS_CLASS;
|
|
|
|
|
EMIT_DEF (space, pr_class->protocols,
|
2010-12-31 06:44:54 +00:00
|
|
|
|
emit_protocol_list (class->protocols, class->name));
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
void
|
2002-11-14 18:17:43 +00:00
|
|
|
|
class_begin (class_type_t *class_type)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2011-03-24 02:39:34 +00:00
|
|
|
|
if (current_class) {
|
|
|
|
|
warning (0, "‘@end’ missing in implementation context");
|
|
|
|
|
class_finish (current_class);
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2010-12-31 06:44:54 +00:00
|
|
|
|
switch (class_type->type) {
|
|
|
|
|
case ct_category:
|
|
|
|
|
begin_category (class_type->c.category);
|
|
|
|
|
break;
|
|
|
|
|
case ct_class:
|
|
|
|
|
begin_class (class_type->c.class);
|
|
|
|
|
break;
|
|
|
|
|
case ct_protocol:
|
|
|
|
|
return; // probably error recovery
|
2002-05-16 22:33:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-12 11:27:56 +00:00
|
|
|
|
void
|
2003-03-13 19:16:45 +00:00
|
|
|
|
emit_class_ref (const char *class_name)
|
|
|
|
|
{
|
2011-02-11 06:42:37 +00:00
|
|
|
|
symbol_t *ref_sym;
|
|
|
|
|
symbol_t *name_sym;
|
|
|
|
|
def_t *ref_def;
|
|
|
|
|
def_t *name_def;
|
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
ref_sym = make_symbol (va (0, ".obj_class_ref_%s", class_name),
|
2022-01-18 13:34:52 +00:00
|
|
|
|
&type_ptr, pr.far_data, sc_static);
|
2011-02-11 06:42:37 +00:00
|
|
|
|
if (!ref_sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, ref_sym);
|
|
|
|
|
ref_def = ref_sym->s.def;
|
|
|
|
|
if (ref_def->initialized)
|
2003-03-13 19:16:45 +00:00
|
|
|
|
return;
|
2011-02-11 06:42:37 +00:00
|
|
|
|
ref_def->initialized = ref_def->constant = ref_def->nosave = 1;
|
2021-01-31 07:01:20 +00:00
|
|
|
|
name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name),
|
2022-01-18 13:34:52 +00:00
|
|
|
|
&type_ptr, pr.far_data, sc_extern);
|
2011-02-11 06:42:37 +00:00
|
|
|
|
if (!name_sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, name_sym);
|
|
|
|
|
name_def = name_sym->s.def;
|
|
|
|
|
if (!name_def->external)
|
|
|
|
|
D_INT (ref_def) = name_def->offset;
|
2011-02-12 13:34:38 +00:00
|
|
|
|
reloc_def_def (name_def, ref_def);
|
2003-03-13 19:16:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
static void
|
2003-03-13 19:16:45 +00:00
|
|
|
|
emit_class_name (const char *class_name)
|
|
|
|
|
{
|
2011-02-11 06:42:37 +00:00
|
|
|
|
symbol_t *name_sym;
|
|
|
|
|
def_t *name_def;
|
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name),
|
2022-01-18 13:34:52 +00:00
|
|
|
|
&type_ptr, pr.far_data, sc_global);
|
2011-02-11 06:42:37 +00:00
|
|
|
|
if (!name_sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, name_sym);
|
|
|
|
|
name_def = name_sym->s.def;
|
|
|
|
|
if (name_def->initialized)
|
2003-03-13 19:16:45 +00:00
|
|
|
|
return;
|
2011-02-11 06:42:37 +00:00
|
|
|
|
name_def->initialized = name_def->constant = 1;
|
|
|
|
|
name_def->nosave = 1;
|
|
|
|
|
D_INT (name_def) = 0;
|
2003-03-13 19:16:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-12 11:27:56 +00:00
|
|
|
|
void
|
|
|
|
|
emit_category_ref (const char *class_name, const char *category_name)
|
|
|
|
|
{
|
2011-02-11 06:42:37 +00:00
|
|
|
|
symbol_t *ref_sym;
|
|
|
|
|
symbol_t *name_sym;
|
|
|
|
|
def_t *ref_def;
|
|
|
|
|
def_t *name_def;
|
2010-12-12 11:27:56 +00:00
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
ref_sym = make_symbol (va (0, ".obj_category_ref_%s_%s",
|
|
|
|
|
class_name, category_name),
|
2022-01-18 13:34:52 +00:00
|
|
|
|
&type_ptr, pr.far_data, sc_static);
|
2011-02-11 06:42:37 +00:00
|
|
|
|
if (!ref_sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, ref_sym);
|
|
|
|
|
ref_def = ref_sym->s.def;
|
|
|
|
|
if (ref_def->initialized)
|
2010-12-12 11:27:56 +00:00
|
|
|
|
return;
|
2011-02-11 06:42:37 +00:00
|
|
|
|
ref_def->initialized = ref_def->constant = 1;
|
|
|
|
|
ref_def->nosave = 1;
|
2021-01-31 07:01:20 +00:00
|
|
|
|
name_sym = make_symbol (va (0, ".obj_category_name_%s_%s",
|
|
|
|
|
class_name, category_name),
|
2022-01-18 13:34:52 +00:00
|
|
|
|
&type_ptr, pr.far_data, sc_extern);
|
2011-02-11 06:42:37 +00:00
|
|
|
|
if (!name_sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, name_sym);
|
|
|
|
|
name_def = name_sym->s.def;
|
|
|
|
|
if (!name_def->external)
|
|
|
|
|
D_INT (ref_def) = name_def->offset;
|
2011-02-12 13:34:38 +00:00
|
|
|
|
reloc_def_def (name_def, ref_def);
|
2010-12-12 11:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
static void
|
2003-03-13 19:16:45 +00:00
|
|
|
|
emit_category_name (const char *class_name, const char *category_name)
|
|
|
|
|
{
|
2011-02-11 06:42:37 +00:00
|
|
|
|
symbol_t *name_sym;
|
|
|
|
|
def_t *name_def;
|
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
name_sym = make_symbol (va (0, ".obj_category_name_%s_%s",
|
2011-02-11 06:42:37 +00:00
|
|
|
|
class_name, category_name),
|
2022-01-18 13:34:52 +00:00
|
|
|
|
&type_ptr, pr.far_data, sc_global);
|
2011-02-11 06:42:37 +00:00
|
|
|
|
if (!name_sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, name_sym);
|
|
|
|
|
name_def = name_sym->s.def;
|
|
|
|
|
if (name_def->initialized)
|
2003-03-13 19:16:45 +00:00
|
|
|
|
return;
|
2011-02-11 06:42:37 +00:00
|
|
|
|
name_def->initialized = name_def->constant = 1;
|
|
|
|
|
name_def->nosave = 1;
|
|
|
|
|
D_INT (name_def) = 0;
|
2003-03-13 19:16:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
static void
|
|
|
|
|
finish_category (category_t *category)
|
2002-05-16 22:33:11 +00:00
|
|
|
|
{
|
2010-12-31 06:44:54 +00:00
|
|
|
|
pr_category_t *pr_category;
|
|
|
|
|
class_t *class = category->class;
|
|
|
|
|
char *name;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
defspace_t *space;
|
2003-07-24 19:41:59 +00:00
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
if (!category->def) // probably in error recovery
|
|
|
|
|
return;
|
|
|
|
|
name = nva ("%s_%s", class->name, category->name);
|
2011-01-24 06:41:43 +00:00
|
|
|
|
pr_category = &D_STRUCT (pr_category_t, category->def);
|
|
|
|
|
space = category->def->space;
|
|
|
|
|
EMIT_DEF (space, pr_category->instance_methods,
|
2010-12-31 06:44:54 +00:00
|
|
|
|
emit_methods (category->methods, name, 1));
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_DEF (space, pr_category->class_methods,
|
2010-12-31 06:44:54 +00:00
|
|
|
|
emit_methods (category->methods, name, 0));
|
|
|
|
|
free (name);
|
|
|
|
|
emit_class_ref (class->name);
|
|
|
|
|
emit_category_name (class->name, category->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
finish_class (class_t *class)
|
|
|
|
|
{
|
|
|
|
|
pr_class_t *meta;
|
|
|
|
|
pr_class_t *cls;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
defspace_t *space;
|
2002-05-16 22:33:11 +00:00
|
|
|
|
|
2012-12-22 10:35:19 +00:00
|
|
|
|
if (pr.error_count) // probably in error recovery
|
2010-12-31 06:44:54 +00:00
|
|
|
|
return;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
space = class->def->space;
|
|
|
|
|
cls = &D_STRUCT (pr_class_t, class->def);
|
2002-05-16 22:33:11 +00:00
|
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
|
meta = &G_STRUCT (space, pr_class_t, cls->class_pointer);
|
2010-12-31 06:44:54 +00:00
|
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_DEF (space, meta->methods, emit_methods (class->methods,
|
|
|
|
|
class->name, 0));
|
2010-12-31 06:44:54 +00:00
|
|
|
|
|
2011-03-08 13:45:34 +00:00
|
|
|
|
cls->instance_size = type_size (class->type);
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_DEF (space, cls->ivars, emit_ivars (class->ivars, class->name));
|
|
|
|
|
EMIT_DEF (space, cls->methods, emit_methods (class->methods,
|
|
|
|
|
class->name, 1));
|
2010-12-31 06:44:54 +00:00
|
|
|
|
if (class->super_class)
|
|
|
|
|
emit_class_ref (class->super_class->name);
|
|
|
|
|
emit_class_name (class->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
class_finish (class_type_t *class_type)
|
|
|
|
|
{
|
|
|
|
|
switch (class_type->type) {
|
|
|
|
|
case ct_category:
|
|
|
|
|
finish_category (class_type->c.category);
|
|
|
|
|
break;
|
|
|
|
|
case ct_class:
|
|
|
|
|
finish_class (class_type->c.class);
|
|
|
|
|
break;
|
|
|
|
|
case ct_protocol:
|
|
|
|
|
return; // probably in error recovery
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-05-16 22:33:11 +00:00
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_t *
|
|
|
|
|
extract_class (class_type_t *class_type)
|
|
|
|
|
{
|
|
|
|
|
switch (class_type->type) {
|
|
|
|
|
case ct_class:
|
|
|
|
|
return current_class->c.class;
|
|
|
|
|
case ct_category:
|
|
|
|
|
return current_class->c.category->class;
|
|
|
|
|
case ct_protocol:
|
|
|
|
|
return 0; // probably in error recovery
|
2002-05-15 23:24:19 +00:00
|
|
|
|
}
|
2010-12-31 06:44:54 +00:00
|
|
|
|
return 0; // should not happen
|
2002-05-15 23:24:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
int
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_access (class_type_t *class_type, class_t *class)
|
2002-11-14 18:17:43 +00:00
|
|
|
|
{
|
2004-11-13 01:37:00 +00:00
|
|
|
|
class_t *cur;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
if (class_type) {
|
|
|
|
|
if (!(cur = extract_class (class_type)))
|
|
|
|
|
return vis_private;
|
2004-11-13 01:37:00 +00:00
|
|
|
|
if (cur == class)
|
|
|
|
|
return vis_private;
|
|
|
|
|
cur = cur->super_class;
|
|
|
|
|
while (cur) {
|
|
|
|
|
if (cur == class)
|
|
|
|
|
return vis_protected;
|
|
|
|
|
cur = cur->super_class;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return vis_public;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
symbol_t *
|
2004-11-13 01:37:00 +00:00
|
|
|
|
class_find_ivar (class_t *class, int vis, const char *name)
|
2002-05-17 06:20:27 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
symbol_t *ivar;
|
2002-05-17 06:20:27 +00:00
|
|
|
|
|
2020-03-01 08:43:28 +00:00
|
|
|
|
if (!class->ivars) {
|
2020-03-05 06:39:34 +00:00
|
|
|
|
if (!class->interface_declared) {
|
|
|
|
|
class->interface_declared = 1;
|
|
|
|
|
error (0, "accessing incomplete type %s", class->name);
|
|
|
|
|
}
|
2020-03-01 08:43:28 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
ivar = symtab_lookup (class->ivars, name);
|
|
|
|
|
if (ivar) {
|
2020-03-05 09:45:47 +00:00
|
|
|
|
if (ivar->visibility > (vis_t) vis
|
|
|
|
|
|| (ivar->table->class != class
|
|
|
|
|
&& ivar->visibility > vis_protected)) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
goto access_error;
|
2020-03-05 09:45:47 +00:00
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
return ivar;
|
2002-05-17 06:20:27 +00:00
|
|
|
|
}
|
2002-11-12 19:52:43 +00:00
|
|
|
|
error (0, "%s.%s does not exist", class->name, name);
|
2002-05-17 06:20:27 +00:00
|
|
|
|
return 0;
|
2003-07-24 19:41:59 +00:00
|
|
|
|
access_error:
|
2002-11-12 19:52:43 +00:00
|
|
|
|
error (0, "%s.%s is not accessable here", class->name, name);
|
2002-05-17 19:35:26 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
method_t *
|
2002-11-14 18:17:43 +00:00
|
|
|
|
class_find_method (class_type_t *class_type, method_t *method)
|
2002-05-15 23:24:19 +00:00
|
|
|
|
{
|
2010-12-31 06:44:54 +00:00
|
|
|
|
methodlist_t *methods = 0, *start_methods;
|
2002-05-15 23:24:19 +00:00
|
|
|
|
method_t *m;
|
|
|
|
|
dstring_t *sel;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_t *class = 0, *start_class;
|
2002-05-15 23:24:19 +00:00
|
|
|
|
|
2010-12-31 06:44:54 +00:00
|
|
|
|
switch (class_type->type) {
|
|
|
|
|
case ct_category:
|
|
|
|
|
methods = class_type->c.category->methods;
|
|
|
|
|
class = class_type->c.category->class;
|
|
|
|
|
break;
|
|
|
|
|
case ct_class:
|
|
|
|
|
class = class_type->c.class;
|
|
|
|
|
methods = class->methods;
|
|
|
|
|
break;
|
|
|
|
|
case ct_protocol:
|
|
|
|
|
return 0; // probably in error recovery
|
2003-08-01 05:08:15 +00:00
|
|
|
|
}
|
|
|
|
|
start_methods = methods;
|
|
|
|
|
start_class = class;
|
|
|
|
|
while (class) {
|
2020-03-01 04:53:18 +00:00
|
|
|
|
for (m = methods->head; m; m = m->next) {
|
2003-08-01 05:08:15 +00:00
|
|
|
|
if (method_compare (method, m)) {
|
|
|
|
|
if (m->type != method->type)
|
|
|
|
|
error (0, "method type mismatch");
|
|
|
|
|
if (methods != start_methods) {
|
|
|
|
|
m = copy_method (m);
|
2004-11-02 11:56:00 +00:00
|
|
|
|
set_self_type (start_class, m);
|
2003-08-01 16:24:44 +00:00
|
|
|
|
add_method (start_methods, m);
|
2003-08-01 05:08:15 +00:00
|
|
|
|
}
|
2004-11-02 11:56:00 +00:00
|
|
|
|
method_set_param_names (m, method);
|
2003-08-01 05:08:15 +00:00
|
|
|
|
return m;
|
|
|
|
|
}
|
2020-03-01 04:53:18 +00:00
|
|
|
|
}
|
2003-08-01 05:08:15 +00:00
|
|
|
|
if (class->methods == methods)
|
|
|
|
|
class = class->super_class;
|
|
|
|
|
else
|
|
|
|
|
methods = class->methods;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
}
|
2002-05-15 23:24:19 +00:00
|
|
|
|
sel = dstring_newstr ();
|
|
|
|
|
selector_name (sel, (keywordarg_t *)method->selector);
|
2004-11-02 11:56:00 +00:00
|
|
|
|
set_self_type (start_class, method);
|
2004-02-03 07:48:23 +00:00
|
|
|
|
add_method (start_methods, method);
|
2002-05-15 23:24:19 +00:00
|
|
|
|
dstring_delete (sel);
|
|
|
|
|
return method;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-15 14:30:57 +00:00
|
|
|
|
static method_t *
|
|
|
|
|
cls_find_method (methodlist_t *methodlist, selector_t *selector,
|
|
|
|
|
int class_msg, int is_root)
|
|
|
|
|
{
|
|
|
|
|
method_t *m = 0;
|
|
|
|
|
m = methodlist_find_method (methodlist, selector, !class_msg);
|
|
|
|
|
if (!m && is_root && class_msg
|
|
|
|
|
&& (m = methodlist_find_method (methodlist, selector, 1))) {
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
method_t *
|
2020-03-15 14:30:57 +00:00
|
|
|
|
class_message_response (type_t *clstype, int class_msg, expr_t *sel)
|
2002-05-16 20:20:23 +00:00
|
|
|
|
{
|
2003-08-23 06:15:19 +00:00
|
|
|
|
selector_t *selector;
|
2002-05-16 20:20:23 +00:00
|
|
|
|
method_t *m;
|
2020-03-15 14:30:57 +00:00
|
|
|
|
class_t *c;
|
|
|
|
|
class_t *class = 0;
|
2002-11-12 19:52:43 +00:00
|
|
|
|
category_t *cat;
|
2020-03-15 14:30:57 +00:00
|
|
|
|
dstring_t *dstr;
|
2002-05-16 20:20:23 +00:00
|
|
|
|
|
2003-08-23 06:15:19 +00:00
|
|
|
|
selector = get_selector (sel);
|
2011-02-15 01:48:05 +00:00
|
|
|
|
if (!selector)
|
|
|
|
|
return 0;
|
2020-03-15 14:30:57 +00:00
|
|
|
|
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!is_classptr (clstype) && !is_class (clstype)) {
|
2020-03-15 14:30:57 +00:00
|
|
|
|
error (0, "neither class nor object");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_id (clstype)) {
|
2020-03-15 14:30:57 +00:00
|
|
|
|
protocollist_t *protos = clstype->t.fldptr.type->protos;
|
|
|
|
|
if (protos) {
|
|
|
|
|
if ((m = protocollist_find_method (protos, selector, !class_msg))) {
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
dstr = dstring_new ();
|
|
|
|
|
print_protocollist (dstr, protos);
|
|
|
|
|
warning (sel, "id%s may not respond to %c%s", dstr->str,
|
|
|
|
|
class_msg ? '+' : '-', selector->name);
|
|
|
|
|
dstring_delete (dstr);
|
2020-03-05 06:39:34 +00:00
|
|
|
|
}
|
2020-03-15 14:30:57 +00:00
|
|
|
|
} else {
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (is_class (clstype)) {
|
2020-03-15 14:30:57 +00:00
|
|
|
|
class = clstype->t.class;
|
2020-03-27 06:16:41 +00:00
|
|
|
|
} else if (is_class (clstype->t.fldptr.type)) {
|
2020-03-15 14:30:57 +00:00
|
|
|
|
class = clstype->t.fldptr.type->t.class;
|
|
|
|
|
}
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (class && !is_object(class->type)) {
|
2020-03-15 14:30:57 +00:00
|
|
|
|
if (!class->interface_declared) {
|
|
|
|
|
class->interface_declared = 1;
|
|
|
|
|
warning (0, "cannot find interface declaration for `%s'",
|
|
|
|
|
class->name);
|
|
|
|
|
}
|
|
|
|
|
c = class;
|
|
|
|
|
while (c) {
|
|
|
|
|
for (cat = c->categories; cat; cat = cat->next) {
|
|
|
|
|
if ((m = cls_find_method (cat->methods, selector,
|
|
|
|
|
class_msg,
|
|
|
|
|
!c->super_class))) {
|
2002-11-12 19:52:43 +00:00
|
|
|
|
return m;
|
2020-03-15 14:30:57 +00:00
|
|
|
|
}
|
2002-11-12 19:52:43 +00:00
|
|
|
|
}
|
2020-03-15 14:30:57 +00:00
|
|
|
|
if ((m = cls_find_method (c->methods, selector, class_msg,
|
|
|
|
|
!c->super_class))) {
|
2004-11-02 11:56:00 +00:00
|
|
|
|
return m;
|
2020-03-15 14:30:57 +00:00
|
|
|
|
}
|
|
|
|
|
c = c->super_class;
|
2004-11-02 11:56:00 +00:00
|
|
|
|
}
|
2020-03-15 14:30:57 +00:00
|
|
|
|
warning (sel, "%s may not respond to %c%s", class->name,
|
|
|
|
|
class_msg ? '+' : '-', selector->name);
|
2002-05-16 20:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-09 10:18:09 +00:00
|
|
|
|
m = find_method (selector->name);
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!m && (!class || is_object(class->type))) {
|
2012-11-09 10:18:09 +00:00
|
|
|
|
warning (sel, "could not find method for %c%s",
|
|
|
|
|
class_msg ? '+' : '-', selector->name);
|
2020-03-05 05:48:53 +00:00
|
|
|
|
}
|
|
|
|
|
return m;
|
2002-05-16 20:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-04-04 11:22:48 +00:00
|
|
|
|
static uintptr_t
|
2012-07-18 13:34:37 +00:00
|
|
|
|
category_get_hash (const void *_c, void *unused)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2002-11-12 19:52:43 +00:00
|
|
|
|
category_t *c = (category_t *) _c;
|
|
|
|
|
return Hash_String (c->name) ^ Hash_String (c->class->name);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
static int
|
2012-07-18 13:34:37 +00:00
|
|
|
|
category_compare (const void *_c1, const void *_c2, void *unused)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2002-11-12 19:52:43 +00:00
|
|
|
|
category_t *c1 = (category_t *) _c1;
|
|
|
|
|
category_t *c2 = (category_t *) _c2;
|
|
|
|
|
return strcmp (c1->name, c2->name) == 0
|
2003-07-24 19:41:59 +00:00
|
|
|
|
&& strcmp (c1->class->name, c2->class->name) == 0;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
symtab_t *
|
2003-07-30 04:11:45 +00:00
|
|
|
|
class_new_ivars (class_t *class)
|
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
symtab_t *ivars;
|
|
|
|
|
symtab_t *super_ivars = 0;
|
2012-05-21 23:23:22 +00:00
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
if (class->super_class)
|
|
|
|
|
super_ivars = class->super_class->ivars;
|
|
|
|
|
ivars = new_symtab (super_ivars, stab_local);
|
2020-03-05 09:45:47 +00:00
|
|
|
|
ivars->class = class;
|
2003-07-30 04:11:45 +00:00
|
|
|
|
return ivars;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
void
|
2011-01-17 13:33:33 +00:00
|
|
|
|
class_add_ivars (class_t *class, symtab_t *ivars)
|
2002-05-17 06:20:27 +00:00
|
|
|
|
{
|
2011-02-09 13:02:52 +00:00
|
|
|
|
int base = 0;
|
|
|
|
|
symbol_t *sym;
|
|
|
|
|
|
|
|
|
|
if (class->super_class)
|
|
|
|
|
base = type_size (class->super_class->type);
|
|
|
|
|
for (sym = ivars->symbols; sym; sym = sym->next)
|
|
|
|
|
sym->s.offset += base;
|
2002-05-17 06:20:27 +00:00
|
|
|
|
class->ivars = ivars;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-03 06:02:26 +00:00
|
|
|
|
static int
|
|
|
|
|
compare_symbols (symbol_t *s1, symbol_t *s2)
|
|
|
|
|
{
|
|
|
|
|
if (s1->visibility != s2->visibility)
|
|
|
|
|
return 0;
|
|
|
|
|
if (s1->name != s2->name) // works thanks to save_string
|
|
|
|
|
return 0;
|
|
|
|
|
if (s1->sy_type != s2->sy_type)
|
|
|
|
|
return 0;
|
|
|
|
|
if (s1->type != s2->type)
|
|
|
|
|
return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
void
|
2011-01-17 13:33:33 +00:00
|
|
|
|
class_check_ivars (class_t *class, symtab_t *ivars)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2011-01-24 12:13:37 +00:00
|
|
|
|
symbol_t *civ, *iv;
|
2011-03-20 04:33:42 +00:00
|
|
|
|
int missmatch = 0;
|
2011-01-24 12:13:37 +00:00
|
|
|
|
|
2011-03-20 04:33:42 +00:00
|
|
|
|
if (!class->ivars != !ivars) {
|
|
|
|
|
missmatch = 1;
|
|
|
|
|
} else if (ivars) {
|
2011-01-24 12:13:37 +00:00
|
|
|
|
for (civ = class->ivars->symbols, iv = ivars->symbols;
|
|
|
|
|
civ && iv; civ = civ->next, iv = iv->next) {
|
2011-03-20 04:33:42 +00:00
|
|
|
|
if (!compare_symbols (civ, iv)) {
|
|
|
|
|
missmatch = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-01-24 12:13:37 +00:00
|
|
|
|
}
|
2004-02-17 00:39:21 +00:00
|
|
|
|
}
|
2011-01-24 12:13:37 +00:00
|
|
|
|
//FIXME right option?
|
2011-03-20 04:33:42 +00:00
|
|
|
|
if (missmatch && options.warnings.interface_check)
|
2011-01-24 12:13:37 +00:00
|
|
|
|
warning (0, "instance variable missmatch for %s", class->name);
|
2011-03-20 04:33:42 +00:00
|
|
|
|
class_add_ivars (class, ivars);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
category_t *
|
2011-01-17 13:33:33 +00:00
|
|
|
|
get_category (symbol_t *class_name, const char *category_name, int create)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2002-11-14 18:17:43 +00:00
|
|
|
|
category_t *category;
|
2002-11-12 19:52:43 +00:00
|
|
|
|
class_t *class;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
|
|
|
|
|
if (!category_hash) {
|
2020-03-25 06:43:16 +00:00
|
|
|
|
category_hash = Hash_NewTable (1021, 0, 0, 0, 0);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
Hash_SetHashCompare (category_hash,
|
2003-07-24 19:41:59 +00:00
|
|
|
|
category_get_hash, category_compare);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
2002-11-12 19:52:43 +00:00
|
|
|
|
class = get_class (class_name, 0);
|
|
|
|
|
if (!class) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
error (0, "undefined class %s", class_name->name);
|
2002-11-14 18:17:43 +00:00
|
|
|
|
return 0;
|
2002-11-12 19:52:43 +00:00
|
|
|
|
}
|
2002-05-15 19:10:23 +00:00
|
|
|
|
if (class_name && category_name) {
|
2002-11-14 18:17:43 +00:00
|
|
|
|
category_t _c = {0, category_name, class};
|
|
|
|
|
|
|
|
|
|
category = Hash_FindElement (category_hash, &_c);
|
|
|
|
|
if (category || !create)
|
|
|
|
|
return category;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-11-14 18:17:43 +00:00
|
|
|
|
category = calloc (sizeof (category_t), 1);
|
|
|
|
|
category->next = class->categories;
|
|
|
|
|
class->categories = category;
|
|
|
|
|
category->name = category_name;
|
|
|
|
|
category->class = class;
|
2004-11-02 11:56:00 +00:00
|
|
|
|
category->methods = new_methodlist ();
|
2010-12-31 06:44:54 +00:00
|
|
|
|
category->class_type.type = ct_category;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
category->class_type.c.category = category;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
if (class_name && category_name)
|
2002-11-14 18:17:43 +00:00
|
|
|
|
Hash_AddElement (category_hash, category);
|
|
|
|
|
return category;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
void
|
2002-11-14 18:17:43 +00:00
|
|
|
|
category_add_methods (category_t *category, methodlist_t *methods)
|
|
|
|
|
{
|
|
|
|
|
if (!methods)
|
|
|
|
|
return;
|
2020-03-02 15:11:54 +00:00
|
|
|
|
merge_method_lists (category->methods, methods);
|
2004-11-02 11:56:00 +00:00
|
|
|
|
|
|
|
|
|
methods_set_self_type (category->class, category->methods);
|
2002-11-14 18:17:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
void
|
2004-11-11 00:34:00 +00:00
|
|
|
|
category_add_protocols (category_t *category, protocollist_t *protocols)
|
2002-11-14 18:17:43 +00:00
|
|
|
|
{
|
2004-11-11 00:34:00 +00:00
|
|
|
|
int i;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
protocol_t *p;
|
2004-11-11 00:34:00 +00:00
|
|
|
|
methodlist_t *methods;
|
2020-03-05 03:52:37 +00:00
|
|
|
|
methodset_t *except;
|
|
|
|
|
class_t *class;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
if (!protocols)
|
|
|
|
|
return;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
methods = category->methods;
|
2002-11-14 18:17:43 +00:00
|
|
|
|
|
2020-03-05 03:52:37 +00:00
|
|
|
|
except = new_methodset ();
|
|
|
|
|
for (class = category->class; class; class = class->super_class) {
|
|
|
|
|
methodset_add_methods (except, class->methods);
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
for (i = 0; i < protocols->count; i++) {
|
|
|
|
|
p = protocols->list[i];
|
2020-03-05 03:52:37 +00:00
|
|
|
|
copy_methods (methods, p->methods, except);
|
2004-11-11 00:34:00 +00:00
|
|
|
|
if (p->protocols)
|
|
|
|
|
category_add_protocols (category, p->protocols);
|
2002-11-14 18:17:43 +00:00
|
|
|
|
}
|
2004-11-11 00:34:00 +00:00
|
|
|
|
category->protocols = protocols;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-06 05:33:52 +00:00
|
|
|
|
symbol_t *
|
|
|
|
|
class_pointer_symbol (class_t *class)
|
2002-05-10 00:00:23 +00:00
|
|
|
|
{
|
2002-05-16 22:33:11 +00:00
|
|
|
|
def_t *def;
|
2011-02-06 05:33:52 +00:00
|
|
|
|
symbol_t *sym;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
class_type_t class_type = {ct_class, {0}};
|
2002-11-14 18:17:43 +00:00
|
|
|
|
|
|
|
|
|
class_type.c.class = class;
|
2002-05-16 22:33:11 +00:00
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
sym = make_symbol (va (0, "_OBJ_CLASS_POINTER_%s", class->name),
|
|
|
|
|
&type_Class, pr.near_data, sc_static);
|
2011-02-06 07:56:19 +00:00
|
|
|
|
if (!sym->table)
|
|
|
|
|
symtab_addsymbol (pr.symtab, sym);
|
2011-02-06 05:33:52 +00:00
|
|
|
|
def = sym->s.def;
|
2002-05-17 18:46:11 +00:00
|
|
|
|
if (def->initialized)
|
2011-02-06 05:33:52 +00:00
|
|
|
|
return sym;
|
2002-05-17 18:46:11 +00:00
|
|
|
|
def->initialized = def->constant = 1;
|
2003-04-25 17:00:22 +00:00
|
|
|
|
def->nosave = 1;
|
2002-07-03 20:16:32 +00:00
|
|
|
|
if (!class->def)
|
2011-01-24 06:41:43 +00:00
|
|
|
|
class->def = class_symbol (&class_type, 1)->s.def;
|
2002-07-03 20:16:32 +00:00
|
|
|
|
if (!class->def->external)
|
2011-01-24 06:41:43 +00:00
|
|
|
|
D_INT (def) = class->def->offset;
|
2011-02-12 13:34:38 +00:00
|
|
|
|
reloc_def_def (class->def, def);
|
2011-02-06 05:33:52 +00:00
|
|
|
|
return sym;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-01-24 12:13:37 +00:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
def_t *refs;
|
|
|
|
|
class_t **classes;
|
|
|
|
|
int cls_def_cnt;
|
|
|
|
|
category_t **categories;
|
|
|
|
|
int cat_def_cnt;
|
2020-03-02 01:48:51 +00:00
|
|
|
|
def_t *instances_list;
|
2011-01-24 12:13:37 +00:00
|
|
|
|
} obj_symtab_data_t;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_symtab_ref_cnt (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_symtab_data_t *da = (obj_symtab_data_t *)data;
|
|
|
|
|
|
2022-01-18 04:21:06 +00:00
|
|
|
|
if (!is_int(def->type))
|
|
|
|
|
internal_error (0, "%s: expected int def", __FUNCTION__);
|
2011-02-08 13:28:32 +00:00
|
|
|
|
D_INT (def) = 0;
|
|
|
|
|
if (da->refs)
|
|
|
|
|
D_INT (def) = da->refs->type->t.array.size;
|
2011-01-24 12:13:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_symtab_refs (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_symtab_data_t *da = (obj_symtab_data_t *)data;
|
|
|
|
|
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!is_SEL(def->type))
|
2011-01-24 12:13:37 +00:00
|
|
|
|
internal_error (0, "%s: expected SEL def", __FUNCTION__);
|
2011-02-08 13:28:32 +00:00
|
|
|
|
D_INT (def) = 0;
|
|
|
|
|
if (da->refs)
|
2011-02-09 06:58:32 +00:00
|
|
|
|
EMIT_DEF (def->space, D_INT (def), da->refs);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_symtab_cls_def_cnt (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_symtab_data_t *da = (obj_symtab_data_t *)data;
|
|
|
|
|
|
2022-01-18 04:21:06 +00:00
|
|
|
|
if (!is_int(def->type))
|
|
|
|
|
internal_error (0, "%s: expected int def", __FUNCTION__);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
D_INT (def) = da->cls_def_cnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_symtab_cat_def_cnt (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_symtab_data_t *da = (obj_symtab_data_t *)data;
|
|
|
|
|
|
2022-01-18 04:21:06 +00:00
|
|
|
|
if (!is_int(def->type))
|
|
|
|
|
internal_error (0, "%s: expected int def", __FUNCTION__);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
D_INT (def) = da->cat_def_cnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_symtab_defs (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
obj_symtab_data_t *da = (obj_symtab_data_t *)data;
|
|
|
|
|
|
2022-01-18 05:36:06 +00:00
|
|
|
|
if (!is_array (def->type) || def->type->t.array.type->type != ev_ptr)
|
2011-02-08 13:31:09 +00:00
|
|
|
|
internal_error (0, "%s: expected array of pointers def", __FUNCTION__);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt + 1)
|
2011-01-24 12:13:37 +00:00
|
|
|
|
internal_error (0, "%s: out of bounds index: %d %d",
|
|
|
|
|
__FUNCTION__, index,
|
2020-03-02 01:48:51 +00:00
|
|
|
|
da->cls_def_cnt + da->cat_def_cnt + 1);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
|
|
|
|
|
if (index < da->cls_def_cnt) {
|
2011-02-13 04:21:00 +00:00
|
|
|
|
class_t **cl;
|
|
|
|
|
for (cl = da->classes; *cl; cl++)
|
|
|
|
|
if ((*cl)->def && !(*cl)->def->external)
|
|
|
|
|
if (!index--)
|
|
|
|
|
break;
|
|
|
|
|
EMIT_DEF (def->space, D_INT (def), (*cl)->def);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
} else if (index < da->cls_def_cnt + da->cat_def_cnt) {
|
2011-02-13 04:21:00 +00:00
|
|
|
|
category_t **ca;
|
|
|
|
|
index -= da->cls_def_cnt;
|
|
|
|
|
for (ca = da->categories; *ca; ca++)
|
|
|
|
|
if ((*ca)->def && !(*ca)->def->external)
|
|
|
|
|
if (!index--)
|
|
|
|
|
break;
|
|
|
|
|
EMIT_DEF (def->space, D_INT (def), (*ca)->def);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
} else {
|
|
|
|
|
D_INT (def) = 0;
|
|
|
|
|
if (da->instances_list) {
|
|
|
|
|
EMIT_DEF (def->space, D_INT (def), da->instances_list);
|
|
|
|
|
}
|
2011-01-24 12:13:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-27 18:50:17 +00:00
|
|
|
|
void
|
2002-05-21 21:28:40 +00:00
|
|
|
|
class_finish_module (void)
|
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
static struct_def_t symtab_struct[] = {
|
2022-01-18 04:21:06 +00:00
|
|
|
|
{"sel_ref_cnt", &type_int, emit_symtab_ref_cnt},
|
|
|
|
|
{"refs", &type_SEL, emit_symtab_refs},
|
|
|
|
|
{"cls_def_cnt", &type_int, emit_symtab_cls_def_cnt},
|
|
|
|
|
{"cat_def_cnt", &type_int, emit_symtab_cat_def_cnt},
|
|
|
|
|
{"defs", 0, emit_symtab_defs},
|
2011-01-17 13:33:33 +00:00
|
|
|
|
{0, 0}
|
|
|
|
|
};
|
2011-01-24 12:13:37 +00:00
|
|
|
|
|
2020-03-02 01:48:51 +00:00
|
|
|
|
obj_symtab_data_t data = {};
|
2011-01-24 12:13:37 +00:00
|
|
|
|
|
|
|
|
|
class_t **cl;
|
|
|
|
|
category_t **ca;
|
2002-05-21 21:28:40 +00:00
|
|
|
|
def_t *symtab_def;
|
2011-01-19 13:19:26 +00:00
|
|
|
|
symbol_t *module_sym;
|
2018-10-12 12:09:36 +00:00
|
|
|
|
expr_t *module_expr;
|
2011-01-24 12:13:37 +00:00
|
|
|
|
pr_module_t *module;
|
2011-01-19 13:19:26 +00:00
|
|
|
|
symbol_t *exec_class_sym;
|
|
|
|
|
symbol_t *init_sym;
|
2002-05-21 21:28:40 +00:00
|
|
|
|
expr_t *init_expr;
|
|
|
|
|
|
2011-01-24 12:13:37 +00:00
|
|
|
|
data.refs = emit_selectors ();
|
2002-05-21 21:28:40 +00:00
|
|
|
|
if (class_hash) {
|
2011-01-24 12:13:37 +00:00
|
|
|
|
data.classes = (class_t **) Hash_GetList (class_hash);
|
|
|
|
|
for (cl = data.classes; *cl; cl++)
|
2002-11-14 18:17:43 +00:00
|
|
|
|
if ((*cl)->def && !(*cl)->def->external)
|
2011-01-24 12:13:37 +00:00
|
|
|
|
data.cls_def_cnt++;
|
2002-05-21 21:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
if (category_hash) {
|
2011-01-24 12:13:37 +00:00
|
|
|
|
data.categories = (category_t **) Hash_GetList (category_hash);
|
|
|
|
|
for (ca = data.categories; *ca; ca++)
|
2002-11-14 18:17:43 +00:00
|
|
|
|
if ((*ca)->def && !(*ca)->def->external)
|
2011-01-24 12:13:37 +00:00
|
|
|
|
data.cat_def_cnt++;
|
2002-05-21 21:28:40 +00:00
|
|
|
|
}
|
2020-03-02 01:48:51 +00:00
|
|
|
|
data.instances_list = emit_static_instances_list ();
|
|
|
|
|
if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt
|
|
|
|
|
&& !data.instances_list)
|
2002-05-21 21:28:40 +00:00
|
|
|
|
return;
|
2022-01-18 13:34:52 +00:00
|
|
|
|
symtab_struct[4].type = array_type (&type_ptr,
|
2020-03-02 01:48:51 +00:00
|
|
|
|
data.cls_def_cnt
|
|
|
|
|
+ data.cat_def_cnt
|
|
|
|
|
+ 1);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
symtab_def = emit_structure ("_OBJ_SYMTAB", 's', symtab_struct, 0, &data,
|
2020-04-03 05:16:16 +00:00
|
|
|
|
0, sc_static);
|
2011-02-13 04:21:00 +00:00
|
|
|
|
free (data.classes);
|
|
|
|
|
free (data.categories);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
|
2020-03-27 06:33:53 +00:00
|
|
|
|
module_sym = make_symbol ("_OBJ_MODULE", &type_module, pr.far_data,
|
2012-12-02 01:11:30 +00:00
|
|
|
|
sc_static);
|
2011-02-08 13:38:34 +00:00
|
|
|
|
symtab_addsymbol (current_symtab, module_sym);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
module = &D_STRUCT (pr_module_t, module_sym->s.def);
|
2020-03-27 06:33:53 +00:00
|
|
|
|
module->size = type_size (&type_module);
|
2011-01-24 12:13:37 +00:00
|
|
|
|
EMIT_STRING (module_sym->s.def->space, module->name,
|
|
|
|
|
GETSTR (pr.source_file));
|
|
|
|
|
EMIT_DEF (module_sym->s.def->space, module->symtab, symtab_def);
|
2002-05-21 21:28:40 +00:00
|
|
|
|
|
2011-02-11 09:27:07 +00:00
|
|
|
|
exec_class_sym = symtab_lookup (pr.symtab, "__obj_exec_class");
|
|
|
|
|
if (!exec_class_sym) {
|
|
|
|
|
exec_class_sym = new_symbol_type ("__obj_exec_class",
|
2020-03-27 06:33:53 +00:00
|
|
|
|
&type_exec_class);
|
2011-02-11 09:27:07 +00:00
|
|
|
|
exec_class_sym = function_symbol (exec_class_sym, 0, 1);
|
2011-02-15 03:38:29 +00:00
|
|
|
|
make_function (exec_class_sym, 0, exec_class_sym->table->space,
|
2012-12-02 01:11:30 +00:00
|
|
|
|
sc_extern);
|
2011-02-11 09:27:07 +00:00
|
|
|
|
}
|
2002-05-21 21:28:40 +00:00
|
|
|
|
|
2022-01-18 13:34:52 +00:00
|
|
|
|
init_sym = new_symbol_type (".ctor", &type_func);
|
2011-02-08 13:38:34 +00:00
|
|
|
|
init_sym = function_symbol (init_sym, 0, 1);
|
|
|
|
|
|
2022-01-25 14:39:17 +00:00
|
|
|
|
module_expr = address_expr (new_symbol_expr (module_sym), 0);
|
2018-10-12 12:09:36 +00:00
|
|
|
|
|
2002-05-21 21:28:40 +00:00
|
|
|
|
init_expr = new_block_expr ();
|
|
|
|
|
append_expr (init_expr,
|
2018-10-12 12:09:36 +00:00
|
|
|
|
build_function_call (new_symbol_expr (exec_class_sym),
|
|
|
|
|
exec_class_sym->type, module_expr));
|
2011-02-08 13:38:34 +00:00
|
|
|
|
|
2021-09-24 10:49:55 +00:00
|
|
|
|
current_func = begin_function (init_sym, 0, current_symtab, 1, sc_static);
|
2021-01-09 11:42:23 +00:00
|
|
|
|
build_code_function (init_sym, 0, init_expr);
|
2002-05-21 21:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
protocol_t *
|
2002-05-10 00:00:23 +00:00
|
|
|
|
get_protocol (const char *name, int create)
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2002-05-10 00:00:23 +00:00
|
|
|
|
protocol_t *p;
|
|
|
|
|
|
2003-07-24 19:41:59 +00:00
|
|
|
|
if (!protocol_hash)
|
2020-03-25 06:43:16 +00:00
|
|
|
|
protocol_hash = Hash_NewTable (1021, protocol_get_key, 0, 0, 0);
|
2003-07-24 19:41:59 +00:00
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
if (name) {
|
|
|
|
|
p = Hash_Find (protocol_hash, name);
|
|
|
|
|
if (p || !create)
|
|
|
|
|
return p;
|
|
|
|
|
}
|
2002-05-08 21:24:24 +00:00
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
p = calloc (sizeof (protocol_t), 1);
|
2002-05-08 21:24:24 +00:00
|
|
|
|
p->name = name;
|
2020-03-01 10:37:40 +00:00
|
|
|
|
p->methods = 0;
|
2010-12-31 06:44:54 +00:00
|
|
|
|
p->class_type.type = ct_protocol;
|
|
|
|
|
p->class_type.c.protocol = p;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
if (name)
|
|
|
|
|
Hash_Add (protocol_hash, p);
|
2002-05-08 21:24:24 +00:00
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
void
|
|
|
|
|
protocol_add_methods (protocol_t *protocol, methodlist_t *methods)
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2002-05-10 00:00:23 +00:00
|
|
|
|
if (!methods)
|
|
|
|
|
return;
|
2020-03-02 15:11:54 +00:00
|
|
|
|
merge_method_lists (protocol->methods, methods);
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
void
|
2004-11-11 00:34:00 +00:00
|
|
|
|
protocol_add_protocols (protocol_t *protocol, protocollist_t *protocols)
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2004-11-11 00:34:00 +00:00
|
|
|
|
protocol->protocols = protocols;
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
def_t *
|
|
|
|
|
protocol_def (protocol_t *protocol)
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2020-03-02 01:42:26 +00:00
|
|
|
|
if (!protocol->def) {
|
|
|
|
|
protocol->def = emit_protocol (protocol);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
add_static_instance ("Protocol", protocol->def);
|
2020-03-02 01:42:26 +00:00
|
|
|
|
}
|
|
|
|
|
return protocol->def;
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2002-05-15 19:10:23 +00:00
|
|
|
|
|
|
|
|
|
protocollist_t *
|
2004-11-11 00:34:00 +00:00
|
|
|
|
new_protocol_list (void)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
|
|
|
|
protocollist_t *protocollist = malloc (sizeof (protocollist_t));
|
|
|
|
|
|
|
|
|
|
protocollist->count = 0;
|
|
|
|
|
protocollist->list = 0;
|
|
|
|
|
return protocollist;
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-11 00:34:00 +00:00
|
|
|
|
protocollist_t *
|
|
|
|
|
add_protocol (protocollist_t *protocollist, const char *name)
|
|
|
|
|
{
|
|
|
|
|
protocol_t *protocol = get_protocol (name, 0);
|
|
|
|
|
|
|
|
|
|
if (!protocol) {
|
|
|
|
|
error (0, "undefined protocol `%s'", name);
|
|
|
|
|
return protocollist;
|
|
|
|
|
}
|
|
|
|
|
protocollist->count++;
|
|
|
|
|
protocollist->list = realloc (protocollist->list,
|
2018-09-07 11:00:57 +00:00
|
|
|
|
sizeof (protocol_t *) * protocollist->count);
|
2004-11-11 00:34:00 +00:00
|
|
|
|
protocollist->list[protocollist->count - 1] = protocol;
|
|
|
|
|
return protocollist;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-20 04:12:05 +00:00
|
|
|
|
int
|
2012-12-18 11:45:48 +00:00
|
|
|
|
procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2012-12-20 04:12:05 +00:00
|
|
|
|
if (!protocollist)
|
|
|
|
|
return 0;
|
2012-12-18 11:45:48 +00:00
|
|
|
|
for (i = 0; i < protocollist->count; i++)
|
|
|
|
|
if (protocollist->list[i] == proto)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-15 14:30:57 +00:00
|
|
|
|
static method_t *
|
|
|
|
|
protocol_find_method (protocol_t *protocol, selector_t *selector, int instance)
|
|
|
|
|
{
|
|
|
|
|
method_t *m = 0;
|
|
|
|
|
if (protocol->methods) {
|
|
|
|
|
m = methodlist_find_method (protocol->methods, selector, instance);
|
|
|
|
|
}
|
|
|
|
|
if (!m && protocol->protocols) {
|
|
|
|
|
return protocollist_find_method (protocol->protocols, selector,
|
|
|
|
|
instance);
|
|
|
|
|
}
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
method_t *
|
|
|
|
|
protocollist_find_method (protocollist_t *protocollist, selector_t *selector,
|
|
|
|
|
int instance)
|
|
|
|
|
{
|
|
|
|
|
method_t *m;
|
|
|
|
|
for (int i = 0; i < protocollist->count; i++) {
|
|
|
|
|
if ((m = protocol_find_method (protocollist->list[i], selector,
|
|
|
|
|
instance))) {
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-18 11:45:48 +00:00
|
|
|
|
int
|
|
|
|
|
compare_protocols (protocollist_t *protos1, protocollist_t *protos2)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-12-20 04:12:05 +00:00
|
|
|
|
if (protos1 == protos2)
|
2012-12-18 11:45:48 +00:00
|
|
|
|
return 1;
|
|
|
|
|
if (!protos1 || !protos2)
|
|
|
|
|
return 0;
|
|
|
|
|
if (protos1->count != protos2->count)
|
|
|
|
|
return 0;
|
|
|
|
|
for (i = 0; i < protos1->count; i++)
|
|
|
|
|
if (!procollist_find_protocol (protos2, protos1->list[i]))
|
|
|
|
|
return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
print_protocollist (dstring_t *dstr, protocollist_t *protocollist)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
dstring_appendstr (dstr, "<");
|
|
|
|
|
for (i = 0; i < protocollist->count; i++)
|
|
|
|
|
dasprintf (dstr, "%s%s", i ? "," : "", protocollist->list[i]->name);
|
|
|
|
|
dstring_appendstr (dstr, ">");
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-13 06:09:03 +00:00
|
|
|
|
def_t *
|
2002-05-15 23:24:19 +00:00
|
|
|
|
emit_protocol (protocol_t *protocol)
|
|
|
|
|
{
|
|
|
|
|
def_t *proto_def;
|
|
|
|
|
pr_protocol_t *proto;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
defspace_t *space;
|
2002-05-15 23:24:19 +00:00
|
|
|
|
|
2021-01-31 07:01:20 +00:00
|
|
|
|
proto_def = make_symbol (va (0, "_OBJ_PROTOCOL_%s", protocol->name),
|
2020-03-27 06:33:53 +00:00
|
|
|
|
&type_protocol, pr.far_data, sc_static)->s.def;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
if (proto_def->initialized)
|
2006-12-16 08:09:10 +00:00
|
|
|
|
return proto_def;
|
2002-05-16 21:57:03 +00:00
|
|
|
|
proto_def->initialized = proto_def->constant = 1;
|
2003-04-25 17:00:22 +00:00
|
|
|
|
proto_def->nosave = 1;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
space = proto_def->space;
|
|
|
|
|
proto = &D_STRUCT (pr_protocol_t, proto_def);
|
2002-05-15 23:24:19 +00:00
|
|
|
|
proto->class_pointer = 0;
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_STRING (space, proto->protocol_name, protocol->name);
|
|
|
|
|
EMIT_DEF (space, proto->protocol_list,
|
2002-07-13 06:09:03 +00:00
|
|
|
|
emit_protocol_list (protocol->protocols,
|
2021-01-31 07:01:20 +00:00
|
|
|
|
va (0, "PROTOCOL_%s", protocol->name)));
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_DEF (space, proto->instance_methods,
|
2004-11-11 00:34:00 +00:00
|
|
|
|
emit_method_descriptions (protocol->methods, protocol->name, 1));
|
2011-01-24 06:41:43 +00:00
|
|
|
|
EMIT_DEF (space, proto->class_methods,
|
2004-11-11 00:34:00 +00:00
|
|
|
|
emit_method_descriptions (protocol->methods, protocol->name, 0));
|
|
|
|
|
emit_class_ref ("Protocol");
|
2002-07-13 06:09:03 +00:00
|
|
|
|
return proto_def;
|
2002-05-15 23:24:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-08 10:23:49 +00:00
|
|
|
|
static void
|
|
|
|
|
emit_protocol_next (def_t *def, void *data, int index)
|
|
|
|
|
{
|
2022-01-19 08:48:46 +00:00
|
|
|
|
if (!is_ptr(def->type)) {
|
2019-06-08 10:23:49 +00:00
|
|
|
|
internal_error (0, "%s: expected pointer def", __FUNCTION__);
|
|
|
|
|
}
|
|
|
|
|
D_INT (def) = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_protocol_count (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
protocollist_t *protocols = (protocollist_t *) data;
|
|
|
|
|
|
2022-01-18 04:21:06 +00:00
|
|
|
|
if (!is_int(def->type)) {
|
|
|
|
|
internal_error (0, "%s: expected int def", __FUNCTION__);
|
2019-06-08 10:23:49 +00:00
|
|
|
|
}
|
|
|
|
|
D_INT (def) = protocols->count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_protocol_list_item (def_t *def, void *data, int index)
|
|
|
|
|
{
|
|
|
|
|
protocollist_t *protocols = (protocollist_t *) data;
|
|
|
|
|
protocol_t *protocol = protocols->list[index];
|
|
|
|
|
|
2022-01-19 08:48:46 +00:00
|
|
|
|
if (!is_array (def->type) || !is_ptr(def->type->t.array.type)) {
|
2019-06-08 10:23:49 +00:00
|
|
|
|
internal_error (0, "%s: expected array of pointer def", __FUNCTION__);
|
|
|
|
|
}
|
|
|
|
|
if (index < 0 || index >= protocols->count) {
|
|
|
|
|
internal_error (0, "%s: out of bounds index: %d %d",
|
|
|
|
|
__FUNCTION__, index, protocols->count);
|
|
|
|
|
}
|
2020-03-02 01:55:46 +00:00
|
|
|
|
EMIT_DEF (def->space, D_INT(def), protocol_def (protocol));
|
2019-06-08 10:23:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-13 06:09:03 +00:00
|
|
|
|
def_t *
|
2002-05-15 23:24:19 +00:00
|
|
|
|
emit_protocol_list (protocollist_t *protocols, const char *name)
|
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
static struct_def_t proto_list_struct[] = {
|
2022-01-18 13:34:52 +00:00
|
|
|
|
{"next", &type_ptr, emit_protocol_next},
|
|
|
|
|
{"count", &type_int, emit_protocol_count},
|
|
|
|
|
{"list", 0, emit_protocol_list_item},
|
2011-01-17 13:33:33 +00:00
|
|
|
|
{0, 0},
|
|
|
|
|
};
|
2002-05-15 23:24:19 +00:00
|
|
|
|
|
|
|
|
|
if (!protocols)
|
|
|
|
|
return 0;
|
2022-01-18 13:34:52 +00:00
|
|
|
|
proto_list_struct[2].type = array_type (&type_ptr, protocols->count);
|
2021-01-31 07:01:20 +00:00
|
|
|
|
return emit_structure (va (0, "_OBJ_PROTOCOLS_%s", name), 's',
|
2020-04-03 05:16:16 +00:00
|
|
|
|
proto_list_struct, 0, protocols, 0, sc_static);
|
2002-05-15 23:24:19 +00:00
|
|
|
|
}
|
2002-06-28 16:00:01 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
clear_classes (void)
|
|
|
|
|
{
|
|
|
|
|
if (class_hash)
|
|
|
|
|
Hash_FlushTable (class_hash);
|
|
|
|
|
if (protocol_hash)
|
|
|
|
|
Hash_FlushTable (protocol_hash);
|
|
|
|
|
if (category_hash)
|
|
|
|
|
Hash_FlushTable (category_hash);
|
2020-03-02 01:48:51 +00:00
|
|
|
|
if (static_instances)
|
|
|
|
|
Hash_FlushTable (static_instances);
|
|
|
|
|
if (static_instance_classes)
|
|
|
|
|
Hash_FlushTable (static_instance_classes);
|
2012-11-08 07:46:48 +00:00
|
|
|
|
obj_initialized = 0;
|
2011-01-17 13:33:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
symtab_t *
|
|
|
|
|
class_to_struct (class_t *class, symtab_t *symtab)
|
|
|
|
|
{
|
|
|
|
|
symtab_t *parent = symtab->parent;
|
|
|
|
|
symtab_t *ivars = class->ivars;
|
|
|
|
|
symtab_t *ancestor;
|
|
|
|
|
|
|
|
|
|
if (!ivars)
|
|
|
|
|
return symtab;
|
|
|
|
|
|
|
|
|
|
// disconnect the struct symbol table from the scope
|
|
|
|
|
symtab->parent = 0;
|
|
|
|
|
// find the ancestor of the ivars symbol table chain
|
|
|
|
|
for (ancestor = ivars; ancestor->parent; ancestor = ancestor->parent)
|
|
|
|
|
;
|
|
|
|
|
// connect the ivars symbol table chain to the struct symbol table
|
|
|
|
|
ancestor->parent = symtab;
|
|
|
|
|
// create a new struct symbol table from the ivars symbol table chain
|
|
|
|
|
symtab = symtab_flat_copy (ivars, 0);
|
|
|
|
|
// disconnect the ivars symbol table chain
|
|
|
|
|
ancestor->parent = 0;
|
|
|
|
|
// connect the new struct symbol table to the scope
|
|
|
|
|
symtab->parent = parent;
|
|
|
|
|
return symtab;
|
2003-08-20 19:58:41 +00:00
|
|
|
|
}
|
2011-02-06 23:32:52 +00:00
|
|
|
|
|
|
|
|
|
symtab_t *
|
|
|
|
|
class_ivar_scope (class_type_t *class_type, symtab_t *parent)
|
|
|
|
|
{
|
|
|
|
|
class_t *class = extract_class (class_type);
|
2012-12-22 10:35:19 +00:00
|
|
|
|
if (!class->ivars)
|
|
|
|
|
return 0;
|
2011-02-06 23:32:52 +00:00
|
|
|
|
return symtab_flat_copy (class->ivars, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-05 09:45:47 +00:00
|
|
|
|
static expr_t *
|
|
|
|
|
class_dereference_ivar (symbol_t *sym, void *_self)
|
|
|
|
|
{
|
|
|
|
|
expr_t *self = (expr_t *) _self;
|
|
|
|
|
|
|
|
|
|
return field_expr (copy_expr (self),
|
|
|
|
|
new_symbol_expr (new_symbol (sym->name)));
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-06 23:32:52 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-12-22 10:35:19 +00:00
|
|
|
|
if (!ivar_scope)
|
|
|
|
|
return;
|
2011-02-06 23:32:52 +00:00
|
|
|
|
self = symtab_lookup (param_scope, "self");
|
2020-03-05 09:45:47 +00:00
|
|
|
|
if (!self) {
|
2011-02-06 23:32:52 +00:00
|
|
|
|
internal_error (0, "I've lost my self!");
|
2020-03-05 09:45:47 +00:00
|
|
|
|
}
|
2011-02-06 23:32:52 +00:00
|
|
|
|
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;
|
2020-03-05 09:45:47 +00:00
|
|
|
|
sym->sy_type = sy_convert;
|
|
|
|
|
sym->s.convert.conv = class_dereference_ivar;
|
|
|
|
|
sym->s.convert.data = self_expr;
|
2011-02-06 23:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-10 03:56:19 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init_objective_structs (void)
|
|
|
|
|
{
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_selector", 's', sel_struct, &type_selector);
|
|
|
|
|
chain_type (&type_selector);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
chain_type (&type_SEL);
|
|
|
|
|
chain_type (&type_IMP);
|
|
|
|
|
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_method", 's', method_struct, &type_method);
|
|
|
|
|
chain_type (&type_method);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
|
2012-11-12 02:12:33 +00:00
|
|
|
|
make_structure ("obj_method_description", 's', method_desc_struct,
|
2020-03-27 06:33:53 +00:00
|
|
|
|
&type_method_description);
|
|
|
|
|
chain_type (&type_method_description);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_category", 's', category_struct, &type_category);
|
|
|
|
|
chain_type (&type_category);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_ivar", 's', ivar_struct, &type_ivar);
|
|
|
|
|
chain_type (&type_ivar);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_super", 's', super_struct, &type_super);
|
|
|
|
|
chain_type (&type_super);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
chain_type (&type_SuperPtr);
|
|
|
|
|
chain_type (&type_supermsg);
|
2012-12-18 03:49:43 +00:00
|
|
|
|
|
|
|
|
|
symtab_addsymbol (current_symtab, new_symbol ("id"));
|
2012-11-10 03:56:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init_classes (void)
|
|
|
|
|
{
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_class", 's', class_struct, &type_class);
|
|
|
|
|
chain_type (&type_class);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
chain_type (&type_Class);
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_object", 's', object_struct, &type_object);
|
|
|
|
|
chain_type (&type_object);
|
2012-11-11 10:05:19 +00:00
|
|
|
|
chain_type (&type_id);
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_protocol", 's', protocol_struct, &type_protocol);
|
|
|
|
|
chain_type (&type_protocol);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
class_init_obj_module (void)
|
|
|
|
|
{
|
2020-03-27 06:33:53 +00:00
|
|
|
|
make_structure ("obj_module", 's', module_struct, &type_module);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
|
2020-03-27 06:33:53 +00:00
|
|
|
|
chain_type (&type_module);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
chain_type (&type_moduleptr);
|
2020-03-27 06:33:53 +00:00
|
|
|
|
chain_type (&type_exec_class);
|
2012-11-10 03:56:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
class_init (void)
|
|
|
|
|
{
|
2012-12-22 11:06:14 +00:00
|
|
|
|
symtab_t *cs = current_symtab;
|
|
|
|
|
|
|
|
|
|
current_symtab = pr.symtab;
|
2012-11-10 03:56:19 +00:00
|
|
|
|
class_init_obj_module ();
|
|
|
|
|
init_classes ();
|
|
|
|
|
init_objective_structs ();
|
|
|
|
|
obj_initialized = 1;
|
2012-12-22 11:06:14 +00:00
|
|
|
|
|
|
|
|
|
current_symtab = cs;
|
2012-11-10 03:56:19 +00:00
|
|
|
|
}
|