void buzzvm_vstig_onconflictlost(buzzvm_t vm, buzzvstig_t vs, buzzobj_t k, buzzvstig_elem_t lv) { /* Was a conflict manager defined? */ if(vs->onconflictlost) { /* Push closure */ buzzvm_push(vm, vs->onconflictlost); /* Push key */ buzzvm_push(vm, k); /* Make table for local value */ buzzvm_pusht(vm); buzzobj_t loc = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_pushi(vm, lv->robot); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_push(vm, lv->data); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "timestamp")); buzzvm_pushi(vm, lv->timestamp); buzzvm_tput(vm); /* Call closure with 2 arguments */ buzzvm_push(vm, loc); buzzvm_closure_call(vm, 2); } }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, SInt32 n_value) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pushi(m_tBuzzVM, n_value); buzzvm_tput(m_tBuzzVM); return m_tBuzzVM->state; }
// proper way to send loooong 1D array int BuzzSetMap(buzzvm_t vm){ /* Make sure one parameter has been passed */ buzzvm_lnum_assert(vm, 1); /* Get the parameter */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_TABLE); // matrix /* Get the table */ buzzobj_t t = buzzvm_stack_at(vm, 1); /* Copy the values into a vector */ std::vector<float> mat; for(int32_t i = 0; i < buzzdict_size(t->t.value); ++i) { /* Duplicate the table */ buzzvm_dup(vm); /* Push the index */ buzzvm_pushi(vm, i); /* Get the value */ buzzvm_tget(vm); /* Store it in the vector (assume all values are float, no mistake...) */ mat.push_back((float)buzzvm_stack_at(vm, 1)->f.value); /* Get rid of the value, now useless */ buzzvm_pop(vm); } /* Get a pointer to the controller */ buzzvm_pushs(vm, buzzvm_string_register(vm, "controller", 1)); buzzvm_gload(vm); /* Copy data into the controller */ reinterpret_cast<CBuzzControllerFootBot*>(buzzvm_stack_at(vm, 1)->u.value)->SetMapParams(mat, Sqrt(buzzdict_size(t->t.value))); /* Done with the function */ return buzzvm_ret0(vm); }
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); }
int buzzvstig_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 */ const 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 */ buzzvm_pusht(vm); /* Add data and methods */ buzzvm_dup(vm); buzzvm_pushs(vm, buzzvm_string_register(vm, "id", 1)); buzzvm_pushi(vm, id); buzzvm_tput(vm); function_register(foreach); function_register(size); function_register(put); function_register(get); function_register(onconflict); function_register(onconflictlost); /* Return the table */ return buzzvm_ret1(vm); }
buzzvm_state CBuzzController::Register(const std::string& str_key, SInt32 n_value) { buzzvm_pushs(m_tBuzzVM, buzzvm_string_register(m_tBuzzVM, str_key.c_str(), 1)); buzzvm_pushi(m_tBuzzVM, n_value); buzzvm_gstore(m_tBuzzVM); return m_tBuzzVM->state; }
int buzzvstig_size(buzzvm_t vm) { buzzvm_lnum_assert(vm, 0); /* Get vstig id */ id_get(); /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Virtual stigmergy found, return its size */ buzzvm_pushi(vm, buzzdict_size((*vs)->data)); } else { /* Virtual stigmergy not found, return 0 */ buzzvm_pushi(vm, 0); } /* Return */ return buzzvm_ret1(vm); }
static int BuzzTakeOff(buzzvm_t vm) { /* Get pointer to the controller */ buzzvm_pushs(vm, buzzvm_string_register(vm, "controller", 1)); buzzvm_gload(vm); /* Call function */ int cont = reinterpret_cast<CBuzzControllerSpiri*>(buzzvm_stack_at(vm, 1)->u.value)->TakeOff(); buzzvm_pushi(vm, cont); return buzzvm_ret1(vm); }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, const std::string& str_key, SInt32 n_value) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushs(m_tBuzzVM, buzzvm_string_register(m_tBuzzVM, str_key.c_str(), 1)); buzzvm_pushi(m_tBuzzVM, n_value); buzzvm_tput(m_tBuzzVM); return m_tBuzzVM->state; }
int buzzvm_vstig_size(buzzvm_t vm) { buzzvm_lnum_assert(vm, 0); /* Get vstig id */ buzzvm_lload(vm, 0); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_tget(vm); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; /* Look for virtual stigmergy */ buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Virtual stigmergy found, return its size */ buzzvm_pushi(vm, buzzdict_size((*vs)->data)); } else { /* Virtual stigmergy not found, return 0 */ buzzvm_pushi(vm, 0); } /* Return */ return buzzvm_ret1(vm); }
int BuzzSetPath(buzzvm_t vm){ buzzvm_lnum_assert(vm, 1); /* Get the parameter */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_TABLE); // dictionary buzzobj_t t = buzzvm_stack_at(vm, 1); std::vector<CBuzzControllerFootBot::PathItem> pis; for(int32_t i = 0; i < buzzdict_size(t->t.value); ++i) { buzzvm_dup(vm); buzzvm_pushi(vm, i); buzzvm_tget(vm); int id = 0; int parent = 0; float x = 0.0; float y = 0.0; for(int32_t j = 0; j < buzzdict_size(buzzvm_stack_at(vm, 1)->t.value); ++j) { buzzvm_dup(vm); buzzvm_pushi(vm, j); buzzvm_tget(vm); if(j == 0){ id = (float)buzzvm_stack_at(vm, 1)->i.value; } else if(j == 1){ parent = (float)buzzvm_stack_at(vm, 1)->i.value; } else if (j == 2){ x = (float)buzzvm_stack_at(vm, 1)->f.value; } else if (j == 3){ y = (float)buzzvm_stack_at(vm, 1)->f.value; } //fprintf(stdout, "%d %f \n", j, (float)buzzvm_stack_at(vm, 1)->f.value); buzzvm_pop(vm); } pis.push_back(CBuzzControllerFootBot::PathItem(id, parent, x, y)); buzzvm_pop(vm); } /* Get a pointer to the controller */ buzzvm_pushs(vm, buzzvm_string_register(vm, "controller", 1)); buzzvm_gload(vm); /* Copy data into the controller */ reinterpret_cast<CBuzzControllerFootBot*>(buzzvm_stack_at(vm, 1)->u.value)->Done(pis); /* Done with the function */ return buzzvm_ret0(vm); }
int buzzvm_set_bcode(buzzvm_t vm, const uint8_t* bcode, uint32_t bcode_size) { /* Fetch the string count */ uint16_t count; memcpy(&count, bcode, sizeof(uint16_t)); /* Go through the strings and store them */ uint32_t i = sizeof(uint16_t); long int c = 0; for(; (c < count) && (i < bcode_size); ++c) { /* Store string */ buzzvm_string_register(vm, (char*)(bcode + i), 1); /* Advance to first character of next string */ while(*(bcode + i) != 0) ++i; ++i; } /* Initialize VM state */ vm->state = BUZZVM_STATE_READY; vm->error = BUZZVM_ERROR_NONE; /* Initialize bytecode data */ vm->bcode_size = bcode_size; vm->bcode = bcode; /* Set program counter */ vm->pc = i; vm->oldpc = vm->pc; /* * Register function definitions * Stop when you find a 'nop' */ while(vm->bcode[vm->pc] != BUZZVM_INSTR_NOP) if(buzzvm_step(vm) != BUZZVM_STATE_READY) return vm->state; buzzvm_step(vm); /* Initialize empty neighbors */ buzzneighbors_reset(vm); /* Register robot id */ buzzvm_pushs(vm, buzzvm_string_register(vm, "id", 1)); buzzvm_pushi(vm, vm->robot); buzzvm_gstore(vm); /* Register basic functions */ buzzobj_register(vm); /* Register stigmergy methods */ buzzvstig_register(vm); /* Register swarm methods */ buzzswarm_register(vm); /* Register math methods */ buzzmath_register(vm); /* Register io methods */ buzzio_register(vm); /* Register string methods */ buzzstring_register(vm); /* All done */ return BUZZVM_STATE_READY; }
void buzzvstig_foreach_entry(const void* key, void* data, void* params) { /* Cast params */ struct buzzvstig_foreach_params* p = (struct buzzvstig_foreach_params*)params; if(p->vm->state != BUZZVM_STATE_READY) return; /* Push closure and params (key, value, robot) */ buzzvm_push(p->vm, p->fun); buzzvm_push(p->vm, *(buzzobj_t*)key); buzzvm_push(p->vm, (*(buzzvstig_elem_t*)data)->data); buzzvm_pushi(p->vm, (*(buzzvstig_elem_t*)data)->robot); /* Call closure */ p->vm->state = buzzvm_closure_call(p->vm, 3); }
int BuzzDrawObstacles(buzzvm_t vm){ buzzvm_lnum_assert(vm, 1); buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_TABLE); // dictionary buzzobj_t t = buzzvm_stack_at(vm, 1); std::vector<CBuzzControllerFootBot::Obstacle> obs; for(int32_t i = 0; i < buzzdict_size(t->t.value); ++i) { buzzvm_dup(vm); buzzvm_pushi(vm, i); buzzvm_tget(vm); float x = 0.0; float y = 0.0; float radius = 0.0; int type = 0; for(int32_t j = 0; j < buzzdict_size(buzzvm_stack_at(vm, 1)->t.value); ++j) { buzzvm_dup(vm); buzzvm_pushi(vm, j); buzzvm_tget(vm); if(j == 0){ x = (float)buzzvm_stack_at(vm, 1)->f.value; } else if(j == 1){ y = (float)buzzvm_stack_at(vm, 1)->f.value; } else if (j == 2){ radius = (float)buzzvm_stack_at(vm, 1)->f.value; } else if (j == 3){ type = (int) buzzvm_stack_at(vm, 1)->i.value; } //fprintf(stdout, "%d %f \n", j, (float)buzzvm_stack_at(vm, 1)->f.value); buzzvm_pop(vm); } obs.push_back(CBuzzControllerFootBot::Obstacle(x, y, radius, type)); buzzvm_pop(vm); } buzzvm_pushs(vm, buzzvm_string_register(vm, "controller", 1)); buzzvm_gload(vm); reinterpret_cast<CBuzzControllerFootBot*>(buzzvm_stack_at(vm, 1)->u.value)->ArgosDrawObstacles(obs); return buzzvm_ret0(vm); }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, const CVector3& c_vec) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pusht(m_tBuzzVM); buzzobj_t tVecTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); TablePut(tVecTable, "x", c_vec.GetX()); TablePut(tVecTable, "y", c_vec.GetY()); TablePut(tVecTable, "z", c_vec.GetZ()); return m_tBuzzVM->state; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, const CColor& c_color) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pusht(m_tBuzzVM); buzzobj_t tColorTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); TablePut(tColorTable, "red", c_color.GetRed()); TablePut(tColorTable, "green", c_color.GetGreen()); TablePut(tColorTable, "blue", c_color.GetBlue()); return m_tBuzzVM->state; }
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; }
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; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, const CQuaternion& c_quat) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pusht(m_tBuzzVM); buzzobj_t tQuatTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); CRadians cYaw, cPitch, cRoll; c_quat.ToEulerAngles(cYaw, cPitch, cRoll); TablePut(tQuatTable, "yaw", cYaw); TablePut(tQuatTable, "pitch", cPitch); TablePut(tQuatTable, "roll", cRoll); return m_tBuzzVM->state; }
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 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); }
int buzzvm_swarm_in(buzzvm_t vm) { buzzvm_lnum_assert(vm, 0); /* Get the id */ buzzvm_lload(vm, 0); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_tget(vm); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; /* Get the swarm entry */ uint8_t* x = buzzdict_get(vm->swarms, &id, uint8_t); if(!x) { vm->state = BUZZVM_STATE_ERROR; vm->error = BUZZVM_ERROR_SWARM; return BUZZVM_STATE_ERROR; } /* Push the return value */ buzzvm_pushi(vm, *x); /* Return */ 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; }
int buzzvm_swarm_exec(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get the id */ buzzvm_lload(vm, 0); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_tget(vm); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; /* Get the swarm entry */ uint8_t* x = buzzdict_get(vm->swarms, &id, uint8_t); if(!x) { vm->state = BUZZVM_STATE_ERROR; vm->error = BUZZVM_ERROR_SWARM; return BUZZVM_STATE_ERROR; } /* Check whether the robot is in the swarm */ if(*x) { /* Get the closure */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_CLOSURE); buzzobj_t c = buzzvm_stack_at(vm, 1); /* Get rid of the current call structure */ if(buzzvm_ret0(vm) != BUZZVM_STATE_READY) return vm->state; /* Save the current stack depth */ uint32_t stacks = buzzdarray_size(vm->stacks); /* Push the current swarm in the stack */ buzzdarray_push(vm->swarmstack, &id); /* Call the closure */ buzzvm_push(vm, c); int32_t numargs = 0; buzzvm_pushi(vm, numargs); buzzvm_calls(vm); do if(buzzvm_step(vm) != BUZZVM_STATE_READY) return vm->state; while(stacks < buzzdarray_size(vm->stacks)); return vm->state; } else { /* Get rid of the current call structure */ return buzzvm_ret0(vm); } }
buzzvstig_elem_t buzzvm_vstig_onconflict(buzzvm_t vm, buzzvstig_t vs, buzzobj_t k, buzzvstig_elem_t lv, buzzvstig_elem_t rv) { /* Was a conflict manager defined? */ if(vs->onconflict) { /* Push closure */ buzzvm_push(vm, vs->onconflict); /* Push key */ buzzvm_push(vm, k); /* Make table for local value */ buzzvm_pusht(vm); buzzobj_t loc = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_pushi(vm, lv->robot); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_push(vm, lv->data); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "timestamp")); buzzvm_pushi(vm, lv->timestamp); buzzvm_tput(vm); /* Make table for remote value */ buzzvm_pusht(vm); buzzobj_t rem = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_pushi(vm, rv->robot); buzzvm_tput(vm); buzzvm_push(vm, rem); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_push(vm, rv->data); buzzvm_tput(vm); buzzvm_push(vm, rem); buzzvm_pushs(vm, buzzvm_string_register(vm, "timestamp")); buzzvm_pushi(vm, rv->timestamp); buzzvm_tput(vm); /* Call closure with 3 arguments */ buzzvm_push(vm, loc); buzzvm_push(vm, rem); buzzvm_closure_call(vm, 3); /* Make new entry with return value */ /* Make sure it's a table */ if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_TABLE) { fprintf(stderr, "[WARNING] [ROBOT %u] Return value type is %d\n", vm->robot, buzzvm_stack_at(vm, 1)->o.type); return NULL; } /* Get the robot id */ buzzobj_t ret = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_tget(vm); if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_INT) return NULL; uint16_t robot = buzzvm_stack_at(vm, 1)->i.value; buzzvm_pop(vm); /* Get the data */ buzzvm_push(vm, ret); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_tget(vm); buzzobj_t data = buzzvm_stack_at(vm, 1); buzzvm_pop(vm); /* Make new entry */ return buzzvstig_elem_new(data, lv->timestamp, robot); } else { /* No conflict manager, use default behavior */ if(lv->robot > rv->robot) return buzzvstig_elem_clone(lv); else return buzzvstig_elem_clone(rv); } }
buzzvm_state buzzvm_step(buzzvm_t vm) { /* buzzvm_dump(vm); */ /* Can't execute if not ready */ if(vm->state != BUZZVM_STATE_READY) return vm->state; /* Execute GC */ buzzheap_gc(vm); /* Fetch instruction and (potential) argument */ uint8_t instr = vm->bcode[vm->pc]; /* Execute instruction */ switch(instr) { case BUZZVM_INSTR_NOP: { inc_pc(); break; } case BUZZVM_INSTR_DONE: { buzzvm_done(vm); break; } case BUZZVM_INSTR_PUSHNIL: { inc_pc(); buzzvm_pushnil(vm); break; } case BUZZVM_INSTR_DUP: { inc_pc(); buzzvm_dup(vm); break; } case BUZZVM_INSTR_POP: { if(buzzvm_pop(vm) != BUZZVM_STATE_READY) return vm->state; inc_pc(); break; } case BUZZVM_INSTR_RET0: { if(buzzvm_ret0(vm) != BUZZVM_STATE_READY) return vm->state; assert_pc(vm->pc); break; } case BUZZVM_INSTR_RET1: { if(buzzvm_ret1(vm) != BUZZVM_STATE_READY) return vm->state; assert_pc(vm->pc); break; } case BUZZVM_INSTR_ADD: { buzzvm_add(vm); inc_pc(); break; } case BUZZVM_INSTR_SUB: { buzzvm_sub(vm); inc_pc(); break; } case BUZZVM_INSTR_MUL: { buzzvm_mul(vm); inc_pc(); break; } case BUZZVM_INSTR_DIV: { buzzvm_div(vm); inc_pc(); break; } case BUZZVM_INSTR_MOD: { buzzvm_mod(vm); inc_pc(); break; } case BUZZVM_INSTR_POW: { buzzvm_pow(vm); inc_pc(); break; } case BUZZVM_INSTR_UNM: { buzzvm_unm(vm); inc_pc(); break; } case BUZZVM_INSTR_AND: { buzzvm_and(vm); inc_pc(); break; } case BUZZVM_INSTR_OR: { buzzvm_or(vm); inc_pc(); break; } case BUZZVM_INSTR_NOT: { buzzvm_not(vm); inc_pc(); break; } case BUZZVM_INSTR_EQ: { buzzvm_eq(vm); inc_pc(); break; } case BUZZVM_INSTR_NEQ: { buzzvm_neq(vm); inc_pc(); break; } case BUZZVM_INSTR_GT: { buzzvm_gt(vm); inc_pc(); break; } case BUZZVM_INSTR_GTE: { buzzvm_gte(vm); inc_pc(); break; } case BUZZVM_INSTR_LT: { buzzvm_lt(vm); inc_pc(); break; } case BUZZVM_INSTR_LTE: { buzzvm_lte(vm); inc_pc(); break; } case BUZZVM_INSTR_GLOAD: { inc_pc(); buzzvm_gload(vm); break; } case BUZZVM_INSTR_GSTORE: { inc_pc(); if(buzzvm_gstore(vm) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_PUSHT: { buzzvm_pusht(vm); inc_pc(); break; } case BUZZVM_INSTR_TPUT: { if(buzzvm_tput(vm) != BUZZVM_STATE_READY) return vm->state; inc_pc(); break; } case BUZZVM_INSTR_TGET: { if(buzzvm_tget(vm) != BUZZVM_STATE_READY) return vm->state; inc_pc(); break; } case BUZZVM_INSTR_CALLC: { inc_pc(); if(buzzvm_callc(vm) != BUZZVM_STATE_READY) return vm->state; assert_pc(vm->pc); break; } case BUZZVM_INSTR_CALLS: { inc_pc(); if(buzzvm_calls(vm) != BUZZVM_STATE_READY) return vm->state; assert_pc(vm->pc); break; } case BUZZVM_INSTR_PUSHF: { inc_pc(); get_arg(float); if(buzzvm_pushf(vm, arg) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_PUSHI: { inc_pc(); get_arg(int32_t); if(buzzvm_pushi(vm, arg) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_PUSHS: { inc_pc(); get_arg(int32_t); if(buzzvm_pushs(vm, arg) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_PUSHCN: { inc_pc(); get_arg(uint32_t); if(buzzvm_pushcn(vm, arg) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_PUSHCC: { inc_pc(); get_arg(uint32_t); if(buzzvm_pushcc(vm, arg) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_PUSHL: { inc_pc(); get_arg(uint32_t); if(buzzvm_pushl(vm, arg) != BUZZVM_STATE_READY) return vm->state; break; } case BUZZVM_INSTR_LLOAD: { inc_pc(); get_arg(uint32_t); buzzvm_lload(vm, arg); break; } case BUZZVM_INSTR_LSTORE: { inc_pc(); get_arg(uint32_t); buzzvm_lstore(vm, arg); break; } case BUZZVM_INSTR_JUMP: { inc_pc(); get_arg(uint32_t); vm->pc = arg; assert_pc(vm->pc); break; } case BUZZVM_INSTR_JUMPZ: { inc_pc(); get_arg(uint32_t); buzzvm_stack_assert(vm, 1); if(buzzvm_stack_at(vm, 1)->o.type == BUZZTYPE_NIL || (buzzvm_stack_at(vm, 1)->o.type == BUZZTYPE_INT && buzzvm_stack_at(vm, 1)->i.value == 0)) { vm->pc = arg; assert_pc(vm->pc); } buzzvm_pop(vm); break; } case BUZZVM_INSTR_JUMPNZ: { inc_pc(); get_arg(uint32_t); buzzvm_stack_assert(vm, 1); if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_NIL && (buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_INT || buzzvm_stack_at(vm, 1)->i.value != 0)) { vm->pc = arg; assert_pc(vm->pc); } buzzvm_pop(vm); break; } default: buzzvm_seterror(vm, BUZZVM_ERROR_INSTR, NULL); break; } return vm->state; }