diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-28 23:15:10 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-28 23:15:10 -0800 |
commit | 94750af472e12acf3a5970c98e4dab6feada2e84 (patch) | |
tree | 0f91686515e864ea184cc866c980ddc979783b0c /rand.c | |
parent | 8c634953700bdf3199b68e8ccf2eff4132ca81d5 (diff) | |
download | txr-94750af472e12acf3a5970c98e4dab6feada2e84.tar.gz txr-94750af472e12acf3a5970c98e4dab6feada2e84.tar.bz2 txr-94750af472e12acf3a5970c98e4dab6feada2e84.zip |
Change in the design of how special variables work, to fix the broken
re-binding. C code now has to go through the dynamic environment lookup
to access things like *random-state*, or *stdout*. As part of this,
I'm moving some intrinsic variable and function initializations out of
eval.c and into their respective modules. Macros are are used to make
global variables look like ordinary C variables. This is very similar
to the errno trick in POSIX threads implementations.
* eval.c (looup_var, lookup_var_l): Restructured to eliminate silly
goto, the cobjp handling is gone.
(reg_fun, reg_var): Internal function becomes external.
reg_var registers a simple cons cell binding now, without any
C pointer tricks to real C global variables.
(c_var_mark): Static function removed.
(c_var_ops): Static struct removed.
(eval_init): Numerous initializations for streams, syslog, rand,
signals and others moved to their respective modules.
The new symbol variables user_package_s, keyword_package_s
and system_package_s are interned here, and the variables are
created in a special way.
* eval.h (reg_var, reg_fun): Declared.
* gc.c (prot1): Added assert that the loc pointer isn't null.
This happened, and blew up during garbage collection.
* lib.c (system_package, keyword_package, user_package): Variables
removed these become macros.
(system_package_var, keyword_package_var, user_package_var): New
global variables.
(system_package_s, keyword_package_s, user_package_s): New
symbol globals.
(get_user_package, get_system_package, get_keyword_package): New
functions.
(obj_init): Protect new variables. Initialization order of modules
tweaked: the modules sig_init, stream_init, and rand_init are moved
after eval_init because they register variables.
* lib.h (keyword_package, system_pckage, user_package): Variables
turned into macros.
(system_package_var, keyword_package_var, user_package_var): Declared.
(system_package_s, keyword_package_s, user_package_s): Declared.
(get_user_package, get_system_package, get_keyword_package): Declared.
* rand.c (struct random_state): Renamed to struct rand_state to
avoid clash with new random_state macro.
(random_state): Global variable removed.
(random_state_s): New symbol global.
(make_state, rand32, make_random_state, random_fixnum, random):
Follow rename of struct random_state.
Diffstat (limited to 'rand.c')
-rw-r--r-- | rand.c | 29 |
1 files changed, 14 insertions, 15 deletions
@@ -43,6 +43,7 @@ #include "gc.h" #include "arith.h" #include "rand.h" +#include "eval.h" #if SIZEOF_INT == 4 typedef unsigned int rand32_t; @@ -54,12 +55,11 @@ typedef unsigned long rand32_t; * The algorithm here is WELL 512. * (Francois Panneton, Pierre L'Ecuyer.) */ -struct random_state { +struct rand_state { rand32_t state[16]; int cur; }; -val random_state; val random_state_s; static struct cobj_ops random_state_ops = { @@ -72,7 +72,7 @@ static struct cobj_ops random_state_ops = { static val make_state(void) { - struct random_state *r = (struct random_state *) chk_malloc(sizeof *r); + struct rand_state *r = (struct rand_state *) chk_malloc(sizeof *r); return cobj((mem_t *) r, random_state_s, &random_state_ops); } @@ -81,7 +81,7 @@ val random_state_p(val obj) return typeof(obj) == random_state_s ? t : nil; } -static rand32_t rand32(struct random_state *r) +static rand32_t rand32(struct rand_state *r) { #define RSTATE(r,i) ((r)->state[((r)->cur + i) % 16]) rand32_t s0 = RSTATE(r, 0); @@ -106,8 +106,7 @@ val make_random_state(val seed) { val rs = make_state(); int i; - struct random_state *r = (struct random_state *) - cobj_handle(rs, random_state_s); + struct rand_state *r = (struct rand_state *) cobj_handle(rs, random_state_s); r->cur = 0; @@ -142,8 +141,8 @@ val make_random_state(val seed) r->state[1] = (rand32_t) c_num(cdr(time)); memset(r->state + 2, 0xAA, sizeof r->state - 2 * sizeof r->state[0]); } else if (random_state_p(seed)) { - struct random_state *rseed = (struct random_state *) - cobj_handle(seed, random_state_s); + struct rand_state *rseed = (struct rand_state *) + cobj_handle(seed, random_state_s); *r = *rseed; } else { uw_throwf(error_s, lit("make-random-state: seed ~s is not a number"), @@ -159,16 +158,16 @@ val make_random_state(val seed) val random_fixnum(val state) { uses_or2; - struct random_state *r = (struct random_state *) - cobj_handle(or2(state, random_state), - random_state_s); + struct rand_state *r = (struct rand_state *) cobj_handle(or2(state, + random_state), + random_state_s); return num(rand32(r) & NUM_MAX); } val random(val state, val modulus) { - struct random_state *r = (struct random_state *) - cobj_handle(random_state, random_state_s); + struct rand_state *r = (struct rand_state *) cobj_handle(random_state, + random_state_s); if (bignump(modulus)) { mp_int *m = mp(modulus); @@ -250,7 +249,7 @@ val rnd(val modulus, val state) void rand_init(void) { - prot1(&random_state); random_state_s = intern(lit("random-state"), user_package); - random_state = make_random_state(num(42)); + reg_var(intern(lit("*random-state*"), user_package), + make_random_state(num_fast(42))); } |