diff options
Diffstat (limited to 'src_c/env.c')
| -rw-r--r-- | src_c/env.c | 86 |
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; +} |
