int buzzvm_swarm_others(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get the id of the current swarm */ buzzvm_lload(vm, 0); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_tget(vm); uint16_t id1 = buzzvm_stack_at(vm, 1)->i.value; /* Get the swarm entry */ uint8_t* x = buzzdict_get(vm->swarms, &id1, uint8_t); if(!x) { vm->state = BUZZVM_STATE_ERROR; vm->error = BUZZVM_ERROR_SWARM; return BUZZVM_STATE_ERROR; } /* Get the id of the new swarm to create */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); uint16_t id2 = buzzvm_stack_at(vm, 1)->i.value; /* Add a new entry for the swarm */ uint8_t v = *x ? 0 : 1; buzzdict_set(vm->swarms, &id2, &v); /* Send update, if necessary */ if(v) buzzoutmsg_queue_append_swarm_joinleave( vm->outmsgs, BUZZMSG_SWARM_JOIN, id2); /* Create a table to return */ make_table(vm, id2); /* Return */ return buzzvm_ret1(vm); }
int buzzvm_swarm_select(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 result of the condition check */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); uint8_t in = buzzvm_stack_at(vm, 1)->i.value; /* Update the swarm, if known */ if(buzzdict_exists(vm->swarms, &id)) { /* Store membership */ buzzdict_set(vm->swarms, &id, &in); /* Send update */ buzzoutmsg_queue_append_swarm_joinleave( vm->outmsgs, in ? BUZZMSG_SWARM_JOIN : BUZZMSG_SWARM_LEAVE, id); /* Return */ return buzzvm_ret0(vm); } else { vm->state = BUZZVM_STATE_ERROR; vm->error = BUZZVM_ERROR_SWARM; return BUZZVM_STATE_ERROR; } }
int buzzvm_vstig_setonconflictlost(struct buzzvm_s* vm) { buzzvm_lnum_assert(vm, 1); /* 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 */ /* Get closure */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_CLOSURE); /* Clone the closure */ if((*vs)->onconflictlost) free((*vs)->onconflictlost); (*vs)->onconflictlost = buzzobj_clone(buzzvm_stack_at(vm, 1)); } else { /* No virtual stigmergy found, just push false */ /* If this happens, its a bug */ buzzvm_pushnil(vm); fprintf(stderr, "[BUG] [ROBOT %u] Can't find virtual stigmergy %u\n", vm->robot, id); } /* Return the value found */ return buzzvm_ret0(vm); }
// 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 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 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); }
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 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); }
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); }
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 buzzvm_vstig_get(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* 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; /* Get key */ buzzvm_lload(vm, 1); buzzobj_t k = buzzvm_stack_at(vm, 1); /* Look for virtual stigmergy */ buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Virtual stigmergy found */ /* Look for key and push result */ buzzvstig_elem_t* e = buzzvstig_fetch(*vs, &k); if(e) { /* Key found */ buzzvm_push(vm, (*e)->data); /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm->outmsgs, BUZZMSG_VSTIG_QUERY, id, k, *e); } else { /* Key not found, add a new one containing nil */ buzzvm_pushnil(vm); buzzvstig_elem_t x = buzzvstig_elem_new(buzzvm_stack_at(vm, 1), 1, vm->robot); /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm->outmsgs, BUZZMSG_VSTIG_QUERY, id, k, x); } } else { /* No virtual stigmergy found, just push false */ /* If this happens, its a bug */ buzzvm_pushnil(vm); fprintf(stderr, "[BUG] [ROBOT %u] Can't find virtual stigmergy %u\n", vm->robot, id); } /* Return the value found */ return buzzvm_ret1(vm); }
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); } }
int buzzvm_vstig_put(buzzvm_t vm) { buzzvm_lnum_assert(vm, 2); /* 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; /* Get key */ buzzvm_lload(vm, 1); buzzobj_t k = buzzvm_stack_at(vm, 1); /* Get value */ buzzvm_lload(vm, 2); buzzobj_t v = buzzvm_stack_at(vm, 1); /* Look for virtual stigmergy */ buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Look for the element */ buzzvstig_elem_t* x = buzzvstig_fetch(*vs, &k); if(x) { /* Element found, update it */ (*x)->data = v; ++((*x)->timestamp); (*x)->robot = vm->robot; /* Append a PUT message to the out message queue */ buzzoutmsg_queue_append_vstig(vm->outmsgs, BUZZMSG_VSTIG_PUT, id, k, *x); } else { /* Element not found, create a new one */ buzzvstig_elem_t y = buzzvstig_elem_new(v, 1, vm->robot); buzzvstig_store(*vs, &k, &y); /* Append a PUT message to the out message queue */ buzzoutmsg_queue_append_vstig(vm->outmsgs, BUZZMSG_VSTIG_PUT, id, k, y); } } /* Return */ return buzzvm_ret0(vm); }
int buzzvm_swarm_leave(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; /* Leave the swarm, if known */ if(buzzdict_exists(vm->swarms, &id)) { /* Store membership */ uint8_t v = 0; buzzdict_set(vm->swarms, &id, &v); /* Send update */ buzzoutmsg_queue_append_swarm_joinleave( vm->outmsgs, BUZZMSG_SWARM_LEAVE, id); /* Return */ return buzzvm_ret0(vm); } else { vm->state = BUZZVM_STATE_ERROR; vm->error = BUZZVM_ERROR_SWARM; return BUZZVM_STATE_ERROR; } }
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); } }
buzzvstig_elem_t buzzvstig_onconflict_call(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); add_field(robot, lv, pushi); add_field(data, lv, push); add_field(timestamp, lv, pushi); /* Make table for remote value */ buzzvm_pusht(vm); add_field(robot, rv, pushi); add_field(data, rv, push); add_field(timestamp, rv, pushi); /* Call closure (key, lv, rv on the stack) */ 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] virtual stigmergy onconflict(): Return value type is %s, expected table\n", vm->robot, buzztype_desc[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", 1)); 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", 1)); 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 both values are not nil, keep the value of the robot with the higher id */ if(((lv->data->o.type == BUZZTYPE_NIL) && (rv->data->o.type == BUZZTYPE_NIL)) || ((lv->data->o.type != BUZZTYPE_NIL) && (rv->data->o.type != BUZZTYPE_NIL))) { if(lv->robot > rv->robot) return buzzvstig_elem_clone(vm, lv); else return buzzvstig_elem_clone(vm, rv); } /* If my value is not nil, keep mine */ if(lv->data->o.type != BUZZTYPE_NIL) return buzzvstig_elem_clone(vm, lv); /* If the other value is not nil, keep that one */ if(rv->data->o.type != BUZZTYPE_NIL) return buzzvstig_elem_clone(vm, rv); /* Otherwise nothing to do */ return NULL; } }
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; }