Open xgroleau opened 3 years ago
We are looking into this issue and the other related one. Thank you for reporting it.
The reason why the onconflict function doesn't work for your test case is because you are registering some C functions (using bbzvm_register_functions) without providing a .bst file which would let the compiler know that there will be additional functions added to the VM during runtime.
This causes the compiler to register the function with the string id which is now taken by one of the C functions. It only happens when using named functions because registering C functions happens before the first execution of the script which registers the named functions.
Providing .bst file allows the compiler to preallocate the string id for the C functions. Otherwise, there would be no way for the compiler to know that we wanna register C functions.
Thanks a lot! I should have provided you this info at the beginning. I understand the problem though, the ID was already assigned to a C function since it was not in the BST file. Copy and paste error on my part from the vm_onconflict
test.
There is something else, maybe it's linked with the memory leak but I'm not sure yet, I'm still investigating: When I access a stigmergy variable, the value return is not the data. I've had this error multiple times during usage and not just testing, I wasn't able to recreate it until now.
Here is the code C:
TEST(vm_onconflict_named_function) {
// Init VM
vm = &vmObj;
uint16_t robot = 0;
bbzvm_construct(robot);
bbzvm_set_error_receiver(&set_last_error);
fbcode = fopen(FILE_TEST6, "rb");
REQUIRE(fbcode != NULL);
REQUIRE(fseek(fbcode, 0, SEEK_END) == 0);
fsize = ftell(fbcode);
REQUIRE(fsize > 0);
REQUIRE(fseek(fbcode, 0, SEEK_SET) >= 0);
bbzvm_set_bcode(&testBcode, fsize);
REQUIRE(vm->state == BBZVM_STATE_READY);
REQUIRE(bbzvm_register_functions() >= 0); // If this fails, it means that the heap doesn't have enough memory allocated to execute this test.
// Stepping through script
while (vm->state == BBZVM_STATE_READY) {
#ifdef DEBUG
uint8_t instr = *vm->bcode_fetch_fun(vm->pc,1);
if (instr > BBZVM_INSTR_CALLS) {
printf("[%d: %s %d]\n", vm->pc, instr_desc[instr], *(int16_t*)vm->bcode_fetch_fun(vm->pc+1,2));
}
else {
printf("[%d: %s]\n", vm->pc, instr_desc[instr]);
}
#endif
bbzvm_step();
ASSERT(vm->state != BBZVM_STATE_ERROR);
}
ASSERT_EQUAL(vm->state, BBZVM_STATE_DONE);
ASSERT_EQUAL(vm->error, BBZVM_ERROR_NONE);
vm->state = BBZVM_STATE_READY;
// Sending stigmergy message, loop twice, once for inserting in stig, other for conflict to be called
for(uint8_t i=0; i<2; i++) {
bbzmsg_payload_t payload;
uint8_t buff[] = {1, i, 0, __BBZSTRID_count 0, 57, 2, 0, 1};
bbzringbuf_construct(&payload, buff, 1, 16);
payload.elsize = 1;
payload.capacity = 10;
payload.datastart = 0;
payload.dataend = 9;
bbzinmsg_queue_append(&payload);
bbzvm_process_inmsgs();
if(vm->error == BBZVM_ERROR_MEM){
break;
}
// Calling the step function
bbzvm_pushs(__BBZSTRID_step);
bbzheap_idx_t l = bbzvm_stack_at(0);
bbzvm_pop();
if (bbztable_get(vm->gsyms, l, &l) == 1) {
bbzvm_pushnil(); // Push self table
bbzvm_push(l);
bbzvm_closure_call(0);
bbzvm_pop();
}
// End of calling the step function
bbzvm_gc();
}
ASSERT_EQUAL(vm->state, BBZVM_STATE_READY);
ASSERT_EQUAL(vm->error, BBZVM_ERROR_NONE);
bbzvm_destruct();
fclose(fbcode);
}
Here is the bzz file
function conflict_resolver(key, ld, rd) {
print(ld);
return ld
}
stig = stigmergy.create(0);
stig.onconflict(conflict_resolver)
function step() {
var val = stig.get("count");
print(val);
}
will provide more information after some more investigation. And here is the bst
id
swarm
create
select
init
step
reset
destroy
join
unselect
leave
in
exec
intersection
union
difference
others
neighbors
foreach
map
reduce
distance
azimuth
elevation
count
kin
nonkin
data
filter
broadcast
listen
ignore
stigmergy
put
get
size
onconflict
onconflictlost
robot
timestamp
pos
x
y
orientation
__INTERNAL_1_DO_NOT_USE__
__INTERNAL_2_DO_NOT_USE__
print
forward
stop
turn
Here is the console output
[17: PUSHS 51]
[20: PUSHS 32]
[23: GLOAD]
[24: DUP]
[25: PUSHS 2]
[28: TGET]
[29: PUSHI 0]
[32: PUSHI 1]
[35: CALLC]
[36: GSTORE]
[37: PUSHS 51]
[40: GLOAD]
[41: DUP]
[42: PUSHS 36]
[45: TGET]
[46: PUSHS 50]
[49: GLOAD]
[50: PUSHI 1]
[53: CALLC]
[54: POP]
[55: DONE]
2 <-- first step call at line 11
[t:3]14 <-- on conflict call, line 2
[s]27 <-- on second step call, line 11, the data is actually a string, which is the key. The data seems to be replace by the key
I'm not sure how this is happening though. The change of the metadata is when bbzvm_process_inmsgs
is called for the second time. So the value becomes the key (data has an strid of 27), which causes problems when using the stigmergy
onconflict resolution only seems to work with lambdas, when it's a named function and the conflict is called the vm gets a BBZVM_ERROR_RET error.
Here is the code to tests
When it uses a lambda, the tests passes (though it leaks memory as stated here)
But when it uses a function name, the test fails:
The closure is registered properly with bbzvstig_onconflict, but when the closure is called, the blockptr doesn't seem to change. It call as a c function instead of changing the pc and execute buzz code since it's not a native closure which would explain the blockptr not increasing. In my case it calls bbzvm_dummy c function instead of conflict_resolver, though that may be undefined behavior.