* doc/ref/api-debug.texi:
* doc/ref/vm.texi: Fix some cross-references.
* doc/ref/compiler.texi: Hack some more, finishing the section on the
compiler tower.
* doc/ref/api-procedures.texi (Compiled Procedures): Stub out these docs
some more, taking some commented-out docs from vm.texi.
* doc/ref/vm.texi: Move docs ^.
* doc/ref/api-evaluation.texi: Add documentation for the standard
compilation interface, and some notes about compiled files.
* doc/ref/api-procedures.texi (Compiled Procedures): A stub at
documenting compiled procedures.
* doc/ref/compiler.texi (Compiling to the Virtual Machine): Flesh out
with some structure, though much of the text remains to be written.
This stuff is hard to write!
* libguile/vm-engine.h (PUSH_LIST): Add a parameter to check that the
list was proper.
* libguile/vm-i-system.c: Adapt PUSH_LIST callsites to pass SCM_NULLP or
SCM_NULL_OR_NIL_P, as appropriate. Add a check to return/values*.
* libguile/vm.c: Add lang.h header for SCM_NULL_OR_NIL_P.
* test-suite/tests/elisp.test: Fix XFAIL for elisp + apply.
* doc/ref/vm.texi (Stack Layout): Update to remove references to the
"heap link".
* gdbinit: Update for "heap link" removal.
* libguile/frames.c:
* libguile/frames.h: Update macros and diagram for removal of "heap
link". As part of this, we also remove "heap frames", replacing them
with "vm frames", which are much like the interpreter's debug objects,
but for VM stacks. That is to say, they don't actually hold the stack
themselves, just the pointers into stack that's held by a continuation
(either captured or current).
* libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is
really a copy of information that comes from somewhere else, it makes
sense to copy over info from the VM, just as `make-stack' does from the
evaluator. The tricky bit is to figure out how to interleave VM and
interpreter frames. We do that by starting in the interpreter, and
whenever the current frame's procedure is actually a program, we switch
to the VM stack, switching back when we reach a "bootstrap frame". The
last bit is hacky, but it does work...
(is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a
bootstrap frame.
(scm_make_stack): Accept a VM frame in addition to debug frames.
Probably has some bugs in this case. But in the case that the arg is
#t (a common case), do the right thing, capturing the top VM frame as
well, and interleaving those frames appropriately on the stack.
As an accident, we lost the ability to limit the number of frames in
the backtrace. We could add that back, but personally I always want
*all* frames in the trace... Narrowing still works fine, though there
are some hiccups sometimes -- e.g. an outer cut to a procedure that
does a tail-call in VM code will never find the cut, as it no longer
exists in the continuation.
* libguile/vm.h (struct scm_vm): So! Now that we have switched to save
stacks in the normal make-stack, there's no more need for `this_frame'
or `last_frame'. On the other hand, we can take this opportunity to fix
tracing: when we're in a trace hook, we set `trace_frame' on the VM,
so we know not to fire hooks when we're already in a hook.
(struct scm_vm_cont): Expose this, as make-stack needs it to make VM
frames from VM continuations.
* libguile/vm.c (scm_vm_trace_frame): New function, gets the current
trace frame.
(vm_mark, make_vm): Hook up the trace frame.
(vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the
right thing if the hook exits nonlocally.
* libguile/vm-engine.c (vm_run): No more this_frame in the wind data.
* libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher.
(ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code.
(NEW_FRAME): Adapt for no HL in the frame.
* libguile/vm-i-system.c (goto/args, mv-call, return, return/values):
Adapt for no HL in the frame.
* module/system/vm/frame.scm:
* module/system/vm/vm.scm: Beginnings of some reworkings, needs more
thought.
* module/ice-9/boot-9.scm (default-pre-unwind-handler): Rename from
default-lazy-handler.
(pre-unwind-handler-dispatch): Rename from lazy-hadler-dispatch.
(error-catching-loop): Adjust caller.
* module/system/repl/repl.scm (default-pre-unwind-handler): Remove this
definition, in favor of the default one in boot-9.
(default-catch-handler): Don't do a vm-backtrace, as we will soon be
relying on core machinery to do that for us.
(call-with-backtrace): Start a new stack for the thunk.
(with-backtrace): Macro version of call-with-backtrace.
(start-repl): Use with-backtrace for brevity. Start a stack with #t as
the tag instead of repl-eval, because all traces of repl-eval are gone
after it does a tail-call.
* module/ice-9/debugger.scm:
* module/ice-9/debugging/traps.scm:
* module/ice-9/stack-catch.scm: Adapt to s/lazy/pre-unwind/ in
boot-9.scm.
* libguile/backtrace.c (display_backtrace_get_file_line): If the source
is a vector, treat it as a #(line column file) vector, as emitted by
the VM. Needs subsequent patches to make sense.
* doc/ref/vm.texi: Flesh out the VM documentation, adding a rationale.
* doc/ref/history.texi: Write the Guile history.
* doc/ref/guile.texi (Top): Some tweaks.
* doc/ref/compiler.texi: A new empty section on the compiler.
* doc/ref/data-rep.texi: Made to be a section of a chapter instead of an
appendix. The beginnings of some revision, but not there yet.
* doc/ref/guile.texi: Put the "Data Representation" essay into the new
"History and Implementation Details" chapter.
* doc/ref/history.texi: New empty section on Guile history.
* doc/ref/libguile-concepts.texi:
* doc/ref/libguile-smobs.texi: Fix up some xrefs.
* doc/ref/vm.texi: New section documenting the VM. Not done yet.
* module/system/base/language.scm (<language>): Rework so that instead of
hardcoding passes in the language, we define compilers that translate
from one language to another. Add `parser' to the language fields, a
bit of a hack but useful for languages with s-expression external
representations but with record internal representations.
(define-language, *compilation-cache*, invalidate-compilation-cache!)
(compute-compilation-order, lookup-compilation-order): Add an algorithm
that does a depth-first search for a translation path from a source
language to a target language, caching the result in a lookup table.
* module/language/scheme/spec.scm:
* module/language/ghil/spec.scm: Update to the new language format.
* module/language/glil/spec.scm: Add a language specification for GLIL,
with a compiler to objcode. Also there are parsers and printers, for
repl usage, but for some reason this doesn't work yet.
* module/language/objcode/spec.scm: Define a language specification for
object code. There is some sleight of hand here, in the "compiler" to
values; but there is method behind the madness, because this way we
higher levels can pass environments (a module + externals pair) to
objcode->program.
* module/language/value/spec.scm: Define a language specification for
values. There is something intellectually dishonest about this, but it
does serve its purpose as a foundation for the language hierarchy.
* configure.in:
* module/language/Makefile.am
* module/language/ghil/Makefile.am
* module/language/glil/Makefile.am
* module/language/objcode/Makefile.am
* module/language/value/Makefile.am:
Autotomfoolery for the ghil, glil, objcode, and value languages.
* module/language/scheme/translate.scm (translate): Import the bits that
understand `compile-time-environment' here, and pass on the relevant
portions of the environment to the next compiler pass.
* module/system/base/compile.scm (current-language): New procedure, refs
the current language fluid, or lazily sets it to scheme.
(call-once, call-with-output-file/atomic): Refactor these bits to use
with-throw-handler. No functional change.
(compile-file, compile-and-load, compile-passes, compile-fold)
(compile): Refactor the public interface of the compiler to be generic
and simple. Uses `lookup-compilation-order' to find a path from the
source language to the target language.
* module/system/base/syntax.scm (define-type): Adapt to changes in
define-record.
(define-record): Instead of expecting all slots in the first form,
expect them in the body, and let the first form hold the options.
* module/system/il/compile.scm (compile): Adapt to the compilation pass
API (three in and two out).
* module/system/il/ghil.scm (<ghil-var>, <ghil-env>)
(<ghil-toplevel-env>): Adapt to define-record changes.
* module/system/il/glil.scm (<glil-vars>): Adapt to define-record
changes.
(<glil>, print-glil): Add a GLIL record printer that uses unparse.
(parse-glil, unparse-glil): Update unparse (formerly known as pprint),
and write a parse function.
* module/system/repl/common.scm (<repl>): Adapt to define-record changes.
(repl-parse): New function, parses the read form using the current
language. Something of a hack.
(repl-compile): Adapt to changes in `compile'.
(repl-eval): Fix up the does-the-language-have-a-compiler check for
changes in <language>.
* module/system/repl/repl.scm (start-repl): Parse the form before eval.
* module/system/repl/command.scm (describe): Parse.
(compile): Be more generic.
(compile-file): Adapt to changes in compile-file.
(disassemble, time, profile, trace): Parse.
* module/system/vm/debug.scm:
* module/system/vm/assemble.scm: Adapt to define-record changes.
* module/language/scheme/translate.scm (receive): Fix an important bug
that gave `receive' letrec semantics instead of let semantics. Whoops!
* module/system/il/ghil.scm (parse-ghil): Fix a typo for values*
(unparse-ghil): Only output (quote foo) if the object is a symbol.
(unparse-ghil): Fix some missing ,@.
* libguile/eval.c (scm_debug_opts): Whereas, today's machines are larger
than yesterday's; GCC consumes more words per stack frame than it used
to; and you can get quite some recursion in a halfway-compiled system,
be it resolved: let's bump up the C stack limit to 40k words (160 kB /
320 kB, depending on word size).
* module/system/repl/common.scm (repl-print): Slightly refine the meaning
of "language-printer": a language printer prints an expression of a
language, not the result of evaluation. `write' prints values.
* module/language/ghil/spec.scm (ghil): Define a language printer, and a
translator for turning s-expressions (not scheme, mind you) into GHIL.
* module/language/scheme/translate.scm (quote, quasiquote): Add some
#:keyword action, so that we can (quote #:keywords).
* module/system/base/language.scm (<language>):
* module/system/base/compile.scm (read-file-in): Don't require that a
language have a read-file; instead error when read-file is called.
(compile-passes, compile-in): Refactor to call a helper method to turn
the language + set of options into a set of compiler passes.
* module/system/base/syntax.scm (define-type): Allow the type to be a
list, with the car being the name and the cdr being keyword options.
Interpret #:printer as a printer, and pass it down to...
(define-record): Here.
* module/system/il/ghil.scm (print-ghil, <ghil>): New printer for GHIL,
yay!
(parse-ghil, unparse-ghil): New lovely functions. Will document them in
the manual.
* module/system/vm/disasm.scm (disassemble-program): Don't print the
nargs= nrest= etc line, it's redundant.
* module/system/vm/program.scm (program-bindings-as-lambda-list): If the
program bindings is null, then that's that.
* module/srfi/srfi-69.scm: Move the macros up before the functions that
use them, so that the compiler can do its job.
(hash-table-walk): While it is true about what I said about R5RS
before, it seems that for R6 this will have to change. Anyway. In the
meantime, since the test suite checks that hash-table-walk procedures'
return values and number of return values are ignored, call that
procedure within a call-with-values.
* libguile/vm-i-system.c (return/values): In the
multiple-values-to-a-single-value-continuation (or MV but where N=1),
null out the correct number of values from the stack. Fixes aborts on
(apply values '(1)).
* testsuite/t-values.scm (call-with-values): Add a test.
* libguile/vm-i-system.c (call, goto/args): Handle the case in which a
non-program (i.e. interpreted program or a subr) returns multiple
values.
* testsuite/t-values.scm: Add test case that exhibited this problem.
* libguile/procs.c (scm_make_procedure_with_setter): Patch through the
getter's procedure name to the procedure-with-setter. Fixes part of the
srfi-17 test, as the VM doesn't set procedure-name on define -- but
perhaps that is the bug that should be fixed. In any case this patching
is cheap.
* test-suite/tests/eval.test: Change so that (define name pws) is
initially passed an anonymous procedure-with-setter, as was the case
before the procs.c change.
* module/srfi/srfi-19.scm: Some parts of this code used a strange idiom,
`(values)', to indicate that a procedure did nothing. However, quoth
R5RS:
Except for continuations created by the `call-with-values'
procedure, all continuations take exactly one value.
Indeed the VM indicated this error. I reworked the code to avoid these
cases.
Moved ice-9/ and oop/ under module/, with the idea being that we have
only scheme under module/. Adjusted configure.in and Makefile.am
appropriately. Put oop/ at the end of the compilation order.
* oop/goops.scm: Define compiler hooks for dealing with @slot-ref and
@slot-set!.
(make-bound-check-get, make-get, make-set): Compile these indexed
accessors instead of having them be closures. Probably slower for the
memoizer, but faster for the vm... not sure what the perfect solution
is.
* test-suite/tests/goops.test ("defining classes"): Add a test that
defining a class with accessors works (it didn't until I figured out
that (@ (system base compile) compile) thing).
* module/system/base/compile.scm (call-with-nonlocal-exit-protect): New
helper, like unwind-protect but only for nonlocal exits.
(call-with-output-file/atomic): Use call-with-nonlocal-exit-protect so
that we don't mess up backtraces by catching all and then rethrowing.
Should fix this more comprehensively somewhere, though.
* module/system/il/inline.scm (define-inline): Use @ when accessing
module vars so that other modules don't need to import all of our
modules. However case-lambda is still needed.
* module/language/scheme/translate.scm (*translate-table*)
(define-scheme-translator): Rework the translator to have the clauses
defined separately via the define-scheme-translator macro, so that
external modules can define their own translators. Should be no
functional change in this commit, though.
* libguile/goops.c (get_slot_value, set_slot_value): While keeping the
inlined getter/setter dispatch for closures, allow the getters and
setters to be any kind of procedure.
* oop/goops.scm (compute-getters-n-setters): Relax the checks on
getter/setter procedures, so that if a getter is a procedure but not a
closure, we don't try to poke its arity.
* oop/goops/Makefile.am (SOURCES): Compile all the goops submodules!
* oop/goops/old-define-method.scm: Removed, in an act of housekeeping.
* oop/goops/compile.scm:
* oop/goops/dispatch.scm: Break a circular module dependency by making
sure that (oop goops) is loaded when we go to compile submodules.
* oop/goops/compile.scm (compile-method/memoizer)
(compile-method/memoizer+next): Allow a procedure without source
through. This can happen with getter and setter lambdas that were
compiled, and in that case there is no next-method call anyway. Ideally
we should be able to specify compile-method for accessor methods...
* libguile/goops.c (scm_sys_initialize_object): Don't assume that an init
thunk is a closure; just go through scm_call_0 instead.
* oop/goops/compile.scm (make-make-next-method/memoizer): Allow for the
case that the next method is compiled.
The pending task is to make the accessors compiled too, and also to
compile compile.scm and dispatch.scm, and to integrate dispatch into the
VM.
* oop/Makefile.am (SOURCES): VM-ify the makefile, so we compile goops.scm
by default.
* oop/goops.scm (load-toplevel): Load goops builtins when compiling too.
(method): Fix a literal #<unspecified> in the generated procedure (for
an empty body).
(internal-add-method!): Cleverness when bootstrapping add-method!.
Neat!
(initialize for <generic>): Use the `method' macro so we get
compilation support.
* oop/goops/dispatch.scm (cache-methods): Don't assume entries are pairs.
* libguile/eval.i.c (type_dispatch, apply_vm_cmethod)
(apply_memoized_cmethod): Tweak the nastiness a bit more so as to deal
with the '(no-method) empty entries. I would like to stop the search if
the cdr isn't a pair, but currently with the inlined memoized bits, the
cdr is a pair. The fix would be to make the memoizer return a procedure
and not the already-inlined bits -- slightly slower but the vm will be
faster anyway.
* libguile/objects.c (scm_mcache_lookup_cmethod): Same fixes here.
* oop/goops/dispatch.scm (cache-hashval, cache-try-hash!): Allow non-list
cmethod tails.
* ice-9/boot-9.scm (make-modules-in): Change to make sure that we are
making modules in modules; that is, that a global binding of `compile'
doesn't prevent a module from importing a submodule named `compile'.
(resolve-module): Clean up a bit, and serialize the logic.
* libguile/objects.c (scm_mcache_lookup_cmethod, scm_apply_generic):
* libguile/eval.i.c (CEVAL): Now that cmethod entries can have a program
as their tail instead of a memoized proc, we have to change the halting
condition on the method cache search, in both places: the one that's
inlined into eval.i.c and the one in objects.c. If the cmethod isn't a
pair, apply it.
* libguile/goops.c (make): In the `make' procedure that's used before
GOOPS is booted, bind #:formals, #:body, and #:compile-env on methods.
* oop/goops/compile.scm (compute-entry-with-cmethod): There was a
terrible trick here that involved putting a dummy pair in the cache,
then modifying it in place with the result of memoization. The note
claimed that this was to cut recursion short, or something. I can't see
how it could recurse, given that `methods' is changing each time. Also,
the pair trick doesn't work with byte-compiled methods. So, remove it.
(compile-method): Dispatch to the appropriate method compiler, based on
whether the method was defined with the interpreter or with the
compiler.
(make-next-method): New function, generically computes a `next-method'
procedure, though the caller has to supply the arguments.
(compile-method/vm): Exciting method byte compiler!
(make-make-next-method/memoizer, compile-method/memoizer): Add the
/memoizer suffix, and move all this code to the bottom of the file.
* ice-9/boot-9.scm (compile-time-environment): Remove definition from
boot-9 -- instead, autoload it and `compile' from (system base
compile).
* libguile/objcodes.h:
* libguile/objcodes.c (scm_objcode_to_program): Add an optional argument,
`external', the external list to set on the returned program.
* libguile/vm-i-system.c (externals): New instruction, returns the
external list. Only used by (compile-time-environment).
* libguile/vm.c (scm_load_compiled_with_vm): Adapt to
scm_objcode_to_program change.
* module/language/scheme/translate.scm (translate): Actually pay
attention to the environment passed as an argument.
(custom-transformer-table): Expand out (compile-time-environment) to
something that can be passed to `compile'.
* module/system/base/compile.scm (*current-language*): Instead of
hard-coding `scheme' in various places, use a current language fluid,
initialized to `scheme'.
(compile-file, load-source-file): Adapt to *current-language*.
(load-source-file): Ada
(scheme-eval): Removed, no one used this.
(compiled-file-name): Don't hard-code "scm" and "go"; instead use the
%load-extensions and %load-compiled-extensions.
(cenv-module, cenv-ghil-env, cenv-externals): Some accessors for
compile-time environments.
(compile-time-environment): Here we define (compile-time-environment)
to something that will return #f; the compiler however produces
different code as noted above.
(compile): New function, compiles an expression into a thunk, then runs
the thunk to get the value. Useful for procedures. The optional second
argument can be either a module or a compile-time-environment; in the
latter case, we can recompile even with lexical bindings.
(compile-in): If the env specifies a module, set that module for the
duration of the compilation.
* module/system/base/syntax.scm (%compute-initargs): Fix a bug where the
default value for a field would always replace a user-supplied value.
Whoops.
* module/system/il/ghil.scm (ghil-env-dereify): New function, takes the
result of ghil-env-reify and turns it back into a GHIL environment.
* scripts/compile (compile): Remove some of the tricky error handling, as
the library procedures handle this for us.
* test-suite/tests/compiler.test: Add a test for the dynamic compilation
bits.
* ice-9/boot-9.scm (compile-time-environment): Return #f instead of
erroring under the interpreter, a bit more sane.
* libguile/goops.c (create_standard_classes):
* libguile/goops.h (scm_si_formals, scm_si_body, scm_si_compile_env):
* oop/goops.scm (method, initialize): Add `formals', `body', and
`compile-env' slots to <method>.
* oop/goops/accessors.scm (define-class-with-accessors)
(define-class-with-accessors-keywords): Turn into defmacros.
* oop/goops/save.scm (readable, restore, write-component): Turn into
defmacros.
Both of these changes are untested, unfortunately.
* ice-9/boot-9.scm (compile-time-environment): New function, with
documentation. The trick is that the compiler recognizes calls to
(compile-time-environment) and replaces it with a representation of the
*available* lexicals. Note that this might not be all the lexicals;
only the heap-allocated ones are returned.
* module/language/scheme/translate.scm (custom-transformer-table):
Compile `compile-time-environment' to <ghil-reified-env>.
* module/system/il/compile.scm (codegen): Add <ghil-reified-env> clause,
which calls ghil-env-reify.
* module/system/il/ghil.scm (ghil-env-reify): New procedure, returns a
list of (NAME . EXTERNAL-INDEX).
(<ghil>): Add <ghil-reified-env> object.