summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@oblong.net>2009-03-17 16:40:52 +0100
committerAndy Wingo <wingo@oblong.net>2009-03-17 16:40:52 +0100
commit3b91e017e32e1fb6b911f456c61aea6386075095 (patch)
tree23ec6a0c667756eb48148ada7704086eb489964d
parent325226dad9ab6f0488500e7381a5d1c07dc9ae91 (diff)
parente20d7001c3f7150400169fecb0bf0eefdf122fe2 (diff)
downloadguile-3b91e017e32e1fb6b911f456c61aea6386075095.tar.gz
Merge commit 'e20d7001c3f7150400169fecb0bf0eefdf122fe2' into vm-check
Conflicts: libguile/stacks.c
-rw-r--r--NEWS5
-rw-r--r--benchmark-suite/Makefile.am1
-rw-r--r--benchmark-suite/benchmarks/subr.bm46
-rw-r--r--libguile/__scm.h4
-rw-r--r--libguile/debug.c8
-rw-r--r--libguile/eval.c8
-rw-r--r--libguile/eval.i.c46
-rw-r--r--libguile/evalext.c3
-rw-r--r--libguile/gc-card.c14
-rw-r--r--libguile/gc-mark.c15
-rw-r--r--libguile/goops.c4
-rw-r--r--libguile/gsubr.c78
-rw-r--r--libguile/gsubr.h16
-rw-r--r--libguile/print.c27
-rw-r--r--libguile/procprop.c25
-rw-r--r--libguile/procs.c47
-rw-r--r--libguile/procs.h17
-rw-r--r--libguile/stacks.c8
-rw-r--r--libguile/tags.h5
-rw-r--r--test-suite/Makefile.am3
-rw-r--r--test-suite/tests/eval.test65
-rw-r--r--test-suite/tests/goops.test20
-rw-r--r--test-suite/tests/procprop.test61
23 files changed, 281 insertions, 245 deletions
diff --git a/NEWS b/NEWS
index 2d9916c5d..5e3f7ae4f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,5 @@
Guile NEWS --- history of user-visible changes.
-Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
See the end for copying conditions.
Please send Guile bug reports to bug-guile@gnu.org.
@@ -40,6 +40,9 @@ application code.
** Functions for handling `scm_option' now no longer require an argument
indicating length of the `scm_t_option' array.
+** Primitive procedures (aka. "subrs") are now stored in double cells
+This removes the subr table and simplifies the code.
+
Changes in 1.8.7 (since 1.8.6)
diff --git a/benchmark-suite/Makefile.am b/benchmark-suite/Makefile.am
index 5357cf050..e65e8bcb2 100644
--- a/benchmark-suite/Makefile.am
+++ b/benchmark-suite/Makefile.am
@@ -3,6 +3,7 @@ SCM_BENCHMARKS = benchmarks/0-reference.bm \
benchmarks/if.bm \
benchmarks/logand.bm \
benchmarks/read.bm \
+ benchmarks/subr.bm \
benchmarks/uniform-vector-read.bm
EXTRA_DIST = guile-benchmark lib.scm $(SCM_BENCHMARKS) \
diff --git a/benchmark-suite/benchmarks/subr.bm b/benchmark-suite/benchmarks/subr.bm
new file mode 100644
index 000000000..fbb9ed386
--- /dev/null
+++ b/benchmark-suite/benchmarks/subr.bm
@@ -0,0 +1,46 @@
+;;; subr.bm --- Measure the subr invocation cost. -*- Scheme -*-
+;;;
+;;; Copyright (C) 2009 Free Software Foundation, Inc.
+;;;
+;;; This program is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this software; see the file COPYING. If not, write to
+;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;;; Boston, MA 02110-1301 USA
+
+(define-module (benchmarks subrs)
+ :use-module (benchmark-suite lib))
+
+
+(with-benchmark-prefix "subr invocation"
+
+ (benchmark "simple subr" 700000
+ ;; 1 required argument, 0 optional arguments, no rest.
+ (1+ 0))
+
+ (benchmark "generic subr" 700000
+ ;; 2 required arguments, 4 optional arguments, no rest.
+
+ ;; In Guile 1.8 and earlier, such subrs are implemented as "compiled
+ ;; closures" (cclos). There, when a cclo/gsubr is called, the evaluator
+ ;; goes through `SCM_APPLY ()' and conses the arguments, which is more
+ ;; costly than the invocation of a "simple subr".
+ (string= "foo" "bar")))
+
+
+(with-benchmark-prefix "subr application"
+
+ (benchmark "simple subr" 700000
+ (apply 1+ '(0)))
+
+ (benchmark "generic subr" 700000
+ (apply string= "foo" '("bar"))))
diff --git a/libguile/__scm.h b/libguile/__scm.h
index d486b69bf..3672b1c09 100644
--- a/libguile/__scm.h
+++ b/libguile/__scm.h
@@ -3,7 +3,7 @@
#ifndef SCM___SCM_H
#define SCM___SCM_H
-/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -140,8 +140,6 @@
*/
-#define CCLO
-
/* Guile Scheme supports the #f/() distinction; Guile Lisp won't. We
have horrible plans for their unification. */
#undef SICP
diff --git a/libguile/debug.c b/libguile/debug.c
index ac9a89143..5d0e20899 100644
--- a/libguile/debug.c
+++ b/libguile/debug.c
@@ -1,5 +1,5 @@
/* Debugging extensions for Guile
- * Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008 Free Software Foundation
+ * Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008, 2009 Free Software Foundation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -357,9 +357,6 @@ SCM_DEFINE (scm_procedure_source, "procedure-source", 1, 0, 0,
if (!SCM_SMOB_DESCRIPTOR (proc).apply)
break;
case scm_tcs_subrs:
-#ifdef CCLO
- case scm_tc7_cclo:
-#endif
procprop:
/* It would indeed be a nice thing if we supplied source even for
built in procedures! */
@@ -390,9 +387,6 @@ SCM_DEFINE (scm_procedure_environment, "procedure-environment", 1, 0, 0,
case scm_tcs_closures:
return SCM_ENV (proc);
case scm_tcs_subrs:
-#ifdef CCLO
- case scm_tc7_cclo:
-#endif
return SCM_EOL;
default:
SCM_WRONG_TYPE_ARG (1, proc);
diff --git a/libguile/eval.c b/libguile/eval.c
index 73ad5dde1..48b229903 100644
--- a/libguile/eval.c
+++ b/libguile/eval.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009
* Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -3269,7 +3269,7 @@ scm_trampoline_0 (SCM proc)
break;
case scm_tc7_asubr:
case scm_tc7_rpsubr:
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
case scm_tc7_pws:
trampoline = scm_call_0;
break;
@@ -3395,7 +3395,7 @@ scm_trampoline_1 (SCM proc)
break;
case scm_tc7_asubr:
case scm_tc7_rpsubr:
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
case scm_tc7_pws:
trampoline = scm_call_1;
break;
@@ -3489,7 +3489,7 @@ scm_trampoline_2 (SCM proc)
else
return NULL;
break;
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
case scm_tc7_pws:
trampoline = scm_call_2;
break;
diff --git a/libguile/eval.i.c b/libguile/eval.i.c
index b208f01b0..ff3b45e18 100644
--- a/libguile/eval.i.c
+++ b/libguile/eval.i.c
@@ -1,7 +1,7 @@
/*
* eval.i.c - actual evaluator code for GUILE
*
- * Copyright (C) 2002, 03, 04, 05, 06, 07 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 03, 04, 05, 06, 07, 09 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1135,14 +1135,12 @@ dispatch:
if (!SCM_SMOB_APPLICABLE_P (proc))
goto badfun;
RETURN (SCM_SMOB_APPLY_0 (proc));
- case scm_tc7_cclo:
- arg1 = proc;
- proc = SCM_CCLO_SUBR (proc);
+ case scm_tc7_gsubr:
#ifdef DEVAL
debug.info->a.proc = proc;
- debug.info->a.args = scm_list_1 (arg1);
+ debug.info->a.args = SCM_EOL;
#endif
- goto evap1;
+ RETURN (scm_gsubr_apply (scm_list_1 (proc)));
case scm_tc7_pws:
proc = SCM_PROCEDURE (proc);
#ifdef DEVAL
@@ -1256,15 +1254,12 @@ dispatch:
if (!SCM_SMOB_APPLICABLE_P (proc))
goto badfun;
RETURN (SCM_SMOB_APPLY_1 (proc, arg1));
- case scm_tc7_cclo:
- arg2 = arg1;
- arg1 = proc;
- proc = SCM_CCLO_SUBR (proc);
+ case scm_tc7_gsubr:
#ifdef DEVAL
debug.info->a.args = scm_cons (arg1, debug.info->a.args);
debug.info->a.proc = proc;
#endif
- goto evap2;
+ RETURN (scm_gsubr_apply (scm_list_2 (proc, arg1)));
case scm_tc7_pws:
proc = SCM_PROCEDURE (proc);
#ifdef DEVAL
@@ -1362,19 +1357,14 @@ dispatch:
goto badfun;
RETURN (SCM_SMOB_APPLY_2 (proc, arg1, arg2));
cclon:
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
#ifdef DEVAL
- RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
- scm_cons (proc, debug.info->a.args),
- SCM_EOL));
+ RETURN (scm_gsubr_apply (scm_cons (proc, debug.info->a.args)));
#else
- RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
- scm_cons2 (proc, arg1,
- scm_cons (arg2,
- scm_ceval_args (x,
- env,
- proc))),
- SCM_EOL));
+ RETURN (scm_gsubr_apply
+ (scm_cons (proc,
+ scm_cons2 (arg1, arg2,
+ scm_ceval_args (x, env, proc)))));
#endif
case scm_tcs_struct:
if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
@@ -1503,7 +1493,7 @@ dispatch:
goto badfun;
RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
SCM_CDDR (debug.info->a.args)));
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
goto cclon;
case scm_tc7_pws:
proc = SCM_PROCEDURE (proc);
@@ -1566,7 +1556,7 @@ dispatch:
goto badfun;
RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
scm_ceval_args (x, env, proc)));
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
goto cclon;
case scm_tc7_pws:
proc = SCM_PROCEDURE (proc);
@@ -1878,19 +1868,15 @@ tail:
RETURN (SCM_SMOB_APPLY_2 (proc, arg1, SCM_CAR (args)));
else
RETURN (SCM_SMOB_APPLY_3 (proc, arg1, SCM_CAR (args), SCM_CDR (args)));
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
#ifdef DEVAL
args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
- arg1 = proc;
- proc = SCM_CCLO_SUBR (proc);
debug.vect[0].a.proc = proc;
debug.vect[0].a.args = scm_cons (arg1, args);
#else
args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
- arg1 = proc;
- proc = SCM_CCLO_SUBR (proc);
#endif
- goto tail;
+ RETURN (scm_gsubr_apply (scm_cons (proc, args)));
case scm_tc7_pws:
proc = SCM_PROCEDURE (proc);
#ifdef DEVAL
diff --git a/libguile/evalext.c b/libguile/evalext.c
index 9bec8f410..5ca78066d 100644
--- a/libguile/evalext.c
+++ b/libguile/evalext.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998,1999,2000,2001,2002,2003, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1998,1999,2000,2001,2002,2003, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -106,7 +106,6 @@ SCM_DEFINE (scm_self_evaluating_p, "self-evaluating?", 1, 0, 0,
case scm_tc7_number:
case scm_tc7_string:
case scm_tc7_smob:
- case scm_tc7_cclo:
case scm_tc7_pws:
case scm_tcs_subrs:
case scm_tcs_struct:
diff --git a/libguile/gc-card.c b/libguile/gc-card.c
index 1948aff1b..0629da078 100644
--- a/libguile/gc-card.c
+++ b/libguile/gc-card.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -131,14 +131,6 @@ scm_i_sweep_card (scm_t_cell *card, SCM *free_list, scm_t_heap_segment *seg)
scm_i_vector_free (scmptr);
break;
-#ifdef CCLO
- case scm_tc7_cclo:
- scm_gc_free (SCM_CCLO_BASE (scmptr),
- SCM_CCLO_LENGTH (scmptr) * sizeof (SCM),
- "compiled closure");
- break;
-#endif
-
case scm_tc7_number:
switch SCM_TYP16 (scmptr)
{
@@ -397,10 +389,6 @@ scm_i_tag_name (scm_t_bits tag)
return "weak vector";
case scm_tc7_vector:
return "vector";
-#ifdef CCLO
- case scm_tc7_cclo:
- return "compiled closure";
-#endif
case scm_tc7_number:
switch (tag)
{
diff --git a/libguile/gc-mark.c b/libguile/gc-mark.c
index ab629f262..4eef19102 100644
--- a/libguile/gc-mark.c
+++ b/libguile/gc-mark.c
@@ -294,21 +294,6 @@ scm_gc_mark_dependencies (SCM p)
}
ptr = SCM_SIMPLE_VECTOR_REF (ptr, 0);
goto gc_mark_loop;
-#ifdef CCLO
- case scm_tc7_cclo:
- {
- size_t i = SCM_CCLO_LENGTH (ptr);
- size_t j;
- for (j = 1; j != i; ++j)
- {
- SCM obj = SCM_CCLO_REF (ptr, j);
- if (!SCM_IMP (obj))
- scm_gc_mark (obj);
- }
- ptr = SCM_CCLO_REF (ptr, 0);
- goto gc_mark_loop;
- }
-#endif
case scm_tc7_string:
ptr = scm_i_string_mark (ptr);
diff --git a/libguile/goops.c b/libguile/goops.c
index 2fc6c317b..b623212ad 100644
--- a/libguile/goops.c
+++ b/libguile/goops.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008
+/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009
* Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -239,7 +239,7 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
return scm_class_primitive_generic;
else
return scm_class_procedure;
- case scm_tc7_cclo:
+ case scm_tc7_gsubr:
return scm_class_procedure;
case scm_tc7_pws:
return scm_class_procedure_with_setter;
diff --git a/libguile/gsubr.c b/libguile/gsubr.c
index fdb70ed92..91852d5b8 100644
--- a/libguile/gsubr.c
+++ b/libguile/gsubr.c
@@ -40,11 +40,10 @@
SCM_GLOBAL_SYMBOL (scm_sym_name, "name");
-SCM scm_f_gsubr_apply;
-
static SCM
create_gsubr (int define, const char *name,
- int req, int opt, int rst, SCM (*fcn)())
+ unsigned int req, unsigned int opt, unsigned int rst,
+ SCM (*fcn) ())
{
SCM subr;
@@ -52,53 +51,47 @@ create_gsubr (int define, const char *name,
{
case SCM_GSUBR_MAKTYPE(0, 0, 0):
subr = scm_c_make_subr (name, scm_tc7_subr_0, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(1, 0, 0):
subr = scm_c_make_subr (name, scm_tc7_subr_1, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(0, 1, 0):
subr = scm_c_make_subr (name, scm_tc7_subr_1o, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(1, 1, 0):
subr = scm_c_make_subr (name, scm_tc7_subr_2o, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(2, 0, 0):
subr = scm_c_make_subr (name, scm_tc7_subr_2, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(3, 0, 0):
subr = scm_c_make_subr (name, scm_tc7_subr_3, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(0, 0, 1):
subr = scm_c_make_subr (name, scm_tc7_lsubr, fcn);
- goto create_subr;
+ break;
case SCM_GSUBR_MAKTYPE(2, 0, 1):
subr = scm_c_make_subr (name, scm_tc7_lsubr_2, fcn);
- create_subr:
- if (define)
- scm_define (SCM_SNAME (subr), subr);
- return subr;
+ break;
default:
{
- SCM cclo = scm_makcclo (scm_f_gsubr_apply, 3L);
- SCM subr = scm_c_make_subr (name, scm_tc7_subr_0, fcn);
- SCM sym = SCM_SNAME (subr);
- if (SCM_GSUBR_MAX < req + opt + rst)
- {
- fprintf (stderr,
- "ERROR in scm_c_make_gsubr: too many args (%d) to %s\n",
- req + opt + rst, name);
- exit (1);
- }
- SCM_SET_GSUBR_PROC (cclo, subr);
- SCM_SET_GSUBR_TYPE (cclo,
- scm_from_int (SCM_GSUBR_MAKTYPE (req, opt, rst)));
- if (SCM_REC_PROCNAMES_P)
- scm_set_procedure_property_x (cclo, scm_sym_name, sym);
- if (define)
- scm_define (sym, cclo);
- return cclo;
+ unsigned type;
+
+ type = SCM_GSUBR_MAKTYPE (req, opt, rst);
+ if (SCM_GSUBR_REQ (type) != req
+ || SCM_GSUBR_OPT (type) != opt
+ || SCM_GSUBR_REST (type) != rst)
+ scm_out_of_range ("create_gsubr", scm_from_uint (req + opt + rst));
+
+ subr = scm_c_make_subr (name, scm_tc7_gsubr | (type << 8U),
+ fcn);
}
}
+
+ if (define)
+ scm_define (SCM_SNAME (subr), subr);
+
+ return subr;
}
SCM
@@ -190,20 +183,15 @@ scm_gsubr_apply (SCM args)
#define FUNC_NAME "scm_gsubr_apply"
{
SCM self = SCM_CAR (args);
- SCM (*fcn)() = SCM_SUBRF (SCM_GSUBR_PROC (self));
+ SCM (*fcn)() = SCM_SUBRF (self);
SCM v[SCM_GSUBR_MAX];
- int typ = scm_to_int (SCM_GSUBR_TYPE (self));
+ unsigned int typ = SCM_GSUBR_TYPE (self);
long i, n = SCM_GSUBR_REQ (typ) + SCM_GSUBR_OPT (typ) + SCM_GSUBR_REST (typ);
-#if 0
- if (n > SCM_GSUBR_MAX)
- scm_misc_error (FUNC_NAME,
- "Function ~S has illegal arity ~S.",
- scm_list_2 (self, scm_from_int (n)));
-#endif
+
args = SCM_CDR (args);
for (i = 0; i < SCM_GSUBR_REQ (typ); i++) {
if (scm_is_null (args))
- scm_wrong_num_args (SCM_SNAME (SCM_GSUBR_PROC (self)));
+ scm_wrong_num_args (SCM_SNAME (self));
v[i] = SCM_CAR(args);
args = SCM_CDR(args);
}
@@ -218,7 +206,7 @@ scm_gsubr_apply (SCM args)
if (SCM_GSUBR_REST(typ))
v[i] = args;
else if (!scm_is_null (args))
- scm_wrong_num_args (SCM_SNAME (SCM_GSUBR_PROC (self)));
+ scm_wrong_num_args (SCM_SNAME (self));
switch (n) {
case 2: return (*fcn)(v[0], v[1]);
case 3: return (*fcn)(v[0], v[1], v[2]);
@@ -229,6 +217,10 @@ scm_gsubr_apply (SCM args)
case 8: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
case 9: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
case 10: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]);
+ default:
+ scm_misc_error ((char *) SCM_SNAME (self),
+ "gsubr invocation with more than 10 arguments not implemented",
+ SCM_EOL);
}
return SCM_BOOL_F; /* Never reached. */
}
@@ -259,8 +251,6 @@ gsubr_21l(SCM req1, SCM req2, SCM opt, SCM rst)
void
scm_init_gsubr()
{
- scm_f_gsubr_apply = scm_c_make_subr ("gsubr-apply", scm_tc7_lsubr,
- scm_gsubr_apply);
#ifdef GSUBR_TEST
scm_c_define_gsubr ("gsubr-2-1-l", 2, 1, 1, gsubr_21l); /* example */
#endif
diff --git a/libguile/gsubr.h b/libguile/gsubr.h
index 418564901..ea4843696 100644
--- a/libguile/gsubr.h
+++ b/libguile/gsubr.h
@@ -3,7 +3,7 @@
#ifndef SCM_GSUBR_H
#define SCM_GSUBR_H
-/* Copyright (C) 1995,1996,1998,2000,2001, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,2000,2001, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,19 +26,17 @@
+/* Return an integer describing the arity of GSUBR, a subr of type
+ `scm_tc7_gsubr'. The result can be interpreted with `SCM_GSUBR_REQ ()'
+ and similar. */
+#define SCM_GSUBR_TYPE(gsubr) (SCM_CELL_TYPE (gsubr) >> 8)
+
#define SCM_GSUBR_MAKTYPE(req, opt, rst) ((req)|((opt)<<4)|((rst)<<8))
+#define SCM_GSUBR_MAX 33
#define SCM_GSUBR_REQ(x) ((long)(x)&0xf)
#define SCM_GSUBR_OPT(x) (((long)(x)&0xf0)>>4)
#define SCM_GSUBR_REST(x) ((long)(x)>>8)
-#define SCM_GSUBR_MAX 10
-#define SCM_GSUBR_TYPE(cclo) (SCM_CCLO_REF ((cclo), 1))
-#define SCM_SET_GSUBR_TYPE(cclo, type) (SCM_CCLO_SET ((cclo), 1, (type)))
-#define SCM_GSUBR_PROC(cclo) (SCM_CCLO_REF ((cclo), 2))
-#define SCM_SET_GSUBR_PROC(cclo, proc) (SCM_CCLO_SET ((cclo), 2, (proc)))
-
-SCM_API SCM scm_f_gsubr_apply;
-
SCM_API SCM scm_c_make_gsubr (const char *name,
int req, int opt, int rst, SCM (*fcn) ());
SCM_API SCM scm_c_make_gsubr_with_generic (const char *name,
diff --git a/libguile/print.c b/libguile/print.c
index d218837d2..fa4cb1e28 100644
--- a/libguile/print.c
+++ b/libguile/print.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-1999,2000,2001, 2002, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995-1999,2000,2001, 2002, 2003, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -657,30 +657,7 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
scm_puts (scm_i_symbol_chars (SCM_SNAME (exp)), port);
scm_putc ('>', port);
break;
-#ifdef CCLO
- case scm_tc7_cclo:
- {
- SCM proc = SCM_CCLO_SUBR (exp);
- if (scm_is_eq (proc, scm_f_gsubr_apply))
- {
- /* Print gsubrs as primitives */
- SCM name = scm_procedure_name (exp);
- scm_puts ("#<primitive-procedure", port);
- if (scm_is_true (name))
- {
- scm_putc (' ', port);
- scm_puts (scm_i_symbol_chars (name), port);
- }
- }
- else
- {
- scm_puts ("#<compiled-closure ", port);
- scm_iprin1 (proc, port, pstate);
- }
- scm_putc ('>', port);
- }
- break;
-#endif
+
case scm_tc7_pws:
scm_puts ("#<procedure-with-setter", port);
{
diff --git a/libguile/procprop.c b/libguile/procprop.c
index 88f2c2218..db16834c5 100644
--- a/libguile/procprop.c
+++ b/libguile/procprop.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1998,2000,2001,2003,2004, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,2000,2001,2003,2004, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -88,21 +88,14 @@ scm_i_procedure_arity (SCM proc)
{
return SCM_BOOL_F;
}
- case scm_tc7_cclo:
- if (scm_is_eq (SCM_CCLO_SUBR (proc), scm_f_gsubr_apply))
- {
- int type = scm_to_int (SCM_GSUBR_TYPE (proc));
- a += SCM_GSUBR_REQ (type);
- o = SCM_GSUBR_OPT (type);
- r = SCM_GSUBR_REST (type);
- break;
- }
- else
- {
- proc = SCM_CCLO_SUBR (proc);
- a -= 1;
- goto loop;
- }
+ case scm_tc7_gsubr:
+ {
+ unsigned int type = SCM_GSUBR_TYPE (proc);
+ a = SCM_GSUBR_REQ (type);
+ o = SCM_GSUBR_OPT (type);
+ r = SCM_GSUBR_REST (type);
+ break;
+ }
case scm_tc7_pws:
proc = SCM_PROCEDURE (proc);
goto loop;
diff --git a/libguile/procs.c b/libguile/procs.c
index a2f5ef37a..8230e07ae 100644
--- a/libguile/procs.c
+++ b/libguile/procs.c
@@ -93,39 +93,6 @@ scm_c_define_subr_with_generic (const char *name,
}
-#ifdef CCLO
-SCM
-scm_makcclo (SCM proc, size_t len)
-{
- scm_t_bits *base = scm_gc_malloc (len * sizeof (scm_t_bits),
- "compiled closure");
- unsigned long i;
- SCM s;
-
- for (i = 0; i < len; ++i)
- base [i] = SCM_UNPACK (SCM_UNSPECIFIED);
-
- s = scm_cell (SCM_MAKE_CCLO_TAG (len), (scm_t_bits) base);
- SCM_SET_CCLO_SUBR (s, proc);
- return s;
-}
-
-/* Undocumented debugging procedure */
-#ifdef GUILE_DEBUG
-SCM_DEFINE (scm_make_cclo, "make-cclo", 2, 0, 0,
- (SCM proc, SCM len),
- "Create a compiled closure for @var{proc}, which reserves\n"
- "@var{len} objects for its usage.")
-#define FUNC_NAME s_scm_make_cclo
-{
- return scm_makcclo (proc, scm_to_size_t (len));
-}
-#undef FUNC_NAME
-#endif
-#endif
-
-
-
SCM_DEFINE (scm_procedure_p, "procedure?", 1, 0, 0,
(SCM obj),
"Return @code{#t} if @var{obj} is a procedure.")
@@ -139,9 +106,6 @@ SCM_DEFINE (scm_procedure_p, "procedure?", 1, 0, 0,
break;
case scm_tcs_closures:
case scm_tcs_subrs:
-#ifdef CCLO
- case scm_tc7_cclo:
-#endif
case scm_tc7_pws:
return SCM_BOOL_T;
case scm_tc7_smob:
@@ -179,10 +143,9 @@ SCM_DEFINE (scm_thunk_p, "thunk?", 1, 0, 0,
case scm_tc7_lsubr:
case scm_tc7_rpsubr:
case scm_tc7_asubr:
-#ifdef CCLO
- case scm_tc7_cclo:
-#endif
return SCM_BOOL_T;
+ case scm_tc7_gsubr:
+ return scm_from_bool (SCM_GSUBR_REQ (SCM_GSUBR_TYPE (obj)) == 0);
case scm_tc7_pws:
obj = SCM_PROCEDURE (obj);
goto again;
@@ -235,12 +198,6 @@ SCM_DEFINE (scm_procedure_documentation, "procedure-documentation", 1, 0, 0,
return SCM_BOOL_F;
default:
return SCM_BOOL_F;
-/*
- case scm_tcs_subrs:
-#ifdef CCLO
- case scm_tc7_cclo:
-#endif
-*/
}
}
#undef FUNC_NAME
diff --git a/libguile/procs.h b/libguile/procs.h
index f0c0ee363..b7ab61497 100644
--- a/libguile/procs.h
+++ b/libguile/procs.h
@@ -40,18 +40,6 @@
#define SCM_SET_SUBR_GENERIC(x, g) (*((SCM *) SCM_CELL_WORD_2 (x)) = (g))
#define SCM_SET_SUBR_GENERIC_LOC(x, g) (SCM_SET_CELL_WORD_2 (x, (scm_t_bits) g))
-#define SCM_CCLO_LENGTH(x) (SCM_CELL_WORD_0 (x) >> 8)
-#define SCM_MAKE_CCLO_TAG(v) (((v) << 8) + scm_tc7_cclo)
-#define SCM_SET_CCLO_LENGTH(x, v) (SCM_SET_CELL_WORD_0 ((x), SCM_MAKE_CCLO_TAG(v)))
-#define SCM_CCLO_BASE(x) ((scm_t_bits *) SCM_CELL_WORD_1 (x))
-#define SCM_SET_CCLO_BASE(x, v) (SCM_SET_CELL_WORD_1 ((x), (v)))
-
-#define SCM_CCLO_REF(x, i) (SCM_PACK (SCM_CCLO_BASE (x) [i]))
-#define SCM_CCLO_SET(x, i, v) (SCM_CCLO_BASE (x) [i] = SCM_UNPACK (v))
-
-#define SCM_CCLO_SUBR(x) (SCM_CCLO_REF ((x), 0))
-#define SCM_SET_CCLO_SUBR(x, v) (SCM_CCLO_SET ((x), 0, (v)))
-
/* Closures
*/
@@ -129,7 +117,6 @@ SCM_API SCM scm_c_make_subr_with_generic (const char *name, long type,
SCM_API SCM scm_c_define_subr (const char *name, long type, SCM (*fcn)());
SCM_API SCM scm_c_define_subr_with_generic (const char *name, long type,
SCM (*fcn)(), SCM *gf);
-SCM_API SCM scm_makcclo (SCM proc, size_t len);
SCM_API SCM scm_procedure_p (SCM obj);
SCM_API SCM scm_closure_p (SCM obj);
SCM_API SCM scm_thunk_p (SCM obj);
@@ -141,10 +128,6 @@ SCM_API SCM scm_procedure (SCM proc);
SCM_API SCM scm_setter (SCM proc);
SCM_INTERNAL void scm_init_procs (void);
-#ifdef GUILE_DEBUG
-SCM_API SCM scm_make_cclo (SCM proc, SCM len);
-#endif /*GUILE_DEBUG*/
-
#endif /* SCM_PROCS_H */
/*
diff --git a/libguile/stacks.c b/libguile/stacks.c
index b9595e364..5b2eea99d 100644
--- a/libguile/stacks.c
+++ b/libguile/stacks.c
@@ -1,5 +1,5 @@
/* Representation of stack frame debug information
- * Copyright (C) 1996,1997,2000,2001, 2006, 2007, 2008 Free Software Foundation
+ * Copyright (C) 1996,1997,2000,2001, 2006, 2007, 2008, 2009 Free Software Foundation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -174,9 +174,6 @@ stack_depth (scm_t_debug_frame *dframe, scm_t_ptrdiff offset, SCM vmframe,
}
}
}
- else if (scm_is_eq (vect[0].a.proc, scm_f_gsubr_apply))
- /* Skip gsubr apply frames. */
- continue;
else
++n; /* increment for non-program apply frame */
}
@@ -321,9 +318,6 @@ read_frames (scm_t_debug_frame *dframe, scm_t_ptrdiff offset,
NEXT_FRAME (iframe, n, quit);
}
}
- else if (scm_is_eq (iframe->proc, scm_f_gsubr_apply))
- /* Skip gsubr apply frames. */
- continue;
else if (SCM_PROGRAM_P (iframe->proc))
{
if (!SCM_PROGRAM_IS_BOOT (iframe->proc))
diff --git a/libguile/tags.h b/libguile/tags.h
index 4e0700b52..2f30369d9 100644
--- a/libguile/tags.h
+++ b/libguile/tags.h
@@ -455,7 +455,7 @@ typedef unsigned long scm_t_bits;
#define scm_tc7_unused_9 79
#define scm_tc7_dsubr 61
-#define scm_tc7_cclo 63
+#define scm_tc7_gsubr 63
#define scm_tc7_rpsubr 69
#define scm_tc7_subr_0 85
#define scm_tc7_subr_1 87
@@ -677,7 +677,8 @@ enum scm_tc8_tags
case scm_tc7_subr_1o:\
case scm_tc7_subr_2o:\
case scm_tc7_lsubr_2:\
- case scm_tc7_lsubr
+ case scm_tc7_lsubr: \
+ case scm_tc7_gsubr
diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am
index a8bd6233c..3854d4ab1 100644
--- a/test-suite/Makefile.am
+++ b/test-suite/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in.
##
-## Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Software Foundation, Inc.
+## Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Software Foundation, Inc.
##
## This file is part of GUILE.
##
@@ -54,6 +54,7 @@ SCM_TESTS = tests/alist.test \
tests/numbers.test \
tests/optargs.test \
tests/options.test \
+ tests/procprop.test \
tests/poe.test \
tests/popen.test \
tests/ports.test \
diff --git a/test-suite/tests/eval.test b/test-suite/tests/eval.test
index 52c793b69..7a22f0dff 100644
--- a/test-suite/tests/eval.test
+++ b/test-suite/tests/eval.test
@@ -1,5 +1,5 @@
;;;; eval.test --- tests guile's evaluator -*- scheme -*-
-;;;; Copyright (C) 2000, 2001, 2006, 2007 Free Software Foundation, Inc.
+;;;; Copyright (C) 2000, 2001, 2006, 2007, 2009 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
@@ -17,6 +17,7 @@
(define-module (test-suite test-eval)
:use-module (test-suite lib)
+ :use-module ((srfi srfi-1) :select (unfold count))
:use-module (ice-9 documentation))
@@ -316,6 +317,68 @@
(%make-void-port "w"))
#t))))
+
+;;;
+;;; stacks
+;;;
+
+(define (stack->frames stack)
+ ;; Return the list of frames comprising STACK.
+ (unfold (lambda (i)
+ (>= i (stack-length stack)))
+ (lambda (i)
+ (stack-ref stack i))
+ 1+
+ 0))
+
+(with-test-prefix "stacks"
+ (with-debugging-evaluator
+
+ (pass-if "stack involving a subr"
+ ;; The subr involving the error must appear exactly once on the stack.
+ (catch 'result
+ (lambda ()
+ (start-stack 'foo
+ (lazy-catch 'wrong-type-arg
+ (lambda ()
+ ;; Trigger a `wrong-type-arg' exception.
+ (fluid-ref 'not-a-fluid))
+ (lambda _
+ (let* ((stack (make-stack #t))
+ (frames (stack->frames stack)))
+ (throw 'result
+ (count (lambda (frame)
+ (and (frame-procedure? frame)
+ (eq? (frame-procedure frame)
+ fluid-ref)))
+ frames)))))))
+ (lambda (key result)
+ (= 1 result))))
+
+ (pass-if "stack involving a gsubr"
+ ;; The gsubr involving the error must appear exactly once on the stack.
+ ;; This is less obvious since gsubr application may require an
+ ;; additional `SCM_APPLY ()' call, which should not be visible to the
+ ;; application.
+ (catch 'result
+ (lambda ()
+ (start-stack 'foo
+ (lazy-catch 'wrong-type-arg
+ (lambda ()
+ ;; Trigger a `wrong-type-arg' exception.
+ (hashq-ref 'wrong 'type 'arg))
+ (lambda _
+ (let* ((stack (make-stack #t))
+ (frames (stack->frames stack)))
+ (throw 'result
+ (count (lambda (frame)
+ (and (frame-procedure? frame)
+ (eq? (frame-procedure frame)
+ hashq-ref)))
+ frames)))))))
+ (lambda (key result)
+ (= 1 result))))))
+
;;;
;;; letrec init evaluation
;;;
diff --git a/test-suite/tests/goops.test b/test-suite/tests/goops.test
index 8861d23a9..2317228e4 100644
--- a/test-suite/tests/goops.test
+++ b/test-suite/tests/goops.test
@@ -1,6 +1,6 @@
;;;; goops.test --- test suite for GOOPS -*- scheme -*-
;;;;
-;;;; Copyright (C) 2001,2003,2004, 2006, 2008 Free Software Foundation, Inc.
+;;;; Copyright (C) 2001,2003,2004, 2006, 2008, 2009 Free Software Foundation, Inc.
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
@@ -125,6 +125,24 @@
table))))
)
+(with-test-prefix "classes for built-in types"
+
+ (pass-if "subr"
+ (eq? (class-of fluid-ref) <procedure>))
+
+ (pass-if "gsubr"
+ (eq? (class-of hashq-ref) <procedure>))
+
+ (pass-if "car"
+ (eq? (class-of car) <procedure>))
+
+ (pass-if "string"
+ (eq? (class-of "foo") <string>))
+
+ (pass-if "port"
+ (is-a? (%make-void-port "w") <port>)))
+
+
(with-test-prefix "defining classes"
(with-test-prefix "define-class"
diff --git a/test-suite/tests/procprop.test b/test-suite/tests/procprop.test
new file mode 100644
index 000000000..5ab585058
--- /dev/null
+++ b/test-suite/tests/procprop.test
@@ -0,0 +1,61 @@
+;;;; procprop.test --- Procedure properties -*- Scheme -*-
+;;;; Ludovic Courtès <ludo@gnu.org>
+;;;;
+;;;; Copyright (C) 2009 Free Software Foundation, Inc.
+;;;;
+;;;; This program is free software; you can redistribute it and/or modify
+;;;; it under the terms of the GNU General Public License as published by
+;;;; the Free Software Foundation; either version 2, or (at your option)
+;;;; any later version.
+;;;;
+;;;; This program is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;;; GNU General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU General Public License
+;;;; along with this software; see the file COPYING. If not, write to
+;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;;;; Boston, MA 02110-1301 USA
+
+(define-module (test-procpop)
+ :use-module (test-suite lib))
+
+
+(with-test-prefix "procedure-name"
+ (pass-if "simple subr"
+ (eq? 'display (procedure-name display)))
+
+ (pass-if "gsubr"
+ (eq? 'hashq-ref (procedure-name hashq-ref))))
+
+
+(with-test-prefix "procedure-arity"
+ (pass-if "simple subr"
+ (equal? (procedure-property display 'arity)
+ '(1 1 #f)))
+
+ (pass-if "gsubr"
+ (equal? (procedure-property hashq-ref 'arity)
+ '(2 1 #f)))
+
+ (pass-if "port-closed?"
+ (equal? (procedure-property port-closed? 'arity)
+ '(1 0 #f)))
+
+ (pass-if "apply"
+ (equal? (procedure-property apply 'arity)
+ '(1 0 #t)))
+
+ (pass-if "cons*"
+ (equal? (procedure-property cons* 'arity)
+ '(1 0 #t)))
+
+ (pass-if "list"
+ (equal? (procedure-property list 'arity)
+ '(0 0 #t))))
+
+
+;;; Local Variables:
+;;; coding: latin-1
+;;; End: