mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-22 20:11:44 +00:00
A quick attempt to get accessors working inside classes. Needs proper testing.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5945 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
4ac09f8a03
commit
3d1014efe4
2 changed files with 254 additions and 181 deletions
|
@ -1886,7 +1886,20 @@ static const char *QCC_GetRefName(QCC_ref_t *ref, char *buffer, size_t buffersiz
|
||||||
QC_snprintfz(buffer, buffersize, "%s->%s", QCC_GetSRefName(ref->base), QCC_GetSRefName(ref->index));
|
QC_snprintfz(buffer, buffersize, "%s->%s", QCC_GetSRefName(ref->base), QCC_GetSRefName(ref->index));
|
||||||
return buffer;
|
return buffer;
|
||||||
case REF_ACCESSOR:
|
case REF_ACCESSOR:
|
||||||
//FIXME
|
if (*ref->accessor->fieldname)
|
||||||
|
{ //not an anonymous field
|
||||||
|
if (ref->index.sym)
|
||||||
|
QC_snprintfz(buffer, buffersize, "%s.%s[%s]", QCC_GetSRefName(ref->base), ref->accessor->fieldname, QCC_GetSRefName(ref->index));
|
||||||
|
else
|
||||||
|
QC_snprintfz(buffer, buffersize, "%s.%s", QCC_GetSRefName(ref->base), ref->accessor->fieldname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ref->index.sym)
|
||||||
|
QC_snprintfz(buffer, buffersize, "%s[%s]", QCC_GetSRefName(ref->base), QCC_GetSRefName(ref->index));
|
||||||
|
else
|
||||||
|
QC_snprintfz(buffer, buffersize, "*%s", QCC_GetSRefName(ref->base));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case REF_ARRAYHEAD:
|
case REF_ARRAYHEAD:
|
||||||
case REF_GLOBAL:
|
case REF_GLOBAL:
|
||||||
|
@ -8728,78 +8741,95 @@ static QCC_ref_t *QCC_PR_ParseField(QCC_ref_t *refbuf, QCC_ref_t *lhs)
|
||||||
{
|
{
|
||||||
QCC_type_t *t;
|
QCC_type_t *t;
|
||||||
t = lhs->cast;
|
t = lhs->cast;
|
||||||
if (t->type == ev_entity && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
|
if ((t->accessors || t->type == ev_entity) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
|
||||||
{
|
{
|
||||||
QCC_ref_t *field;
|
QCC_ref_t *field;
|
||||||
QCC_ref_t fieldbuf;
|
QCC_ref_t fieldbuf;
|
||||||
if (QCC_PR_CheckToken("("))
|
|
||||||
{
|
|
||||||
field = QCC_PR_RefExpression(&fieldbuf, TOP_PRIORITY, 0);
|
|
||||||
QCC_PR_Expect(")");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
field = QCC_PR_ParseRefValue(&fieldbuf, t, false, false, true);
|
|
||||||
if (field->type != REF_ARRAYHEAD && (field->cast->type == ev_field || field->cast->type == ev_variant))
|
|
||||||
{
|
|
||||||
//fields are generally always readonly. that refers to the field def itself, rather than products of said field.
|
|
||||||
//entities, like 'world' might also be consts. just ignore that fact. the def itself is not assigned, but the fields of said def.
|
|
||||||
//the engine may have a problem with this, but the qcc has no way to referenced locations as readonly separately from the def itself.
|
|
||||||
lhs = QCC_PR_BuildRef(refbuf, REF_FIELD, QCC_RefToDef(lhs, true), QCC_RefToDef(field, true), (field->cast->type == ev_field)?field->cast->aux_type:type_variant, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (field->type == REF_GLOBAL && strstr(QCC_GetSRefName(field->base), "::"))
|
|
||||||
{
|
|
||||||
QCC_sref_t theent = QCC_RefToDef(lhs, true);
|
|
||||||
*refbuf = *field;
|
|
||||||
refbuf->type = REF_NONVIRTUAL;
|
|
||||||
refbuf->index = theent;
|
|
||||||
return refbuf;
|
|
||||||
}
|
|
||||||
if (t->parentclass)
|
|
||||||
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a field of class %s", QCC_GetSRefName(QCC_RefToDef(field, false)), t->name);
|
|
||||||
else
|
|
||||||
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a field", QCC_GetSRefName(QCC_RefToDef(field, false)));
|
|
||||||
}
|
|
||||||
|
|
||||||
lhs = QCC_PR_ParseField(refbuf, lhs);
|
if (pr_token_type == tt_name)
|
||||||
|
{
|
||||||
|
QCC_sref_t index = nullsref;
|
||||||
|
char *fieldname = pr_token;
|
||||||
|
struct accessor_s *acc = NULL, *anon = NULL;
|
||||||
|
QCC_type_t *a;
|
||||||
|
|
||||||
lhs = QCC_PR_ParseRefArrayPointer (refbuf, lhs, false, false);
|
for (a = t; a && !acc; a = a->parentclass)
|
||||||
}
|
for (acc = a->accessors; acc; acc = acc->next)
|
||||||
else if (t->accessors && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
|
|
||||||
{
|
|
||||||
QCC_sref_t index = nullsref;
|
|
||||||
char *fieldname = QCC_PR_ParseName();
|
|
||||||
struct accessor_s *acc;
|
|
||||||
|
|
||||||
for (acc = t->accessors; acc; acc = acc->next)
|
|
||||||
if (!strcmp(acc->fieldname, fieldname))
|
|
||||||
{
|
|
||||||
if (acc->indexertype)
|
|
||||||
{
|
{
|
||||||
if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
|
if (!*acc->fieldname && acc->indexertype)
|
||||||
index = QCC_MakeStringConst(QCC_PR_ParseName());
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
QCC_PR_Expect("[");
|
if (!anon)
|
||||||
index = QCC_PR_Expression (TOP_PRIORITY, 0);
|
anon = acc;
|
||||||
QCC_PR_Expect("]");
|
}
|
||||||
|
else if (!strcmp(acc->fieldname, fieldname))
|
||||||
|
{
|
||||||
|
fieldname = QCC_PR_ParseName(); //do it for real now.
|
||||||
|
if (acc->indexertype)
|
||||||
|
{
|
||||||
|
if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
|
||||||
|
index = QCC_MakeStringConst(QCC_PR_ParseName());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QCC_PR_Expect("[");
|
||||||
|
index = QCC_PR_Expression (TOP_PRIORITY, 0);
|
||||||
|
QCC_PR_Expect("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
if (!acc && anon)
|
||||||
|
{
|
||||||
|
acc = anon;
|
||||||
|
fieldname = QCC_PR_ParseName(); //do it for real now.
|
||||||
|
index = QCC_MakeStringConst(fieldname);
|
||||||
}
|
}
|
||||||
if (!acc)
|
if (acc)
|
||||||
for (acc = t->accessors; acc; acc = acc->next)
|
{
|
||||||
if (!*acc->fieldname && acc->indexertype)
|
lhs = QCC_PR_BuildAccessorRef(refbuf, QCC_RefToDef(lhs, true), index, acc, lhs->readonly);
|
||||||
{
|
lhs = QCC_PR_ParseField(refbuf, lhs);
|
||||||
index = QCC_MakeStringConst(fieldname);
|
return lhs;
|
||||||
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);
|
if (t->type == ev_entity)
|
||||||
lhs = QCC_PR_ParseField(refbuf, lhs);
|
{
|
||||||
|
if (QCC_PR_CheckToken("("))
|
||||||
|
{
|
||||||
|
field = QCC_PR_RefExpression(&fieldbuf, TOP_PRIORITY, 0);
|
||||||
|
QCC_PR_Expect(")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
field = QCC_PR_ParseRefValue(&fieldbuf, t, false, false, true);
|
||||||
|
if (field->type != REF_ARRAYHEAD && (field->cast->type == ev_field || field->cast->type == ev_variant))
|
||||||
|
{
|
||||||
|
//fields are generally always readonly. that refers to the field def itself, rather than products of said field.
|
||||||
|
//entities, like 'world' might also be consts. just ignore that fact. the def itself is not assigned, but the fields of said def.
|
||||||
|
//the engine may have a problem with this, but the qcc has no way to referenced locations as readonly separately from the def itself.
|
||||||
|
lhs = QCC_PR_BuildRef(refbuf, REF_FIELD, QCC_RefToDef(lhs, true), QCC_RefToDef(field, true), (field->cast->type == ev_field)?field->cast->aux_type:type_variant, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (field->type == REF_GLOBAL && strstr(QCC_GetSRefName(field->base), "::"))
|
||||||
|
{
|
||||||
|
QCC_sref_t theent = QCC_RefToDef(lhs, true);
|
||||||
|
*refbuf = *field;
|
||||||
|
refbuf->type = REF_NONVIRTUAL;
|
||||||
|
refbuf->index = theent;
|
||||||
|
return refbuf;
|
||||||
|
}
|
||||||
|
if (t->parentclass)
|
||||||
|
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a field of class %s", QCC_GetSRefName(QCC_RefToDef(field, false)), t->name);
|
||||||
|
else
|
||||||
|
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a field", QCC_GetSRefName(QCC_RefToDef(field, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
lhs = QCC_PR_ParseField(refbuf, lhs);
|
||||||
|
|
||||||
|
lhs = QCC_PR_ParseRefArrayPointer (refbuf, lhs, false, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a member of %s", QCC_PR_ParseName(), t->name);
|
||||||
}
|
}
|
||||||
else if (flag_qccx && t->type == ev_entity && QCC_PR_CheckToken("["))
|
else if (flag_qccx && t->type == ev_entity && QCC_PR_CheckToken("["))
|
||||||
{ //p[%0] gives a regular array reference. except that p is probably a float, and we're expecting OP_LOAD_F
|
{ //p[%0] gives a regular array reference. except that p is probably a float, and we're expecting OP_LOAD_F
|
||||||
|
@ -9522,6 +9552,7 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
|
||||||
{
|
{
|
||||||
for(type = assumeclass; type && !d.cast; type = type->parentclass)
|
for(type = assumeclass; type && !d.cast; type = type->parentclass)
|
||||||
{
|
{
|
||||||
|
|
||||||
//look for virtual things
|
//look for virtual things
|
||||||
QC_snprintfz(membername, sizeof(membername), "%s::"MEMBERFIELDNAME, type->name, name);
|
QC_snprintfz(membername, sizeof(membername), "%s::"MEMBERFIELDNAME, type->name, name);
|
||||||
d = QCC_PR_GetSRef (NULL, membername, pr_scope, false, 0, false);
|
d = QCC_PR_GetSRef (NULL, membername, pr_scope, false, 0, false);
|
||||||
|
|
|
@ -5248,6 +5248,142 @@ QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s
|
||||||
return QCC_PR_FindType (ftype);
|
return QCC_PR_FindType (ftype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct accessor_s *QCC_PR_ParseAccessorMember(QCC_type_t *classtype, pbool isinline, pbool setnotget)
|
||||||
|
{
|
||||||
|
struct accessor_s *acc, *pacc;
|
||||||
|
char *fieldtypename;
|
||||||
|
QCC_type_t *fieldtype;
|
||||||
|
QCC_type_t *indextype;
|
||||||
|
QCC_sref_t def;
|
||||||
|
QCC_type_t *functype;
|
||||||
|
QCC_type_t *parenttype;
|
||||||
|
struct QCC_typeparam_s arg[3];
|
||||||
|
int args;
|
||||||
|
char *indexname;
|
||||||
|
pbool isref;
|
||||||
|
char *accessorname;
|
||||||
|
|
||||||
|
if (QCC_PR_CheckToken("&"))
|
||||||
|
isref = 2;
|
||||||
|
else
|
||||||
|
isref = QCC_PR_CheckToken("*");
|
||||||
|
|
||||||
|
fieldtypename = QCC_PR_ParseName();
|
||||||
|
fieldtype = QCC_TypeForName(fieldtypename);
|
||||||
|
if (!fieldtype)
|
||||||
|
QCC_PR_ParseError(ERR_NOTATYPE, "Invalid type: %s", fieldtypename);
|
||||||
|
while(QCC_PR_CheckToken("*"))
|
||||||
|
fieldtype = QCC_PR_PointerType(fieldtype);
|
||||||
|
|
||||||
|
if (pr_token_type != tt_punct)
|
||||||
|
accessorname = QCC_PR_ParseName();
|
||||||
|
else
|
||||||
|
accessorname = "";
|
||||||
|
|
||||||
|
indextype = NULL;
|
||||||
|
indexname = "index";
|
||||||
|
if (QCC_PR_CheckToken("["))
|
||||||
|
{
|
||||||
|
fieldtypename = QCC_PR_ParseName();
|
||||||
|
indextype = QCC_TypeForName(fieldtypename);
|
||||||
|
|
||||||
|
if (!QCC_PR_CheckToken("]"))
|
||||||
|
{
|
||||||
|
indexname = QCC_PR_ParseName();
|
||||||
|
QCC_PR_Expect("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QCC_PR_Expect("=");
|
||||||
|
|
||||||
|
args = 0;
|
||||||
|
memset(arg, 0, sizeof(arg));
|
||||||
|
strcpy (pr_parm_names[args], "this");
|
||||||
|
arg[args].paramname = "this";
|
||||||
|
if (isref == 2)
|
||||||
|
{
|
||||||
|
arg[args].type = classtype;
|
||||||
|
arg[args].out = 1; //inout
|
||||||
|
}
|
||||||
|
else if (isref)
|
||||||
|
arg[args].type = QCC_PointerTypeTo(classtype);
|
||||||
|
else
|
||||||
|
arg[args].type = classtype;
|
||||||
|
args++;
|
||||||
|
if (indextype)
|
||||||
|
{
|
||||||
|
strcpy (pr_parm_names[args], indexname);
|
||||||
|
arg[args].paramname = indexname;
|
||||||
|
arg[args++].type = indextype;
|
||||||
|
}
|
||||||
|
if (setnotget)
|
||||||
|
{
|
||||||
|
strcpy (pr_parm_names[args], "value");
|
||||||
|
arg[args].paramname = "value";
|
||||||
|
arg[args++].type = fieldtype;
|
||||||
|
}
|
||||||
|
functype = QCC_PR_GenFunctionType(setnotget?type_void:fieldtype, arg, args);
|
||||||
|
|
||||||
|
if (pr_token_type != tt_name)
|
||||||
|
{
|
||||||
|
QCC_function_t *f;
|
||||||
|
char funcname[256];
|
||||||
|
QC_snprintfz(funcname, sizeof(funcname), "%s::%s_%s", classtype->name, setnotget?"set":"get", accessorname);
|
||||||
|
|
||||||
|
def = QCC_PR_GetSRef(functype, funcname, NULL, true, 0, GDF_CONST | (isinline?GDF_INLINE:0));
|
||||||
|
|
||||||
|
pr_classtype = ((classtype->type==ev_entity)?classtype:NULL);
|
||||||
|
f = QCC_PR_ParseImmediateStatements (def.sym, functype, false);
|
||||||
|
pr_classtype = NULL;
|
||||||
|
pr_scope = NULL;
|
||||||
|
def.sym->symboldata[def.ofs].function = f - functions;
|
||||||
|
f->def = def.sym;
|
||||||
|
def.sym->initialized = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *funcname = QCC_PR_ParseName();
|
||||||
|
def = QCC_PR_GetSRef(functype, funcname, NULL, true, 0, GDF_CONST|(isinline?GDF_INLINE:0));
|
||||||
|
if (!def.cast)
|
||||||
|
QCC_Error(ERR_NOFUNC, "%s::set_%s: %s was not defined", classtype->name, accessorname, funcname);
|
||||||
|
}
|
||||||
|
if (!def.cast || !def.sym || def.sym->temp)
|
||||||
|
QCC_Error(ERR_NOFUNC, "%s::%s_%s function invalid", classtype->name, setnotget?"set":"get", accessorname);
|
||||||
|
|
||||||
|
for (acc = classtype->accessors; acc; acc = acc->next)
|
||||||
|
if (!strcmp(acc->fieldname, accessorname))
|
||||||
|
break;
|
||||||
|
if (!acc)
|
||||||
|
{
|
||||||
|
acc = qccHunkAlloc(sizeof(*acc));
|
||||||
|
acc->fieldname = accessorname;
|
||||||
|
acc->next = classtype->accessors;
|
||||||
|
acc->type = fieldtype;
|
||||||
|
acc->indexertype = indextype;
|
||||||
|
classtype->accessors = acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acc->getset_func[setnotget].cast)
|
||||||
|
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::%s_%s already declared", classtype->name, setnotget?"set":"get", accessorname);
|
||||||
|
acc->getset_func[setnotget] = def;
|
||||||
|
acc->getset_isref[setnotget] = isref;
|
||||||
|
QCC_FreeTemp(def);
|
||||||
|
|
||||||
|
for (parenttype = classtype->parentclass; parenttype; parenttype = parenttype->parentclass)
|
||||||
|
{
|
||||||
|
if (!parenttype->accessors)
|
||||||
|
continue;
|
||||||
|
for (pacc = parenttype->accessors; pacc; pacc = pacc->next)
|
||||||
|
{
|
||||||
|
if (!strcmp(acc->fieldname, pacc->fieldname))
|
||||||
|
QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s::%s shadows parent %s", classtype->name, acc->fieldname?acc->fieldname:"<anon>", parenttype->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
extern char *basictypenames[];
|
extern char *basictypenames[];
|
||||||
extern QCC_type_t **basictypes[];
|
extern QCC_type_t **basictypes[];
|
||||||
pbool type_inlinefunction;
|
pbool type_inlinefunction;
|
||||||
|
@ -5404,20 +5540,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
|
|
||||||
if (QCC_PR_CheckToken("{"))
|
if (QCC_PR_CheckToken("{"))
|
||||||
{
|
{
|
||||||
struct accessor_s *acc;
|
|
||||||
pbool setnotget;
|
pbool setnotget;
|
||||||
char *fieldtypename;
|
|
||||||
QCC_type_t *fieldtype;
|
|
||||||
QCC_type_t *indextype;
|
|
||||||
QCC_sref_t def;
|
|
||||||
QCC_type_t *functype;
|
|
||||||
struct QCC_typeparam_s arg[3];
|
|
||||||
int args;
|
|
||||||
char *indexname;
|
|
||||||
pbool isref;
|
|
||||||
pbool isinline;
|
pbool isinline;
|
||||||
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
isinline = QCC_PR_CheckName("inline");
|
isinline = QCC_PR_CheckName("inline");
|
||||||
|
@ -5428,115 +5553,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
setnotget = false;
|
setnotget = false;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
if (QCC_PR_CheckToken("&"))
|
|
||||||
isref = 2;
|
|
||||||
else
|
|
||||||
isref = QCC_PR_CheckToken("*");
|
|
||||||
|
|
||||||
fieldtypename = QCC_PR_ParseName();
|
QCC_PR_ParseAccessorMember(newt, isinline, setnotget);
|
||||||
fieldtype = QCC_TypeForName(fieldtypename);
|
|
||||||
if (!fieldtype)
|
|
||||||
QCC_PR_ParseError(ERR_NOTATYPE, "Invalid type: %s", fieldtypename);
|
|
||||||
while(QCC_PR_CheckToken("*"))
|
|
||||||
fieldtype = QCC_PR_PointerType(fieldtype);
|
|
||||||
|
|
||||||
if (pr_token_type != tt_punct)
|
|
||||||
{
|
|
||||||
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("]"))
|
|
||||||
{
|
|
||||||
indexname = QCC_PR_ParseName();
|
|
||||||
QCC_PR_Expect("]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QCC_PR_Expect("=");
|
|
||||||
|
|
||||||
args = 0;
|
|
||||||
memset(arg, 0, sizeof(arg));
|
|
||||||
strcpy (pr_parm_names[args], "this");
|
|
||||||
arg[args].paramname = "this";
|
|
||||||
if (isref == 2)
|
|
||||||
{
|
|
||||||
arg[args].type = newt;
|
|
||||||
arg[args].out = 1; //inout
|
|
||||||
}
|
|
||||||
else if (isref)
|
|
||||||
arg[args].type = QCC_PointerTypeTo(newt);
|
|
||||||
else
|
|
||||||
arg[args].type = newt;
|
|
||||||
args++;
|
|
||||||
if (indextype)
|
|
||||||
{
|
|
||||||
strcpy (pr_parm_names[args], indexname);
|
|
||||||
arg[args].paramname = indexname;
|
|
||||||
arg[args++].type = indextype;
|
|
||||||
}
|
|
||||||
if (setnotget)
|
|
||||||
{
|
|
||||||
strcpy (pr_parm_names[args], "value");
|
|
||||||
arg[args].paramname = "value";
|
|
||||||
arg[args++].type = fieldtype;
|
|
||||||
}
|
|
||||||
functype = QCC_PR_GenFunctionType(setnotget?type_void:fieldtype, arg, args);
|
|
||||||
|
|
||||||
if (pr_token_type != tt_name)
|
|
||||||
{
|
|
||||||
QCC_function_t *f;
|
|
||||||
char funcname[256];
|
|
||||||
QC_snprintfz(funcname, sizeof(funcname), "%s::%s_%s", newt->name, setnotget?"set":"get", accessorname);
|
|
||||||
|
|
||||||
def = QCC_PR_GetSRef(functype, funcname, NULL, true, 0, GDF_CONST | (isinline?GDF_INLINE:0));
|
|
||||||
|
|
||||||
//pr_classtype = newt;
|
|
||||||
f = QCC_PR_ParseImmediateStatements (def.sym, functype, false);
|
|
||||||
pr_classtype = NULL;
|
|
||||||
pr_scope = NULL;
|
|
||||||
def.sym->symboldata[def.ofs].function = f - functions;
|
|
||||||
f->def = def.sym;
|
|
||||||
def.sym->initialized = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
funcname = QCC_PR_ParseName();
|
|
||||||
def = QCC_PR_GetSRef(functype, funcname, NULL, true, 0, GDF_CONST|(isinline?GDF_INLINE:0));
|
|
||||||
if (!def.cast)
|
|
||||||
QCC_Error(ERR_NOFUNC, "%s::set_%s: %s was not defined", newt->name, accessorname, funcname);
|
|
||||||
}
|
|
||||||
if (!def.cast || !def.sym || def.sym->temp)
|
|
||||||
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 (acc->getset_func[setnotget].cast)
|
|
||||||
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::%s_%s already declared", newt->name, setnotget?"set":"get", accessorname);
|
|
||||||
acc->getset_func[setnotget] = def;
|
|
||||||
acc->getset_isref[setnotget] = isref;
|
|
||||||
QCC_FreeTemp(def);
|
|
||||||
} while (QCC_PR_CheckToken(",") || QCC_PR_CheckToken(";"));
|
} while (QCC_PR_CheckToken(",") || QCC_PR_CheckToken(";"));
|
||||||
QCC_PR_Expect("}");
|
QCC_PR_Expect("}");
|
||||||
}
|
}
|
||||||
|
@ -5619,6 +5637,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
pbool isnonvirt = false;
|
pbool isnonvirt = false;
|
||||||
pbool isstatic = false;
|
pbool isstatic = false;
|
||||||
pbool isignored = false;
|
pbool isignored = false;
|
||||||
|
pbool isinline = false;
|
||||||
|
pbool isget = false;
|
||||||
|
pbool isset = false;
|
||||||
// pbool ispublic = false;
|
// pbool ispublic = false;
|
||||||
// pbool isprivate = false;
|
// pbool isprivate = false;
|
||||||
// pbool isprotected = false;
|
// pbool isprotected = false;
|
||||||
|
@ -5634,6 +5655,12 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
isignored = true;
|
isignored = true;
|
||||||
else if (QCC_PR_CheckKeyword(1, "strip"))
|
else if (QCC_PR_CheckKeyword(1, "strip"))
|
||||||
isignored = true;
|
isignored = true;
|
||||||
|
else if (QCC_PR_CheckKeyword(1, "inline"))
|
||||||
|
isinline = true;
|
||||||
|
else if (QCC_PR_CheckKeyword(1, "get"))
|
||||||
|
isget = true;
|
||||||
|
else if (QCC_PR_CheckKeyword(1, "set"))
|
||||||
|
isset = true;
|
||||||
else if (QCC_PR_CheckKeyword(1, "public"))
|
else if (QCC_PR_CheckKeyword(1, "public"))
|
||||||
/*ispublic = true*/;
|
/*ispublic = true*/;
|
||||||
else if (QCC_PR_CheckKeyword(1, "private"))
|
else if (QCC_PR_CheckKeyword(1, "private"))
|
||||||
|
@ -5651,6 +5678,17 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
assumevirtual = -1;
|
assumevirtual = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (isget || isset)
|
||||||
|
{
|
||||||
|
if (isvirt)
|
||||||
|
QCC_PR_ParseWarning(ERR_INTERNAL, "virtual accessors are not supported at this time");
|
||||||
|
if (isstatic)
|
||||||
|
QCC_PR_ParseError(ERR_INTERNAL, "static accessors are not supported");
|
||||||
|
QCC_PR_ParseAccessorMember(newt, isinline, isset);
|
||||||
|
QCC_PR_CheckToken(";");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
newparm = QCC_PR_ParseType(false, false);
|
newparm = QCC_PR_ParseType(false, false);
|
||||||
|
|
||||||
if (!newparm)
|
if (!newparm)
|
||||||
|
@ -5700,6 +5738,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
{
|
{
|
||||||
if (isvirt||isnonvirt)
|
if (isvirt||isnonvirt)
|
||||||
QCC_Error(ERR_INTERNAL, "virtual keyword on member that is not a function");
|
QCC_Error(ERR_INTERNAL, "virtual keyword on member that is not a function");
|
||||||
|
if (isinline)
|
||||||
|
QCC_Error(ERR_INTERNAL, "inline keyword on member that is not a function");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newparm->type == ev_function)
|
if (newparm->type == ev_function)
|
||||||
|
@ -5710,6 +5750,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
||||||
}
|
}
|
||||||
else if (pr_token[0] == '{')
|
else if (pr_token[0] == '{')
|
||||||
havebody = true;
|
havebody = true;
|
||||||
|
if (isinline && (!havebody || isvirt))
|
||||||
|
QCC_Error(ERR_INTERNAL, "inline keyword on function prototype or virtual function");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (havebody)
|
if (havebody)
|
||||||
|
|
Loading…
Reference in a new issue