diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-01-05 18:26:26 +0200 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-01-05 18:26:26 +0200 |
commit | 79d80d2d8905b62a30f8856b86811ed932c00c45 (patch) | |
tree | 4450dd14740a2d7e94e354e4e9fd5d4a7041de15 | |
parent | 1b670d703473fbf00cb6e1a8411e0e8c27e84c8e (diff) | |
download | posthaste-79d80d2d8905b62a30f8856b86811ed932c00c45.tar.gz posthaste-79d80d2d8905b62a30f8856b86811ed932c00c45.zip |
fix procedure/function compilation
+ Add fib example
m--------- | deps/ejit | 0 | ||||
-rw-r--r-- | examples/fib.ph | 11 | ||||
-rw-r--r-- | include/posthaste/ast.h | 2 | ||||
-rw-r--r-- | src/lower.c | 42 |
4 files changed, 32 insertions, 23 deletions
diff --git a/deps/ejit b/deps/ejit -Subproject 8e04d594e8d280e37651f9976be52e0052c9051 +Subproject cb21b31b31dc30023d6fadcab3c15b258f40be9 diff --git a/examples/fib.ph b/examples/fib.ph new file mode 100644 index 0000000..9e1a185 --- /dev/null +++ b/examples/fib.ph @@ -0,0 +1,11 @@ +function Fib{ num[int] } return int +is + do + 1 + unless 1 < num + otherwise + Fib(num - 1) + Fib(num - 2) + done +end function + +print Fib(42) diff --git a/include/posthaste/ast.h b/include/posthaste/ast.h index 64e987f..3096186 100644 --- a/include/posthaste/ast.h +++ b/include/posthaste/ast.h @@ -68,7 +68,7 @@ enum type_kind { /* used by lower.c, defined here to avoid circular dependencies */ struct loc { - /* offset within either local stack */ + /* offset within local stack */ uintptr_t s; /* offset within global array */ uintptr_t g; diff --git a/src/lower.c b/src/lower.c index 5e0e41e..cdede46 100644 --- a/src/lower.c +++ b/src/lower.c @@ -36,9 +36,7 @@ * now */ static struct vec fns = {0}; -/* locs use global 0 to mean unitialized and global 1 is reserved as null_loc(), - * so skip two first globals */ -static size_t globals = 2; +static size_t globals = 1; /* get register/stack slot for AST node */ #define regno(x) ((x)->l.s) @@ -59,18 +57,17 @@ static void lower_list(struct fn *f, struct ast *l) static struct loc build_local_loc(size_t idx) { - return (struct loc){.g = 0, .s = idx}; + return (struct loc){.g = -1, .s = idx}; } static struct loc build_global_loc(size_t idx) { - return (struct loc){.g = idx, .s = 0}; + return (struct loc){.g = idx, .s = -1}; } static struct loc null_loc() { - /* don't exactly love this but I guess it works */ - return build_global_loc(1); + return (struct loc){.g = -1, .s = -1}; } static enum ejit_type ejit_type_from(enum type_kind t) @@ -87,9 +84,9 @@ static enum ejit_type ejit_type_from(enum type_kind t) static void put(struct fn *f, struct loc l) { - assert(l.g != 1); + assert(l.g != 0); /* local values are already where they should be */ - if (l.g <= 1) + if (l.g == -1) return; /* something like this I think, should still check the type width */ @@ -98,8 +95,8 @@ static void put(struct fn *f, struct loc l) static void get(struct fn *f, struct loc l) { - assert(l.g != 1); - if (l.g <= 1) + assert(l.g != 0); + if (l.g == -1) return; ejit_ldxi_u64(f->f, EJIT_GPR(l.s), EJIT_GPR(0), l.g * sizeof(int64_t)); @@ -321,8 +318,8 @@ static void get_id_loc(struct fn *f, struct ast *n) /* using ast nodes/scope lookup as convenient way to store variable -> * location mappings */ n->l = exists->l; - assert(n->l.g != 1); - if (n->l.g > 1) { + assert(n->l.g != 0); + if (n->l.g != -1) { /* global variables should get loaded to the stack for handling */ n->l.s = f->sp; } @@ -538,7 +535,10 @@ static void lower_proc_call(struct fn *f, struct ast *c) } struct ast *def = file_scope_find(c->scope, proc_call_id(c)); - ejit_calli(f->f, (struct ejit_func *)def->l.s, count, args); + struct fn *target = vec_at(&fns, def->l.s); + assert(target); + + ejit_calli(f->f, target->f, count, args); f->sp -= count; @@ -562,9 +562,10 @@ static void lower_func_call(struct fn *f, struct ast *c) } struct ast *def = file_scope_find(c->scope, func_call_id(c)); - /* note, def->l.s is not actually a register, rather a pointer to the - * struct ejit_func */ - ejit_calli(f->f, (struct ejit_func *)def->l.s, count, args); + struct fn *target = vec_at(&fns, def->l.s); + assert(target); + + ejit_calli(f->f, target->f, count, args); f->sp -= count; @@ -957,10 +958,7 @@ static void lower_global_var(struct fn *f, struct ast *n) { static void add_proc(struct ast *n) { size_t idx = vec_len(&fns); - /* global locs are effectively just indexes, so this is a nifty way to - * encode the procedure index into the AST for later use by - * lower_proc_call and so on */ - n->l = build_global_loc(idx); + n->l = build_local_loc(idx); struct fn f = {.name = proc_id(n), .idx = idx, .sp = 0, @@ -971,7 +969,7 @@ static void add_proc(struct ast *n) { static void add_func(struct ast *n) { size_t idx = vec_len(&fns); - n->l = build_global_loc(idx); + n->l = build_local_loc(idx); struct fn f = {.name = func_id(n), .idx = idx, .sp = 0, |