Unify duplicate typesymbol checking.

This commit is contained in:
David Anderson 2014-06-16 22:11:58 -07:00
parent 09161bf269
commit 05cf368202
5 changed files with 133 additions and 34 deletions

View File

@ -3138,6 +3138,13 @@ static void decl_const(int vclass)
needtoken(tTERM);
}
static void check_struct_name(const char *name)
{
LayoutSpec spec = deduce_layout_spec_by_name(name);
if (!can_redef_layout_spec(spec, Layout_PawnStruct))
error(110, name, layout_spec_name(spec));
}
/*
* declstruct - declare a struct type
*/
@ -3148,6 +3155,7 @@ static void declstruct(void)
int tok;
pstruct_t *pstruct;
int size;
LayoutSpec spec;
/* get the explicit tag (required!) */
tok = lex(&val,&str);
@ -3156,10 +3164,7 @@ static void declstruct(void)
error(93);
}
if (pstructs_find(str) != NULL)
{
error(98);
}
check_struct_name(str);
pstruct = pstructs_add(str);
@ -3246,8 +3251,9 @@ static void declstruct(void)
*/
static void domethodmap()
{
int val;
char *str;
LayoutSpec spec;
int val, extends;
char mapname[sNAMEMAX + 1];
methodmap_t *map;
methodmap_t *parent = NULL;
@ -3261,11 +3267,11 @@ static void domethodmap()
if (!isupper(*mapname))
error(109, decltype);
int maptag = pc_addtag(mapname);
if (methodmap_find_by_tag(maptag))
error(103, decltype, mapname);
spec = deduce_layout_spec_by_name(mapname);
if (!can_redef_layout_spec(spec, Layout_MethodMap))
error(110, mapname, layout_spec_name(spec));
int extends = matchtoken('<');
extends = matchtoken('<');
if (extends) {
if (lex(&val, &str) != tSYMBOL) {
error(93);
@ -3279,7 +3285,8 @@ static void domethodmap()
map = (methodmap_t *)calloc(1, sizeof(methodmap_t));
map->parent = parent;
map->tag = maptag;
map->tag = pc_addtag(mapname);
map->spec = Layout_MethodMap;
strcpy(map->name, mapname);
methodmap_add(map);
@ -3597,15 +3604,17 @@ static void decl_enum(int vclass)
cell increment,multiplier;
constvalue *enumroot;
symbol *enumsym;
LayoutSpec spec;
/* get an explicit tag, if any (we need to remember whether an explicit
* tag was passed, even if that explicit tag was "_:", so we cannot call
* pc_addtag() here
*/
if (lex(&val,&str)==tLABEL) {
tag=pc_addtag(str);
if (methodmap_find_by_tag(tag))
error(110, str, "methodmap");
tag = pc_addtag(str);
spec = deduce_layout_spec_by_tag(tag);
if (!can_redef_layout_spec(spec, Layout_Enum))
error(110, str, layout_spec_name(spec));
explicittag=TRUE;
} else {
lexpush();
@ -3618,11 +3627,13 @@ static void decl_enum(int vclass)
strcpy(enumname,str); /* save enum name (last constant) */
if (!explicittag) {
tag=pc_addtag(enumname);
if (methodmap_find_by_tag(tag))
error(110, str, "methodmap");
spec = deduce_layout_spec_by_tag(tag);
if (!can_redef_layout_spec(spec, Layout_Enum))
error(110, enumname, layout_spec_name(spec));
} else {
if (methodmap_find_by_name(enumname))
error(110, str, "methodmap");
spec = deduce_layout_spec_by_name(enumname);
if (!can_redef_layout_spec(spec, Layout_Enum))
error(110, enumname, layout_spec_name(spec));
}
} else {
lexpush(); /* analyze again */

View File

@ -141,12 +141,12 @@ static char *errmsg[] = {
/*095*/ "cannot have required parameters after optional parameters\n",
/*096*/ "could not find member \"%s\" in struct \"%s\"\n",
/*097*/ "symbol \"%s\" does not have a matching type\n",
/*098*/ "struct requires unique struct name\n",
/*098*/ "UNUSED\n",
/*099*/ "member \"%s\" appears more than once in struct \"%s\"\n",
/*100*/ "function prototypes do not match\n",
/*101*/ "specify either all dimensions or only the last dimension\n",
/*102*/ "cannot find %s %s\n",
/*103*/ "%s %s was already defined\n",
/*103*/ "UNUSED\n",
/*104*/ "cannot find any methods for %s\n",
/*105*/ "cannot find method %s.%s\n",
/*106*/ "cannot call methods on an array\n",

View File

@ -484,3 +484,85 @@ void methodmaps_free()
methodmap_first = NULL;
methodmap_last = NULL;
}
LayoutSpec deduce_layout_spec_by_tag(int tag)
{
symbol *sym;
const char *name;
methodmap_t *map;
if ((map = methodmap_find_by_tag(tag)) != NULL)
return map->spec;
if (tag & FUNCTAG)
return Layout_FuncTag;
name = pc_tagname(tag);
if (pstructs_find(name))
return Layout_PawnStruct;
if ((sym = findglb(name, sGLOBAL)) != NULL)
return Layout_Enum;
return Layout_None;
}
LayoutSpec deduce_layout_spec_by_name(const char *name)
{
symbol *sym;
methodmap_t *map;
int tag = pc_findtag(name);
if (tag != -1 && (tag & FUNCTAG))
return Layout_FuncTag;
if (pstructs_find(name))
return Layout_PawnStruct;
if ((map = methodmap_find_by_name(name)) != NULL)
return map->spec;
if ((sym = findglb(name, sGLOBAL)) != NULL)
return Layout_Enum;
return Layout_None;
}
const char *layout_spec_name(LayoutSpec spec)
{
switch (spec) {
case Layout_None:
return "<none>";
case Layout_Enum:
return "enum";
case Layout_FuncTag:
return "functag";
case Layout_PawnStruct:
return "deprecated-struct";
case Layout_MethodMap:
return "methodmap";
case Layout_Class:
return "class";
}
return "<unknown>";
}
int can_redef_layout_spec(LayoutSpec def1, LayoutSpec def2)
{
// Normalize the ordering, since these checks are symmetrical.
if (def1 > def2) {
LayoutSpec temp = def2;
def2 = def1;
def1 = temp;
}
switch (def1) {
case Layout_None:
return TRUE;
case Layout_Enum:
if (def2 == Layout_Enum || def2 == Layout_FuncTag)
return TRUE;
return def2 == Layout_MethodMap;
case Layout_FuncTag:
return def2 == Layout_Enum || def2 == Layout_FuncTag;
case Layout_PawnStruct:
case Layout_MethodMap:
return FALSE;
case Layout_Class:
return FALSE;
}
return FALSE;
}

View File

@ -67,6 +67,18 @@ typedef struct pstruct_s
struct pstruct_s *next;
} pstruct_t;
// The ordering of these definitions should be preserved for
// can_redef_layout_spec().
typedef enum
{
Layout_None,
Layout_Enum,
Layout_FuncTag,
Layout_PawnStruct,
Layout_MethodMap,
Layout_Class
} LayoutSpec;
typedef struct methodmap_method_s
{
char name[sNAMEMAX+1];
@ -78,6 +90,7 @@ typedef struct methodmap_s
struct methodmap_s *next;
struct methodmap_s *parent;
int tag;
LayoutSpec spec;
char name[sNAMEMAX+1];
methodmap_method_t **methods;
size_t nummethods;
@ -100,6 +113,14 @@ funcenum_t *funcenums_add(const char *name);
funcenum_t *funcenums_find_byval(int value);
functag_t *functags_add(funcenum_t *en, functag_t *src);
/**
* Given a name or tag, find any extra weirdness it has associated with it.
*/
LayoutSpec deduce_layout_spec_by_tag(int tag);
LayoutSpec deduce_layout_spec_by_name(const char *name);
const char *layout_spec_name(LayoutSpec spec);
int can_redef_layout_spec(LayoutSpec olddef, LayoutSpec newdef);
/**
* Heap functions
*/

View File

@ -1,15 +0,0 @@
native CloseHandle(Handle:this);
methodmap Handle {
Close = CloseHandle;
};
methodmap Crab {
};
enum Crab {
};
public main()
{
}