* module/oop/goops/dispatch.scm: Add a dispatch protocol in Scheme. The
idea is that instead of using a hardcoded C protocol, we compile
dispatch procedures at runtime. To avoid too much thrashing at bootup,
there is a simple JIT mechanism -- dispatch will be data-driven,
through the cache, for the first 5 invocations, then a dispatch
procedure will be compiled from the cache.
My initial timings indicate that interpreted dispatch takes about
100us, and that compiled dispatch takes about 60us. Compilation itself
takes about 16000us (16 ms). The compiled procedure dispatch times
will improve soon, hopefully.
* libguile/eq.c (scm_eqv_p): Not a generic any more. Since eqv? is used
by e.g. `case', which should be able to compile into dispatch tables,
it really doesn't make sense to dispatch out to a generic.
(scm_equal_p): So it was always the case that (equal? 'foo "foo") =>
#f. But (equal? 'foo 'bar) could actually be extended by a generic.
This was a bug, if you follow the other logic of the code. Changed so
that generic functions can only extend the domain of equal? when
operating on goops objects.
* oop/goops.scm: No more eqv? generic.
* test-suite/tests/goops.test: Remove eqv? tests.
* module/oop/goops/dispatch.scm (memoize-method!): If we don't have a
no-applicable-method, just call no-applicable-method directly.
* test-suite/tests/goops.test ("no-applicable-method"): Add some tests.
* libguile/goops.c (scm_sys_invalidate_method_cache_x, scm_make)
(create_standard_classes): Remove code-table slot from methods. The
generic cache completely does its job, afaict.
* libguile/goops.h (scm_si_formals, scm_si_body, scm_si_make_procedure):
Renumber slots.
* module/oop/goops.scm (initialize on <method>): No more code-table
slot.
* module/oop/goops/compile.scm: Always "compile" a method, instead of
looking for a hit in an always-empty cache.
* libguile/goops.c (clear_method_cache)
(scm_sys_invalidate_method_cache_x, scm_make)
(create_standard_classes): Remove the used-by method from generics, as
it is not used at all.
* libguile/goops.h: Renumber generic slots.
* module/oop/goops/dispatch.scm (memoize-method!): No more used-by slot.
I tried to split this one, and I know it's a bit disruptive, but this
stuff really is one big cobweb. So instead we'll pretend like these are
separate commits, by separating the changelog.
Applicable struct runtime support.
* libguile/debug.c (scm_procedure_source):
* libguile/eval.c (scm_trampoline_0, scm_trampoline_1)
(scm_trampoline_2):
* libguile/eval.i.c (CEVAL):
* libguile/goops.c (scm_class_of):
* libguile/procprop.c (scm_i_procedure_arity):
* libguile/procs.c (scm_procedure_p, scm_procedure, scm_setter): Allow
for applicable structs. Whee!
* libguile/deprecated.h (scm_vtable_index_vtable): Define as a synonym
for scm_vtable_index_self.
(scm_vtable_index_printer): Alias scm_vtable_index_instance_printer.
(scm_struct_i_free): Alias scm_vtable_index_instance_finalize.
(scm_struct_i_flags): Alias scm_vtable_index_flags.
(SCM_STRUCTF_FLAGS): Be a -1 mask, we have a whole word now.
(SCM_SET_VTABLE_DESTRUCTOR): Implement by hand.
Hidden slots.
* libguile/struct.c (scm_make_struct_layout): Add support for "hidden"
fields, writable fields that are not visible to make-struct. This
allows us to add fields to vtables and not break existing make-struct
invocations.
(scm_struct_ref, scm_struct_set_x): Always get struct length from the
vtable. Support hidden fields.
* libguile/goops.c (scm_class_hidden, scm_class_protected_hidden): New
slot classes, to correspond to the new vtable slots.
(scm_sys_prep_layout_x): Turn hidden slots into 'h'.
(build_class_class_slots): Reorder the class slots to account for
vtable fields coming out of negative-land, for name as a vtable slot,
and for hidden fields.
(create_standard_classes): Define <hidden-slot> and
<protected-hidden-slot>.
Clean up struct.h.
* libguile/struct.h: Lay things out cleaner. There are no more hidden
(negative) words. Names are nicer. The exposition is nicer. But the
basics are the same. The incompatibilities are that <vtable> has more
slots now, and that scm_alloc_struct's signature has changed. The
former is ameliorated by the "hidden" slots mentioned before, and the
latter, well, it was always a very internal thing...
(scm_t_struct_finalize): New type, a finalizer function to be run when
instances of a vtable are collected.
(scm_t_struct_free): Removed, structs' data is managed by the GC now,
and not freed by vtable functions.
* libguile/struct.c: (scm_vtable_p): Now we keep flags on
vtable-vtables, so this check is cheaper.
(scm_alloc_struct): No hidden words. Yippee.
(struct_finalizer_trampoline): Entersify.
(scm_make_struct): No need to babysit extra words, though now we have
to babysit flags. Propagate the vtable, applicable, and setter flags
appropriately.
(scm_make_vtable_vtable): Update for new simplicity.
(scm_print_struct): A better printer.
(scm_init_struct): Define <applicable-struct-vtable>, a magical vtable
like CL's funcallable-standard-class. Also define
<applicable-struct-with-setter-vtable>.
Remove foreign object implementation.
* libguile/goops.h:
* libguile/goops.c (scm_make_foreign_object, scm_make_class)
(scm_add_slot, scm_wrap_object, scm_wrap_component): Remove, these
were undocumented and unworking.
Clean up goops.h, a little.
* libguile/goops.h:
* libguile/goops.c: Also clean up.
* module/oop/goops/dispatch.scm (hashset-index): Adapt for new hashset
index.
lists in method cache matching.
* libguile/goops.c (scm_mcache_lookup_cmethod): Don't apply SCM_CAR to
non-pairs when walking argument lists in method cache matching.
Don't check for CLASSP or symbol in the car slot, since the end of
the specifier list is a non-pair. Update comments to reflect new
structure of method cache entry.
* module/oops/goops/dispatch.scm: Update comments here too.
* module/ice-9/channel.scm (eval): Fix number of arguments to
`guile:eval'.
* module/oop/goops/save.scm (write-readably): Fix number of arguments to
`write-array'.
* module/srfi/srfi-19.scm (priv:char->int): Fix number of arguments to
`priv:time-error'.
* module/oop/goops.scm (method): Reimplement as a hygienic macro. This
seriously took me like 6 hours to figure out. Allows for lexical
specializers: (let ((<x> ...)) (define-method (foo (arg <x>)) ...)).
* module/oop/goops/compile.scm (next-method?, compile-make-procedure):
Remove these, as `method' does it all now, hygienically.
* module/language/tree-il/compile-glil.scm: Add primcall compilers for
@slot-ref and @slot-set.
* module/language/tree-il/optimize.scm (add-interesting-primitive!): New
export. Creates an association between a variable in the current module
and a primitive name.
* module/oop/goops.scm: Rework compiler hooks to work with tree-il and
not ghil.
* module/ice-9/boot-9.scm (datum->syntax, syntax->datum): Rename from
datum->syntax-object and syntax-object->datum, following r6rs. Change
all callers. Reorder some of the other exports from psyntax.
* module/ice-9/psyntax.scm: Change datum->syntax and syntax->datum
definitions and callers.
* module/ice-9/psyntax-pp.scm: Regenerated.
* module/oop/goops.scm (define-class-pre-definition): Update for changes.
* libguile/eval.c (scm_m_eval_when): Whoops, eval-when has an implicit
begin. Fix.
* module/oop/goops.scm: Syncase doesn't like definitions in expression
context, and grudgingly I have decided to go along with that. But that
doesn't mean we can't keep the old semantics, via accessing the module
system directly. So do so. I took the opportunity to rewrite some
macros with syntax-rules and syntax-case -- the former is nicer than
the latter, of course.
* module/oop/goops/save.scm: Don't define within an expression.
* module/oop/goops/simple.scm (define-class): Use define-syntax.
* module/oop/goops/stklos.scm (define-class): Use define-syntax.
* module/ice-9/boot-9.scm (define-macro): Use syntax-case to destructure
macro arguments, so we get good errors.
* module/ice-9/match.scm (defstruct, define-const-structure): Don't
unquote in the `defstruct' macro as a value in expansions.
* module/oop/goops.scm (standard-define-class): Can't define a macro with
`define', use `define-syntax' instead.
(define-accessor): Use syntax-rules. Doesn't give us much in this case.
(toplevel-define!): New helper, to let us keep GOOPS' behavior with the
new expander. Some solution that works lexically and at the toplevel
would be nice, though.
(define-method): Reimplement with syntax-rules -- soooo much nicer.
* module/oop/goops/dispatch.scm (lookup-create-cmethod): Don't define
within an expression.
* configure.in: No longer output the Makefile.ins.
* module/Makefile.am: Include the contents of ice-9/, srfi/, and oop/.
* module/ice-9/Makefile.am:
* module/ice-9/debugger/Makefile.am:
* module/ice-9/debugging/Makefile.am:
* module/oop/Makefile.am:
* module/oop/goops/Makefile.am:
* module/srfi/Makefile.am: Removed.
* module/oop/goops.scm (method-source): Don't throw an error if this
method has no source.
(method-formals): New generic function, the complement of
method-specializers for introspection.
* module/ice-9/boot-9.scm (eval-when): Replace eval-case with eval-when.
Eval-when is *much* simpler, and more expressive to boot. Perhaps in
the future we'll get 'visit and 'revisit too.
* module/ice-9/deprecated.scm (eval-case): Provide mostly-working
deprecated version of eval-case.
* module/ice-9/boot-9.scm (defmacro, define-macro): Relax condition: we
can make defmacros that are not at the toplevel now. But in the future
we should replace this implementation of defmacros with one written in
syntax-case.
(define-module, use-modules, use-syntax): Allow at non-toplevel.
(define-public, defmacro-public, export, re-export): Don't evaluate at
compile-time, I can't see how that helps things. Allow `export' and
`re-export' at non-toplevel.
* module/ice-9/getopt-long.scm:
* module/ice-9/i18n.scm:
* module/oop/goops.scm:
* module/oop/goops/compile.scm:
* module/oop/goops/dispatch.scm: Switch to use eval-when, not
eval-case.
* module/language/scheme/compile-ghil.scm (eval-when): Replace eval-case
transformer with eval-when transformer. Sooooo much simpler, and it
will get better once we separate expansion from compilation.
* module/language/scheme/expand.scm (quasiquote): Hm, expand quasiquote
properly. Not hygienic. Syncase needed.
(lambda): Handle internal defines with docstrings propertly.
* module/language/scheme/compile-ghil.scm (define-scheme-translator):
Only add an else clause if the transformer didn't have one.
* module/oop/goops.scm (min-fixnum, max-fixnum): Define at compile-time
as well.
(@slot-ref, @slot-set!): Only define transformers for these at
compile-time. Avoids loading up the compiler unnecessarily. Also, allow
for the `n' to be determined lexically, in which case we dispatch to
the primitive.
(num-standard-pre-cache, define-standard-accessor-method)
(bound-check-get, standard-get, standard-set): Rework the fixed-offset
getters and setters so that they can be computed at compile-time.
Accessors to fields with n > num-standard-pre-cache will be dispatched
to the primitive instead of within the VM.
* libguile/goops.c (scm_make): In the pre-inst `make', default
`procedure' to #f, and read a `make-procedure' instead of
`compile-env'.
* libguile/goops.h (scm_si_make_procedure): This instead of
scm_si_compile_env.
* module/oop/goops.scm (make-method): Remove this unused function. Users
should use (make <method> ...) directly.
(method): Capture `make-procedure' instead of `procedure' in the case
that the body calls a next-method. Allows for the kind of
"recompilation" that we were using before, but with closures instead of
re-entering the compiler. Type-specific compilation is still
interesting, but probably should be implemented in another way.
(initialize): Default #:procedure to #f, and
s/compile-env/make-procedure/.
* module/oop/goops/compile.scm (code-table-lookup): Just return the
cmethod, not the entry -- since the entry is now just (append types
cmethod).
(compile-make-procedure): New procedure, returns a form that, when
evaluated/compiled, will yield a procedure of one argument, the
next-method. When called with a next-method, the procedure returns an
actual method implementation. compile-make-procedure returns #f if the
body doesn't call next-method.
(compile-method): Unify to always return procedures. Much cleaner and
*much* faster in the compiled case. In the interpreted case, there
might be a slight slowdown, but if there is one it should be slight.
* module/oop/goops/dispatch.scm (method-cache-install!): Adapt to removal
of compute-entry-with-cmethod.
* libguile/objects.c (scm_apply_generic): Inline the case when the
generic is a program.
* libguile/vm-i-system.c (return): Tick when functions return.
* module/oop/goops.scm (object-eqv?, object-equal?): Remove these
historical methods.
* doc/ref/api-evaluation.texi: Fix some typos and xrefs.
* doc/ref/compiler.texi (The Scheme Compiler): Document the scheme
compiler, and start documenting the GHIL language.
* doc/ref/guile.texi (Guile Implementation): Whoops, put autoconf after
the implementation foo. Unless we want it before?
* doc/ref/history.texi (The Emacs Thesis): Fix typo.
* doc/ref/vm.texi (Environment Control Instructions): Rename offset to
index.
* module/language/ghil.scm (parse-ghil): Fix what I think was a bug --
the consumer in a mv-call shouldn't be a rest arg.
* module/language/scheme/Makefile.am (SOURCES):
* module/language/scheme/compile-ghil.scm: Rename this file from
translate.scm.
* module/oop/goops.scm:
* module/language/scheme/spec.scm: Deal with renaming.
* 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!
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.