From 5b5a7e5a243e9be0274a0df575d6e94c9da2b4ca Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 8 Jan 2022 10:57:14 -0600 Subject: [PATCH] Make top level vars reuse ref cell when redefined at the top level. This improves the repl experience while not messing with existing code very much, if at all. --- src/core/ev.c | 3 --- src/core/specials.c | 27 ++++++++++++++++----------- src/core/util.c | 13 +++++++------ test/suite0000.janet | 10 ---------- 4 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/core/ev.c b/src/core/ev.c index d37cb4f6..e143b532 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -1614,9 +1614,6 @@ JanetTimestamp to_interval(const JanetTimestamp ts) { } #define JANET_KQUEUE_INTERVAL(timestamp) (to_interval((timestamp - ts_now()))) - -/* TODO: make this available be we using kqueue or epoll, instead of - * redefinining it for kqueue and epoll separately? */ static JanetTimestamp ts_now(void) { struct timespec now; janet_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &now), "failed to get time"); diff --git a/src/core/specials.c b/src/core/specials.c index ede62824..9ccf8879 100644 --- a/src/core/specials.c +++ b/src/core/specials.c @@ -298,8 +298,20 @@ static int varleaf( /* Global var, generate var */ JanetSlot refslot; JanetTable *entry = janet_table_clone(reftab); - JanetArray *ref = janet_array(1); - janet_array_push(ref, janet_wrap_nil()); + + Janet redef_kw = janet_ckeywordv("redef"); + int is_redef = janet_truthy(janet_table_get(c->env, redef_kw)); + + JanetArray *ref; + JanetBinding old_binding; + if (is_redef && (old_binding = janet_resolve_ext(c->env, sym), + old_binding.type == JANET_BINDING_VAR)) { + ref = janet_unwrap_array(old_binding.value); + } else { + ref = janet_array(1); + janet_array_push(ref, janet_wrap_nil()); + } + janet_table_put(entry, janet_ckeywordv("ref"), janet_wrap_array(ref)); janet_table_put(entry, janet_ckeywordv("source-map"), janet_wrap_tuple(janetc_make_sourcemap(c))); @@ -332,16 +344,9 @@ static int defleaf( janet_table_put(entry, janet_ckeywordv("source-map"), janet_wrap_tuple(janetc_make_sourcemap(c))); - int is_redef = 0; Janet redef_kw = janet_ckeywordv("redef"); - Janet meta_redef = janet_table_get(entry, redef_kw); - if (janet_truthy(meta_redef)) { - is_redef = 1; - } else if (janet_checktype(meta_redef, JANET_NIL) && - janet_truthy(janet_table_get(c->env, redef_kw))) { - janet_table_put(entry, redef_kw, janet_wrap_true()); - is_redef = 1; - } + int is_redef = janet_truthy(janet_table_get(c->env, redef_kw)); + if (is_redef) janet_table_put(entry, redef_kw, janet_wrap_true()); if (is_redef) { JanetBinding binding = janet_resolve_ext(c->env, sym); diff --git a/src/core/util.c b/src/core/util.c index 706e3646..8a1fcad6 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -626,10 +626,11 @@ JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) { binding.deprecation = JANET_BINDING_DEP_NORMAL; } - int redef = janet_truthy(janet_table_get(entry_table, janet_ckeywordv("redef"))); int macro = janet_truthy(janet_table_get(entry_table, janet_ckeywordv("macro"))); Janet value = janet_table_get(entry_table, janet_ckeywordv("value")); Janet ref = janet_table_get(entry_table, janet_ckeywordv("ref")); + int ref_is_valid = janet_checktype(ref, JANET_ARRAY); + int redef = ref_is_valid && janet_truthy(janet_table_get(entry_table, janet_ckeywordv("redef"))); if (macro) { binding.value = redef ? ref : value; @@ -637,14 +638,14 @@ JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) { return binding; } - if (!redef && janet_checktype(ref, JANET_ARRAY)) { + if (ref_is_valid) { binding.value = ref; - binding.type = JANET_BINDING_VAR; - return binding; + binding.type = redef ? JANET_BINDING_DYNAMIC_DEF : JANET_BINDING_VAR; + } else { + binding.value = value; + binding.type = JANET_BINDING_DEF; } - binding.value = redef ? ref : value; - binding.type = redef ? JANET_BINDING_DYNAMIC_DEF : JANET_BINDING_DEF; return binding; } diff --git a/test/suite0000.janet b/test/suite0000.janet index d3a46400..99b8a8db 100644 --- a/test/suite0000.janet +++ b/test/suite0000.janet @@ -302,17 +302,7 @@ (assert (= 1 (staticdef1-inc)) "before redefinition without :redef") (def staticdef1 1) (assert (= 1 (staticdef1-inc)) "after redefinition without :redef") -(def dynamicdef1 :redef 0) -(defn dynamicdef1-inc [] (+ 1 dynamicdef1)) -(assert (= 1 (dynamicdef1-inc)) "before redefinition with :redef") -(def dynamicdef1 :redef 1) -(assert (= 2 (dynamicdef1-inc)) "after redefinition with :redef") (setdyn :redef true) -(def staticdef2 {:redef false} 0) -(defn staticdef2-inc [] (+ 1 staticdef2)) -(assert (= 1 (staticdef2-inc)) "before redefinition with :redef false") -(def staticdef2 {:redef false} 1) -(assert (= 1 (staticdef2-inc)) "after redefinition with :redef false") (def dynamicdef2 0) (defn dynamicdef2-inc [] (+ 1 dynamicdef2)) (assert (= 1 (dynamicdef2-inc)) "before redefinition with dyn :redefs")