int64_t buzzmsg_deserialize_u16(uint16_t* data, buzzdarray_t buf, uint32_t pos) { if(pos + sizeof(uint16_t) > buzzdarray_size(buf)) return -1; *data = buzzdarray_get(buf, pos, uint8_t) + (buzzdarray_get(buf, pos+1, uint8_t) << 8); *data = ntohs(*data); return pos + sizeof(uint16_t); }
int64_t buzzmsg_deserialize_u32(uint32_t* data, buzzdarray_t buf, uint32_t pos) { if(pos + sizeof(uint32_t) > buzzdarray_size(buf)) return -1; *data = buzzdarray_get(buf, pos, uint8_t) + (buzzdarray_get(buf, pos+1, uint8_t) << 8) + (buzzdarray_get(buf, pos+2, uint8_t) << 16) + (buzzdarray_get(buf, pos+3, uint8_t) << 24); *data = ntohl(*data); return pos + sizeof(uint32_t); }
buzzvm_state buzzvm_call(buzzvm_t vm, int isswrm) { /* Get argument number and pop it */ buzzvm_stack_assert(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); int32_t argn = buzzvm_stack_at(vm, 1)->i.value; buzzvm_pop(vm); /* Make sure the stack has enough elements */ buzzvm_stack_assert(vm, argn+1); /* Make sure the closure is where expected */ buzzvm_type_assert(vm, argn+1, BUZZTYPE_CLOSURE); buzzobj_t c = buzzvm_stack_at(vm, argn+1); /* Make sure that that data about C closures is correct */ if((!c->c.value.isnative) && ((c->c.value.ref) >= buzzdarray_size(vm->flist))) { buzzvm_seterror(vm, BUZZVM_ERROR_FLIST, NULL); return vm->state; } /* Create a new local symbol list copying the parent's */ vm->lsyms = buzzvm_lsyms_new(isswrm, buzzdarray_clone(c->c.value.actrec)); buzzdarray_push(vm->lsymts, &(vm->lsyms)); /* Add function arguments to the local symbols */ int32_t i; for(i = argn; i > 0; --i) buzzdarray_push(vm->lsyms->syms, &buzzdarray_get(vm->stack, buzzdarray_size(vm->stack) - i, buzzobj_t)); /* Get rid of the function arguments */ for(i = argn+1; i > 0; --i) buzzdarray_pop(vm->stack); /* Pop unused self table */ buzzdarray_pop(vm->stack); /* Push return address */ buzzvm_pushi((vm), vm->pc); /* Make a new stack for the function */ vm->stack = buzzdarray_new(1, sizeof(buzzobj_t), NULL); buzzdarray_push(vm->stacks, &(vm->stack)); /* Jump to/execute the function */ if(c->c.value.isnative) { vm->oldpc = vm->pc; vm->pc = c->c.value.ref; } else buzzdarray_get(vm->flist, c->c.value.ref, buzzvm_funp)(vm); return vm->state; }
int buzzvm_swarm_id(struct buzzvm_s* vm) { /* Is the swarm stack empty? */ if(buzzdarray_isempty(vm->swarmstack)) { /* Yes, no swarm to push, push nil instead */ buzzvm_pushnil(vm); } else { /* Take the stack top by default */ uint16_t stackpos = 1; /* Do we have an argument? */ if(buzzvm_lnum(vm) > 1) { buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); stackpos = buzzvm_stack_at(vm, 1)->i.value; } /* Limit stackpos value to avoid out-of-bounds operations */ if(stackpos > buzzdarray_size(vm->swarmstack)) stackpos = buzzdarray_size(vm->swarmstack); /* Push the swarm id located at stackpos */ buzzvm_pushi(vm, buzzdarray_get( vm->swarmstack, buzzdarray_size(vm->swarmstack) - stackpos, uint16_t)); } /* Return the value */ return buzzvm_ret1(vm); }
int64_t buzzmsg_deserialize_u8(uint8_t* data, buzzdarray_t buf, uint32_t pos) { if(pos + sizeof(uint8_t) > buzzdarray_size(buf)) return -1; *data = buzzdarray_get(buf, pos, uint8_t); return pos + sizeof(uint8_t); }
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); }
void buzzvm_dump(buzzvm_t vm) { int64_t i, j; fprintf(stderr, "============================================================\n"); fprintf(stderr, "state: %d\terror: %d\n", vm->state, vm->error); fprintf(stderr, "code size: %u\tpc: %d\n", vm->bcode_size, vm->pc); fprintf(stderr, "stacks: %" PRId64 "\tcur elem: %" PRId64 " (size %" PRId64 ")\n", buzzdarray_size(vm->stacks), buzzvm_stack_top(vm), buzzvm_stack_top(vm)); for(i = buzzdarray_size(vm->stacks)-1; i >= 0 ; --i) { fprintf(stderr, "===== stack: %" PRId64 " =====\n", i); for(j = buzzdarray_size(buzzdarray_get(vm->stacks, i, buzzdarray_t)) - 1; j >= 0; --j) { fprintf(stderr, "\t%" PRId64 "\t", j); buzzobj_t o = buzzdarray_get(buzzdarray_get(vm->stacks, i, buzzdarray_t), j, buzzobj_t); switch(o->o.type) { case BUZZTYPE_NIL: fprintf(stderr, "[nil]\n"); break; case BUZZTYPE_INT: fprintf(stderr, "[int] %d\n", o->i.value); break; case BUZZTYPE_FLOAT: fprintf(stderr, "[float] %f\n", o->f.value); break; case BUZZTYPE_TABLE: fprintf(stderr, "[table] %d elements\n", buzzdict_size(o->t.value)); break; case BUZZTYPE_CLOSURE: if(o->c.value.isnative) { fprintf(stderr, "[n-closure] %d\n", o->c.value.ref); } else { fprintf(stderr, "[c-closure] %d\n", o->c.value.ref); } break; case BUZZTYPE_STRING: fprintf(stderr, "[string] %d:'%s'\n", o->s.value.sid, o->s.value.str); break; default: fprintf(stderr, "[TODO] type = %d\n", o->o.type); } } } fprintf(stderr, "============================================================\n\n"); }
void print_swarm_elem(const void* key, void* data, void* params) { uint32_t i; buzzswarm_elem_t e = *(buzzswarm_elem_t*)data; fprintf(stdout, "ROBOT %u -> R%u:", *(uint16_t*)params, *(uint16_t*)key); for(i = 0; i < buzzdarray_size(e->swarms); ++i) { fprintf(stdout, " %u", buzzdarray_get(e->swarms, i, uint16_t)); } fprintf(stdout, "\n"); }
int buzzswarm_members_isrobotin(buzzswarm_members_t m, uint16_t robot, uint16_t swarm) { /* Is an entry for the passed robot present? * If not, return false */ buzzswarm_elem_t* e = buzzdict_get(m, &robot, buzzswarm_elem_t); if(!e) return 0; /* If we get here, an entry is present * Does it contain the passed swarm id? */ uint32_t i; for(i = 0; i < buzzdarray_size((*e)->swarms); ++i) { if(buzzdarray_get((*e)->swarms, i, uint16_t) == swarm) return 1; } /* If we get here, it's because we couldn't find the id */ return 0; }
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); }
void buzzswarm_members_leave(buzzswarm_members_t m, uint16_t robot, uint16_t swarm) { /* Is an entry for the passed robot present? */ buzzswarm_elem_t* e = buzzdict_get(m, &robot, buzzswarm_elem_t); if(e) { /* Yes, update it */ (*e)->age = 0; /* Search for the passed id */ uint32_t i; for(i = 0; i < buzzdarray_size((*e)->swarms); ++i) { if(buzzdarray_get((*e)->swarms, i, uint16_t) == swarm) break; } /* If the element was found, remove it */ if(i < buzzdarray_size((*e)->swarms)) buzzdarray_remove((*e)->swarms, i); /* If no swarm id is known for this robot, remove the entry altogether */ if(buzzdarray_isempty((*e)->swarms)) buzzdict_remove(m, &robot); } /* Nothing to do if you get a 'leave' message for someone you don't know */ }
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 buzzswarm_members_join(buzzswarm_members_t m, uint16_t robot, uint16_t swarm) { /* Is an entry for the passed robot already present? */ buzzswarm_elem_t* e = buzzdict_get(m, &robot, buzzswarm_elem_t); if(e) { /* Yes, update it */ (*e)->age = 0; /* Search for the passed id; if found, nothing to do */ uint32_t i; for(i = 0; i < buzzdarray_size((*e)->swarms); ++i) { if(buzzdarray_get((*e)->swarms, i, uint16_t) == swarm) return; } /* If we get here, it's because we got new information - add it */ buzzdarray_push((*e)->swarms, &swarm); } else { /* No, create it */ buzzswarm_elem_t ne = buzzswarm_elem_new(); buzzdarray_push(ne->swarms, &swarm); /* Add it to the structure */ buzzdict_set(m, &robot, &ne); } }