1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-28 16:00:22 +02:00

Merge remote-tracking branch 'origin/stable-2.0'

Conflicts:
	configure.ac
	libguile/fluids.c
	libguile/gc.c
	libguile/gc.h
	libguile/objcodes.c
	libguile/procprop.c
	libguile/vm.c
	module/ice-9/psyntax-pp.scm
	module/ice-9/psyntax.scm
This commit is contained in:
Andy Wingo 2011-12-01 23:31:50 +01:00
commit b2208d2e98
54 changed files with 10211 additions and 9681 deletions

23
README
View file

@ -239,25 +239,28 @@ switches specific to Guile you may find useful in some circumstances.
Cross building Guile ===================================================== Cross building Guile =====================================================
As of guile-1.5.x, the build process uses compiled C files for As of Guile 2.0.x, the build process produces a library, libguile-2.0,
snarfing, and (indirectly, through libtool) for linking, and uses the along with Guile "object files" containing bytecode to be interpreted by
guile executable for generating documentation. Guile's virtual machine. The bytecode format depends on the endianness
and word size of the host CPU.
When cross building guile, you first need to configure, build and Thus, when cross building Guile, you first need to configure, build and
install guile for your build host. install it for your build host.
Then, you may configure guile for cross building, eg: Then, you may configure Guile for cross building:
./configure --host=i686-pc-cygwin --disable-shared ./configure --host=i686-pc-cygwin --disable-shared
A C compiler for the build system is required. The default is A C compiler for the build system is required. If that doesn't suit it
"PATH=/usr/bin:$PATH cc". If that doesn't suit it can be specified can be specified with the CC_FOR_BUILD variable in the usual way, for
with the CC_FOR_BUILD variable in the usual way, for instance instance:
./configure --host=m68k-unknown-linux-gnu CC_FOR_BUILD=/my/local/gcc ./configure --host=m68k-unknown-linux-gnu CC_FOR_BUILD=/my/local/gcc
Guile for the build system can be specified similarly with the Guile for the build system can be specified similarly with the
GUILE_FOR_BUILD variable, it defaults to just "guile". GUILE_FOR_BUILD variable, which defaults to whatever `guile' executable
is found in $PATH. It must have the exact same version has the Guile
that you intend to cross-build.
Using Guile Without Installing It ========================================= Using Guile Without Installing It =========================================

View file

@ -530,6 +530,56 @@ AC_DEFUN([GUILE_UNISTRING_ICONVEH_VALUES], [
GUILE_UNISTRING_CONSTANT([iconveh_escape_sequence]) GUILE_UNISTRING_CONSTANT([iconveh_escape_sequence])
]) ])
dnl GUILE_CHECK_VERSION
dnl
dnl Ensure that $GUILE_FOR_BUILD has the same version as ourselves.
AC_DEFUN([GUILE_CHECK_VERSION], [
if ! "$GUILE_FOR_BUILD" --version > /dev/null 2>&1; then
AC_MSG_ERROR([failed to run `$GUILE_FOR_BUILD'])
fi
dnl Use MAJOR.MINOR.MICRO instead of (version) so that developers can
dnl freely shoot themselves in the foot by using, say, 2.0.3.80 and
dnl 2.0.3.42.
AC_CACHE_CHECK([the version of $GUILE_FOR_BUILD],
[ac_cv_guile_for_build_version],
[ac_cv_guile_for_build_version="`"$GUILE_FOR_BUILD" \
-c '(format #t "~a.~a.~a" (major-version) (minor-version) (micro-version))'`"
])
if test "$ac_cv_guile_for_build_version" != \
"$GUILE_MAJOR_VERSION.$GUILE_MINOR_VERSION.$GUILE_MICRO_VERSION"
then
AC_MSG_ERROR([building Guile $PACKAGE_VERSION but `$GUILE_FOR_BUILD' has version $ac_cv_guile_for_build_version"])
fi
])
dnl GUILE_CHECK_GUILE_FOR_BUILD
dnl
dnl When cross-compiling, ensure that $GUILE_FOR_BUILD is suitable.
AC_DEFUN([GUILE_CHECK_GUILE_FOR_BUILD], [
if test "$cross_compiling" = "yes"; then
if test "x$GUILE_FOR_BUILD" = "x"; then
AC_PATH_PROG([GUILE_FOR_BUILD], [guile], [not-found])
if test "$GUILE_FOR_BUILD" = "not-found"; then
AC_MSG_ERROR([a native Guile $PACKAGE_VERSION is required to cross-build Guile])
fi
fi
AC_MSG_CHECKING([guile for build])
AC_MSG_RESULT([$GUILE_FOR_BUILD])
dnl Since there is currently no distinction between the run-time
dnl search path, %load-path, and the compiler's search path,
dnl $GUILE_FOR_BUILD must be a native build of the very same version.
GUILE_CHECK_VERSION
else
GUILE_FOR_BUILD='this-value-will-never-be-used'
fi
AC_ARG_VAR([GUILE_FOR_BUILD], [guile for the build system])
AM_SUBST_NOTMAKE([GUILE_FOR_BUILD])
])
dnl Declare file $1 to be a script that needs configuring, dnl Declare file $1 to be a script that needs configuring,
dnl and arrange to make it executable in the process. dnl and arrange to make it executable in the process.
AC_DEFUN([GUILE_CONFIG_SCRIPT],[AC_CONFIG_FILES([$1],[chmod +x $1])]) AC_DEFUN([GUILE_CONFIG_SCRIPT],[AC_CONFIG_FILES([$1],[chmod +x $1])])

View file

@ -26,6 +26,9 @@ AM_V_GUILEC_0 = @echo " GUILEC" $@;
SUFFIXES = .scm .go SUFFIXES = .scm .go
.scm.go: .scm.go:
$(AM_V_GUILEC)GUILE_AUTO_COMPILE=0 \ $(AM_V_GUILEC)GUILE_AUTO_COMPILE=0 \
$(top_builddir)/meta/uninstalled-env \ $(top_builddir)/meta/uninstalled-env \
guild compile $(GUILE_WARNINGS) -o "$@" "$<" guild compile --target="$(host)" $(GUILE_WARNINGS) \
-L "$(abs_srcdir)" -L "$(abs_builddir)" \
-L "$(abs_top_srcdir)/guile-readline" \
-o "$@" "$<"

View file

@ -1,5 +1,5 @@
;;;; benchmark-suite/lib.scm --- generic support for benchmarking ;;;; benchmark-suite/lib.scm --- generic support for benchmarking
;;;; Copyright (C) 2002, 2006 Free Software Foundation, Inc. ;;;; Copyright (C) 2002, 2006, 2011 Free Software Foundation, Inc.
;;;; ;;;;
;;;; This program is free software; you can redistribute it and/or ;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
@ -348,8 +348,7 @@
(append (current-benchmark-prefix) (list name))) (append (current-benchmark-prefix) (list name)))
;;; A fluid containing the current benchmark prefix, as a list. ;;; A fluid containing the current benchmark prefix, as a list.
(define prefix-fluid (make-fluid)) (define prefix-fluid (make-fluid '()))
(fluid-set! prefix-fluid '())
(define (current-benchmark-prefix) (define (current-benchmark-prefix)
(fluid-ref prefix-fluid)) (fluid-ref prefix-fluid))

View file

@ -1259,7 +1259,7 @@ save_LIBS="$LIBS"
LIBS="$BDW_GC_LIBS $LIBS" LIBS="$BDW_GC_LIBS $LIBS"
CFLAGS="$BDW_GC_CFLAGS $CFLAGS" CFLAGS="$BDW_GC_CFLAGS $CFLAGS"
AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask GC_set_start_callback GC_get_suspend_signal GC_move_disappearing_link]) AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask GC_set_start_callback GC_get_suspend_signal GC_move_disappearing_link GC_get_heap_usage_safe GC_get_free_space_divisor])
# Though the `GC_do_blocking ()' symbol is present in GC 7.1, it is not # Though the `GC_do_blocking ()' symbol is present in GC 7.1, it is not
# declared, and has a different type (returning void instead of # declared, and has a different type (returning void instead of
@ -1511,20 +1511,7 @@ AC_SUBST(CCLD_FOR_BUILD)
HOST_CC="$CC_FOR_BUILD" HOST_CC="$CC_FOR_BUILD"
AC_SUBST(HOST_CC) AC_SUBST(HOST_CC)
if test "$cross_compiling" = "yes"; then GUILE_CHECK_GUILE_FOR_BUILD
AC_MSG_CHECKING(guile for build)
GUILE_FOR_BUILD="${GUILE_FOR_BUILD-guile}"
else
GUILE_FOR_BUILD='this-value-will-never-be-used'
fi
## AC_MSG_CHECKING("if we are cross compiling")
## AC_MSG_RESULT($cross_compiling)
if test "$cross_compiling" = "yes"; then
AC_MSG_RESULT($GUILE_FOR_BUILD)
fi
AC_ARG_VAR(GUILE_FOR_BUILD,[guile for build system])
AM_SUBST_NOTMAKE(GUILE_FOR_BUILD)
## If we're using GCC, ask for aggressive warnings. ## If we're using GCC, ask for aggressive warnings.
GCC_CFLAGS="" GCC_CFLAGS=""

View file

@ -4546,7 +4546,8 @@ Fill bytevector @var{bv} with @var{fill}, a byte.
@deffnx {C Function} scm_bytevector_copy_x (source, source_start, target, target_start, len) @deffnx {C Function} scm_bytevector_copy_x (source, source_start, target, target_start, len)
Copy @var{len} bytes from @var{source} into @var{target}, starting Copy @var{len} bytes from @var{source} into @var{target}, starting
reading from @var{source-start} (a positive index within @var{source}) reading from @var{source-start} (a positive index within @var{source})
and start writing at @var{target-start}. and start writing at @var{target-start}. It is permitted for the
@var{source} and @var{target} regions to overlap.
@end deffn @end deffn
@deffn {Scheme Procedure} bytevector-copy bv @deffn {Scheme Procedure} bytevector-copy bv

View file

@ -640,6 +640,13 @@ Use @var{lang} as the source language of @var{file}. If this option is omitted,
Use @var{lang} as the target language of @var{file}. If this option is omitted, Use @var{lang} as the target language of @var{file}. If this option is omitted,
@code{objcode} is assumed. @code{objcode} is assumed.
@item -T @var{target}
@itemx --target=@var{target}
Produce bytecode for @var{target} instead of @var{%host-type}
(@pxref{Build Config, %host-type}). Target must be a valid GNU triplet,
such as @code{armv5tel-unknown-linux-gnueabi} (@pxref{Specifying Target
Triplets,,, autoconf, GNU Autoconf Manual}).
@end table @end table
Each @var{file} is assumed to be UTF-8-encoded, unless it contains a Each @var{file} is assumed to be UTF-8-encoded, unless it contains a

View file

@ -1,6 +1,6 @@
@c -*-texinfo-*- @c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual. @c This is part of the GNU Guile Reference Manual.
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2010 @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2010, 2011
@c Free Software Foundation, Inc. @c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions. @c See the file guile.texi for copying conditions.
@ -8,9 +8,9 @@
@chapter Introduction @chapter Introduction
Guile is an implementation of the Scheme programming language. Scheme Guile is an implementation of the Scheme programming language. Scheme
(@url{schemers.org}) is an elegant and conceptually simple dialect of (@url{http://schemers.org/}) is an elegant and conceptually simple
Lisp, originated by Guy Steele and Gerald Sussman, and since evolved dialect of Lisp, originated by Guy Steele and Gerald Sussman, and since
by the series of reports known as RnRS (the evolved by the series of reports known as RnRS (the
@tex @tex
Revised$^n$ Revised$^n$
@end tex @end tex

View file

@ -1,6 +1,6 @@
@c -*-texinfo-*- @c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual. @c This is part of the GNU Guile Reference Manual.
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2011
@c Free Software Foundation, Inc. @c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions. @c See the file guile.texi for copying conditions.
@ -10,7 +10,7 @@
@itemize @bullet @itemize @bullet
@item @item
The website @url{http://www.schemers.org} is a good starting point for The website @url{http://www.schemers.org/} is a good starting point for
all things Scheme. all things Scheme.
@item @item

View file

@ -16,7 +16,7 @@ Guile has support for a number of SRFIs. This chapter gives an overview
over the available SRFIs and some usage hints. For complete over the available SRFIs and some usage hints. For complete
documentation, design rationales and further examples, we advise you to documentation, design rationales and further examples, we advise you to
get the relevant SRFI documents from the SRFI home page get the relevant SRFI documents from the SRFI home page
@url{http://srfi.schemers.org}. @url{http://srfi.schemers.org/}.
@menu @menu
* About SRFI Usage:: What to know about Guile's SRFI support. * About SRFI Usage:: What to know about Guile's SRFI support.

View file

@ -847,7 +847,7 @@ indicating any etag, or a list of entity tags.
Indicates that a response should proceed if and only if the resource has Indicates that a response should proceed if and only if the resource has
been modified since the given date. been modified since the given date.
@example @example
(parse-header if-modified-since "Tue, 15 Nov 1994 08:12:31 GMT") (parse-header 'if-modified-since "Tue, 15 Nov 1994 08:12:31 GMT")
@result{} #<date ...> @result{} #<date ...>
@end example @end example
@end deftypevr @end deftypevr

View file

@ -596,9 +596,9 @@ SCM_DEFINE (scm_bytevector_copy_x, "bytevector-copy!", 5, 0, 0,
if (SCM_UNLIKELY (c_target_start + c_len > c_target_len)) if (SCM_UNLIKELY (c_target_start + c_len > c_target_len))
scm_out_of_range (FUNC_NAME, target_start); scm_out_of_range (FUNC_NAME, target_start);
memcpy (c_target + c_target_start, memmove (c_target + c_target_start,
c_source + c_source_start, c_source + c_source_start,
c_len); c_len);
return SCM_UNSPECIFIED; return SCM_UNSPECIFIED;
} }

View file

@ -68,7 +68,7 @@ grow_dynamic_state (SCM state)
/* Assume the assignment below is atomic. */ /* Assume the assignment below is atomic. */
len = allocated_fluids_len; len = allocated_fluids_len;
new_fluids = scm_c_make_vector (len, SCM_BOOL_F); new_fluids = scm_c_make_vector (len, SCM_UNDEFINED);
for (i = 0; i < old_len; i++) for (i = 0; i < old_len; i++)
SCM_SIMPLE_VECTOR_SET (new_fluids, i, SCM_SIMPLE_VECTOR_SET (new_fluids, i,
@ -103,14 +103,14 @@ scm_i_with_fluids_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
/* Return a new fluid. */ /* Return a new fluid. */
static SCM static SCM
new_fluid () new_fluid (SCM init)
{ {
SCM fluid; SCM fluid;
size_t trial, n; size_t trial, n;
/* Fluids are pointerless cells: the first word is the type tag; the second /* Fluids hold the type tag and the fluid number in the first word,
word is the fluid number. */ and the default value in the second word. */
fluid = SCM_PACK_POINTER (scm_gc_malloc_pointerless (sizeof (scm_t_cell), "fluid")); fluid = scm_cell (scm_tc7_fluid, SCM_UNPACK (init));
SCM_SET_CELL_TYPE (fluid, scm_tc7_fluid); SCM_SET_CELL_TYPE (fluid, scm_tc7_fluid);
scm_dynwind_begin (0); scm_dynwind_begin (0);
@ -157,7 +157,7 @@ new_fluid ()
} }
allocated_fluids[n] = SCM_UNPACK_POINTER (fluid); allocated_fluids[n] = SCM_UNPACK_POINTER (fluid);
SCM_SET_CELL_WORD_1 (fluid, (scm_t_bits) n); SCM_SET_CELL_WORD_0 (fluid, (scm_tc7_fluid | (n << 8)));
GC_GENERAL_REGISTER_DISAPPEARING_LINK (&allocated_fluids[n], GC_GENERAL_REGISTER_DISAPPEARING_LINK (&allocated_fluids[n],
SCM_HEAP_OBJECT_BASE (fluid)); SCM_HEAP_OBJECT_BASE (fluid));
@ -166,13 +166,19 @@ new_fluid ()
/* Now null out values. We could (and probably should) do this when /* Now null out values. We could (and probably should) do this when
the fluid is collected instead of now. */ the fluid is collected instead of now. */
scm_i_reset_fluid (n, SCM_BOOL_F); scm_i_reset_fluid (n);
return fluid; return fluid;
} }
SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0, SCM
(), scm_make_fluid (void)
{
return new_fluid (SCM_BOOL_F);
}
SCM_DEFINE (scm_make_fluid_with_default, "make-fluid", 0, 1, 0,
(SCM dflt),
"Return a newly created fluid.\n" "Return a newly created fluid.\n"
"Fluids are objects that can hold one\n" "Fluids are objects that can hold one\n"
"value per dynamic state. That is, modifications to this value are\n" "value per dynamic state. That is, modifications to this value are\n"
@ -180,9 +186,9 @@ SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
"the modifying code. When a new dynamic state is constructed, it\n" "the modifying code. When a new dynamic state is constructed, it\n"
"inherits the values from its parent. Because each thread normally executes\n" "inherits the values from its parent. Because each thread normally executes\n"
"with its own dynamic state, you can use fluids for thread local storage.") "with its own dynamic state, you can use fluids for thread local storage.")
#define FUNC_NAME s_scm_make_fluid #define FUNC_NAME s_scm_make_fluid_with_default
{ {
return new_fluid (); return new_fluid (SCM_UNBNDP (dflt) ? SCM_BOOL_F : dflt);
} }
#undef FUNC_NAME #undef FUNC_NAME
@ -191,9 +197,7 @@ SCM_DEFINE (scm_make_unbound_fluid, "make-unbound-fluid", 0, 0, 0,
"Make a fluid that is initially unbound.") "Make a fluid that is initially unbound.")
#define FUNC_NAME s_scm_make_unbound_fluid #define FUNC_NAME s_scm_make_unbound_fluid
{ {
SCM f = new_fluid (); return new_fluid (SCM_UNDEFINED);
scm_fluid_set_x (f, SCM_UNDEFINED);
return f;
} }
#undef FUNC_NAME #undef FUNC_NAME
@ -217,6 +221,7 @@ scm_is_fluid (SCM obj)
static SCM static SCM
fluid_ref (SCM fluid) fluid_ref (SCM fluid)
{ {
SCM ret;
SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state); SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
if (SCM_UNLIKELY (FLUID_NUM (fluid) >= SCM_SIMPLE_VECTOR_LENGTH (fluids))) if (SCM_UNLIKELY (FLUID_NUM (fluid) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
@ -227,7 +232,11 @@ fluid_ref (SCM fluid)
fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state); fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
} }
return SCM_SIMPLE_VECTOR_REF (fluids, FLUID_NUM (fluid)); ret = SCM_SIMPLE_VECTOR_REF (fluids, FLUID_NUM (fluid));
if (SCM_UNBNDP (ret))
return SCM_I_FLUID_DEFAULT (fluid);
else
return ret;
} }
SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0, SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
@ -274,6 +283,9 @@ SCM_DEFINE (scm_fluid_unset_x, "fluid-unset!", 1, 0, 0,
"Unset the value associated with @var{fluid}.") "Unset the value associated with @var{fluid}.")
#define FUNC_NAME s_scm_fluid_unset_x #define FUNC_NAME s_scm_fluid_unset_x
{ {
/* FIXME: really unset the default value, too? The current test
suite demands it, but I would prefer not to. */
SCM_SET_CELL_OBJECT_1 (fluid, SCM_UNDEFINED);
return scm_fluid_set_x (fluid, SCM_UNDEFINED); return scm_fluid_set_x (fluid, SCM_UNDEFINED);
} }
#undef FUNC_NAME #undef FUNC_NAME

View file

@ -56,10 +56,12 @@
#define SCM_FLUID_P(x) (SCM_HAS_TYP7 (x, scm_tc7_fluid)) #define SCM_FLUID_P(x) (SCM_HAS_TYP7 (x, scm_tc7_fluid))
#ifdef BUILDING_LIBGUILE #ifdef BUILDING_LIBGUILE
#define SCM_I_FLUID_NUM(x) ((size_t)SCM_CELL_WORD_1(x)) #define SCM_I_FLUID_NUM(x) ((size_t)(SCM_CELL_WORD_0 (x) >> 8))
#define SCM_I_FLUID_DEFAULT(x) (SCM_CELL_OBJECT_1 (x))
#endif #endif
SCM_API SCM scm_make_fluid (void); SCM_API SCM scm_make_fluid (void);
SCM_API SCM scm_make_fluid_with_default (SCM dflt);
SCM_API SCM scm_make_unbound_fluid (void); SCM_API SCM scm_make_unbound_fluid (void);
SCM_API int scm_is_fluid (SCM obj); SCM_API int scm_is_fluid (SCM obj);
SCM_API SCM scm_fluid_p (SCM fl); SCM_API SCM scm_fluid_p (SCM fl);

View file

@ -1124,7 +1124,7 @@ SCM_DEFINE (scm_procedure_to_pointer, "procedure->pointer", 3, 0, 0,
"type should match @var{return-type} and @var{arg-types}.\n") "type should match @var{return-type} and @var{arg-types}.\n")
#define FUNC_NAME s_scm_procedure_to_pointer #define FUNC_NAME s_scm_procedure_to_pointer
{ {
SCM pointer; SCM cif_pointer, pointer;
ffi_cif *cif; ffi_cif *cif;
ffi_status err; ffi_status err;
void *closure, *executable; void *closure, *executable;
@ -1141,8 +1141,17 @@ SCM_DEFINE (scm_procedure_to_pointer, "procedure->pointer", 3, 0, 0,
SCM_MISC_ERROR ("`ffi_prep_closure_loc' failed", SCM_EOL); SCM_MISC_ERROR ("`ffi_prep_closure_loc' failed", SCM_EOL);
} }
/* CIF points to GC-managed memory and it should remain as long as
POINTER (see below) is live. Wrap it in a Scheme pointer to then
hold a weak reference on it. */
cif_pointer = scm_from_pointer (cif, NULL);
if (closure == executable) if (closure == executable)
pointer = scm_from_pointer (executable, ffi_closure_free); {
pointer = scm_from_pointer (executable, ffi_closure_free);
register_weak_reference (pointer,
scm_list_2 (proc, cif_pointer));
}
else else
{ {
/* CLOSURE needs to be freed eventually. However, since /* CLOSURE needs to be freed eventually. However, since
@ -1155,7 +1164,8 @@ SCM_DEFINE (scm_procedure_to_pointer, "procedure->pointer", 3, 0, 0,
pointer = scm_from_pointer (executable, NULL); pointer = scm_from_pointer (executable, NULL);
friend = scm_from_pointer (closure, ffi_closure_free); friend = scm_from_pointer (closure, ffi_closure_free);
register_weak_reference (pointer, friend); register_weak_reference (pointer,
scm_list_3 (proc, cif_pointer, friend));
} }
return pointer; return pointer;

View file

@ -88,12 +88,14 @@ scm_realloc (void *mem, size_t size)
{ {
void *ptr; void *ptr;
scm_gc_register_allocation (size);
SCM_SYSCALL (ptr = realloc (mem, size)); SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr) if (ptr)
return ptr; return ptr;
/* Time is hard: trigger a full, ``stop-the-world'' GC, and try again. */ /* Time is hard: trigger a full, ``stop-the-world'' GC, and try again. */
GC_gcollect (); GC_gcollect_and_unmap ();
SCM_SYSCALL (ptr = realloc (mem, size)); SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr) if (ptr)

View file

@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <math.h>
#ifdef __ia64__ #ifdef __ia64__
#include <ucontext.h> #include <ucontext.h>
@ -187,6 +188,32 @@ SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */ #endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
/* Compatibility. */
#ifndef HAVE_GC_GET_HEAP_USAGE_SAFE
static void
GC_get_heap_usage_safe (GC_word *pheap_size, GC_word *pfree_bytes,
GC_word *punmapped_bytes, GC_word *pbytes_since_gc,
GC_word *ptotal_bytes)
{
*pheap_size = GC_get_heap_size ();
*pfree_bytes = GC_get_free_bytes ();
*punmapped_bytes = GC_get_unmapped_bytes ();
*pbytes_since_gc = GC_get_bytes_since_gc ();
*ptotal_bytes = GC_get_total_bytes ();
}
#endif
#ifndef HAVE_GC_GET_FREE_SPACE_DIVISOR
static GC_word
GC_get_free_space_divisor (void)
{
return GC_free_space_divisor;
}
#endif
/* Hooks. */ /* Hooks. */
scm_t_c_hook scm_before_gc_c_hook; scm_t_c_hook scm_before_gc_c_hook;
@ -209,6 +236,9 @@ unsigned long scm_gc_ports_collected = 0;
static long gc_time_taken = 0; static long gc_time_taken = 0;
static long gc_start_time = 0; static long gc_start_time = 0;
static unsigned long free_space_divisor;
static unsigned long minimum_free_space_divisor;
static double target_free_space_divisor;
static unsigned long protected_obj_count = 0; static unsigned long protected_obj_count = 0;
@ -270,14 +300,12 @@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
#define FUNC_NAME s_scm_gc_stats #define FUNC_NAME s_scm_gc_stats
{ {
SCM answer; SCM answer;
size_t heap_size, free_bytes, bytes_since_gc, total_bytes; GC_word heap_size, free_bytes, unmapped_bytes, bytes_since_gc, total_bytes;
size_t gc_times; size_t gc_times;
heap_size = GC_get_heap_size (); GC_get_heap_usage_safe (&heap_size, &free_bytes, &unmapped_bytes,
free_bytes = GC_get_free_bytes (); &bytes_since_gc, &total_bytes);
bytes_since_gc = GC_get_bytes_since_gc (); gc_times = GC_gc_no;
total_bytes = GC_get_total_bytes ();
gc_times = GC_gc_no;
answer = answer =
scm_list_n (scm_cons (sym_gc_time_taken, scm_from_long (gc_time_taken)), scm_list_n (scm_cons (sym_gc_time_taken, scm_from_long (gc_time_taken)),
@ -579,7 +607,10 @@ void
scm_storage_prehistory () scm_storage_prehistory ()
{ {
GC_all_interior_pointers = 0; GC_all_interior_pointers = 0;
GC_set_free_space_divisor (scm_getenv_int ("GC_FREE_SPACE_DIVISOR", 3)); free_space_divisor = scm_getenv_int ("GC_FREE_SPACE_DIVISOR", 3);
minimum_free_space_divisor = free_space_divisor;
target_free_space_divisor = free_space_divisor;
GC_set_free_space_divisor (free_space_divisor);
GC_INIT (); GC_INIT ();
@ -723,7 +754,8 @@ accumulate_gc_timer (void * hook_data SCM_UNUSED,
void *data SCM_UNUSED) void *data SCM_UNUSED)
{ {
if (gc_start_time) if (gc_start_time)
{ long now = scm_c_get_internal_run_time (); {
long now = scm_c_get_internal_run_time ();
gc_time_taken += now - gc_start_time; gc_time_taken += now - gc_start_time;
gc_start_time = 0; gc_start_time = 0;
} }
@ -731,6 +763,168 @@ accumulate_gc_timer (void * hook_data SCM_UNUSED,
return NULL; return NULL;
} }
/* Return some idea of the memory footprint of a process, in bytes.
Currently only works on Linux systems. */
static size_t
get_image_size (void)
{
unsigned long size, resident, share;
size_t ret = 0;
FILE *fp = fopen ("/proc/self/statm", "r");
if (fp && fscanf (fp, "%lu %lu %lu", &size, &resident, &share) == 3)
ret = resident * 4096;
if (fp)
fclose (fp);
return ret;
}
/* These are discussed later. */
static size_t bytes_until_gc;
static scm_i_pthread_mutex_t bytes_until_gc_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
/* Make GC run more frequently when the process image size is growing,
measured against the number of bytes allocated through the GC.
If Guile is allocating at a GC-managed heap size H, libgc will tend
to limit the process image size to H*N. But if at the same time the
user program is mallocating at a rate M bytes per GC-allocated byte,
then the process stabilizes at H*N*M -- assuming that collecting data
will result in malloc'd data being freed. It doesn't take a very
large M for this to be a bad situation. To limit the image size,
Guile should GC more often -- the bigger the M, the more often.
Numeric functions that produce bigger and bigger integers are
pessimal, because M is an increasing function of time. Here is an
example of such a function:
(define (factorial n)
(define (fac n acc)
(if (<= n 1)
acc
(fac (1- n) (* n acc))))
(fac n 1))
It is possible for a process to grow for reasons that will not be
solved by faster GC. In that case M will be estimated as
artificially high for a while, and so GC will happen more often on
the Guile side. But when it stabilizes, Guile can ease back the GC
frequency.
The key is to measure process image growth, not mallocation rate.
For maximum effectiveness, Guile reacts quickly to process growth,
and exponentially backs down when the process stops growing.
See http://thread.gmane.org/gmane.lisp.guile.devel/12552/focus=12936
for further discussion.
*/
static void *
adjust_gc_frequency (void * hook_data SCM_UNUSED,
void *fn_data SCM_UNUSED,
void *data SCM_UNUSED)
{
static size_t prev_image_size = 0;
static size_t prev_bytes_alloced = 0;
size_t image_size;
size_t bytes_alloced;
scm_i_pthread_mutex_lock (&bytes_until_gc_lock);
bytes_until_gc = GC_get_heap_size ();
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
image_size = get_image_size ();
bytes_alloced = GC_get_total_bytes ();
#define HEURISTICS_DEBUG 0
#if HEURISTICS_DEBUG
fprintf (stderr, "prev image / alloced: %lu / %lu\n", prev_image_size, prev_bytes_alloced);
fprintf (stderr, " image / alloced: %lu / %lu\n", image_size, bytes_alloced);
fprintf (stderr, "divisor %lu / %f\n", free_space_divisor, target_free_space_divisor);
#endif
if (prev_image_size && bytes_alloced != prev_bytes_alloced)
{
double growth_rate, new_target_free_space_divisor;
double decay_factor = 0.5;
double hysteresis = 0.1;
growth_rate = ((double) image_size - prev_image_size)
/ ((double)bytes_alloced - prev_bytes_alloced);
#if HEURISTICS_DEBUG
fprintf (stderr, "growth rate %f\n", growth_rate);
#endif
new_target_free_space_divisor = minimum_free_space_divisor;
if (growth_rate > 0)
new_target_free_space_divisor *= 1.0 + growth_rate;
#if HEURISTICS_DEBUG
fprintf (stderr, "new divisor %f\n", new_target_free_space_divisor);
#endif
if (new_target_free_space_divisor < target_free_space_divisor)
/* Decay down. */
target_free_space_divisor =
(decay_factor * target_free_space_divisor
+ (1.0 - decay_factor) * new_target_free_space_divisor);
else
/* Jump up. */
target_free_space_divisor = new_target_free_space_divisor;
#if HEURISTICS_DEBUG
fprintf (stderr, "new target divisor %f\n", target_free_space_divisor);
#endif
if (free_space_divisor + 0.5 + hysteresis < target_free_space_divisor
|| free_space_divisor - 0.5 - hysteresis > target_free_space_divisor)
{
free_space_divisor = lround (target_free_space_divisor);
#if HEURISTICS_DEBUG
fprintf (stderr, "new divisor %lu\n", free_space_divisor);
#endif
GC_set_free_space_divisor (free_space_divisor);
}
}
prev_image_size = image_size;
prev_bytes_alloced = bytes_alloced;
return NULL;
}
/* The adjust_gc_frequency routine handles transients in the process
image size. It can't handle instense non-GC-managed steady-state
allocation though, as it decays the FSD at steady-state down to its
minimum value.
The only real way to handle continuous, high non-GC allocation is to
let the GC know about it. This routine can handle non-GC allocation
rates that are similar in size to the GC-managed heap size.
*/
void
scm_gc_register_allocation (size_t size)
{
scm_i_pthread_mutex_lock (&bytes_until_gc_lock);
if (bytes_until_gc - size > bytes_until_gc)
{
bytes_until_gc = GC_get_heap_size ();
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
GC_gcollect ();
}
else
{
bytes_until_gc -= size;
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
}
}
@ -833,6 +1027,16 @@ scm_init_gc ()
scm_c_hook_add (&scm_before_gc_c_hook, start_gc_timer, NULL, 0); scm_c_hook_add (&scm_before_gc_c_hook, start_gc_timer, NULL, 0);
scm_c_hook_add (&scm_after_gc_c_hook, accumulate_gc_timer, NULL, 0); scm_c_hook_add (&scm_after_gc_c_hook, accumulate_gc_timer, NULL, 0);
#if HAVE_GC_GET_HEAP_USAGE_SAFE
/* GC_get_heap_usage does not take a lock, and so can run in the GC
start hook. */
scm_c_hook_add (&scm_before_gc_c_hook, adjust_gc_frequency, NULL, 0);
#else
/* GC_get_heap_usage might take a lock (and did from 7.2alpha1 to
7.2alpha7), so call it in the after_gc_hook. */
scm_c_hook_add (&scm_after_gc_c_hook, adjust_gc_frequency, NULL, 0);
#endif
#ifdef HAVE_GC_SET_START_CALLBACK #ifdef HAVE_GC_SET_START_CALLBACK
GC_set_start_callback (run_before_gc_c_hook); GC_set_start_callback (run_before_gc_c_hook);
#endif #endif

View file

@ -157,6 +157,8 @@ SCM_INTERNAL void scm_i_gc (const char *what);
SCM_API void scm_gc_mark (SCM p); SCM_API void scm_gc_mark (SCM p);
SCM_API void scm_gc_sweep (void); SCM_API void scm_gc_sweep (void);
SCM_API void scm_gc_register_allocation (size_t size);
SCM_API void *scm_malloc (size_t size) SCM_MALLOC; SCM_API void *scm_malloc (size_t size) SCM_MALLOC;
SCM_API void *scm_calloc (size_t size) SCM_MALLOC; SCM_API void *scm_calloc (size_t size) SCM_MALLOC;
SCM_API void *scm_realloc (void *mem, size_t size); SCM_API void *scm_realloc (void *mem, size_t size);

View file

@ -1043,8 +1043,7 @@ scm_init_load ()
scm_loc_fresh_auto_compile scm_loc_fresh_auto_compile
= SCM_VARIABLE_LOC (scm_c_define ("%fresh-auto-compile", SCM_BOOL_F)); = SCM_VARIABLE_LOC (scm_c_define ("%fresh-auto-compile", SCM_BOOL_F));
the_reader = scm_make_fluid (); the_reader = scm_make_fluid_with_default (SCM_BOOL_F);
scm_fluid_set_x (the_reader, SCM_BOOL_F);
scm_c_define("current-reader", the_reader); scm_c_define("current-reader", the_reader);
scm_c_define ("load-compiled", scm_c_define ("load-compiled",

View file

@ -292,7 +292,7 @@ memoize (SCM exp, SCM env)
int nreq, nopt, ntotal; int nreq, nopt, ntotal;
req = REF (exp, LAMBDA_CASE, REQ); req = REF (exp, LAMBDA_CASE, REQ);
rest = REF (exp, LAMBDA_CASE, REST); rest = scm_not (scm_not (REF (exp, LAMBDA_CASE, REST)));
opt = REF (exp, LAMBDA_CASE, OPT); opt = REF (exp, LAMBDA_CASE, OPT);
kw = REF (exp, LAMBDA_CASE, KW); kw = REF (exp, LAMBDA_CASE, KW);
inits = REF (exp, LAMBDA_CASE, INITS); inits = REF (exp, LAMBDA_CASE, INITS);

View file

@ -32,6 +32,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <assert.h> #include <assert.h>
#include <alignof.h> #include <alignof.h>
#include <byteswap.h>
#include <full-read.h> #include <full-read.h>
@ -45,11 +46,55 @@
The length of the header must be a multiple of 8 bytes. */ The length of the header must be a multiple of 8 bytes. */
verify (((sizeof (SCM_OBJCODE_COOKIE) - 1) & 7) == 0); verify (((sizeof (SCM_OBJCODE_COOKIE) - 1) & 7) == 0);
/* Endianness and word size of the compilation target. */
static SCM target_endianness_var = SCM_BOOL_F;
static SCM target_word_size_var = SCM_BOOL_F;
/* /*
* Objcode type * Objcode type
*/ */
/* Endianness of the build machine. */
#ifdef WORDS_BIGENDIAN
# define NATIVE_ENDIANNESS 'B'
#else
# define NATIVE_ENDIANNESS 'L'
#endif
/* Return the endianness of the compilation target. */
static char
target_endianness (void)
{
if (scm_is_true (target_endianness_var))
return scm_is_eq (scm_call_0 (scm_variable_ref (target_endianness_var)),
scm_endianness_big) ? 'B' : 'L';
else
return NATIVE_ENDIANNESS;
}
/* Return the word size in bytes of the compilation target. */
static size_t
target_word_size (void)
{
if (scm_is_true (target_word_size_var))
return scm_to_size_t (scm_call_0
(scm_variable_ref (target_word_size_var)));
else
return sizeof (void *);
}
/* Convert X, which is in byte order ENDIANNESS, to its native
representation. */
static inline uint32_t
to_native_order (uint32_t x, char endianness)
{
if (endianness == NATIVE_ENDIANNESS)
return x;
else
return bswap_32 (x);
}
static void static void
verify_cookie (char *cookie, struct stat *st, int map_fd, void *map_addr) verify_cookie (char *cookie, struct stat *st, int map_fd, void *map_addr)
#define FUNC_NAME "make_objcode_from_file" #define FUNC_NAME "make_objcode_from_file"
@ -183,7 +228,7 @@ make_objcode_from_file (int fd)
verify_cookie (cookie, &st, -1, NULL); verify_cookie (cookie, &st, -1, NULL);
return scm_bytecode_to_objcode (bv); return scm_bytecode_to_native_objcode (bv);
} }
#endif #endif
} }
@ -254,12 +299,12 @@ SCM_DEFINE (scm_objcode_meta, "objcode-meta", 1, 0, 0,
} }
#undef FUNC_NAME #undef FUNC_NAME
SCM_DEFINE (scm_bytecode_to_objcode, "bytecode->objcode", 1, 0, 0, /* Turn BYTECODE into objcode encoded for ENDIANNESS and WORD_SIZE. */
(SCM bytecode), static SCM
"") bytecode_to_objcode (SCM bytecode, char endianness, size_t word_size)
#define FUNC_NAME s_scm_bytecode_to_objcode #define FUNC_NAME "bytecode->objcode"
{ {
size_t size; size_t size, len, metalen;
const scm_t_uint8 *c_bytecode; const scm_t_uint8 *c_bytecode;
struct scm_objcode *data; struct scm_objcode *data;
@ -268,14 +313,17 @@ SCM_DEFINE (scm_bytecode_to_objcode, "bytecode->objcode", 1, 0, 0,
size = SCM_BYTEVECTOR_LENGTH (bytecode); size = SCM_BYTEVECTOR_LENGTH (bytecode);
c_bytecode = (const scm_t_uint8*)SCM_BYTEVECTOR_CONTENTS (bytecode); c_bytecode = (const scm_t_uint8*)SCM_BYTEVECTOR_CONTENTS (bytecode);
SCM_ASSERT_RANGE (0, bytecode, size >= sizeof(struct scm_objcode)); SCM_ASSERT_RANGE (0, bytecode, size >= sizeof(struct scm_objcode));
data = (struct scm_objcode*)c_bytecode; data = (struct scm_objcode*)c_bytecode;
if (data->len + data->metalen != (size - sizeof (*data))) len = to_native_order (data->len, endianness);
metalen = to_native_order (data->metalen, endianness);
if (len + metalen != (size - sizeof (*data)))
scm_misc_error (FUNC_NAME, "bad bytevector size (~a != ~a)", scm_misc_error (FUNC_NAME, "bad bytevector size (~a != ~a)",
scm_list_2 (scm_from_size_t (size), scm_list_2 (scm_from_size_t (size),
scm_from_uint32 (sizeof (*data) + data->len + data->metalen))); scm_from_uint32 (sizeof (*data) + len + metalen)));
/* foolishly, we assume that as long as bytecode is around, that c_bytecode /* foolishly, we assume that as long as bytecode is around, that c_bytecode
will be of the same length; perhaps a bad assumption? */ will be of the same length; perhaps a bad assumption? */
@ -284,6 +332,27 @@ SCM_DEFINE (scm_bytecode_to_objcode, "bytecode->objcode", 1, 0, 0,
} }
#undef FUNC_NAME #undef FUNC_NAME
SCM_DEFINE (scm_bytecode_to_objcode, "bytecode->objcode", 1, 0, 0,
(SCM bytecode),
"")
#define FUNC_NAME s_scm_bytecode_to_objcode
{
/* Assume we're called from Scheme, which known that to do with
`target-type'. */
return bytecode_to_objcode (bytecode, target_endianness (),
target_word_size ());
}
#undef FUNC_NAME
/* Like `bytecode->objcode', but ignore the `target-type' fluid. This
is useful for native compilation that happens lazily---e.g., direct
calls to this function from libguile itself. */
SCM
scm_bytecode_to_native_objcode (SCM bytecode)
{
return bytecode_to_objcode (bytecode, NATIVE_ENDIANNESS, sizeof (void *));
}
SCM_DEFINE (scm_load_objcode, "load-objcode", 1, 0, 0, SCM_DEFINE (scm_load_objcode, "load-objcode", 1, 0, 0,
(SCM file), (SCM file),
"") "")
@ -324,41 +393,37 @@ SCM_DEFINE (scm_write_objcode, "write-objcode", 2, 0, 0,
"") "")
#define FUNC_NAME s_scm_write_objcode #define FUNC_NAME s_scm_write_objcode
{ {
static SCM target_endianness_var = SCM_BOOL_F;
static SCM target_word_size_var = SCM_BOOL_F;
char cookie[sizeof (SCM_OBJCODE_COOKIE) - 1]; char cookie[sizeof (SCM_OBJCODE_COOKIE) - 1];
char endianness; char endianness, word_size;
char word_size; size_t total_size;
SCM_VALIDATE_OBJCODE (1, objcode); SCM_VALIDATE_OBJCODE (1, objcode);
SCM_VALIDATE_OUTPUT_PORT (2, port); SCM_VALIDATE_OUTPUT_PORT (2, port);
endianness = target_endianness ();
if (scm_is_false (target_endianness_var)) switch (target_word_size ())
target_endianness_var =
scm_c_public_variable ("system base target", "target-endianness");
if (scm_is_false (target_word_size_var))
target_word_size_var =
scm_c_public_variable ("system base target", "target-word-size");
endianness =
scm_is_eq (scm_call_0 (scm_variable_ref (target_endianness_var)),
scm_endianness_big) ? 'B' : 'L';
switch (scm_to_int (scm_call_0 (scm_variable_ref (target_word_size_var))))
{ {
case 4: word_size = '4'; break; case 4:
case 8: word_size = '8'; break; word_size = '4';
default: abort (); break;
case 8:
word_size = '8';
break;
default:
abort ();
} }
memcpy (cookie, SCM_OBJCODE_COOKIE, strlen (SCM_OBJCODE_COOKIE)); memcpy (cookie, SCM_OBJCODE_COOKIE, strlen (SCM_OBJCODE_COOKIE));
cookie[SCM_OBJCODE_ENDIANNESS_OFFSET] = endianness; cookie[SCM_OBJCODE_ENDIANNESS_OFFSET] = endianness;
cookie[SCM_OBJCODE_WORD_SIZE_OFFSET] = word_size; cookie[SCM_OBJCODE_WORD_SIZE_OFFSET] = word_size;
total_size =
to_native_order (SCM_OBJCODE_LEN (objcode), target_endianness ())
+ to_native_order (SCM_OBJCODE_META_LEN (objcode), target_endianness ());
scm_c_write_unlocked (port, cookie, strlen (SCM_OBJCODE_COOKIE)); scm_c_write_unlocked (port, cookie, strlen (SCM_OBJCODE_COOKIE));
scm_c_write_unlocked (port, SCM_OBJCODE_DATA (objcode), scm_c_write_unlocked (port, SCM_OBJCODE_DATA (objcode),
sizeof (struct scm_objcode) sizeof (struct scm_objcode)
+ SCM_OBJCODE_TOTAL_LEN (objcode)); + total_size);
return SCM_UNSPECIFIED; return SCM_UNSPECIFIED;
} }
@ -398,6 +463,11 @@ scm_init_objcodes (void)
scm_c_define ("word-size", scm_from_size_t (sizeof(SCM))); scm_c_define ("word-size", scm_from_size_t (sizeof(SCM)));
scm_c_define ("byte-order", scm_from_uint16 (SCM_BYTE_ORDER)); scm_c_define ("byte-order", scm_from_uint16 (SCM_BYTE_ORDER));
target_endianness_var = scm_c_public_variable ("system base target",
"target-endianness");
target_word_size_var = scm_c_public_variable ("system base target",
"target-word-size");
} }
/* /*

View file

@ -60,11 +60,12 @@ struct scm_objcode
#define SCM_OBJCODE_NATIVE_CODE(x) (SCM_CELL_WORD_3 (x)) #define SCM_OBJCODE_NATIVE_CODE(x) (SCM_CELL_WORD_3 (x))
#define SCM_SET_OBJCODE_NATIVE_CODE(x, code) (SCM_SET_CELL_WORD_3 (x, code)) #define SCM_SET_OBJCODE_NATIVE_CODE(x, code) (SCM_SET_CELL_WORD_3 (x, code))
SCM scm_c_make_objcode_slice (SCM parent, const scm_t_uint8 *ptr); SCM_API SCM scm_c_make_objcode_slice (SCM parent, const scm_t_uint8 *ptr);
SCM_API SCM scm_load_objcode (SCM file); SCM_API SCM scm_load_objcode (SCM file);
SCM_API SCM scm_objcode_p (SCM obj); SCM_API SCM scm_objcode_p (SCM obj);
SCM_API SCM scm_objcode_meta (SCM objcode); SCM_API SCM scm_objcode_meta (SCM objcode);
SCM_API SCM scm_bytecode_to_objcode (SCM bytecode); SCM_API SCM scm_bytecode_to_objcode (SCM bytecode);
SCM_INTERNAL SCM scm_bytecode_to_native_objcode (SCM bytecode);
SCM_API SCM scm_objcode_to_bytecode (SCM objcode); SCM_API SCM scm_objcode_to_bytecode (SCM objcode);
SCM_API SCM scm_write_objcode (SCM objcode, SCM port); SCM_API SCM scm_write_objcode (SCM objcode, SCM port);

View file

@ -2762,13 +2762,13 @@ scm_init_ports ()
#include "libguile/ports.x" #include "libguile/ports.x"
/* Use Latin-1 as the default port encoding. */ /* Use Latin-1 as the default port encoding. */
SCM_VARIABLE_SET (default_port_encoding_var, scm_make_fluid ()); SCM_VARIABLE_SET (default_port_encoding_var,
scm_fluid_set_x (SCM_VARIABLE_REF (default_port_encoding_var), SCM_BOOL_F); scm_make_fluid_with_default (SCM_BOOL_F));
scm_port_encoding_init = 1; scm_port_encoding_init = 1;
SCM_VARIABLE_SET (scm_conversion_strategy, scm_make_fluid ()); SCM_VARIABLE_SET (scm_conversion_strategy,
scm_fluid_set_x (SCM_VARIABLE_REF (scm_conversion_strategy), scm_make_fluid_with_default
scm_from_int ((int) SCM_FAILED_CONVERSION_QUESTION_MARK)); (scm_from_int ((int) SCM_FAILED_CONVERSION_QUESTION_MARK)));
scm_conversion_strategy_init = 1; scm_conversion_strategy_init = 1;
} }

View file

@ -43,9 +43,23 @@ SCM_GLOBAL_SYMBOL (scm_sym_name, "name");
static SCM overrides; static SCM overrides;
static SCM arity_overrides;
int int
scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest) scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest)
{ {
SCM o;
o = scm_weak_table_refq (arity_overrides, proc, SCM_BOOL_F);
if (scm_is_true (o))
{
*req = scm_to_int (scm_car (o));
*opt = scm_to_int (scm_cadr (o));
*rest = scm_is_true (scm_caddr (o));
return 1;
}
while (!SCM_PROGRAM_P (proc)) while (!SCM_PROGRAM_P (proc))
{ {
if (SCM_STRUCTP (proc)) if (SCM_STRUCTP (proc))
@ -63,9 +77,27 @@ scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest)
else else
return 0; return 0;
} }
return scm_i_program_arity (proc, req, opt, rest); return scm_i_program_arity (proc, req, opt, rest);
} }
SCM_DEFINE (scm_set_procedure_minimum_arity_x, "set-procedure-minimum-arity!",
4, 0, 0, (SCM proc, SCM req, SCM opt, SCM rest),
"")
#define FUNC_NAME s_scm_set_procedure_minimum_arity_x
{
int t SCM_UNUSED;
SCM_VALIDATE_PROC (1, proc);
SCM_VALIDATE_INT_COPY (2, req, t);
SCM_VALIDATE_INT_COPY (3, opt, t);
SCM_VALIDATE_BOOL (4, rest);
scm_weak_table_putq_x (arity_overrides, proc, scm_list_3 (req, opt, rest));
return SCM_UNDEFINED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_procedure_minimum_arity, "procedure-minimum-arity", 1, 0, 0, SCM_DEFINE (scm_procedure_minimum_arity, "procedure-minimum-arity", 1, 0, 0,
(SCM proc), (SCM proc),
"Return the \"minimum arity\" of a procedure.\n\n" "Return the \"minimum arity\" of a procedure.\n\n"
@ -171,6 +203,7 @@ void
scm_init_procprop () scm_init_procprop ()
{ {
overrides = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY); overrides = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
arity_overrides = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
#include "libguile/procprop.x" #include "libguile/procprop.x"
} }

View file

@ -33,6 +33,8 @@ SCM_API SCM scm_sym_system_procedure;
SCM_INTERNAL int scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest); SCM_INTERNAL int scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest);
SCM_API SCM scm_set_procedure_minimum_arity_x (SCM proc, SCM req, SCM opt,
SCM rest);
SCM_API SCM scm_procedure_minimum_arity (SCM proc); SCM_API SCM scm_procedure_minimum_arity (SCM proc);
SCM_API SCM scm_procedure_properties (SCM proc); SCM_API SCM scm_procedure_properties (SCM proc);
SCM_API SCM scm_set_procedure_properties_x (SCM proc, SCM alist); SCM_API SCM scm_set_procedure_properties_x (SCM proc, SCM alist);

