aboutsummaryrefslogtreecommitdiff
path: root/fptr_ast/fptr.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-08-31 14:25:07 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-08-31 14:25:07 +0300
commita0c6ff2c222beb72493f2e40ed27492061dfdf22 (patch)
treea3a8c8279135fb92e3032dc85e9e4c6a06ca71e2 /fptr_ast/fptr.c
downloadplayground-a0c6ff2c222beb72493f2e40ed27492061dfdf22.tar.gz
playground-a0c6ff2c222beb72493f2e40ed27492061dfdf22.zip
initial fptr ast programs
Diffstat (limited to 'fptr_ast/fptr.c')
-rw-r--r--fptr_ast/fptr.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/fptr_ast/fptr.c b/fptr_ast/fptr.c
new file mode 100644
index 0000000..7959735
--- /dev/null
+++ b/fptr_ast/fptr.c
@@ -0,0 +1,387 @@
+#include <stdarg.h>
+#include <stdint.h>
+
+#include "common.h"
+
+typedef struct var {
+ char *name;
+ intptr_t v;
+} var;
+
+#define VEC_NAME vars
+#define VEC_TYPE var
+#include <conts/vec.h>
+typedef struct vars vars;
+
+typedef struct proc {
+ vars vars;
+} proc;
+
+static proc *gen_proc(int header, ...)
+{
+ (void)header;
+
+ proc *proc = calloc(1, sizeof(struct proc));
+ if (!proc)
+ return NULL;
+
+ proc->vars = vars_create(0);
+
+ va_list args;
+ va_start(args, header);
+ while (1) {
+ char *name = va_arg(args, char *);
+
+ /* NULL sentinel */
+ if (!name)
+ break;
+
+ var var = {
+ .name = name,
+ .v = 0
+ };
+ vars_append(&proc->vars, var);
+ }
+ va_end(args);
+
+ return proc;
+}
+
+#define gen_proc(...) gen_proc(0, __VA_ARGS__, NULL)
+
+static void proc_set(proc *proc, char *name, intptr_t v)
+{
+ foreach(vars, var, &proc->vars) {
+ if (strcmp(var->name, name) != 0)
+ continue;
+
+ var->v = v;
+ return;
+ }
+
+ /* abort? */
+}
+
+typedef struct node node;
+
+typedef intptr_t (*node_run_t)(struct node *);
+
+typedef struct node {
+ node_run_t run;
+} node;
+
+static intptr_t run(node *n)
+{
+ assert(n);
+ return n->run(n);
+}
+
+typedef struct load {
+ node node;
+ node *addr;
+} load;
+
+static intptr_t run_load(load *l)
+{
+ return *(intptr_t *)run(l->addr);
+}
+
+static node *gen_load(node *addr)
+{
+ load *l = calloc(1, sizeof(load));
+ if (!l)
+ return NULL;
+
+ l->node.run = (node_run_t)run_load;
+ l->addr = addr;
+ return &l->node;
+}
+
+typedef struct store {
+ node node;
+ node *addr;
+ node *val;
+} store;
+
+static intptr_t run_store(store *s)
+{
+ intptr_t *dst = (intptr_t *)run(s->addr);
+ intptr_t val = run(s->val);
+ *dst = val;
+ return 0;
+}
+
+static node *gen_store(node *addr, node *val)
+{
+ store *s = calloc(1, sizeof(store));
+ if (!s)
+ return NULL;
+
+ s->node.run = (node_run_t)run_store;
+ s->addr = addr;
+ s->val = val;
+ return &s->node;
+}
+
+typedef struct add {
+ node node;
+ node *l;
+ node *r;
+} add;
+
+static intptr_t run_add(add *a)
+{
+ intptr_t l = run(a->l);
+ intptr_t r = run(a->r);
+ return l + r;
+}
+
+static node *gen_add(node *l, node *r)
+{
+ add *a = calloc(1, sizeof(add));
+ if (!a)
+ return NULL;
+
+ a->node.run = (node_run_t)run_add;
+ a->l = l;
+ a->r = r;
+ return &a->node;
+}
+
+typedef struct mul {
+ node node;
+ node *l;
+ node *r;
+} mul;
+
+static intptr_t run_mul(mul *m)
+{
+ intptr_t l = run(m->l);
+ intptr_t r = run(m->r);
+ return l * r;
+}
+
+static node *gen_mul(node *l, node *r)
+{
+ mul *m = calloc(1, sizeof(mul));
+ if (!m)
+ return NULL;
+
+ m->node.run = (node_run_t)run_mul;
+ m->l = l;
+ m->r = r;
+ return &m->node;
+}
+
+typedef struct var_n {
+ node node;
+ intptr_t *varref;
+} var_n;
+
+static intptr_t run_var(var_n *v)
+{
+ return *v->varref;
+}
+
+static node *gen_var(proc *proc, char *name)
+{
+ assert(proc && name);
+
+ var_n *v = calloc(1, sizeof(var_n));
+ if (!v)
+ return NULL;
+
+ v->node.run = (node_run_t)run_var;
+ foreach(vars, var, &proc->vars) {
+ if (strcmp(var->name, name) != 0)
+ continue;
+
+ v->varref = &var->v;
+ return &v->node;
+ }
+
+ free(v);
+ return NULL;
+}
+
+typedef struct varref {
+ node node;
+ intptr_t *varref;
+} varref;
+
+static intptr_t run_varref(varref *v)
+{
+ return (intptr_t)v->varref;
+}
+
+static node *gen_varref(proc *proc, char *name)
+{
+ assert(proc && name);
+
+ /* technically speaking we could use the same trick here as in struct.c
+ * since var and varref are the same shape, but feels a bit dirty. */
+
+ varref *v = calloc(1, sizeof(varref));
+ if (!v)
+ return NULL;
+
+ v->node.run = (node_run_t)run_varref;
+ foreach(vars, var, &proc->vars) {
+ if (strcmp(var->name, name) != 0)
+ continue;
+
+ v->varref = &var->v;
+ return &v->node;
+ }
+
+ free(v);
+ return NULL;
+}
+
+typedef struct const_n {
+ node node;
+ intptr_t v;
+} const_n;
+
+static intptr_t run_const_n(const_n *c)
+{
+ return c->v;
+}
+
+static node *gen_const(intptr_t v)
+{
+ const_n *c = calloc(1, sizeof(const_n));
+ if (!c)
+ return NULL;
+
+ c->node.run = (node_run_t)run_const_n;
+ c->v = v;
+ return &c->node;
+}
+
+typedef struct assign {
+ node node;
+ node *dst;
+ node *src;
+} assign;
+
+static intptr_t run_assign(assign *a)
+{
+ intptr_t *dst = (intptr_t *)run(a->dst);
+ intptr_t src = run(a->src);
+ *dst = src;
+ return 0;
+}
+
+static node *gen_assign(node *dst, node *src)
+{
+ assign *a = calloc(1, sizeof(assign));
+ if (!a)
+ return NULL;
+
+ a->node.run = (node_run_t)run_assign;
+ a->dst = dst;
+ a->src = src;
+ return &a->node;
+}
+
+typedef struct for_n {
+ node node;
+ node *init;
+ node *cond;
+ node *post;
+ node *body;
+} for_n;
+
+static intptr_t run_for(for_n *f)
+{
+ for (run(f->init); run(f->cond); run(f->post))
+ run(f->body);
+
+ return 0;
+}
+
+static node *gen_for(node *init, node *cond, node *post, node *body)
+{
+ for_n *f = calloc(1, sizeof(for_n));
+ if (!f)
+ return NULL;
+
+ f->node.run = (node_run_t)run_for;
+ f->init = init;
+ f->cond = cond;
+ f->post = post;
+ f->body = body;
+ return &f->node;
+}
+
+typedef struct lt {
+ node node;
+ node *l;
+ node *r;
+} lt;
+
+static intptr_t run_lt(lt *c)
+{
+ intptr_t l = run(c->l);
+ intptr_t r = run(c->r);
+ return l < r;
+}
+
+static node *gen_lt(node *l, node *r)
+{
+ lt *c = calloc(1, sizeof(lt));
+ if (!c)
+ return NULL;
+
+ c->node.run = (node_run_t)run_lt;
+ c->l = l;
+ c->r = r;
+ return &c->node;
+}
+
+#define VEC_NAME nodes
+#define VEC_TYPE node *
+#include <conts/vec.h>
+typedef struct nodes nodes;
+
+typedef struct body {
+ node node;
+ nodes list;
+} body;
+
+static intptr_t run_body(body *b)
+{
+ foreach(nodes, node, &b->list) {
+ run(*node);
+ }
+
+ return 0;
+}
+
+static node *gen_body(int header, ...)
+{
+ (void)header;
+ body *b = calloc(1, sizeof(body));
+ if (!b)
+ return NULL;
+
+ b->node.run = (node_run_t)run_body;
+ b->list = nodes_create(0);
+
+ va_list args;
+ va_start(args, header);
+ while (1) {
+ node *n = va_arg(args, node *);
+ if (!n)
+ break;
+
+ nodes_append(&b->list, n);
+ }
+
+ va_end(args);
+
+ return &b->node;
+}
+
+#define gen_body(...) gen_body(0, __VA_ARGS__, NULL)