diff --git a/.gitmodules b/.gitmodules index 9a9b342f..085016aa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,10 +3,4 @@ url = https://github.com/fastvm/minivm-tree-sitter [submodule "vendor/isocline"] path = vendor/isocline - url = https://github.com/fastvm/minivm-isocline -[submodule "vendor/raylib"] - path = vendor/raylib - url = https://github.com/FastVM/minivm-raylib -[submodule "vendor/mimalloc"] - path = vendor/mimalloc - url = https://github.com/shawsumma/mimalloc + url = https://github.com/fastvm/minivm-isocline \ No newline at end of file diff --git a/main/minivm.c b/main/minivm.c index 1f731f29..54d6dc14 100644 --- a/main/minivm.c +++ b/main/minivm.c @@ -78,7 +78,7 @@ __attribute__((no_instrument_function)) int main(int argc, char **argv) { } if (echo) { vm_io_buffer_t buf = {0}; - vm_io_debug(&buf, 0, "", value, NULL); + vm_io_buffer_obj_debug(&buf, 0, "", value, NULL); printf("%.*s", (int)buf.len, buf.buf); } diff --git a/vendor/mimalloc b/vendor/mimalloc deleted file mode 160000 index dccc8545..00000000 --- a/vendor/mimalloc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dccc8545a8b5c9da44cf764ee3237aed99c883da diff --git a/vendor/raylib b/vendor/raylib deleted file mode 160000 index b4fbdc02..00000000 --- a/vendor/raylib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b4fbdc028302f9a697f196e8d02a7dca28912f59 diff --git a/vm/ast/comp.c b/vm/ast/comp.c index a1a11b01..5499483f 100644 --- a/vm/ast/comp.c +++ b/vm/ast/comp.c @@ -43,16 +43,6 @@ struct vm_ast_comp_names_t { vm_ast_comp_names_t *next; }; -void vm_lua_comp_op_std_pow(vm_t *vm, vm_obj_t *args) { - vm_obj_t *ret = args; - double v = vm_obj_get_number(*args++); - while (!vm_obj_is_empty(args[0])) { - v = pow(v, vm_obj_get_number(*args++)); - } - *ret = vm_obj_of_number(v); - return; -} - static void vm_ast_comp_names_push(vm_ast_comp_t *comp) { vm_ast_comp_names_t *names = vm_malloc(sizeof(vm_ast_comp_names_t)); *names = (vm_ast_comp_names_t){ @@ -107,8 +97,8 @@ static vm_ir_arg_t vm_ast_comp_br_raw(vm_ast_comp_t *comp, vm_ast_node_t node, v ret; \ }) -extern void vm_std_vm_closure(vm_t *vm, vm_obj_t *args); -extern void vm_std_vm_concat(vm_t *vm, vm_obj_t *args); +extern void vm_std_vm_closure(vm_t *vm, size_t nargs, vm_obj_t *args); +extern void vm_std_vm_concat(vm_t *vm, size_t nargs, vm_obj_t *args); static vm_ir_arg_t *vm_ast_args(size_t nargs, ...) { va_list ap; @@ -586,7 +576,7 @@ static vm_ir_arg_t vm_ast_comp_to_raw(vm_ast_comp_t *comp, vm_ast_node_t node) { vm_ast_free_node(node); vm_ir_arg_t key_arg = (vm_ir_arg_t){ .type = VM_IR_ARG_TYPE_LIT, - .lit = vm_str(comp->vm, target.value.ident), + .lit = vm_obj_of_string(comp->vm, target.value.ident), }; vm_ast_blocks_instr( comp, @@ -710,72 +700,14 @@ static vm_ir_arg_t vm_ast_comp_to_raw(vm_ast_comp_t *comp, vm_ast_node_t node) { comp->cur = next; return out; } - case VM_AST_FORM_CONCAT: { - vm_ir_arg_t arg1 = vm_ast_comp_to_rec(comp, form.args[0]); - vm_ir_arg_t arg2 = vm_ast_comp_to_rec(comp, form.args[1]); - vm_ir_block_t *with_result = vm_ast_comp_new_block(comp); - - vm_ir_arg_t *call_args = vm_malloc(sizeof(vm_ir_arg_t) * 4); - call_args[0] = (vm_ir_arg_t){ - .type = VM_IR_ARG_TYPE_LIT, - .lit = vm_obj_of_ffi(&vm_std_vm_concat), - }; - call_args[1] = arg1; - call_args[2] = arg2; - call_args[3] = (vm_ir_arg_t){ - .type = VM_IR_ARG_TYPE_NONE, - }; - vm_ir_arg_t out = vm_ast_comp_reg(comp); - - vm_ast_blocks_branch( - comp, - (vm_ir_branch_t){ - .op = VM_IR_BRANCH_OPCODE_CALL, - .out = out, - .args = call_args, - .targets[0] = with_result, - } - ); - - comp->cur = with_result; - return out; - } - case VM_AST_FORM_POW: { - vm_ir_arg_t arg1 = vm_ast_comp_to_rec(comp, form.args[0]); - vm_ir_arg_t arg2 = vm_ast_comp_to_rec(comp, form.args[1]); - vm_ir_block_t *with_result = vm_ast_comp_new_block(comp); - - vm_ir_arg_t *call_args = vm_malloc(sizeof(vm_ir_arg_t) * 4); - call_args[0] = (vm_ir_arg_t){ - .type = VM_IR_ARG_TYPE_LIT, - .lit = vm_obj_of_ffi(&vm_lua_comp_op_std_pow), - }; - call_args[1] = arg1; - call_args[2] = arg2; - call_args[3] = (vm_ir_arg_t){ - .type = VM_IR_ARG_TYPE_NONE, - }; - vm_ir_arg_t out = vm_ast_comp_reg(comp); - - vm_ast_blocks_branch( - comp, - (vm_ir_branch_t){ - .op = VM_IR_BRANCH_OPCODE_CALL, - .out = out, - .args = call_args, - .targets[0] = with_result, - } - ); - - comp->cur = with_result; - return out; - } case VM_AST_FORM_ADD: case VM_AST_FORM_SUB: case VM_AST_FORM_MUL: case VM_AST_FORM_DIV: case VM_AST_FORM_IDIV: - case VM_AST_FORM_MOD: { + case VM_AST_FORM_MOD: + case VM_AST_FORM_POW: + case VM_AST_FORM_CONCAT: { vm_ir_arg_t arg1 = vm_ast_comp_to_rec(comp, form.args[0]); vm_ir_arg_t arg2 = vm_ast_comp_to_rec(comp, form.args[1]); vm_ir_arg_t out = vm_ast_comp_reg(comp); @@ -805,6 +737,14 @@ static vm_ir_arg_t vm_ast_comp_to_raw(vm_ast_comp_t *comp, vm_ast_node_t node) { op = VM_IR_INSTR_OPCODE_MOD; break; } + case VM_AST_FORM_POW: { + op = VM_IR_INSTR_OPCODE_POW; + break; + } + case VM_AST_FORM_CONCAT: { + op = VM_AST_FORM_CONCAT; + break; + } } vm_ast_blocks_instr( comp, @@ -1034,7 +974,7 @@ static vm_ir_arg_t vm_ast_comp_to_raw(vm_ast_comp_t *comp, vm_ast_node_t node) { if (got.type != VM_IR_ARG_TYPE_NONE) { vm_ir_arg_t env_key = (vm_ir_arg_t){ .type = VM_IR_ARG_TYPE_LIT, - .lit = vm_str(comp->vm, lit), + .lit = vm_obj_of_string(comp->vm, lit), }; vm_ir_arg_t out = vm_ast_comp_reg(comp); vm_ir_block_t *next = vm_ast_comp_new_block(comp); diff --git a/vm/ast/print.c b/vm/ast/print.c index 7d976776..9c2f3ffc 100644 --- a/vm/ast/print.c +++ b/vm/ast/print.c @@ -158,7 +158,7 @@ void vm_ast_print_node(vm_io_buffer_t *out, size_t indent, const char *prefix, v break; } case VM_AST_NODE_LITERAL: { - vm_io_debug(out, indent, prefix, node.value.literal, NULL); + vm_io_buffer_obj_debug(out, indent, prefix, node.value.literal, NULL); break; } } diff --git a/vm/backend/backend.c b/vm/backend/backend.c index 134b7bfa..e92a7640 100644 --- a/vm/backend/backend.c +++ b/vm/backend/backend.c @@ -80,6 +80,14 @@ enum { VM_OP_MOD_IR, VM_OP_MOD_RR, + VM_OP_POW_RI, + VM_OP_POW_IR, + VM_OP_POW_RR, + + VM_OP_CONCAT_RI, + VM_OP_CONCAT_IR, + VM_OP_CONCAT_RR, + VM_OP_JUMP, VM_OP_BB_R, @@ -197,6 +205,27 @@ static VM_INLINE vm_obj_t vm_interp_mod(vm_obj_t v1, vm_obj_t v2) { } } +static VM_INLINE vm_obj_t vm_interp_pow(vm_obj_t v1, vm_obj_t v2) { + if (vm_obj_is_number(v1) && vm_obj_is_number(v2)) { + return vm_obj_of_number(pow(vm_obj_get_number(v1), vm_obj_get_number(v2))); + } else { + return vm_obj_of_error(vm_error_from_msg(vm_location_range_unknown, "bad modulo")); + } +} + +static VM_INLINE vm_obj_t vm_interp_concat(vm_t *vm, vm_obj_t v1, vm_obj_t v2) { + if (vm_obj_is_string(v1) && vm_obj_is_string(v2)) { + vm_io_buffer_t *buf = vm_io_buffer_new(); + vm_io_buffer_object_tostring(buf, v1); + vm_io_buffer_object_tostring(buf, v2); + vm_obj_t ret = vm_obj_of_buffer(buf); + vm_gc_add(vm, ret); + return ret; + } else { + return vm_obj_of_error(vm_error_from_msg(vm_location_range_unknown, "bad modulo")); + } +} + #if VM_UNALIGNED #define vm_interp_push_num(size_) ({ \ size_t size = (size_); \ @@ -415,6 +444,62 @@ void *vm_interp_renumber_block(vm_t *vm, void **ptrs, vm_ir_block_t *block) { } break; } + case VM_IR_INSTR_OPCODE_POW: { + if (instr.args[0].type == VM_IR_ARG_TYPE_LIT && instr.args[1].type == VM_IR_ARG_TYPE_LIT) { + vm_obj_t v1 = instr.args[0].lit; + vm_obj_t v2 = instr.args[1].lit; + vm_obj_t v3 = vm_interp_pow(v1, v2); + vm_interp_push_op(VM_OP_MOVE_I); + vm_interp_push(vm_obj_t, v3); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else if (instr.args[0].type == VM_IR_ARG_TYPE_REG && instr.args[1].type == VM_IR_ARG_TYPE_LIT) { + vm_interp_push_op(VM_OP_POW_RI); + vm_interp_push(vm_interp_reg_t, instr.args[0].reg); + vm_interp_push(vm_obj_t, instr.args[1].lit); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else if (instr.args[0].type == VM_IR_ARG_TYPE_LIT && instr.args[1].type == VM_IR_ARG_TYPE_REG) { + vm_interp_push_op(VM_OP_POW_IR); + vm_interp_push(vm_obj_t, instr.args[0].lit); + vm_interp_push(vm_interp_reg_t, instr.args[1].reg); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else if (instr.args[0].type == VM_IR_ARG_TYPE_REG && instr.args[1].type == VM_IR_ARG_TYPE_REG) { + vm_interp_push_op(VM_OP_POW_RR); + vm_interp_push(vm_interp_reg_t, instr.args[0].reg); + vm_interp_push(vm_interp_reg_t, instr.args[1].reg); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else { + __builtin_trap(); + } + break; + } + case VM_IR_INSTR_OPCODE_CONCAT: { + if (instr.args[0].type == VM_IR_ARG_TYPE_LIT && instr.args[1].type == VM_IR_ARG_TYPE_LIT) { + vm_obj_t v1 = instr.args[0].lit; + vm_obj_t v2 = instr.args[1].lit; + vm_obj_t v3 = vm_interp_concat(vm, v1, v2); + vm_interp_push_op(VM_OP_MOVE_I); + vm_interp_push(vm_obj_t, v3); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else if (instr.args[0].type == VM_IR_ARG_TYPE_REG && instr.args[1].type == VM_IR_ARG_TYPE_LIT) { + vm_interp_push_op(VM_OP_CONCAT_RI); + vm_interp_push(vm_interp_reg_t, instr.args[0].reg); + vm_interp_push(vm_obj_t, instr.args[1].lit); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else if (instr.args[0].type == VM_IR_ARG_TYPE_LIT && instr.args[1].type == VM_IR_ARG_TYPE_REG) { + vm_interp_push_op(VM_OP_CONCAT_IR); + vm_interp_push(vm_obj_t, instr.args[0].lit); + vm_interp_push(vm_interp_reg_t, instr.args[1].reg); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else if (instr.args[0].type == VM_IR_ARG_TYPE_REG && instr.args[1].type == VM_IR_ARG_TYPE_REG) { + vm_interp_push_op(VM_OP_CONCAT_RR); + vm_interp_push(vm_interp_reg_t, instr.args[0].reg); + vm_interp_push(vm_interp_reg_t, instr.args[1].reg); + vm_interp_push(vm_interp_reg_t, instr.out.reg); + } else { + __builtin_trap(); + } + break; + } case VM_IR_INSTR_OPCODE_TABLE_SET: { vm_interp_push_op(VM_OP_TABLE_SET); for (size_t i = 0; i < 3; i++) { @@ -731,6 +816,12 @@ vm_obj_t vm_run_repl_inner(vm_t *vm, vm_ir_block_t *block) { [VM_OP_MOD_RI] = &&VM_OP_MOD_RI, [VM_OP_MOD_IR] = &&VM_OP_MOD_IR, [VM_OP_MOD_RR] = &&VM_OP_MOD_RR, + [VM_OP_POW_RI] = &&VM_OP_POW_RI, + [VM_OP_POW_IR] = &&VM_OP_POW_IR, + [VM_OP_POW_RR] = &&VM_OP_POW_RR, + [VM_OP_CONCAT_RI] = &&VM_OP_CONCAT_RI, + [VM_OP_CONCAT_IR] = &&VM_OP_CONCAT_IR, + [VM_OP_CONCAT_RR] = &&VM_OP_CONCAT_RR, [VM_OP_JUMP] = &&VM_OP_JUMP, [VM_OP_BB_R] = &&VM_OP_BB_R, [VM_OP_BLT_RI] = &&VM_OP_BLT_RI, @@ -1013,6 +1104,72 @@ VM_OP_MOD_RR:; vm_run_repl_out(v3); vm_run_repl_jump(); } +VM_OP_POW_RI:; + VM_OPCODE_DEBUG(mod_ri) { + vm_obj_t v1 = vm_run_repl_reg(); + vm_obj_t v2 = vm_run_repl_lit(); + vm_obj_t v3 = vm_interp_pow(v1, v2); + if (vm_obj_is_error(v3)) { + vm_backend_return(vm_obj_of_error(vm_error_from_error(block->range, vm_obj_get_error(v3)))); + } + vm_run_repl_out(v3); + vm_run_repl_jump(); + } +VM_OP_POW_IR:; + VM_OPCODE_DEBUG(mod_ir) { + vm_obj_t v1 = vm_run_repl_lit(); + vm_obj_t v2 = vm_run_repl_reg(); + vm_obj_t v3 = vm_interp_pow(v1, v2); + if (vm_obj_is_error(v3)) { + vm_backend_return(vm_obj_of_error(vm_error_from_error(block->range, vm_obj_get_error(v3)))); + } + vm_run_repl_out(v3); + vm_run_repl_jump(); + } +VM_OP_POW_RR:; + VM_OPCODE_DEBUG(mod_rr) { + vm_obj_t v1 = vm_run_repl_reg(); + vm_obj_t v2 = vm_run_repl_reg(); + vm_obj_t v3 = vm_interp_pow(v1, v2); + if (vm_obj_is_error(v3)) { + vm_backend_return(vm_obj_of_error(vm_error_from_error(block->range, vm_obj_get_error(v3)))); + } + vm_run_repl_out(v3); + vm_run_repl_jump(); + } +VM_OP_CONCAT_RI:; + VM_OPCODE_DEBUG(mod_ri) { + vm_obj_t v1 = vm_run_repl_reg(); + vm_obj_t v2 = vm_run_repl_lit(); + vm_obj_t v3 = vm_interp_concat(vm, v1, v2); + if (vm_obj_is_error(v3)) { + vm_backend_return(vm_obj_of_error(vm_error_from_error(block->range, vm_obj_get_error(v3)))); + } + vm_run_repl_out(v3); + vm_run_repl_jump(); + } +VM_OP_CONCAT_IR:; + VM_OPCODE_DEBUG(mod_ir) { + vm_obj_t v1 = vm_run_repl_lit(); + vm_obj_t v2 = vm_run_repl_reg(); + vm_obj_t v3 = vm_interp_concat(vm, v1, v2); + if (vm_obj_is_error(v3)) { + vm_backend_return(vm_obj_of_error(vm_error_from_error(block->range, vm_obj_get_error(v3)))); + } + vm_run_repl_out(v3); + vm_run_repl_jump(); + } +VM_OP_CONCAT_RR:; + VM_OPCODE_DEBUG(mod_rr) { + vm_obj_t v1 = vm_run_repl_reg(); + vm_obj_t v2 = vm_run_repl_reg(); + vm_obj_t v3 = vm_interp_concat(vm, v1, v2); + if (vm_obj_is_error(v3)) { + vm_backend_return(vm_obj_of_error(vm_error_from_error(block->range, vm_obj_get_error(v3)))); + } + vm_run_repl_out(v3); + vm_run_repl_jump(); + } VM_OP_JUMP:; VM_OPCODE_DEBUG(jump) { block = vm_run_repl_read(vm_ir_block_t *); @@ -1197,7 +1354,7 @@ VM_OP_CALL:; } } call_closure_end:; - next_regs[j] = vm_obj_of_empty(); + next_regs[j] = vm_obj_of_nil(); vm_obj_t *last_regs = regs; vm->regs = next_regs; vm_obj_t got = vm_run_repl_inner(vm, vm_obj_get_closure(v1)->block); @@ -1229,10 +1386,9 @@ VM_OP_CALL:; } } call_ffi_end:; - next_regs[j] = vm_obj_of_empty(); vm_obj_t *last_regs = regs; vm->regs = next_regs; - vm_obj_get_ffi(v1)(vm, next_regs); + vm_obj_get_ffi(v1)(vm, j, next_regs); vm->regs = last_regs; vm_obj_t got = next_regs[0]; if (vm_obj_is_error(got)) { diff --git a/vm/errors.h b/vm/errors.h index 80d845c1..9320fdba 100644 --- a/vm/errors.h +++ b/vm/errors.h @@ -6,11 +6,9 @@ struct vm_location_t; struct vm_location_range_t; -struct vm_error_t; typedef struct vm_location_t vm_location_t; typedef struct vm_location_range_t vm_location_range_t; -typedef struct vm_error_t vm_error_t; struct vm_location_t { size_t byte; diff --git a/vm/io.c b/vm/io.c index 295fc73c..5d280cf8 100644 --- a/vm/io.c +++ b/vm/io.c @@ -93,7 +93,7 @@ static void vm_io_indent(vm_io_buffer_t *out, size_t indent, const char *prefix) vm_io_buffer_format(out, "%s", prefix); } -void vm_io_print_lit(vm_io_buffer_t *out, vm_obj_t value) { +void vm_io_buffer_print_lit(vm_io_buffer_t *out, vm_obj_t value) { if (vm_obj_is_nil(value)) { vm_io_buffer_format(out, "nil"); } @@ -111,7 +111,7 @@ void vm_io_print_lit(vm_io_buffer_t *out, vm_obj_t value) { } } -void vm_io_debug(vm_io_buffer_t *out, size_t indent, const char *prefix, vm_obj_t value, vm_io_debug_t *link) { +void vm_io_buffer_obj_debug(vm_io_buffer_t *out, size_t indent, const char *prefix, vm_obj_t value, vm_io_debug_t *link) { size_t up = 1; while (link != NULL) { if (vm_obj_eq(value, link->value)) { @@ -165,29 +165,29 @@ void vm_io_debug(vm_io_buffer_t *out, size_t indent, const char *prefix, vm_obj_ size_t len = vm_primes_table[tab->size]; for (size_t i = 0; i < len; i++) { vm_table_pair_t p = tab->pairs[i]; - if (vm_obj_is_empty(p.key) || vm_obj_is_nil(p.key)) { + if (vm_obj_is_nil(p.key)) { // no print for empty keys } else if (vm_obj_is_boolean(value)) { if (vm_obj_get_boolean(value)) { - vm_io_debug(out, indent + 1, "true = ", p.value, &next); + vm_io_buffer_obj_debug(out, indent + 1, "true = ", p.value, &next); } else { - vm_io_debug(out, indent + 1, "false = ", p.value, &next); + vm_io_buffer_obj_debug(out, indent + 1, "false = ", p.value, &next); } } else if (vm_obj_is_number(value)) { char buf[64]; snprintf(buf, 63, VM_FORMAT_FLOAT " = ", vm_obj_get_number(p.key)); - vm_io_debug(out, indent + 1, buf, p.value, &next); + vm_io_buffer_obj_debug(out, indent + 1, buf, p.value, &next); } else if (vm_obj_is_string(value)) { vm_io_buffer_t buf = {0}; vm_io_buffer_format(&buf, "%s = ", vm_obj_get_string(p.key)->buf); - vm_io_debug(out, indent + 1, buf.buf, p.value, &next); + vm_io_buffer_obj_debug(out, indent + 1, buf.buf, p.value, &next); vm_free(buf.buf); } else { vm_io_indent(out, indent + 1, ""); vm_io_buffer_format(out, "pair {\n"); - vm_io_debug(out, indent + 2, "key = ", p.key, &next); - vm_io_debug(out, indent + 2, "val = ", p.value, &next); + vm_io_buffer_obj_debug(out, indent + 2, "key = ", p.key, &next); + vm_io_buffer_obj_debug(out, indent + 2, "val = ", p.value, &next); vm_io_indent(out, indent + 1, ""); vm_io_buffer_format(out, "}\n"); } @@ -202,7 +202,7 @@ void vm_io_debug(vm_io_buffer_t *out, size_t indent, const char *prefix, vm_obj_ } } -void vm_obj_buffer_tostring(vm_io_buffer_t *buf, vm_obj_t value) { +void vm_io_buffer_object_tostring(vm_io_buffer_t *buf, vm_obj_t value) { if (vm_obj_is_nil(value)) { vm_io_buffer_format(buf, "nil"); } diff --git a/vm/io.h b/vm/io.h index 7224f647..9019d2d3 100644 --- a/vm/io.h +++ b/vm/io.h @@ -13,15 +13,15 @@ struct vm_io_debug_t { }; vm_io_buffer_t *vm_io_buffer_new(void); -char *vm_io_buffer_get(vm_io_buffer_t *buf); -void vm_io_print_lit(vm_io_buffer_t *out, vm_obj_t value); -void vm_io_debug(vm_io_buffer_t *out, size_t indent, const char *prefix, vm_obj_t value, vm_io_debug_t *link); +vm_io_buffer_t *vm_io_buffer_from_str(const char *str); + +char *vm_io_format(const char *fmt, ...); char *vm_io_read(const char *filename); -void vm_io_buffer_vformat(vm_io_buffer_t *buf, const char *fmt, va_list ap); -void vm_io_buffer_format(vm_io_buffer_t *buf, const char *fmt, ...); char *vm_io_vformat(const char *fmt, va_list ap); -char *vm_io_format(const char *fmt, ...); -void vm_obj_buffer_tostring(vm_io_buffer_t *buf, vm_obj_t value); -vm_io_buffer_t *vm_io_buffer_from_str(const char *str); +void vm_io_buffer_format(vm_io_buffer_t *buf, const char *fmt, ...); +void vm_io_buffer_obj_debug(vm_io_buffer_t *out, size_t indent, const char *prefix, vm_obj_t value, vm_io_debug_t *link); +void vm_io_buffer_object_tostring(vm_io_buffer_t *buf, vm_obj_t value); +void vm_io_buffer_print_lit(vm_io_buffer_t *out, vm_obj_t value); +void vm_io_buffer_vformat(vm_io_buffer_t *buf, const char *fmt, va_list ap); #endif diff --git a/vm/ir.c b/vm/ir.c index 1d5f1228..701befe7 100644 --- a/vm/ir.c +++ b/vm/ir.c @@ -14,7 +14,7 @@ void vm_block_realloc(vm_ir_block_t *block, vm_ir_instr_t instr) { void vm_io_format_arg(vm_io_buffer_t *out, vm_ir_arg_t val) { switch (val.type) { case VM_IR_ARG_TYPE_LIT: { - vm_io_print_lit(out, val.lit); + vm_io_buffer_print_lit(out, val.lit); break; } case VM_IR_ARG_TYPE_REG: { diff --git a/vm/ir.h b/vm/ir.h index 7111e731..88784e79 100644 --- a/vm/ir.h +++ b/vm/ir.h @@ -3,12 +3,10 @@ #define VM_HEADER_IR struct vm_ir_arg_t; -struct vm_ir_block_t; struct vm_ir_branch_t; struct vm_ir_instr_t; typedef struct vm_ir_arg_t vm_ir_arg_t; -typedef struct vm_ir_block_t vm_ir_block_t; typedef struct vm_ir_branch_t vm_ir_branch_t; typedef struct vm_ir_instr_t vm_ir_instr_t; @@ -48,6 +46,8 @@ enum { VM_IR_INSTR_OPCODE_DIV, VM_IR_INSTR_OPCODE_IDIV, VM_IR_INSTR_OPCODE_MOD, + VM_IR_INSTR_OPCODE_POW, + VM_IR_INSTR_OPCODE_CONCAT, VM_IR_INSTR_OPCODE_TABLE_SET, VM_IR_INSTR_OPCODE_TABLE_NEW, VM_IR_INSTR_OPCODE_TABLE_LEN, diff --git a/vm/lua/ast.c b/vm/lua/ast.c index 8759000e..31770be6 100644 --- a/vm/lua/ast.c +++ b/vm/lua/ast.c @@ -197,7 +197,7 @@ vm_ast_node_t vm_lang_lua_conv_raw(vm_lang_lua_t src, TSNode node) { return vm_ast_build_set( vm_ast_build_load( vm_lang_lua_conv(src, vm_ts_node_child_checked(target, 0)), - vm_ast_build_obj(vm_str(src.vm, vm_lang_lua_src(src, vm_ts_node_child_checked(target, 2)))) + vm_ast_build_obj(vm_obj_of_string(src.vm, vm_lang_lua_src(src, vm_ts_node_child_checked(target, 2)))) ), vm_ast_build_lambda( vm_ast_build_nil(), @@ -433,7 +433,7 @@ vm_ast_node_t vm_lang_lua_conv_raw(vm_lang_lua_t src, TSNode node) { if (ts_node_child_count(node) == 2) { char *ret = vm_malloc(sizeof(char) * 1); ret[0] = '\0'; - return vm_ast_build_obj(vm_str(src.vm, ret)); + return vm_ast_build_obj(vm_obj_of_string(src.vm, ret)); } TSNode content = vm_ts_node_child_checked(node, 1); char *val = vm_lang_lua_src(src, content); @@ -471,7 +471,7 @@ vm_ast_node_t vm_lang_lua_conv_raw(vm_lang_lua_t src, TSNode node) { } *buf++ = '\0'; vm_free(val_head); - return vm_ast_build_obj(vm_str(src.vm, ret)); + return vm_ast_build_obj(vm_obj_of_string(src.vm, ret)); } if (!strcmp(type, "number")) { const char *str = vm_lang_lua_src(src, node); @@ -487,7 +487,7 @@ vm_ast_node_t vm_lang_lua_conv_raw(vm_lang_lua_t src, TSNode node) { if (!strcmp(ts_node_type(func_node), "method_index_expression")) { const char *obj = vm_lang_lua_gensym(src); vm_ast_node_t set_obj = vm_ast_build_local(vm_ast_build_ident(obj), vm_lang_lua_conv(src, vm_ts_node_child_checked(func_node, 0))); - vm_ast_node_t index = vm_ast_build_obj(vm_str(src.vm, vm_lang_lua_src(src, vm_ts_node_child_checked(func_node, 2)))); + vm_ast_node_t index = vm_ast_build_obj(vm_obj_of_string(src.vm, vm_lang_lua_src(src, vm_ts_node_child_checked(func_node, 2)))); vm_ast_node_t func = vm_ast_build_load(vm_ast_build_ident(vm_strdup(obj)), index); TSNode args_node = vm_ts_node_child_checked(node, 1); size_t nargs = ts_node_child_count(args_node); @@ -547,7 +547,7 @@ vm_ast_node_t vm_lang_lua_conv_raw(vm_lang_lua_t src, TSNode node) { nfields += 1; } else if (sub_children == 3) { char *key_field = vm_lang_lua_src(src, vm_ts_node_child_checked(sub, 0)); - vm_ast_node_t key = vm_ast_build_obj(vm_str(src.vm, key_field)); + vm_ast_node_t key = vm_ast_build_obj(vm_obj_of_string(src.vm, key_field)); vm_ast_node_t value = vm_lang_lua_conv(src, vm_ts_node_child_checked(sub, 2)); cur = vm_ast_build_set(vm_ast_build_load(vm_ast_build_ident(vm_strdup(var)), key), value); } else if (sub_children == 5) { @@ -572,7 +572,7 @@ vm_ast_node_t vm_lang_lua_conv_raw(vm_lang_lua_t src, TSNode node) { if (!strcmp(type, "dot_index_expression")) { vm_ast_node_t table = vm_lang_lua_conv(src, vm_ts_node_child_checked(node, 0)); char *field = vm_lang_lua_src(src, vm_ts_node_child_checked(node, 2)); - return vm_ast_build_load(table, vm_ast_build_obj(vm_str(src.vm, field))); + return vm_ast_build_load(table, vm_ast_build_obj(vm_obj_of_string(src.vm, field))); } if (!strcmp(type, "nil")) { return vm_ast_build_nil(); diff --git a/vm/lua/repl.c b/vm/lua/repl.c index a293f06a..fc1a4c86 100644 --- a/vm/lua/repl.c +++ b/vm/lua/repl.c @@ -160,7 +160,7 @@ void vm_lang_lua_repl(vm_t *vm) { vm_error_report(vm_obj_get_error(value), stderr); } else if (!vm_obj_is_nil(value)) { vm_io_buffer_t buf = {0}; - vm_io_debug(&buf, 0, "", value, NULL); + vm_io_buffer_obj_debug(&buf, 0, "", value, NULL); printf("%.*s", (int)buf.len, buf.buf); } } diff --git a/vm/obj.c b/vm/obj.c index 7fcf4929..1bf12f8c 100644 --- a/vm/obj.c +++ b/vm/obj.c @@ -31,9 +31,9 @@ uint64_t vm_obj_hash(vm_obj_t value) { } if (vm_obj_is_string(value)) { uint64_t ret = 0xcbf29ce484222325; - const char *head = vm_obj_get_string(value)->buf; - while (true) { - char c = *head++; + vm_io_buffer_t *restrict buf = vm_obj_get_string(value); + for (size_t i = 0; i < buf->len; i++) { + char c = buf->buf[i]; if (c == '\0') { break; } @@ -54,7 +54,7 @@ uint64_t vm_obj_hash(vm_obj_t value) { if (vm_obj_is_table(value)) { return (uint64_t)(size_t)vm_obj_get_table(value) >> 4; } - if (vm_obj_is_empty(value) || vm_obj_is_nil(value)) { + if (vm_obj_is_nil(value)) { return 0; } __builtin_trap(); @@ -62,11 +62,14 @@ uint64_t vm_obj_hash(vm_obj_t value) { } vm_table_pair_t *vm_table_lookup(vm_obj_table_t *table, vm_obj_t key) { - size_t len = vm_primes_table[table->size]; - size_t look = vm_primes_mod(table->size, vm_obj_hash(key)); - for (size_t i = 0; i < len; i++) { - vm_table_pair_t *pair = &table->pairs[look]; - if (vm_obj_is_empty(pair->key) || vm_obj_is_nil(pair->key)) { + size_t len = 1 << table->alloc; + size_t and = len - 1; + size_t stop = vm_obj_hash(key) & and; + size_t next = stop; + do { + vm_table_pair_t *pair = &table->pairs[next]; + vm_obj_t value = pair->key; + if (vm_obj_is_empty(value) || vm_obj_is_nil(value)) { return NULL; } if (vm_obj_eq(key, pair->key)) { @@ -85,12 +88,12 @@ void vm_table_set(vm_obj_table_t *restrict table, vm_obj_t key, vm_obj_t value) size_t look = vm_primes_mod(table->size, vm_obj_hash(key)); for (size_t i = 0; i < len; i++) { vm_table_pair_t *pair = &table->pairs[look]; - if (vm_obj_is_empty(pair->key) || vm_obj_is_nil(pair->key)) { + if (vm_obj_is_nil(pair->key)) { break; } if (vm_obj_eq(key, pair->key)) { if (vm_obj_is_nil(key)) { - pair->key = vm_obj_of_empty(); + pair->key = vm_obj_of_nil(); if (vm_obj_is_number(key)) { double f64val = vm_obj_get_number(key); if ((double)INT64_MIN <= f64val && f64val <= (double)INT64_MAX) { @@ -113,9 +116,9 @@ void vm_table_set(vm_obj_table_t *restrict table, vm_obj_t key, vm_obj_t value) look = 0; } } - if (vm_obj_is_empty(value) || vm_obj_is_nil(value)) { + if (vm_obj_is_nil(value)) { table->pairs[look] = (vm_table_pair_t){ - .key = vm_obj_of_empty(), + .key = vm_obj_of_nil(), .value = value, }; @@ -139,7 +142,7 @@ void vm_table_set(vm_obj_table_t *restrict table, vm_obj_t key, vm_obj_t value) size_t table_len = vm_primes_table[table->size]; for (size_t i = 0; i < table_len; i++) { vm_table_pair_t *in_pair = &table->pairs[i]; - if (!vm_obj_is_empty(in_pair->key) && !vm_obj_is_nil(in_pair->key)) { + if (!vm_obj_is_nil(in_pair->key)) { vm_table_set_pair(&ret, in_pair); } } diff --git a/vm/std.c b/vm/std.c index e9a57b59..9e17c19a 100644 --- a/vm/std.c +++ b/vm/std.c @@ -26,13 +26,13 @@ static inline void vm_config_add_extern(vm_t *vm, void *value) { vm->externs = next; } -void vm_std_os_exit(vm_t *vm, vm_obj_t *args) { +void vm_std_os_exit(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; exit((int)vm_obj_get_number(args[0])); return; } -void vm_std_load(vm_t *vm, vm_obj_t *args) { +void vm_std_load(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; if (!vm_obj_is_string(args[0])) { *args = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "cannot load non-string value")); @@ -50,14 +50,14 @@ void vm_std_load(vm_t *vm, vm_obj_t *args) { return; } -void vm_std_assert(vm_t *vm, vm_obj_t *args) { +void vm_std_assert(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; vm_obj_t val = args[0]; if (vm_obj_is_nil(val) || (vm_obj_is_boolean(val) && !vm_obj_get_boolean(val))) { vm_obj_t msg = args[1]; vm_io_buffer_t buf = {0}; - vm_io_debug(&buf, 0, "assert failed with mesage: ", msg, NULL); - *args = vm_str(vm, buf.buf); + vm_io_buffer_obj_debug(&buf, 0, "assert failed with mesage: ", msg, NULL); + *args = vm_obj_of_string(vm, buf.buf); vm_free(buf.buf); return; } else { @@ -66,24 +66,20 @@ void vm_std_assert(vm_t *vm, vm_obj_t *args) { } } -void vm_std_error(vm_t *vm, vm_obj_t *args) { +void vm_std_error(vm_t *vm, size_t nargs, vm_obj_t *args) { if (vm_obj_is_string(args[0])) { *args = vm_obj_of_error(vm_error_from_msg(vm_location_range_unknown, vm_obj_get_string(args[0])->buf)); return; } vm_obj_t msg = args[0]; vm_io_buffer_t buf = {0}; - vm_io_debug(&buf, 0, "", msg, NULL); - *args = vm_str(vm, buf.buf); + vm_io_buffer_obj_debug(&buf, 0, "", msg, NULL); + *args = vm_obj_of_string(vm, buf.buf); vm_free(buf.buf); return; } -void vm_std_vm_closure(vm_t *vm, vm_obj_t *args) { - int64_t nargs = 0; - for (size_t i = 0; !vm_obj_is_empty(args[i]); i++) { - nargs += 1; - } +void vm_std_vm_closure(vm_t *vm, size_t nargs, vm_obj_t *args) { if (nargs == 0 || !vm_obj_is_block(args[0])) { *args = vm_obj_of_nil(); return; @@ -91,7 +87,7 @@ void vm_std_vm_closure(vm_t *vm, vm_obj_t *args) { vm_obj_closure_t *closure = vm_malloc(sizeof(vm_obj_closure_t) + sizeof(vm_obj_t) * (nargs - 1)); closure->block = vm_obj_get_block(args[0]); closure->len = nargs - 1; - for (size_t i = 1; !vm_obj_is_empty(args[i]); i++) { + for (size_t i = 1; i < nargs; i++) { closure->values[i - 1] = args[i]; } vm_obj_t ret = vm_obj_of_closure(closure); @@ -100,26 +96,26 @@ void vm_std_vm_closure(vm_t *vm, vm_obj_t *args) { return; } -void vm_std_vm_gc(vm_t *vm, vm_obj_t *args) { +void vm_std_vm_gc(vm_t *vm, size_t nargs, vm_obj_t *args) { vm_gc_run(vm, vm->regs); *args = vm_obj_of_nil(); } -void vm_std_vm_print(vm_t *vm, vm_obj_t *args) { +void vm_std_vm_print(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; - for (size_t i = 0; !vm_obj_is_empty(args[i]); i++) { + for (size_t i = 0; i < nargs; i++) { vm_io_buffer_t buf = {0}; - vm_io_debug(&buf, 0, "", args[i], NULL); + vm_io_buffer_obj_debug(&buf, 0, "", args[i], NULL); printf("%.*s", (int)buf.len, buf.buf); } *args = vm_obj_of_nil(); return; } -void vm_std_vm_concat(vm_t *vm, vm_obj_t *args) { +void vm_std_vm_concat(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; size_t len = 1; - for (size_t i = 0; vm_obj_is_string(args[i]); i++) { + for (size_t i = 0; i < nargs; i++) { len += vm_obj_get_string(args[i])->len; } char *buf = vm_malloc(sizeof(char) * len); @@ -133,17 +129,17 @@ void vm_std_vm_concat(vm_t *vm, vm_obj_t *args) { head += len; } buf[len - 1] = '\0'; - *args = vm_str(vm, buf); + *args = vm_obj_of_string(vm, buf); } -void vm_std_math_rand_int(vm_t *vm, vm_obj_t *args) { +void vm_std_math_rand_int(vm_t *vm, size_t nargs, vm_obj_t *args) { args[0] = vm_obj_of_number(rand()); } -void vm_std_type(vm_t *vm, vm_obj_t *args) { +void vm_std_type(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; const char *ret; - if (vm_obj_is_empty(args[0]) || vm_obj_is_nil(args[0])) { + if (vm_obj_is_nil(args[0])) { ret = "nil"; } else if (vm_obj_is_boolean(args[0])) { ret = "booolean"; @@ -158,18 +154,18 @@ void vm_std_type(vm_t *vm, vm_obj_t *args) { } else { ret = "userdata"; } - *args = vm_str(vm, ret); + *args = vm_obj_of_string(vm, ret); } -void vm_std_tostring(vm_t *vm, vm_obj_t *args) { +void vm_std_tostring(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; vm_io_buffer_t out = {0}; - vm_obj_buffer_tostring(&out, *args); - *args = vm_str(vm, out.buf); + vm_io_buffer_object_tostring(&out, *args); + *args = vm_obj_of_string(vm, out.buf); vm_free(out.buf); } -void vm_std_tonumber(vm_t *vm, vm_obj_t *args) { +void vm_std_tonumber(vm_t *vm, size_t nargs, vm_obj_t *args) { if (vm_obj_is_number(args[0])) { } else if (vm_obj_is_string(args[0])) { double num; @@ -183,43 +179,41 @@ void vm_std_tonumber(vm_t *vm, vm_obj_t *args) { } } -void vm_std_print(vm_t *vm, vm_obj_t *args) { +void vm_std_print(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; - vm_obj_t *ret = args; vm_io_buffer_t out = {0}; bool first = true; - while (!vm_obj_is_empty(args[0])) { + for (size_t i = 0; i < nargs; i++) { if (!first) { vm_io_buffer_format(&out, "\t"); } - vm_obj_buffer_tostring(&out, *args++); + vm_io_buffer_object_tostring(&out, args[i]); first = false; } fprintf(stdout, "%.*s\n", (int)out.len, out.buf); vm_free(out.buf); - *ret = vm_obj_of_nil(); + args[0] = vm_obj_of_nil(); return; } -void vm_std_io_write(vm_t *vm, vm_obj_t *args) { +void vm_std_io_write(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; - vm_obj_t *ret = args; vm_io_buffer_t out = {0}; - while (!vm_obj_is_empty(args[0])) { - vm_obj_buffer_tostring(&out, *args++); + for (size_t i = 0; i < nargs; i++) { + vm_io_buffer_object_tostring(&out, args[i]); } fprintf(stdout, "%.*s", (int)out.len, out.buf); - *ret = vm_obj_of_nil(); + args[0] = vm_obj_of_nil(); return; } -void vm_std_string_format(vm_t *vm, vm_obj_t *args) { +void vm_std_string_format(vm_t *vm, size_t nargs, vm_obj_t *args) { (void)vm; - vm_obj_t *ret = args; vm_io_buffer_t *out = vm_io_buffer_new(); - vm_obj_t fmt = *args++; + size_t argnum = 0; + vm_obj_t fmt = args[argnum++]; if (!vm_obj_is_string(fmt)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (not a string)")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (not a string)")); return; } const char *str = vm_obj_get_string(fmt)->buf; @@ -250,7 +244,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { str++; } if ('0' < *str && *str <= '9') { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (width > 99)")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (width > 99)")); return; } bool format_has_dot = *str == '.'; @@ -263,26 +257,26 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { } } if ('0' < *str && *str <= '9') { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (precision > 99)")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (precision > 99)")); return; } ptrdiff_t len = str - head; if (!(0 < len || len > 48)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (too long to handle)")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "invalid format (too long to handle)")); return; } char format[64]; strncpy(format, head, str - head); - vm_obj_t arg = *args++; - if (vm_obj_is_empty(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "too few args")); + if (argnum >= nargs) { + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "too few args")); return; } + vm_obj_t arg = args[argnum++]; char fc = *str++; switch (fc) { case 'c': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %c format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %c format")); return; } strcpy(&format[len], "c"); @@ -292,7 +286,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { case 'd': case 'i': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for integer format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for integer format")); return; } strcpy(&format[len], PRIi64); @@ -301,7 +295,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { } case 'o': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %o format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %o format")); return; } strcpy(&format[len], PRIo64); @@ -310,7 +304,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { } case 'u': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %u format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %u format")); return; } strcpy(&format[len], PRIu64); @@ -319,7 +313,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { } case 'x': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %x format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %x format")); return; } strcpy(&format[len], PRIx64); @@ -328,7 +322,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { } case 'X': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %X format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %X format")); return; } strcpy(&format[len], PRIX64); @@ -342,7 +336,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { case 'g': case 'G': { if (!vm_obj_is_number(arg)) { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for float format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for float format")); return; } format[len] = fc; @@ -351,7 +345,7 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { break; } case 'q': { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "unimplemented %q")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "unimplemented %q")); return; } case 's': { @@ -362,18 +356,18 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { strcpy(&format[len], "f"); vm_io_buffer_format(out, format, vm_obj_get_number(arg)); } else { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "unimplemented %s for a type")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "unimplemented %s for a type")); return; } break; } default: { - *ret = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %u format")); + args[0] = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "expected a number for %u format")); return; } } } - *ret = vm_str(vm, out->buf); + args[0] = vm_obj_of_string(vm, out->buf); vm_free(out->buf); vm_free(out); } @@ -381,19 +375,19 @@ void vm_std_string_format(vm_t *vm, vm_obj_t *args) { void vm_std_set_arg(vm_t *vm, const char *prog, const char *file, int argc, char **argv) { vm_obj_table_t *arg = vm_table_new(vm); if (prog != NULL) { - vm_table_set(arg, vm_obj_of_number(-1), vm_str(vm, prog)); + vm_table_set(arg, vm_obj_of_number(-1), vm_obj_of_string(vm, prog)); } if (file != NULL) { - vm_table_set(arg, vm_obj_of_number(0), vm_str(vm, file)); + vm_table_set(arg, vm_obj_of_number(0), vm_obj_of_string(vm, file)); } for (int64_t i = 0; i < argc; i++) { - vm_table_set(arg, vm_obj_of_number(i + 1), vm_str(vm, argv[i])); + vm_table_set(arg, vm_obj_of_number(i + 1), vm_obj_of_string(vm, argv[i])); } - vm_table_set(vm_obj_get_table(vm->std), vm_str(vm, "arg"), vm_obj_of_table(arg)); + vm_table_set(vm_obj_get_table(vm->std), vm_obj_of_string(vm, "arg"), vm_obj_of_table(arg)); } -void vm_std_table_keys(vm_t *vm, vm_obj_t *args) { +void vm_std_table_keys(vm_t *vm, size_t nargs, vm_obj_t *args) { if (!vm_obj_is_table(args[0])) { *args = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "table.values: expect a table")); return; @@ -404,7 +398,7 @@ void vm_std_table_keys(vm_t *vm, vm_obj_t *args) { size_t write_head = 1; for (size_t i = 0; i < len; i++) { vm_table_pair_t *pair = &tab->pairs[i]; - if (!vm_obj_is_empty(pair->key)) { + if (!vm_obj_is_nil(pair->key)) { vm_obj_t key = vm_obj_of_number(write_head); vm_table_set(ret, key, pair->key); write_head++; @@ -414,7 +408,7 @@ void vm_std_table_keys(vm_t *vm, vm_obj_t *args) { return; } -void vm_std_table_values(vm_t *vm, vm_obj_t *args) { +void vm_std_table_values(vm_t *vm, size_t nargs, vm_obj_t *args) { if (!vm_obj_is_table(args[0])) { *args = vm_obj_of_error(vm_error_from_msg(VM_LOCATION_RANGE_FUNC, "table.values: expect a table")); return; @@ -425,7 +419,7 @@ void vm_std_table_values(vm_t *vm, vm_obj_t *args) { size_t write_head = 1; for (size_t i = 0; i < len; i++) { vm_table_pair_t *pair = &tab->pairs[i]; - if (!vm_obj_is_empty(pair->key)) { + if (!vm_obj_is_nil(pair->key)) { vm_obj_t key = vm_obj_of_number(write_head); vm_table_set(ret, key, pair->value); write_head++; @@ -435,16 +429,14 @@ void vm_std_table_values(vm_t *vm, vm_obj_t *args) { return; } -void vm_lua_comp_op_std_pow(vm_t *vm, vm_obj_t *args); - -void vm_std_vm_import(vm_t *vm, vm_obj_t *args) { +void vm_std_vm_import(vm_t *vm, size_t nargs, vm_obj_t *args) { if (!vm_obj_is_string(args[0])) { - args[0] = vm_str(vm, "import() must take a string"); + args[0] = vm_obj_of_string(vm, "import() must take a string"); return; } const char *src = vm_io_read(vm_obj_get_string(args[0])->buf); if (src == NULL) { - args[0] = vm_str(vm, "import() no such file"); + args[0] = vm_obj_of_string(vm, "import() no such file"); return; } vm_ir_block_t *block = vm_lang_lua_compile(vm, src, vm_obj_get_string(args[0])->buf); @@ -460,55 +452,54 @@ void vm_std_new(vm_t *vm) { { vm_obj_table_t *io = vm_table_new(vm); - vm_table_set(std, vm_str(vm, "io"), vm_obj_of_table(io)); - vm_table_set(io, vm_str(vm, "write"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_io_write))); + vm_table_set(std, vm_obj_of_string(vm, "io"), vm_obj_of_table(io)); + vm_table_set(io, vm_obj_of_string(vm, "write"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_io_write))); } { vm_obj_table_t *string = vm_table_new(vm); - vm_table_set(std, vm_str(vm, "string"), vm_obj_of_table(string)); - vm_table_set(string, vm_str(vm, "format"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_string_format))); + vm_table_set(std, vm_obj_of_string(vm, "string"), vm_obj_of_table(string)); + vm_table_set(string, vm_obj_of_string(vm, "format"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_string_format))); } { vm_obj_table_t *tvm = vm_table_new(vm); - vm_table_set(std, vm_str(vm, "vm"), vm_obj_of_table(tvm)); - vm_table_set(tvm, vm_str(vm, "import"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_import))); - vm_table_set(tvm, vm_str(vm, "gc"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_gc))); - vm_table_set(tvm, vm_str(vm, "print"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_print))); - vm_table_set(tvm, vm_str(vm, "version"), vm_str(vm, VM_VERSION)); - vm_table_set(tvm, vm_str(vm, "conacat"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_concat))); + vm_table_set(std, vm_obj_of_string(vm, "vm"), vm_obj_of_table(tvm)); + vm_table_set(tvm, vm_obj_of_string(vm, "import"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_import))); + vm_table_set(tvm, vm_obj_of_string(vm, "gc"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_gc))); + vm_table_set(tvm, vm_obj_of_string(vm, "print"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_print))); + vm_table_set(tvm, vm_obj_of_string(vm, "version"), vm_obj_of_string(vm, VM_VERSION)); + vm_table_set(tvm, vm_obj_of_string(vm, "conacat"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_vm_concat))); } { vm_obj_table_t *math = vm_table_new(vm); - vm_table_set(std, vm_str(vm, "math"), vm_obj_of_table(math)); - vm_table_set(math, vm_str(vm, "randint"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_math_rand_int))); + vm_table_set(std, vm_obj_of_string(vm, "math"), vm_obj_of_table(math)); + vm_table_set(math, vm_obj_of_string(vm, "randint"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_math_rand_int))); } { vm_obj_table_t *os = vm_table_new(vm); - vm_table_set(std, vm_str(vm, "os"), vm_obj_of_table(os)); - vm_table_set(os, vm_str(vm, "exit"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_os_exit))); + vm_table_set(std, vm_obj_of_string(vm, "os"), vm_obj_of_table(os)); + vm_table_set(os, vm_obj_of_string(vm, "exit"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_os_exit))); } { vm_obj_table_t *table = vm_table_new(vm); - vm_table_set(std, vm_str(vm, "table"), vm_obj_of_table(table)); - vm_table_set(table, vm_str(vm, "keys"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_table_keys))); - vm_table_set(table, vm_str(vm, "values"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_table_values))); + vm_table_set(std, vm_obj_of_string(vm, "table"), vm_obj_of_table(table)); + vm_table_set(table, vm_obj_of_string(vm, "keys"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_table_keys))); + vm_table_set(table, vm_obj_of_string(vm, "values"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_table_values))); } - vm_table_set(std, vm_str(vm, "error"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_error))); - vm_table_set(std, vm_str(vm, "tostring"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_tostring))); - vm_table_set(std, vm_str(vm, "tonumber"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_tonumber))); - vm_table_set(std, vm_str(vm, "type"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_type))); - vm_table_set(std, vm_str(vm, "print"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_print))); - vm_table_set(std, vm_str(vm, "assert"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_assert))); - vm_table_set(std, vm_str(vm, "load"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_load))); - vm_table_set(std, vm_str(vm, "_G"), vm_obj_of_table(std)); + vm_table_set(std, vm_obj_of_string(vm, "error"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_error))); + vm_table_set(std, vm_obj_of_string(vm, "tostring"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_tostring))); + vm_table_set(std, vm_obj_of_string(vm, "tonumber"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_tonumber))); + vm_table_set(std, vm_obj_of_string(vm, "type"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_type))); + vm_table_set(std, vm_obj_of_string(vm, "print"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_print))); + vm_table_set(std, vm_obj_of_string(vm, "assert"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_assert))); + vm_table_set(std, vm_obj_of_string(vm, "load"), vm_obj_of_ffi(VM_STD_REF(vm, vm_std_load))); + vm_table_set(std, vm_obj_of_string(vm, "_G"), vm_obj_of_table(std)); - vm_config_add_extern(vm, &vm_lua_comp_op_std_pow); vm_config_add_extern(vm, &vm_std_vm_closure); vm->std = vm_obj_of_table(std); diff --git a/vm/std.h b/vm/std.h index a814524f..5e494eb5 100644 --- a/vm/std.h +++ b/vm/std.h @@ -5,7 +5,7 @@ #define VM_STD_REF(vm, x) (vm_config_add_extern((vm), &(x)), &(x)) -void vm_obj_buffer_tostring(vm_io_buffer_t *buf, vm_obj_t value); +void vm_io_buffer_object_tostring(vm_io_buffer_t *buf, vm_obj_t value); void vm_std_set_arg(vm_t *vm, const char *prog, const char *file, int argc, char **argv); void vm_std_new(vm_t *vm); diff --git a/vm/vm.c b/vm/vm.c index 721bb202..f7069175 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -35,8 +35,8 @@ void vm_state_delete(vm_t *vm) { vm_free(vm); } -vm_obj_t vm_str(vm_t *vm, const char *str) { - vm_obj_t ret = vm_obj_of_string(vm_io_buffer_from_str(str)); +vm_obj_t vm_obj_of_string(vm_t *vm, const char *str) { + vm_obj_t ret = vm_obj_of_buffer(vm_io_buffer_from_str(str)); vm_gc_add(vm, ret); return ret; } diff --git a/vm/vm.h b/vm/vm.h index ada87bb2..dbc1fc40 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -5,6 +5,7 @@ #include #include #include +#include "../vendor/nanbox/nanbox.h" #define VM_VERSION "0.0.5" @@ -12,7 +13,7 @@ #define VM_GC_MIN (1 << 8) // #define VM_GC_MIN 16 -#define VM_GC_FACTOR 2 +#define VM_GC_FACTOR 1.4 #define VM_DEBUG_BACKEND_BLOCKS 0 #define VM_DEBUG_BACKEND_OPCODES 0 @@ -26,7 +27,10 @@ #define VM_OBJ_FIELD_VALUE _value ## __COUNTER__ #define VM_OBJ_FIELD_TAG _tag ## __COUNTER__ +#define VM_EMPTY_BYTE NANBOX_EMPTY_BYTE + struct vm_t; +struct vm_error_t; struct vm_ir_block_t; struct vm_ir_blocks_t; struct vm_obj_closure_t; @@ -38,32 +42,15 @@ struct vm_io_buffer_t; typedef struct vm_io_buffer_t vm_io_buffer_t; typedef struct vm_t vm_t; +typedef struct vm_error_t vm_error_t; +typedef struct vm_ir_block_t vm_ir_block_t; typedef struct vm_ir_blocks_t vm_ir_blocks_t; typedef struct vm_obj_closure_t vm_obj_closure_t; typedef struct vm_externs_t vm_externs_t; typedef struct vm_obj_table_t vm_obj_table_t; typedef struct vm_table_pair_t vm_table_pair_t; -#include "../vendor/nanbox/nanbox.h" - -#define VM_EMPTY_BYTE NANBOX_EMPTY_BYTE - -typedef nanbox_t vm_obj_t; - -typedef void vm_ffi_t(vm_t *closure, vm_obj_t *args); -#define vm_obj_of_empty() nanbox_empty() -#define vm_obj_of_nil() nanbox_undefined() -#define vm_obj_of_boolean(b) ((b) ? nanbox_true() : nanbox_false()) -#define vm_obj_of_number(n) nanbox_from_double(n) -#define vm_obj_of_string(s) nanbox_from_aux1(s) -#define vm_obj_of_table(o) nanbox_from_aux2(o) -#define vm_obj_of_closure(o) nanbox_from_aux3(o) -#define vm_obj_of_ffi(o) nanbox_from_aux4(o) -#define vm_obj_of_block(o) nanbox_from_aux5(o) -#define vm_obj_of_error(o) nanbox_from_pointer(o) - -#define vm_obj_is_empty(o) nanbox_is_empty(o) -#define vm_obj_is_nil(o) nanbox_is_undefined(o) +#define vm_obj_is_nil(o) nanbox_is_empty(o) #define vm_obj_is_boolean(o) nanbox_is_boolean(o) #define vm_obj_is_number(o) nanbox_is_number(o) #define vm_obj_is_string(o) nanbox_is_aux1(o) @@ -82,6 +69,37 @@ typedef void vm_ffi_t(vm_t *closure, vm_obj_t *args); #define vm_obj_get_block(o) ((vm_ir_block_t *) nanbox_to_aux(o)) #define vm_obj_get_error(o) ((vm_error_t *) nanbox_to_pointer(o)) +typedef nanbox_t vm_obj_t; +typedef void vm_ffi_t(vm_t *vm, size_t nargs, vm_obj_t *args); + +static inline vm_obj_t vm_obj_of_nil(void) { + return nanbox_empty(); +} +static inline vm_obj_t vm_obj_of_boolean(bool b) { + return nanbox_from_boolean(b); +} +static inline vm_obj_t vm_obj_of_number(double n) { + return nanbox_from_double(n); +} +static inline vm_obj_t vm_obj_of_buffer(vm_io_buffer_t *o) { + return nanbox_from_aux1(o); +} +static inline vm_obj_t vm_obj_of_table(vm_obj_table_t *o) { + return nanbox_from_aux2(o); +} +static inline vm_obj_t vm_obj_of_closure(vm_obj_closure_t *o) { + return nanbox_from_aux3(o); +} +static inline vm_obj_t vm_obj_of_ffi(vm_ffi_t *o) { + return nanbox_from_aux4(o); +} +static inline vm_obj_t vm_obj_of_block(vm_ir_block_t *o) { + return nanbox_from_aux5(o); +} +static inline vm_obj_t vm_obj_of_error(vm_error_t *o) { + return nanbox_from_pointer(o); +} + struct vm_table_pair_t { vm_obj_t key; vm_obj_t value; @@ -138,6 +156,6 @@ vm_t *vm_state_new(void); void vm_state_delete(vm_t *vm); void vm_lang_lua_repl(vm_t *vm); -vm_obj_t vm_str(vm_t *vm, const char *str); +vm_obj_t vm_obj_of_string(vm_t *vm, const char *str); #endif