📄 transform.c
字号:
{ fatalScopedName(classFQCName(scope)); fatal(" unsupported ctor argument type - provide %%MethodCode and a C++ signature\n"); } ifaceFileIsUsed(pt, scope->iff, ad); scopeDefaultValue(pt,scope,ad); }}/* * Resolve the types of a function. */static void resolveFuncTypes(sipSpec *pt, moduleDef *mod, classDef *scope, overDef *od){ argDef *res; /* Handle any C++ signature. */ if (od -> cppsig != &od -> pysig) { int a; getBaseType(pt,mod, scope, &od->cppsig->result); for (a = 0; a < od -> cppsig -> nrArgs; ++a) getBaseType(pt, mod, scope, &od->cppsig->args[a]); } /* Handle the Python signature. */ resolvePySigTypes(pt, mod, scope, od, &od->pysig,isSignal(od)); /* These slots must return int. */ res = &od -> pysig.result; if (isIntReturnSlot(od->common)) if (res -> atype != int_type || res -> nrderefs != 0 || isReference(res) || isConstArg(res)) fatal("%s slots must return int\n",od -> common -> pyname -> text); /* These slots must return void. */ if (isVoidReturnSlot(od -> common)) if (res -> atype != void_type || res -> nrderefs != 0 || isReference(res) || isConstArg(res)) fatal("%s slots must return void\n",od -> common -> pyname -> text); /* These slots must return long. */ if (isLongReturnSlot(od->common)) if (res->atype != long_type || res->nrderefs != 0 || isReference(res) || isConstArg(res)) fatal("%s slots must return long\n", od->common->pyname->text);}/* * Resolve the types of a Python signature. */static void resolvePySigTypes(sipSpec *pt, moduleDef *mod, classDef *scope, overDef *od, signatureDef *pysig, int issignal){ int a; argDef *res = &pysig -> result; if (res -> atype != void_type || res -> nrderefs != 0) { if (issignal) { if (scope != NULL) { fatalScopedName(classFQCName(scope)); fatal("::"); } fatal("%s() signals must return void\n",od -> cppname); } getBaseType(pt, mod, scope, res); /* Results must be simple. */ if (!supportedType(scope,od,res,FALSE) && (od -> cppsig == &od -> pysig || od -> methodcode == NULL)) { if (scope != NULL) { fatalScopedName(classFQCName(scope)); fatal("::"); } fatal("%s() unsupported function return type - provide %%MethodCode and a %s signature\n",od -> cppname,(pt -> genc ? "C" : "C++")); } } for (a = 0; a < pysig -> nrArgs; ++a) { argDef *ad = &pysig -> args[a]; getBaseType(pt, mod, scope, ad); if (ad -> atype == slotcon_type) resolvePySigTypes(pt, mod, scope, od, ad->u.sa,TRUE); /* * Note signal arguments are restricted in their types because * we don't (yet) support handwritten code for them. */ if (issignal) { if (!supportedType(scope,od,ad,FALSE)) { if (scope != NULL) { fatalScopedName(classFQCName(scope)); fatal("::"); } fatal("%s() unsupported signal argument type\n"); } } else if (!supportedType(scope,od,ad,TRUE) && (od -> cppsig == &od -> pysig || od -> methodcode == NULL || (isVirtual(od) && od -> virthandler -> virtcode == NULL))) { if (scope != NULL) { fatalScopedName(classFQCName(scope)); fatal("::"); } if (isVirtual(od)) fatal("%s() unsupported function argument type - provide %%Method code, a valid %%VirtualCatcherCode and a valid C++ signature\n",od -> cppname); fatal("%s() unsupported function argument type - provide %%Method code and a valid %s signature\n",od -> cppname,(pt -> genc ? "C" : "C++")); } if (scope != NULL) scopeDefaultValue(pt,scope,ad); }}/* * Resolve the type of a variable. */static void resolveVariableType(sipSpec *pt,varDef *vd){ int bad = TRUE; argDef *vtype = &vd -> type; getBaseType(pt, vd->module, vd->ecd, vtype); switch (vtype -> atype) { case mapped_type: case class_type: /* Class, Class & and Class * are supported. */ if (vtype -> nrderefs <= 1) bad = FALSE; break; case sstring_type: case ustring_type: case string_type: /* * (signed/unsigned) char, (signed/unsigned) char * are * supported. */ if (!isReference(vtype) && vtype -> nrderefs <= 1) bad = FALSE; break; case cfloat_type: case float_type: case cdouble_type: case double_type: case enum_type: case bool_type: case cbool_type: case ushort_type: case short_type: case uint_type: case cint_type: case int_type: case ulong_type: case long_type: case ulonglong_type: case longlong_type: case pyobject_type: case pytuple_type: case pylist_type: case pydict_type: case pycallable_type: case pyslice_type: case pytype_type: /* These are supported without pointers or references. */ if (!isReference(vtype) && vtype -> nrderefs == 0) bad = FALSE; break; case struct_type: case void_type: /* A simple pointer is supported. */ if (!isReference(vtype) && vtype -> nrderefs == 1) bad = FALSE; break; } if (bad) { fatalScopedName(vd -> fqcname); fatal(" has an unsupported type\n"); } if (vtype -> atype != class_type && vd -> accessfunc != NULL) { fatalScopedName(vd -> fqcname); fatal(" has %%AccessCode but isn't a class instance\n"); } if (vd -> ecd != NULL) ifaceFileIsUsed(pt, vd->ecd->iff, vtype); else ifaceFileIsUsed(pt, NULL, vtype); /* * Instance variables or static class variables (unless they are * constants) need a handler. */ if (vd -> ecd != NULL && vd -> accessfunc == NULL && (!isStaticVar(vd) || vtype -> nrderefs != 0 || !isConstArg(vtype))) { setNeedsHandler(vd); setHasVarHandlers(vd -> ecd); }}/* * See if a type is supported by the generated code. */static int supportedType(classDef *cd,overDef *od,argDef *ad,int outputs){ switch (ad -> atype) { case anyslot_type: /* * This must be an input, and must also have handwritten code. */ ensureInput(cd,od,ad); return FALSE; case signal_type: case slot_type: case rxcon_type: case rxdis_type: case slotcon_type: case slotdis_type: case qobject_type: case ellipsis_type: /* These can only appear in argument lists without * or &. */ ensureInput(cd,od,ad); return TRUE; case sstring_type: case ustring_type: case string_type: if (isReference(ad)) { if (outputs && ad -> nrderefs <= 1) { defaultOutput(cd,od,ad); return TRUE; } } else if (ad -> nrderefs == 0) { ensureInput(cd,od,ad); return TRUE; } else if (ad -> nrderefs == 1) { if (outputs) defaultInput(ad); else ensureInput(cd,od,ad); return TRUE; } else if (ad -> nrderefs == 2 && outputs) { defaultOutput(cd,od,ad); return TRUE; } break; case cfloat_type: case float_type: case cdouble_type: case double_type: case enum_type: case bool_type: case cbool_type: case ushort_type: case short_type: case uint_type: case cint_type: case int_type: case ulong_type: case long_type: case ulonglong_type: case longlong_type: case pyobject_type: case pytuple_type: case pylist_type: case pydict_type: case pycallable_type: case pyslice_type: case pytype_type: if (isReference(ad)) { if (ad -> nrderefs == 0 && outputs) { defaultOutput(cd,od,ad); return TRUE; } } else if (ad -> nrderefs == 0) { ensureInput(cd,od,ad); return TRUE; } else if (ad -> nrderefs == 1 && outputs) { defaultOutput(cd,od,ad); return TRUE; } break; case mapped_type: case class_type: if (isReference(ad)) { if (ad -> nrderefs == 0) { defaultInput(ad); return TRUE; } else if (ad -> nrderefs == 1 && outputs) { defaultOutput(cd,od,ad); return TRUE; } } else if (ad -> nrderefs == 0) { ensureInput(cd,od,ad); return TRUE; } else if (ad -> nrderefs == 1) { if (outputs) defaultInput(ad); else ensureInput(cd,od,ad); return TRUE; } else if (ad -> nrderefs == 2 && outputs) { defaultOutput(cd,od,ad); return TRUE; } break; case struct_type: case void_type: if (isReference(ad)) { if (ad -> nrderefs == 1 && outputs) { defaultOutput(cd,od,ad); return TRUE; } } else if (ad -> nrderefs == 1) { ensureInput(cd,od,ad); return TRUE; } else if (ad -> nrderefs == 2 && outputs) { defaultOutput(cd,od,ad); return TRUE; } break; } /* Unsupported if we got this far. */ return FALSE;}/* * Ensure the direction of an argument is an input. */static void ensureInput(classDef *cd,overDef *od,argDef *ad){ if (isOutArg(ad)) { if (cd != NULL) { fatalScopedName(classFQCName(cd)); fatal("::"); } if (od != NULL) fatal("%s",od -> cppname); fatal("() invalid argument type for /Out/\n"); } setIsInArg(ad);}/* * Default the direction of an argument to an input. */static void defaultInput(argDef *ad){ if (!isInArg(ad) && !isOutArg(ad)) setIsInArg(ad);}/* * Default the direction of an argument to an output unless the argument is * const. */static void defaultOutput(classDef *cd,overDef *od,argDef *ad){ if (isOutArg(ad)) { if (isConstArg(ad)) { if (cd != NULL) { fatalScopedName(classFQCName(cd)); fatal("::"); } if (od != NULL) fatal("%s",od -> cppname); fatal("() const argument cannot have /Out/ specified\n"); } } else if (!isInArg(ad)) if (isConstArg(ad)) setIsInArg(ad); else setIsOutArg(ad);}/* * Put a scoped name to stderr. */void fatalScopedName(scopedNameDef *snd){ while (snd != NULL) { fatal("%s",snd -> name); snd = snd -> next; if (snd != NULL) fatal("::"); }}/* * Compare two overloads and return TRUE if they are the same. */static int sameOverload(overDef *od1,overDef *od2){ /* They must both be const, or both not. */ if (isConst(od1) != isConst(od2)) return FALSE; return sameSignature(&od1 -> pysig,&od2 -> pysig,TRUE);}/* * Compare two virtual handlers and return TRUE if they are the same. */static int sameVirtualHandler(virtHandlerDef *vhd1,virtHandlerDef *vhd2){ if (isTransferVH(vhd1) != isTransferVH(vhd2)) return FALSE; if (!sameArgType(&vhd1 -> sd -> result,&vhd2 -> sd -> result,TRUE)) return FALSE; return sameSignature(vhd1 -> sd,vhd2 -> sd,TRUE);}/* * Compare two signatures and return TRUE if they are the same. */int sameSignature(signatureDef *sd1,signatureDef *sd2,int strict){ int a; if (strict) { /* The number of arguments must be the same. */ if (sd1 -> nrArgs != sd2 -> nrArgs) return FALSE; } else { int na1, na2; /* We only count the compulsory arguments. */ na1 = 0; for (a = 0; a < sd1 -> nrArgs; ++a) { if (sd1 -> args[a].defval != NULL) break; ++na1; } na2 = 0; for (a = 0; a < sd2 -> nrArgs; ++a) { if (sd2 -> args[a].defval != NULL) break; ++na2; } if (na1 != na2) return FALSE; } /* The arguments must be the same. */ for (a = 0; a < sd1 -> nrArgs; ++a) { if (!strict && sd1 -> args[a].defval != NULL) break; if (!sameArgType(&sd1 -> args[a],&sd2 -> args[a],strict)) return FALSE; } /* Must be the same if we've got this far. */ return TRUE;}#define pyAsFloat(t) ((t) == cfloat_type || (t) == float_type || \ (t) == cdouble_type || (t) == double_type)#define pyAsInt(t) ((t) == cint_type || (t) == bool_type || \ (t) == short_type || (t) == ushort_type || \ (t) == int_type || (t) == uint_type)#define pyAsAuto(t) ((t) == bool_type || \ (t) == short_type || (t) == ushort_type || \ (t) == int_type || (t) == uint_type || \ (t) == float_type || (t) == double_type)/* * Compare two argument types and return TRUE if they are the same. "strict" * means as C++ would see it, rather than Python. */static int sameArgType(argDef *a1,argDef *a2,int strict){ /* The indirection and the references must be the same. */ if (isReference(a1) != isReference(a2) || a1 -> nrderefs != a2 -> nrderefs) return FALSE; if (strict) { /* The const should be the same. */ if (isConstArg(a1) != isConstArg(a2)) return FALSE; return sameBaseType(a1,a2); } else if (sameBaseType(a1,a2)) return TRUE; /* Python will see all these as floats. */ if (pyAsFloat(a1->atype) && pyAsFloat(a2->atype)) return TRUE; /* Python will see all these as ints. */ if (pyAsInt(a1->atype) && pyAsInt(a2->atype)) return TRUE; /* Python will automatically convert between these. */ if (pyAsAuto(a1->atype) && pyAsAuto(a2->atype)) return TRUE; /* They must be different if we have got this far. */ return FALSE;}/* * Compare two basic types and return TRUE if they are the same. */int sameBaseType(argDef *a1,argDef *a2){ /* The types must be the same. */ if (a1 -> atype != a2 ->atype) return FALSE; switch (a1 -> atype) { case class_type: if (a1 -> u.cd != a2 -> u.cd) return FALSE; break; case enum_type: if (a1 -> u.ed != a2 -> u.ed) return FALSE; break; case slotcon_type: case slotdis_type: if (!sameSignature(a1 -> u.sa,a2 -> u.sa,TRUE)) return FALSE; break; case template_type: { int a; templateDef *td1, *td2; td1 = a1 -> u.td; td2 = a2 -> u.td; if (!sameScopedName(td1 -> fqname,td2 -> fqname) != 0 || td1 -> types.nrArgs != td2 -> types.nrArgs) return FALSE; for (a = 0; a < td1 -> types.nrArgs; ++a) if (!sameBaseType(&td1 -> types.args[a],&td2 -> types.args[a])) return FALSE; break; } case struct_type: if (!sameScopedName(a1 -> u.sname,a2 -> u.sname) != 0) return FALSE; break; case defined_type:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -