From fad0ce3ced52f8e6b15cc52d19bdbe6ac0c2587d Mon Sep 17 00:00:00 2001 From: Michael Camilleri Date: Mon, 24 Jan 2022 11:08:33 +0900 Subject: [PATCH] Move missing symbol lookup to compiler --- src/core/compile.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/util.c | 25 ++++++++--------------- src/core/util.h | 1 + 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/core/compile.c b/src/core/compile.c index a4c8c2bf..347a472e 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -197,6 +197,39 @@ void janetc_popscope_keepslot(JanetCompiler *c, JanetSlot retslot) { } } +static int lookup_missing( + JanetCompiler *c, + const uint8_t *sym, + JanetFunction *handler, + Janet *out) { + Janet args[2] = { janet_wrap_symbol(sym), janet_wrap_table(c->env) }; + JanetFiber *fiberp = janet_fiber(handler, 64, 2, args); + if (NULL == fiberp) { + int32_t minar = handler->def->min_arity; + int32_t maxar = handler->def->max_arity; + const uint8_t *es = NULL; + if (minar > 2) + es = janet_formatc("lookup handler arity mismatch, minimum at most 2, got %d", minar); + if (maxar < 2) + es = janet_formatc("lookup handler arity mismatch, maximum at least 2, got %d", maxar); + janetc_error(c, es); + return 0; + } + fiberp->env = c->env; + int lock = janet_gclock(); + Janet tempOut; + JanetSignal status = janet_continue(fiberp, janet_wrap_nil(), &tempOut); + janet_gcunlock(lock); + if (status != JANET_SIGNAL_OK) { + janetc_error(c, janet_formatc("(lookup) %V", tempOut)); + return 0; + } else { + *out = tempOut; + } + + return 1; +} + /* Allow searching for symbols. Return information about the symbol */ JanetSlot janetc_resolve( JanetCompiler *c, @@ -230,6 +263,23 @@ JanetSlot janetc_resolve( /* Symbol not found - check for global */ { JanetBinding binding = janet_resolve_ext(c->env, sym); + if (binding.type == JANET_BINDING_NONE) { + Janet handler = janet_table_get(c->env, janet_ckeywordv("missing-symbol")); + switch (janet_type(handler)) { + case JANET_NIL: + break; + case JANET_FUNCTION: + Janet entry; + if (!lookup_missing(c, sym, janet_unwrap_function(handler), &entry)) + return janetc_cslot(janet_wrap_nil()); + binding = janet_binding_from_entry(entry); + break; + default: + janetc_error(c, janet_formatc("invalid lookup handler %V", handler)); + return janetc_cslot(janet_wrap_nil()); + } + } + switch (binding.type) { default: case JANET_BINDING_NONE: diff --git a/src/core/util.c b/src/core/util.c index 99edcd7c..44ad8b34 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -597,9 +597,8 @@ void janet_core_cfuns_ext(JanetTable *env, const char *regprefix, const JanetReg } #endif -JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) { +JanetBinding janet_binding_from_entry(Janet entry) { JanetTable *entry_table; - Janet entry = janet_table_get(env, janet_wrap_symbol(sym)); JanetBinding binding = { JANET_BINDING_NONE, janet_wrap_nil(), @@ -607,21 +606,8 @@ JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) { }; /* Check environment for entry */ - if (!janet_checktype(entry, JANET_TABLE)) { - Janet lookup_entry = janet_table_get(env, janet_ckeywordv("missing-symbol")); - if (janet_checktype(lookup_entry, JANET_FUNCTION)) { - JanetFunction *lookup = janet_unwrap_function(lookup_entry); - Janet args[2] = { janet_wrap_symbol(sym), janet_wrap_table(env) }; - JanetFiber *fiberp = janet_fiber(lookup, 64, 2, args); - if (NULL == fiberp) return binding; - fiberp->env = env; - int lock = janet_gclock(); - JanetSignal status = janet_continue(fiberp, janet_wrap_nil(), &entry); - janet_gcunlock(lock); - if (status != JANET_SIGNAL_OK) return binding; - } - if (!janet_checktype(entry, JANET_TABLE)) return binding; - } + if (!janet_checktype(entry, JANET_TABLE)) + return binding; entry_table = janet_unwrap_table(entry); /* deprecation check */ @@ -662,6 +648,11 @@ JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) { return binding; } +JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) { + Janet entry = janet_table_get(env, janet_wrap_symbol(sym)); + return janet_binding_from_entry(entry); +} + JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out) { JanetBinding binding = janet_resolve_ext(env, sym); if (binding.type == JANET_BINDING_DYNAMIC_DEF || binding.type == JANET_BINDING_DYNAMIC_MACRO) { diff --git a/src/core/util.h b/src/core/util.h index 0c2a8ae8..6f253c89 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -84,6 +84,7 @@ void janet_buffer_format( int32_t argc, Janet *argv); Janet janet_next_impl(Janet ds, Janet key, int is_interpreter); +JanetBinding janet_binding_from_entry(Janet entry); /* Registry functions */ void janet_registry_put(