/* TODO this is copy-paste from dbsh.c */ static char* dbsh_attrStr(cx_object o, char* buff) { cx_bool first; *buff = '\0'; first = TRUE; if (cx_checkAttr(o, CX_ATTR_SCOPED)) { strcat(buff, "S"); first = FALSE; } if (cx_checkAttr(o, CX_ATTR_WRITABLE)) { if (!first) { strcat(buff, "|W"); } else { strcat(buff, "W"); first = FALSE; } } if (cx_checkAttr(o, CX_ATTR_OBSERVABLE)) { if (!first) { strcat(buff, "|O"); } else { strcat(buff, "O"); first = FALSE; } } if (cx_checkAttr(o, CX_ATTR_PERSISTENT)) { if (!first) { strcat(buff, "|P"); } else { strcat(buff, "P"); } } return buff; }
int cx_genCollectAnonymous(void* o, void* userData) { cx_ll list = userData; if (!cx_checkAttr(o, CX_ATTR_SCOPED)) { cx_llInsert(list, o); } return 1; }
/* Handle subscribe message */ static int web_subscribe(struct mg_connection *conn) { char *flag_start = conn->content + 2; char *id_start = strchr(flag_start, ' ') + 1; int len; cx_id id; cx_object o = NULL; web_wsconnection wc = web_wsconnection(conn->connection_param); /* Check if message is correct */ if ((id_start - conn->content) > (int)conn->content_len) { printf("error: message '%.*s' not correctly formatted\n", (int)conn->content_len, conn->content); goto error; } /* Copy identifier to buffer */ len = (int)conn->content_len - (id_start - conn->content); memcpy(id, id_start, len); id[len] = '\0'; /* Silence previous subscription */ if (wc->observing) { cx_silence(wc->observing, web_wsconnection_onUpdate_o, wc); cx_silence(wc->observing, web_wsconnection_onDelete_o, wc); } wc->eventCount = 0; /* Lookup object */ o = cx_resolve(NULL, id); if (!o) { goto error; } else if (!cx_checkAttr(o, CX_ATTR_OBSERVABLE)) { /* Can't listen if object is not observable, but can send the client the value */ cx_set(&wc->observing, NULL); web_wsconnection_send(wc, o, TRUE, TRUE, TRUE, TRUE, FALSE); wc->eventCount++; } else { /* Configure observer to listen for updates */ cx_set(&wc->observing, o); cx_listen(o, web_wsconnection_onUpdate_o, wc); cx_listen(o, web_wsconnection_onDelete_o, wc); } return 0; error: return -1; }
/* ::cortex::lang::type::parentof() */ cx_object cx_type_parentof(cx_any _this) { /* $begin(::cortex::lang::type::parentof) */ cx_string result = NULL; if (cx_checkAttr(_this.value, CX_ATTR_SCOPED)) { result = cx_parentof(_this.value); } else { cx_id id; cx_error("cannot get parent from non-scoped object of type '%s'", cx_fullname(cx_typeof(_this.value), id)); } if (result) { cx_keep(result); } return result; /* $end */ }
/* ::cortex::Fast::StaticInitializer::define() */ cx_int16 Fast_StaticInitializer_define(Fast_StaticInitializer _this) { /* $begin(::cortex::Fast::StaticInitializer::define) */ cx_uint32 variable; cx_object o; /* Types are defined during 1st pass. All other objects are defined when a program starts. Defining types * at compile-time is required to do validity checking while parsing. On the other hand, objects cannot be * defined at compile-time because class constructors\destructors are not yet defined at that point. This * would cause object creation\destruction without calling the appropriate constructors\destructors. */ for(variable=0; variable<Fast_Initializer(_this)->variableCount; variable++) { o = (cx_object)Fast_Object(Fast_Initializer(_this)->variables[variable].object)->value; if (cx_instanceof(cx_type(cx_type_o), o) || (cx_checkAttr(o, CX_ATTR_SCOPED) && cx_instanceof(cx_type(cx_type_o), cx_parentof(o)))) { if (cx_define(o)) { cx_id id1, id2; Fast_Parser_error(yparser(), "define of variable '%s' of type '%s' failed", Fast_Parser_id(o, id1), Fast_Parser_id(cx_typeof(o), id2)); goto error; } } else { Fast_Expression refVar = Fast_Expression(Fast_Object__create(o)); refVar->isReference = TRUE; /* Always treat object as reference */ Fast_Define defineStmt = Fast_Define__create(refVar); Fast_Parser_addStatement(yparser(), Fast_Node(defineStmt)); Fast_Parser_collect(yparser(), defineStmt); Fast_Parser_collect(yparser(), refVar); } } Fast_Initializer_define_v(Fast_Initializer(_this)); return 0; error: return -1; /* $end */ }
static cx_int16 serializeReference(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(s); cx_json_ser_t *data; void *o; cx_object object; cx_id id; data = userData; o = cx_valueValue(v); object = *(cx_object*)o; if (object) { if (cx_checkAttr(object, CX_ATTR_SCOPED) || (cx_valueObject(v) == object)) { cx_uint32 length; cx_fullname(object, id); /* Escape value */ cx_string escapedValue = cx_malloc((length = stresc(NULL, 0, id)) + 1); stresc(escapedValue, length, id); if (!cx_ser_appendstr(data, "\"@R %s\"", escapedValue)) { cx_dealloc(escapedValue); goto finished; } cx_dealloc(escapedValue); } else { cx_ser_appendstr(data, "\"anonymous\""); } } else { if (!cx_ser_appendstrbuff(data, "null")) { goto finished; } } return 0; finished: return 1; }
/* Serialize dependencies on references */ cx_int16 cx_genDepReference(cx_serializer s, cx_value* info, void* userData) { cx_object o; g_depWalk_t data; CX_UNUSED(s); data = userData; o = *(cx_object*)cx_valueValue(info); if (o && g_mustParse(data->data->g, o)) { cx_member m; m = NULL; if (info->kind == CX_MEMBER) { m = info->is.member.t; if (!m->type->reference) { m = NULL; } } /* Add dependency on item */ if (m) { cx_depresolver_depend(data->data->resolver, data->o, CX_DEFINED, o, m->state); } else { cx_depresolver_depend(data->data->resolver, data->o, CX_DEFINED, o, CX_DEFINED); } /* Include dependencies on anonymous types */ if (!cx_checkAttr(o, CX_ATTR_SCOPED)) { cx_genDepBuildAction(o, data->data); } } return 0; }
/* Build dependency-administration for object */ int cx_genDepBuildAction(cx_object o, void* userData) { g_itemWalk_t data; struct g_depWalk_t walkData; struct cx_serializer_s s; int result; cx_object parent = NULL; if (cx_checkAttr(o, CX_ATTR_SCOPED)) { parent = cx_parentof(o); } data = userData; /* If object is cortex_lang_o, signal that a bootstrap is found, indicating * that dependencies should be disregarded. */ if (o == cortex_lang_o) { data->bootstrap = TRUE; result = 0; } else { /* Insert type-dependency: object can be declared only after it's type is defined. */ if (g_mustParse(data->g, cx_typeof(o))) { cx_depresolver_depend(data->resolver, o, CX_DECLARED, cx_typeof(o), CX_DEFINED); } /* TODO: this is not nice */ if (cx_class_instanceof(cx_procedure_o, cx_typeof(o))) { /* Insert base-dependency: methods may only be declared after the base of a class has been defined. */ if (cx_typeof(o) != cx_type(cx_function_o)) { if (cx_class_instanceof(cx_class_o, parent) && cx_interface(parent)->base) { if (g_mustParse(data->g, cx_interface(parent)->base)) { cx_depresolver_depend(data->resolver, o, CX_DECLARED, cx_interface(parent)->base, CX_DEFINED); } } } /* Add dependencies on function parameters - types must be declared before function is declared. */ if (cx_genDepBuildProc(cx_function(o), data)) { goto error; } } /* Insert dependency on parent */ if (cx_checkAttr(o, CX_ATTR_SCOPED)) { if (parent != root_o) { /* Root is always available */ cx_int8 parentState = cx_type(cx_typeof(o))->parentState; cx_depresolver_depend(data->resolver, o, CX_DECLARED, parent, parentState); if (parentState == CX_DECLARED) { cx_depresolver_depend(data->resolver, parent, CX_DEFINED, o, CX_DEFINED); } } } /* Insert dependencies on references in the object-value */ walkData.o = o; walkData.data = data; s = cx_genDepSerializer(); if (cx_serialize(&s, o, &walkData)) { goto error; } result = 1; } return result; error: return 0; }
static cx_int16 serializeMeta(cx_serializer s, cx_value* v, void* userData) { CX_UNUSED(s); cx_json_ser_t *data = userData; cx_object o = cx_valueValue(v); if (!data->serializeMeta) { goto error; } if (!cx_ser_appendstr(userData, "{")) { goto finished; } cx_string name = cx_nameof(o); if (name) { if (!cx_appendStringAttr("name", name, userData)) { goto finished; } } else { if (!cx_ser_appendstr(userData, "\"name\":\"::\",")) { goto finished; } } cx_id type_fullname; cx_fullname(cx_typeof(o), type_fullname); if (!cx_appendStringAttr("type", type_fullname, userData)) { goto finished; } if (cx_checkAttr(o, CX_ATTR_PERSISTENT)) { cx_time t = cx_timestampof(o); if (!cx_ser_appendstr(data, "\"timestamp\":\"%d.%.9d\",", t.tv_sec, t.tv_nsec)) { goto finished; } } char states[sizeof("V|DCL|DEF")]; dbsh_stateStr(o, states); if (!cx_ser_appendstr(data, "\"states\":\"%s\",", states)) { goto finished; } char attributes[sizeof("S|W|O|P")]; dbsh_attrStr(o, attributes); if (!cx_ser_appendstr(data, "\"attributes\":\"%s\",", attributes)) { goto finished; } cx_id parent_fullname; cx_fullname(cx_parentof(o), parent_fullname); if (!cx_ser_appendstr(data, "\"parent\":\"%s\",", parent_fullname)) { goto finished; } cx_uint32 scopeSize = cx_scopeSize(o); if (!cx_ser_appendstr(data, "\"childCount\":%"PRId32"", scopeSize)) { goto finished; } if (!cx_ser_appendstr(data, "}")) { goto finished; } return 0; error: return -1; finished: return 1; }
/* ::cortex::lang::type::checkAttr(attr attributes) */ cx_bool cx_type_checkAttr(cx_any _this, cx_attr attributes) { /* $begin(::cortex::lang::type::checkAttr) */ return cx_checkAttr(_this.value, attributes); /* $end */ }