View file

@ -1740,8 +1740,7 @@ scm_init_read ()
{ {
SCM read_hash_procs; SCM read_hash_procs;
read_hash_procs = scm_make_fluid (); read_hash_procs = scm_make_fluid_with_default (SCM_EOL);
scm_fluid_set_x (read_hash_procs, SCM_EOL);
scm_i_read_hash_procedures = scm_i_read_hash_procedures =
SCM_VARIABLE_LOC (scm_c_define ("%read-hash-procedures", read_hash_procs)); SCM_VARIABLE_LOC (scm_c_define ("%read-hash-procedures", read_hash_procs));

View file

@ -477,7 +477,7 @@ static SCM scm_i_default_dynamic_state;
/* Run when a fluid is collected. */ /* Run when a fluid is collected. */
void void
scm_i_reset_fluid (size_t n, SCM val) scm_i_reset_fluid (size_t n)
{ {
scm_i_thread *t; scm_i_thread *t;
@ -488,7 +488,7 @@ scm_i_reset_fluid (size_t n, SCM val)
SCM v = SCM_I_DYNAMIC_STATE_FLUIDS (t->dynamic_state); SCM v = SCM_I_DYNAMIC_STATE_FLUIDS (t->dynamic_state);
if (n < SCM_SIMPLE_VECTOR_LENGTH (v)) if (n < SCM_SIMPLE_VECTOR_LENGTH (v))
SCM_SIMPLE_VECTOR_SET (v, n, val); SCM_SIMPLE_VECTOR_SET (v, n, SCM_UNDEFINED);
} }
scm_i_pthread_mutex_unlock (&thread_admin_mutex); scm_i_pthread_mutex_unlock (&thread_admin_mutex);
} }
@ -1001,6 +1001,7 @@ SCM_DEFINE (scm_call_with_new_thread, "call-with-new-thread", 1, 1, 0,
SCM_ASSERT (SCM_UNBNDP (handler) || scm_is_true (scm_procedure_p (handler)), SCM_ASSERT (SCM_UNBNDP (handler) || scm_is_true (scm_procedure_p (handler)),
handler, SCM_ARG2, FUNC_NAME); handler, SCM_ARG2, FUNC_NAME);
GC_collect_a_little ();
data.parent = scm_current_dynamic_state (); data.parent = scm_current_dynamic_state ();
data.thunk = thunk; data.thunk = thunk;
data.handler = handler; data.handler = handler;

View file

@ -136,7 +136,7 @@ SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data,
SCM_API void *scm_without_guile (void *(*func)(void *), void *data); SCM_API void *scm_without_guile (void *(*func)(void *), void *data);
SCM_API void *scm_with_guile (void *(*func)(void *), void *data); SCM_API void *scm_with_guile (void *(*func)(void *), void *data);
SCM_INTERNAL void scm_i_reset_fluid (size_t, SCM); SCM_INTERNAL void scm_i_reset_fluid (size_t);
SCM_INTERNAL void scm_threads_prehistory (void *); SCM_INTERNAL void scm_threads_prehistory (void *);
SCM_INTERNAL void scm_init_threads (void); SCM_INTERNAL void scm_init_threads (void);
SCM_INTERNAL void scm_init_thread_procs (void); SCM_INTERNAL void scm_init_thread_procs (void);

View file

@ -1660,6 +1660,8 @@ VM_DEFINE_INSTRUCTION (91, fluid_ref, "fluid-ref", 0, 1, 1)
else else
{ {
SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num); SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num);
if (scm_is_eq (val, SCM_UNDEFINED))
val = SCM_I_FLUID_DEFAULT (*sp);
if (SCM_UNLIKELY (scm_is_eq (val, SCM_UNDEFINED))) if (SCM_UNLIKELY (scm_is_eq (val, SCM_UNDEFINED)))
{ {
finish_args = *sp; finish_args = *sp;

View file

@ -393,7 +393,7 @@ really_make_boot_program (long nargs)
u8vec = scm_c_take_gc_bytevector ((scm_t_int8*)bp, u8vec = scm_c_take_gc_bytevector ((scm_t_int8*)bp,
sizeof (struct scm_objcode) + sizeof (text), sizeof (struct scm_objcode) + sizeof (text),
SCM_BOOL_F); SCM_BOOL_F);
ret = scm_make_program (scm_bytecode_to_objcode (u8vec), ret = scm_make_program (scm_bytecode_to_native_objcode (u8vec),
SCM_BOOL_F, SCM_BOOL_F); SCM_BOOL_F, SCM_BOOL_F);
SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT); SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);

View file

@ -46,62 +46,72 @@ top_builddir="@top_builddir_absolute@"
exit 1 exit 1
} }
if [ x"$GUILE_LOAD_PATH" = x ] # When cross-compiling, let $GUILE_FOR_BUILD use its own .go files since
# the ones that are being built may be incompatible ($GUILE_FOR_BUILD is
# typically used to run `guild compile --target=$host'.) Likewise,
# $GUILE_FOR_BUILD must use its own source files when booting; for
# instance, $srcdir/module/ice-9/boot-9.scm must not be in its search
# path, because it would then end up using its C evaluator to run the
# compiler.
if test "@cross_compiling@" = "no"
then then
GUILE_LOAD_PATH="${top_srcdir}/module:${top_srcdir}/guile-readline:${top_srcdir}" if [ x"$GUILE_LOAD_PATH" = x ]
if test "${top_srcdir}" != "${top_builddir}"; then then
GUILE_LOAD_PATH="$GUILE_LOAD_PATH:${top_builddir}/module:${top_builddir}/guile-readline:${top_builddir}" GUILE_LOAD_PATH="${top_srcdir}/module:${top_srcdir}/guile-readline:${top_srcdir}"
if test "${top_srcdir}" != "${top_builddir}"; then
GUILE_LOAD_PATH="$GUILE_LOAD_PATH:${top_builddir}/module:${top_builddir}/guile-readline:${top_builddir}"
fi
else
for d in "/module" "/guile-readline" ""
do
# This hair prevents double inclusion.
# The ":" prevents prefix aliasing.
case x"$GUILE_LOAD_PATH" in
x*${top_srcdir}${d}:*) ;;
x*${top_srcdir}${d}) ;;
*) GUILE_LOAD_PATH="${top_srcdir}${d}:$GUILE_LOAD_PATH" ;;
esac
case x"$GUILE_LOAD_PATH" in
x*${top_builddir}${d}:*) ;;
x*${top_builddir}${d}) ;;
*) GUILE_LOAD_PATH="${top_builddir}${d}:$GUILE_LOAD_PATH" ;;
esac
done
fi fi
else export GUILE_LOAD_PATH
for d in "/module" "/guile-readline" ""
do
# This hair prevents double inclusion.
# The ":" prevents prefix aliasing.
case x"$GUILE_LOAD_PATH" in
x*${top_srcdir}${d}:*) ;;
x*${top_srcdir}${d}) ;;
*) GUILE_LOAD_PATH="${top_srcdir}${d}:$GUILE_LOAD_PATH" ;;
esac
case x"$GUILE_LOAD_PATH" in
x*${top_builddir}${d}:*) ;;
x*${top_builddir}${d}) ;;
*) GUILE_LOAD_PATH="${top_builddir}${d}:$GUILE_LOAD_PATH" ;;
esac
done
fi
export GUILE_LOAD_PATH
if [ x"$GUILE_LOAD_COMPILED_PATH" = x ] if test "x$GUILE_LOAD_COMPILED_PATH" = "x"
then then
GUILE_LOAD_COMPILED_PATH="${top_builddir}/module:${top_builddir}/guile-readline:${top_builddir}" GUILE_LOAD_COMPILED_PATH="${top_builddir}/module:${top_builddir}/guile-readline:${top_builddir}"
else else
for d in "/module" "/guile-readline" "" for d in "/module" "/guile-readline" ""
do do
# This hair prevents double inclusion. # This hair prevents double inclusion.
# The ":" prevents prefix aliasing. # The ":" prevents prefix aliasing.
case x"$GUILE_LOAD_COMPILED_PATH" in case x"$GUILE_LOAD_COMPILED_PATH" in
x*${top_builddir}${d}:*) ;; x*${top_builddir}${d}:*) ;;
x*${top_builddir}${d}) ;; x*${top_builddir}${d}) ;;
*) GUILE_LOAD_COMPILED_PATH="${top_builddir}${d}:$GUILE_LOAD_COMPILED_PATH" ;; *) GUILE_LOAD_COMPILED_PATH="${top_builddir}${d}:$GUILE_LOAD_COMPILED_PATH" ;;
esac esac
done done
fi fi
export GUILE_LOAD_COMPILED_PATH export GUILE_LOAD_COMPILED_PATH
# Don't look in installed dirs for guile modules # Don't look in installed dirs for guile modules
if ( env | grep -v '^GUILE_SYSTEM_PATH=' > /dev/null ); then if ( env | grep -v '^GUILE_SYSTEM_PATH=' > /dev/null ); then
GUILE_SYSTEM_PATH= GUILE_SYSTEM_PATH=
export GUILE_SYSTEM_PATH export GUILE_SYSTEM_PATH
fi fi
# Don't look in installed dirs for compiled guile modules # Don't look in installed dirs for compiled guile modules
if ( env | grep -v '^GUILE_SYSTEM_COMPILED_PATH=' > /dev/null ); then if ( env | grep -v '^GUILE_SYSTEM_COMPILED_PATH=' > /dev/null ); then
GUILE_SYSTEM_COMPILED_PATH= GUILE_SYSTEM_COMPILED_PATH=
export GUILE_SYSTEM_COMPILED_PATH export GUILE_SYSTEM_COMPILED_PATH
fi fi
# Don't look in installed dirs for dlopen-able modules # Don't look in installed dirs for dlopen-able modules
if ( env | grep -v '^GUILE_SYSTEM_EXTENSIONS_PATH=' > /dev/null ); then if ( env | grep -v '^GUILE_SYSTEM_EXTENSIONS_PATH=' > /dev/null ); then
GUILE_SYSTEM_EXTENSIONS_PATH= GUILE_SYSTEM_EXTENSIONS_PATH=
export GUILE_SYSTEM_EXTENSIONS_PATH export GUILE_SYSTEM_EXTENSIONS_PATH
fi
fi fi
# handle LTDL_LIBRARY_PATH (no clobber) # handle LTDL_LIBRARY_PATH (no clobber)

