buzzvm_state buzzvm_pushc(buzzvm_t vm, int32_t rfrnc, int32_t nat) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_CLOSURE); o->c.value.isnative = nat; o->c.value.ref = rfrnc; buzzobj_t nil = buzzheap_newobj(vm, BUZZTYPE_NIL); buzzdarray_push(o->c.value.actrec, &nil); buzzvm_push(vm, o); return vm->state; }
buzzvm_state buzzvm_pushl(buzzvm_t vm, int32_t addr) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_CLOSURE); o->c.value.isnative = 1; o->c.value.ref = addr; if(vm->lsyms) { int i; for(i = 0; i < buzzdarray_size(vm->lsyms->syms); ++i) buzzdarray_push(o->c.value.actrec, &buzzdarray_get(vm->lsyms->syms, i, buzzobj_t)); } else { buzzobj_t nil = buzzheap_newobj(vm, BUZZTYPE_NIL); buzzdarray_push(o->c.value.actrec, &nil); } return buzzvm_push(vm, o); }
static int make_table(buzzvm_t vm, buzzobj_t* t) { /* Make new table */ *t = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); /* Add methods */ function_register(*t, "get", buzzneighbors_get); function_register(*t, "kin", buzzneighbors_kin); function_register(*t, "nonkin", buzzneighbors_nonkin); function_register(*t, "foreach", buzzneighbors_foreach); function_register(*t, "map", buzzneighbors_map); function_register(*t, "reduce", buzzneighbors_reduce); function_register(*t, "count", buzzneighbors_count); return vm->state; }
buzzvm_state buzzvm_pushs(buzzvm_t vm, uint16_t strid) { if(!buzzstrman_get(vm->strings, strid)) { buzzvm_seterror(vm, BUZZVM_ERROR_STRING, "id read = %" PRIu16, strid); return vm->state; } buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_STRING); o->s.value.sid = (strid); o->s.value.str = buzzstrman_get(vm->strings, strid); buzzvm_push(vm, o); return BUZZVM_STATE_READY; }
int buzzneighbors_add(buzzvm_t vm, uint16_t robot, float distance, float azimuth, float elevation) { if(vm->state != BUZZVM_STATE_READY) return vm->state; /* Get "neighbors" table */ buzzvm_pushs(vm, buzzvm_string_register(vm, "neighbors", 1)); buzzvm_gload(vm); buzzvm_type_assert(vm, 1, BUZZTYPE_TABLE); buzzobj_t nbr = buzzvm_stack_at(vm, 1); /* Get "data" field */ buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_tget(vm); if(buzzvm_stack_at(vm, 1)->o.type == BUZZTYPE_NIL) { /* Empty data, create a new table */ buzzvm_pop(vm); buzzvm_push(vm, nbr); buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_pusht(vm); buzzobj_t data = buzzvm_stack_at(vm, 1); buzzvm_tput(vm); buzzvm_push(vm, data); } /* When we get here, the "data" table is on top of the stack */ /* Push robot id */ buzzvm_pushi(vm, robot); /* Create entry table */ buzzobj_t entry = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); /* Insert distance */ buzzvm_push(vm, entry); buzzvm_pushs(vm, buzzvm_string_register(vm, "distance", 1)); buzzvm_pushf(vm, distance); buzzvm_tput(vm); /* Insert azimuth */ buzzvm_push(vm, entry); buzzvm_pushs(vm, buzzvm_string_register(vm, "azimuth", 1)); buzzvm_pushf(vm, azimuth); buzzvm_tput(vm); /* Insert elevation */ buzzvm_push(vm, entry); buzzvm_pushs(vm, buzzvm_string_register(vm, "elevation", 1)); buzzvm_pushf(vm, elevation); buzzvm_tput(vm); /* Save entry into data table */ buzzvm_push(vm, entry); buzzvm_tput(vm); return vm->state; }
int buzzvm_vstig_create(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get vstig id */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; buzzvm_pop(vm); /* Look for virtual stigmergy */ buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) /* Found, destroy it */ buzzdict_remove(vm->vstigs, &id); /* Create a new virtual stigmergy */ buzzvstig_t nvs = buzzvstig_new(); buzzdict_set(vm->vstigs, &id, &nvs); /* Create a table and add data and methods */ buzzobj_t t = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "size")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_size)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "put")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_put)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "get")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_get)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "onconflict")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_setonconflict)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "onconflictlost")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_setonconflictlost)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_pushi(vm, id); buzzvm_tput(vm); /* Push the table on the stack */ buzzvm_push(vm, t); /* Return */ return buzzvm_ret1(vm); }
void CBuzzController::UpdateSensors() { /* * Update positioning sensor */ if(m_pcPos != NULL) { /* Get positioning readings */ const CCI_PositioningSensor::SReading& sPosRead = m_pcPos->GetReading(); /* Create empty positioning data table */ buzzobj_t tPose = buzzheap_newobj(m_tBuzzVM, BUZZTYPE_TABLE); /* Store position data */ TablePut(tPose, "position", sPosRead.Position); /* Store orientation data */ TablePut(tPose, "orientation", sPosRead.Orientation); /* Register positioning data table as global symbol */ Register("pose", tPose); } }
buzzvm_state buzzvm_closure_call(buzzvm_t vm, uint32_t argc) { /* Insert the self table right before the closure */ buzzdarray_insert(vm->stack, buzzdarray_size(vm->stack) - argc - 1, buzzheap_newobj(vm, BUZZTYPE_NIL)); /* Push the argument count */ buzzvm_pushi(vm, argc); /* Save the current stack depth */ uint32_t stacks = buzzdarray_size(vm->stacks); /* Call the closure and keep stepping until * the stack count is back to the saved value */ buzzvm_callc(vm); do if(buzzvm_step(vm) != BUZZVM_STATE_READY) return vm->state; while(stacks < buzzdarray_size(vm->stacks)); return vm->state; }
int buzzneighbors_kin(buzzvm_t vm) { buzzvm_lnum_assert(vm, 0); /* Initialize the swarm id to 'unknown' */ int32_t swarmid = -1; /* If the swarm stack is not empty, look for the swarm id */ if(!buzzdarray_isempty(vm->swarmstack)) { /* Get position in swarm stack */ uint16_t sstackpos = 1; if(buzzdarray_size(vm->lsyms->syms) > 1) sstackpos = buzzdarray_get(vm->lsyms->syms, 1, buzzobj_t)->i.value; /* Get swarm id */ if(sstackpos <= buzzdarray_size(vm->swarmstack)) swarmid = buzzdarray_get(vm->swarmstack, buzzdarray_size(vm->swarmstack) - sstackpos, uint16_t); } /* Get the self table */ buzzvm_lload(vm, 0); buzzvm_type_assert(vm, 1, BUZZTYPE_TABLE); /* Get the data table */ buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_tget(vm); buzzobj_t data = buzzvm_stack_at(vm, 1); /* Create a new table as return value */ buzzobj_t t; vm->state = make_table(vm, &t); if(vm->state != BUZZVM_STATE_READY) return vm->state; /* If data is available, filter it */ if(data->o.type == BUZZTYPE_TABLE) { /* Create a new data table */ buzzobj_t kindata = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); /* Filter the neighbors in data and add them to kindata */ struct neighbor_filter_s fdata = { .vm = vm, .swarm_id = swarmid, .result = kindata->t.value }; buzzdict_foreach(data->t.value, neighbor_filter_kin, &fdata); /* Add kindata as the "data" field in t */ buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_push(vm, kindata); buzzvm_tput(vm); } /* Return the table */ buzzvm_push(vm, t); return buzzvm_ret1(vm); }
static int make_table(buzzvm_t vm, uint16_t id) { /* Create a table and add data and methods */ buzzobj_t t = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); function_register(t, "others", buzzvm_swarm_others); function_register(t, "join", buzzvm_swarm_join); function_register(t, "leave", buzzvm_swarm_leave); function_register(t, "in", buzzvm_swarm_in); function_register(t, "select", buzzvm_swarm_select); function_register(t, "exec", buzzvm_swarm_exec); function_register(t, "others", buzzvm_swarm_others); /* Register swarm id */ buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_pushi(vm, id); buzzvm_tput(vm); /* Push the table on the stack */ buzzvm_push(vm, t); return BUZZVM_STATE_READY; }
buzzvm_state buzzvm_tput(buzzvm_t vm) { buzzvm_stack_assert(vm, 3); buzzvm_type_assert(vm, 3, BUZZTYPE_TABLE); buzzobj_t v = buzzvm_stack_at(vm, 1); buzzobj_t k = buzzvm_stack_at(vm, 2); buzzobj_t t = buzzvm_stack_at(vm, 3); buzzvm_pop(vm); buzzvm_pop(vm); buzzvm_pop(vm); if(k->o.type != BUZZTYPE_INT && k->o.type != BUZZTYPE_FLOAT && k->o.type != BUZZTYPE_STRING) { buzzvm_seterror(vm, BUZZVM_ERROR_TYPE, "a %s value can't be used as table key", buzztype_desc[k->o.type]); return vm->state; } if(v->o.type == BUZZTYPE_NIL) { /* Nil, erase entry */ buzzdict_remove(t->t.value, &k); } else if(v->o.type == BUZZTYPE_CLOSURE) { /* Method call */ int i; buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_CLOSURE); o->c.value.isnative = v->c.value.isnative; o->c.value.ref = v->c.value.ref; buzzdarray_push(o->c.value.actrec, &t); for(i = 1; i < buzzdarray_size(v->c.value.actrec); ++i) buzzdarray_push(o->c.value.actrec, &buzzdarray_get(v->c.value.actrec, i, buzzobj_t)); buzzdict_set(t->t.value, &k, &o); } else { buzzdict_set(t->t.value, &k, &v); } return BUZZVM_STATE_READY; }
void buzzvm_process_inmsgs(buzzvm_t vm) { /* Go through the messages */ while(!buzzinmsg_queue_isempty(vm->inmsgs)) { /* Make sure the VM is in the right state */ if(vm->state != BUZZVM_STATE_READY) return; /* Extract the message data */ uint16_t rid; buzzmsg_payload_t msg; buzzinmsg_queue_extract(vm, &rid, &msg); /* Dispatch the message wrt its type in msg->payload[0] */ switch(buzzmsg_payload_get(msg, 0)) { case BUZZMSG_BROADCAST: { /* Deserialize the topic */ buzzobj_t topic; int64_t pos = buzzobj_deserialize(&topic, msg, 1, vm); /* Make sure there's a listener to call */ const buzzobj_t* l = buzzdict_get(vm->listeners, &topic->s.value.sid, buzzobj_t); if(!l) { /* No listener, ignore message */ break; } /* Deserialize value */ buzzobj_t value; pos = buzzobj_deserialize(&value, msg, pos, vm); /* Make an object for the robot id */ buzzobj_t rido = buzzheap_newobj(vm, BUZZTYPE_INT); rido->i.value = rid; /* Call listener */ buzzvm_push(vm, *l); buzzvm_push(vm, topic); buzzvm_push(vm, value); buzzvm_push(vm, rido); buzzvm_closure_call(vm, 3); break; } case BUZZMSG_VSTIG_PUT: { /* Deserialize the vstig id */ uint16_t id; int64_t pos = buzzmsg_deserialize_u16(&id, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_PUT message received\n", vm->robot); break; } /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(!vs) break; /* Virtual stigmergy found */ /* Deserialize key and value from msg */ buzzobj_t k; // key buzzvstig_elem_t v = // value (buzzvstig_elem_t)malloc(sizeof(struct buzzvstig_elem_s)); if(buzzvstig_elem_deserialize(&k, &v, msg, pos, vm) < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_PUT message received\n", vm->robot); free(v); break; } /* Deserialization successful */ /* Fetch local vstig element */ const buzzvstig_elem_t* l = buzzvstig_fetch(*vs, &k); if((!l) || /* Element not found */ ((*l)->timestamp < v->timestamp)) { /* Local element is older */ /* Local element must be updated */ /* Store element */ buzzvstig_store(*vs, &k, &v); buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, v); } else if(((*l)->timestamp == v->timestamp) && /* Same timestamp */ ((*l)->robot != v->robot)) { /* Different robot */ /* Conflict! */ /* Call conflict manager */ buzzvstig_elem_t c = buzzvstig_onconflict_call(vm, *vs, k, *l, v); if(!c) { fprintf(stderr, "[WARNING] [ROBOT %u] Error resolving PUT conflict\n", vm->robot); break; } /* Get rid of useless vstig element */ free(v); /* Did this robot lose the conflict? */ if((c->robot != vm->robot) && ((*l)->robot == vm->robot)) { /* Yes */ /* Save current local entry */ buzzvstig_elem_t ol = buzzvstig_elem_clone(vm, *l); /* Store winning value */ buzzvstig_store(*vs, &k, &c); /* Call conflict lost manager */ buzzvstig_onconflictlost_call(vm, *vs, k, ol); } else { /* This robot did not lose the conflict */ /* Just propagate the PUT message */ buzzvstig_store(*vs, &k, &c); } buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, c); } else { /* Remote element is older, ignore it */ /* Get rid of useless vstig element */ free(v); } break; } case BUZZMSG_VSTIG_QUERY: { /* Deserialize the vstig id */ uint16_t id; int64_t pos = buzzmsg_deserialize_u16(&id, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_QUERY message received (1)\n", vm->robot); break; } /* Deserialize key and value from msg */ buzzobj_t k; // key buzzvstig_elem_t v = // value (buzzvstig_elem_t)malloc(sizeof(struct buzzvstig_elem_s)); if(buzzvstig_elem_deserialize(&k, &v, msg, pos, vm) < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_QUERY message received (2)\n", vm->robot); free(v); break; } /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(!vs) { /* Virtual stigmergy not found, simply propagate the message */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, v); free(v); break; } /* Virtual stigmergy found */ /* Fetch local vstig element */ const buzzvstig_elem_t* l = buzzvstig_fetch(*vs, &k); if(!l) { /* Element not found */ if(v->data->o.type == BUZZTYPE_NIL) { /* This robot knows nothing about the query, just propagate it */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, v); free(v); } else { /* Store element and propagate PUT message */ buzzvstig_store(*vs, &k, &v); buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, v); } break; } /* Element found */ if((*l)->timestamp < v->timestamp) { /* Local element is older */ /* Store element */ buzzvstig_store(*vs, &k, &v); buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, v); } else if((*l)->timestamp > v->timestamp) { /* Local element is newer */ /* Append a PUT message to the out message queue */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, *l); free(v); } else if(((*l)->timestamp == v->timestamp) && /* Same timestamp */ ((*l)->robot != v->robot)) { /* Different robot */ /* Conflict! */ /* Call conflict manager */ buzzvstig_elem_t c = buzzvstig_onconflict_call(vm, *vs, k, *l, v); free(v); /* Make sure conflict manager returned with an element to process */ if(!c) break; /* Did this robot lose the conflict? */ if((c->robot != vm->robot) && ((*l)->robot == vm->robot)) { /* Yes */ /* Save current local entry */ buzzvstig_elem_t ol = buzzvstig_elem_clone(vm, *l); /* Store winning value */ buzzvstig_store(*vs, &k, &c); /* Call conflict lost manager */ buzzvstig_onconflictlost_call(vm, *vs, k, ol); } else { /* This robot did not lose the conflict */ /* Just propagate the PUT message */ buzzvstig_store(*vs, &k, &c); } buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, c); } else { /* Remote element is same as local, ignore it */ /* Get rid of useless vstig element */ free(v); } break; } case BUZZMSG_SWARM_LIST: { /* Deserialize number of swarm ids */ uint16_t nsids; int64_t pos = buzzmsg_deserialize_u16(&nsids, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_LIST message received\n", vm->robot); break; } if(nsids < 1) break; /* Deserialize swarm ids */ buzzdarray_t sids = buzzdarray_new(nsids, sizeof(uint16_t), NULL); uint16_t i; for(i = 0; i < nsids; ++i) { pos = buzzmsg_deserialize_u16(buzzdarray_makeslot(sids, i), msg, pos); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_LIST message received\n", vm->robot); break; } } /* Update the information */ buzzswarm_members_refresh(vm->swarmmembers, rid, sids); break; } case BUZZMSG_SWARM_JOIN: { /* Deserialize swarm id */ uint16_t sid; int64_t pos = buzzmsg_deserialize_u16(&sid, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_JOIN message received\n", vm->robot); break; } /* Update the information */ buzzswarm_members_join(vm->swarmmembers, rid, sid); break; } case BUZZMSG_SWARM_LEAVE: { /* Deserialize swarm id */ uint16_t sid; int64_t pos = buzzmsg_deserialize_u16(&sid, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_LEAVE message received\n", vm->robot); break; } /* Update the information */ buzzswarm_members_leave(vm->swarmmembers, rid, sid); break; } } /* Get rid of the message */ buzzmsg_payload_destroy(&msg); } /* Update swarm membership */ buzzswarm_members_update(vm->swarmmembers); }
buzzvm_state buzzvm_pushf(buzzvm_t vm, float v) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_FLOAT); o->f.value = v; buzzvm_push(vm, o); return vm->state; }
buzzvm_state buzzvm_pushi(buzzvm_t vm, int32_t v) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_INT); o->i.value = v; buzzvm_push(vm, o); return vm->state; }
buzzvm_state buzzvm_pushnil(buzzvm_t vm) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_NIL); buzzvm_push(vm, o); return vm->state; }
buzzvm_state buzzvm_pushu(buzzvm_t vm, void* v) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_USERDATA); o->u.value = v; buzzvm_push(vm, o); return vm->state; }