From 0fb5e2bc25463ad20242b47bf4d8ca726efe1f39 Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 8 Sep 2014 23:35:32 +0000 Subject: [PATCH] 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 --- engine/qclib/qcc.h | 16 ++- engine/qclib/qcc_pr_comp.c | 130 ++++++++++++-------- engine/qclib/qcc_pr_lex.c | 246 +++++++++++++++++++++++++------------ 3 files changed, 260 insertions(+), 132 deletions(-) diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index ce41d6489..0b55d6845 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -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; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index aabdb2f08..5dffa328c 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -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: // { diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 1ec4961b3..023ca5064 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -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 ; inumparms ; 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("{");