faster than python :3
This commit is contained in:
parent
e90fe8cadf
commit
5f36739c9c
3 changed files with 240 additions and 119 deletions
2
main.c
2
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,
|
||||
|
|
286
src/lang/ast.c
286
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue