mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
lots of obj work
This commit is contained in:
parent
8f0661f5be
commit
308fa78fc6
7 changed files with 236 additions and 76 deletions
|
@ -34,25 +34,41 @@
|
|||
|
||||
typedef struct class_s {
|
||||
int defined;
|
||||
const char *name;
|
||||
struct class_s *base;
|
||||
struct methodlist_s *methods;
|
||||
const char *class_name;
|
||||
const char *category_name;
|
||||
struct class_s *super_class;
|
||||
struct type_s *ivars;
|
||||
struct methodlist_s *methods;
|
||||
struct protocollist_s *protocols;
|
||||
} class_t;
|
||||
|
||||
struct protocol_s;
|
||||
struct type_s;
|
||||
|
||||
class_t *get_class (const char *name, int create);
|
||||
void class_add_methods (class_t *class, struct methodlist_s *methods);
|
||||
void class_add_protocol_methods (class_t *class, expr_t *protocols);
|
||||
void class_add_protocol (class_t *class, struct protocol_s *protocol);
|
||||
void class_check_ivars (class_t *class, struct type_s *ivars);
|
||||
struct def_s *class_def (class_t *class);
|
||||
class_t *get_category (const char *class_name, const char *category_name,
|
||||
int create);
|
||||
|
||||
typedef struct protocol_s {
|
||||
const char *name;
|
||||
struct methodlist_s *methods;
|
||||
} protocol_t;
|
||||
|
||||
class_t *get_class (const char *name, int create);
|
||||
void class_add_methods (class_t *class, struct methodlist_s *methods);
|
||||
void class_add_protocol_methods (class_t *class, expr_t *protocols);
|
||||
struct def_s *class_def (class_t *class);
|
||||
typedef struct protocollist_s {
|
||||
int count;
|
||||
protocol_t **list;
|
||||
} protocollist_t;
|
||||
|
||||
protocol_t *get_protocol (const char *name, int create);
|
||||
void protocol_add_methods (protocol_t *protocol, struct methodlist_s *methods);
|
||||
void protocol_add_protocol_methods (protocol_t *protocol, expr_t *protocols);
|
||||
struct def_s *protocol_def (protocol_t *protocol);
|
||||
protocollist_t *new_protocollist (void);
|
||||
void add_protocol (protocollist_t *protocollist, protocol_t *protocol);
|
||||
|
||||
#endif//__class_h
|
||||
|
|
|
@ -62,8 +62,7 @@ struct dstring_s;
|
|||
|
||||
method_t *new_method (type_t *ret_type, param_t *selector, param_t *opt_parms);
|
||||
void add_method (methodlist_t *methodlist, method_t *method);
|
||||
def_t *method_def (struct class_s *class, struct class_s *category,
|
||||
method_t *method);
|
||||
def_t *method_def (struct class_s *class, method_t *method);
|
||||
|
||||
methodlist_t *new_methodlist (void);
|
||||
void copy_methods (methodlist_t *dst, methodlist_t *src);
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef struct struct_field_s {
|
|||
struct_field_t *new_struct_field (struct type_s *strct, struct type_s *type,
|
||||
const char *name, visibility_t visibility);
|
||||
struct_field_t *struct_find_field (struct type_s *strct, const char *name);
|
||||
int struct_compare_fields (struct type_s *s1, struct type_s *s2);
|
||||
struct type_s *new_struct (const char *name);
|
||||
struct type_s *find_struct (const char *name);
|
||||
void copy_struct_fields (struct type_s *dst, struct type_s *src);
|
||||
|
|
|
@ -37,15 +37,17 @@ static const char rcsid[] =
|
|||
|
||||
#include "class.h"
|
||||
#include "method.h"
|
||||
#include "struct.h"
|
||||
#include "type.h"
|
||||
|
||||
static hashtab_t *class_hash;
|
||||
static hashtab_t *category_hash;
|
||||
static hashtab_t *protocol_hash;
|
||||
|
||||
static const char *
|
||||
class_get_key (void *class, void *unused)
|
||||
{
|
||||
return ((class_t *) class)->name;
|
||||
return ((class_t *) class)->class_name;
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
@ -68,7 +70,8 @@ get_class (const char *name, int create)
|
|||
}
|
||||
|
||||
c = calloc (sizeof (class_t), 1);
|
||||
c->name = name;
|
||||
c->class_name = name;
|
||||
if (name)
|
||||
Hash_Add (class_hash, c);
|
||||
return c;
|
||||
}
|
||||
|
@ -105,10 +108,68 @@ class_add_protocol_methods (class_t *class, expr_t *protocols)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
class_add_protocol (class_t *class, protocol_t *protocol)
|
||||
{
|
||||
if (!class->protocols)
|
||||
class->protocols = new_protocollist ();
|
||||
add_protocol (class->protocols, protocol);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
category_get_hash (void *_c, void *unused)
|
||||
{
|
||||
class_t *c = (class_t *) _c;
|
||||
return Hash_String (c->class_name) ^ Hash_String (c->category_name);
|
||||
}
|
||||
|
||||
static int
|
||||
category_compare (void *_c1, void *_c2, void *unused)
|
||||
{
|
||||
class_t *c1 = (class_t *) _c1;
|
||||
class_t *c2 = (class_t *) _c2;
|
||||
return strcmp (c1->class_name, c2->class_name) == 0
|
||||
&& strcmp (c1->category_name, c2->category_name) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
class_check_ivars (class_t *class, struct type_s *ivars)
|
||||
{
|
||||
if (!struct_compare_fields (class->ivars, ivars))
|
||||
warning (0, "instance variable missmatch for %s", class->class_name);
|
||||
class->ivars = ivars;
|
||||
}
|
||||
|
||||
class_t *
|
||||
get_category (const char *class_name, const char *category_name, int create)
|
||||
{
|
||||
class_t *c;
|
||||
|
||||
if (!category_hash) {
|
||||
category_hash = Hash_NewTable (1021, 0, 0, 0);
|
||||
Hash_SetHashCompare (category_hash,
|
||||
category_get_hash, category_compare);
|
||||
}
|
||||
if (class_name && category_name) {
|
||||
class_t _c = {0, class_name, category_name};
|
||||
|
||||
c = Hash_FindElement (category_hash, &_c);
|
||||
if (c || !create)
|
||||
return c;
|
||||
}
|
||||
|
||||
c = calloc (sizeof (class_t), 1);
|
||||
c->class_name = class_name;
|
||||
c->class_name = category_name;
|
||||
if (class_name && category_name)
|
||||
Hash_AddElement (category_hash, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
def_t *
|
||||
class_def (class_t *class)
|
||||
{
|
||||
return PR_GetDef (&type_Class, class->name, 0, &numpr_globals);
|
||||
return PR_GetDef (&type_Class, class->class_name, 0, &numpr_globals);
|
||||
}
|
||||
|
||||
protocol_t *
|
||||
|
@ -124,6 +185,7 @@ get_protocol (const char *name, int create)
|
|||
|
||||
p = calloc (sizeof (protocol_t), 1);
|
||||
p->name = name;
|
||||
if (name)
|
||||
Hash_Add (protocol_hash, p);
|
||||
return p;
|
||||
}
|
||||
|
@ -163,3 +225,22 @@ protocol_def (protocol_t *protocol)
|
|||
{
|
||||
return PR_GetDef (&type_Protocol, protocol->name, 0, &numpr_globals);
|
||||
}
|
||||
|
||||
protocollist_t *
|
||||
new_protocollist (void)
|
||||
{
|
||||
protocollist_t *protocollist = malloc (sizeof (protocollist_t));
|
||||
|
||||
protocollist->count = 0;
|
||||
protocollist->list = 0;
|
||||
return protocollist;
|
||||
}
|
||||
|
||||
void
|
||||
add_protocol (protocollist_t *protocollist, protocol_t *protocol)
|
||||
{
|
||||
protocollist->list = realloc (protocollist->list,
|
||||
(protocollist->count + 1)
|
||||
* sizeof (protocollist_t));
|
||||
protocollist->list[protocollist->count++] = protocol;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ add_method (methodlist_t *methodlist, method_t *method)
|
|||
}
|
||||
|
||||
def_t *
|
||||
method_def (class_t *class, class_t *category, method_t *method)
|
||||
method_def (class_t *class, method_t *method)
|
||||
{
|
||||
dstring_t *str = dstring_newstr ();
|
||||
dstring_t *sel = dstring_newstr ();
|
||||
|
@ -87,8 +87,8 @@ method_def (class_t *class, class_t *category, method_t *method)
|
|||
selector_name (sel, (keywordarg_t *)method->selector);
|
||||
dsprintf (str, "_%c_%s_%s_%s",
|
||||
method->instance ? 'i' : 'c',
|
||||
class->name,
|
||||
category ? category->name : "",
|
||||
class->class_name,
|
||||
class->category_name ? class->category_name : "",
|
||||
sel->str);
|
||||
for (s = str->str; *s; s++)
|
||||
if (*s == ':')
|
||||
|
|
|
@ -54,6 +54,14 @@ yyerror (const char *s)
|
|||
error (0, "%s %s\n", yytext, s);
|
||||
}
|
||||
|
||||
void
|
||||
parse_error (void)
|
||||
{
|
||||
error (0, "parse error before %s", yytext);
|
||||
}
|
||||
|
||||
#define PARSE_ERROR do { parse_error (); YYERROR; } while (0)
|
||||
|
||||
int yylex (void);
|
||||
|
||||
type_t *build_type (int is_field, type_t *type);
|
||||
|
@ -133,9 +141,11 @@ void free_local_inits (hashtab_t *def_list);
|
|||
%type <expr> protocolrefs
|
||||
%type <keywordarg> messageargs keywordarg keywordarglist selectorarg
|
||||
%type <keywordarg> keywordnamelist keywordname
|
||||
%type <class> class_name new_class_name
|
||||
%type <class> class_name new_class_name class_with_super new_class_with_super
|
||||
%type <class> category_name new_category_name
|
||||
%type <protocol> protocol_name
|
||||
%type <methodlist> methodprotolist methodprotolist2
|
||||
%type <type> ivar_decl_list
|
||||
|
||||
%expect 2 // statement : if | if else, defs : defs def ';' | defs obj_def
|
||||
|
||||
|
@ -153,6 +163,7 @@ expr_t *continue_label;
|
|||
switch_block_t *switch_block;
|
||||
type_t *struct_type;
|
||||
visibility_t current_visibility;
|
||||
type_t *current_ivars;
|
||||
|
||||
def_t *pr_scope; // the function being parsed, or NULL
|
||||
string_t s_file; // filename for function definition
|
||||
|
@ -165,7 +176,7 @@ int element_flag;
|
|||
|
||||
defs
|
||||
: /* empty */
|
||||
| defs def ';'
|
||||
| defs {if (current_class) PARSE_ERROR;} def ';'
|
||||
| defs obj_def
|
||||
;
|
||||
|
||||
|
@ -853,8 +864,13 @@ obj_def
|
|||
: classdef
|
||||
| classdecl
|
||||
| protocoldef
|
||||
| methoddef
|
||||
| { if (!current_class) PARSE_ERROR; } methoddef
|
||||
| END
|
||||
{
|
||||
if (!current_class)
|
||||
PARSE_ERROR;
|
||||
current_class = 0;
|
||||
}
|
||||
;
|
||||
|
||||
identifier_list
|
||||
|
@ -888,6 +904,7 @@ class_name
|
|||
error (0, "undefined symbol `%s'", $1);
|
||||
$$ = get_class (0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -902,70 +919,91 @@ new_class_name
|
|||
current_class = $$;
|
||||
}
|
||||
|
||||
class_with_super
|
||||
: class_name ':' class_name
|
||||
{
|
||||
if ($1->super_class != $3)
|
||||
error (0, "%s is not a super class of %s",
|
||||
$3->class_name, $1->class_name);
|
||||
$$ = $1;
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
new_class_with_super
|
||||
: new_class_name ':' class_name
|
||||
{
|
||||
$1->super_class = $3;
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
category_name
|
||||
: NAME '(' NAME ')'
|
||||
{
|
||||
$$ = get_category ($1, $3, 0);
|
||||
if (!$$) {
|
||||
error (0, "undefined category `%s (%s)'", $1, $3);
|
||||
$$ = get_category (0, 0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
new_category_name
|
||||
: NAME '(' NAME ')'
|
||||
{
|
||||
$$ = get_category ($1, $3, 1);
|
||||
if ($$->defined) {
|
||||
error (0, "redefinition of category `%s (%s)'", $1, $3);
|
||||
$$ = get_category (0, 0, 1);
|
||||
}
|
||||
current_class = $$;
|
||||
}
|
||||
;
|
||||
|
||||
protocol_name
|
||||
: NAME
|
||||
{
|
||||
$$ = get_protocol ($1, 1);
|
||||
if ($$->methods) {
|
||||
$$ = get_protocol ($1, 0);
|
||||
if ($$) {
|
||||
error (0, "redefinition of %s", $1);
|
||||
$$ = get_protocol (0, 1);
|
||||
} else {
|
||||
$$ = get_protocol ($1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
classdef /* XXX */
|
||||
classdef
|
||||
: INTERFACE new_class_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $3); }
|
||||
'{' { $2->ivars = new_struct (0); }
|
||||
ivar_decl_list '}'
|
||||
'{' ivar_decl_list '}' { $2->ivars = $6; }
|
||||
methodprotolist { class_add_methods ($2, $9); }
|
||||
END
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_class_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $3); }
|
||||
methodprotolist { class_add_methods ($2, $5); }
|
||||
END
|
||||
| INTERFACE new_class_name ':' class_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $5); }
|
||||
'{'
|
||||
{
|
||||
$2->ivars = new_struct (0);
|
||||
copy_struct_fields ($2->ivars, $4->ivars);
|
||||
}
|
||||
ivar_decl_list '}'
|
||||
methodprotolist { class_add_methods ($2, $11); }
|
||||
END
|
||||
| INTERFACE new_class_name ':' class_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $5); }
|
||||
methodprotolist { class_add_methods ($2, $7); }
|
||||
END
|
||||
| INTERFACE new_class_name '(' class_name ')'
|
||||
protocolrefs { class_add_protocol_methods ($2, $6); }
|
||||
methodprotolist { class_add_methods ($2, $8); }
|
||||
END
|
||||
| IMPLEMENTATION class_name '{'
|
||||
{
|
||||
$2->ivars = new_struct (0);
|
||||
current_class = $2;
|
||||
}
|
||||
ivar_decl_list '}'
|
||||
| IMPLEMENTATION class_name { current_class = $2; }
|
||||
| IMPLEMENTATION class_name ':' class_name '{'
|
||||
{
|
||||
if ($4 != $2->base)
|
||||
warning (0, "%s is not a super class of %s",
|
||||
$4->name, $2->name);
|
||||
$2->ivars = new_struct (0);
|
||||
copy_struct_fields ($2->ivars, $4->ivars);
|
||||
current_class = $2;
|
||||
}
|
||||
ivar_decl_list '}'
|
||||
| IMPLEMENTATION class_name ':' class_name
|
||||
{
|
||||
if ($4 != $2->base)
|
||||
warning (0, "%s is not a super class of %s",
|
||||
$4->name, $2->name);
|
||||
current_class = $2;
|
||||
}
|
||||
| IMPLEMENTATION class_name '(' class_name ')' { current_class = $2; }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_class_with_super
|
||||
protocolrefs { class_add_protocol_methods ($2, $3); }
|
||||
'{' ivar_decl_list '}' { $2->ivars = $6; }
|
||||
methodprotolist { class_add_methods ($2, $9); }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_class_with_super
|
||||
protocolrefs { class_add_protocol_methods ($2, $3); }
|
||||
methodprotolist { class_add_methods ($2, $5); }
|
||||
END { current_class = 0; }
|
||||
| INTERFACE new_category_name
|
||||
protocolrefs { class_add_protocol_methods ($2, $3); }
|
||||
methodprotolist { class_add_methods ($2, $5); }
|
||||
END { current_class = 0; }
|
||||
| IMPLEMENTATION class_name
|
||||
'{' ivar_decl_list '}' { class_check_ivars ($2, $4); }
|
||||
| IMPLEMENTATION class_name
|
||||
| IMPLEMENTATION class_with_super
|
||||
'{' ivar_decl_list '}' { class_check_ivars ($2, $4); }
|
||||
| IMPLEMENTATION class_with_super
|
||||
| IMPLEMENTATION category_name
|
||||
;
|
||||
|
||||
protocoldef
|
||||
|
@ -981,7 +1019,15 @@ protocolrefs
|
|||
;
|
||||
|
||||
ivar_decl_list
|
||||
: ivar_decl_list visibility_spec ivar_decls
|
||||
: { current_ivars = new_struct (0); } ivar_decl_list_2
|
||||
{
|
||||
$$ = current_ivars;
|
||||
current_ivars = 0;
|
||||
}
|
||||
;
|
||||
|
||||
ivar_decl_list_2
|
||||
: ivar_decl_list_2 visibility_spec ivar_decls
|
||||
| ivar_decls
|
||||
;
|
||||
|
||||
|
@ -997,7 +1043,7 @@ ivar_decls
|
|||
;
|
||||
|
||||
ivar_decl
|
||||
: type ivars { current_type = $1; }
|
||||
: type { current_type = $1; } ivars
|
||||
;
|
||||
|
||||
ivars
|
||||
|
@ -1008,7 +1054,7 @@ ivars
|
|||
ivar_declarator
|
||||
: NAME
|
||||
{
|
||||
new_struct_field (current_class->ivars, current_type,
|
||||
new_struct_field (current_ivars, current_type,
|
||||
$1, current_visibility);
|
||||
}
|
||||
;
|
||||
|
@ -1018,7 +1064,7 @@ methoddef
|
|||
methoddecl opt_state_expr
|
||||
{
|
||||
$2->instance = 0;
|
||||
current_def = $2->def = method_def (current_class, 0, $2);
|
||||
current_def = $2->def = method_def (current_class, $2);
|
||||
current_params = $2->params;
|
||||
}
|
||||
begin_function statement_block end_function
|
||||
|
@ -1036,7 +1082,7 @@ methoddef
|
|||
methoddecl opt_state_expr
|
||||
{
|
||||
$2->instance = 1;
|
||||
current_def = $2->def = method_def (current_class, 0, $2);
|
||||
current_def = $2->def = method_def (current_class, $2);
|
||||
current_params = $2->params;
|
||||
}
|
||||
begin_function statement_block end_function
|
||||
|
|
|
@ -117,6 +117,7 @@ new_struct (const char *name)
|
|||
strct->type->type = ev_struct;
|
||||
strct->type->struct_tail = &strct->type->struct_head;
|
||||
strct->type->struct_fields = Hash_NewTable (61, struct_field_get_key, 0, 0);
|
||||
if (name)
|
||||
Hash_Add (structs, strct);
|
||||
return strct->type;
|
||||
}
|
||||
|
@ -145,6 +146,22 @@ copy_struct_fields (type_t *dst, type_t *src)
|
|||
new_struct_field (dst, s->type, s->name, s->visibility);
|
||||
}
|
||||
|
||||
int
|
||||
struct_compare_fields (struct type_s *s1, struct type_s *s2)
|
||||
{
|
||||
struct_field_t *f1 = s1->struct_head;
|
||||
struct_field_t *f2 = s2->struct_head;
|
||||
|
||||
while (f1 && f2) {
|
||||
if (strcmp (f1->name, f2->name)
|
||||
|| f1->type != f2->type)
|
||||
return 0;
|
||||
f1 = f1->next;
|
||||
f2 = f2->next;
|
||||
}
|
||||
return !((!f1) ^ !(f2));
|
||||
}
|
||||
|
||||
void
|
||||
process_enum (expr_t *enm)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue