Second attempt at accessors. syntax is a little more usable. also supports arbitrary custom fields too, without requiring it to use lots of string compares.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4747 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
abde2fa81b
commit
0fb5e2bc25
3 changed files with 260 additions and 132 deletions
|
@ -302,6 +302,15 @@ struct QCC_typeparam_s
|
|||
unsigned int arraysize;
|
||||
char *paramname;
|
||||
};
|
||||
struct accessor_s
|
||||
{
|
||||
struct accessor_s *next;
|
||||
struct QCC_type_s *type;
|
||||
struct QCC_type_s *indexertype; //null if not indexer
|
||||
struct QCC_def_s *get;
|
||||
struct QCC_def_s *set;
|
||||
char *fieldname;
|
||||
};
|
||||
|
||||
typedef struct QCC_type_s
|
||||
{
|
||||
|
@ -321,11 +330,7 @@ typedef struct QCC_type_s
|
|||
char *name;
|
||||
char *aname;
|
||||
|
||||
struct QCC_def_s *getptr;
|
||||
struct QCC_def_s *getarr;
|
||||
struct QCC_def_s *setptr;
|
||||
struct QCC_def_s *setarr;
|
||||
struct QCC_def_s *getlength;
|
||||
struct accessor_s *accessors;
|
||||
} QCC_type_t;
|
||||
int typecmp(QCC_type_t *a, QCC_type_t *b);
|
||||
int typecmp_lax(QCC_type_t *a, QCC_type_t *b);
|
||||
|
@ -390,6 +395,7 @@ typedef struct
|
|||
QCC_def_t *base;
|
||||
QCC_def_t *index;
|
||||
QCC_type_t *cast; //entity.float is float, not pointer.
|
||||
struct accessor_s *accessor; //the accessor field of base that we're trying to use
|
||||
int postinc; //+1 or -1
|
||||
pbool readonly; //for whatever reason, like base being a const
|
||||
} QCC_ref_t;
|
||||
|
|
|
@ -156,6 +156,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
|
|||
QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbool allowarrayassign, pbool expandmemberfields, pbool makearraypointers);
|
||||
QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *refbuf, QCC_ref_t *d, pbool allowarrayassign, pbool makestructpointers);
|
||||
QCC_ref_t *QCC_PR_BuildRef(QCC_ref_t *retbuf, unsigned int reftype, QCC_def_t *base, QCC_def_t *index, QCC_type_t *cast, pbool readonly);
|
||||
QCC_ref_t *QCC_PR_BuildAccessorRef(QCC_ref_t *retbuf, QCC_def_t *base, QCC_def_t *index, struct accessor_s *accessor, pbool readonly);
|
||||
QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pbool preservedest);
|
||||
void QCC_PR_DiscardRef(QCC_ref_t *ref);
|
||||
|
||||
|
@ -3102,19 +3103,19 @@ QCC_def_t *QCC_PR_StatementFlags (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t
|
|||
case OP_ADD_FI:
|
||||
numstatements--;
|
||||
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
|
||||
case OP_BITAND_FI:
|
||||
numstatements--;
|
||||
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
|
||||
case OP_BITOR_FI:
|
||||
numstatements--;
|
||||
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
|
||||
case OP_LT_FI:
|
||||
numstatements--;
|
||||
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_LT_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_LT_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
|
||||
//statements where the lhs is a const int and can be swapped with a float
|
||||
case OP_ADD_IF:
|
||||
numstatements--;
|
||||
|
@ -5264,26 +5265,35 @@ static QCC_ref_t *QCC_PR_ParseField(QCC_ref_t *refbuf, QCC_ref_t *lhs)
|
|||
|
||||
lhs = QCC_PR_ParseField(refbuf, lhs);
|
||||
}
|
||||
else if (t->type == ev_accessor && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
|
||||
else if (t->accessors && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
|
||||
{
|
||||
QCC_def_t *index = NULL;
|
||||
char *fieldname = QCC_PR_ParseName();
|
||||
if (!t->aux_type)
|
||||
QCC_PR_ParseError(ERR_INTERNAL, "Accessor %s was not defined yet", t->name);
|
||||
else if (!strcmp(fieldname, "length"))
|
||||
{
|
||||
QCC_def_t *obj = QCC_RefToDef(lhs, true);
|
||||
obj = QCC_PR_GenerateFunctionCall(NULL, t->getlength, &obj, &t->parentclass, 1);
|
||||
lhs = QCC_PR_BuildRef(refbuf, REF_GLOBAL, obj, NULL, obj->type, true);
|
||||
lhs = QCC_PR_ParseField(refbuf, lhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
//these are not defs, but weird crap.
|
||||
QCC_def_t *index = QCC_MakeStringConst(fieldname);
|
||||
pbool noset = !t->setarr && !t->setptr;
|
||||
lhs = QCC_PR_BuildRef(refbuf, REF_ACCESSOR, QCC_RefToDef(lhs, true), index, t->aux_type, lhs->readonly || noset);
|
||||
lhs = QCC_PR_ParseField(refbuf, lhs);
|
||||
}
|
||||
struct accessor_s *acc;
|
||||
|
||||
for (acc = t->accessors; acc; acc = acc->next)
|
||||
if (!strcmp(acc->fieldname, fieldname))
|
||||
{
|
||||
if (acc->indexertype)
|
||||
{
|
||||
QCC_PR_Expect("[");
|
||||
index = QCC_PR_Expression (TOP_PRIORITY, 0);
|
||||
QCC_PR_Expect("]");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!acc)
|
||||
for (acc = t->accessors; acc; acc = acc->next)
|
||||
if (!*acc->fieldname && acc->indexertype)
|
||||
{
|
||||
index = QCC_MakeStringConst(fieldname);
|
||||
break;
|
||||
}
|
||||
if (!acc)
|
||||
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a member of %s", fieldname, t->name);
|
||||
|
||||
lhs = QCC_PR_BuildAccessorRef(refbuf, QCC_RefToDef(lhs, true), index, acc, lhs->readonly);
|
||||
lhs = QCC_PR_ParseField(refbuf, lhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
@ -5325,7 +5335,7 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
|
|||
(t->type == ev_string) || //strings are effectively pointers
|
||||
(t->type == ev_vector) || //vectors are mini arrays
|
||||
(t->type == ev_field && t->aux_type->type == ev_vector) || //as are field vectors
|
||||
(t->type == ev_accessor); //custom accessors
|
||||
(!arraysize&&t->accessors); //custom accessors
|
||||
}
|
||||
|
||||
if (allowarray && QCC_PR_CheckToken("["))
|
||||
|
@ -5333,12 +5343,17 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
|
|||
tmp = QCC_PR_Expression (TOP_PRIORITY, 0);
|
||||
QCC_PR_Expect("]");
|
||||
|
||||
if (!arraysize && t->type == ev_accessor)
|
||||
if (!arraysize && t->accessors)
|
||||
{
|
||||
if (!t->aux_type)
|
||||
QCC_PR_ParseError(ERR_INTERNAL, "Accessor %s was not defined yet", t->name);
|
||||
r = QCC_PR_BuildRef(retbuf, REF_ACCESSOR, QCC_RefToDef(r, true), tmp, t->aux_type, r->readonly || (!t->setarr && !t->setptr));
|
||||
return QCC_PR_ParseRefArrayPointer(retbuf, r, allowarrayassign, makearraypointers);
|
||||
struct accessor_s *acc;
|
||||
for (acc = t->accessors; acc; acc = acc->next)
|
||||
if (!*acc->fieldname)
|
||||
break;
|
||||
if(acc)
|
||||
{
|
||||
r = QCC_PR_BuildAccessorRef(retbuf, QCC_RefToDef(r, true), tmp, acc, r->readonly);
|
||||
return QCC_PR_ParseRefArrayPointer(retbuf, r, allowarrayassign, makearraypointers);
|
||||
}
|
||||
}
|
||||
|
||||
/*if its a pointer that got dereferenced, follow the type*/
|
||||
|
@ -5930,10 +5945,14 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
|
|||
e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
|
||||
if (e->type->type == ev_pointer)
|
||||
return QCC_PR_BuildRef(retbuf, REF_POINTER, e, NULL, e->type->aux_type, false);
|
||||
else if (e->type->type == ev_accessor)
|
||||
return QCC_PR_BuildRef(retbuf, REF_ACCESSOR, e, NULL, e->type->aux_type, !e->type->setptr);
|
||||
else
|
||||
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCH, e, "Unable to dereference non-pointer type.");
|
||||
else if (e->type->accessors)
|
||||
{
|
||||
struct accessor_s *acc;
|
||||
for (acc = e->type->accessors; acc; acc = acc->next)
|
||||
if (!strcmp(acc->fieldname, ""))
|
||||
return QCC_PR_BuildAccessorRef(retbuf, e, NULL, acc, e->constant);
|
||||
}
|
||||
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCH, e, "Unable to dereference non-pointer type.");
|
||||
}
|
||||
if (QCC_PR_CheckToken ("-"))
|
||||
{
|
||||
|
@ -6095,6 +6114,17 @@ QCC_PR_RefExpression
|
|||
==============
|
||||
*/
|
||||
|
||||
QCC_ref_t *QCC_PR_BuildAccessorRef(QCC_ref_t *retbuf, QCC_def_t *base, QCC_def_t *index, struct accessor_s *accessor, pbool readonly)
|
||||
{
|
||||
retbuf->postinc = 0;
|
||||
retbuf->type = REF_ACCESSOR;
|
||||
retbuf->base = base;
|
||||
retbuf->index = index;
|
||||
retbuf->accessor = accessor;
|
||||
retbuf->cast = accessor->type;
|
||||
retbuf->readonly = readonly;
|
||||
return retbuf;
|
||||
}
|
||||
QCC_ref_t *QCC_PR_BuildRef(QCC_ref_t *retbuf, unsigned int reftype, QCC_def_t *base, QCC_def_t *index, QCC_type_t *cast, pbool readonly)
|
||||
{
|
||||
retbuf->postinc = 0;
|
||||
|
@ -6624,18 +6654,17 @@ QCC_def_t *QCC_RefToDef(QCC_ref_t *ref, pbool freetemps)
|
|||
case REF_STRING:
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_LOADP_C], ref->base, ref->index, NULL, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB));
|
||||
case REF_ACCESSOR:
|
||||
if (!ref->index && ref->base->type->getptr)
|
||||
if (ref->accessor && ref->accessor->get)
|
||||
{
|
||||
QCC_def_t *arg[] = {ref->base};
|
||||
return QCC_PR_GenerateFunctionCall(NULL, ref->base->type->getptr, arg, NULL, 1);
|
||||
}
|
||||
else if (ref->base->type->getarr)
|
||||
{
|
||||
QCC_def_t *arg[] = {ref->base, ref->index?QCC_SupplyConversion(ref->index, ref->base->type->aux_type->type, true):QCC_MakeIntConst(0)};
|
||||
return QCC_PR_GenerateFunctionCall(NULL, ref->base->type->getarr, arg, NULL, 2);
|
||||
int args = 0;
|
||||
QCC_def_t *arg[2] = {NULL, NULL};
|
||||
arg[args++] = ref->base;
|
||||
if (ref->accessor->indexertype)
|
||||
arg[args++] = ref->index?QCC_SupplyConversion(ref->index, ref->accessor->indexertype->type, true):QCC_MakeIntConst(0);
|
||||
return QCC_PR_GenerateFunctionCall(NULL, ref->accessor->get, arg, NULL, args);
|
||||
}
|
||||
else
|
||||
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, ref->base, "Accessor has no appropriate get function");
|
||||
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, ref->base, "Accessor %s has no get function", ref->accessor?ref->accessor->fieldname:"");
|
||||
break;
|
||||
}
|
||||
if (ref->cast != ret->type)
|
||||
|
@ -6777,18 +6806,19 @@ QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pb
|
|||
}
|
||||
break;
|
||||
case REF_ACCESSOR:
|
||||
if (!dest->index && dest->base->type->setptr)
|
||||
if (dest->accessor && dest->accessor->set)
|
||||
{
|
||||
QCC_def_t *arg[] = {dest->base, source};
|
||||
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->base->type->setptr, arg, NULL/*argt*/, 2));
|
||||
}
|
||||
else if (dest->index && dest->base->type->setarr)
|
||||
{
|
||||
QCC_def_t *arg[] = {dest->base, dest->index?QCC_SupplyConversion(dest->index, dest->base->type->setarr->type->params[1].type->type, true):QCC_MakeIntConst(0), source};
|
||||
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->base->type->setarr, arg, NULL/*argt*/, 2));
|
||||
int args = 0;
|
||||
QCC_def_t *arg[3] = {NULL, NULL, NULL};
|
||||
arg[args++] = dest->base;
|
||||
if (dest->accessor->indexertype)
|
||||
arg[args++] = dest->index?QCC_SupplyConversion(dest->index, dest->accessor->indexertype->type, true):QCC_MakeIntConst(0);
|
||||
arg[args++] = source;
|
||||
|
||||
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->accessor->set, arg, NULL/*argt*/, args));
|
||||
}
|
||||
else
|
||||
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, dest->base, "Accessor has no suitable set function");
|
||||
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, dest->base, "Accessor has no set function");
|
||||
break;
|
||||
case REF_FIELD:
|
||||
// {
|
||||
|
|
|
@ -43,6 +43,11 @@ CompilerConstant_t *CompilerConstant;
|
|||
int numCompilerConstants;
|
||||
extern pbool expandedemptymacro;
|
||||
|
||||
//really these should not be in here
|
||||
extern unsigned int locals_end, locals_start;
|
||||
extern QCC_type_t *pr_classtype;
|
||||
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type);
|
||||
|
||||
|
||||
static void Q_strlcpy(char *dest, const char *src, int sizeofdest)
|
||||
{
|
||||
|
@ -3669,11 +3674,7 @@ int typecmp_strict(QCC_type_t *a, QCC_type_t *b)
|
|||
if (a->size != b->size)
|
||||
return 1;
|
||||
|
||||
if (a->getarr != b->getarr ||
|
||||
a->getptr != b->getptr ||
|
||||
a->setarr != b->setarr ||
|
||||
a->setptr != b->setptr ||
|
||||
a->getlength != b->getlength)
|
||||
if (a->accessors != b->accessors)
|
||||
return 1;
|
||||
|
||||
if (STRCMP(a->name, b->name))
|
||||
|
@ -4228,6 +4229,28 @@ QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
|
|||
ptype->size = ptype->aux_type->size;
|
||||
return QCC_PR_FindType (ptype);
|
||||
}
|
||||
QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, QCC_type_t **args, char **argnames, int numargs)
|
||||
{
|
||||
int i;
|
||||
struct QCC_typeparam_s *p;
|
||||
QCC_type_t *ftype;
|
||||
ftype = QCC_PR_NewType("$func", ev_function, false);
|
||||
ftype->aux_type = rettype;
|
||||
ftype->num_parms = numargs;
|
||||
ftype->params = p = qccHunkAlloc(sizeof(*ftype->params)*numargs);
|
||||
ftype->vargs = false;
|
||||
ftype->vargcount = false;
|
||||
for (i = 0; i < numargs; i++, p++)
|
||||
{
|
||||
p->paramname = qccHunkAlloc(strlen(argnames[i])+1);
|
||||
strcpy(p->paramname, argnames[i]);
|
||||
p->type = args[i];
|
||||
p->optional = false;
|
||||
p->ofs = 0;
|
||||
p->arraysize = 0;
|
||||
}
|
||||
return QCC_PR_FindType (ftype);
|
||||
}
|
||||
|
||||
extern char *basictypenames[];
|
||||
extern QCC_type_t **basictypes[];
|
||||
|
@ -4300,6 +4323,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
|||
//accessors
|
||||
if (QCC_PR_CheckKeyword (keyword_class, "accessor"))
|
||||
{
|
||||
char *parentname;
|
||||
char *accessorname;
|
||||
char *funcname;
|
||||
|
||||
|
@ -4323,12 +4347,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
|||
|
||||
if (QCC_PR_CheckToken(":"))
|
||||
{
|
||||
char *parentname = QCC_PR_ParseName();
|
||||
parentname = QCC_PR_ParseName();
|
||||
type = QCC_TypeForName(parentname);
|
||||
|
||||
if (!type || type->type == ev_struct || type->type == ev_union)
|
||||
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
|
||||
}
|
||||
else
|
||||
type = NULL;
|
||||
|
||||
if (!newt)
|
||||
{
|
||||
|
@ -4336,93 +4362,163 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
|||
newt->size=type->size;
|
||||
}
|
||||
if (!newt->parentclass)
|
||||
{
|
||||
newt->parentclass = type;
|
||||
if (!newt->parentclass || newt->parentclass->type == ev_struct || newt->parentclass->type == ev_union || newt->size != newt->parentclass->size)
|
||||
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
|
||||
}
|
||||
else if (type != newt->parentclass)
|
||||
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s basic type mismatch", accessorname);
|
||||
|
||||
if (QCC_PR_CheckToken(":"))
|
||||
if (QCC_PR_CheckToken("{"))
|
||||
{
|
||||
char *parentname = QCC_PR_ParseName();
|
||||
if (newt->aux_type)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Accessor %s was already defined", accessorname);
|
||||
newt->aux_type = QCC_TypeForName(parentname);
|
||||
if (!newt->parentclass || newt->parentclass->type == ev_struct || newt->parentclass->type == ev_union || newt->size != newt->parentclass->size)
|
||||
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
|
||||
struct accessor_s *acc;
|
||||
pbool setnotget;
|
||||
char *fieldtypename;
|
||||
QCC_type_t *fieldtype;
|
||||
QCC_type_t *indextype;
|
||||
QCC_def_t *def;
|
||||
QCC_type_t *functype;
|
||||
char *argname[3];
|
||||
QCC_type_t *arg[3];
|
||||
int args;
|
||||
char *indexname;
|
||||
|
||||
if (QCC_PR_CheckToken("["))
|
||||
{
|
||||
newt->vargcount = true;
|
||||
QCC_PR_Expect("]");
|
||||
}
|
||||
|
||||
QCC_PR_Expect("{");
|
||||
|
||||
do
|
||||
{
|
||||
if (QCC_PR_CheckName("length"))
|
||||
{
|
||||
QCC_PR_Expect("=");
|
||||
funcname = QCC_PR_ParseName();
|
||||
newt->getlength = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
|
||||
if (!newt->getlength)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
|
||||
else if (newt->getlength->type->type != ev_function || newt->getlength->type->num_parms != 1)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "length function unsuitable \"%s\"", funcname);
|
||||
}
|
||||
if (QCC_PR_CheckName("set"))
|
||||
setnotget = true;
|
||||
else if (QCC_PR_CheckName("get"))
|
||||
setnotget = false;
|
||||
else
|
||||
break;
|
||||
|
||||
fieldtypename = QCC_PR_ParseName();
|
||||
fieldtype = QCC_TypeForName(fieldtypename);
|
||||
if (!fieldtype)
|
||||
QCC_PR_ParseError(ERR_NOTATYPE, "Invalid type: %s", fieldtypename);
|
||||
|
||||
if (pr_token_type != tt_punct)
|
||||
{
|
||||
pbool stareq = QCC_PR_CheckToken("*=");
|
||||
if (stareq || QCC_PR_CheckToken("*"))
|
||||
funcname = QCC_PR_ParseName();
|
||||
accessorname = qccHunkAlloc(strlen(funcname)+1);
|
||||
strcpy(accessorname, funcname);
|
||||
}
|
||||
else
|
||||
accessorname = "";
|
||||
|
||||
indextype = NULL;
|
||||
indexname = "index";
|
||||
if (QCC_PR_CheckToken("["))
|
||||
{
|
||||
fieldtypename = QCC_PR_ParseName();
|
||||
indextype = QCC_TypeForName(fieldtypename);
|
||||
|
||||
if (!QCC_PR_CheckToken("]"))
|
||||
{
|
||||
if (!stareq) QCC_PR_Expect("=");
|
||||
funcname = QCC_PR_ParseName();
|
||||
newt->getptr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
|
||||
if (!newt->getptr)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
|
||||
else if (newt->getptr->type->type != ev_function || (newt->getptr->type->num_parms != 1 && !(newt->getptr->type->num_parms > 1 && newt->getptr->type->params[1].optional)))
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "get* function unsuitable \"%s\"", funcname);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (QCC_PR_CheckToken("["))
|
||||
QCC_PR_Expect("]");
|
||||
QCC_PR_Expect("=");
|
||||
funcname = QCC_PR_ParseName();
|
||||
newt->getarr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
|
||||
if (!newt->getarr)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
|
||||
else if (newt->getarr->type->type != ev_function || (newt->getarr->type->num_parms != 2 && !(newt->getarr->type->num_parms > 2 && newt->getarr->type->params[2].optional)))
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "get[] function unsuitable \"%s\"", funcname);
|
||||
indexname = QCC_PR_ParseName();
|
||||
QCC_PR_Expect("]");
|
||||
}
|
||||
}
|
||||
else if (QCC_PR_CheckName("set"))
|
||||
|
||||
QCC_PR_Expect("=");
|
||||
|
||||
args = 0;
|
||||
strcpy (pr_parm_names[args], "this");
|
||||
argname[args] = "this";
|
||||
arg[args++] = newt;
|
||||
if (indextype)
|
||||
{
|
||||
pbool stareq = QCC_PR_CheckToken("*=");
|
||||
if (stareq || QCC_PR_CheckToken("*"))
|
||||
{
|
||||
if (!stareq) QCC_PR_Expect("=");
|
||||
funcname = QCC_PR_ParseName();
|
||||
newt->setptr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
|
||||
if (!newt->setptr)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
|
||||
else if (newt->setptr->type->type != ev_function || (newt->setptr->type->num_parms != 2 && !(newt->setptr->type->num_parms > 2 && newt->setptr->type->params[2].optional)))
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "set* function unsuitable \"%s\"", funcname);
|
||||
}
|
||||
strcpy (pr_parm_names[args], indexname);
|
||||
argname[args] = indexname;
|
||||
arg[args++] = indextype;
|
||||
}
|
||||
if (setnotget)
|
||||
{
|
||||
strcpy (pr_parm_names[args], "value");
|
||||
argname[args] = "value";
|
||||
arg[args++] = fieldtype;
|
||||
}
|
||||
functype = QCC_PR_GenFunctionType(setnotget?type_void:fieldtype, arg, argname, args);
|
||||
|
||||
if (pr_token_type != tt_name)
|
||||
{
|
||||
QCC_function_t *f;
|
||||
QCC_dfunction_t *df;
|
||||
char funcname[256];
|
||||
QC_snprintfz(funcname, sizeof(funcname), "%s::%s_%s", newt->name, setnotget?"set":"get", accessorname);
|
||||
|
||||
def = QCC_PR_GetDef(functype, funcname, NULL, true, 0, GDF_CONST);
|
||||
|
||||
pr_scope = def;
|
||||
//pr_classtype = newt;
|
||||
f = QCC_PR_ParseImmediateStatements (functype);
|
||||
pr_classtype = NULL;
|
||||
pr_scope = NULL;
|
||||
G_FUNCTION(def->ofs) = numfunctions;
|
||||
f->def = def;
|
||||
def->initialized = 1;
|
||||
|
||||
if (numfunctions >= MAX_FUNCTIONS)
|
||||
QCC_Error(ERR_INTERNAL, "Too many function defs");
|
||||
|
||||
// fill in the dfunction
|
||||
df = &functions[numfunctions];
|
||||
numfunctions++;
|
||||
if (f->builtin)
|
||||
df->first_statement = -f->builtin;
|
||||
else
|
||||
df->first_statement = f->code;
|
||||
|
||||
if (f->builtin && opt_function_names)
|
||||
optres_function_names += strlen(f->def->name);
|
||||
else
|
||||
df->s_name = QCC_CopyString (f->def->name);
|
||||
df->s_file = s_file;
|
||||
df->numparms = f->def->type->num_parms;
|
||||
df->locals = locals_end - locals_start;
|
||||
df->parm_start = locals_start;
|
||||
for (i=0 ; i<df->numparms ; i++)
|
||||
{
|
||||
if (QCC_PR_CheckToken("["))
|
||||
QCC_PR_Expect("]");
|
||||
QCC_PR_Expect("=");
|
||||
funcname = QCC_PR_ParseName();
|
||||
newt->setarr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
|
||||
if (!newt->setarr)
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
|
||||
else if (newt->setarr->type->type != ev_function || (newt->setarr->type->num_parms != 3 && !(newt->setarr->type->num_parms > 3 && newt->setarr->type->params[3].optional)))
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "set[] function unsuitable \"%s\"", funcname);
|
||||
df->parm_size[i] = functype->params[i].type->size;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
{
|
||||
funcname = QCC_PR_ParseName();
|
||||
def = QCC_PR_GetDef(functype, funcname, NULL, true, 0, 0);
|
||||
if (!def)
|
||||
QCC_Error(ERR_NOFUNC, "%s::set_%s: %s was not defined", newt->name, accessorname, funcname);
|
||||
}
|
||||
if (!def)
|
||||
QCC_Error(ERR_NOFUNC, "%s::%s_%s function invalid", newt->name, setnotget?"set":"get", accessorname);
|
||||
|
||||
for (acc = newt->accessors; acc; acc = acc->next)
|
||||
if (!strcmp(acc->fieldname, accessorname))
|
||||
break;
|
||||
if (!acc)
|
||||
{
|
||||
acc = qccHunkAlloc(sizeof(*acc));
|
||||
acc->fieldname = accessorname;
|
||||
acc->next = newt->accessors;
|
||||
acc->type = fieldtype;
|
||||
acc->indexertype = indextype;
|
||||
newt->accessors = acc;
|
||||
}
|
||||
|
||||
if (setnotget)
|
||||
{
|
||||
if (acc->set)
|
||||
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::set_%s already declared", newt->name, accessorname);
|
||||
acc->set = def;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (acc->get)
|
||||
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::get_%s already declared", newt->name, accessorname);
|
||||
acc->get = def;
|
||||
}
|
||||
} while (QCC_PR_CheckToken(",") || QCC_PR_CheckToken(";"));
|
||||
QCC_PR_Expect("}");
|
||||
}
|
||||
|
@ -4606,10 +4702,6 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
|||
QCC_Error(ERR_INTERNAL, "Can only initialise member functions");
|
||||
else
|
||||
{
|
||||
extern unsigned int locals_end, locals_start;
|
||||
extern QCC_type_t *pr_classtype;
|
||||
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type);
|
||||
|
||||
if (autoprototype)
|
||||
{
|
||||
QCC_PR_Expect("{");
|
||||
|
|
Loading…
Reference in a new issue