aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-01-05 18:26:26 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2025-01-05 18:26:26 +0200
commit79d80d2d8905b62a30f8856b86811ed932c00c45 (patch)
tree4450dd14740a2d7e94e354e4e9fd5d4a7041de15
parent1b670d703473fbf00cb6e1a8411e0e8c27e84c8e (diff)
downloadposthaste-79d80d2d8905b62a30f8856b86811ed932c00c45.tar.gz
posthaste-79d80d2d8905b62a30f8856b86811ed932c00c45.zip
fix procedure/function compilation
+ Add fib example
m---------deps/ejit0
-rw-r--r--examples/fib.ph11
-rw-r--r--include/posthaste/ast.h2
-rw-r--r--src/lower.c42
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,