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:
Spoike 2014-09-08 23:35:32 +00:00
parent abde2fa81b
commit 0fb5e2bc25
3 changed files with 260 additions and 132 deletions

View file

@ -302,6 +302,15 @@ struct QCC_typeparam_s
unsigned int arraysize; unsigned int arraysize;
char *paramname; 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 typedef struct QCC_type_s
{ {
@ -321,11 +330,7 @@ typedef struct QCC_type_s
char *name; char *name;
char *aname; char *aname;
struct QCC_def_s *getptr; struct accessor_s *accessors;
struct QCC_def_s *getarr;
struct QCC_def_s *setptr;
struct QCC_def_s *setarr;
struct QCC_def_s *getlength;
} QCC_type_t; } QCC_type_t;
int typecmp(QCC_type_t *a, QCC_type_t *b); int typecmp(QCC_type_t *a, QCC_type_t *b);
int typecmp_lax(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 *base;
QCC_def_t *index; QCC_def_t *index;
QCC_type_t *cast; //entity.float is float, not pointer. 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 int postinc; //+1 or -1
pbool readonly; //for whatever reason, like base being a const pbool readonly; //for whatever reason, like base being a const
} QCC_ref_t; } QCC_ref_t;

View file

@ -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_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_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_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); 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); 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: case OP_ADD_FI:
numstatements--; numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0); 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: case OP_BITAND_FI:
numstatements--; numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0); 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: case OP_BITOR_FI:
numstatements--; numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0); 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: case OP_LT_FI:
numstatements--; numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0); 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 //statements where the lhs is a const int and can be swapped with a float
case OP_ADD_IF: case OP_ADD_IF:
numstatements--; 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); 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(); char *fieldname = QCC_PR_ParseName();
if (!t->aux_type) struct accessor_s *acc;
QCC_PR_ParseError(ERR_INTERNAL, "Accessor %s was not defined yet", t->name);
else if (!strcmp(fieldname, "length")) for (acc = t->accessors; acc; acc = acc->next)
{ if (!strcmp(acc->fieldname, fieldname))
QCC_def_t *obj = QCC_RefToDef(lhs, true); {
obj = QCC_PR_GenerateFunctionCall(NULL, t->getlength, &obj, &t->parentclass, 1); if (acc->indexertype)
lhs = QCC_PR_BuildRef(refbuf, REF_GLOBAL, obj, NULL, obj->type, true); {
lhs = QCC_PR_ParseField(refbuf, lhs); QCC_PR_Expect("[");
} index = QCC_PR_Expression (TOP_PRIORITY, 0);
else QCC_PR_Expect("]");
{ }
//these are not defs, but weird crap. break;
QCC_def_t *index = QCC_MakeStringConst(fieldname); }
pbool noset = !t->setarr && !t->setptr; if (!acc)
lhs = QCC_PR_BuildRef(refbuf, REF_ACCESSOR, QCC_RefToDef(lhs, true), index, t->aux_type, lhs->readonly || noset); for (acc = t->accessors; acc; acc = acc->next)
lhs = QCC_PR_ParseField(refbuf, lhs); 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; 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_string) || //strings are effectively pointers
(t->type == ev_vector) || //vectors are mini arrays (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_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("[")) 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); tmp = QCC_PR_Expression (TOP_PRIORITY, 0);
QCC_PR_Expect("]"); QCC_PR_Expect("]");
if (!arraysize && t->type == ev_accessor) if (!arraysize && t->accessors)
{ {
if (!t->aux_type) struct accessor_s *acc;
QCC_PR_ParseError(ERR_INTERNAL, "Accessor %s was not defined yet", t->name); for (acc = t->accessors; acc; acc = acc->next)
r = QCC_PR_BuildRef(retbuf, REF_ACCESSOR, QCC_RefToDef(r, true), tmp, t->aux_type, r->readonly || (!t->setarr && !t->setptr)); if (!*acc->fieldname)
return QCC_PR_ParseRefArrayPointer(retbuf, r, allowarrayassign, makearraypointers); 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*/ /*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); e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
if (e->type->type == ev_pointer) if (e->type->type == ev_pointer)
return QCC_PR_BuildRef(retbuf, REF_POINTER, e, NULL, e->type->aux_type, false); return QCC_PR_BuildRef(retbuf, REF_POINTER, e, NULL, e->type->aux_type, false);
else if (e->type->type == ev_accessor) else if (e->type->accessors)
return QCC_PR_BuildRef(retbuf, REF_ACCESSOR, e, NULL, e->type->aux_type, !e->type->setptr); {
else struct accessor_s *acc;
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCH, e, "Unable to dereference non-pointer type."); 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 ("-")) 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) 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; retbuf->postinc = 0;
@ -6624,18 +6654,17 @@ QCC_def_t *QCC_RefToDef(QCC_ref_t *ref, pbool freetemps)
case REF_STRING: case REF_STRING:
return QCC_PR_StatementFlags(&pr_opcodes[OP_LOADP_C], ref->base, ref->index, NULL, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB)); return QCC_PR_StatementFlags(&pr_opcodes[OP_LOADP_C], ref->base, ref->index, NULL, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB));
case REF_ACCESSOR: case REF_ACCESSOR:
if (!ref->index && ref->base->type->getptr) if (ref->accessor && ref->accessor->get)
{ {
QCC_def_t *arg[] = {ref->base}; int args = 0;
return QCC_PR_GenerateFunctionCall(NULL, ref->base->type->getptr, arg, NULL, 1); QCC_def_t *arg[2] = {NULL, NULL};
} arg[args++] = ref->base;
else if (ref->base->type->getarr) if (ref->accessor->indexertype)
{ arg[args++] = ref->index?QCC_SupplyConversion(ref->index, ref->accessor->indexertype->type, true):QCC_MakeIntConst(0);
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->accessor->get, arg, NULL, args);
return QCC_PR_GenerateFunctionCall(NULL, ref->base->type->getarr, arg, NULL, 2);
} }
else 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; break;
} }
if (ref->cast != ret->type) 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; break;
case REF_ACCESSOR: case REF_ACCESSOR:
if (!dest->index && dest->base->type->setptr) if (dest->accessor && dest->accessor->set)
{ {
QCC_def_t *arg[] = {dest->base, source}; int args = 0;
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->base->type->setptr, arg, NULL/*argt*/, 2)); QCC_def_t *arg[3] = {NULL, NULL, NULL};
} arg[args++] = dest->base;
else if (dest->index && dest->base->type->setarr) if (dest->accessor->indexertype)
{ arg[args++] = dest->index?QCC_SupplyConversion(dest->index, dest->accessor->indexertype->type, true):QCC_MakeIntConst(0);
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}; arg[args++] = source;
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->base->type->setarr, arg, NULL/*argt*/, 2));
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->accessor->set, arg, NULL/*argt*/, args));
} }
else 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; break;
case REF_FIELD: case REF_FIELD:
// { // {

