bool _corto_delegate_compatible( corto_delegate _this, corto_type type) { static corto_uint32 _methodId; corto_method _method; bool _result; corto_interface _abstract; _abstract = corto_interface(corto_typeof(_this)); /* Determine methodId once, then cache it for subsequent calls. */ if (!_methodId) { _methodId = corto_interface_resolveMethodId(_abstract, "compatible(type type)"); } corto_assert(_methodId, "virtual 'compatible(type type)' not found in '%s'%s%s", corto_fullpath(NULL, _abstract), corto_lasterr() ? ": " : "", corto_lasterr() ? corto_lasterr() : ""); /* Lookup method-object. */ _method = corto_interface_resolveMethodById(_abstract, _methodId); corto_assert(_method != NULL, "unresolved method '%s::compatible(type type)@%d'", corto_idof(_this), _methodId); if (corto_function(_method)->kind == CORTO_PROCEDURE_CDECL) { _result = ((bool ___ (*)(corto_object, corto_type))((corto_function)_method)->fptr)(_this, type); } else { corto_call(corto_function(_method), &_result, _this, type); } return _result; }
corto_int16 cpp_fluentTemplDecl(corto_type type, char *base, cpp_classWalk_t *data) { corto_id id; g_oid(data->g, type, id); g_fileWrite(data->header, "// Helper class that sets members and enables inheritance for factories\n"); g_fileWrite(data->header, "template <class T>\n"); g_fileWrite(data->header, "class %s_v : public %s_v<T>\n", id, base); g_fileWrite(data->header, "{\n"); g_fileWrite(data->header, "public:\n"); g_fileIndent(data->header); g_fileWrite(data->header, "%s_v(T& _this, void *ptr) : %s_v<T>(_this, ptr) { }\n", id, base); if (corto_instanceof(corto_interface_o, type) && corto_interface(type)->base) { g_fileWrite(data->header, "%s_v<T> super() ", base); g_fileWrite(data->header, "{ return %s_v<T>(this->m_this, this->ptr); }\n", base); } if (cpp_fluent_walkMembers(type, data)) { goto error; } g_fileDedent(data->header); g_fileWrite(data->header, "};\n"); g_fileWrite(data->header, "\n"); return 0; error: return -1; }
/* Create a class that mounts fibonacci numbers in corto */ corto_class createFiboClass(void) { corto_class FiboClass = corto_declareChild(root_o, "FiboConnector", corto_class_o); if (!FiboClass) { goto error; } /* Inherit from the corto mount class */ corto_setref(&corto_interface(FiboClass)->base, corto_mount_o); /* Create onNotify method (called when the mount receives an update) */ corto_method onRequestMethod = corto_declareChild( FiboClass, "onRequest(core/request request)", corto_method_o); if (!onRequestMethod) { goto error; } corto_function(onRequestMethod)->kind = CORTO_PROCEDURE_CDECL; corto_function(onRequestMethod)->fptr = (corto_word)onRequest; if (corto_define(onRequestMethod)) { goto error; } /* Finalize class */ if (corto_define(FiboClass)) { goto error; } return FiboClass; error: return NULL; }
corto_int16 corto_value_memberExpr(corto_value *val, corto_string member, corto_value *out) { corto_type t = corto_value_typeof(val); corto_object o = corto_value_objectof(val); void *ptr = corto_value_ptrof(val); corto_id tokens; strncpy(tokens, member, sizeof(corto_id)); char *cur = tokens, *prev = tokens; do { if (cur && (cur = strchr(cur + 1, '.'))) *cur = '\0'; if (!corto_instanceof(corto_interface_o, t)) { corto_seterr( "cannot get member from a non-composite value (type is '%s')", corto_fullpath(NULL, t)); goto error; } if (!strcmp(prev, "super")) { if (!(t = (corto_type)corto_interface(t)->base)) { corto_seterr("super unpexpected: interface '%s' does not have a base", corto_fullpath(NULL, t)); goto error; } else { *out = corto_value_base(ptr, t); } } else { corto_member m = corto_interface_resolveMember(t, prev); if (!m) { corto_seterr( "unresolved member '%s' in type '%s'", prev, corto_fullpath(NULL, t)); goto error; } ptr = CORTO_OFFSET(ptr, m->offset); t = m->type; *out = corto_value_member(o, m, ptr); } prev = cur + 1; } while (cur); return 0; error: return -1; }
corto_int16 _corto_delegate_bind(corto_function object) { /* $begin(::corto::lang::delegate::bind) */ corto_object parent = corto_parentof(object); if (corto_class_instanceof(corto_interface_o, corto_typeof(parent))) { corto_interface type = corto_interface(corto_typeof(parent)); corto_id functionName; corto_member m = NULL; /* Get function name, lookup delegate, assign function */ corto_signatureName(corto_nameof(object), functionName); if (corto_checkState(corto_type_o, CORTO_DEFINED) && (m = corto_interface_resolveMember(type, functionName)) && (m->type->kind == CORTO_COMPOSITE) && (corto_interface(m->type)->kind == CORTO_DELEGATE)) { if (corto_delegate_instanceof(corto_delegate(m->type), object)) { /* Bind instance of function is a method */ if (corto_procedure(corto_typeof(object))->kind == CORTO_METHOD) { corto_setref(&((corto_delegatedata *) CORTO_OFFSET(parent, m->offset))->instance, parent); } /* Bind procedure */ corto_setref(&((corto_delegatedata *) CORTO_OFFSET(parent, m->offset))->procedure, object); } else { /* If there is a member that corresponds to a delegate but has a non matching * signature, always report error */ corto_id id1, id2; corto_error("member '%s' of delegate type '%s' does not match signature of '%s'", corto_nameof(m), corto_fullname(m->type, id1), corto_fullname(object, id2)); goto error; } } } return 0; error: return -1; /* $end */ }
/* Compare composites */ static corto_int16 corto_ser_composite(corto_walk_opt* s, corto_value *info, void* userData) { corto_compare_ser_t *data = userData; corto_type t = corto_value_typeof(info); void *this = corto_value_ptrof(info); void *value = (void*)((corto_word)corto_value_ptrof(&data->value) + ((corto_word)this - (corto_word)data->base)); if (corto_interface(t)->kind == CORTO_UNION) { corto_int32 d1 = *(corto_int32*)this; corto_int32 d2 = *(corto_int32*)value; if (d1 != d2) { corto_member m1 = safe_corto_union_findCase(t, d1); corto_member m2 = safe_corto_union_findCase(t, d2); if (m1 != m2) { goto nomatch; } } } return corto_walk_members(s, info, userData); nomatch: data->result = CORTO_NEQ; return 1; }
/* Parse scope */ static corto_string corto_string_deserParseScope(corto_string str, struct corto_string_deserIndexInfo* info, corto_string_deser_t* data) { struct corto_string_deserIndexInfo rootInfo; corto_typeKind kind; void *ptr = data->ptr; if (data->allocValue) { ptr = data->allocValue(ptr, data); } /* Prepare privateData */ corto_string_deser_t privateData = { .out = data->out, .scope = data->scope, .anonymousObjects = data->anonymousObjects, .type = data->type, .isObject = data->isObject, .members = {0, NULL} }; /* Offset the scope-members with the current offset */ if (info && info->m) { ptr = corto_getMemberPtr(data->isObject ? data->out : NULL, ptr, info->m); } privateData.ptr = ptr; /* Open scope of type */ if (!info) { if (!data->type) { rootInfo.type = corto_typeof(data->out); } else { rootInfo.type = data->type; } rootInfo.m = NULL; rootInfo.parsed = FALSE; info = &rootInfo; } /* Check if type is any, composite or collection */ kind = info->type->kind; if ((kind != CORTO_COMPOSITE) && (kind != CORTO_COLLECTION) && (kind != CORTO_ANY)) { corto_seterr("'{' unexpected for type '%s'", corto_fullpath(NULL, info->type)); goto error; } /* Build index for type */ if (info->type->kind == CORTO_COMPOSITE) { if (corto_interface(info->type)->kind == CORTO_UNION) { /* Parse discriminator */ struct corto_string_deserIndexInfo dInfo; dInfo.type = (corto_type)corto_int32_o; dInfo.parsed = FALSE; dInfo.m = NULL; str = corto_string_deserParse(str + 1, &dInfo, &privateData); if (!str) { goto error; } /* Find corresponding union case */ corto_int32 d = *(corto_int32*)ptr; corto_member m = safe_corto_union_findCase(info->type, d); if (!m) { corto_seterr("discriminator '%d' invalid for union '%s'", d, corto_fullpath(NULL, info->type)); goto error; } /* Build index for one member */ struct corto_string_deserIndexInfo *caseInfo = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); caseInfo->type = m->type; caseInfo->parsed = FALSE; caseInfo->m = m; corto_string_deserIndexInsert(&privateData, caseInfo); } else { corto_walk_opt s = corto_string_deserBuildIndex(); s.members = data->members; if (s.members.length) { s.access = 0; } if (corto_metawalk(&s, info->type, &privateData)) { goto error; } } /* Create iterator for index */ if (privateData.index) { privateData.currentIter = _corto_ll_iter(privateData.index, &privateData.iterData); } /* If type is a collection, build index with one node for element */ } else if (info->type->kind == CORTO_COLLECTION) { struct corto_string_deserIndexInfo *elementNode; elementNode = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); elementNode->m = NULL; elementNode->parsed = FALSE; elementNode->type = corto_collection(info->type)->elementType; corto_string_deserIndexInsert(&privateData, elementNode); /* Create iterator for index */ privateData.currentIter = _corto_ll_iter(privateData.index, &privateData.iterData); privateData.allocValue = corto_string_deserAllocElem; privateData.allocUdata = info->type; if (ptr) { switch(corto_collection(info->type)->kind) { case CORTO_ARRAY: case CORTO_SEQUENCE: break; case CORTO_LIST: if (!*(corto_ll*)ptr) { *(corto_ll*)ptr = corto_ll_new(); } else { corto_ll_clear(*(corto_ll*)ptr); } privateData.ptr = ptr; break; default: break; } } } else if (info->type->kind == CORTO_ANY) { struct corto_string_deserIndexInfo *anyNode; anyNode = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); anyNode->m = NULL; anyNode->parsed = FALSE; anyNode->type = corto_type(corto_type_o); corto_string_deserIndexInsert(&privateData, anyNode); privateData.currentIter = _corto_ll_iter(privateData.index, &privateData.iterData); privateData.allocValue = corto_string_deserAllocAny; privateData.allocUdata = anyNode; } /* Parse scope */ if (!(str = corto_string_deserParse(str+1, info, &privateData))) { goto error; } corto_string_deserFreeIndex(&privateData); data->anonymousObjects = privateData.anonymousObjects; return str; error: return NULL; } /* Get pointer to current destination value */ corto_int16 corto_string_getDestinationPtr( struct corto_string_deserIndexInfo* info, corto_string_deser_t* data, void **ptr_out) { void *result = data->ptr; *ptr_out = NULL; if (!info) { corto_seterr("excess elements in string"); goto error; } if (data->allocValue) { result = data->allocValue(result, data); } if (info->m) { result = corto_getMemberPtr(data->isObject ? data->out : NULL, data->ptr, info->m); } *ptr_out = result; return 0; error: return -1; }
static corto_int16 json_deserComposite(void* p, corto_type t, JSON_Value *v) { corto_assert(t->kind == CORTO_COMPOSITE, "not deserializing composite"); if (json_value_get_type(v) != JSONObject) { corto_seterr("expected object, got %s", json_valueTypeToString(v)); goto error; } JSON_Object* o = json_value_get_object(v); size_t count = json_object_get_count(o); size_t i; corto_bool isUnion = corto_interface(t)->kind == CORTO_UNION; corto_int32 discriminator = 0; corto_member unionMember = NULL; for (i = 0; i < count; i++) { const char* memberName = json_object_get_name(o, i); corto_member member_o; if (!strcmp(memberName, "super")) { JSON_Value* value = json_object_get_value(o, memberName); if (json_deserItem(p, corto_type(corto_interface(t)->base), value)) { goto error; } } else if (!strcmp(memberName, "_d") && isUnion) { JSON_Value* value = json_object_get_value(o, memberName); if (json_deserPrimitive(&discriminator, corto_union(t)->discriminator, value)) { goto error; } unionMember = corto_union_findCase(t, discriminator); if (!unionMember) { corto_seterr("discriminator '%d' invalid for union '%s'", discriminator, corto_fullpath(NULL, t)); } } else { member_o = corto_interface_resolveMember(t, (char*)memberName); /* Ensure that we're not resolving members from a base type */ if (!member_o || (corto_parentof(member_o) != t)) { corto_seterr( "cannot find member '%s' in type '%s'", memberName, corto_fullpath(NULL, t)); goto error; } if (isUnion && (unionMember != member_o)) { corto_seterr( "member '%s' does not match discriminator '%d' (expected member '%s')", memberName, discriminator, corto_idof(unionMember)); goto error; } else if (isUnion) { corto_int32 prev = *(corto_int32*)p; if (prev != discriminator) { corto_member prevMember = corto_union_findCase(t, prev); corto_deinitp(CORTO_OFFSET(p, prevMember->offset), prevMember->type); memset(CORTO_OFFSET(p, member_o->offset), 0, member_o->type->size); } *(corto_int32*)p = discriminator; } if (!json_deserMustSkip(member_o, p)) { JSON_Value* value = json_object_get_value(o, memberName); void *offset = CORTO_OFFSET(p, member_o->offset); if (member_o->modifiers & CORTO_OBSERVABLE) { offset = *(void**)offset; if (json_deserType(offset, member_o->type, value)) { goto error; } } else { if (member_o->modifiers & CORTO_OPTIONAL) { if (*(void**)offset) { corto_deinitp(*(void**)offset, member_o->type); memset(*(void**)offset, 0, member_o->type->size); } else { *(void**)offset = corto_calloc(member_o->type->size); } offset = *(void**)offset; } if (json_deserItem(offset, member_o->type, value)) { goto error; } } } } } return 0; error: return -1; }
* This file contains wrapper functions for /corto/lang. */ #include <corto/lang/lang.h> #include <corto/lang/_meta.h> corto_bool _corto_collection_castable( corto_collection this, corto_type type) { static corto_uint32 _methodId; corto_method _method; corto_bool _result; corto_interface _abstract; _abstract = corto_interface(corto_typeof(this)); /* Determine methodId once, then cache it for subsequent calls. */ if (!_methodId) { _methodId = corto_interface_resolveMethodId(_abstract, "castable(type type)"); } corto_assert(_methodId, "virtual 'castable(type type)' not found in '%s'%s%s", corto_fullpath(NULL, _abstract), corto_lasterr()?": ":"", corto_lasterr()); /* Lookup method-object. */ _method = corto_interface_resolveMethodById(_abstract, _methodId); corto_assert(_method != NULL, "unresolved method '%s::castable(type type)@%d'", corto_idof(this), _methodId); corto_call(corto_function(_method), &_result, this, type); return _result; }