diff --git a/main.c b/main.c index 0d57d52..d8da28f 100644 --- a/main.c +++ b/main.c @@ -5,38 +5,102 @@ #include"lexer.h" #include"str.h" #include"dump.h" +#include +#include -static size_t native_print(LVM *lvm, void *ud, size_t argn, LRegSet *regset) { +static size_t native_print(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) { if(lvalue_tag(regset->regs[0]) == LTAG_STRING) { LString *lstr = (void*) (regset->regs[0].u & ~LTAG_MASK); printf("%.*s\n", (int) lstr->length, lstr->data); } else if(lvalue_tag(regset->regs[0]) == LTAG_I32) { printf("%i\n", lvalue_to_int32(regset->regs[0])); + } else if(lvalue_tag(regset->regs[0]) == LTAG_TABLE) { + printf("table: 0x%lx\n", (uintptr_t) (regset->regs[0].u & ~LTAG_MASK)); + } else if(lvalue_tag(regset->regs[0]) == LTAG_FUNCTION) { + printf("function: 0x%lx\n", (uintptr_t) (regset->regs[0].u & ~LTAG_MASK)); } else if(regset->regs[0].u == LTAG_NIL) { printf("nil\n"); + } else if(regset->regs[0].u == LTAG_TRUE) { + printf("true\n"); + } else if(regset->regs[0].u == LTAG_FALSE) { + printf("false\n"); + } else if(!isnan(regset->regs[0].f)) { + printf("%f\n", regset->regs[0].f); } return 0; } +static size_t table_insert(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) { + LTable *tbl = (LTable*) (regset->regs[0].u & ~LTAG_MASK); + ltable_insert(tbl, regset->regs[1], 0); + return 0; +} + +// This function is intended for small-medium runtimes, since the caller thread's heap is not touchable during this call. +static size_t threads_parallel(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) { + size_t no = lvalue_to_int32(regset->regs[0]); + LFunc *func = (LFunc*) (regset->regs[1].u & ~LTAG_MASK); + + atomic_fetch_sub(&lvm->active_thread_count, 1); + + #pragma omp parallel for + for(size_t i = 0; i < no; i++) { + LRegSet regset = {}; + lvm_reset_regs(®set); + lvm_run(lvm, func, 0, ®set); + } + + atomic_fetch_add(&lvm->active_thread_count, 1); + + return 0; +} + static char* read_full_file(const char *fn) { - FILE *f = fopen(fn, "rb"); + FILE *f = fn ? fopen(fn, "rb") : stdin; fseek(f, 0, SEEK_END); size_t filesize = ftell(f); fseek(f, 0, SEEK_SET); char *buf = malloc(filesize + 1); fread(buf, 1, filesize, f); buf[filesize] = '\0'; - fclose(f); + if(fn) fclose(f); return buf; } int main(int argc, char **argv) { LTable *env = ltable_new(128); - LString *key = lstring_newz("print"); - LFunc *func = lvm_func_from_native(native_print, NULL); + ltable_set(env, + lvalue_from_string(lstring_newz("print")), + lvalue_from_func(lvm_func_from_native(native_print, NULL))); - ltable_set(env, lvalue_from_string(key), lvalue_from_func(func)); + LTable *table = ltable_new(16); + { + ltable_set(table, + lvalue_from_string(lstring_newz("insert")), + lvalue_from_func(lvm_func_from_native(table_insert, NULL))); + } + ltable_set(env, + lvalue_from_string(lstring_newz("table")), + lvalue_from_table(table)); + + LTable *threads = ltable_new(16); + { + ltable_set(threads, + lvalue_from_string(lstring_newz("parallel")), + lvalue_from_func(lvm_func_from_native(threads_parallel, NULL))); + } + ltable_set(env, + lvalue_from_string(lstring_newz("threads")), + lvalue_from_table(threads)); + + LTable *math = ltable_new(16); + { + ltable_set(math, lvalue_from_string(lstring_newz("pi")), (LValue) {.f = 3.141592653589793238463}); + } + ltable_set(env, + lvalue_from_string(lstring_newz("math")), + lvalue_from_table(math)); //const char *bufs = "for i = 1, 10000 do print(i) if i % 3 == 0 then print(\"Fizz\") end if i % 5 == 0 then print(\"Buzz\") end end"; //const char *bufs = "local t = {a = 9} print(t.a)"; @@ -59,12 +123,9 @@ int main(int argc, char **argv) { LVM lvm = {}; lvm_init(&lvm); - //#pragma omp parallel for - for(int i = 0; i < 1; i++) { - LRegSet regset = {.parent = NULL}; - lvm_reset_regs(®set); - lvm_run(&lvm, &unit->funcs[0], 0, ®set); - } + LRegSet regset = {.parent = NULL}; + lvm_reset_regs(®set); + lvm_run(&lvm, &unit->funcs[0], 0, ®set); lvm_destroy(&lvm); } diff --git a/vm.c b/vm.c index cdf4483..7015ec3 100644 --- a/vm.c +++ b/vm.c @@ -7,9 +7,9 @@ #include #include -static size_t lvm_run_internal(LVM *L, LFunc *func, size_t arg_count, set_LValueU *heap, LRegSet *regset) { +size_t lvm_call(LVM *L, LFunc *func, size_t arg_count, set_LValueU *heap, LRegSet *regset) { if(func->is_native) { - return func->native_func(L, func->ud, arg_count, regset); + return func->native_func(L, func->ud, arg_count, heap, regset); } static const void *dispatch_table[] = { @@ -38,6 +38,7 @@ static size_t lvm_run_internal(LVM *L, LFunc *func, size_t arg_count, set_LValue [L_COND_NEQ] = &&do_cond_neq, [L_SETFIELD] = &&do_setfield, [L_GETFIELD] = &&do_getfield, + [L_LEN] = &&do_len, }; LUnit *unit = func->unit; @@ -248,7 +249,7 @@ do_call:; for(int i = 0; i < arg_count; i++) { regset2.regs[i] = regset->regs[args[i]]; } - size_t returned_count = lvm_run_internal(L, (LFunc*) (regset->regs[inst->a].u & ~LTAG_MASK), arg_count, heap, ®set2); + size_t returned_count = lvm_call(L, (LFunc*) (regset->regs[inst->a].u & ~LTAG_MASK), arg_count, heap, ®set2); if(returned_count) { // TODO: more than 1 return @@ -286,7 +287,7 @@ do_setfield:; goto err; } - if(lvalue_tag(regset->regs[inst->b]) == LTAG_NIL) { + if(regset->regs[inst->b].u == LTAG_NIL) { goto err; } @@ -307,6 +308,14 @@ do_getfield:; regset->regs[inst->a] = ltable_get(tbl, regset->regs[inst->c]); } DISPATCH(); + +do_len: + if(lvalue_tag(regset->regs[inst->b]) == LTAG_STRING) { + regset->regs[inst->a] = lvalue_from_int32(((LString*) (regset->regs[inst->b].u & ~LTAG_MASK))->length); + } else if(lvalue_tag(regset->regs[inst->b]) == LTAG_TABLE) { + regset->regs[inst->a] = lvalue_from_int32(ltable_len((LTable*) (regset->regs[inst->b].u & ~LTAG_MASK))); + } else goto err; + DISPATCH(); err:; puts("Error"); @@ -320,7 +329,7 @@ size_t lvm_run(LVM *L, LFunc *func, size_t arg_count, LRegSet *regset) { atomic_fetch_add(&L->active_thread_count, 1); - size_t ret = lvm_run_internal(L, func, arg_count, &heap, regset); + size_t ret = lvm_call(L, func, arg_count, &heap, regset); mtx_lock(&L->dead_heap_mut); for(c_each(i, set_LValueU, heap)) { @@ -400,7 +409,7 @@ static void gc_mark(LValue v) { LTable *tbl = gco; tbl->ref = true; - for(size_t i = 0; tbl->buckets->capacity; i++) { + for(size_t i = 0; i < tbl->buckets->capacity; i++) { LTableEntry e = tbl->buckets->data[i]; gc_mark(e.key); gc_mark(e.val); diff --git a/vm.h b/vm.h index cd9a19c..fa69dc7 100644 --- a/vm.h +++ b/vm.h @@ -42,6 +42,7 @@ typedef enum { L_SETFIELD, L_GETFIELD, L_SETINT32, + L_LEN, } LOp; typedef union __attribute__((packed)) { @@ -74,7 +75,12 @@ typedef struct LRegSet { LValue regs[256]; } LRegSet; -typedef size_t(*LFuncCallback)(struct LVM*, void *ud, size_t argn, LRegSet *regset); +#define i_header +#define T set_LValueU, uint64_t +#include"stc/hashset.h" +#undef i_header + +typedef size_t(*LFuncCallback)(struct LVM*, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset); typedef struct LFunc { struct LUnit *unit; bool is_native; @@ -99,11 +105,6 @@ typedef struct LUnit { LFunc *funcs; } LUnit; -#define i_header -#define T set_LValueU, uint64_t -#include"stc/hashset.h" -#undef i_header - typedef struct LThreadPrivates { set_LValueU *heap; LRegSet *regset; @@ -130,6 +131,7 @@ typedef struct LVM { set_LValueU dead_heap; } LVM; +size_t lvm_call(LVM *L, LFunc *func, size_t arg_count, set_LValueU *heap, LRegSet *regset); size_t lvm_run(LVM *L, LFunc *func, size_t arg_count, LRegSet *regset); LFunc *lvm_func_from_native(LFuncCallback, void *ud);