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; }
int main(int argc, char** argv) { /* Parse command line */ if(argc != 2) { fprintf(stderr, "Usage:\n\t%s <file.bo>\n\n", argv[0]); return 0; } /* Open file */ int fd = open(argv[1], O_RDONLY); if(fd < 0) perror(argv[1]); /* Read data */ size_t bcode_size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); uint8_t* bcode_buf = (uint8_t*)malloc(bcode_size); ssize_t rd; size_t tot = 0; while(tot < bcode_size) { rd = read(fd, bcode_buf + tot, bcode_size - tot); if(rd < 0) perror(argv[1]); tot += rd; } close(fd); /* Create new VM */ buzzvm_t vm = buzzvm_new(1); /* Set byte code */ buzzvm_set_bcode(vm, bcode_buf, bcode_size); /* Register hook function */ buzzvm_pushs(vm, buzzvm_string_register(vm, "hook")); buzzvm_pushcc(vm, buzzvm_function_register(vm, hook)); buzzvm_gstore(vm); /* Run byte code and dump state */ do dump(vm); while(buzzvm_step(vm) == BUZZVM_STATE_READY); if(vm->state == BUZZVM_STATE_DONE) { dump(vm); fprintf(stdout, "%s: execution terminated correctly\n\n", argv[1]); } else { fprintf(stderr, "%s: execution terminated abnormally: %s\n\n", argv[1], buzzvm_error_desc[vm->error]); } /* Destroy VM */ free(bcode_buf); buzzvm_destroy(&vm); return 0; }
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_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 main(int argc, char** argv) { /* The bytecode filename */ char* bcfname; /* The debugging information file name */ char* dbgfname; /* Whether or not to show the assembly information */ int trace = 0; /* Parse command line */ if(argc < 3 || argc > 4) usage(argv[0], 0); if(argc == 3) { bcfname = argv[1]; dbgfname = argv[2]; } else { bcfname = argv[2]; dbgfname = argv[3]; if(strcmp(argv[1], "--trace") != 0) { fprintf(stderr, "error: %s: unrecognized option '%s'\n", argv[0], argv[1]); usage(argv[0], 1); } trace = 1; } /* Read bytecode and fill in data structure */ FILE* fd = fopen(bcfname, "rb"); if(!fd) perror(bcfname); fseek(fd, 0, SEEK_END); size_t bcode_size = ftell(fd); rewind(fd); uint8_t* bcode_buf = (uint8_t*)malloc(bcode_size); if(fread(bcode_buf, 1, bcode_size, fd) < bcode_size) { perror(bcfname); } fclose(fd); /* Read debug information */ buzzdebug_t dbg_buf = buzzdebug_new(); if(!buzzdebug_fromfile(dbg_buf, dbgfname)) { perror(dbgfname); } /* Create new VM */ buzzvm_t vm = buzzvm_new(1); /* Set byte code */ buzzvm_set_bcode(vm, bcode_buf, bcode_size); /* Register hook functions */ buzzvm_pushs(vm, buzzvm_string_register(vm, "print", 1)); buzzvm_pushcc(vm, buzzvm_function_register(vm, print)); buzzvm_gstore(vm); /* Run byte code */ do if(trace) buzzdebug_stack_dump(vm, 1, stdout); while(buzzvm_step(vm) == BUZZVM_STATE_READY); /* Done running, check final state */ int retval; if(vm->state == BUZZVM_STATE_DONE) { /* Execution terminated without errors */ if(trace) buzzdebug_stack_dump(vm, 1, stdout); fprintf(stdout, "%s: execution terminated correctly\n\n", bcfname); retval = 0; } else { /* Execution terminated with errors */ if(trace) buzzdebug_stack_dump(vm, 1, stdout); buzzdebug_entry_t dbg = *buzzdebug_info_get_fromoffset(dbg_buf, &vm->pc); if(dbg != NULL) { fprintf(stderr, "%s: execution terminated abnormally at %s:%" PRIu64 ":%" PRIu64 " : %s\n\n", bcfname, dbg->fname, dbg->line, dbg->col, vm->errormsg); } else { fprintf(stderr, "%s: execution terminated abnormally at bytecode offset %d: %s\n\n", bcfname, vm->pc, vm->errormsg); } retval = 1; } /* Destroy VM */ free(bcode_buf); buzzdebug_destroy(&dbg_buf); buzzvm_destroy(&vm); /* All done */ return retval; }
buzzvm_state buzzvm_execute_script(buzzvm_t vm) { while(buzzvm_step(vm) == BUZZVM_STATE_READY); return vm->state; }