aboutsummaryrefslogtreecommitdiff
path: root/src_c/env.c
diff options
context:
space:
mode:
authorbozo.kopic <bozo@kopic.xyz>2022-08-02 01:20:12 +0200
committerbozo.kopic <bozo@kopic.xyz>2022-09-25 02:40:23 +0200
commit288727f09a1b3458c268497d111349e608c3f9fa (patch)
treed62565249fa3c7127856c65405752572fc41aca9 /src_c/env.c
Diffstat (limited to 'src_c/env.c')
-rw-r--r--src_c/env.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/src_c/env.c b/src_c/env.c
new file mode 100644
index 0000000..13999d5
--- /dev/null
+++ b/src_c/env.c
@@ -0,0 +1,86 @@
+#include "env.h"
+#include "ctx.h"
+#include "eval.h"
+
+
+static void init_result(lsp_env_t *e) {
+ e->result.is_value = true;
+ e->result.ctx = e->m->nil;
+ e->result.value = e->m->nil;
+}
+
+
+static void release_result(lsp_env_t *e) {
+ lsp_mem_dec_ref(e->m, e->result.ctx);
+ lsp_mem_dec_ref(e->m, e->result.value);
+
+ init_result(e);
+}
+
+
+void lsp_env_init(lsp_env_t *e, lsp_mem_t *m, lsp_in_stream_t *in,
+ lsp_out_stream_t *out) {
+ e->m = m;
+ e->in = in;
+ e->out = out;
+
+ init_result(e);
+}
+
+
+lsp_status_t lsp_env_set_result_value(lsp_env_t *e, lsp_addr_t value) {
+ release_result(e);
+
+ lsp_status_t status = lsp_mem_inc_ref(e->m, value);
+ if (status != LSP_SUCCESS)
+ return status;
+
+ e->result.is_value = true;
+ e->result.value = value;
+ return LSP_SUCCESS;
+}
+
+
+lsp_status_t lsp_env_set_result_eval(lsp_env_t *e, lsp_addr_t ctx,
+ lsp_addr_t value) {
+ release_result(e);
+
+ lsp_status_t status = lsp_mem_inc_ref(e->m, ctx);
+ if (status != LSP_SUCCESS)
+ return status;
+
+ status = lsp_mem_inc_ref(e->m, value);
+ if (status != LSP_SUCCESS) {
+ lsp_mem_dec_ref(e->m, ctx);
+ return status;
+ }
+
+ e->result.is_value = false;
+ e->result.ctx = ctx;
+ e->result.value = value;
+ return LSP_SUCCESS;
+}
+
+
+lsp_status_t lsp_env_resolve(lsp_env_t *e, lsp_addr_t ctx, lsp_addr_t value,
+ lsp_addr_t *result) {
+ lsp_status_t status = lsp_env_set_result_eval(e, ctx, value);
+ if (status != LSP_SUCCESS)
+ return status;
+
+ while (!e->result.is_value) {
+ lsp_addr_t eval_ctx = e->result.ctx;
+ lsp_addr_t eval_value = e->result.value;
+ init_result(e);
+
+ status = lsp_eval(e, eval_ctx, eval_value);
+ lsp_mem_dec_ref(e->m, eval_ctx);
+ lsp_mem_dec_ref(e->m, eval_value);
+ if (status != LSP_SUCCESS)
+ return status;
+ }
+
+ *result = e->result.value;
+ init_result(e);
+ return LSP_SUCCESS;
+}