mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-29 08:20:20 +02:00
Letrectify only on -O2; update docs
* doc/ref/api-evaluation.texi (Compilation): Document the -O options. * doc/ref/api-modules.texi (Using Guile Modules): @@ docs refer to declarative modules. (Creating Guile Modules): Use when for 1-armed if. (Declarative Modules): Make implications of declarative bindings more explicit, and explicitly document ways to disable the optimization. * module/language/tree-il/optimize.scm (tree-il-optimizations): Punt letrectification to -O2.
This commit is contained in:
parent
253cf3dc6f
commit
31cb10af81
3 changed files with 96 additions and 6 deletions
|
@ -675,6 +675,17 @@ warnings include @code{unused-variable}, @code{unused-toplevel},
|
||||||
@code{arity-mismatch}, @code{format},
|
@code{arity-mismatch}, @code{format},
|
||||||
@code{duplicate-case-datum}, and @code{bad-case-datum}.
|
@code{duplicate-case-datum}, and @code{bad-case-datum}.
|
||||||
|
|
||||||
|
@item -O @var{opt}
|
||||||
|
@itemx --optimize=@var{opt}
|
||||||
|
@cindex optimizations, compiler
|
||||||
|
Enable or disable specific compiler optimizations; use @code{-Ohelp} for
|
||||||
|
a list of available options. The default is @code{-O2}, which enables
|
||||||
|
most optimizations. @code{-O1} is recommended if compilation speed is
|
||||||
|
more important than the speed of the compiled code. Pass
|
||||||
|
@code{-Ono-@var{opt}} to disable a specific compiler pass. Any number
|
||||||
|
of @code{-O} options can be passed to the compiler, with later ones
|
||||||
|
taking precedence.
|
||||||
|
|
||||||
@item -f @var{lang}
|
@item -f @var{lang}
|
||||||
@itemx --from=@var{lang}
|
@itemx --from=@var{lang}
|
||||||
Use @var{lang} as the source language of @var{file}. If this option is omitted,
|
Use @var{lang} as the source language of @var{file}. If this option is omitted,
|
||||||
|
|
|
@ -240,7 +240,8 @@ Refer to the binding named @var{binding-name} in module
|
||||||
Refer to the binding named @var{binding-name} in module
|
Refer to the binding named @var{binding-name} in module
|
||||||
@var{module-name}. The binding must not have been exported by the
|
@var{module-name}. The binding must not have been exported by the
|
||||||
module. This syntax is only intended for debugging purposes or as a
|
module. This syntax is only intended for debugging purposes or as a
|
||||||
last resort.
|
last resort. @xref{Declarative Modules}, for some limitations on the
|
||||||
|
use of @code{@@@@}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@node Creating Guile Modules
|
@node Creating Guile Modules
|
||||||
|
@ -290,8 +291,8 @@ example,
|
||||||
(define-module (my mod)
|
(define-module (my mod)
|
||||||
#:autoload (srfi srfi-1) (partition delete-duplicates))
|
#:autoload (srfi srfi-1) (partition delete-duplicates))
|
||||||
...
|
...
|
||||||
(if something
|
(when something
|
||||||
(set! foo (delete-duplicates ...)))
|
(set! foo (delete-duplicates ...)))
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
When a module is autoloaded, all its bindings become available.
|
When a module is autoloaded, all its bindings become available.
|
||||||
|
@ -922,7 +923,7 @@ However, as Scheme godparent Mathias Felleisen wrote in ``On the
|
||||||
Expressive Power of Programming Languages'', a more expressive language
|
Expressive Power of Programming Languages'', a more expressive language
|
||||||
is necessarily harder to reason about. There are transformations that
|
is necessarily harder to reason about. There are transformations that
|
||||||
Guile's compiler would like to make which can't be done if every
|
Guile's compiler would like to make which can't be done if every
|
||||||
top-level binding is subject to mutation at any time.
|
top-level definition is subject to mutation at any time.
|
||||||
|
|
||||||
Consider this module:
|
Consider this module:
|
||||||
|
|
||||||
|
@ -946,6 +947,9 @@ text. However, in the general case it could be that a programmer could
|
||||||
reach into the @code{(boxes)} module at any time and change the value of
|
reach into the @code{(boxes)} module at any time and change the value of
|
||||||
@code{box-ref}.
|
@code{box-ref}.
|
||||||
|
|
||||||
|
@cindex declarative
|
||||||
|
@cindex modules, declarative
|
||||||
|
@cindex definitions, declarative
|
||||||
To allow Guile to reason about the values of top-levels from a module, a
|
To allow Guile to reason about the values of top-levels from a module, a
|
||||||
module can be marked as @dfn{declarative}. This flag applies only to
|
module can be marked as @dfn{declarative}. This flag applies only to
|
||||||
the subset of top-level definitions that are themselves declarative:
|
the subset of top-level definitions that are themselves declarative:
|
||||||
|
@ -965,7 +969,7 @@ By default, modules are compiled declaratively if the
|
||||||
@code{user-modules-declarative?} parameter is true when the
|
@code{user-modules-declarative?} parameter is true when the
|
||||||
module is compiled.
|
module is compiled.
|
||||||
|
|
||||||
@deffn {Scheme Parameter} user-modules-declarative-by-default?
|
@deffn {Scheme Parameter} user-modules-declarative?
|
||||||
A boolean indicating whether definitions in modules created by
|
A boolean indicating whether definitions in modules created by
|
||||||
@code{define-module} or implicitly as part of a compilation unit without
|
@code{define-module} or implicitly as part of a compilation unit without
|
||||||
an explicit module can be treated as declarative.
|
an explicit module can be treated as declarative.
|
||||||
|
@ -974,6 +978,76 @@ an explicit module can be treated as declarative.
|
||||||
Because it's usually what you want, the default value of
|
Because it's usually what you want, the default value of
|
||||||
@code{user-modules-declarative?} is @code{#t}.
|
@code{user-modules-declarative?} is @code{#t}.
|
||||||
|
|
||||||
|
@subsubheading Should I Mark My Module As Declarative?
|
||||||
|
|
||||||
|
In the vast majority of use cases, declarative modules are what you
|
||||||
|
want. However, there are exceptions.
|
||||||
|
|
||||||
|
Consider the @code{(boxes)} module above. Let's say you want to be able
|
||||||
|
to go in and change the definition of @code{box-set!} at run-time:
|
||||||
|
|
||||||
|
@example
|
||||||
|
scheme@@(guile-user)> (use-modules (boxes))
|
||||||
|
scheme@@(guile-user)> ,module boxes
|
||||||
|
scheme@@(boxes)> (define (box-set! x y) (set-car! x (pk y)))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
However, considering that @code{(boxes)} is a declarative module, it
|
||||||
|
could be that @code{box-swap!} inlined the call to @code{box-set!} -- so
|
||||||
|
it may be that you are surprised if you call @code{(box-swap! x y)} and
|
||||||
|
you don't see the new definition being used. (Note, however, that Guile
|
||||||
|
has no guarantees about what definitions its compiler will or will not
|
||||||
|
inline.)
|
||||||
|
|
||||||
|
If you want to allow the definition of @code{box-set!} to be changed and
|
||||||
|
to have all of its uses updated, then probably the best option is to
|
||||||
|
edit the module and reload the whole thing:
|
||||||
|
|
||||||
|
@example
|
||||||
|
scheme@@(guile-user)> ,reload (boxes)
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The advantage of the reloading approach is that you maintain the
|
||||||
|
optimizations that declarative modules enable, while also being able to
|
||||||
|
live-update the code. If the module keeps precious program state, those
|
||||||
|
definitions can be marked as @code{define-once} to prevent reloads from
|
||||||
|
overwriting them. @xref{Top Level}, for more on @code{define-once}.
|
||||||
|
Incidentally, @code{define-once} also prevents declarative-definition
|
||||||
|
optimizations, so if there's a limited subset of redefinable bindings,
|
||||||
|
@code{define-once} could be an interesting tool to mark those
|
||||||
|
definitions as works-in-progress for interactive program development.
|
||||||
|
|
||||||
|
To users, whether a module is declarative or not is mostly immaterial:
|
||||||
|
besides normal use via @code{use-modules}, users can reference and
|
||||||
|
redefine public or private bindings programmatically or interactively.
|
||||||
|
The only difference is that changing a declarative definition may not
|
||||||
|
change all of its uses. If this use-case is important to you, and if
|
||||||
|
reloading whole modules is insufficient, then you can mark all
|
||||||
|
definitions in a module as non-declarative by adding
|
||||||
|
@code{#:declarative? #f} to the module definition.
|
||||||
|
|
||||||
|
The default of whether modules are declarative or not can be controlled
|
||||||
|
via the @code{(user-modules-declarative?)} parameter mentioned above,
|
||||||
|
but care should be taken to set this parameter when the modules are
|
||||||
|
compiled, e.g. via @code{(eval-when (expand) (user-modules-declarative?
|
||||||
|
#f))}. @xref{Eval When}.
|
||||||
|
|
||||||
|
Alternately you can prevent declarative-definition optimizations by
|
||||||
|
compiling at the @code{-O1} optimization level instead of the default
|
||||||
|
@code{-O2}, or via explicitly passing @code{-Ono-letrectify} to the
|
||||||
|
@code{guild compile} invocation. @xref{Compilation}, for more on
|
||||||
|
compiler options.
|
||||||
|
|
||||||
|
@cindex inlining
|
||||||
|
One final note. Currently, definitions from declarative modules can
|
||||||
|
only be inlined within the module they are defined in, and within a
|
||||||
|
compilation unit. This may change in the future to allow Guile to
|
||||||
|
inline imported declarative definitions as well (cross-module inlining).
|
||||||
|
To Guile, whether a definition is inlinable or not is a property of the
|
||||||
|
definition, not its use. We hope to improve compiler tooling in the
|
||||||
|
future to allow the user to identify definitions that are out of date
|
||||||
|
when a declarative binding is redefined.
|
||||||
|
|
||||||
|
|
||||||
@node Accessing Modules from C
|
@node Accessing Modules from C
|
||||||
@subsection Accessing Modules from C
|
@subsection Accessing Modules from C
|
||||||
|
|
|
@ -59,7 +59,12 @@
|
||||||
;; Avoid resolve-primitives until -O2, when CPS optimizations kick in.
|
;; Avoid resolve-primitives until -O2, when CPS optimizations kick in.
|
||||||
;; Otherwise, inlining the primcalls during Tree-IL->CPS compilation
|
;; Otherwise, inlining the primcalls during Tree-IL->CPS compilation
|
||||||
;; will result in a lot of code that will never get optimized nicely.
|
;; will result in a lot of code that will never get optimized nicely.
|
||||||
|
;; Similarly letrectification is great for generated code quality, but
|
||||||
|
;; as it gives the compiler more to work with, it increases compile
|
||||||
|
;; time enough that we reserve it for -O2. Also, this makes -O1 avoid
|
||||||
|
;; assumptions about top-level values, in the same way that avoiding
|
||||||
|
;; resolve-primitives does.
|
||||||
'((#:resolve-primitives? 2)
|
'((#:resolve-primitives? 2)
|
||||||
(#:expand-primitives? 1)
|
(#:expand-primitives? 1)
|
||||||
(#:letrectify? 1)
|
(#:letrectify? 2)
|
||||||
(#:partial-eval? 1)))
|
(#:partial-eval? 1)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue