1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 03:30:27 +02:00

change to format of memoization lambda expressions

* libguile/memoize.c (scm_m_lambda, memoize_named_let)
  (scm_memoize_lambda, unmemoize)
* libguile/eval.c (eval, prepare_boot_closure_env_for_apply)
  (prepare_boot_closure_env_for_eval, boot_closure_apply):
* module/ice-9/eval.scm (primitive-eval): Change the format for memoized
  lambda expressions, so as to allow, in the future, case-lambda* to be
  supported by the evaluator.
This commit is contained in:
Andy Wingo 2010-05-12 12:17:18 +02:00
parent cc00f44743
commit 8f9c5b589d
3 changed files with 119 additions and 80 deletions

View file

@ -106,10 +106,19 @@ static scm_t_bits scm_tc16_boot_closure;
#define BOOT_CLOSURE_P(obj) SCM_TYP16_PREDICATE (scm_tc16_boot_closure, (obj))
#define BOOT_CLOSURE_CODE(x) SCM_SMOB_OBJECT (x)
#define BOOT_CLOSURE_ENV(x) SCM_SMOB_OBJECT_2 (x)
#define BOOT_CLOSURE_NUM_REQUIRED_ARGS(x) SCM_I_INUM (CAR (BOOT_CLOSURE_CODE (x)))
#define BOOT_CLOSURE_HAS_REST_ARGS(x) scm_is_true (CADR (BOOT_CLOSURE_CODE (x)))
#define BOOT_CLOSURE_BODY(x) CDDR (BOOT_CLOSURE_CODE (x))
#define BOOT_CLOSURE_BODY(x) CAR (BOOT_CLOSURE_CODE (x))
#define BOOT_CLOSURE_NUM_REQUIRED_ARGS(x) SCM_I_INUM (CADR (BOOT_CLOSURE_CODE (x)))
#define BOOT_CLOSURE_IS_FIXED(x) scm_is_null (CDDR (BOOT_CLOSURE_CODE (x)))
/* NB: One may only call the following accessors if the closure is not FIXED. */
#define BOOT_CLOSURE_HAS_REST_ARGS(x) scm_is_true (CADDR (BOOT_CLOSURE_CODE (x)))
#define BOOT_CLOSURE_IS_REST(x) scm_is_null (CDDDR (BOOT_CLOSURE_CODE (x)))
/* NB: One may only call the following accessors if the closure is not REST. */
#define BOOT_CLOSURE_IS_FULL(x) (1)
#define BOOT_CLOSURE_OPT(x) CAR (CDDDR (BOOT_CLOSURE_CODE (x)))
#define BOOT_CLOSURE_ALT(x) CADR (CDDDR (BOOT_CLOSURE_CODE (x)))
static SCM prepare_boot_closure_env_for_apply (SCM proc, SCM args);
static SCM prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
SCM exps, SCM env);
#define CAR(x) SCM_CAR(x)
@ -238,25 +247,8 @@ eval (SCM x, SCM env)
* ARGS is the list of arguments. */
if (BOOT_CLOSURE_P (proc))
{
int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
SCM new_env = BOOT_CLOSURE_ENV (proc);
if (BOOT_CLOSURE_HAS_REST_ARGS (proc))
{
if (SCM_UNLIKELY (scm_ilength (args) < nreq))
scm_wrong_num_args (proc);
for (; nreq; nreq--, args = CDR (args))
new_env = scm_cons (CAR (args), new_env);
new_env = scm_cons (args, new_env);
}
else
{
if (SCM_UNLIKELY (scm_ilength (args) != nreq))
scm_wrong_num_args (proc);
for (; scm_is_pair (args); args = CDR (args))
new_env = scm_cons (CAR (args), new_env);
}
x = BOOT_CLOSURE_BODY (proc);
env = new_env;
env = prepare_boot_closure_env_for_apply (proc, args);
goto loop;
}
else
@ -270,31 +262,8 @@ eval (SCM x, SCM env)
if (BOOT_CLOSURE_P (proc))
{
int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
SCM new_env = BOOT_CLOSURE_ENV (proc);
if (BOOT_CLOSURE_HAS_REST_ARGS (proc))
{
if (SCM_UNLIKELY (argc < nreq))
scm_wrong_num_args (proc);
for (; nreq; nreq--, mx = CDR (mx))
new_env = scm_cons (eval (CAR (mx), env), new_env);
{
SCM rest = SCM_EOL;
for (; scm_is_pair (mx); mx = CDR (mx))
rest = scm_cons (eval (CAR (mx), env), rest);
new_env = scm_cons (scm_reverse (rest),
new_env);
}
}
else
{
for (; scm_is_pair (mx); mx = CDR (mx), nreq--)
new_env = scm_cons (eval (CAR (mx), env), new_env);
if (SCM_UNLIKELY (nreq != 0))
scm_wrong_num_args (proc);
}
x = BOOT_CLOSURE_BODY (proc);
env = new_env;
env = prepare_boot_closure_env_for_eval (proc, argc, mx, env);
goto loop;
}
else
@ -908,28 +877,73 @@ scm_apply (SCM proc, SCM arg1, SCM args)
return scm_vm_apply (scm_the_vm (), proc, args);
}
static SCM
prepare_boot_closure_env_for_apply (SCM proc, SCM args)
{
int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
SCM env = BOOT_CLOSURE_ENV (proc);
if (BOOT_CLOSURE_IS_FIXED (proc)
|| (BOOT_CLOSURE_IS_REST (proc)
&& !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
{
if (SCM_UNLIKELY (scm_ilength (args) != nreq))
scm_wrong_num_args (proc);
for (; scm_is_pair (args); args = CDR (args))
env = scm_cons (CAR (args), env);
}
else if (BOOT_CLOSURE_IS_REST (proc))
{
if (SCM_UNLIKELY (scm_ilength (args) < nreq))
scm_wrong_num_args (proc);
for (; nreq; nreq--, args = CDR (args))
env = scm_cons (CAR (args), env);
env = scm_cons (args, env);
}
else
abort ();
return env;
}
static SCM
prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
SCM exps, SCM env)
{
int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
SCM new_env = BOOT_CLOSURE_ENV (proc);
if (BOOT_CLOSURE_IS_FIXED (proc)
|| (BOOT_CLOSURE_IS_REST (proc)
&& !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
{
for (; scm_is_pair (exps); exps = CDR (exps), nreq--)
new_env = scm_cons (eval (CAR (exps), env), new_env);
if (SCM_UNLIKELY (nreq != 0))
scm_wrong_num_args (proc);
}
else if (BOOT_CLOSURE_IS_REST (proc))
{
if (SCM_UNLIKELY (argc < nreq))
scm_wrong_num_args (proc);
for (; nreq; nreq--, exps = CDR (exps))
new_env = scm_cons (eval (CAR (exps), env), new_env);
{
SCM rest = SCM_EOL;
for (; scm_is_pair (exps); exps = CDR (exps))
rest = scm_cons (eval (CAR (exps), env), rest);
new_env = scm_cons (scm_reverse (rest),
new_env);
}
}
else
abort ();
return new_env;
}
static SCM
boot_closure_apply (SCM closure, SCM args)
{
int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure);
SCM new_env = BOOT_CLOSURE_ENV (closure);
if (BOOT_CLOSURE_HAS_REST_ARGS (closure))
{
if (SCM_UNLIKELY (scm_ilength (args) < nreq))
scm_wrong_num_args (closure);
for (; nreq; nreq--, args = CDR (args))
new_env = scm_cons (CAR (args), new_env);
new_env = scm_cons (args, new_env);
}
else
{
if (SCM_UNLIKELY (scm_ilength (args) != nreq))
scm_wrong_num_args (closure);
for (; scm_is_pair (args); args = CDR (args))
new_env = scm_cons (CAR (args), new_env);
}
return eval (BOOT_CLOSURE_BODY (closure), new_env);
return eval (BOOT_CLOSURE_BODY (closure),
prepare_boot_closure_env_for_apply (closure, args));
}
static int
@ -941,7 +955,7 @@ boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
scm_putc (' ', port);
args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
scm_from_locale_symbol ("_"));
if (BOOT_CLOSURE_HAS_REST_ARGS (closure))
if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
args = scm_cons_star (scm_from_locale_symbol ("_"), args);
scm_display (args, port);
scm_putc ('>', port);

View file

@ -179,8 +179,15 @@ scm_t_bits scm_tc16_memoized;
MAKMEMO (SCM_M_BEGIN, exps)
#define MAKMEMO_IF(test, then, else_) \
MAKMEMO (SCM_M_IF, scm_cons (test, scm_cons (then, else_)))
#define MAKMEMO_LAMBDA(nreq, rest, body) \
MAKMEMO (SCM_M_LAMBDA, scm_cons (SCM_I_MAKINUM (nreq), scm_cons (rest, body)))
#define FIXED_ARITY(nreq) \
scm_list_1 (SCM_I_MAKINUM (nreq))
#define REST_ARITY(nreq, rest) \
scm_list_2 (SCM_I_MAKINUM (nreq), rest)
/* opts := #f | (aok? (pos? kw init) ...) */
#define FULL_ARITY(nreq, rest, opts, alt) \
scm_list_4 (SCM_I_MAKINUM (nreq), rest, opts, alt)
#define MAKMEMO_LAMBDA(body, arity) \
MAKMEMO (SCM_M_LAMBDA, (scm_cons (body, arity)))
#define MAKMEMO_LET(inits, body) \
MAKMEMO (SCM_M_LET, scm_cons (inits, body))
#define MAKMEMO_QUOTE(exp) \
@ -676,6 +683,7 @@ scm_m_lambda (SCM expr, SCM env SCM_UNUSED)
SCM formals;
SCM formals_idx;
SCM formal_vars = SCM_EOL;
SCM body;
int nreq = 0;
const SCM cdr_expr = CDR (expr);
@ -715,9 +723,13 @@ scm_m_lambda (SCM expr, SCM env SCM_UNUSED)
s_bad_formal, formals_idx, expr);
if (scm_is_symbol (formals_idx))
formal_vars = scm_cons (formals_idx, formal_vars);
return MAKMEMO_LAMBDA (nreq, scm_symbol_p (formals_idx),
memoize_sequence (CDDR (expr),
memoize_env_extend (env, formal_vars)));
body = memoize_sequence (CDDR (expr), memoize_env_extend (env, formal_vars));
if (scm_is_symbol (formals_idx))
return MAKMEMO_LAMBDA (body, REST_ARITY (nreq, SCM_BOOL_T));
else
return MAKMEMO_LAMBDA (body, FIXED_ARITY (nreq));
}
/* Check if the format of the bindings is ((<symbol> <init-form>) ...). */
@ -796,10 +808,10 @@ memoize_named_let (const SCM expr, SCM env)
MAKMEMO_BEGIN
(scm_list_2 (MAKMEMO_LEX_SET
(0,
MAKMEMO_LAMBDA
(nreq, SCM_BOOL_F,
memoize_sequence (CDDDR (expr),
memoize_env_extend (env, rvariables)))),
MAKMEMO_LAMBDA (memoize_sequence
(CDDDR (expr),
memoize_env_extend (env, rvariables)),
FIXED_ARITY (nreq))),
MAKMEMO_CALL (MAKMEMO_LEX_REF (0),
nreq,
memoize_exprs (inits, env)))));
@ -1118,7 +1130,7 @@ SCM_DEFINE (scm_memoize_lambda, "memoize-lambda", 3, 0, 0,
{
SCM_VALIDATE_BOOL (2, rest);
SCM_VALIDATE_MEMOIZED (3, body);
return MAKMEMO_LAMBDA (scm_to_uint16 (nreq), rest, body);
return MAKMEMO_LAMBDA (body, REST_ARITY (scm_to_uint16 (nreq), rest));
}
#undef FUNC_NAME
@ -1323,9 +1335,21 @@ unmemoize (const SCM expr)
return scm_list_4 (scm_sym_if, unmemoize (scm_car (args)),
unmemoize (scm_cadr (args)), unmemoize (scm_cddr (args)));
case SCM_M_LAMBDA:
return scm_list_3 (scm_sym_lambda,
scm_make_list (CAR (args), sym_placeholder),
unmemoize (CDDR (args)));
if (scm_is_null (CDDR (args)))
return scm_list_3 (scm_sym_lambda,
scm_make_list (CADR (args), sym_placeholder),
unmemoize (CAR (args)));
else if (scm_is_null (CDDDR (args)))
{
SCM formals = scm_make_list (CADR (args), sym_placeholder);
return scm_list_3 (scm_sym_lambda,
scm_is_true (CADDR (args))
? scm_cons_star (sym_placeholder, formals)
: formals,
unmemoize (CAR (args)));
}
else
abort ();
case SCM_M_LET:
return scm_list_3 (scm_sym_let,
unmemoize_bindings (CAR (args)),

View file

@ -255,8 +255,9 @@
(lp (cdr inits)
(cons (eval (car inits) env) new-env)))))
(('lambda (nreq rest? . body))
(make-closure eval nreq rest? body (capture-env env)))
(('lambda (body nreq . tail))
(make-closure eval nreq (and (pair? tail) (car tail))
body (capture-env env)))
(('begin (first . rest))
(let lp ((first first) (rest rest))