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); }
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_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); }
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); }
int buzzvm_swarm_create(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get the id */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; /* Add a new entry if necessary */ if(!buzzdict_exists(vm->swarms, &id)) { uint8_t v = 0; buzzdict_set(vm->swarms, &id, &v); } /* Create a table to return */ make_table(vm, id); /* Return */ return buzzvm_ret1(vm); }
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); }
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 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 buzzvstig_get(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get vstig id */ id_get(); /* Get key */ buzzvm_lload(vm, 1); buzzobj_t k = buzzvm_stack_at(vm, 1); /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Virtual stigmergy found */ /* Look for key and push result */ const 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, BUZZMSG_VSTIG_QUERY, id, k, *e); } else { /* Key not found, make a new one containing nil */ buzzvm_pushnil(vm); buzzvstig_elem_t x = buzzvstig_elem_new(buzzvm_stack_at(vm, 1), // nil value 0, // timestamp vm->robot); // robot id /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, x); free(x); } } else { /* No virtual stigmergy found, just push false */ /* If this happens, its a bug */ buzzvm_pushnil(vm); } /* Return the value found */ return buzzvm_ret1(vm); }
int hook(buzzvm_t vm) { fprintf(stdout, "Hook called!\n\n"); buzzvm_pushf(vm, 17.0); return buzzvm_ret1(vm); }
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; }