From 5f36739c9caebd3c57f956a94d0919abca57cc49 Mon Sep 17 00:00:00 2001 From: qwertzuiopy Date: Thu, 13 Mar 2025 19:39:50 +0100 Subject: [PATCH] faster than python :3 --- main.c | 2 + src/lang/ast.c | 286 ++++++++++++++++++++++++++++++++----------------- src/lang/ast.h | 71 ++++++++---- 3 files changed, 240 insertions(+), 119 deletions(-) diff --git a/main.c b/main.c index a7e1d6c..6bb5e25 100644 --- a/main.c +++ b/main.c @@ -19,6 +19,8 @@ int main() { 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))); + meow("add is at %p", op_add); + meow("eq is at %p", op_unequals); pawctrl_append( ast->prog, make_pawctrl_while(ast->mem, diff --git a/src/lang/ast.c b/src/lang/ast.c index 93eb3b1..6fe5278 100644 --- a/src/lang/ast.c +++ b/src/lang/ast.c @@ -4,86 +4,148 @@ #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); +const bool log_stack = false; + +struct PawStackVal op_equals(struct PawAST *ast, 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: + switch (rhs.type) { + case PAW_VAL_FLOAT: + return PSV_BOOL(rhs.f == lhs.f); + case PAW_VAL_INT: + return PSV_BOOL(rhs.f == lhs.i); + } + case PAW_VAL_INT: + switch (rhs.type) { + case PAW_VAL_FLOAT: + return PSV_BOOL(lhs.i == rhs.f); + case PAW_VAL_INT: + return PSV_BOOL(lhs.i == rhs.i); + } + case PAW_VAL_BOOL: + switch (rhs.type) { + case PAW_VAL_BOOL: + return PSV_BOOL(lhs.b == rhs.b); } } - 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); + meow("trying to compare %s to %s, not suppported", print_valtype(lhs.type), + print_valtype(rhs.type)); + return PSV_NULL; +} + +const char *print_valtype(enum PawVal type) { + switch (type) { + case PAW_VAL_FLOAT: + return "float"; + case PAW_VAL_INT: + return "int"; + case PAW_VAL_BOOL: + return "bool"; + case PAW_VAL_FUNC: + return "call"; + case PAW_VAL_POINT: + return "void*"; + case PAW_VAL_EXPR: + return "expr"; } } -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; +const char *print_ctrltype(enum PawCtrl ctrl) { + switch (ctrl) { + case PAW_CTRL_SEQ: + return "seq"; + case PAW_CTRL_WHILE: + return "while"; + case PAW_CTRL_ASIGN: + return "asign"; + case PAW_CTRL_CALL: + return "call"; + } } -enum PawVal *op_add(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { - 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); +struct PawStackVal try_cast_stack(enum PawVal target, struct PawStackVal val) { + LS("casting from %s to %s", print_valtype(val.type), print_valtype(target)); + switch (target) { + case PAW_VAL_FLOAT: + switch (val.type) { + case PAW_VAL_FLOAT: + return PSV_FLOAT((float)val.f); + case PAW_VAL_INT: + return PSV_FLOAT((float)val.i); + } + case PAW_VAL_INT: + switch (val.type) { + case PAW_VAL_FLOAT: + return PSV_INT((int)val.f); + case PAW_VAL_INT: + return PSV_INT((int)val.i); + } + case PAW_VAL_BOOL: + switch (val.type) { + case PAW_VAL_BOOL: + return PSV_BOOL((bool)val.b); + } } - if (*rhs == PAW_VAL_FLOAT) { - r = *(float *)val_get_data(rhs); - } else if (*rhs == PAW_VAL_INT) { - r = *(int *)val_get_data(rhs); + meow("trying to cast %s to %s, returning null", print_valtype(val.type), + print_valtype(target)); + return PSV_NULL; +} +struct PawStackVal try_cast(enum PawVal target, enum PawVal *val) { + switch (target) { + case PAW_VAL_FLOAT: + switch (*val) { + case PAW_VAL_FLOAT: + return PSV_FLOAT((float)*(float *)val_get_data(val)); + case PAW_VAL_INT: + return PSV_FLOAT((float)*(int *)val_get_data(val)); + } + case PAW_VAL_INT: + switch (*val) { + case PAW_VAL_FLOAT: + return PSV_INT((int)*(float *)val_get_data(val)); + case PAW_VAL_INT: + return PSV_INT((int)*(int *)val_get_data(val)); + } + case PAW_VAL_BOOL: + switch (*val) { + case PAW_VAL_BOOL: + return PSV_BOOL((bool)*(bool *)val_get_data(val)); + } } - return make_pawval_float(ast->mem, l + r); + meow("trying to cast %s to %s, returning null", print_valtype(*val), + print_valtype(target)); + return PSV_NULL; } -enum PawVal *op_mul(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { - 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); - } - return make_pawval_float(ast->mem, l * r); +struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs, + struct PawStackVal rhs) { + return PSV_BOOL(!op_equals(ast, lhs, rhs).b); } -enum PawVal *op_sub(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { - 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); +struct PawStackVal op_add(struct PawAST *ast, 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: + switch (rhs.type) { + case PAW_VAL_FLOAT: + return PSV_FLOAT(lhs.f + rhs.f); + case PAW_VAL_INT: + return PSV_FLOAT(lhs.f + rhs.i); + } + case PAW_VAL_INT: + switch (rhs.type) { + case PAW_VAL_FLOAT: + return PSV_FLOAT(lhs.i + rhs.f); + case PAW_VAL_INT: + return PSV_INT(lhs.i + rhs.i); + } } - if (*rhs == PAW_VAL_FLOAT) { - r = *(float *)val_get_data(rhs); - } else if (*rhs == PAW_VAL_INT) { - r = *(int *)val_get_data(rhs); - } - return make_pawval_float(ast->mem, l - r); + meow("trying to add %s to %s, returning null", print_valtype(lhs.type), + print_valtype(rhs.type)); + return PSV_NULL; } enum PawVal *make_pawval_float(struct Mem *mem, float n) { @@ -127,12 +189,6 @@ enum PawVal *make_pawval_expr(struct Mem *mem, enum PawVal *lhs, 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) { @@ -285,31 +341,55 @@ void ast_stack_push(struct Stack *stack, enum PawCtrl *ctrl) { // 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) { +struct PawStackVal ast_eval(struct PawAST *ast, enum PawVal *val) { + LS("evaling a %s", print_valtype(*val)); switch (*val) { case PAW_VAL_FLOAT: - return make_pawval_float(ast->mem, *(float *)val_get_data(val)); + return (struct PawStackVal){ + PAW_VAL_FLOAT, + .f = *(float *)val_get_data(val), + }; case PAW_VAL_INT: - return make_pawval_int(ast->mem, *(int *)val_get_data(val)); + return (struct PawStackVal){ + PAW_VAL_INT, + .i = *(int *)val_get_data(val), + }; case PAW_VAL_BOOL: - return make_pawval_bool(ast->mem, *(bool *)val_get_data(val)); + return (struct PawStackVal){ + PAW_VAL_BOOL, + .b = *(float *)val_get_data(val), + }; case PAW_VAL_POINT: - return make_pawval_point(ast->mem, *(void **)val_get_data(val)); + return (struct PawStackVal){ + PAW_VAL_POINT, + .b = *(paw_p *)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); + LS("calling op at %p", expr->op); + struct PawStackVal lhs = ast_eval(ast, expr->lhs); + struct PawStackVal rhs = ast_eval(ast, expr->rhs); + struct PawStackVal ret = expr->op(ast, lhs, rhs); return ret; break; } meow("unreachable"); - return NULL; + return PSV_NULL; +} + +void unwind_stack(struct Stack *stack) { + while (stack->top < stack->right) { + enum PawCtrl *ctrl = stack_poke(stack); + meow("got a %s", print_ctrltype(*ctrl)); + if (*ctrl == PAW_CTRL_SEQ) { + stack_pop(stack); + } + stack_pop(stack); + } + crash("unwound stack, exiting"); } void ast_exec(struct PawAST *ast) { @@ -321,6 +401,7 @@ void ast_exec(struct PawAST *ast) { enum PawCtrl *ctrl = stack_poke(stack); switch (*ctrl) { case PAW_CTRL_SEQ:; + LS("SEQ"); int i = (int64_t)(stack_poke2(stack)); struct PawSeq *seq = ctrl_get_data(ctrl); if (i >= seq->seq.count) { @@ -332,6 +413,7 @@ void ast_exec(struct PawAST *ast) { ast_stack_push(stack, seq->seq.items[i]); break; case PAW_CTRL_CALL:; + LS("CALL"); struct PawCall *call = ctrl_get_data(ctrl); if (call->addr == ast->ping_func) { ping_func(); @@ -339,49 +421,55 @@ void ast_exec(struct PawAST *ast) { stack_pop(stack); break; case PAW_CTRL_WHILE:; + LS("WHILE"); struct PawWhile *whle = ctrl_get_data(ctrl); - enum PawVal *ret = ast_eval(ast, whle->cond); - if (*ret != PAW_VAL_BOOL) { - meow("unsuported"); + struct PawStackVal ret = + try_cast_stack(PAW_VAL_BOOL, ast_eval(ast, whle->cond)); + if (ret.type != PAW_VAL_BOOL) { + meow("unsuported: a %s in a while loop condition", + print_valtype(ret.type)); + stack_pop(stack); + break; } - bool *v = val_get_data(ret); - if (*v) { + if ((bool)ret.b) { ast_stack_push(stack, whle->body); } else { stack_pop(stack); } - free_pawval(ast->mem, ret); break; case PAW_CTRL_ASIGN:; + LS("ASIGN"); struct PawAsign *asign = ctrl_get_data(ctrl); - enum PawVal *val = ast_eval(ast, asign->rhs); - if (*val != *asign->lhs) { - crash("woopsie wrong type"); + struct PawStackVal val = + try_cast_stack(*asign->lhs, ast_eval(ast, asign->rhs)); + if (val.type != *asign->lhs) { + meow("woopsie wrong type, expected %s but got %s", + print_valtype(*asign->lhs), print_valtype(val.type)); + unwind_stack(stack); } - switch (*val) { + switch (val.type) { case PAW_VAL_FLOAT:; float *ft = val_get_data(asign->lhs); - *ft = *(float *)val_get_data(val); + *ft = val.f; break; case PAW_VAL_INT:; int *it = val_get_data(asign->lhs); - *it = *(int *)val_get_data(val); + *it = val.i; break; case PAW_VAL_BOOL: bool *bt = val_get_data(asign->lhs); - *bt = *(bool *)val_get_data(val); + *bt = val.b; break; case PAW_VAL_POINT:; paw_p *pt = val_get_data(asign->lhs); - *bt = *(paw_p *)val_get_data(val); + *pt = val.p; break; case PAW_VAL_EXPR: case PAW_VAL_FUNC: meow("whhooopsie not primitive"); + unwind_stack(stack); break; } - - free_pawval(ast->mem, val); stack_pop(stack); break; } diff --git a/src/lang/ast.h b/src/lang/ast.h index 4cd92d4..5dd6cee 100644 --- a/src/lang/ast.h +++ b/src/lang/ast.h @@ -6,7 +6,22 @@ #include "../dynarray.h" #define paw_p void * +#define PSV_NULL \ + (struct PawStackVal) { PAW_VAL_POINT, .p = NULL } #define PAW_STACK_SIZE 2048 +#define PSV_BOOL($v) \ + (struct PawStackVal) { PAW_VAL_BOOL, .b = ($v) } +#define PSV_FLOAT($v) \ + (struct PawStackVal) { PAW_VAL_FLOAT, .f = ($v) } +#define PSV_INT($v) \ + (struct PawStackVal) { PAW_VAL_INT, .i = ($v) } +#define PSV_P($v) \ + (struct PawStackVal) { PAW_VAL_POINT, .p = ($v) } + +#define LS(fmt, ...) \ + if (log_stack) { \ + fprintf(stderr, "[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ + } struct Stack { void *right; @@ -29,29 +44,14 @@ enum PawCtrl { 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; @@ -66,7 +66,36 @@ struct PawAST { }; struct PawExpr { - enum PawVal *(*op)(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs); + struct PawStackVal (*op)(struct PawAST *ast, struct PawStackVal lhs, + struct PawStackVal rhs); + enum PawVal *lhs; + enum PawVal *rhs; +}; + +// simple types which can be entirely allocated on the stack +struct PawStackVal { + enum PawVal type; + union { + float f; + int i; + bool b; + paw_p p; + }; +}; + +// the return value does not have to be freed +const char *print_valtype(enum PawVal type); + +struct PawSeq { + struct da_paw_ctrl seq; +}; + +struct PawWhile { + enum PawVal *cond; + enum PawCtrl *body; +}; + +struct PawAsign { enum PawVal *lhs; enum PawVal *rhs; }; @@ -75,10 +104,12 @@ 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); +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); enum PawVal *make_pawval_float(struct Mem *mem, float n); enum PawVal *make_pawval_int(struct Mem *mem, int n);