mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-03 11:16:36 +02:00
Updating ephemerons use a context local type id.
Disabling weak vectors for now.
This commit is contained in:
parent
34adcd3b19
commit
74c121f2b2
3 changed files with 96 additions and 17 deletions
|
@ -1,19 +1,16 @@
|
|||
/* weak.c -- weak pointers and ephemerons */
|
||||
/* Copyright (c) 2010-2011 Alex Shinn. All rights reserved. */
|
||||
/* Copyright (c) 2010-2013 Alex Shinn. All rights reserved. */
|
||||
/* BSD-style license: http://synthcode.com/license.txt */
|
||||
|
||||
#include <chibi/eval.h>
|
||||
|
||||
static int sexp_ephemeron_id, sexp_weak_vector_id;
|
||||
|
||||
#define sexp_ephemeronp(x) sexp_check_tag(x, sexp_ephemeron_id)
|
||||
#define sexp_ephemeron_key(x) sexp_slot_ref(x, 0)
|
||||
#define sexp_ephemeron_value(x) sexp_slot_ref(x, 1)
|
||||
|
||||
#define sexp_weak_vector_p(x) sexp_check_tag(x, sexp_weak_vector_id)
|
||||
|
||||
sexp sexp_make_ephemeron (sexp ctx, sexp self, sexp_sint_t n, sexp key, sexp value) {
|
||||
sexp res = sexp_alloc_type(ctx, pair, sexp_ephemeron_id);
|
||||
sexp res = sexp_alloc_type(ctx, pair, sexp_unbox_fixnum(sexp_opcode_return_type(self)));
|
||||
if (! sexp_exceptionp(res)) {
|
||||
sexp_ephemeron_key(res) = key;
|
||||
sexp_ephemeron_value(res) = value;
|
||||
|
@ -22,6 +19,8 @@ sexp sexp_make_ephemeron (sexp ctx, sexp self, sexp_sint_t n, sexp key, sexp val
|
|||
}
|
||||
|
||||
sexp sexp_ephemeron_brokenp_op (sexp ctx, sexp self, sexp_sint_t n, sexp eph) {
|
||||
if (! (sexp_pointerp(eph) && (sexp_pointer_tag(eph) == sexp_unbox_fixnum(sexp_opcode_arg1_type(self)))))
|
||||
return sexp_type_exception(ctx, self, sexp_unbox_fixnum(sexp_opcode_arg1_type(self)), eph);
|
||||
return sexp_make_boolean(sexp_brokenp(eph));
|
||||
}
|
||||
|
||||
|
@ -30,7 +29,7 @@ sexp sexp_make_weak_vector (sexp ctx, sexp self, sexp_sint_t n, sexp len) {
|
|||
int i, clen = sexp_unbox_fixnum(len);
|
||||
sexp_assert_type(ctx, sexp_fixnump, SEXP_FIXNUM, len);
|
||||
vec = sexp_alloc_tagged(ctx, sexp_sizeof(vector) + clen*sizeof(sexp),
|
||||
SEXP_VECTOR);
|
||||
sexp_unbox_fixnum(sexp_opcode_return_type(self)));
|
||||
if (sexp_exceptionp(vec)) return vec;
|
||||
x = sexp_vector_data(vec);
|
||||
for (i=0; i<clen; i++)
|
||||
|
@ -40,25 +39,32 @@ sexp sexp_make_weak_vector (sexp ctx, sexp self, sexp_sint_t n, sexp len) {
|
|||
}
|
||||
|
||||
sexp sexp_weak_vector_length (sexp ctx, sexp self, sexp_sint_t n, sexp v) {
|
||||
sexp_assert_type(ctx, sexp_weak_vector_p, sexp_weak_vector_id, v);
|
||||
if (! (sexp_pointerp(v) && (sexp_pointer_tag(v) == sexp_unbox_fixnum(sexp_opcode_arg1_type(self)))))
|
||||
return sexp_type_exception(ctx, self, sexp_unbox_fixnum(sexp_opcode_arg1_type(self)), v);
|
||||
return sexp_make_fixnum(sexp_vector_length(v));
|
||||
}
|
||||
|
||||
sexp sexp_weak_vector_ref (sexp ctx, sexp self, sexp_sint_t n, sexp v, sexp k) {
|
||||
sexp_assert_type(ctx, sexp_weak_vector_p, sexp_weak_vector_id, v);
|
||||
if (! (sexp_pointerp(v) && (sexp_pointer_tag(v) == sexp_unbox_fixnum(sexp_opcode_arg1_type(self)))))
|
||||
return sexp_type_exception(ctx, self, sexp_unbox_fixnum(sexp_opcode_arg1_type(self)), v);
|
||||
sexp_assert_type(ctx, sexp_fixnump, SEXP_FIXNUM, k);
|
||||
return sexp_vector_ref(v, k);
|
||||
}
|
||||
|
||||
sexp sexp_weak_vector_set (sexp ctx, sexp self, sexp_sint_t n, sexp v, sexp k, sexp x) {
|
||||
sexp_assert_type(ctx, sexp_weak_vector_p, sexp_weak_vector_id, v);
|
||||
if (! (sexp_pointerp(v) && (sexp_pointer_tag(v) == sexp_unbox_fixnum(sexp_opcode_arg1_type(self)))))
|
||||
return sexp_type_exception(ctx, self, sexp_unbox_fixnum(sexp_opcode_arg1_type(self)), v);
|
||||
sexp_assert_type(ctx, sexp_fixnump, SEXP_FIXNUM, k);
|
||||
sexp_vector_set(v, k, x);
|
||||
return SEXP_VOID;
|
||||
}
|
||||
|
||||
sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char* version, sexp_abi_identifier_t abi) {
|
||||
#if 0
|
||||
sexp v;
|
||||
int sexp_weak_vector_id;
|
||||
#endif
|
||||
int sexp_ephemeron_id;
|
||||
sexp_gc_var3(name, t, op);
|
||||
if (!(sexp_version_compatible(ctx, version, sexp_version)
|
||||
&& sexp_abi_compatible(ctx, abi, SEXP_ABI_IDENTIFIER)))
|
||||
|
@ -79,9 +85,17 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
|
|||
sexp_env_define(ctx, env, name=sexp_intern(ctx, "ephemeron-key", -1), op);
|
||||
op = sexp_make_getter(ctx, name=sexp_c_string(ctx, "ephemeron-value", -1), t, SEXP_ONE);
|
||||
sexp_env_define(ctx, env, name=sexp_intern(ctx, "ephemeron-value", -1), op);
|
||||
sexp_define_foreign(ctx, env, "make-ephemeron", 2, sexp_make_ephemeron);
|
||||
sexp_define_foreign(ctx, env, "ephemeron-broken?", 1, sexp_ephemeron_brokenp_op);
|
||||
op = sexp_define_foreign(ctx, env, "make-ephemeron", 2, sexp_make_ephemeron);
|
||||
if (sexp_opcodep(op)) {
|
||||
sexp_opcode_return_type(op) = sexp_make_fixnum(sexp_ephemeron_id);
|
||||
}
|
||||
op = sexp_define_foreign(ctx, env, "ephemeron-broken?", 1, sexp_ephemeron_brokenp_op);
|
||||
if (sexp_opcodep(op)) {
|
||||
sexp_opcode_return_type(op) = sexp_make_fixnum(SEXP_OBJECT);
|
||||
sexp_opcode_arg1_type(op) = sexp_make_fixnum(sexp_ephemeron_id);
|
||||
}
|
||||
|
||||
#if 0
|
||||
name = sexp_c_string(ctx, "Weak-Vector", -1);
|
||||
t = sexp_register_simple_type(ctx, name, SEXP_FALSE, SEXP_ZERO);
|
||||
v = sexp_type_by_index(ctx, SEXP_VECTOR);
|
||||
|
@ -92,10 +106,29 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
|
|||
|
||||
op = sexp_make_type_predicate(ctx, name=sexp_c_string(ctx,"weak-vector?",-1), t);
|
||||
sexp_env_define(ctx, env, name=sexp_intern(ctx, "weak-vector?", -1), op);
|
||||
sexp_define_foreign(ctx, env, "make-weak-vector", 1, sexp_make_weak_vector);
|
||||
sexp_define_foreign(ctx, env, "weak-vector-length", 2, sexp_weak_vector_length);
|
||||
sexp_define_foreign(ctx, env, "weak-vector-ref", 2, sexp_weak_vector_ref);
|
||||
sexp_define_foreign(ctx, env, "weak-vector-set!", 3, sexp_weak_vector_set);
|
||||
op = sexp_define_foreign(ctx, env, "make-weak-vector", 1, sexp_make_weak_vector);
|
||||
if (sexp_opcodep(op)) {
|
||||
sexp_opcode_return_type(op) = sexp_make_fixnum(sexp_weak_vector_id);
|
||||
sexp_opcode_arg1_type(op) = sexp_make_fixnum(SEXP_FIXNUM);
|
||||
}
|
||||
op = sexp_define_foreign(ctx, env, "weak-vector-length", 2, sexp_weak_vector_length);
|
||||
if (sexp_opcodep(op)) {
|
||||
sexp_opcode_return_type(op) = sexp_make_fixnum(SEXP_FIXNUM);
|
||||
sexp_opcode_arg1_type(op) = sexp_make_fixnum(sexp_weak_vector_id);
|
||||
}
|
||||
op = sexp_define_foreign(ctx, env, "weak-vector-ref", 2, sexp_weak_vector_ref);
|
||||
if (sexp_opcodep(op)) {
|
||||
sexp_opcode_return_type(op) = sexp_make_fixnum(SEXP_OBJECT);
|
||||
sexp_opcode_arg1_type(op) = sexp_make_fixnum(sexp_weak_vector_id);
|
||||
sexp_opcode_arg2_type(op) = sexp_make_fixnum(SEXP_FIXNUM);
|
||||
}
|
||||
op = sexp_define_foreign(ctx, env, "weak-vector-set!", 3, sexp_weak_vector_set);
|
||||
if (sexp_opcodep(op)) {
|
||||
sexp_opcode_return_type(op) = SEXP_VOID;
|
||||
sexp_opcode_arg1_type(op) = sexp_make_fixnum(sexp_weak_vector_id);
|
||||
sexp_opcode_arg2_type(op) = sexp_make_fixnum(SEXP_FIXNUM);
|
||||
}
|
||||
#endif
|
||||
|
||||
sexp_gc_release3(ctx);
|
||||
return SEXP_VOID;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
(define-library (chibi weak)
|
||||
(export make-ephemeron ephemeron? ephemeron-broken?
|
||||
ephemeron-key ephemeron-value
|
||||
make-weak-vector weak-vector? weak-vector-length
|
||||
weak-vector-ref weak-vector-set!)
|
||||
;; make-weak-vector weak-vector? weak-vector-length
|
||||
;; weak-vector-ref weak-vector-set!
|
||||
)
|
||||
(include-shared "weak"))
|
||||
|
|
45
tests/weak-tests.scm
Normal file
45
tests/weak-tests.scm
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
(import (chibi weak) (chibi ast) (only (chibi test) test-begin test test-end))
|
||||
|
||||
(test-begin "weak pointers")
|
||||
|
||||
(test "preserved key and value" '("key" "value" #f)
|
||||
(let ((key (string-append "key"))
|
||||
(value (string-append "value")))
|
||||
(let ((eph (make-ephemeron key value)))
|
||||
(gc)
|
||||
(list key (ephemeron-value eph) (ephemeron-broken? eph)))))
|
||||
|
||||
(test "unpreserved key and value" '(#f #f #t)
|
||||
(let ((eph (make-ephemeron (string-append "key") (string-append "value"))))
|
||||
(gc)
|
||||
(list (ephemeron-key eph) (ephemeron-value eph) (ephemeron-broken? eph))))
|
||||
|
||||
(test "unpreserved key and preserved value" '(#f "value" #t)
|
||||
(let ((value (string-append "value")))
|
||||
(let ((eph (make-ephemeron (string-append "key") value)))
|
||||
(gc)
|
||||
(list (ephemeron-key eph) value (ephemeron-broken? eph)))))
|
||||
|
||||
(test "unpreserved value references unpreserved key" '(#f #f #t)
|
||||
(let ((key (string-append "key")))
|
||||
(let ((eph (make-ephemeron key (cons (string-append "value") key))))
|
||||
(gc)
|
||||
(list (ephemeron-key eph) (ephemeron-value eph) (ephemeron-broken? eph)))))
|
||||
|
||||
;; disabled - we support weak keys, but not proper ephemerons
|
||||
|
||||
'(test "preserved key and unpreserved value" '("key" "value" #f)
|
||||
(let ((key (string-append "key")))
|
||||
(let ((eph (make-ephemeron key (string-append "value"))))
|
||||
(gc)
|
||||
(list key (ephemeron-value eph) (ephemeron-broken? eph)))))
|
||||
|
||||
'(test "preserved value references unpreserved key" '(#f #f #t)
|
||||
(let* ((key (string-append "key"))
|
||||
(value (cons (string-append "value") key)))
|
||||
(let ((eph (make-ephemeron key value)))
|
||||
(gc)
|
||||
(list (ephemeron-key eph) value (ephemeron-broken? eph)))))
|
||||
|
||||
(test-end)
|
Loading…
Add table
Reference in a new issue