diff --git a/Makefile b/Makefile index f619f98..6ed2d19 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ 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+=object.c register.c S+=Wayland/xdg-shell-protocol.c +S+=lang/ast.c SO=$(addprefix build/,$(S:.c=.o)) SC=$(addprefix src/,$(S)) @@ -20,6 +21,7 @@ clean: rm -rf build/ mkdir build mkdir build/Wayland + mkdir build/lang install: ./main diff --git a/main.c b/main.c index 68c6fc0..a7e1d6c 100644 --- a/main.c +++ b/main.c @@ -3,9 +3,32 @@ #include "src/register.h" #include "trig.c" +#include "src/lang/ast.h" + #include int main() { + + struct PawAST *ast = ast_make(); + ast_insert_property(ast, "i", make_pawval_int(ast->mem, 0)); + + enum PawCtrl *body = make_pawctrl_seq(ast->mem); + pawctrl_append(body, make_pawctrl_call(ast->mem, ping_func)); + pawctrl_append(body, + make_pawctrl_asign( + ast->mem, ast_get_property(ast, "i"), + make_pawval_expr(ast->mem, ast_get_property(ast, "i"), + make_pawval_int(ast->mem, 1), op_add))); + pawctrl_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), + body)); + ast_exec(ast); + return 0; + struct Vk *vk; cat_Comp *state = cat_comp_init("meooow", 500, 500, &vk); diff --git a/src/allocator.c b/src/allocator.c index f5e6c2f..75cb8f6 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -64,10 +64,10 @@ void *mem_malloc(struct Mem *mem, size_t size) { next, }; prev->next = new; - meow("MALLOC %p:%ld, size %zu, prev is %p:%ld, size %u", new->start, + /*meow("MALLOC %p:%ld, size %zu, prev is %p:%ld, size %u", new->start, new - mem->allocs, size, prev->start, prev - mem->allocs, prev->size); - /* print_backtrace(); */ + print_backtrace(); */ return new->start; } else { prev = next; @@ -94,7 +94,7 @@ void mem_free(struct Mem *mem, void *p) { if (index < mem->count) { mem->count = index; } - meow("FREE at %d : %p", index, current->start); - /* print_backtrace(); */ + /*meow("FREE at %d : %p", index, current->start); + print_backtrace(); */ memset(&mem->allocs[index], 0, sizeof(struct Alloc)); } diff --git a/src/dynarray.h b/src/dynarray.h index 4146738..bfc7c3f 100644 --- a/src/dynarray.h +++ b/src/dynarray.h @@ -4,6 +4,7 @@ #include "allocator.h" #include +#include #define dyn_array_append(array, item) \ do { \ diff --git a/src/lang/ast.c b/src/lang/ast.c new file mode 100644 index 0000000..cbb8795 --- /dev/null +++ b/src/lang/ast.c @@ -0,0 +1,347 @@ +#include +#include + +#include "../log.h" +#include "ast.h" + +enum PawVal *op_equals(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { + if (*lhs == PAW_VAL_BOOL && *rhs == PAW_VAL_BOOL) { + if (*(bool *)val_get_data(lhs) == *(bool *)val_get_data(rhs)) { + return make_pawval_bool(ast->mem, true); + } else { + return make_pawval_bool(ast->mem, false); + } + } + float l; + float r; + if (*lhs == PAW_VAL_FLOAT) { + l = *(float *)val_get_data(lhs); + } else if (*lhs == PAW_VAL_INT) { + l = *(int *)val_get_data(lhs); + } + if (*rhs == PAW_VAL_FLOAT) { + r = *(float *)val_get_data(rhs); + } else if (*rhs == PAW_VAL_INT) { + r = *(int *)val_get_data(rhs); + } + if (l == r) { + return make_pawval_bool(ast->mem, true); + } else { + return make_pawval_bool(ast->mem, false); + } +} + +enum PawVal *op_unequals(struct PawAST *ast, enum PawVal *lhs, + enum PawVal *rhs) { + enum PawVal *res = op_equals(ast, lhs, rhs); + *(bool *)val_get_data(res) = !*(bool *)val_get_data(res); + return res; +} + +enum PawVal *op_add(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { + return make_pawval_int(ast->mem, + *(int *)val_get_data(lhs) + *(int *)val_get_data(rhs)); +} + +enum PawVal *make_pawval_float(struct Mem *mem, float n) { + enum PawVal *val; + val_make(val, float, PAW_VAL_FLOAT); + float *f = val_get_data(val); + *f = n; + return val; +} + +enum PawVal *make_pawval_int(struct Mem *mem, int n) { + enum PawVal *val; + val_make(val, int, PAW_VAL_INT); + int *i = (int *)val_get_data(val); + *i = n; + return val; +} + +enum PawVal *make_pawval_bool(struct Mem *mem, bool n) { + enum PawVal *val; + val_make(val, bool, PAW_VAL_BOOL); + bool *i = val_get_data(val); + *i = n; + return val; +} + +enum PawVal *make_pawval_point(struct Mem *mem, paw_p n) { + enum PawVal *val; + val_make(val, paw_p, PAW_VAL_INT); + paw_p *i = val_get_data(val); + *i = n; + return val; +} + +enum PawVal *make_pawval_expr(struct Mem *mem, enum PawVal *lhs, + enum PawVal *rhs, paw_p op) { + enum PawVal *val; + val_make(val, struct PawExpr, PAW_VAL_EXPR); + struct PawExpr *i = val_get_data(val); + i->op = op; + i->lhs = lhs; + i->rhs = rhs; + return val; + *i = (struct PawExpr){ + .op = op, + .lhs = lhs, + .rhs = rhs, + }; + return val; +} + +enum PawVal *make_pawval_func(struct Mem *mem) { + enum PawVal *val; + val_make(val, struct PawFunc, PAW_VAL_FUNC); + struct PawFunc *i = val_get_data(val); + return val; +} + +void free_pawval(struct Mem *mem, enum PawVal *val) { + switch (*val) { + case PAW_VAL_FLOAT: + case PAW_VAL_INT: + case PAW_VAL_BOOL: + case PAW_VAL_POINT: + mem_free(mem, val); + break; + case PAW_VAL_FUNC: + crash("todo"); + break; + case PAW_VAL_EXPR:; + struct PawExpr *expr = val_get_data(val); + free_pawval(mem, expr->lhs); + free_pawval(mem, expr->rhs); + mem_free(mem, val); + break; + } +} + +enum PawCtrl *make_pawctrl_seq(struct Mem *mem) { + enum PawCtrl *ctrl; + ctrl_make(ctrl, struct PawSeq, PAW_CTRL_SEQ); + struct PawSeq *i = ctrl_get_data(ctrl); + dyn_array_create_inplace_mem(&i->seq, mem); + return ctrl; +} + +enum PawCtrl *make_pawctrl_call(struct Mem *mem, paw_p addr) { + enum PawCtrl *ctrl; + ctrl_make(ctrl, struct PawCall, PAW_CTRL_CALL); + struct PawCall *i = ctrl_get_data(ctrl); + i->addr = addr; + return ctrl; +} + +enum PawCtrl *make_pawctrl_while(struct Mem *mem, enum PawVal *cond, + enum PawCtrl *body) { + enum PawCtrl *ctrl; + ctrl_make(ctrl, struct PawWhile, PAW_CTRL_WHILE); + struct PawWhile *i = ctrl_get_data(ctrl); + i->body = body; + i->cond = cond; + return ctrl; +} + +enum PawCtrl *make_pawctrl_asign(struct Mem *mem, enum PawVal *target, + enum PawVal *val) { + enum PawCtrl *ctrl; + ctrl_make(ctrl, struct PawAsign, PAW_CTRL_ASIGN); + struct PawAsign *i = ctrl_get_data(ctrl); + i->lhs = target; + i->rhs = val; + return ctrl; +} + +void pawctrl_append(enum PawCtrl *seq, enum PawCtrl *ctrl) { + struct PawSeq *seqval = ctrl_get_data(seq); + dyn_array_append(&seqval->seq, ctrl); +} + +void ping_func() { meow("ping"); } + +struct PawAST *ast_make() { + struct Mem *mem = make_mem(8192); + struct PawAST *ast = mem_malloc(mem, sizeof(struct PawAST)); + + ast->mem = mem; + ast->ping_func = ping_func; + ast->prog = make_pawctrl_seq(ast->mem); + dyn_array_create_inplace_mem(&ast->properties, ast->mem); + + return ast; +} + +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) { + return ast->properties.items[i].val; + } + } + meow("could not find property %s", name); + return NULL; +} + +void ast_insert_property(struct PawAST *ast, char *name, enum PawVal *val) { + dyn_array_append(&ast->properties, ((struct PawProperty){name, val})); +} + +struct Stack *stack_make(struct Mem *mem, size_t size) { + struct Stack *stack = mem_malloc(mem, sizeof(struct Stack)); + stack->left = mem_malloc(mem, size); + stack->right = stack->left + size; + stack->top = stack->right; + return stack; +} + +void stack_pop(struct Stack *stack) { + stack->top = stack->top + sizeof(void *); + if (stack->top > stack->right) { + meow("pop stack is %p:%p:%p", stack->left, stack->top, stack->right); + crash("uuuh am in cellar"); + } +} +void stack_push(struct Stack *stack, void *v) { + stack->top = stack->top - sizeof(void *); + if (stack->top < stack->left) { + crash("uuuh am in space"); + } + *(void **)stack->top = v; +} + +void *stack_poke(struct Stack *stack) { return *(void **)stack->top; } +void *stack_poke2(struct Stack *stack) { + return *(void **)(stack->top + sizeof(void *)); +} +void stack_set2(struct Stack *stack, void *v) { + void **n = stack->top + sizeof(void *); + *n = v; +} + +void stack_free(struct Stack *stack, struct Mem *mem) { + mem_free(mem, stack->left); + mem_free(mem, stack); +} + +void ast_stack_push(struct Stack *stack, enum PawCtrl *ctrl) { + switch (*ctrl) { + case PAW_CTRL_SEQ: + stack_push(stack, NULL); + stack_push(stack, ctrl); + break; + case PAW_CTRL_ASIGN: + case PAW_CTRL_CALL: + case PAW_CTRL_WHILE: + stack_push(stack, ctrl); + break; + } +} + +// will no ownership of val is transferred and val will not be touched, +// the caller takes ownership of the returned value which is always a newly +// allocated value +enum PawVal *ast_eval(struct PawAST *ast, enum PawVal *val) { + switch (*val) { + case PAW_VAL_FLOAT: + return make_pawval_float(ast->mem, *(float *)val_get_data(val)); + case PAW_VAL_INT: + return make_pawval_int(ast->mem, *(int *)val_get_data(val)); + case PAW_VAL_BOOL: + return make_pawval_bool(ast->mem, *(bool *)val_get_data(val)); + case PAW_VAL_POINT: + return make_pawval_point(ast->mem, *(void **)val_get_data(val)); + case PAW_VAL_FUNC: + meow("todo"); + break; + case PAW_VAL_EXPR:; + struct PawExpr *expr = val_get_data(val); + enum PawVal *lhs = ast_eval(ast, expr->lhs); + enum PawVal *rhs = ast_eval(ast, expr->rhs); + enum PawVal *ret = expr->op(ast, lhs, rhs); + free_pawval(ast->mem, lhs); + free_pawval(ast->mem, rhs); + return ret; + break; + } + meow("unreachable"); + return NULL; +} + +void ast_exec(struct PawAST *ast) { + meow("allocing stack"); + struct Stack *stack = stack_make(ast->mem, 2048); + ast_stack_push(stack, ast->prog); + meow("starting exec"); + while (stack->top < stack->right) { + enum PawCtrl *ctrl = stack_poke(stack); + switch (*ctrl) { + case PAW_CTRL_SEQ:; + int i = (int64_t)(stack_poke2(stack)); + struct PawSeq *seq = ctrl_get_data(ctrl); + if (i >= seq->seq.count) { + stack_pop(stack); + stack_pop(stack); + continue; + } + stack_set2(stack, (void *)(uint64_t)(i + 1)); + ast_stack_push(stack, seq->seq.items[i]); + break; + case PAW_CTRL_CALL:; + struct PawCall *call = ctrl_get_data(ctrl); + if (call->addr == ast->ping_func) { + ping_func(); + } + stack_pop(stack); + break; + case PAW_CTRL_WHILE:; + struct PawWhile *whle = ctrl_get_data(ctrl); + enum PawVal *ret = ast_eval(ast, whle->cond); + if (*ret != PAW_VAL_BOOL) { + meow("unsuported"); + } + bool *v = val_get_data(ret); + if (*v) { + ast_stack_push(stack, whle->body); + } else { + stack_pop(stack); + } + free_pawval(ast->mem, ret); + break; + case PAW_CTRL_ASIGN:; + struct PawAsign *asign = ctrl_get_data(ctrl); + enum PawVal *val = ast_eval(ast, asign->rhs); + if (*val != *asign->lhs) { + crash("woopsie wrong type"); + } + switch (*val) { + case PAW_VAL_FLOAT:; + float *ft = val_get_data(asign->lhs); + *ft = *(float *)val_get_data(val); + break; + case PAW_VAL_INT:; + int *it = val_get_data(asign->lhs); + *it = *(int *)val_get_data(val); + break; + case PAW_VAL_BOOL: + bool *bt = val_get_data(asign->lhs); + *bt = *(bool *)val_get_data(val); + break; + case PAW_VAL_POINT:; + paw_p *pt = val_get_data(asign->lhs); + *bt = *(paw_p *)val_get_data(val); + break; + case PAW_VAL_EXPR: + case PAW_VAL_FUNC: + meow("whhooopsie not primitive"); + break; + } + + free_pawval(ast->mem, val); + stack_pop(stack); + break; + } + } + meow("ending exec"); +} diff --git a/src/lang/ast.h b/src/lang/ast.h new file mode 100644 index 0000000..4cd92d4 --- /dev/null +++ b/src/lang/ast.h @@ -0,0 +1,115 @@ + +#include +#include + +#include "../allocator.h" +#include "../dynarray.h" + +#define paw_p void * +#define PAW_STACK_SIZE 2048 + +struct Stack { + void *right; + void *left; + void *top; +}; + +enum PawVal { + PAW_VAL_FLOAT, + PAW_VAL_INT, + PAW_VAL_BOOL, + PAW_VAL_FUNC, + PAW_VAL_POINT, + PAW_VAL_EXPR, +}; + +enum PawCtrl { + PAW_CTRL_SEQ, + PAW_CTRL_WHILE, + PAW_CTRL_ASIGN, + PAW_CTRL_CALL, +}; + +dyn_array_define(da_paw_ctrl, enum PawCtrl *); +dyn_array_define(da_paw_val, enum PawVal *); + +struct PawSeq { + struct da_paw_ctrl seq; +}; + +struct PawFunc { + enum PawVal *body; + struct da_paw_val val; +}; + +struct PawWhile { + enum PawVal *cond; + enum PawCtrl *body; +}; + +struct PawAsign { + enum PawVal *lhs; + enum PawVal *rhs; +}; + +struct PawProperty { + char *name; + enum PawVal *val; +}; +dyn_array_define(da_paw_property, struct PawProperty); + +struct PawAST { + struct Mem *mem; + enum PawCtrl *prog; + void *ping_func; + struct da_paw_property properties; +}; + +struct PawExpr { + enum PawVal *(*op)(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs); + enum PawVal *lhs; + enum PawVal *rhs; +}; + +struct PawCall { + paw_p addr; +}; + +enum PawVal *op_equals(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs); +enum PawVal *op_unequals(struct PawAST *ast, enum PawVal *lhs, + enum PawVal *rhs); +enum PawVal *op_add(struct PawAST *ast, enum PawVal *lhs, enum PawVal *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); +void free_pawval(struct Mem *mem, enum PawVal *val); +enum PawCtrl *make_pawctrl_seq(struct Mem *mem); +enum PawCtrl *make_pawctrl_call(struct Mem *mem, paw_p addr); +enum PawCtrl *make_pawctrl_while(struct Mem *mem, enum PawVal *cond, + enum PawCtrl *body); +enum PawCtrl *make_pawctrl_asign(struct Mem *mem, enum PawVal *target, + enum PawVal *val); +void pawctrl_append(enum PawCtrl *seq, enum PawCtrl *ctrl); +void ping_func(); +struct PawAST *ast_make(); +void ast_insert_property(struct PawAST *ast, char *name, enum PawVal *val); +enum PawVal *ast_get_property(struct PawAST *ast, char *name); +void ast_exec(struct PawAST *ast); + +#define val_get_data($val) ((void *)$val + sizeof(enum PawVal)) +#define val_make($ret, $type, $TYPE_ENUM) \ + do { \ + $ret = mem_malloc(mem, sizeof(enum PawVal) + sizeof($type)); \ + *$ret = $TYPE_ENUM; \ + } while (0) + +#define ctrl_get_data($ctrl) (void *)$ctrl + sizeof(enum PawCtrl) +#define ctrl_make($ret, $type, $TYPE_ENUM) \ + do { \ + $ret = mem_malloc(mem, sizeof(enum PawCtrl) + sizeof($type)); \ + *$ret = $TYPE_ENUM; \ + } while (0)