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"),
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,

View file

@ -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;
}

View file

@ -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);