faster than python :3

This commit is contained in:
qwertzuiopy 2025-03-13 19:39:50 +01:00
parent e90fe8cadf
commit 5f36739c9c
3 changed files with 240 additions and 119 deletions

2
main.c
View file

@ -19,6 +19,8 @@ int main() {
ast->mem, ast_get_property(ast, "i"), ast->mem, ast_get_property(ast, "i"),
make_pawval_expr(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))); make_pawval_int(ast->mem, 1), op_add)));
meow("add is at %p", op_add);
meow("eq is at %p", op_unequals);
pawctrl_append( pawctrl_append(
ast->prog, ast->prog,
make_pawctrl_while(ast->mem, make_pawctrl_while(ast->mem,

View file

@ -4,86 +4,148 @@
#include "../log.h" #include "../log.h"
#include "ast.h" #include "ast.h"
enum PawVal *op_equals(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { const bool log_stack = false;
if (*lhs == PAW_VAL_BOOL && *rhs == PAW_VAL_BOOL) {
if (*(bool *)val_get_data(lhs) == *(bool *)val_get_data(rhs)) { struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs,
return make_pawval_bool(ast->mem, true); struct PawStackVal rhs) {
} else { LS("comparing %s to %s", print_valtype(lhs.type), print_valtype(rhs.type));
return make_pawval_bool(ast->mem, false); 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; meow("trying to compare %s to %s, not suppported", print_valtype(lhs.type),
float r; print_valtype(rhs.type));
if (*lhs == PAW_VAL_FLOAT) { return PSV_NULL;
l = *(float *)val_get_data(lhs); }
} else if (*lhs == PAW_VAL_INT) {
l = *(int *)val_get_data(lhs); const char *print_valtype(enum PawVal type) {
} switch (type) {
if (*rhs == PAW_VAL_FLOAT) { case PAW_VAL_FLOAT:
r = *(float *)val_get_data(rhs); return "float";
} else if (*rhs == PAW_VAL_INT) { case PAW_VAL_INT:
r = *(int *)val_get_data(rhs); return "int";
} case PAW_VAL_BOOL:
if (l == r) { return "bool";
return make_pawval_bool(ast->mem, true); case PAW_VAL_FUNC:
} else { return "call";
return make_pawval_bool(ast->mem, false); case PAW_VAL_POINT:
return "void*";
case PAW_VAL_EXPR:
return "expr";
} }
} }
enum PawVal *op_unequals(struct PawAST *ast, enum PawVal *lhs, const char *print_ctrltype(enum PawCtrl ctrl) {
enum PawVal *rhs) { switch (ctrl) {
enum PawVal *res = op_equals(ast, lhs, rhs); case PAW_CTRL_SEQ:
*(bool *)val_get_data(res) = !*(bool *)val_get_data(res); return "seq";
return res; 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) { struct PawStackVal try_cast_stack(enum PawVal target, struct PawStackVal val) {
float l; LS("casting from %s to %s", print_valtype(val.type), print_valtype(target));
float r; switch (target) {
if (*lhs == PAW_VAL_FLOAT) { case PAW_VAL_FLOAT:
l = *(float *)val_get_data(lhs); switch (val.type) {
} else if (*lhs == PAW_VAL_INT) { case PAW_VAL_FLOAT:
l = *(int *)val_get_data(lhs); 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) { meow("trying to cast %s to %s, returning null", print_valtype(val.type),
r = *(float *)val_get_data(rhs); print_valtype(target));
} else if (*rhs == PAW_VAL_INT) { return PSV_NULL;
r = *(int *)val_get_data(rhs); }
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) { struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs,
float l; struct PawStackVal rhs) {
float r; return PSV_BOOL(!op_equals(ast, lhs, rhs).b);
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);
} }
enum PawVal *op_sub(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs) { struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs,
float l; struct PawStackVal rhs) {
float r; LS("adding %s to %s", print_valtype(lhs.type), print_valtype(rhs.type));
if (*lhs == PAW_VAL_FLOAT) { switch (lhs.type) {
l = *(float *)val_get_data(lhs); case PAW_VAL_FLOAT:
} else if (*lhs == PAW_VAL_INT) { switch (rhs.type) {
l = *(int *)val_get_data(lhs); 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) { meow("trying to add %s to %s, returning null", print_valtype(lhs.type),
r = *(float *)val_get_data(rhs); print_valtype(rhs.type));
} else if (*rhs == PAW_VAL_INT) { return PSV_NULL;
r = *(int *)val_get_data(rhs);
}
return make_pawval_float(ast->mem, l - r);
} }
enum PawVal *make_pawval_float(struct Mem *mem, float n) { 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->lhs = lhs;
i->rhs = rhs; i->rhs = rhs;
return val; return val;
*i = (struct PawExpr){
.op = op,
.lhs = lhs,
.rhs = rhs,
};
return val;
} }
enum PawVal *make_pawval_func(struct Mem *mem) { 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, // 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 // the caller takes ownership of the returned value which is always a newly
// allocated value // 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) { switch (*val) {
case PAW_VAL_FLOAT: 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: 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: 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: 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: case PAW_VAL_FUNC:
meow("todo"); meow("todo");
break; break;
case PAW_VAL_EXPR:; case PAW_VAL_EXPR:;
struct PawExpr *expr = val_get_data(val); struct PawExpr *expr = val_get_data(val);
enum PawVal *lhs = ast_eval(ast, expr->lhs); LS("calling op at %p", expr->op);
enum PawVal *rhs = ast_eval(ast, expr->rhs); struct PawStackVal lhs = ast_eval(ast, expr->lhs);
enum PawVal *ret = expr->op(ast, lhs, rhs); struct PawStackVal rhs = ast_eval(ast, expr->rhs);
free_pawval(ast->mem, lhs); struct PawStackVal ret = expr->op(ast, lhs, rhs);
free_pawval(ast->mem, rhs);
return ret; return ret;
break; break;
} }
meow("unreachable"); 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) { void ast_exec(struct PawAST *ast) {
@ -321,6 +401,7 @@ void ast_exec(struct PawAST *ast) {
enum PawCtrl *ctrl = stack_poke(stack); enum PawCtrl *ctrl = stack_poke(stack);
switch (*ctrl) { switch (*ctrl) {
case PAW_CTRL_SEQ:; case PAW_CTRL_SEQ:;
LS("SEQ");
int i = (int64_t)(stack_poke2(stack)); int i = (int64_t)(stack_poke2(stack));
struct PawSeq *seq = ctrl_get_data(ctrl); struct PawSeq *seq = ctrl_get_data(ctrl);
if (i >= seq->seq.count) { if (i >= seq->seq.count) {
@ -332,6 +413,7 @@ void ast_exec(struct PawAST *ast) {
ast_stack_push(stack, seq->seq.items[i]); ast_stack_push(stack, seq->seq.items[i]);
break; break;
case PAW_CTRL_CALL:; case PAW_CTRL_CALL:;
LS("CALL");
struct PawCall *call = ctrl_get_data(ctrl); struct PawCall *call = ctrl_get_data(ctrl);
if (call->addr == ast->ping_func) { if (call->addr == ast->ping_func) {
ping_func(); ping_func();
@ -339,49 +421,55 @@ void ast_exec(struct PawAST *ast) {
stack_pop(stack); stack_pop(stack);
break; break;
case PAW_CTRL_WHILE:; case PAW_CTRL_WHILE:;
LS("WHILE");
struct PawWhile *whle = ctrl_get_data(ctrl); struct PawWhile *whle = ctrl_get_data(ctrl);
enum PawVal *ret = ast_eval(ast, whle->cond); struct PawStackVal ret =
if (*ret != PAW_VAL_BOOL) { try_cast_stack(PAW_VAL_BOOL, ast_eval(ast, whle->cond));
meow("unsuported"); 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 ((bool)ret.b) {
if (*v) {
ast_stack_push(stack, whle->body); ast_stack_push(stack, whle->body);
} else { } else {
stack_pop(stack); stack_pop(stack);
} }
free_pawval(ast->mem, ret);
break; break;
case PAW_CTRL_ASIGN:; case PAW_CTRL_ASIGN:;
LS("ASIGN");
struct PawAsign *asign = ctrl_get_data(ctrl); struct PawAsign *asign = ctrl_get_data(ctrl);
enum PawVal *val = ast_eval(ast, asign->rhs); struct PawStackVal val =
if (*val != *asign->lhs) { try_cast_stack(*asign->lhs, ast_eval(ast, asign->rhs));
crash("woopsie wrong type"); 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:; case PAW_VAL_FLOAT:;
float *ft = val_get_data(asign->lhs); float *ft = val_get_data(asign->lhs);
*ft = *(float *)val_get_data(val); *ft = val.f;
break; break;
case PAW_VAL_INT:; case PAW_VAL_INT:;
int *it = val_get_data(asign->lhs); int *it = val_get_data(asign->lhs);
*it = *(int *)val_get_data(val); *it = val.i;
break; break;
case PAW_VAL_BOOL: case PAW_VAL_BOOL:
bool *bt = val_get_data(asign->lhs); bool *bt = val_get_data(asign->lhs);
*bt = *(bool *)val_get_data(val); *bt = val.b;
break; break;
case PAW_VAL_POINT:; case PAW_VAL_POINT:;
paw_p *pt = val_get_data(asign->lhs); paw_p *pt = val_get_data(asign->lhs);
*bt = *(paw_p *)val_get_data(val); *pt = val.p;
break; break;
case PAW_VAL_EXPR: case PAW_VAL_EXPR:
case PAW_VAL_FUNC: case PAW_VAL_FUNC:
meow("whhooopsie not primitive"); meow("whhooopsie not primitive");
unwind_stack(stack);
break; break;
} }
free_pawval(ast->mem, val);
stack_pop(stack); stack_pop(stack);
break; break;
} }

View file

@ -6,7 +6,22 @@
#include "../dynarray.h" #include "../dynarray.h"
#define paw_p void * #define paw_p void *
#define PSV_NULL \
(struct PawStackVal) { PAW_VAL_POINT, .p = NULL }
#define PAW_STACK_SIZE 2048 #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 { struct Stack {
void *right; void *right;
@ -29,29 +44,14 @@ enum PawCtrl {
PAW_CTRL_ASIGN, PAW_CTRL_ASIGN,
PAW_CTRL_CALL, PAW_CTRL_CALL,
}; };
dyn_array_define(da_paw_ctrl, enum PawCtrl *); dyn_array_define(da_paw_ctrl, enum PawCtrl *);
dyn_array_define(da_paw_val, enum PawVal *); dyn_array_define(da_paw_val, enum PawVal *);
struct PawSeq {
struct da_paw_ctrl seq;
};
struct PawFunc { struct PawFunc {
enum PawVal *body; enum PawVal *body;
struct da_paw_val val; struct da_paw_val val;
}; };
struct PawWhile {
enum PawVal *cond;
enum PawCtrl *body;
};
struct PawAsign {
enum PawVal *lhs;
enum PawVal *rhs;
};
struct PawProperty { struct PawProperty {
char *name; char *name;
enum PawVal *val; enum PawVal *val;
@ -66,7 +66,36 @@ struct PawAST {
}; };
struct PawExpr { 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 *lhs;
enum PawVal *rhs; enum PawVal *rhs;
}; };
@ -75,10 +104,12 @@ struct PawCall {
paw_p addr; paw_p addr;
}; };
enum PawVal *op_equals(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs); struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs,
enum PawVal *op_unequals(struct PawAST *ast, enum PawVal *lhs, struct PawStackVal rhs);
enum PawVal *rhs); struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs,
enum PawVal *op_add(struct PawAST *ast, enum PawVal *lhs, enum PawVal *rhs); 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_float(struct Mem *mem, float n);
enum PawVal *make_pawval_int(struct Mem *mem, int n); enum PawVal *make_pawval_int(struct Mem *mem, int n);