View file

@ -43,6 +43,11 @@ CompilerConstant_t *CompilerConstant;
int numCompilerConstants; int numCompilerConstants;
extern pbool expandedemptymacro; 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) 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) if (a->size != b->size)
return 1; return 1;
if (a->getarr != b->getarr || if (a->accessors != b->accessors)
a->getptr != b->getptr ||
a->setarr != b->setarr ||
a->setptr != b->setptr ||
a->getlength != b->getlength)
return 1; return 1;
if (STRCMP(a->name, b->name)) 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; ptype->size = ptype->aux_type->size;
return QCC_PR_FindType (ptype); 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 char *basictypenames[];
extern QCC_type_t **basictypes[]; extern QCC_type_t **basictypes[];
@ -4300,6 +4323,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
//accessors //accessors
if (QCC_PR_CheckKeyword (keyword_class, "accessor")) if (QCC_PR_CheckKeyword (keyword_class, "accessor"))
{ {
char *parentname;
char *accessorname; char *accessorname;
char *funcname; char *funcname;
@ -4323,12 +4347,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (QCC_PR_CheckToken(":")) if (QCC_PR_CheckToken(":"))
{ {
char *parentname = QCC_PR_ParseName(); parentname = QCC_PR_ParseName();
type = QCC_TypeForName(parentname); type = QCC_TypeForName(parentname);
if (!type || type->type == ev_struct || type->type == ev_union) if (!type || type->type == ev_struct || type->type == ev_union)
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname); QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
} }
else
type = NULL;
if (!newt) if (!newt)
{ {
@ -4336,93 +4362,163 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
newt->size=type->size; newt->size=type->size;
} }
if (!newt->parentclass) if (!newt->parentclass)
{
newt->parentclass = type; 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) else if (type != newt->parentclass)
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s basic type mismatch", accessorname); QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s basic type mismatch", accessorname);
if (QCC_PR_CheckToken(":")) if (QCC_PR_CheckToken("{"))
{ {
char *parentname = QCC_PR_ParseName(); struct accessor_s *acc;
if (newt->aux_type) pbool setnotget;
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Accessor %s was already defined", accessorname); char *fieldtypename;
newt->aux_type = QCC_TypeForName(parentname); QCC_type_t *fieldtype;
if (!newt->parentclass || newt->parentclass->type == ev_struct || newt->parentclass->type == ev_union || newt->size != newt->parentclass->size) QCC_type_t *indextype;
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname); 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 do
{ {
if (QCC_PR_CheckName("length")) if (QCC_PR_CheckName("set"))
{ setnotget = true;
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);
}
else if (QCC_PR_CheckName("get")) 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("*="); funcname = QCC_PR_ParseName();
if (stareq || QCC_PR_CheckToken("*")) 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("="); indexname = QCC_PR_ParseName();
funcname = QCC_PR_ParseName(); QCC_PR_Expect("]");
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);
} }
} }
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("*="); strcpy (pr_parm_names[args], indexname);
if (stareq || QCC_PR_CheckToken("*")) argname[args] = indexname;
{ arg[args++] = indextype;
if (!stareq) QCC_PR_Expect("="); }
funcname = QCC_PR_ParseName(); if (setnotget)
newt->setptr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0); {
if (!newt->setptr) strcpy (pr_parm_names[args], "value");
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname); argname[args] = "value";
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))) arg[args++] = fieldtype;
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "set* function unsuitable \"%s\"", funcname); }
} 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 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("[")) df->parm_size[i] = functype->params[i].type->size;
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);
} }
} }
else 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(";")); } while (QCC_PR_CheckToken(",") || QCC_PR_CheckToken(";"));
QCC_PR_Expect("}"); 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"); QCC_Error(ERR_INTERNAL, "Can only initialise member functions");
else 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) if (autoprototype)
{ {
QCC_PR_Expect("{"); QCC_PR_Expect("{");