diff --git a/Makefile b/Makefile index f944187..89bb4cc 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,10 @@ FLAGS=-g $(CFLAGS) $(LDFLAGS) $(LIBS) S=main.c S+=comp.c wayland.c glfw.c S+=vulkan.c kitty.c -S+=gpu_allocator.c hashmap.c util.c io.c matrix.c dynarray.c image.c types.c allocator.c log.c +S+=string.c gpu_allocator.c hashmap.c util.c io.c matrix.c dynarray.c image.c types.c allocator.c log.c S+=object.c register.c S+=Wayland/xdg-shell-protocol.c -S+=lang/ast.c lang/vstack.c +S+=lang/ast.c lang/vstack.c lang/parser.c lang/ast_disc.c lang/functable.c SO=$(addprefix build/,$(S:.c=.o)) SC=$(addprefix src/,$(S)) diff --git a/main.c b/main.c index e65bda0..a923d45 100644 --- a/main.c +++ b/main.c @@ -4,41 +4,49 @@ #include "trig.c" #include "src/lang/ast.h" +#include "src/lang/ast_disc.h" +#include "src/lang/parser.h" #include int main() { + struct PawAST *t = parse("./src/lang/test.paw"); + return 0; + struct PawAST *ast = ast_make(); ast_insert_property(ast, "i", make_pawval_int(ast->mem, 0)); ast_append_cfunc(ast, print); enum PawCtrl *body = make_pawctrl_seq(ast->mem); - pawseq_append(body, - make_pawctrl_asign( - ast->mem, PSV_P(ast_get_property(ast, "i")), - make_pawval_expr(ast->mem, ast_get_property(ast, "i"), - make_pawval_int(ast->mem, 1), op_add))); + pawseq_append(body, make_pawctrl_asign( + ast->mem, PSV_P(ast_get_property(ast, "i")), + make_pawval_expr(ast->mem, ast_get_property(ast, "i"), + make_pawval_int(ast->mem, 1), + paw_get_op_index("+")))); enum PawCtrl *truthy = make_pawctrl_seq(ast->mem); pawseq_append(truthy, make_pawctrl_spush(ast->mem, PSV_INT(0))); pawseq_append(truthy, make_pawctrl_asign(ast->mem, PSV_SP(0), ast_get_property(ast, "i"))); - pawseq_append(truthy, make_pawctrl_ccall(ast->mem, 0)); + pawseq_append(truthy, + make_pawctrl_ccall(ast->mem, paw_get_cfunc_index("io::print"))); pawseq_append(truthy, make_pawctrl_spop(ast->mem)); - pawseq_append(body, - make_pawctrl_if( - ast->mem, - make_pawval_expr(ast->mem, ast_get_property(ast, "i"), - make_pawval_int(ast->mem, 20), op_equals), - truthy, make_pawctrl_seq(ast->mem))); + pawseq_append(body, make_pawctrl_if( + ast->mem, + make_pawval_expr(ast->mem, ast_get_property(ast, "i"), + make_pawval_int(ast->mem, 20), + paw_get_op_index("==")), + truthy, make_pawctrl_seq(ast->mem))); pawseq_append( ast->prog, make_pawctrl_while(ast->mem, make_pawval_expr(ast->mem, ast_get_property(ast, "i"), - make_pawval_int(ast->mem, 1000000), - op_unequals), + make_pawval_int(ast->mem, 100), + paw_get_op_index("!=")), body)); + ast_write(ast, "test"); + ast = ast_read("test"); ast_exec(ast); return 0; diff --git a/src/allocator.c b/src/allocator.c index 75cb8f6..6f911f1 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -1,3 +1,4 @@ +#include "allocator.h" #include "log.h" #include @@ -21,9 +22,9 @@ struct Mem { }; struct Mem *make_mem(size_t size) { - struct Mem *mem = malloc(sizeof(struct Mem)); + struct Mem *mem = malloc(sizeof(struct Mem) + size); mem->mem_size = size; - mem->mem = malloc(mem->mem_size); + mem->mem = mem + 1; memset(mem->mem, 0, mem->mem_size); mem->count = 0; memset(&mem->allocs, 0, sizeof(struct Alloc) * MAX_ALLOCS); @@ -32,10 +33,7 @@ struct Mem *make_mem(size_t size) { mem->alloc = &mem->allocs[1]; return mem; } -void uninit_mem(struct Mem *mem) { - free(mem->mem); - free(mem); -} +void uninit_mem(struct Mem *mem) { free(mem); } static struct Alloc *get_next_alloc(struct Mem *mem) { while (mem->allocs[mem->count].start != NULL || @@ -49,6 +47,21 @@ static struct Alloc *get_next_alloc(struct Mem *mem) { return &mem->allocs[mem->count]; } +void *malloc_or_mem_malloc(struct Mem *mem, size_t size) { + if (mem == NULL) { + return malloc(size); + } else { + return mem_malloc(mem, size); + } +} +void free_or_mem_free(struct Mem *mem, void *ptr) { + if (mem == NULL) { + free(ptr); + } else { + mem_free(mem, ptr); + } +} + void *mem_malloc(struct Mem *mem, size_t size) { if (size <= 0) { size = 1; diff --git a/src/allocator.h b/src/allocator.h index e6d3ee9..e607bfa 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -3,12 +3,26 @@ #include "sys/types.h" -struct Mem; +#define MAX_ALLOCS 256 +struct Alloc { + void *start; + uint size; + struct Alloc *next; +}; +struct Mem { + void *mem; + size_t mem_size; + uint count; + struct Alloc *alloc; + struct Alloc allocs[MAX_ALLOCS]; +}; struct Mem *make_mem(size_t size); void uninit_mem(struct Mem *mem); void *mem_malloc(struct Mem *mem, size_t size); void mem_free(struct Mem *mem, void *p); +void *malloc_or_mem_malloc(struct Mem *mem, size_t size); +void free_or_mem_free(struct Mem *mem, void *ptr); #endif // INCLUDE_WAYLANDCLIENT_ALLOCATOR_H_ diff --git a/src/dynarray.h b/src/dynarray.h index bfc7c3f..b3c8645 100644 --- a/src/dynarray.h +++ b/src/dynarray.h @@ -4,6 +4,7 @@ #include "allocator.h" #include +#include #include #define dyn_array_append(array, item) \ diff --git a/src/io.c b/src/io.c index 4b5c2ea..218ce00 100644 --- a/src/io.c +++ b/src/io.c @@ -28,7 +28,7 @@ char *read_text_file(char *path) { uint32_t *read_binary_file(char *path, int *size) { FILE *file = fopen(path, "r"); if (file == NULL) { - meow("Could not open file %s", path); + meow("could not open file %s", path); return NULL; } fseek(file, 0, SEEK_END); @@ -45,3 +45,13 @@ uint32_t *read_binary_file(char *path, int *size) { fclose(file); return (uint32_t *)content; } + +void write_binary_file(char *path, char *data, int size) { + FILE *file = fopen(path, "w"); + if (file == NULL) { + meow("could not open file %s", path); + return; + } + fwrite(data, size, sizeof(char), file); + fclose(file); +} diff --git a/src/io.h b/src/io.h index 5a7c83e..348c09a 100644 --- a/src/io.h +++ b/src/io.h @@ -5,5 +5,6 @@ char *read_text_file(char *path); uint32_t *read_binary_file(char *path, int *size); +void write_binary_file(char *path, char *data, int size); #endif // INCLUDE_WAYLANDCLIENT_IO_H_ diff --git a/src/lang/ast.c b/src/lang/ast.c index c3b2136..90bcad7 100644 --- a/src/lang/ast.c +++ b/src/lang/ast.c @@ -6,8 +6,7 @@ const bool log_stack = false; -struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs) { +struct PawStackVal op_equals(struct PawStackVal lhs, struct PawStackVal rhs) { LS("comparing %s to %s", print_valtype(lhs.type), print_valtype(rhs.type)); switch (lhs.type) { case PAW_VAL_FLOAT: @@ -22,6 +21,7 @@ struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs, case PAW_VAL_FLOAT: return PSV_BOOL(lhs.i == rhs.f); case PAW_VAL_INT: + LS("%d == %d", lhs.i, rhs.i); return PSV_BOOL(lhs.i == rhs.i); } case PAW_VAL_BOOL: @@ -145,13 +145,34 @@ struct PawStackVal try_cast(enum PawVal target, enum PawVal *val) { return PSV_NULL; } -struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs) { - return PSV_BOOL(!op_equals(ast, lhs, rhs).b); +enum PawVal *ast_stack_to_heap(struct PawAST *ast, struct PawStackVal val) { + switch (val.type) { + case PAW_VAL_FLOAT: + return make_pawval_float(ast->mem, val.f); + case PAW_VAL_INT: + return make_pawval_int(ast->mem, val.i); + case PAW_VAL_BOOL: + return make_pawval_bool(ast->mem, val.b); + case PAW_VAL_CHAR: + crash("TODO"); + // return make_pawval_char(ast->mem, val.c); + case PAW_VAL_POINT: + return make_pawval_point(ast->mem, val.p); + case PAW_VAL_SPOINT: + crash("TODO"); + // return make_pawval_spoint(ast->mem, val.sp); + case PAW_VAL_EXPR: + crash("sdfgjhhkjdfgd"); + } + meow("unreachable"); + return NULL; } -struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs) { +struct PawStackVal op_unequals(struct PawStackVal lhs, struct PawStackVal rhs) { + return PSV_BOOL(!op_equals(lhs, rhs).b); +} + +struct PawStackVal op_add(struct PawStackVal lhs, struct PawStackVal rhs) { LS("adding %s to %s", print_valtype(lhs.type), print_valtype(rhs.type)); switch (lhs.type) { case PAW_VAL_FLOAT: @@ -166,6 +187,7 @@ struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs, case PAW_VAL_FLOAT: return PSV_FLOAT(lhs.i + rhs.f); case PAW_VAL_INT: + LS("%d + %d", lhs.i, rhs.i); return PSV_INT(lhs.i + rhs.i); } } @@ -223,7 +245,7 @@ enum PawVal *make_pawval_char(struct Mem *mem, char n) { } enum PawVal *make_pawval_expr(struct Mem *mem, enum PawVal *lhs, - enum PawVal *rhs, paw_p op) { + enum PawVal *rhs, uint32_t op) { enum PawVal *val; val_make(val, struct PawExpr, PAW_VAL_EXPR); struct PawExpr *i = val_get_data(val); @@ -323,17 +345,20 @@ void pawseq_append(enum PawCtrl *seq, enum PawCtrl *ctrl) { dyn_array_append(&seqval->seq, ctrl); } -void ping_func() { meow("ping"); } - struct PawAST *ast_make() { struct Mem *mem = make_mem(8192); + // ast HAS to be the first thing allocated with mem struct PawAST *ast = mem_malloc(mem, sizeof(struct PawAST)); + char *t = "meow\n"; + char *test = mem_malloc(mem, strlen(t) + 1); + memcpy(test, t, strlen(t) + 1); + ast->mem = mem; - ast->ping_func = ping_func; ast->prog = make_pawctrl_seq(ast->mem); dyn_array_create_inplace_mem(&ast->properties, ast->mem); dyn_array_create_inplace_mem(&ast->cfuncs, ast->mem); + dyn_array_create_inplace_mem(&ast->funcs, ast->mem); return ast; } @@ -343,6 +368,19 @@ void ast_append_cfunc(struct PawAST *ast, dyn_array_append(&ast->cfuncs, (struct CFunc){func}); } +void ast_register_func(struct PawAST *ast, char *name) { + dyn_array_append(&ast->funcs, ((struct PawFunc){.body = NULL, .name = name})); +} +void ast_set_func_body(struct PawAST *ast, char *name, enum PawCtrl *body) { + for (int i = 0; i < ast->funcs.count; i++) { + if (strcmp(name, ast->funcs.items[i].name) == 0) { + ast->funcs.items[i].body = body; + return; + } + } + meow("function %s could not be found", name); +} + enum PawVal *ast_get_property(struct PawAST *ast, char *name) { for (int i = 0; i < ast->properties.count; i++) { if (strcmp(ast->properties.items[i].name, name) == 0) { @@ -457,10 +495,12 @@ struct PawStackVal ast_eval(struct PawAST *ast, enum PawVal *val) { return PSV_CHAR(*(char *)val_get_data(val)); case PAW_VAL_EXPR:; struct PawExpr *expr = val_get_data(val); - LS("calling op at %p", expr->op); + LS("calling op at %d", expr->op); + LS("lhs is %p rhs is %p", expr->lhs, expr->rhs); struct PawStackVal lhs = ast_eval(ast, expr->lhs); struct PawStackVal rhs = ast_eval(ast, expr->rhs); - struct PawStackVal ret = expr->op(ast, lhs, rhs); + struct PawStackVal ret = ((struct PawStackVal(*)( + struct PawStackVal, struct PawStackVal))paw_get_op(expr->op))(lhs, rhs); return ret; break; } @@ -487,7 +527,17 @@ void ast_exec(struct PawAST *ast) { int offset = 0; ast_stack_push(stack, ast->prog); meow("starting exec"); +#define NO_LIMIT_ITS +#ifndef NO_LIMIT_ITS + int i = 0; +#endif while (stack->top < stack->right) { +#ifndef NO_LIMIT_ITS + i++; + if (i > 100) { + break; + } +#endif enum PawCtrl *ctrl = stack_poke(stack); switch (*ctrl) { case PAW_CTRL_SEQ:; diff --git a/src/lang/ast.h b/src/lang/ast.h index 0160454..d4c8ff4 100644 --- a/src/lang/ast.h +++ b/src/lang/ast.h @@ -1,3 +1,5 @@ +#ifndef INCLUDE_LANG_AST_H_ +#define INCLUDE_LANG_AST_H_ #include #include @@ -44,6 +46,14 @@ enum PawVal { PAW_VAL_SPOINT, PAW_VAL_EXPR, }; +enum ArgType { + PAW_ARG_FLOAT, + PAW_ARG_INT, + PAW_ARG_BOOL, + PAW_ARG_CHAR, + PAW_ARG_POINT, + PAW_ARG_ANY, +}; enum PawCtrl { PAW_CTRL_SEQ, @@ -66,18 +76,18 @@ struct PawProperty { dyn_array_define(da_paw_property, struct PawProperty); dyn_array_define(da_cfunc, struct CFunc); +dyn_array_define(da_func, struct PawFunc); struct PawAST { struct Mem *mem; enum PawCtrl *prog; - void *ping_func; struct da_paw_property properties; struct da_cfunc cfuncs; + struct da_func funcs; }; struct PawExpr { - struct PawStackVal (*op)(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs); + uint32_t op; enum PawVal *lhs; enum PawVal *rhs; }; @@ -121,11 +131,16 @@ struct PawStackPush { struct PawStackVal v; }; +struct PawFunc { + enum PawCtrl *body; + char *name; +}; + struct PawCall { enum PawCtrl *body; }; struct PawCCall { - int index; + uint32_t index; }; struct VStack { @@ -153,19 +168,16 @@ struct CFunc { void (*func)(struct VStack *stack, int offset); }; -struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs); -struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs); -struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs, - struct PawStackVal rhs); +struct PawStackVal op_equals(struct PawStackVal lhs, struct PawStackVal rhs); +struct PawStackVal op_unequals(struct PawStackVal lhs, struct PawStackVal rhs); +struct PawStackVal op_add(struct PawStackVal lhs, struct PawStackVal rhs); enum PawVal *make_pawval_float(struct Mem *mem, float n); enum PawVal *make_pawval_int(struct Mem *mem, int n); enum PawVal *make_pawval_bool(struct Mem *mem, bool n); enum PawVal *make_pawval_point(struct Mem *mem, paw_p n); enum PawVal *make_pawval_expr(struct Mem *mem, enum PawVal *lhs, - enum PawVal *rhs, paw_p op); + enum PawVal *rhs, uint32_t op); void free_pawval(struct Mem *mem, enum PawVal *val); enum PawCtrl *make_pawctrl_seq(struct Mem *mem); enum PawCtrl *make_pawctrl_spush(struct Mem *mem, struct PawStackVal val); @@ -179,7 +191,7 @@ enum PawCtrl *make_pawctrl_if(struct Mem *mem, enum PawVal *cond, enum PawCtrl *make_pawctrl_asign(struct Mem *mem, struct PawStackVal target, enum PawVal *val); void pawseq_append(enum PawCtrl *seq, enum PawCtrl *ctrl); -void ping_func(); +enum PawVal *ast_stack_to_heap(struct PawAST *ast, struct PawStackVal val); struct PawAST *ast_make(); void ast_insert_property(struct PawAST *ast, char *name, enum PawVal *val); void ast_append_cfunc(struct PawAST *ast, @@ -200,3 +212,12 @@ void ast_exec(struct PawAST *ast); $ret = mem_malloc(mem, sizeof(enum PawCtrl) + sizeof($type)); \ *$ret = $TYPE_ENUM; \ } while (0) + +uint32_t paw_get_ops_size(); +const char *paw_get_op_sym(uint32_t index); +uint32_t paw_get_op_index(char *sym); +void *paw_get_op(uint32_t); +uint32_t paw_get_cfunc_index(char *name); +void *paw_get_cfunc(uint32_t); + +#endif // INCLUDE_LANG_AST_H_ diff --git a/src/lang/ast_disc.c b/src/lang/ast_disc.c new file mode 100644 index 0000000..21d3a6b --- /dev/null +++ b/src/lang/ast_disc.c @@ -0,0 +1,227 @@ +#include "ast_disc.h" + +#include "../io.h" +#include "../log.h" +#include "ast.h" + +#define AO1($p) \ + if (apply_before && \ + ((void *)($p) >= region_start && (void *)($p) <= region_end)) { \ + $p = (void *)((void *)$p + offset); \ + } +#define AO2($p) \ + if (!apply_before && \ + ((void *)$p >= region_start && (void *)$p <= region_end)) { \ + $p = (void *)((void *)$p + offset); \ + } + +long offset = 0; + +void *region_start = NULL; +void *region_end = NULL; +bool apply_before = false; + +// for nyow ast and ast->mem will be garbled afterwards +void ast_write(struct PawAST *ast, char *path) { + int size = ast->mem->mem_size + sizeof(struct Mem); + char *data = (char *)ast->mem; + meow("size is %d data %p", size, data); + region_start = ast->mem; + region_end = ast->mem + ast->mem->mem_size + sizeof(struct Mem); + offset = -(long)region_start; + apply_before = false; + AO2(ast->mem->alloc); + AO2(ast->mem->mem); + for (int i = 0; i < MAX_ALLOCS; i++) { + if (ast->mem->allocs[i].start == NULL && ast->mem->allocs[i].size == 0 && + ast->mem->allocs[i].next == NULL) { + continue; + } else { + AO2(ast->mem->allocs[i].start); + AO2(ast->mem->allocs[i].next); + } + } + AO2(ast->mem); + apply_offset_ctrl(ast->prog); + AO2(ast->prog); + for (int i = 0; i < ast->properties.count; i++) { + AO2(ast->properties.items[i].name); + apply_offset_val(ast->properties.items[i].val); + AO2(ast->properties.items[i].val); + meow("a property is now at %p", ast->properties.items[i].val); + } + AO2(ast->properties.items); + AO2(ast->properties.mem); + + AO2(ast->cfuncs.items); + AO2(ast->cfuncs.mem); + + for (int i = 0; i < ast->funcs.count; i++) { + AO2(ast->funcs.items[i].name); + apply_offset_ctrl(ast->funcs.items[i].body); + AO2(ast->funcs.items[i].body); + } + AO2(ast->funcs.items); + AO2(ast->funcs.mem); + + write_binary_file(path, data, size); +} + +// assumes all PawStackVals existent at compile time of type PAW_VAL_POINT point +// to a valid PawVal +struct PawAST *ast_read(char *path) { + region_start = 0x0; + int size; + char *data = (char *)read_binary_file(path, &size); + meow("size is %d data %p", size, data); + offset = (long)data; + region_end = (void *)(long)size; + struct Mem *mem = (struct Mem *)data; + + meow("offset is %ld", offset); + + apply_before = true; + for (int i = 0; i < MAX_ALLOCS; i++) { + if (mem->allocs[i].start == NULL && mem->allocs[i].size == 0 && + mem->allocs[i].next == NULL) { + continue; + } else { + AO1(mem->allocs[i].start); + AO1(mem->allocs[i].next); + } + } + meow("mem before %p", mem->mem); + AO1(mem->mem); + meow("mem after %p", mem->mem); + AO1(mem->alloc); + struct PawAST *ast = mem->allocs[2].start; + AO1(ast->mem); + AO1(ast->prog); + apply_offset_ctrl(ast->prog); + meow("ao1 %p", ast->prog); + AO1(ast->properties.items); + AO1(ast->properties.mem); + for (int i = 0; i < ast->properties.count; i++) { + meow("a property was at %p", ast->properties.items[i].val); + AO1(ast->properties.items[i].name); + AO1(ast->properties.items[i].val); + apply_offset_val(ast->properties.items[i].val); + meow("a property is now at %p", ast->properties.items[i].val); + } + + AO1(ast->cfuncs.items); + AO1(ast->cfuncs.mem); + + AO1(ast->funcs.items); + AO1(ast->funcs.mem); + for (int i = 0; i < ast->funcs.count; i++) { + AO1(ast->funcs.items[i].name); + AO1(ast->funcs.items[i].body); + apply_offset_ctrl(ast->funcs.items[i].body); + } + + return ast; +} + +void apply_offset_ctrl(enum PawCtrl *ctrl) { + switch (*ctrl) { + case PAW_CTRL_SEQ:; + struct PawSeq *seq = ctrl_get_data(ctrl); + AO1(seq->seq.mem); + AO1(seq->seq.items); + for (int i = 0; i < seq->seq.count; i++) { + AO1(seq->seq.items[i]); + apply_offset_ctrl(seq->seq.items[i]); + AO2(seq->seq.items[i]); + } + AO2(seq->seq.items); + AO2(seq->seq.mem); + break; + case PAW_CTRL_WHILE:; + struct PawWhile *_while = ctrl_get_data(ctrl); + AO1(_while->body); + apply_offset_ctrl(_while->body); + AO2(_while->body); + AO1(_while->cond); + apply_offset_val(_while->cond); + AO2(_while->cond); + break; + case PAW_CTRL_IF:; + struct PawIf *_if = ctrl_get_data(ctrl); + AO1(_if->truthy); + AO1(_if->falsy); + apply_offset_ctrl(_if->truthy); + apply_offset_ctrl(_if->falsy); + AO2(_if->truthy); + AO2(_if->falsy); + AO1(_if->cond); + apply_offset_val(_if->cond); + AO2(_if->cond); + break; + case PAW_CTRL_ASIGN:; + struct PawAsign *asign = ctrl_get_data(ctrl); + AO1(asign->rhs); + apply_offset_val(asign->rhs); + AO2(asign->rhs); + asign->lhs = apply_offset_stackval(asign->lhs); + break; + case PAW_CTRL_SPUSH: + break; + case PAW_CTRL_SPOP: + break; + case PAW_CTRL_CALL:; + struct PawCall *call = ctrl_get_data(ctrl); + AO1(call->body); + apply_offset_ctrl(call->body); + AO2(call->body); + break; + case PAW_CTRL_CCALL: + break; + } +} +struct PawStackVal apply_offset_stackval(struct PawStackVal val) { + switch (val.type) { + case PAW_VAL_FLOAT: + case PAW_VAL_INT: + case PAW_VAL_BOOL: + case PAW_VAL_CHAR: + case PAW_VAL_SPOINT: + return val; + case PAW_VAL_EXPR: + meow("AGHJKGHJKASZGHJKASGHJKGHJK"); + return (struct PawStackVal){.type = PAW_VAL_POINT, .p = NULL}; + case PAW_VAL_POINT: + AO1(val.p); + apply_offset_val(val.p); + AO2(val.p); + return val; + } +} +void apply_offset_val(enum PawVal *val) { + switch (*val) { + case PAW_VAL_FLOAT: + break; + case PAW_VAL_INT: + break; + case PAW_VAL_BOOL: + break; + case PAW_VAL_CHAR: + break; + case PAW_VAL_POINT: + meow("uuuh this should not happen i thinky?"); + apply_offset_val(*(enum PawVal **)val_get_data(val)); + break; + case PAW_VAL_SPOINT: + break; + case PAW_VAL_EXPR:; + struct PawExpr *expr = val_get_data(val); + AO1(expr->lhs); + AO1(expr->rhs); + apply_offset_val(expr->lhs); + apply_offset_val(expr->rhs); + AO2(expr->lhs); + AO2(expr->rhs); + meow("applying offset to an expr"); + break; + } +} diff --git a/src/lang/ast_disc.h b/src/lang/ast_disc.h new file mode 100644 index 0000000..b53f388 --- /dev/null +++ b/src/lang/ast_disc.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_LANG_AST_DISC_H_ +#define INCLUDE_LANG_AST_DISC_H_ + +#include "ast.h" + +void ast_write(struct PawAST *ast, char *path); +struct PawAST *ast_read(char *path); +void apply_offset_ctrl(enum PawCtrl *ctrl); +void apply_offset_val(enum PawVal *val); +struct PawStackVal apply_offset_stackval(struct PawStackVal val); + +#endif // INCLUDE_LANG_AST_DISC_H_ diff --git a/src/lang/functable.c b/src/lang/functable.c new file mode 100644 index 0000000..8f0ca5d --- /dev/null +++ b/src/lang/functable.c @@ -0,0 +1,49 @@ +#include "../log.h" +#include "../util.h" +#include "ast.h" + +struct FuncDef { + void (*func)(struct VStack *, int); + const char *name; + // enum ArgType *args; +}; +struct OpDef { + struct PawStackVal (*op)(struct PawStackVal, struct PawStackVal); + const char *sym; + // enum ArgType *args; +}; + +struct FuncDef PAW_CFUNCS[] = { + {print, "io::print"}, +}; + +// important to unimportant!!! +struct OpDef PAW_OPS[] = { + {op_equals, "=="}, {op_unequals, "!="}, {NULL, "*"}, + {NULL, "/"}, {op_add, "+"}, {NULL, "-"}, +}; + +uint32_t paw_get_ops_size() { return sizeof(PAW_OPS); } +const char *paw_get_op_sym(uint32_t index) { return PAW_OPS[index].sym; } + +uint32_t paw_get_op_index(char *sym) { + for (int i = 0; i < sizeof(PAW_OPS) / sizeof(PAW_OPS[0]); i++) { + if (strcmp(sym, PAW_OPS[i].sym) == 0) { + return i; + } + } + meow("could not find op %s, returning %d", sym, UINT32_NULL); + return UINT32_NULL; +} +void *paw_get_op(uint32_t index) { return PAW_OPS[index].op; } + +uint32_t paw_get_cfunc_index(char *name) { + for (int i = 0; i < sizeof(PAW_CFUNCS) / sizeof(PAW_CFUNCS[0]); i++) { + if (strcmp(name, PAW_CFUNCS[i].name) == 0) { + return i; + } + } + meow("could not find cfunc %s, returning %d", name, UINT32_NULL); + return UINT32_NULL; +} +void *paw_get_cfunc(uint32_t index) { return PAW_CFUNCS[index].func; } diff --git a/src/lang/parser.c b/src/lang/parser.c new file mode 100644 index 0000000..e7a2e2c --- /dev/null +++ b/src/lang/parser.c @@ -0,0 +1,167 @@ +#include "../allocator.h" +#include "../io.h" +#include "../log.h" +#include "../string.h" +#include "../util.h" +#include "ast.h" +#include + +#include "parser.h" + +struct PawStackVal parse_stack_val(char *start) { + start = trim_start(start); + if (start_matches(start, "true")) { + return PSV_BOOL(true); + } + if (start_matches(start, "false")) { + return PSV_BOOL(false); + } + if (start_matches(start, "null")) { + return PSV_NULL; + } + char *end = start; + + while (is_digid(*end) || *end == '.') { + end++; + } + + if (includes_between(start, end, '.')) { + return PSV_FLOAT(strtof(start, NULL)); + } else { + return PSV_INT(strtol(start, NULL, 10)); + } +} + +enum PawVal *parse_val(int stack_offset, struct StringTable *vars, + struct Mem *tmp, struct Mem *pem, char *start, + char *end) { + start = trim_start(start); + end = trim_end(end); + + // figure out the most important op + char *opstart = start; + int op_rating = INT_MAX; + char *op = NULL; + + // as * before + in functable it will choose to split on + first, meaning + // a+b*c => (a)+(b*c) + while (opstart < end) { + if (*opstart == '(') { + opstart = skip_brackets(opstart, '(', ')'); + continue; + } + for (int i = 0; i < paw_get_ops_size(); i++) { + if (start_matches(opstart, (char *)paw_get_op_sym(i))) { + if (i >= op_rating) { + continue; + } + op_rating = i; + op = opstart; + } + } + opstart++; + } + + if (op == 0) { + } + + enum PawVal *lhs; + // expected: var, brackets or function + if (start_matches(start, "(")) { + char *in_end = skip_brackets(start, '(', ')'); + lhs = parse_val(stack_offset, vars, tmp, pem, start + 1, in_end); + start = in_end; + } else { + char *tmp = start; + while (is_char(*tmp)) { + tmp++; + } + tmp = trim_start(tmp); + if (*tmp == '(') { + // TODO, call + } else { + // TODO, var + } + } + start = trim_start(start); + if (start == end) { + return lhs; + } +} + +enum PawCtrl *parse_block(struct Mem *tmp, struct Mem *pem, + struct StringTable *vars, char *start) { + enum PawCtrl *body = make_pawctrl_seq(pem); + start = trim_start(start); + while (!start_matches(start, "}")) { + if (start_matches(start, "while")) { + start = skip_after_char(start, ' '); + char *end = skip_to_char(start, '{') - 1; + enum PawVal *cond = parse_val(0, vars, tmp, pem, start, end); + enum PawCtrl *wbody = + parse_block(tmp, pem, vars, skip_after_char(start, '{')); + enum PawCtrl *w = make_pawctrl_while(pem, cond, wbody); + pawseq_append(body, w); + start = skip_brackets(start, '{', '}'); + start = trim_start(start); + continue; + } + if (start_matches(start, "if")) { + start = skip_after_char(start, ' '); + char *end = skip_to_char(start, '{') - 1; + enum PawVal *cond = parse_val(0, vars, tmp, pem, start, end); + enum PawCtrl *truthy = + parse_block(tmp, pem, vars, skip_after_char(start, '{')); + enum PawCtrl *falsy = NULL; + start = skip_brackets(start, '{', '}'); + if (start_matches(start, "else")) { + start = skip_after_char(start, '{'); + falsy = parse_block(tmp, pem, vars, start); + start = skip_brackets(start, '{', '}'); + } + enum PawCtrl *i = make_pawctrl_if(pem, cond, truthy, falsy); + pawseq_append(body, i); + start = trim_start(start); + continue; + } + } +} + +// start has to start with func asdjlasd(dfssdf)->jsd +enum PawCtrl *parse_func(char *start) { skip_to_char(start, ' '); } + +struct PawAST *parse(char *path) { + char *contents = read_text_file(path); + struct PawAST *ast = ast_make(); + + struct Mem *tmp = make_mem(4096); // temporary memory + struct Mem *pem = + ast->mem; // permanent memory, will be present once ast is evaled + + struct StringTable *methods = st_make(tmp); + struct StringTable *props = st_make(tmp); + + for (int i = 0; i < strlen(contents); i++) { + if (start_matches(&contents[i], "func ")) { + char *name = extract_inbetween_chars(tmp, &contents[i], ' ', '('); + meow("got a method named '%s'", name); + st_insert(methods, name, &contents[i]); + i = skip_brackets(&contents[i], '{', '}') - contents; + } else if (start_matches(&contents[i], "let")) { + char *name = extract_inbetween_chars(tmp, &contents[i], ' ', ':'); + meow("got a property named '%s'", name); + st_insert(props, name, NULL); + } + } + + for (int i = 0; i < st_get_size(props); i++) { + ast_insert_property( + ast, mem_strdup(st_get_nth_key(props, i), pem), + ast_stack_to_heap( + ast, parse_stack_val(st_get(props, st_get_nth_key(props, i))))); + } + + uninit_mem(tmp); + + return ast; +} diff --git a/src/lang/parser.h b/src/lang/parser.h new file mode 100644 index 0000000..10338b0 --- /dev/null +++ b/src/lang/parser.h @@ -0,0 +1,8 @@ +#ifndef INCLUDE_LANG_PARSER_H_ +#define INCLUDE_LANG_PARSER_H_ + +#include "ast.h" + +struct PawAST *parse(char *path); + +#endif // INCLUDE_LANG_PARSER_H_ diff --git a/src/lang/test.paw b/src/lang/test.paw new file mode 100644 index 0000000..c6c855a --- /dev/null +++ b/src/lang/test.paw @@ -0,0 +1,17 @@ +let count: int = 0; + +func make() -> void { + let b: int = 5; + while i != self.count { + if i == b { + io::print(i); + } + i = i + 1; + } +} + +func tick() -> void { +} + +func free() -> void { +} diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..5d0a2b8 --- /dev/null +++ b/src/string.c @@ -0,0 +1,183 @@ +#include "string.h" +#include "allocator.h" +#include "log.h" +#include "util.h" + +#include +#include +#include + +struct da_string split(struct Mem *mem, char *string, char needle, int *count) { + struct da_string items; + dyn_array_create_inplace_mem(&items, mem); + + int last = 0; + for (int i = 0; i < strlen(string); i++) { + + if (string[i] == needle) { + char *tmp = mem_malloc(mem, i - last + 1); + memcpy(tmp, &string[last], i - last); + tmp[last - i + 1] = 0x0; + dyn_array_append(&items, tmp); + last = i; + } + } + + return items; +} + +bool start_matches(char *string, char *match) { + return memcmp(string, match, strlen(match)) == 0; +} + +char *extract_brackets(struct Mem *mem, char *start, char open, char close) { + char *end = skip_brackets(start, open, close); + // { ... } + // ^ end + end -= 2; + // { ... } + // ^ end + while (*start != open) { + start++; + } + // { ... } + // start ^ ^ end + start++; + char *res = mem_malloc(mem, end - start + 1); + memcpy(res, start, end - start); + res[end - start] = 0x0; + + return res; +} + +char *skip_brackets(char *start, char open, char close) { + char *end = start; + while (end[0] != open) { + end++; + } + end++; + + int count = 1; + while (count > 0) { + if (end[0] == close) { + count--; + } else if (end[0] == open) { + count++; + } + end++; + } + + return end; +} + +int index_of_char(char *string, char key) { + int i = 0; + while (i < strlen(string) && string[i] != key) { + i++; + } + if (i == strlen(string)) { + return -1; + } else { + return i; + } +} + +char *extract(struct Mem *mem, char *string, int start, int size) { + char *new = mem_malloc(mem, size + 1); + memcpy(new, string + start, size); + new[size + 1] = 0x0; + return new; +} + +char *extract_inbetween_chars(struct Mem *mem, char *string, char one, + char two) { + int start = index_of_char(string, one) + 1; + int end = index_of_char(string, two); + if (end < start) { + SWAP(start, end); + } + + return extract(mem, string, start, end - start); +} + +char *tmp_format(struct Mem *mem, char *format, ...) { + char *res = malloc(1024); + va_list ap; + va_start(ap, NULL); + vsprintf(res, format, ap); + + char *new = mem_malloc(mem, (strlen(res) + 1) * sizeof(char)); + memcpy(new, res, (strlen(res) + 1) * sizeof(char)); + + free(res); + return new; +} + +char *trim_start(char *string) { + while (*string == ' ' || *string == '\n') { + string++; + } + return string; +} + +char *trim_end(char *string) { + while (*string == ' ' || *string == '\n') { + string--; + } + return string; +} + +// dont judge :( +bool is_digid(char n) { + if (n == '0' || n == '1' || n == '2' || n == '3' || n == '4' || n == '5' || + n == '6' || n == '7' || n == '8' || n == '9') { + return true; + } else { + return false; + } +} +bool is_char(char n) { + // 65 A, 90 Z, 97 a, 122 z + if (n >= 65 && n <= 90 || n >= 97 && n <= 122) { + return true; + } else { + return false; + } +} + +bool includes_between(char *start, char *end, char n) { + while (*start != n && start <= end) { + start++; + } + if (*start == n) { + return true; + } else { + return false; + } +} + +char *mem_strdup(char *string, struct Mem *mem) { + char *new = mem_malloc(mem, (strlen(string) + 1) * sizeof(char)); + memcpy(new, string, (strlen(string) + 1) * sizeof(char)); + return new; +} + +char *mem_strdup_reg(char *start, char *end, struct Mem *mem) { + char *new = mem_malloc(mem, end - start + 1); + memcpy(new, start, end - start); + new[end - start + 1] = 0x0; + return new; +} + +char *skip_to_char(char *string, char n) { + while (*string != n) { + string++; + } + return string; +} +char *skip_after_char(char *string, char n) { + while (*string != n) { + string++; + } + return string + 1; +} diff --git a/src/string.h b/src/string.h new file mode 100644 index 0000000..02de9a3 --- /dev/null +++ b/src/string.h @@ -0,0 +1,28 @@ +#ifndef INCLUDE_SRC_STRING_H_ +#define INCLUDE_SRC_STRING_H_ + +#include "allocator.h" +#include "dynarray.h" + +#include + +struct da_string split(struct Mem *mem, char *string, char needle, int *count); +bool start_matches(char *string, char *match); +char *extract_brackets(struct Mem *mem, char *start, char open, char close); +char *skip_brackets(char *start, char open, char close); +int index_of_char(char *string, char key); +char *extract(struct Mem *mem, char *string, int start, int size); +char *extract_inbetween_chars(struct Mem *mem, char *string, char one, + char two); +char *tmp_format(struct Mem *mem, char *format, ...); +char *trim_start(char *string); +char *trim_end(char *string); +bool is_digid(char n); +bool is_char(char n); +bool includes_between(char *start, char *end, char n); +char *mem_strdup(char *string, struct Mem *mem); +char *mem_strdup_reg(char *start, char *end, struct Mem *mem); +char *skip_to_char(char *string, char n); +char *skip_after_char(char *string, char n); + +#endif // INCLUDE_SRC_STRING_H_ diff --git a/src/util.c b/src/util.c index 83f2786..55fd8fb 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1,89 @@ +#include "allocator.h" +#include "dynarray.h" +#include #include float randf() { return (float)rand() / (float)RAND_MAX; } + +struct ST_key { + char *key; + void *value; +}; + +dyn_array_define(da_ST_key, struct ST_key); + +struct StringTable { + struct da_ST_key keys; +}; + +struct StringTable *st_make(struct Mem *mem) { + struct StringTable *st = + malloc_or_mem_malloc(mem, sizeof(struct StringTable)); + if (mem == NULL) { + dyn_array_create_inplace(&st->keys); + } else { + dyn_array_create_inplace_mem(&st->keys, mem); + } + return st; +} +struct StringTable *st_dup(struct StringTable *st) { + struct StringTable *new = + malloc_or_mem_malloc(st->keys.mem, sizeof(struct StringTable)); + new->keys.mem = st->keys.mem; + new->keys.count = st->keys.count; + new->keys.capacity = st->keys.capacity; + new->keys.items = malloc_or_mem_malloc(new->keys.mem, sizeof(struct ST_key) * + new->keys.capacity); + memcpy(new->keys.items, st->keys.items, + st->keys.capacity * sizeof(struct ST_key)); + + return new; +} +void st_insert(struct StringTable *st, char *key, void *value) { + dyn_array_append(&st->keys, ((struct ST_key){.key = key, .value = value})); +} +bool st_has_key(struct StringTable *st, char *key) { + for (int i = 0; i < st->keys.count; i++) { + if (strcmp(st->keys.items[i].key, key) == 0) { + return true; + } + } + return false; +} +bool st_has_value(struct StringTable *st, void *value) { + for (int i = 0; i < st->keys.count; i++) { + if (st->keys.items[i].value == value) { + return true; + } + } + return false; +} + +void *st_get(struct StringTable *st, char *key) { + for (int i = 0; i < st->keys.count; i++) { + if (strcmp(st->keys.items[i].key, key) == 0) { + return st->keys.items[i].value; + } + } + return NULL; +} +void st_remove(struct StringTable *st, char *key) { + for (int i = 0; i < st->keys.count; i++) { + if (strcmp(st->keys.items[i].key, key) == 0) { + dyn_array_remove(&st->keys, i); + } + } +} +void st_unmake(struct StringTable *st) { + if (st->keys.mem == NULL) { + dyn_array_destroy(&st->keys); + free(st); + } else { + dyn_array_destroy(&st->keys); + mem_free(st->keys.mem, st); + } +} +int st_get_size(struct StringTable *st) { return st->keys.count; } +char *st_get_nth_key(struct StringTable *st, int index) { + return st->keys.items[index].key; +} diff --git a/src/util.h b/src/util.h index 9fd0072..def4017 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,28 @@ #ifndef INCLUDE_ENGINE_UTIL_H_ #define INCLUDE_ENGINE_UTIL_H_ +#define UINT32_NULL 42424242 + float randf(); +#define SWAP($a, $b) \ + do { \ + void *tmp = alloca(sizeof($a)); \ + memcpy(tmp, &$a, sizeof($a)); \ + $a = $b; \ + memcpy(&$b, tmp, sizeof($b)); \ + } while (0) + +struct StringTable; +struct StringTable *st_make(struct Mem *mem); +struct StringTable *st_dup(struct StringTable *st); +void st_insert(struct StringTable *st, char *key, void *value); +bool st_has_key(struct StringTable *st, char *key); +void *st_get(struct StringTable *st, char *key); +bool st_has_value(struct StringTable *st, void *value); +void st_remove(struct StringTable *st, char *key); +void st_unmake(struct StringTable *st); +int st_get_size(struct StringTable *st); +char *st_get_nth_key(struct StringTable *st, int index); + #endif // INCLUDE_ENGINE_UTIL_H_