View file

@ -79,10 +79,14 @@ ice-9/psyntax-pp.scm.gen:
.PHONY: ice-9/psyntax-pp.scm.gen .PHONY: ice-9/psyntax-pp.scm.gen
# Keep this rule in sync with that in `am/guilec'.
ice-9/psyntax-pp.go: ice-9/psyntax.scm ice-9/psyntax-pp.scm ice-9/psyntax-pp.go: ice-9/psyntax.scm ice-9/psyntax-pp.scm
$(AM_V_GUILEC) GUILE_AUTO_COMPILE=0 \ $(AM_V_GUILEC)GUILE_AUTO_COMPILE=0 \
$(top_builddir)/meta/uninstalled-env \ $(top_builddir)/meta/uninstalled-env \
guild compile $(GUILE_WARNINGS) -o "ice-9/psyntax-pp.go" "$(srcdir)/ice-9/psyntax.scm" guild compile --target="$(host)" $(GUILE_WARNINGS) \
-L "$(abs_srcdir)" -L "$(abs_builddir)" \
-L "$(abs_top_srcdir)/guile-readline" \
-o "ice-9/psyntax-pp.go" "$(srcdir)/ice-9/psyntax.scm"
SCHEME_LANG_SOURCES = \ SCHEME_LANG_SOURCES = \
language/scheme/spec.scm \ language/scheme/spec.scm \

