* 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.
* libguile/vm-i-system.c (br-if-nargs-gt): Fix variable declaration
placement.
(bind-kwargs): Patch mostly by Ludovic: it seems that in the mode in
which we have rest args, the keywords can appear anywhere. Bummer.
Change to allow for this.
* module/ice-9/optargs.scm (parse-lambda-case): Same, add a
permissive-keys clause that handles the case in which there's a rest
argument.
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/language/tree-il/compile-glil.scm (flatten): Compile `if'
statements with `eq?' and `null?', and their `not?' variants, into
more specific bytecode.
Turns out this was not a very useful idea, and semantically tricky to
boot.
This reverts commit 24bf130fd1, and makes
the following additional changes:
* module/ice-9/optargs.scm (parse-lambda-case, let-optional)
(let-optional*, let-keywords, let-keywords*):
* module/language/tree-il.scm: (<lambda-case>, parse-tree-il)
(unparse-tree-il, tree-il->scheme, tree-il-fold,
make-tree-il-folder)
(post-order!, pre-order!):
* module/language/tree-il/analyze.scm (analyze-lexicals):
* module/language/tree-il/compile-glil.scm (compile-glil):
* module/language/tree-il/inline.scm (inline!): Remove all traces of
#:predicate from tree-il.
* module/ice-9/psyntax.scm (build-simple-lambda, build-lambda-case)
(chi-lambda-case): Adapt to tree-il change.
* module/ice-9/psyntax-pp.scm: Regenerated.
* module/language/brainfuck/compile-tree-il.scm (compile-body):
* module/language/ecmascript/compile-tree-il.scm (comp, comp-body):
* test-suite/tests/tree-il.test: Adapt to tree-il change.
* doc/ref/api-procedures.texi (Case-lambda): Remove mention of
#:predicate.
* module/Makefile.am:
* module/ice-9/boot-9.scm:
* module/ice-9/quasisyntax.scm: Add quasisyntax. Implementation by Andre
van Tonder, patch by Andreas Rottmann.
* test-suite/tests/srfi-10.test: Hack to remove srfi-10's clobbering of
#,.
* test-suite/tests/syncase.test: Add a quasisyntax test.
* module/language/ecmascript/compile-tree-il.scm: Fix a number of bugs,
fallen out from the ghil->tree-il conversion.
* module/language/tree-il/compile-glil.scm (*primcall-ops*): Add a hack
for "return" for javascript. Scheme shouldn't see this because it's
not an "interesting primitive".
* module/ice-9/optargs.scm (let-keywords): I thought that I had the
scoping right here, but I didn't. Make sure that the lambda formals
for the initializers are new, fresh identifiers, so that let scoping
works appropriately.
* module/language/tree-il/analyze.scm (validate-arity)[arity]: Rename
to...
[arities]: ... this. Return all the arities of PROC.
Update caller accordingly.
* test-suite/tests/tree-il.test ("warnings")["arity
mismatch"]("case-lambda", "case-lambda with wrong number of
arguments", "case-lambda*", "case-lambda* with wrong arguments"): New
tests.
* module/language/tree-il/analyze.scm
(validate-arity)[filter-keyword-args]: New procedure.
[arity]: Get accurate arity for programs, return ALLOW-OTHER-KEYS? as
an additional value.
Update to `arity' change; use `filter-keyword-args'.
* test-suite/tests/tree-il.test ("warnings")["arity mismatch"]("keyword
not passed and quiet", "keyword passed and quiet", "keyword passed to
global and quiet", "extra keyword", "extra keywords allowed"): New
tests.
* 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/language/tree-il/analyze.scm (<arity-info>): New record type.
(validate-arity, arity-analysis): New variables.
* module/language/tree-il/compile-glil.scm (%warning-passes): Add
`arity-mismatch'.
* module/system/base/message.scm (%warning-types): Likewise.
* test-suite/tests/tree-il.test (read-and-compile): Remove, as it's now
public.
(%opts-w-arity): New.
("warnings")["arity mismatch"]: New test prefix.
* module/language/tree-il/analyze.scm (<tree-analysis>): New type.
(analyze-tree): New procedure.
(report-unused-variables): Replace by...
(unused-variable-analysis): ... this, as a <tree-analysis>.
(report-possibly-unbound-variables): Replace by...
(unbound-variable-analysis): ... this, as a <tree-analysis>.
* module/language/tree-il/compile-glil.scm (%warning-passes): Adjust
accordingly.
(compile-glil): Likewise. Use `analyze-tree'.
A byte ordering error caused incorrect display of wide strings
when using the ",c" decompilation from the REPL.
* module/language/assembly/decompile-bytecode.scm (decode-bytecode):
wide strings are encoded in native endianness
* module/system/vm/program.scm: Export the arity things again, and
program-arity. Why not.
* doc/ref/api-procedures.texi (Compiled Procedures): Update for current
API.
(Optional Arguments): Update to assume lambda* and define* are always
available, and (ice-9 optargs) is now the ghetto.
(Case-lambda): Now here, moved from SRFI-16 docs. Also docs
case-lambda*.
* doc/ref/srfi-modules.texi: Point to core case-lambda docs.
will be useful for making e.g. typecase-lambda. Tough to tell though.
* module/ice-9/psyntax.scm (lambda-formals, lambda*-formals): Parse out
a #:predicate, which goes right before the rest args. The vanilla
lambda doesn't parse it out of course, but it does return another
value.
(chi-lambda-case, lambda*, lambda): Expand and pass the predicate on
to build-lambda-case.
* module/ice-9/psyntax-pp.scm: Regenerate.
* module/language/tree-il/compile-glil.scm (flatten): Compile a failing
predicate without an else clause into a call to `error'. Also, fix
something the compile warnings caught.
* module/srfi/srfi-35.scm (%make-condition-type): New procedure.
(make-condition-type, make-compound-condition-type): Use it.
* test-suite/tests/srfi-35.test ("condition
types")["struct-vtable-name"]: New test.
* module/ice-9/psyntax.scm (case-lambda, case-lambda*): Add
implementations of these, present in the base environment.
* module/ice-9/psyntax-pp.scm: Regenerated.
* module/srfi/srfi-16.scm (case-lambda): Replace the core's case-lambda
definition with our own. We're not quite ready to switch yet.
* module/language/assembly/compile-bytecode.scm (write-bytecode): Handle
br-if-nargs compilation.
* module/language/assembly/decompile-bytecode.scm (decode-load-program):
And decompile them nicely as well.
* module/language/assembly/disassemble.scm (code-annotation): And,
present the disassembly if br-if-nargs-* nicely.
* module/language/glil/compile-assembly.scm (open-arity, close-arity)
(begin-arity, glil->assembly): Refactor so that arities can have
noncontiguous starts and ends. So within a prelude there is no arity
-- only before (the previous arity) or after (the new arity).
* module/system/vm/program.scm (arity:end): Add this private accessor.
Arities are expected to be in the new format. While not a change in
objcode format, it is an incompatible change, so I'll bump the objcode
cookie.
(program-arity): Check that the ip is within both bounds of the arity.
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump.
* libguile/programs.c (scm_i_program_arity): Update for new arity format.
* module/system/vm/frame.scm (vm-frame-arguments): Avoid throwing an
error in this function, which is called from the backtrace code.
* module/ice-9/psyntax.scm (lambda-formals, chi-simple-lambda)
(lambda*-formals, chi-lambda-case): Refactor the lambda
transformations with an eye to being able to do case-lambda.
* module/ice-9/psyntax-pp.scm: Regenerated.
* test-suite/tests/syntax.test: Adapted tests so that the errors we
expect match what is given by psyntax.
* module/ice-9/optargs.scm:
* module/ice-9/psyntax-pp.scm:
* module/ice-9/psyntax.scm: Make define* available in the default
environment, as lambda* is available there.
* module/ice-9/optargs.scm (let-optional, let-optional*, let-keywords)
(let-keywords*): Implement in terms of parse-lambda-case, so all the
logic is in one place.
(lambda*): Re-export from the default environment -- it's all in the
VM now :-))
(define*, define*-public, defmacro*, defmacro*-public): Implement with
syntax-case.
* module/ice-9/psyntax.scm (build-lambda-case): Take an "inits" arg.
Also work around a nasty memoizer bug: see
http://article.gmane.org/gmane.lisp.guile.devel/9561.
(lambda*): Implement in psyntax, in the default environment. Exciting
stuff!
* module/ice-9/psyntax-pp.scm: Regenerated.
* module/ice-9/optargs.scm (parse-lambda-case): Helper for lambda* when
we're running under the interpreter.
* module/language/tree-il.scm (<lambda-case>): Add "inits" field, so we
don't have to parse it out of opt and kw. Adapt the traversal
procedures.
* module/language/tree-il/analyze.scm (analyze-lexicals): Analyze
lexicals in the <lambda-case> init expressions as well. Fix keyword
allocation.
* module/language/tree-il/compile-glil.scm (compile-glil): Adapt to
make-lambda-case change.
(flatten): Adapt to "inits" slot, actually init uninitialized args,
and fix bugs related to keyword arguments.
* module/language/tree-il/inline.scm (inline!): Adapt a little bit --
but with no effect.
* module/language/glil/compile-assembly.scm (glil->assembly): Flesh out
<glil-kw-prelude> compilation some more. Add a "bound?" op for
<glil-lexical>, which will push #t if the local is bound.
* module/ice-9/psyntax.scm (build-simple-lambda, build-lambda-case):
Update for new signature of make-lambda-case.
* module/ice-9/psyntax-pp.scm: Regenerated.
* module/language/brainfuck/compile-tree-il.scm (compile-body):
* module/language/ecmascript/compile-tree-il.scm (comp):
* test-suite/tests/tree-il.test ("lambda"): Update for new lambda-case
syntax.
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bumparoo
* libguile/vm-i-system.c (push-rest, bind-rest): Logically there are
actually two rest binders -- one that pops, conses, and pushes, and
one that pops, conses, and local-sets. The latter is used on keyword
arguments, because the keyword arguments themselves have been shuffled
up on the stack. Renumber ops again.
* module/language/tree-il/compile-glil.scm (flatten): Attempt to handle
compilation of lambda-case with keyword arguments. Might need some
help.
* module/ice-9/psyntax.scm (build-lambda-case): An attempt to handle the
interpreted case correctly. This might need a couple iterations, but
at least it looks like the compile-glil code.
* module/ice-9/psyntax-pp.scm: Regenerated.
* module/language/glil.scm (<glil>): Rename "rest?" to "rest" in
<glil-opt-prelude> and <glil-kw-prelude>, as it is no longer a simple
boolean, but if true is an integer: the index of the local variable to
which the rest should be bound.
* module/language/glil/compile-assembly.scm (glil->assembly): Adapt to
"rest" vs "rest?". In the keyword case, use "bind-rest" instead of
"push-rest".
* test-suite/tests/tree-il.test: Update for opt-prelude change.
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump.
* libguile/vm-i-system.c (br-if-nargs-ne, br-if-args-lt)
(br-if-nargs-gt): New instructions, for use by different lambda cases.
(bind-optionals, bind-optionals/shuffle, bind-kwargs): New
instructions, for binding optional and keyword arguments. Renumber
other ops.
* module/language/ecmascript/compile-tree-il.scm (comp, comp-body):
Update for new tree-il. Use the new optional argument mechanism
instead of emulating it with rest arguments.
* module/language/glil/compile-assembly.scm (glil->assembly): Tweaks for
optional and keyword argument compilation.
* module/language/tree-il.scm (parse-tree-il, unparse-tree-il): Make the
else case optional, in the s-expression serialization of tree-il.
* module/language/tree-il/compile-glil.scm (flatten): Handle all of the
lambda-case capabilities.
* test-suite/Makefile.am:
* test-suite/tests/brainfuck.test: Add a brainfuck test.
* module/system/base/compile.scm: Also export read-and-compile.
* module/language/tree-il/spec.scm (join): Fix the joiner in the
0-expression case.
* module/language/tree-il/primitives.scm (+): Recognize (+ x -1) as 1-.
* module/language/brainfuck/parse.scm (read-brainfuck): Return EOF if we
actually received EOF, and there were no expressions read.
* module/language/brainfuck/compile-tree-il.scm (compile-body): Fix the
compiler for the new format of "lambda" in tree-il.
* module/language/tree-il.scm (<lambda>, <lambda-case>): Split lambda
into the lambda itself, denoting the procedure, and lambda-case,
denoting a particular arity case. Lambda-case is fairly featureful,
and has not yet been fully tested.
(<let-values>): Use a <lambda-case> as the binding expression. Seems
to suit the purpose well.
Adapt parsers, unparsers, traversal operators, etc. Sometimes in this
first version we assume there are no optional args, rest args, or a
predicate.
* module/language/tree-il/analyze.scm (analyze-lexicals): Adapt for the
new case-lambda regime. Fairly well commented. It actually simplifies
things.
(report-unused-variables): Update for new tree-il.
* module/language/tree-il/compile-glil.scm: Adapt for the new tree-il.
There are some first stabs here at proper case-lambda compilation, but
they are untested as of yet.
* module/language/tree-il/inline.scm (inline!): Rework so we can
recurse on a single node; though these transformations are strictly
reductive, so they should complete in bounded time. Simplify
accordingly, and adapt to case-lambda. Oh, and we handle lambda->let
in not just the nullary case.
* module/ice-9/psyntax.scm (build-simple-lambda, build-case-lambda)
(build-lambda-case): New constructors. The idea is that after syntax
expansion, we shouldn't have to deal with improper lists any more.
Build-simple-lambda is a shortcut for the common case. The others are
not fully exercised yet. Adapt callers.
(syntax): Add some debugging in the lambda case. I don't fully
understand this, but in practice we don't seem to see rest args here.
(lambda): Inline chi-lambda-clause, and adapt for build-simple-lambda.
* module/ice-9/psyntax-pp.scm: Regenerated.
* test-suite/tests/tree-il.test: Update tests for new tree-il lambda
format, and to expect post-prelude labels for all glil programs.
* libguile/vm-i-system.c (bind-rest): Renamed from push-rest-list.
(reserve-locals): Change so that instead of reserving space for some
additional number of locals, reserve-locals takes the absolute number
of locals, including the arguments.
* module/language/glil.scm (<glil-std-prelude>, <glil-opt-prelude>)
(<glil-kw-prelude>): New GLIL constructs, to replace <glil-arity>.
* module/language/glil/compile-assembly.scm (glil->assembly): Compile
the new preludes. Some instructions are not yet implemented, though.
* module/language/tree-il/analyze.scm (analyze-lexicals): The nlocs for
a lambda will now be the total number of locals, including arguments.
* module/language/tree-il/compile-glil.scm (flatten-lambda): Update to
write the new prelude.
* module/system/vm/program.scm (program-bindings-for-ip): If a given
index doesn't have a binding at the ip given, don't cons it on the
resulting list.
* test-suite/tests/tree-il.test: Update for GLIL changes.