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); }
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; }
void buzzdict_set(buzzdict_t dt, const void* key, const void* data) { /* Hash the key */ uint32_t h = dt->hashf(key) % dt->num_buckets; /* Is the bucket empty? */ if(!dt->buckets[h]) { /* Create new entry list */ dt->buckets[h] = buzzdarray_new(1, sizeof(struct buzzdict_entry_s), NULL); /* Add entry */ buzzdict_entry_new(dt, e, key, data); buzzdarray_push(dt->buckets[h], &e); /* Increase size */ ++(dt->size); } else { /* Bucket not empty - is the entry present? */ uint32_t i; for(i = 0; i < buzzdarray_size(dt->buckets[h]); ++i) { const struct buzzdict_entry_s* e = &buzzdarray_get(dt->buckets[h], i, struct buzzdict_entry_s); if(dt->keycmpf(key, e->key) == 0) { /* Yes, destroy the entry */ dt->dstryf(e->key, e->data, dt); buzzdarray_remove(dt->buckets[h], i); --(dt->size); break; } } /* Add new entry */ buzzdict_entry_new(dt, e, key, data); buzzdarray_push(dt->buckets[h], &e); /* Increase size */ ++(dt->size); } }
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 buzzdict_remove(buzzdict_t dt, const void* key) { /* Hash the key */ uint32_t h = dt->hashf(key) % dt->num_buckets, i; /* Is the bucket empty? */ if(!dt->buckets[h]) return 0; /* Bucket not empty - is the entry present? */ for(i = 0; i < buzzdarray_size(dt->buckets[h]); ++i) { const struct buzzdict_entry_s* e = &buzzdarray_get(dt->buckets[h], i, struct buzzdict_entry_s); if(dt->keycmpf(key, e->key) == 0) { /* Entry found - remove it */ dt->dstryf(e->key, e->data, dt); buzzdarray_remove(dt->buckets[h], i); /* Is the entry list empty? If so, free the memory */ if(buzzdarray_isempty(dt->buckets[h])) buzzdarray_destroy(&(dt->buckets[h])); /* Increase size */ --(dt->size); /* Done */ return 1; } } /* Entry not found, nothing to do */ return 0; }
void CBuzzController::ControlStep() { /* Update debugging information */ m_sDebug.Clear(); if(m_sDebug.Trajectory.Tracking) { const CCI_PositioningSensor::SReading& sPosRead = m_pcPos->GetReading(); m_sDebug.TrajectoryAdd(sPosRead.Position); } /* Take care of the rest */ if(m_tBuzzVM && m_tBuzzVM->state == BUZZVM_STATE_READY) { ProcessInMsgs(); UpdateSensors(); if(buzzvm_function_call(m_tBuzzVM, "step", 0) != BUZZVM_STATE_READY) { fprintf(stderr, "[ROBOT %u] %s: execution terminated abnormally: %s\n\n", m_tBuzzVM->robot, m_strBytecodeFName.c_str(), ErrorInfo().c_str()); for(UInt32 i = 1; i <= buzzdarray_size(m_tBuzzVM->stacks); ++i) { buzzdebug_stack_dump(m_tBuzzVM, i, stdout); } return; } ProcessOutMsgs(); } else { fprintf(stderr, "[ROBOT %s] Robot is not ready to execute Buzz script.\n\n", GetId().c_str()); } }
int64_t buzzmsg_deserialize_float(float* data, buzzdarray_t buf, uint32_t pos) { /* Make sure enough bytes are left to read */ if(pos + 2*sizeof(uint32_t) > buzzdarray_size(buf)) return -1; /* Read the mantissa and the exponent */ int32_t mant; int32_t exp; pos = buzzmsg_deserialize_u32((uint32_t*)(&mant), buf, pos); pos = buzzmsg_deserialize_u32((uint32_t*)(&exp), buf, pos); /* A zero mantissa corresponds to a zero float */ if(mant == 0) { *data = 0; } else { /* We must calculate the float * * Idea: use the function ldexpf(), which is the opposite of frexpf() * For this, we need to transform the mantissa into a normalized * fraction in the range [0.5,1) * * 1. Take the absolute value of the mantissa, which is in [1, MAX_MANTISSA+1] * 2. Subtract 1, so it's in [0, MAX_MANTISSA] * 3. divide by MAX_MANTISSA, so it's in [0,1) * 4. divide by 2, so it's in [0,0.5) * 5. Add 0.5, so it's in [0.5,1) */ *data = (float)(abs(mant) - 1) / (2.0f * MAX_MANTISSA) + 0.5f; /* Now use ldexpf() to calculate the absolute value */ *data = ldexpf(*data, exp); /* Finally take care of the sign */ if(mant < 0) *data = -*data; } return pos; }
buzzvm_state buzzvm_function_call(buzzvm_t vm, const char* fname, uint32_t argc) { /* Reset the VM state if it's DONE */ if(vm->state == BUZZVM_STATE_DONE) vm->state = BUZZVM_STATE_READY; /* Don't continue if the VM has an error */ if(vm->state != BUZZVM_STATE_READY) return vm->state; /* Push the function name (return with error if not found) */ buzzvm_pushs(vm, buzzvm_string_register(vm, fname, 0)); /* Get associated symbol */ buzzvm_gload(vm); /* Make sure it's a closure */ buzzvm_type_assert(vm, 1, BUZZTYPE_CLOSURE); /* Move closure before arguments */ if(argc > 0) { buzzdarray_insert(vm->stack, buzzdarray_size(vm->stack) - argc - 1, buzzvm_stack_at(vm, 1)); buzzvm_pop(vm); } /* Call the closure */ return buzzvm_closure_call(vm, argc); }
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); }
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_string(char** data, buzzdarray_t buf, uint32_t pos) { /* Make sure there are enough bytes to read the string length */ if(pos + sizeof(uint16_t) > buzzdarray_size(buf)) return -1; /* Read the string length */ uint16_t len; pos = buzzmsg_deserialize_u16(&len, buf, pos); /* Make sure there are enough bytes to read the string itself */ if(pos + len > buzzdarray_size(buf)) return -1; /* Create a buffer for the string */ *data = (char*)malloc(len * sizeof(char) + 1); /* Read the string characters */ memcpy(*data, (uint8_t*)buf->data + pos, len * sizeof(char)); /* Set the termination character */ *(*data + len) = 0; /* Return new position */ return pos + len; }
uint32_t buzzvm_function_register(buzzvm_t vm, buzzvm_funp funp) { /* Look for function pointer to avoid duplicates */ uint32_t fpos = buzzdarray_find(vm->flist, buzzvm_function_cmp, funp); if(fpos == buzzdarray_size(vm->flist)) { /* Add function to the list */ buzzdarray_push(vm->flist, &funp); } return fpos; }
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"); }
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); }
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); } }
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 */ }
void* buzzdict_rawget(buzzdict_t dt, const void* key) { /* Hash the key */ uint32_t h = dt->hashf(key) % dt->num_buckets, i; /* Is the bucket empty? */ if(!dt->buckets[h]) return NULL; /* Bucket not empty - is the entry present? */ for(i = 0; i < buzzdarray_size(dt->buckets[h]); ++i) { const struct buzzdict_entry_s* e = &buzzdarray_get(dt->buckets[h], i, struct buzzdict_entry_s); if(dt->keycmpf(key, e->key) == 0) return e->data; } /* Entry not found */ return NULL; }
void buzzdict_foreach(buzzdict_t dt, buzzdict_elem_funp fun, void* params) { /* Go through buckets */ uint32_t i, j; for(i = 0; i < dt->num_buckets; ++i) { /* Is the bucket used? */ if(dt->buckets[i] != NULL) { /* Go through elements in the bucket */ for(j = 0; j < buzzdarray_size(dt->buckets[i]); ++j) { const struct buzzdict_entry_s* e = &buzzdarray_get(dt->buckets[i], j, struct buzzdict_entry_s); fun(e->key, e->data, params); } } } }
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); }
int BuzzDebugPrint(buzzvm_t vm) { /* Get pointer to controller user data */ buzzvm_pushs(vm, buzzvm_string_register(vm, "controller", 1)); buzzvm_gload(vm); buzzvm_type_assert(vm, 1, BUZZTYPE_USERDATA); CBuzzController& cContr = *reinterpret_cast<CBuzzController*>(buzzvm_stack_at(vm, 1)->u.value); /* Fill message */ std::ostringstream oss; for(UInt32 i = 1; i < buzzdarray_size(vm->lsyms->syms); ++i) { buzzvm_lload(vm, i); buzzobj_t o = buzzvm_stack_at(vm, 1); buzzvm_pop(vm); switch(o->o.type) { case BUZZTYPE_NIL: oss << "[nil]"; break; case BUZZTYPE_INT: oss << o->i.value; break; case BUZZTYPE_FLOAT: oss << o->f.value; break; case BUZZTYPE_TABLE: oss << "[table with " << (buzzdict_size(o->t.value)) << " elems]"; break; case BUZZTYPE_CLOSURE: if(o->c.value.isnative) oss << "[n-closure @" << o->c.value.ref << "]"; else oss << "[c-closure @" << o->c.value.ref << "]"; break; case BUZZTYPE_STRING: oss << o->s.value.str; break; case BUZZTYPE_USERDATA: oss << "[userdata @" << o->u.value << "]"; break; default: break; } } cContr.GetARGoSDebugInfo().Msg = oss.str(); return buzzvm_ret0(vm); }
void buzzdict_destroy(buzzdict_t* dt) { /* Destroy buckets */ uint32_t i, j; for(i = 0; i < (*dt)->num_buckets; ++i) { /* Is the bucket used? */ if((*dt)->buckets[i] != NULL) { /* Destroy elements in the bucket */ for(j = 0; j < buzzdarray_size((*dt)->buckets[i]); ++j) { const struct buzzdict_entry_s* e = &buzzdarray_get((*dt)->buckets[i], j, struct buzzdict_entry_s); (*dt)->dstryf(e->key, e->data, *dt); } /* Destroy bucket */ buzzdarray_destroy(&((*dt)->buckets[i])); } } free((*dt)->buckets); /* Destroy the rest */ free(*dt); *dt = NULL; }
int BuzzLOG (buzzvm_t vm) { LOG << "BUZZ: "; for(UInt32 i = 1; i < buzzdarray_size(vm->lsyms->syms); ++i) { buzzvm_lload(vm, i); buzzobj_t o = buzzvm_stack_at(vm, 1); buzzvm_pop(vm); switch(o->o.type) { case BUZZTYPE_NIL: LOG << "[nil]"; break; case BUZZTYPE_INT: LOG << o->i.value; break; case BUZZTYPE_FLOAT: LOG << o->f.value; break; case BUZZTYPE_TABLE: LOG << "[table with " << (buzzdict_size(o->t.value)) << " elems]"; break; case BUZZTYPE_CLOSURE: if(o->c.value.isnative) LOG << "[n-closure @" << o->c.value.ref << "]"; else LOG << "[c-closure @" << o->c.value.ref << "]"; break; case BUZZTYPE_STRING: LOG << o->s.value.str; break; case BUZZTYPE_USERDATA: LOG << "[userdata @" << o->u.value << "]"; break; default: break; } } LOG << std::endl; LOG.Flush(); return buzzvm_ret0(vm); }
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; }
int print(buzzvm_t vm) { for(int i = 1; i < buzzdarray_size(vm->lsyms->syms); ++i) { buzzvm_lload(vm, i); buzzobj_t o = buzzvm_stack_at(vm, 1); buzzvm_pop(vm); switch(o->o.type) { case BUZZTYPE_NIL: fprintf(stdout, "[nil]"); break; case BUZZTYPE_INT: fprintf(stdout, "%d", o->i.value); break; case BUZZTYPE_FLOAT: fprintf(stdout, "%f", o->f.value); break; case BUZZTYPE_TABLE: fprintf(stdout, "[table with %d elems]", (buzzdict_size(o->t.value))); break; case BUZZTYPE_CLOSURE: if(o->c.value.isnative) fprintf(stdout, "[n-closure @%d]", o->c.value.ref); else fprintf(stdout, "[c-closure @%d]", o->c.value.ref); break; case BUZZTYPE_STRING: fprintf(stdout, "%s", o->s.value.str); break; case BUZZTYPE_USERDATA: fprintf(stdout, "[userdata @%p]", o->u.value); break; default: break; } } fprintf(stdout, "\n"); return buzzvm_ret0(vm); }
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); } }
buzztok_t buzzlex_nexttok(buzzlex_t lex) { buzzlex_file_t lexf = buzzlex_getfile(lex); do { /* Look for a non-space character */ do { /* Keep reading until you find a non-space character or end of stream */ while(lexf->cur_c < lexf->buf_size && buzzlex_isspace(lexf->buf[lexf->cur_c])) { nextchar(); } /* End of stream? */ if(lexf->cur_c >= lexf->buf_size) { /* Done with current file, go back to previous */ buzzdarray_pop(lex); if(buzzdarray_isempty(lex)) /* No file to go back to, done parsing */ return NULL; lexf = buzzlex_getfile(lex); } else /* Non-space character found */ break; } while(1); /* Non-space character found */ /* If the current character is a '#' ignore the rest of the line */ if(lexf->buf[lexf->cur_c] == '#') { do { nextchar(); } while(lexf->cur_c < lexf->buf_size && lexf->buf[lexf->cur_c] != '\n'); /* End of stream? */ if(lexf->cur_c >= lexf->buf_size) { /* Done with current file, go back to previous */ buzzdarray_pop(lex); if(buzzdarray_isempty(lex)) /* No file to go back to, done parsing */ return NULL; lexf = buzzlex_getfile(lex); } else { /* New line and carry on */ ++lexf->cur_line; lexf->cur_col = 0; ++lexf->cur_c; } } else if(strncmp(lexf->buf + lexf->cur_c, "include", 7) == 0) { /* Manage file inclusion */ lexf->cur_c += 7; lexf->cur_col += 7; /* Skip whitespace */ while(lexf->cur_c < lexf->buf_size && buzzlex_isspace(lexf->buf[lexf->cur_c])) { nextchar(); } /* End of file or not-string opening -> syntax error */ if(lexf->cur_c >= lexf->buf_size || !buzzlex_isquote(lexf->buf[lexf->cur_c])) { fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Syntax error: expected string after include\n", lexf->fname, lexf->cur_line, lexf->cur_col); return NULL; } /* Read string */ char quote = lexf->buf[lexf->cur_c]; size_t start = lexf->cur_c + 1; nextchar(); while(lexf->cur_c < lexf->buf_size && lexf->buf[lexf->cur_c] != quote && lexf->buf[lexf->cur_c] != '\n') { nextchar(); } /* End of file or newline -> syntax error */ if(lexf->cur_c >= lexf->buf_size || lexf->buf[lexf->cur_c] == '\n') { fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Syntax error: expected end of string\n", lexf->fname, lexf->cur_line, lexf->cur_col); return NULL; } /* Copy data into a new string */ char* fname = (char*)malloc(lexf->cur_c - start + 1); strncpy(fname, lexf->buf + start, lexf->cur_c - start); fname[lexf->cur_c - start] = '\0'; /* Get to next character in this file */ nextchar(); /* Create new file structure */ buzzlex_file_t f = buzzlex_file_new(fname); if(!f) { fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Can't read '%s'\n", lexf->fname, lexf->cur_line, lexf->cur_col, fname); free(fname); return NULL; } free(fname); /* Make sure the file hasn't been already included */ if(buzzdarray_find(lex, buzzlex_file_cmp, &f) < buzzdarray_size(lex)) { buzzlex_file_destroy(0, &f, NULL); } else { /* Push file structure */ buzzdarray_push(lex, &f); lexf = buzzlex_getfile(lex); } } else /* The character must be parsed */ break; } while(1); /* If we get here it's because we read potential token character */ uint64_t tokstart = lexf->cur_col - 1; char c = lexf->buf[lexf->cur_c]; nextchar(); /* Consider the 1-char non-alphanumeric cases first */ switch(c) { case '\n': { buzztok_t tok = buzzlex_newtok(BUZZTOK_STATEND, NULL, lexf->cur_line, tokstart, lexf->fname); ++lexf->cur_line; lexf->cur_col = 0; return tok; } casetokchar(';', BUZZTOK_STATEND); casetokchar('{', BUZZTOK_BLOCKOPEN); casetokchar('}', BUZZTOK_BLOCKCLOSE); casetokchar('(', BUZZTOK_PAROPEN); casetokchar(')', BUZZTOK_PARCLOSE); casetokchar('[', BUZZTOK_IDXOPEN); casetokchar(']', BUZZTOK_IDXCLOSE); casetokchar(',', BUZZTOK_LISTSEP); casetokchar('.', BUZZTOK_DOT); } /* If we get here, it's because we found either a constant, an * identifier, a keyword, an assignment, a comparison operator, * an arithmetic operator, or an unexpected character */ if(isdigit(c)) { /* It's a constant */ readval(buzzlex_isnumber); return buzzlex_newtok(BUZZTOK_CONST, val, lexf->cur_line, tokstart, lexf->fname); } else if(isalpha(c)) { /* It's either a keyword or an identifier */ readval(buzzlex_isid); /* Go through the possible keywords */ checkkeyword("var", BUZZTOK_VAR); checkkeyword("if", BUZZTOK_IF); checkkeyword("else", BUZZTOK_ELSE); checkkeyword("function", BUZZTOK_FUN); checkkeyword("return", BUZZTOK_RETURN); checkkeyword("for", BUZZTOK_FOR); checkkeyword("while", BUZZTOK_WHILE); checkkeyword("and", BUZZTOK_ANDOR); checkkeyword("or", BUZZTOK_ANDOR); checkkeyword("not", BUZZTOK_NOT); checkkeyword("nil", BUZZTOK_NIL); /* No keyword found, consider it an id */ return buzzlex_newtok(BUZZTOK_ID, val, lexf->cur_line, tokstart, lexf->fname); } else if(c == '=') { /* Either an assignment or a comparison */ if(lexf->cur_c < lexf->buf_size && lexf->buf[lexf->cur_c] == '=') { /* It's a comparison */ nextchar(); return buzzlex_newtok(BUZZTOK_CMP, strdup("=="), lexf->cur_line, tokstart, lexf->fname); } else { /* It's an assignment */ return buzzlex_newtok(BUZZTOK_ASSIGN, NULL, lexf->cur_line, tokstart, lexf->fname); } } else if(c == '!') { /* Comparison operator? */ if(lexf->cur_c < lexf->buf_size && lexf->buf[lexf->cur_c] == '=') { /* It's a comparison */ nextchar(); return buzzlex_newtok(BUZZTOK_CMP, strdup("!="), lexf->cur_line, tokstart, lexf->fname); } else { /* Syntax error */ fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Syntax error: expected '=' after '!'\n", lexf->fname, lexf->cur_line, tokstart); return NULL; } } else if((c == '<') || (c == '>')) { /* It's a comparison operator */ size_t start = lexf->cur_c - 1; /* Include the '=' if present */ if(lexf->cur_c < lexf->buf_size && lexf->buf[lexf->cur_c] == '=') { nextchar(); } char* val = (char*)malloc(lexf->cur_c - start + 1); strncpy(val, lexf->buf + start, lexf->cur_c - start); val[lexf->cur_c - start] = 0; return buzzlex_newtok(BUZZTOK_CMP, val, lexf->cur_line, tokstart, lexf->fname); } else if(buzzlex_isarith(c)) { /* Arithmetic operator */ char* val = (char*)malloc(2); strncpy(val, lexf->buf + lexf->cur_c - 1, 1); val[1] = 0; switch(c) { case '+': case '-': { return buzzlex_newtok(BUZZTOK_ADDSUB, val, lexf->cur_line, tokstart, lexf->fname); } case '*': case '/': { return buzzlex_newtok(BUZZTOK_MULDIV, val, lexf->cur_line, tokstart, lexf->fname); } case '%': { return buzzlex_newtok(BUZZTOK_MOD, val, lexf->cur_line, tokstart, lexf->fname); } case '^': { return buzzlex_newtok(BUZZTOK_POW, val, lexf->cur_line, tokstart, lexf->fname); } default: return NULL; } } else if(buzzlex_isquote(c)) { /* String - eat any character until you find the next matching quote */ size_t start = lexf->cur_c; char last1 = 0, last2 = 0; while(lexf->cur_c < lexf->buf_size && /* Not end of stream */ ((lexf->buf[lexf->cur_c] != c) || /* Matching quote not found */ (lexf->buf[lexf->cur_c] == c && /* Matching quote found, but preceded by \ and not \\ */ last1 == '\\' && last2 != '\\'))) { /* Remember the last two characters read */ last2 = last1; last1 = lexf->buf[lexf->cur_c]; /* Keep parsing the string */ if(lexf->buf[lexf->cur_c] != '\n') { nextchar(); } else { fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Syntax error: string closing quote not found\n", lexf->fname, lexf->cur_line, tokstart); return NULL; } } /* End of stream? Syntax error */ if(lexf->cur_c >= lexf->buf_size) { fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Syntax error: string closing quote not found\n", lexf->fname, lexf->cur_line, tokstart); return NULL; } /* We have a valid string */ char* val = buzzlex_newstring(lexf->buf + start, lexf->cur_c - start); nextchar(); return buzzlex_newtok(BUZZTOK_STRING, val, lexf->cur_line, tokstart, lexf->fname); } else { /* Unknown character */ fprintf(stderr, "%s:%" PRIu64 ":%" PRIu64 ": Syntax error: unknown character '%c' (octal: %o; hex: %x)\n", lexf->fname, lexf->cur_line, tokstart, c, c, c); return NULL; } }