View file

@ -69,23 +69,6 @@
(define with-throw-handler #f) (define with-throw-handler #f)
(let () (let ()
;; Ideally we'd like to be able to give these default values for all threads,
;; even threads not created by Guile; but alack, that does not currently seem
;; possible. So wrap the getters in thunks.
(define %running-exception-handlers (make-fluid))
(define %exception-handler (make-fluid))
(define (running-exception-handlers)
(or (fluid-ref %running-exception-handlers)
(begin
(fluid-set! %running-exception-handlers '())
'())))
(define (exception-handler)
(or (fluid-ref %exception-handler)
(begin
(fluid-set! %exception-handler default-exception-handler)
default-exception-handler)))
(define (default-exception-handler k . args) (define (default-exception-handler k . args)
(cond (cond
((eq? k 'quit) ((eq? k 'quit)
@ -98,18 +81,21 @@
(format (current-error-port) "guile: uncaught throw to ~a: ~a\n" k args) (format (current-error-port) "guile: uncaught throw to ~a: ~a\n" k args)
(primitive-exit 1)))) (primitive-exit 1))))
(define %running-exception-handlers (make-fluid '()))
(define %exception-handler (make-fluid default-exception-handler))
(define (default-throw-handler prompt-tag catch-k) (define (default-throw-handler prompt-tag catch-k)
(let ((prev (exception-handler))) (let ((prev (fluid-ref %exception-handler)))
(lambda (thrown-k . args) (lambda (thrown-k . args)
(if (or (eq? thrown-k catch-k) (eqv? catch-k #t)) (if (or (eq? thrown-k catch-k) (eqv? catch-k #t))
(apply abort-to-prompt prompt-tag thrown-k args) (apply abort-to-prompt prompt-tag thrown-k args)
(apply prev thrown-k args))))) (apply prev thrown-k args)))))
(define (custom-throw-handler prompt-tag catch-k pre) (define (custom-throw-handler prompt-tag catch-k pre)
(let ((prev (exception-handler))) (let ((prev (fluid-ref %exception-handler)))
(lambda (thrown-k . args) (lambda (thrown-k . args)
(if (or (eq? thrown-k catch-k) (eqv? catch-k #t)) (if (or (eq? thrown-k catch-k) (eqv? catch-k #t))
(let ((running (running-exception-handlers))) (let ((running (fluid-ref %running-exception-handlers)))
(with-fluids ((%running-exception-handlers (cons pre running))) (with-fluids ((%running-exception-handlers (cons pre running)))
(if (not (memq pre running)) (if (not (memq pre running))
(apply pre thrown-k args)) (apply pre thrown-k args))
@ -192,9 +178,9 @@ for key @var{key}, then invoke @var{thunk}."
If there is no handler at all, Guile prints an error and then exits." If there is no handler at all, Guile prints an error and then exits."
(if (not (symbol? key)) (if (not (symbol? key))
((exception-handler) 'wrong-type-arg "throw" ((fluid-ref %exception-handler) 'wrong-type-arg "throw"
"Wrong type argument in position ~a: ~a" (list 1 key) (list key)) "Wrong type argument in position ~a: ~a" (list 1 key) (list key))
(apply (exception-handler) key args))))) (apply (fluid-ref %exception-handler) key args)))))
@ -1404,8 +1390,7 @@ VALUE."
;;; Reader code for various "#c" forms. ;;; Reader code for various "#c" forms.
;;; ;;;
(define read-eval? (make-fluid)) (define read-eval? (make-fluid #f))
(fluid-set! read-eval? #f)
(read-hash-extend #\. (read-hash-extend #\.
(lambda (c port) (lambda (c port)
(if (fluid-ref read-eval?) (if (fluid-ref read-eval?)
@ -2843,14 +2828,14 @@ module '(ice-9 q) '(make-q q-length))}."
;;; {Running Repls} ;;; {Running Repls}
;;; ;;;
(define *repl-stack* (make-fluid)) (define *repl-stack* (make-fluid '()))
;; Programs can call `batch-mode?' to see if they are running as part of a ;; Programs can call `batch-mode?' to see if they are running as part of a
;; script or if they are running interactively. REPL implementations ensure that ;; script or if they are running interactively. REPL implementations ensure that
;; `batch-mode?' returns #f during their extent. ;; `batch-mode?' returns #f during their extent.
;; ;;
(define (batch-mode?) (define (batch-mode?)
(null? (or (fluid-ref *repl-stack*) '()))) (null? (fluid-ref *repl-stack*)))
;; Programs can re-enter batch mode, for example after a fork, by calling ;; Programs can re-enter batch mode, for example after a fork, by calling
;; `ensure-batch-mode!'. It's not a great interface, though; it would be better ;; `ensure-batch-mode!'. It's not a great interface, though; it would be better
@ -2889,7 +2874,26 @@ module '(ice-9 q) '(make-q q-length))}."
(define repl-reader (define repl-reader
(lambda* (prompt #:optional (reader (fluid-ref current-reader))) (lambda* (prompt #:optional (reader (fluid-ref current-reader)))
(if (not (char-ready?)) (if (not (char-ready?))
(display (if (string? prompt) prompt (prompt)))) (begin
(display (if (string? prompt) prompt (prompt)))
;; An interesting situation. The printer resets the column to
;; 0 by printing a newline, but we then advance it by printing
;; the prompt. However the port-column of the output port
;; does not typically correspond with the actual column on the
;; screen, because the input is is echoed back! Since the
;; input is line-buffered and thus ends with a newline, the
;; output will really start on column zero. So, here we zero
;; it out. See bug 9664.
;;
;; Note that for similar reasons, the output-line will not
;; reflect the actual line on the screen. But given the
;; possibility of multiline input, the fix is not as
;; straightforward, so we don't bother.
;;
;; Also note that the readline implementation papers over
;; these concerns, because it's readline itself printing the
;; prompt, and not Guile.
(set-port-column! (current-output-port) 0)))
(force-output) (force-output)
(run-hook before-read-hook) (run-hook before-read-hook)
((or reader read) (current-input-port)))) ((or reader read) (current-input-port))))
@ -3241,8 +3245,7 @@ module '(ice-9 q) '(make-q q-length))}."
;;; ;;;
(define* (make-mutable-parameter init #:optional (converter identity)) (define* (make-mutable-parameter init #:optional (converter identity))
(let ((fluid (make-fluid))) (let ((fluid (make-fluid (converter init))))
(fluid-set! fluid (converter init))
(case-lambda (case-lambda
(() (fluid-ref fluid)) (() (fluid-ref fluid))
((val) (fluid-set! fluid (converter val)))))) ((val) (fluid-set! fluid (converter val))))))

View file

@ -235,109 +235,127 @@
(inits (if tail (caddr tail) '())) (inits (if tail (caddr tail) '()))
(alt (and tail (cadddr tail)))) (alt (and tail (cadddr tail))))
(make-general-closure env body nreq rest nopt kw inits alt)))) (make-general-closure env body nreq rest nopt kw inits alt))))
(lambda %args (define (set-procedure-arity! proc)
(let lp ((env env) (let lp ((alt alt) (nreq nreq) (nopt nopt) (rest? rest?))
(nreq* nreq) (if (not alt)
(args %args)) (set-procedure-minimum-arity! proc nreq nopt rest?)
(if (> nreq* 0) (let* ((nreq* (cadr alt))
;; First, bind required arguments. (rest?* (if (null? (cddr alt)) #f (caddr alt)))
(if (null? args) (tail (and (pair? (cddr alt)) (pair? (cdddr alt)) (cdddr alt)))
(if alt (nopt* (if tail (car tail) 0))
(apply alt-proc %args) (alt* (and tail (cadddr tail))))
(scm-error 'wrong-number-of-args (if (or (< nreq* nreq)
"eval" "Wrong number of arguments" (and (= nreq* nreq)
'() #f)) (if rest?
(lp (cons (car args) env) (and rest?* (> nopt* nopt))
(1- nreq*) (or rest?* (> nopt* nopt)))))
(cdr args))) (lp alt* nreq* nopt* rest?*)
;; Move on to optional arguments. (lp alt* nreq nopt rest?)))))
(if (not kw) proc)
;; Without keywords, bind optionals from arguments. (set-procedure-arity!
(let lp ((env env) (lambda %args
(nopt nopt) (let lp ((env env)
(args args) (nreq* nreq)
(inits inits)) (args %args))
(if (zero? nopt) (if (> nreq* 0)
(if rest? ;; First, bind required arguments.
(eval body (cons args env)) (if (null? args)
(if (null? args) (if alt
(eval body env) (apply alt-proc %args)
(if alt (scm-error 'wrong-number-of-args
(apply alt-proc %args) "eval" "Wrong number of arguments"
(scm-error 'wrong-number-of-args '() #f))
"eval" "Wrong number of arguments" (lp (cons (car args) env)
'() #f)))) (1- nreq*)
(if (null? args) (cdr args)))
(lp (cons (eval (car inits) env) env) ;; Move on to optional arguments.
(1- nopt) args (cdr inits)) (if (not kw)
(lp (cons (car args) env) ;; Without keywords, bind optionals from arguments.
(1- nopt) (cdr args) (cdr inits))))) (let lp ((env env)
;; With keywords, we stop binding optionals at the first (nopt nopt)
;; keyword. (args args)
(let lp ((env env) (inits inits))
(nopt* nopt) (if (zero? nopt)
(args args) (if rest?
(inits inits)) (eval body (cons args env))
(if (> nopt* 0) (if (null? args)
(if (or (null? args) (keyword? (car args))) (eval body env)
(lp (cons (eval (car inits) env) env) (if alt
(1- nopt*) args (cdr inits)) (apply alt-proc %args)
(lp (cons (car args) env) (scm-error 'wrong-number-of-args
(1- nopt*) (cdr args) (cdr inits))) "eval" "Wrong number of arguments"
;; Finished with optionals. '() #f))))
(let* ((aok (car kw)) (if (null? args)
(kw (cdr kw)) (lp (cons (eval (car inits) env) env)
(kw-base (+ nopt nreq (if rest? 1 0))) (1- nopt) args (cdr inits))
(imax (let lp ((imax (1- kw-base)) (kw kw)) (lp (cons (car args) env)
(if (null? kw) (1- nopt) (cdr args) (cdr inits)))))
imax ;; With keywords, we stop binding optionals at the first
(lp (max (cdar kw) imax) ;; keyword.
(cdr kw))))) (let lp ((env env)
;; Fill in kwargs with "undefined" vals. (nopt* nopt)
(env (let lp ((i kw-base) (args args)
;; Also, here we bind the rest (inits inits))
;; arg, if any. (if (> nopt* 0)
(env (if rest? (cons args env) env))) (if (or (null? args) (keyword? (car args)))
(if (<= i imax) (lp (cons (eval (car inits) env) env)
(lp (1+ i) (cons unbound-arg env)) (1- nopt*) args (cdr inits))
env)))) (lp (cons (car args) env)
;; Now scan args for keywords. (1- nopt*) (cdr args) (cdr inits)))
(let lp ((args args)) ;; Finished with optionals.
(if (and (pair? args) (pair? (cdr args)) (let* ((aok (car kw))
(keyword? (car args))) (kw (cdr kw))
(let ((kw-pair (assq (car args) kw)) (kw-base (+ nopt nreq (if rest? 1 0)))
(v (cadr args))) (imax (let lp ((imax (1- kw-base)) (kw kw))
(if kw-pair (if (null? kw)
;; Found a known keyword; set its value. imax
(list-set! env (- imax (cdr kw-pair)) v) (lp (max (cdar kw) imax)
;; Unknown keyword. (cdr kw)))))
(if (not aok) ;; Fill in kwargs with "undefined" vals.
(scm-error 'keyword-argument-error (env (let lp ((i kw-base)
"eval" "Unrecognized keyword" ;; Also, here we bind the rest
'() #f))) ;; arg, if any.
(lp (cddr args))) (env (if rest? (cons args env) env)))
(if (pair? args) (if (<= i imax)
(if rest? (lp (1+ i) (cons unbound-arg env))
;; Be lenient parsing rest args. env))))
(lp (cdr args)) ;; Now scan args for keywords.
(scm-error 'keyword-argument-error (let lp ((args args))
"eval" "Invalid keyword" (if (and (pair? args) (pair? (cdr args))
'() #f)) (keyword? (car args)))
;; Finished parsing keywords. Fill in (let ((kw-pair (assq (car args) kw))
;; uninitialized kwargs by evalling init (v (cadr args)))
;; expressions in their appropriate (if kw-pair
;; environment. ;; Found a known keyword; set its value.
(let lp ((i (- imax kw-base)) (list-set! env (- imax (cdr kw-pair)) v)
(inits inits)) ;; Unknown keyword.
(if (pair? inits) (if (not aok)
(let ((tail (list-tail env i))) (scm-error 'keyword-argument-error
(if (eq? (car tail) unbound-arg) "eval" "Unrecognized keyword"
(set-car! tail '() #f)))
(eval (car inits) (lp (cddr args)))
(cdr tail)))) (if (pair? args)
(lp (1- i) (cdr inits))) (if rest?
;; Finally, eval the body. ;; Be lenient parsing rest args.
(eval body env)))))))))))))) (lp (cdr args))
(scm-error 'keyword-argument-error
"eval" "Invalid keyword"
'() #f))
;; Finished parsing keywords. Fill in
;; uninitialized kwargs by evalling init
;; expressions in their appropriate
;; environment.
(let lp ((i (- imax kw-base))
(inits inits))
(if (pair? inits)
(let ((tail (list-tail env i)))
(if (eq? (car tail) unbound-arg)
(set-car! tail
(eval (car inits)
(cdr tail))))
(lp (1- i) (cdr inits)))
;; Finally, eval the body.
(eval body env)))))))))))))))
;; The "engine". EXP is a memoized expression. ;; The "engine". EXP is a memoized expression.
(define (eval exp env) (define (eval exp env)
@ -404,7 +422,10 @@
(memoize-variable-access! exp #f)))) (memoize-variable-access! exp #f))))
(('define (name . x)) (('define (name . x))
(define! name (eval x env))) (let ((x (eval x env)))
(if (and (procedure? x) (not (procedure-property x 'name)))
(set-procedure-property! x 'name name))
(define! name x)))
(('toplevel-set! (var-or-sym . x)) (('toplevel-set! (var-or-sym . x))
(variable-set! (variable-set!

View file

@ -164,9 +164,9 @@
#:use-module (ice-9 optargs) #:use-module (ice-9 optargs)
#:export (getopt-long option-ref)) #:export (getopt-long option-ref))
(define %program-name (make-fluid)) (define %program-name (make-fluid "guile"))
(define (program-name) (define (program-name)
(or (fluid-ref %program-name) "guile")) (fluid-ref %program-name))
(define (fatal-error fmt . args) (define (fatal-error fmt . args)
(format (current-error-port) "~a: " (program-name)) (format (current-error-port) "~a: " (program-name))

File diff suppressed because it is too large Load diff

View file

@ -952,17 +952,17 @@
;; expanding ;; expanding
(define chi-sequence (define expand-sequence
(lambda (body r w s mod) (lambda (body r w s mod)
(build-sequence s (build-sequence s
(let dobody ((body body) (r r) (w w) (mod mod)) (let dobody ((body body) (r r) (w w) (mod mod))
(if (null? body) (if (null? body)
'() '()
(let ((first (chi (car body) r w mod))) (let ((first (expand (car body) r w mod)))
(cons first (dobody (cdr body) r w mod)))))))) (cons first (dobody (cdr body) r w mod))))))))
;; At top-level, we allow mixed definitions and expressions. Like ;; At top-level, we allow mixed definitions and expressions. Like
;; chi-body we expand in two passes. ;; expand-body we expand in two passes.
;; ;;
;; First, from left to right, we expand just enough to know what ;; First, from left to right, we expand just enough to know what
;; expressions are definitions, syntax definitions, and splicing ;; expressions are definitions, syntax definitions, and splicing
@ -975,7 +975,7 @@
;; expansions of all normal definitions and expressions in the ;; expansions of all normal definitions and expressions in the
;; sequence. ;; sequence.
;; ;;
(define chi-top-sequence (define expand-top-sequence
(lambda (body r w s m esew mod) (lambda (body r w s m esew mod)
(let* ((r (cons '("placeholder" . (placeholder)) r)) (let* ((r (cons '("placeholder" . (placeholder)) r))
(ribcage (make-empty-ribcage)) (ribcage (make-empty-ribcage))
@ -1027,11 +1027,11 @@
(record-definition! id var) (record-definition! id var)
(list (list
(if (eq? m 'c&e) (if (eq? m 'c&e)
(let ((x (build-global-definition s var (chi e r w mod)))) (let ((x (build-global-definition s var (expand e r w mod))))
(top-level-eval-hook x mod) (top-level-eval-hook x mod)
(lambda () x)) (lambda () x))
(lambda () (lambda ()
(build-global-definition s var (chi e r w mod))))))) (build-global-definition s var (expand e r w mod)))))))
((define-syntax-form define-syntax-parameter-form) ((define-syntax-form define-syntax-parameter-form)
(let* ((id (wrap value w mod)) (let* ((id (wrap value w mod))
(label (gen-label)) (label (gen-label))
@ -1043,23 +1043,23 @@
((c) ((c)
(cond (cond
((memq 'compile esew) ((memq 'compile esew)
(let ((e (chi-install-global var type (chi e r w mod)))) (let ((e (expand-install-global var type (expand e r w mod))))
(top-level-eval-hook e mod) (top-level-eval-hook e mod)
(if (memq 'load esew) (if (memq 'load esew)
(list (lambda () e)) (list (lambda () e))
'()))) '())))
((memq 'load esew) ((memq 'load esew)
(list (lambda () (list (lambda ()
(chi-install-global var type (chi e r w mod))))) (expand-install-global var type (expand e r w mod)))))
(else '()))) (else '())))
((c&e) ((c&e)
(let ((e (chi-install-global var type (chi e r w mod)))) (let ((e (expand-install-global var type (expand e r w mod))))
(top-level-eval-hook e mod) (top-level-eval-hook e mod)
(list (lambda () e)))) (list (lambda () e))))
(else (else
(if (memq 'eval esew) (if (memq 'eval esew)
(top-level-eval-hook (top-level-eval-hook
(chi-install-global var type (chi e r w mod)) (expand-install-global var type (expand e r w mod))
mod)) mod))
'())))) '()))))
((begin-form) ((begin-form)
@ -1067,13 +1067,13 @@
((_ e1 ...) ((_ e1 ...)
(parse #'(e1 ...) r w s m esew mod)))) (parse #'(e1 ...) r w s m esew mod))))
((local-syntax-form) ((local-syntax-form)
(chi-local-syntax value e r w s mod (expand-local-syntax value e r w s mod
(lambda (forms r w s mod) (lambda (forms r w s mod)
(parse forms r w s m esew mod)))) (parse forms r w s m esew mod))))
((eval-when-form) ((eval-when-form)
(syntax-case e () (syntax-case e ()
((_ (x ...) e1 e2 ...) ((_ (x ...) e1 e2 ...)
(let ((when-list (chi-when-list e #'(x ...) w)) (let ((when-list (parse-when-list e #'(x ...)))
(body #'(e1 e2 ...))) (body #'(e1 e2 ...)))
(define (recurse m esew) (define (recurse m esew)
(parse body r w s m esew mod)) (parse body r w s m esew mod))
@ -1085,7 +1085,7 @@
(begin (begin
(if (memq 'expand when-list) (if (memq 'expand when-list)
(top-level-eval-hook (top-level-eval-hook
(chi-top-sequence body r w s 'e '(eval) mod) (expand-top-sequence body r w s 'e '(eval) mod)
mod)) mod))
'()))) '())))
((memq 'load when-list) ((memq 'load when-list)
@ -1100,7 +1100,7 @@
(memq 'expand when-list) (memq 'expand when-list)
(and (eq? m 'c&e) (memq 'eval when-list))) (and (eq? m 'c&e) (memq 'eval when-list)))
(top-level-eval-hook (top-level-eval-hook
(chi-top-sequence body r w s 'e '(eval) mod) (expand-top-sequence body r w s 'e '(eval) mod)
mod) mod)
'()) '())
(else (else
@ -1108,18 +1108,18 @@
(else (else
(list (list
(if (eq? m 'c&e) (if (eq? m 'c&e)
(let ((x (chi-expr type value e r w s mod))) (let ((x (expand-expr type value e r w s mod)))
(top-level-eval-hook x mod) (top-level-eval-hook x mod)
(lambda () x)) (lambda () x))
(lambda () (lambda ()
(chi-expr type value e r w s mod))))))))) (expand-expr type value e r w s mod)))))))))
(let ((exps (map (lambda (x) (x)) (let ((exps (map (lambda (x) (x))
(reverse (parse body r w s m esew mod))))) (reverse (parse body r w s m esew mod)))))
(if (null? exps) (if (null? exps)
(build-void s) (build-void s)
(build-sequence s exps)))))) (build-sequence s exps))))))
(define chi-install-global (define expand-install-global
(lambda (name type e) (lambda (name type e)
(build-global-definition (build-global-definition
no-source no-source
@ -1135,24 +1135,21 @@
(build-data no-source 'macro) (build-data no-source 'macro)
e)))))) e))))))
(define chi-when-list (define parse-when-list
(lambda (e when-list w) (lambda (e when-list)
;; `when-list' is syntax'd version of list of situations. We ;; `when-list' is syntax'd version of list of situations. We
;; could match these keywords lexically, via free-id=?, but then ;; could match these keywords lexically, via free-id=?, but then
;; we twingle the definition of eval-when to the bindings of ;; we twingle the definition of eval-when to the bindings of
;; eval, load, expand, and compile, which is totally unintended. ;; eval, load, expand, and compile, which is totally unintended.
;; So do a symbolic match instead. ;; So do a symbolic match instead.
(let f ((when-list when-list) (situations '())) (let ((result (strip when-list empty-wrap)))
(if (null? when-list) (let lp ((l result))
situations (if (null? l)
(f (cdr when-list) result
(cons (let ((x (syntax->datum (car when-list)))) (if (memq (car l) '(compile load eval expand))
(if (memq x '(compile load eval expand)) (lp (cdr l))
x (syntax-violation 'eval-when "invalid situation" e
(syntax-violation 'eval-when (car l))))))))
"invalid situation"
e (wrap (car when-list) w #f))))
situations))))))
;; syntax-type returns six values: type, value, e, w, s, and mod. The ;; syntax-type returns six values: type, value, e, w, s, and mod. The
;; first two are described in the table below. ;; first two are described in the table below.
@ -1203,7 +1200,7 @@
((macro) ((macro)
(if for-car? (if for-car?
(values type value e w s mod) (values type value e w s mod)
(syntax-type (chi-macro value e r w s rib mod) (syntax-type (expand-macro value e r w s rib mod)
r empty-wrap s rib mod #f))) r empty-wrap s rib mod #f)))
((global) ((global)
;; Toplevel definitions may resolve to bindings with ;; Toplevel definitions may resolve to bindings with
@ -1225,7 +1222,7 @@
(values 'global-call (make-syntax-object fval w fmod) (values 'global-call (make-syntax-object fval w fmod)
e w s mod)) e w s mod))
((macro) ((macro)
(syntax-type (chi-macro fval e r w s rib mod) (syntax-type (expand-macro fval e r w s rib mod)
r empty-wrap s rib mod for-car?)) r empty-wrap s rib mod for-car?))
((module-ref) ((module-ref)
(call-with-values (lambda () (fval e r w)) (call-with-values (lambda () (fval e r w))
@ -1279,14 +1276,14 @@
((self-evaluating? e) (values 'constant #f e w s mod)) ((self-evaluating? e) (values 'constant #f e w s mod))
(else (values 'other #f e w s mod))))) (else (values 'other #f e w s mod)))))
(define chi (define expand
(lambda (e r w mod) (lambda (e r w mod)
(call-with-values (call-with-values
(lambda () (syntax-type e r w (source-annotation e) #f mod #f)) (lambda () (syntax-type e r w (source-annotation e) #f mod #f))
(lambda (type value e w s mod) (lambda (type value e w s mod)
(chi-expr type value e r w s mod))))) (expand-expr type value e r w s mod)))))
(define chi-expr (define expand-expr
(lambda (type value e r w s mod) (lambda (type value e r w s mod)
(case type (case type
((lexical) ((lexical)
@ -1297,9 +1294,9 @@
((module-ref) ((module-ref)
(call-with-values (lambda () (value e r w)) (call-with-values (lambda () (value e r w))
(lambda (e r w s mod) (lambda (e r w s mod)
(chi e r w mod)))) (expand e r w mod))))
((lexical-call) ((lexical-call)
(chi-call (expand-call
(let ((id (car e))) (let ((id (car e)))
(build-lexical-reference 'fun (source-annotation id) (build-lexical-reference 'fun (source-annotation id)
(if (syntax-object? id) (if (syntax-object? id)
@ -1308,7 +1305,7 @@
value)) value))
e r w s mod)) e r w s mod))
((global-call) ((global-call)
(chi-call (expand-call
(build-global-reference (source-annotation (car e)) (build-global-reference (source-annotation (car e))
(if (syntax-object? value) (if (syntax-object? value)
(syntax-object-expression value) (syntax-object-expression value)
@ -1319,19 +1316,19 @@
e r w s mod)) e r w s mod))
((constant) (build-data s (strip (source-wrap e w s mod) empty-wrap))) ((constant) (build-data s (strip (source-wrap e w s mod) empty-wrap)))
((global) (build-global-reference s value mod)) ((global) (build-global-reference s value mod))
((call) (chi-call (chi (car e) r w mod) e r w s mod)) ((call) (expand-call (expand (car e) r w mod) e r w s mod))
((begin-form) ((begin-form)
(syntax-case e () (syntax-case e ()
((_ e1 e2 ...) (chi-sequence #'(e1 e2 ...) r w s mod)))) ((_ e1 e2 ...) (expand-sequence #'(e1 e2 ...) r w s mod))))
((local-syntax-form) ((local-syntax-form)
(chi-local-syntax value e r w s mod chi-sequence)) (expand-local-syntax value e r w s mod expand-sequence))
((eval-when-form) ((eval-when-form)
(syntax-case e () (syntax-case e ()
((_ (x ...) e1 e2 ...) ((_ (x ...) e1 e2 ...)
(let ((when-list (chi-when-list e #'(x ...) w))) (let ((when-list (parse-when-list e #'(x ...))))
(if (memq 'eval when-list) (if (memq 'eval when-list)
(chi-sequence #'(e1 e2 ...) r w s mod) (expand-sequence #'(e1 e2 ...) r w s mod)
(chi-void)))))) (expand-void))))))
((define-form define-syntax-form define-syntax-parameter-form) ((define-form define-syntax-form define-syntax-parameter-form)
(syntax-violation #f "definition in expression context" (syntax-violation #f "definition in expression context"
e (wrap value w mod))) e (wrap value w mod)))
@ -1344,12 +1341,12 @@
(else (syntax-violation #f "unexpected syntax" (else (syntax-violation #f "unexpected syntax"
(source-wrap e w s mod)))))) (source-wrap e w s mod))))))
(define chi-call (define expand-call
(lambda (x e r w s mod) (lambda (x e r w s mod)
(syntax-case e () (syntax-case e ()
((e0 e1 ...) ((e0 e1 ...)
(build-call s x (build-call s x
(map (lambda (e) (chi e r w mod)) #'(e1 ...))))))) (map (lambda (e) (expand e r w mod)) #'(e1 ...)))))))
;; (What follows is my interpretation of what's going on here -- Andy) ;; (What follows is my interpretation of what's going on here -- Andy)
;; ;;
@ -1384,7 +1381,7 @@
;; really nice if we could also annotate introduced expressions with the ;; really nice if we could also annotate introduced expressions with the
;; locations corresponding to the macro definition, but that is not yet ;; locations corresponding to the macro definition, but that is not yet
;; possible. ;; possible.
(define chi-macro (define expand-macro
(lambda (p e r w s rib mod) (lambda (p e r w s rib mod)
(define rebuild-macro-output (define rebuild-macro-output
(lambda (x m) (lambda (x m)
@ -1425,7 +1422,7 @@
(rebuild-macro-output (p (source-wrap e (anti-mark w) s mod)) (rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
(new-mark)))) (new-mark))))
(define chi-body (define expand-body
;; In processing the forms of the body, we create a new, empty wrap. ;; In processing the forms of the body, we create a new, empty wrap.
;; This wrap is augmented (destructively) each time we discover that ;; This wrap is augmented (destructively) each time we discover that
;; the next form is a definition. This is done: ;; the next form is a definition. This is done:
@ -1509,19 +1506,19 @@
(f (cdr forms))))) (f (cdr forms)))))
ids labels var-ids vars vals bindings)))) ids labels var-ids vars vals bindings))))
((local-syntax-form) ((local-syntax-form)
(chi-local-syntax value e er w s mod (expand-local-syntax value e er w s mod
(lambda (forms er w s mod) (lambda (forms er w s mod)
(parse (let f ((forms forms)) (parse (let f ((forms forms))
(if (null? forms) (if (null? forms)
(cdr body) (cdr body)
(cons (cons er (wrap (car forms) w mod)) (cons (cons er (wrap (car forms) w mod))
(f (cdr forms))))) (f (cdr forms)))))
ids labels var-ids vars vals bindings)))) ids labels var-ids vars vals bindings))))
(else ; found a non-definition (else ; found a non-definition
(if (null? ids) (if (null? ids)
(build-sequence no-source (build-sequence no-source
(map (lambda (x) (map (lambda (x)
(chi (cdr x) (car x) empty-wrap mod)) (expand (cdr x) (car x) empty-wrap mod))
(cons (cons er (source-wrap e w s mod)) (cons (cons er (source-wrap e w s mod))
(cdr body)))) (cdr body))))
(begin (begin
@ -1540,7 +1537,7 @@
(macros-only-env er)))) (macros-only-env er))))
(set-cdr! b (set-cdr! b
(eval-local-transformer (eval-local-transformer
(chi (cddr b) r-cache empty-wrap mod) (expand (cddr b) r-cache empty-wrap mod)
mod)) mod))
(if (eq? (car b) 'syntax-parameter) (if (eq? (car b) 'syntax-parameter)
(set-cdr! b (list (cdr b)))) (set-cdr! b (list (cdr b))))
@ -1551,15 +1548,15 @@
(reverse (map syntax->datum var-ids)) (reverse (map syntax->datum var-ids))
(reverse vars) (reverse vars)
(map (lambda (x) (map (lambda (x)
(chi (cdr x) (car x) empty-wrap mod)) (expand (cdr x) (car x) empty-wrap mod))
(reverse vals)) (reverse vals))
(build-sequence no-source (build-sequence no-source
(map (lambda (x) (map (lambda (x)
(chi (cdr x) (car x) empty-wrap mod)) (expand (cdr x) (car x) empty-wrap mod))
(cons (cons er (source-wrap e w s mod)) (cons (cons er (source-wrap e w s mod))
(cdr body))))))))))))))))) (cdr body)))))))))))))))))
(define chi-local-syntax (define expand-local-syntax
(lambda (rec? e r w s mod k) (lambda (rec? e r w s mod k)
(syntax-case e () (syntax-case e ()
((_ ((id val) ...) e1 e2 ...) ((_ ((id val) ...) e1 e2 ...)
@ -1576,7 +1573,7 @@
(map (lambda (x) (map (lambda (x)
(make-binding 'macro (make-binding 'macro
(eval-local-transformer (eval-local-transformer
(chi x trans-r w mod) (expand x trans-r w mod)
mod))) mod)))
#'(val ...))) #'(val ...)))
r) r)
@ -1593,7 +1590,7 @@
p p
(syntax-violation #f "nonprocedure transformer" p))))) (syntax-violation #f "nonprocedure transformer" p)))))
(define chi-void (define expand-void
(lambda () (lambda ()
(build-void no-source))) (build-void no-source)))
@ -1623,7 +1620,7 @@
orig-args)))) orig-args))))
(req orig-args '()))) (req orig-args '())))
(define chi-simple-lambda (define expand-simple-lambda
(lambda (e r w s mod req rest meta body) (lambda (e r w s mod req rest meta body)
(let* ((ids (if rest (append req (list rest)) req)) (let* ((ids (if rest (append req (list rest)) req))
(vars (map gen-var ids)) (vars (map gen-var ids))
@ -1632,10 +1629,10 @@
s s
(map syntax->datum req) (and rest (syntax->datum rest)) vars (map syntax->datum req) (and rest (syntax->datum rest)) vars
meta meta
(chi-body body (source-wrap e w s mod) (expand-body body (source-wrap e w s mod)
(extend-var-env labels vars r) (extend-var-env labels vars r)
(make-binding-wrap ids labels w) (make-binding-wrap ids labels w)
mod))))) mod)))))
(define lambda*-formals (define lambda*-formals
(lambda (orig-args) (lambda (orig-args)
@ -1718,16 +1715,16 @@
orig-args)))) orig-args))))
(req orig-args '()))) (req orig-args '())))
(define chi-lambda-case (define expand-lambda-case
(lambda (e r w s mod get-formals clauses) (lambda (e r w s mod get-formals clauses)
(define (expand-req req opt rest kw body) (define (parse-req req opt rest kw body)
(let ((vars (map gen-var req)) (let ((vars (map gen-var req))
(labels (gen-labels req))) (labels (gen-labels req)))
(let ((r* (extend-var-env labels vars r)) (let ((r* (extend-var-env labels vars r))
(w* (make-binding-wrap req labels w))) (w* (make-binding-wrap req labels w)))
(expand-opt (map syntax->datum req) (parse-opt (map syntax->datum req)
opt rest kw body (reverse vars) r* w* '() '())))) opt rest kw body (reverse vars) r* w* '() '()))))
(define (expand-opt req opt rest kw body vars r* w* out inits) (define (parse-opt req opt rest kw body vars r* w* out inits)
(cond (cond
((pair? opt) ((pair? opt)
(syntax-case (car opt) () (syntax-case (car opt) ()
@ -1736,27 +1733,27 @@
(l (gen-labels (list v))) (l (gen-labels (list v)))
(r** (extend-var-env l (list v) r*)) (r** (extend-var-env l (list v) r*))
(w** (make-binding-wrap (list #'id) l w*))) (w** (make-binding-wrap (list #'id) l w*)))
(expand-opt req (cdr opt) rest kw body (cons v vars) (parse-opt req (cdr opt) rest kw body (cons v vars)
r** w** (cons (syntax->datum #'id) out) r** w** (cons (syntax->datum #'id) out)
(cons (chi #'i r* w* mod) inits)))))) (cons (expand #'i r* w* mod) inits))))))
(rest (rest
(let* ((v (gen-var rest)) (let* ((v (gen-var rest))
(l (gen-labels (list v))) (l (gen-labels (list v)))
(r* (extend-var-env l (list v) r*)) (r* (extend-var-env l (list v) r*))
(w* (make-binding-wrap (list rest) l w*))) (w* (make-binding-wrap (list rest) l w*)))
(expand-kw req (if (pair? out) (reverse out) #f) (parse-kw req (if (pair? out) (reverse out) #f)
(syntax->datum rest) (syntax->datum rest)
(if (pair? kw) (cdr kw) kw) (if (pair? kw) (cdr kw) kw)
body (cons v vars) r* w* body (cons v vars) r* w*
(if (pair? kw) (car kw) #f) (if (pair? kw) (car kw) #f)
'() inits))) '() inits)))
(else (else
(expand-kw req (if (pair? out) (reverse out) #f) #f (parse-kw req (if (pair? out) (reverse out) #f) #f
(if (pair? kw) (cdr kw) kw) (if (pair? kw) (cdr kw) kw)
body vars r* w* body vars r* w*
(if (pair? kw) (car kw) #f) (if (pair? kw) (car kw) #f)
'() inits)))) '() inits))))
(define (expand-kw req opt rest kw body vars r* w* aok out inits) (define (parse-kw req opt rest kw body vars r* w* aok out inits)
(cond (cond
((pair? kw) ((pair? kw)
(syntax-case (car kw) () (syntax-case (car kw) ()
@ -1765,31 +1762,31 @@
(l (gen-labels (list v))) (l (gen-labels (list v)))
(r** (extend-var-env l (list v) r*)) (r** (extend-var-env l (list v) r*))
(w** (make-binding-wrap (list #'id) l w*))) (w** (make-binding-wrap (list #'id) l w*)))
(expand-kw req opt rest (cdr kw) body (cons v vars) (parse-kw req opt rest (cdr kw) body (cons v vars)
r** w** aok r** w** aok
(cons (list (syntax->datum #'k) (cons (list (syntax->datum #'k)
(syntax->datum #'id) (syntax->datum #'id)
v) v)
out) out)
(cons (chi #'i r* w* mod) inits)))))) (cons (expand #'i r* w* mod) inits))))))
(else (else
(expand-body req opt rest (parse-body req opt rest
(if (or aok (pair? out)) (cons aok (reverse out)) #f) (if (or aok (pair? out)) (cons aok (reverse out)) #f)
body (reverse vars) r* w* (reverse inits) '())))) body (reverse vars) r* w* (reverse inits) '()))))
(define (expand-body req opt rest kw body vars r* w* inits meta) (define (parse-body req opt rest kw body vars r* w* inits meta)
(syntax-case body () (syntax-case body ()
((docstring e1 e2 ...) (string? (syntax->datum #'docstring)) ((docstring e1 e2 ...) (string? (syntax->datum #'docstring))
(expand-body req opt rest kw #'(e1 e2 ...) vars r* w* inits (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
(append meta (append meta
`((documentation `((documentation
. ,(syntax->datum #'docstring)))))) . ,(syntax->datum #'docstring))))))
((#((k . v) ...) e1 e2 ...) ((#((k . v) ...) e1 e2 ...)
(expand-body req opt rest kw #'(e1 e2 ...) vars r* w* inits (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
(append meta (syntax->datum #'((k . v) ...))))) (append meta (syntax->datum #'((k . v) ...)))))
((e1 e2 ...) ((e1 e2 ...)
(values meta req opt rest kw inits vars (values meta req opt rest kw inits vars
(chi-body #'(e1 e2 ...) (source-wrap e w s mod) (expand-body #'(e1 e2 ...) (source-wrap e w s mod)
r* w* mod))))) r* w* mod)))))
(syntax-case clauses () (syntax-case clauses ()
(() (values '() #f)) (() (values '() #f))
@ -1797,12 +1794,12 @@
(call-with-values (lambda () (get-formals #'args)) (call-with-values (lambda () (get-formals #'args))
(lambda (req opt rest kw) (lambda (req opt rest kw)
(call-with-values (lambda () (call-with-values (lambda ()
(expand-req req opt rest kw #'(e1 e2 ...))) (parse-req req opt rest kw #'(e1 e2 ...)))
(lambda (meta req opt rest kw inits vars body) (lambda (meta req opt rest kw inits vars body)
(call-with-values (call-with-values
(lambda () (lambda ()
(chi-lambda-case e r w s mod get-formals (expand-lambda-case e r w s mod get-formals
#'((args* e1* e2* ...) ...))) #'((args* e1* e2* ...) ...)))
(lambda (meta* else*) (lambda (meta* else*)
(values (values
(append meta meta*) (append meta meta*)
@ -1900,9 +1897,9 @@
(map (lambda (x) (map (lambda (x)
(make-binding (make-binding
'macro 'macro
(eval-local-transformer (chi x trans-r w mod) mod))) (eval-local-transformer (expand x trans-r w mod) mod)))
#'(val ...))))) #'(val ...)))))
(chi-body #'(e1 e2 ...) (expand-body #'(e1 e2 ...)
(source-wrap e w s mod) (source-wrap e w s mod)
(extend-env names bindings r) (extend-env names bindings r)
w w
@ -2094,7 +2091,7 @@
((#((k . v) ...) e1 e2 ...) ((#((k . v) ...) e1 e2 ...)
(lp #'(e1 e2 ...) (lp #'(e1 e2 ...)
(append meta (syntax->datum #'((k . v) ...))))) (append meta (syntax->datum #'((k . v) ...)))))
(_ (chi-simple-lambda e r w s mod req rest meta body))))))) (_ (expand-simple-lambda e r w s mod req rest meta body)))))))
(_ (syntax-violation 'lambda "bad lambda" e))))) (_ (syntax-violation 'lambda "bad lambda" e)))))
(global-extend 'core 'lambda* (global-extend 'core 'lambda*
@ -2103,8 +2100,8 @@
((_ args e1 e2 ...) ((_ args e1 e2 ...)
(call-with-values (call-with-values
(lambda () (lambda ()
(chi-lambda-case e r w s mod (expand-lambda-case e r w s mod
lambda*-formals #'((args e1 e2 ...)))) lambda*-formals #'((args e1 e2 ...))))
(lambda (meta lcase) (lambda (meta lcase)
(build-case-lambda s meta lcase)))) (build-case-lambda s meta lcase))))
(_ (syntax-violation 'lambda "bad lambda*" e))))) (_ (syntax-violation 'lambda "bad lambda*" e)))))
@ -2115,9 +2112,9 @@
((_ (args e1 e2 ...) (args* e1* e2* ...) ...) ((_ (args e1 e2 ...) (args* e1* e2* ...) ...)
(call-with-values (call-with-values
(lambda () (lambda ()
(chi-lambda-case e r w s mod (expand-lambda-case e r w s mod
lambda-formals lambda-formals
#'((args e1 e2 ...) (args* e1* e2* ...) ...))) #'((args e1 e2 ...) (args* e1* e2* ...) ...)))
(lambda (meta lcase) (lambda (meta lcase)
(build-case-lambda s meta lcase)))) (build-case-lambda s meta lcase))))
(_ (syntax-violation 'case-lambda "bad case-lambda" e))))) (_ (syntax-violation 'case-lambda "bad case-lambda" e)))))
@ -2128,16 +2125,16 @@
((_ (args e1 e2 ...) (args* e1* e2* ...) ...) ((_ (args e1 e2 ...) (args* e1* e2* ...) ...)
(call-with-values (call-with-values
(lambda () (lambda ()
(chi-lambda-case e r w s mod (expand-lambda-case e r w s mod
lambda*-formals lambda*-formals
#'((args e1 e2 ...) (args* e1* e2* ...) ...))) #'((args e1 e2 ...) (args* e1* e2* ...) ...)))
(lambda (meta lcase) (lambda (meta lcase)
(build-case-lambda s meta lcase)))) (build-case-lambda s meta lcase))))
(_ (syntax-violation 'case-lambda "bad case-lambda*" e))))) (_ (syntax-violation 'case-lambda "bad case-lambda*" e)))))
(global-extend 'core 'let (global-extend 'core 'let
(let () (let ()
(define (chi-let e r w s mod constructor ids vals exps) (define (expand-let e r w s mod constructor ids vals exps)
(if (not (valid-bound-ids? ids)) (if (not (valid-bound-ids? ids))
(syntax-violation 'let "duplicate bound variable" e) (syntax-violation 'let "duplicate bound variable" e)
(let ((labels (gen-labels ids)) (let ((labels (gen-labels ids))
@ -2147,25 +2144,25 @@
(constructor s (constructor s
(map syntax->datum ids) (map syntax->datum ids)
new-vars new-vars
(map (lambda (x) (chi x r w mod)) vals) (map (lambda (x) (expand x r w mod)) vals)
(chi-body exps (source-wrap e nw s mod) (expand-body exps (source-wrap e nw s mod)
nr nw mod)))))) nr nw mod))))))
(lambda (e r w s mod) (lambda (e r w s mod)
(syntax-case e () (syntax-case e ()
((_ ((id val) ...) e1 e2 ...) ((_ ((id val) ...) e1 e2 ...)
(and-map id? #'(id ...)) (and-map id? #'(id ...))
(chi-let e r w s mod (expand-let e r w s mod
build-let build-let
#'(id ...) #'(id ...)
#'(val ...) #'(val ...)
#'(e1 e2 ...))) #'(e1 e2 ...)))
((_ f ((id val) ...) e1 e2 ...) ((_ f ((id val) ...) e1 e2 ...)
(and (id? #'f) (and-map id? #'(id ...))) (and (id? #'f) (and-map id? #'(id ...)))
(chi-let e r w s mod (expand-let e r w s mod
build-named-let build-named-let
#'(f id ...) #'(f id ...)
#'(val ...) #'(val ...)
#'(e1 e2 ...))) #'(e1 e2 ...)))
(_ (syntax-violation 'let "bad let" (source-wrap e w s mod))))))) (_ (syntax-violation 'let "bad let" (source-wrap e w s mod)))))))
@ -2184,9 +2181,9 @@
(build-letrec s #f (build-letrec s #f
(map syntax->datum ids) (map syntax->datum ids)
new-vars new-vars
(map (lambda (x) (chi x r w mod)) #'(val ...)) (map (lambda (x) (expand x r w mod)) #'(val ...))
(chi-body #'(e1 e2 ...) (expand-body #'(e1 e2 ...)
(source-wrap e w s mod) r w mod))))))) (source-wrap e w s mod) r w mod)))))))
(_ (syntax-violation 'letrec "bad letrec" (source-wrap e w s mod)))))) (_ (syntax-violation 'letrec "bad letrec" (source-wrap e w s mod))))))
@ -2205,9 +2202,9 @@
(build-letrec s #t (build-letrec s #t
(map syntax->datum ids) (map syntax->datum ids)
new-vars new-vars
(map (lambda (x) (chi x r w mod)) #'(val ...)) (map (lambda (x) (expand x r w mod)) #'(val ...))
(chi-body #'(e1 e2 ...) (expand-body #'(e1 e2 ...)
(source-wrap e w s mod) r w mod))))))) (source-wrap e w s mod) r w mod)))))))
(_ (syntax-violation 'letrec* "bad letrec*" (source-wrap e w s mod)))))) (_ (syntax-violation 'letrec* "bad letrec*" (source-wrap e w s mod))))))
@ -2223,14 +2220,14 @@
(case type (case type
((lexical) ((lexical)
(build-lexical-assignment s (syntax->datum #'id) value (build-lexical-assignment s (syntax->datum #'id) value
(chi #'val r w mod))) (expand #'val r w mod)))
((global) ((global)
(build-global-assignment s value (chi #'val r w mod) id-mod)) (build-global-assignment s value (expand #'val r w mod) id-mod))
((macro) ((macro)
(if (procedure-property value 'variable-transformer) (if (procedure-property value 'variable-transformer)
;; As syntax-type does, call chi-macro with ;; As syntax-type does, call expand-macro with
;; the mod of the expression. Hmm. ;; the mod of the expression. Hmm.
(chi (chi-macro value e r w s #f mod) r empty-wrap mod) (expand (expand-macro value e r w s #f mod) r empty-wrap mod)
(syntax-violation 'set! "not a variable transformer" (syntax-violation 'set! "not a variable transformer"
(wrap e w mod) (wrap e w mod)
(wrap #'id w id-mod)))) (wrap #'id w id-mod))))
@ -2245,7 +2242,7 @@
(lambda (type value ee ww ss modmod) (lambda (type value ee ww ss modmod)
(case type (case type
((module-ref) ((module-ref)
(let ((val (chi #'val r w mod))) (let ((val (expand #'val r w mod)))
(call-with-values (lambda () (value #'(head tail ...) r w)) (call-with-values (lambda () (value #'(head tail ...) r w))
(lambda (e r w s* mod) (lambda (e r w s* mod)
(syntax-case e () (syntax-case e ()
@ -2254,8 +2251,8 @@
val mod))))))) val mod)))))))
(else (else
(build-call s (build-call s
(chi #'(setter head) r w mod) (expand #'(setter head) r w mod)
(map (lambda (e) (chi e r w mod)) (map (lambda (e) (expand e r w mod))
#'(tail ... val)))))))) #'(tail ... val))))))))
(_ (syntax-violation 'set! "bad set!" (source-wrap e w s mod)))))) (_ (syntax-violation 'set! "bad set!" (source-wrap e w s mod))))))
@ -2301,15 +2298,15 @@
((_ test then) ((_ test then)
(build-conditional (build-conditional
s s
(chi #'test r w mod) (expand #'test r w mod)
(chi #'then r w mod) (expand #'then r w mod)
(build-void no-source))) (build-void no-source)))
((_ test then else) ((_ test then else)
(build-conditional (build-conditional
s s
(chi #'test r w mod) (expand #'test r w mod)
(chi #'then r w mod) (expand #'then r w mod)
(chi #'else r w mod)))))) (expand #'else r w mod))))))
(global-extend 'core 'with-fluids (global-extend 'core 'with-fluids
(lambda (e r w s mod) (lambda (e r w s mod)
@ -2317,10 +2314,10 @@
((_ ((fluid val) ...) b b* ...) ((_ ((fluid val) ...) b b* ...)
(build-dynlet (build-dynlet
s s
(map (lambda (x) (chi x r w mod)) #'(fluid ...)) (map (lambda (x) (expand x r w mod)) #'(fluid ...))
(map (lambda (x) (chi x r w mod)) #'(val ...)) (map (lambda (x) (expand x r w mod)) #'(val ...))
(chi-body #'(b b* ...) (expand-body #'(b b* ...)
(source-wrap e w s mod) r w mod)))))) (source-wrap e w s mod) r w mod))))))
(global-extend 'begin 'begin '()) (global-extend 'begin 'begin '())
@ -2410,7 +2407,7 @@
no-source no-source
'apply 'apply
(list (build-simple-lambda no-source (map syntax->datum ids) #f new-vars '() (list (build-simple-lambda no-source (map syntax->datum ids) #f new-vars '()
(chi exp (expand exp
(extend-env (extend-env
labels labels
(map (lambda (var level) (map (lambda (var level)
@ -2467,14 +2464,14 @@
(and-map (lambda (x) (not (free-id=? #'pat x))) (and-map (lambda (x) (not (free-id=? #'pat x)))
(cons #'(... ...) keys))) (cons #'(... ...) keys)))
(if (free-id=? #'pad #'_) (if (free-id=? #'pad #'_)
(chi #'exp r empty-wrap mod) (expand #'exp r empty-wrap mod)
(let ((labels (list (gen-label))) (let ((labels (list (gen-label)))
(var (gen-var #'pat))) (var (gen-var #'pat)))
(build-call no-source (build-call no-source
(build-simple-lambda (build-simple-lambda
no-source (list (syntax->datum #'pat)) #f (list var) no-source (list (syntax->datum #'pat)) #f (list var)
'() '()
(chi #'exp (expand #'exp
(extend-env labels (extend-env labels
(list (make-binding 'syntax `(,var . 0))) (list (make-binding 'syntax `(,var . 0)))
r) r)
@ -2505,10 +2502,10 @@
#'(key ...) #'(m ...) #'(key ...) #'(m ...)
r r
mod)) mod))
(list (chi #'val r empty-wrap mod)))) (list (expand #'val r empty-wrap mod))))
(syntax-violation 'syntax-case "invalid literals list" e)))))))) (syntax-violation 'syntax-case "invalid literals list" e))))))))
;; The portable macroexpand seeds chi-top's mode m with 'e (for ;; The portable macroexpand seeds expand-top's mode m with 'e (for
;; evaluating) and esew (which stands for "eval syntax expanders ;; evaluating) and esew (which stands for "eval syntax expanders
;; when") with '(eval). In Chez Scheme, m is set to 'c instead of e ;; when") with '(eval). In Chez Scheme, m is set to 'c instead of e
;; if we are compiling a file, and esew is set to ;; if we are compiling a file, and esew is set to
@ -2519,8 +2516,8 @@
;; the object file if we are compiling a file. ;; the object file if we are compiling a file.
(set! macroexpand (set! macroexpand
(lambda* (x #:optional (m 'e) (esew '(eval))) (lambda* (x #:optional (m 'e) (esew '(eval)))
(chi-top-sequence (list x) null-env top-wrap #f m esew (expand-top-sequence (list x) null-env top-wrap #f m esew
(cons 'hygiene (module-name (current-module)))))) (cons 'hygiene (module-name (current-module))))))
(set! identifier? (set! identifier?
(lambda (x) (lambda (x)

View file

@ -66,9 +66,7 @@
;;; ;;;
(define block-growth-factor (define block-growth-factor
(let ((f (make-fluid))) (make-fluid 2))
(fluid-set! f 2)
f))
(define-syntax-rule (define-inline (name formals ...) body ...) (define-syntax-rule (define-inline (name formals ...) body ...)
;; Work around the lack of an inliner. ;; Work around the lack of an inliner.

View file

@ -1,6 +1,6 @@
;;; Guile Emacs Lisp ;;; Guile Emacs Lisp
;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. ;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
;;; ;;;
;;; This library is free software; you can redistribute it and/or ;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Lesser General Public ;;; modify it under the terms of the GNU Lesser General Public
@ -131,8 +131,8 @@
((_ name value) ((_ name value)
(with-syntax ((scheme-name (make-id #'name 'macro- #'name))) (with-syntax ((scheme-name (make-id #'name 'macro- #'name)))
#'(begin #'(begin
(define-public scheme-name (make-fluid)) (define-public scheme-name
(fluid-set! scheme-name (cons 'macro value)))))))) (make-fluid (cons 'macro value)))))))))
(define-syntax defspecial (define-syntax defspecial
(lambda (x) (lambda (x)
@ -140,10 +140,10 @@
((_ name args body ...) ((_ name args body ...)
(with-syntax ((scheme-name (make-id #'name 'compile- #'name))) (with-syntax ((scheme-name (make-id #'name 'compile- #'name)))
#'(begin #'(begin
(define scheme-name (make-fluid)) (define scheme-name
(fluid-set! scheme-name (make-fluid
(cons 'special-operator (cons 'special-operator
(lambda args body ...))))))))) (lambda args body ...))))))))))
;;; Call a guile-primitive that may be rebound for elisp and thus needs ;;; Call a guile-primitive that may be rebound for elisp and thus needs
;;; absolute addressing. ;;; absolute addressing.

View file

@ -30,6 +30,7 @@
(define-module (scripts compile) (define-module (scripts compile)
#:use-module ((system base compile) #:select (compile-file)) #:use-module ((system base compile) #:select (compile-file))
#:use-module (system base target)
#:use-module (system base message) #:use-module (system base message)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-13) #:use-module (srfi srfi-13)
@ -88,7 +89,12 @@
(lambda (opt name arg result) (lambda (opt name arg result)
(if (assoc-ref result 'to) (if (assoc-ref result 'to)
(fail "`--to' option cannot be specified more than once") (fail "`--to' option cannot be specified more than once")
(alist-cons 'to (string->symbol arg) result)))))) (alist-cons 'to (string->symbol arg) result))))
(option '(#\T "target") #t #f
(lambda (opt name arg result)
(if (assoc-ref result 'target)
(fail "`--target' option cannot be specified more than once")
(alist-cons 'target arg result))))))
(define (parse-args args) (define (parse-args args)
"Parse argument list @var{args} and return an alist with all the relevant "Parse argument list @var{args} and return an alist with all the relevant
@ -109,7 +115,7 @@ options."
(define (show-version) (define (show-version)
(format #t "compile (GNU Guile) ~A~%" (version)) (format #t "compile (GNU Guile) ~A~%" (version))
(format #t "Copyright (C) 2009 Free Software Foundation, Inc. (format #t "Copyright (C) 2009, 2011 Free Software Foundation, Inc.
License LGPLv3+: GNU LGPL version 3 or later <http://gnu.org/licenses/lgpl.html>. License LGPLv3+: GNU LGPL version 3 or later <http://gnu.org/licenses/lgpl.html>.
This is free software: you are free to change and redistribute it. This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.~%")) There is NO WARRANTY, to the extent permitted by law.~%"))
@ -134,6 +140,7 @@ There is NO WARRANTY, to the extent permitted by law.~%"))
o))) o)))
(from (or (assoc-ref options 'from) 'scheme)) (from (or (assoc-ref options 'from) 'scheme))
(to (or (assoc-ref options 'to) 'objcode)) (to (or (assoc-ref options 'to) 'objcode))
(target (or (assoc-ref options 'target) %host-type))
(input-files (assoc-ref options 'input-files)) (input-files (assoc-ref options 'input-files))
(output-file (assoc-ref options 'output-file)) (output-file (assoc-ref options 'output-file))
(load-path (assoc-ref options 'load-path))) (load-path (assoc-ref options 'load-path)))
@ -152,6 +159,7 @@ Compile each Guile source file FILE into a Guile object.
-f, --from=LANG specify a source language other than `scheme' -f, --from=LANG specify a source language other than `scheme'
-t, --to=LANG specify a target language other than `objcode' -t, --to=LANG specify a target language other than `objcode'
-T, --target=TRIPLET produce bytecode for host TRIPLET
Note that auto-compilation will be turned off. Note that auto-compilation will be turned off.
@ -171,11 +179,13 @@ Report bugs to <~A>.~%"
(for-each (lambda (file) (for-each (lambda (file)
(format #t "wrote `~A'\n" (format #t "wrote `~A'\n"
(with-fluids ((*current-warning-prefix* "")) (with-fluids ((*current-warning-prefix* ""))
(compile-file file (with-target target
#:output-file output-file (lambda ()
#:from from (compile-file file
#:to to #:output-file output-file
#:opts compile-opts)))) #:from from
#:to to
#:opts compile-opts))))))
input-files))) input-files)))
(define main compile) (define main compile)

View file

@ -57,37 +57,41 @@
(define get-conv-tag (lambda () 'get-conv)) ;; arbitrary unique (as per eq?) value (define get-conv-tag (lambda () 'get-conv)) ;; arbitrary unique (as per eq?) value
(define (make-parameter/helper val conv) (define (make-parameter/helper val conv)
(let ((value (make-fluid)) (let ((fluid (make-fluid (conv val))))
(conv conv)) (case-lambda
(begin (()
(fluid-set! value (conv val)) (fluid-ref fluid))
(lambda new-value ((new-value)
(cond (cond
((null? new-value) (fluid-ref value)) ((eq? new-value get-fluid-tag) fluid)
((eq? (car new-value) get-fluid-tag) value) ((eq? new-value get-conv-tag) conv)
((eq? (car new-value) get-conv-tag) conv) (else (fluid-set! fluid (conv new-value))))))))
((null? (cdr new-value)) (fluid-set! value (conv (car new-value))))
(else (error "make-parameter expects 0 or 1 arguments" new-value)))))))
(define-syntax-rule (parameterize ((?param ?value) ...) ?body ...) (define-syntax-rule (parameterize ((?param ?value) ...) ?body ...)
(with-parameters* (list ?param ...) (with-parameters* (list ?param ...)
(list ?value ...) (list ?value ...)
(lambda () ?body ...))) (lambda () ?body ...)))
(define (current-input-port . new-value) (define current-input-port
(if (null? new-value) (case-lambda
((@ (guile) current-input-port)) (()
(apply set-current-input-port new-value))) ((@ (guile) current-input-port)))
((new-value)
(set-current-input-port new-value))))
(define (current-output-port . new-value) (define current-output-port
(if (null? new-value) (case-lambda
((@ (guile) current-output-port)) (()
(apply set-current-output-port new-value))) ((@ (guile) current-output-port)))
((new-value)
(set-current-output-port new-value))))
(define (current-error-port . new-value) (define current-error-port
(if (null? new-value) (case-lambda
((@ (guile) current-error-port)) (()
(apply set-current-error-port new-value))) ((@ (guile) current-error-port)))
((new-value)
(set-current-error-port new-value))))
(define port-list (define port-list
(list current-input-port current-output-port current-error-port)) (list current-input-port current-output-port current-error-port))

View file

@ -111,7 +111,7 @@
;;; Current language ;;; Current language
;;; ;;;
(define *current-language* (make-fluid)) (define *current-language* (make-fluid 'scheme))
(define (current-language) (define (current-language)
(or (fluid-ref *current-language*) 'scheme)) (fluid-ref *current-language*))

View file

@ -56,15 +56,13 @@
(define *current-warning-port* (define *current-warning-port*
;; The port where warnings are sent. ;; The port where warnings are sent.
(make-fluid)) (make-fluid (current-error-port)))
(fluid-set! *current-warning-port* (current-error-port)) (fluid-set! *current-warning-port* (current-error-port))
(define *current-warning-prefix* (define *current-warning-prefix*
;; Prefix string when emitting a warning. ;; Prefix string when emitting a warning.
(make-fluid)) (make-fluid ";;; "))
(fluid-set! *current-warning-prefix* ";;; ")
(define-record-type <warning-type> (define-record-type <warning-type>

View file

@ -21,6 +21,7 @@
(define-module (system base target) (define-module (system base target)
#:use-module (rnrs bytevectors) #:use-module (rnrs bytevectors)
#:use-module (ice-9 regex)
#:export (target-type with-target #:export (target-type with-target
target-cpu target-vendor target-os target-cpu target-vendor target-os
@ -33,44 +34,90 @@
;;; Target types ;;; Target types
;;; ;;;
(define %target-type (make-fluid)) (define %native-word-size
;; The native word size. Note: don't use `word-size' from
;; (system vm objcode) to avoid a circular dependency.
((@ (system foreign) sizeof) '*))
(define (target-type) (define %target-type (make-fluid %host-type))
(or (fluid-ref %target-type) (define %target-endianness (make-fluid (native-endianness)))
%host-type)) (define %target-word-size (make-fluid %native-word-size))
(define (validate-target target) (define (validate-target target)
(if (or (not (string? target)) (if (or (not (string? target))
(let ((parts (string-split target #\-))) (let ((parts (string-split target #\-)))
(or (< 3 (length parts)) (or (< (length parts) 3)
(or-map string-null? parts)))) (or-map string-null? parts))))
(error "invalid target" target))) (error "invalid target" target)))
(define (with-target target thunk) (define (with-target target thunk)
(validate-target target) (validate-target target)
(with-fluids ((%target-type target)) (let ((cpu (triplet-cpu target)))
(thunk))) (with-fluids ((%target-type target)
(%target-endianness (cpu-endianness cpu))
(%target-word-size (cpu-word-size cpu)))
(thunk))))
(define (target-cpu) (define (cpu-endianness cpu)
(let ((t (target-type))) "Return the endianness for CPU."
(substring t 0 (string-index t #\-)))) (if (string=? cpu (triplet-cpu %host-type))
(native-endianness)
(cond ((string-match "^i[0-9]86$" cpu)
(endianness little))
((member cpu '("x86_64" "ia64"
"powerpcle" "powerpc64le" "mipsel" "mips64el"))
(endianness little))
((member cpu '("sparc" "sparc64" "powerpc" "powerpc64" "spu"
"mips" "mips64"))
(endianness big))
((string-match "^arm.*el" cpu)
(endianness little))
(else
(error "unknown CPU endianness" cpu)))))
(define (target-vendor) (define (cpu-word-size cpu)
(let* ((t (target-type)) "Return the word size for CPU."
(start (1+ (string-index t #\-)))) (if (string=? cpu (triplet-cpu %host-type))
%native-word-size
(cond ((string-match "^i[0-9]86$" cpu) 4)
((string-match "64$" cpu) 8)
((string-match "64[lbe][lbe]$" cpu) 8)
((member cpu '("sparc" "powerpc" "mips")) 4)
((string-match "^arm.*" cpu) 4)
(else "unknown CPU word size" cpu))))
(define (triplet-cpu t)
(substring t 0 (string-index t #\-)))
(define (triplet-vendor t)
(let ((start (1+ (string-index t #\-))))
(substring t start (string-index t #\- start)))) (substring t start (string-index t #\- start))))
(define (target-os) (define (triplet-os t)
(let* ((t (target-type)) (let ((start (1+ (string-index t #\- (1+ (string-index t #\-))))))
(start (1+ (string-index t #\- (1+ (string-index t #\-))))))
(substring t start))) (substring t start)))
(define (target-type)
"Return the GNU configuration triplet of the target platform."
(fluid-ref %target-type))
(define (target-cpu)
"Return the CPU name of the target platform."
(triplet-cpu (target-type)))
(define (target-vendor)
"Return the vendor name of the target platform."
(triplet-vendor (target-type)))
(define (target-os)
"Return the operating system name of the target platform."
(triplet-os (target-type)))
(define (target-endianness) (define (target-endianness)
(if (equal? (target-type) %host-type) "Return the endianness object of the target platform."
(native-endianness) (fluid-ref %target-endianness))
(error "cross-compilation not yet handled" %host-type (target-type))))
(define (target-word-size) (define (target-word-size)
(if (equal? (target-type) %host-type) "Return the word size, in bytes, of the target platform."
((@ (system foreign) sizeof) '*) (fluid-ref %target-word-size))
(error "cross-compilation not yet handled" %host-type (target-type))))

View file

@ -134,7 +134,9 @@ See <http://www.gnu.org/licenses/lgpl.html>, for more details.")
(define %make-repl make-repl) (define %make-repl make-repl)
(define* (make-repl lang #:optional debug) (define* (make-repl lang #:optional debug)
(%make-repl #:language (lookup-language lang) (%make-repl #:language (if (language? lang)
lang
(lookup-language lang))
#:options (copy-tree repl-default-options) #:options (copy-tree repl-default-options)
#:tm-stats (times) #:tm-stats (times)
#:gc-stats (gc-stats) #:gc-stats (gc-stats)

View file

@ -1,6 +1,6 @@
;;;; (texinfo plain-text) -- rendering stexinfo as plain text ;;;; (texinfo plain-text) -- rendering stexinfo as plain text
;;;; ;;;;
;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. ;;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
;;;; Copyright (C) 2003,2004,2009 Andy Wingo <wingo at pobox dot com> ;;;; Copyright (C) 2003,2004,2009 Andy Wingo <wingo at pobox dot com>
;;;; ;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
@ -41,9 +41,6 @@
(or (arg-ref key %-args) (or (arg-ref key %-args)
(error "Missing argument:" key %-args))) (error "Missing argument:" key %-args)))
(define *indent* (make-fluid))
(define *itemizer* (make-fluid))
(define (make-ticker str) (define (make-ticker str)
(lambda () str)) (lambda () str))
(define (make-enumerator n) (define (make-enumerator n)
@ -52,9 +49,8 @@
(set! n (1+ n)) (set! n (1+ n))
(format #f "~A. " last)))) (format #f "~A. " last))))
(fluid-set! *indent* "") (define *indent* (make-fluid ""))
;; Shouldn't be necessary to do this, but just in case. (define *itemizer* (make-fluid (make-ticker "* ")))
(fluid-set! *itemizer* (make-ticker "* "))
(define-macro (with-indent n . body) (define-macro (with-indent n . body)
`(with-fluids ((*indent* (string-append (fluid-ref *indent*) `(with-fluids ((*indent* (string-append (fluid-ref *indent*)

View file

@ -470,7 +470,7 @@ ordered alist."
val) val)
(define (default-val-validator k val) (define (default-val-validator k val)
(string? val)) (or (not val) (string? val)))
(define (default-val-writer k val port) (define (default-val-writer k val port)
(if (or (string-index val #\;) (if (or (string-index val #\;)
@ -518,9 +518,9 @@ ordered alist."
((pair? elt) ((pair? elt)
(let ((k (car elt)) (let ((k (car elt))
(v (cdr elt))) (v (cdr elt)))
(and (or (string? k) (symbol? k)) (and (symbol? k)
(valid? k v)))) (valid? k v))))
((or (string? elt) (symbol? elt)) ((symbol? elt)
(valid? elt #f)) (valid? elt #f))
(else #f))))) (else #f)))))
@ -611,7 +611,7 @@ ordered alist."
(valid? default-val-validator)) (valid? default-val-validator))
(list-of? list (list-of? list
(lambda (elt) (lambda (elt)
(key-value-list? list valid?)))) (key-value-list? elt valid?))))
(define* (write-param-list list port #:optional (define* (write-param-list list port #:optional
(val-writer default-val-writer)) (val-writer default-val-writer))
@ -871,7 +871,10 @@ ordered alist."
(cons scheme (parse-key-value-list str default-val-parser delim end))))))) (cons scheme (parse-key-value-list str default-val-parser delim end)))))))
(define (validate-credentials val) (define (validate-credentials val)
(and (pair? val) (symbol? (car val)) (key-value-list? (cdr val)))) (and (pair? val) (symbol? (car val))
(case (car val)
((basic) (string? (cdr val)))
(else (key-value-list? (cdr val))))))
(define (write-credentials val port) (define (write-credentials val port)
(display (car val) port) (display (car val) port)
@ -1137,7 +1140,7 @@ phrase\"."
(lambda (str) (lambda (str)
(map string->symbol (split-and-trim str))) (map string->symbol (split-and-trim str)))
(lambda (v) (lambda (v)
(list-of? symbol? v)) (list-of? v symbol?))
(lambda (v port) (lambda (v port)
(write-list v port display ", ")))) (write-list v port display ", "))))
@ -1242,7 +1245,14 @@ phrase\"."
((private no-cache) ((private no-cache)
(and v-str (split-header-names v-str))) (and v-str (split-header-names v-str)))
(else v-str))) (else v-str)))
default-val-validator (lambda (k v)
(case k
((max-age max-stale min-fresh s-maxage)
(non-negative-integer? v))
((private no-cache)
(or (not v) (list-of-header-names? v)))
(else
(not v))))
(lambda (k v port) (lambda (k v port)
(cond (cond
((string? v) (display v port)) ((string? v) (display v port))
@ -1522,7 +1532,7 @@ phrase\"."
(lambda (k v) (lambda (k v)
(if (eq? k 'q) (if (eq? k 'q)
(valid-quality? v) (valid-quality? v)
(string? v))) (or (not v) (string? v))))
(lambda (k v port) (lambda (k v port)
(if (eq? k 'q) (if (eq? k 'q)
(write-quality v port) (write-quality v port)

View file

@ -425,8 +425,7 @@
(append (current-test-prefix) (list name))) (append (current-test-prefix) (list name)))
;;; A fluid containing the current test prefix, as a list. ;;; A fluid containing the current test prefix, as a list.
(define prefix-fluid (make-fluid)) (define prefix-fluid (make-fluid '()))
(fluid-set! prefix-fluid '())
(define (current-test-prefix) (define (current-test-prefix)
(fluid-ref prefix-fluid)) (fluid-ref prefix-fluid))

View file

@ -1,15 +1,17 @@
;;;; Assembly to bytecode compilation -*- mode: scheme; coding: utf-8; -*- ;;;; Assembly to bytecode compilation -*- mode: scheme; coding: utf-8; -*-
;;;; ;;;;
;;;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either ;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version. ;;;; version 3 of the License, or (at your option) any later version.
;;;; ;;;;
;;;; This library is distributed in the hope that it will be useful, ;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details. ;;;; Lesser General Public License for more details.
;;;; ;;;;
;;;; You should have received a copy of the GNU Lesser General Public ;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software ;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
@ -19,6 +21,8 @@
#:use-module ((rnrs io ports) #:select (open-bytevector-output-port)) #:use-module ((rnrs io ports) #:select (open-bytevector-output-port))
#:use-module (test-suite lib) #:use-module (test-suite lib)
#:use-module (system vm instruction) #:use-module (system vm instruction)
#:use-module (system vm objcode)
#:use-module (system base target)
#:use-module (language assembly) #:use-module (language assembly)
#:use-module (language assembly compile-bytecode)) #:use-module (language assembly compile-bytecode))
@ -114,3 +118,80 @@
(uint32 0) ;; metalen (uint32 0) ;; metalen
make-int8 3 make-int8 3
return)))) return))))
(define (test-triplet cpu vendor os)
(let ((triplet (string-append cpu "-" vendor "-" os)))
(pass-if (format #f "triplet ~a" triplet)
(with-target triplet
(lambda ()
(and (string=? (target-cpu) cpu)
(string=? (target-vendor) vendor)
(string=? (target-os) os)))))))
(define %objcode-cookie-size
(string-length "GOOF----LE-8-2.0"))
(define (test-target triplet endian word-size)
(pass-if (format #f "target `~a' honored" triplet)
(call-with-values (lambda ()
(open-bytevector-output-port))
(lambda (p get-objcode)
(with-target triplet
(lambda ()
(let ((b (compile-bytecode
'(load-program () 16 #f
(assert-nargs-ee/locals 1)
(make-int8 77)
(toplevel-ref 1)
(local-ref 0)
(mul)
(add)
(return)
(nop) (nop) (nop)
(nop) (nop))
#f)))
(write-objcode (bytecode->objcode b) p)
(let ((cookie (make-bytevector %objcode-cookie-size))
(expected (format #f "GOOF----~a-~a-~a"
(cond ((eq? endian (endianness little))
"LE")
((eq? endian (endianness big))
"BE")
(else
(error "unknown endianness"
endian)))
word-size
(effective-version))))
(bytevector-copy! (get-objcode) 0 cookie 0
%objcode-cookie-size)
(string=? (utf8->string cookie) expected)))))))))
(with-test-prefix "cross-compilation"
(test-triplet "i586" "pc" "gnu0.3")
(test-triplet "x86_64" "unknown" "linux-gnu")
(test-triplet "x86_64" "unknown" "kfreebsd-gnu")
(test-target "i586-pc-gnu0.3" (endianness little) 4)
(test-target "x86_64-pc-linux-gnu" (endianness little) 8)
(test-target "powerpc-unknown-linux-gnu" (endianness big) 4)
(test-target "sparc64-unknown-freebsd8.2" (endianness big) 8)
(pass-if-exception "unknown target"
exception:miscellaneous-error
(call-with-values (lambda ()
(open-bytevector-output-port))
(lambda (p get-objcode)
(let* ((b (compile-bytecode '(load-program () 3 #f
(make-int8 77)
(return))
#f))
(o (bytecode->objcode b)))
(with-target "fcpu-unknown-gnu1.0"
(lambda ()
(write-objcode o p))))))))
;; Local Variables:
;; eval: (put 'with-target 'scheme-indent-function 1)
;; End:

View file

@ -1,6 +1,6 @@
;;;; bytevectors.test --- R6RS bytevectors. -*- mode: scheme; coding: utf-8; -*- ;;;; bytevectors.test --- R6RS bytevectors. -*- mode: scheme; coding: utf-8; -*-
;;;; ;;;;
;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. ;;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
;;;; Ludovic Courtès ;;;; Ludovic Courtès
;;;; ;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
@ -42,7 +42,14 @@
(and (bytevector=? (make-bytevector 20 7) (and (bytevector=? (make-bytevector 20 7)
(make-bytevector 20 7)) (make-bytevector 20 7))
(not (bytevector=? (make-bytevector 20 7) (not (bytevector=? (make-bytevector 20 7)
(make-bytevector 20 0)))))) (make-bytevector 20 0)))))
(pass-if "bytevector-copy! overlapping"
;; See <http://debbugs.gnu.org/10070>.
(let ((b (u8-list->bytevector '(1 2 3 4 5 6 7 8))))
(bytevector-copy! b 0 b 3 4)
(bytevector->u8-list b)
(bytevector=? b #vu8(1 2 3 1 2 3 4 8)))))
(with-test-prefix/c&e "2.3 Operations on Bytes and Octets" (with-test-prefix/c&e "2.3 Operations on Bytes and Octets"

View file

@ -231,10 +231,10 @@
(with-test-prefix "define set procedure-name" (with-test-prefix "define set procedure-name"
(expect-fail "closure" (pass-if "closure"
(eq? 'foo-closure (procedure-name bar-closure))) (eq? 'foo-closure (procedure-name bar-closure)))
(expect-fail "procedure-with-setter" (expect-fail "procedure-with-setter" ; FIXME: `pass-if' when it's supported
(eq? 'foo-pws (procedure-name bar-pws)))) (eq? 'foo-pws (procedure-name bar-pws))))
;;; ;;;
@ -330,78 +330,49 @@
0)) 0))
(with-test-prefix "stacks" (with-test-prefix "stacks"
(with-debugging-evaluator (pass-if "stack involving a primitive"
;; The primitive involving the error must appear exactly once on the
;; stack.
(catch 'result
(lambda ()
(start-stack 'foo
(with-throw-handler '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)
(eq? (frame-procedure frame)
hashq-ref))
frames)))))))
(lambda (key result)
(= 1 result))))
(pass-if "stack involving a subr" (pass-if "arguments of a primitive stack frame"
;; The subr involving the error must appear exactly once on the stack. ;; Create a stack with two primitive frames and make sure the
(catch 'result ;; arguments are correct.
(lambda () (catch 'result
(throw 'unresolved) (lambda ()
(start-stack 'foo (start-stack 'foo
(lazy-catch 'wrong-type-arg (with-throw-handler 'wrong-type-arg
(lambda () (lambda ()
;; Trigger a `wrong-type-arg' exception. ;; Trigger a `wrong-type-arg' exception.
(fluid-ref 'not-a-fluid)) (substring 'wrong 'type 'arg))
(lambda _ (lambda _
(let* ((stack (make-stack #t)) (let* ((stack (make-stack #t))
(frames (stack->frames stack))) (frames (stack->frames stack)))
(throw 'result (throw 'result
(count (lambda (frame) (map (lambda (frame)
(and (frame-procedure? frame) (cons (frame-procedure frame)
(eq? (frame-procedure frame) (frame-arguments frame)))
fluid-ref))) frames)))))))
frames))))))) (lambda (key result)
(lambda (key result) (and (equal? (car result) `(,make-stack #t))
(= 1 result)))) (pair? (member `(,substring wrong type arg)
(cdr 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 ()
(throw 'unresolved)
(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))))
(pass-if "arguments of a gsubr stack frame"
;; Create a stack with two gsubr frames and make sure the arguments are
;; correct.
(catch 'result
(lambda ()
(throw 'unresolved)
(start-stack 'foo
(lazy-catch 'wrong-type-arg
(lambda ()
;; Trigger a `wrong-type-arg' exception.
(substring 'wrong 'type 'arg))
(lambda _
(let* ((stack (make-stack #t))
(frames (stack->frames stack)))
(throw 'result
(map (lambda (frame)
(cons (frame-procedure frame)
(frame-arguments frame)))
frames)))))))
(lambda (key result)
(and (equal? (car result) `(,make-stack #t))
(pair? (member `(,substring wrong type arg)
(cdr result)))))))))
;;; ;;;
;;; letrec init evaluation ;;; letrec init evaluation

View file

@ -254,6 +254,16 @@
(map proc* arg1 arg2 arg3))) (map proc* arg1 arg2 arg3)))
(throw 'unresolved))) (throw 'unresolved)))
(pass-if "procedures returning a pointer"
(if (defined? 'procedure->pointer)
(let* ((called? #f)
(proc (lambda (i) (set! called? #t) (make-pointer i)))
(pointer (procedure->pointer '* proc (list int)))
(proc* (pointer->procedure '* pointer (list int)))
(result (proc* 777)))
(and called? (equal? result (make-pointer 777))))
(throw 'unresolved)))
(pass-if "procedures returning void" (pass-if "procedures returning void"
(if (defined? 'procedure->pointer) (if (defined? 'procedure->pointer)
(let* ((called? #f) (let* ((called? #f)
@ -262,6 +272,22 @@
(proc* (pointer->procedure void pointer '()))) (proc* (pointer->procedure void pointer '())))
(proc*) (proc*)
called?) called?)
(throw 'unresolved)))
(pass-if "procedure is retained"
;; The lambda passed to `procedure->pointer' must remain live.
(if (defined? 'procedure->pointer)
(let* ((ptr (procedure->pointer int
(lambda (x) (+ x 7))
(list int)))
(procs (unfold (cut >= <> 10000)
(lambda (i)
(pointer->procedure int ptr (list int)))
1+
0)))
(gc) (gc) (gc)
(every (cut = <> 9)
(map (lambda (f) (f 2)) procs)))
(throw 'unresolved)))) (throw 'unresolved))))

View file

@ -1,7 +1,7 @@
;;;; procprop.test --- Procedure properties -*- mode: scheme; coding: utf-8; -*- ;;;; procprop.test --- Procedure properties -*- mode: scheme; coding: utf-8; -*-
;;;; Ludovic Courtès <ludo@gnu.org> ;;;; Ludovic Courtès <ludo@gnu.org>
;;;; ;;;;
;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. ;;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
;;;; ;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
@ -26,7 +26,12 @@
(eq? 'display (procedure-name display))) (eq? 'display (procedure-name display)))
(pass-if "gsubr" (pass-if "gsubr"
(eq? 'hashq-ref (procedure-name hashq-ref)))) (eq? 'hashq-ref (procedure-name hashq-ref)))
(pass-if "from eval"
(eq? 'foobar (procedure-name
(eval '(begin (define (foobar) #t) foobar)
(current-module))))))
(with-test-prefix "procedure-arity" (with-test-prefix "procedure-arity"
@ -52,4 +57,19 @@
(pass-if "list" (pass-if "list"
(equal? (procedure-minimum-arity list) (equal? (procedure-minimum-arity list)
'(0 0 #t)))) '(0 0 #t)))
(pass-if "fixed, eval"
(equal? (procedure-minimum-arity (eval '(lambda (a b) #t)
(current-module)))
'(2 0 #f)))
(pass-if "rest, eval"
(equal? (procedure-minimum-arity (eval '(lambda (a b . c) #t)
(current-module)))
'(2 0 #t)))
(pass-if "opt, eval"
(equal? (procedure-minimum-arity (eval '(lambda* (a b #:optional c) #t)
(current-module)))
'(2 1 #f))))

View file

@ -41,8 +41,9 @@
(syntax-rules () (syntax-rules ()
((_ sym str val) ((_ sym str val)
(pass-if (format #f "~a: ~s -> ~s" 'sym str val) (pass-if (format #f "~a: ~s -> ~s" 'sym str val)
(equal? (parse-header 'sym str) (and (equal? (parse-header 'sym str)
val))))) val)
(valid-header? 'sym val))))))
(define-syntax pass-if-any-error (define-syntax pass-if-any-error
(syntax-rules () (syntax-rules ()