impotent/main.c
2025-09-06 15:06:03 +03:00

189 lines
4.9 KiB
C

#include"value.h"
#include"table.h"
#include"parse.h"
#include"vm.h"
#include"lexer.h"
#include"str.h"
#include"dump.h"
#include<stdatomic.h>
#include<math.h>
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;
}
struct ThreadsParallelCtx {
LVM *L;
LFunc *func;
_Atomic uint32_t finished;
};
static int threads_parallel_worker(void *arg) {
struct ThreadsParallelCtx *ctx = arg;
LRegSet regset = {};
lvm_reset_regs(&regset);
lvm_run(ctx->L, ctx->func, 0, &regset);
atomic_fetch_add(&ctx->finished, 1);
return 0;
}
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);
if(no == 0) {
return 0;
}
struct ThreadsParallelCtx ctx = {.L = lvm, .func = func, .finished = 0};
thrd_t thrds[no];
for(size_t i = 1; i < no; i++) {
thrd_create(&thrds[i], threads_parallel_worker, &ctx);
}
LRegSet set = {.parent = regset};
lvm_reset_regs(&set);
lvm_call(lvm, func, 0, heap, &set);
while(atomic_load(&ctx.finished) != no - 1) {
lvm->safepoint_func(lvm, heap, regset);
}
return 0;
}
struct ThreadsRunCtx {
LVM *L;
LFunc *func;
};
static int threads_run_worker(void *arg) {
struct ThreadsRunCtx *ctx = arg;
LRegSet regs = {};
lvm_reset_regs(&regs);
lvm_run(ctx->L, ctx->func, 0, &regs);
free(ctx);
return 0;
}
static size_t threads_run(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) {
LFunc *func = (LFunc*) (regset->regs[0].u & ~LTAG_MASK);
struct ThreadsRunCtx *ctx = calloc(1, sizeof(*ctx));
ctx->L = lvm;
ctx->func = func;
thrd_t thrd;
thrd_create(&thrd, threads_run_worker, ctx);
return 0;
}
static char* read_full_file(const char *fn) {
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';
if(fn) fclose(f);
return buf;
}
int main(int argc, char **argv) {
LTable *env = ltable_new(128);
ltable_set(env,
lvalue_from_string(lstring_newz("print")),
lvalue_from_func(lvm_func_from_native(native_print, NULL)));
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(threads,
lvalue_from_string(lstring_newz("run")),
lvalue_from_func(lvm_func_from_native(threads_run, 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)";
//const char *bufs = "z = 5 print(z)";
//const char *bufs = "local i = 0 while i ~= 1500000 do print(i) i = i + 1 end";
//const char *bufs = "for i = 1, 1000 do print(print) end";
char *bufs = read_full_file(argv[1]);
vec_Token toks = ltokenize(bufs, strlen(bufs));
free(bufs);
LUnit *unit = lparse(toks.size, toks.data, env);
lfreetoks(&toks);
//dump(unit->funcs[0].lua_instrs);
LVM lvm = {};
lvm_init(&lvm);
lvm.unit_count = 1;
lvm.units = calloc(1, sizeof(*lvm.units));
lvm.units[0] = unit;
LRegSet regset = {.parent = NULL};
lvm_reset_regs(&regset);
lvm_run(&lvm, &unit->funcs[0], 0, &regset);
lvm_destroy(&lvm);
}