From 531c9f1dc51c4801c4d031ee80a31f15285a6b85 Mon Sep 17 00:00:00 2001 From: Andreas Rottmann Date: Wed, 9 Mar 2011 21:36:54 +0100 Subject: Don't mix definitions and expressions in SRFI-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The expansion of `define-inlinable' contained an expression, which made SRFI-9's `define-record-type' fail in non-toplevel contexts ("definition used in expression context"). * module/srfi/srfi-9.scm (define-inlinable): Get rid of apparently useless expression in the expansion, so the expansion yields only definitions. At the same time, use a space in the generated names to lessen the chances of name conflicts, also avoiding -Wunused-toplevel warnings. * test-suite/tests/srfi-9.test (non-toplevel): New test verifying that `define-record-type' works in non-toplevel context as well. * doc/ref/srfi-modules.texi (SRFI-9 - define-record-type): Add subsubsection noting that Guile does not enforce top-levelness. Signed-off-by: Ludovic Courtès --- module/srfi/srfi-9.scm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'module/srfi/srfi-9.scm') diff --git a/module/srfi/srfi-9.scm b/module/srfi/srfi-9.scm index 80c3b60e8..fad570b26 100644 --- a/module/srfi/srfi-9.scm +++ b/module/srfi/srfi-9.scm @@ -1,6 +1,6 @@ ;;; srfi-9.scm --- define-record-type -;; Copyright (C) 2001, 2002, 2006, 2009, 2010 Free Software Foundation, Inc. +;; Copyright (C) 2001, 2002, 2006, 2009, 2010, 2011 Free Software Foundation, Inc. ;; ;; This library is free software; you can redistribute it and/or ;; modify it under the terms of the GNU Lesser General Public @@ -69,9 +69,12 @@ ;; the macro expansion, whereas references in non-call contexts refer to ;; the procedure. Inspired by the `define-integrable' macro by Dybvig et al. (lambda (x) + ;; Use a space in the prefix to avoid potential -Wunused-toplevel + ;; warning + (define prefix (string->symbol "% ")) (define (make-procedure-name name) (datum->syntax name - (symbol-append '% (syntax->datum name) + (symbol-append prefix (syntax->datum name) '-procedure))) (syntax-case x () @@ -81,7 +84,6 @@ #`(begin (define (proc-name formals ...) body ...) - proc-name ;; unused (define-syntax name (lambda (x) (syntax-case x () -- cgit v1.2.3 From b075a6d766c2ffe7c575b63648d8ae0d51b5dd3a Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 11 Mar 2011 21:01:35 +0100 Subject: Fix `define-inlinable' in SRFI-9 so that arguments are evaluated only once. * module/srfi/srfi-9.scm (define-inlinable): When inlining, evaluate the arguments only once. Reported by Andreas Rottmann; thanks to Andy Wingo for the elegant solution. * test-suite/tests/srfi-9.test ("side-effecting arguments"): New test prefix. --- module/srfi/srfi-9.scm | 9 ++++++--- test-suite/tests/srfi-9.test | 9 ++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'module/srfi/srfi-9.scm') diff --git a/module/srfi/srfi-9.scm b/module/srfi/srfi-9.scm index fad570b26..f9449a66f 100644 --- a/module/srfi/srfi-9.scm +++ b/module/srfi/srfi-9.scm @@ -80,15 +80,18 @@ (syntax-case x () ((_ (name formals ...) body ...) (identifier? #'name) - (with-syntax ((proc-name (make-procedure-name #'name))) + (with-syntax ((proc-name (make-procedure-name #'name)) + ((args ...) (generate-temporaries #'(formals ...)))) #`(begin (define (proc-name formals ...) body ...) (define-syntax name (lambda (x) (syntax-case x () - ((_ formals ...) - #'(begin body ...)) + ((_ args ...) + #'((lambda (formals ...) + body ...) + args ...)) (_ (identifier? x) #'proc-name)))))))))) diff --git a/test-suite/tests/srfi-9.test b/test-suite/tests/srfi-9.test index f8006c440..f26a7a2cd 100644 --- a/test-suite/tests/srfi-9.test +++ b/test-suite/tests/srfi-9.test @@ -94,8 +94,15 @@ (pass-if-exception "set-y! on bar" exception:wrong-type-arg (set-y! b 99))) +(with-test-prefix "side-effecting arguments" + + (pass-if "predicate" + (let ((x 0)) + (and (foo? (begin (set! x (+ x 1)) f)) + (= x 1))))) + (with-test-prefix "non-toplevel" - + (define-record-type :frotz (make-frotz a b) frotz? (a frotz-a) (b frotz-b set-frotz-b!)) -- cgit v1.2.3 From 165b10ddfaaa8ecc72d45a9be7d29e7537dc2379 Mon Sep 17 00:00:00 2001 From: Andreas Rottmann Date: Thu, 7 Apr 2011 01:12:26 +0200 Subject: Move `define-inlinable' into the default namespace * module/ice-9/boot-9.scm (define-inlineable): Moved here from SRFI-9. * module/srfi/srfi-9 (define-inlinable): Removed here. * doc/ref/api-procedures.texi (Inlinable Procedures): Add subsection about `define-inlinable'. --- doc/ref/api-procedures.texi | 29 ++++++++++++++++++++++++++++- module/ice-9/boot-9.scm | 36 ++++++++++++++++++++++++++++++++++++ module/srfi/srfi-9.scm | 32 -------------------------------- 3 files changed, 64 insertions(+), 33 deletions(-) (limited to 'module/srfi/srfi-9.scm') diff --git a/doc/ref/api-procedures.texi b/doc/ref/api-procedures.texi index 02889c45c..5c6d38024 100644 --- a/doc/ref/api-procedures.texi +++ b/doc/ref/api-procedures.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -16,6 +16,7 @@ * Higher-Order Functions:: Function that take or return functions. * Procedure Properties:: Procedure properties and meta-information. * Procedures with Setters:: Procedures with setters. +* Inlinable Procedures:: Procedures that can be inlined. @end menu @@ -797,6 +798,32 @@ Return the setter of @var{proc}, which must be either a procedure with setter or an operator struct. @end deffn +@node Inlinable Procedures +@subsection Inlinable Procedures + +You can define an @dfn{inlinable procedure} by using +@code{define-inlinable} instead of @code{define}. An inlinable +procedure behaves the same as a regular procedure, but direct calls will +result in the procedure body being inlined into the caller. + +Procedures defined with @code{define-inlinable} are @emph{always} +inlined, at all direct call sites. This eliminates function call +overhead at the expense of an increase in code size. Additionally, the +caller will not transparently use the new definition if the inline +procedure is redefined. It is not possible to trace an inlined +procedures or install a breakpoint in it (@pxref{Traps}). For these +reasons, you should not make a procedure inlinable unless it +demonstrably improves performance in a crucial way. + +In general, only small procedures should be considered for inlining, as +making large procedures inlinable will probably result in an increase in +code size. Additionally, the elimination of the call overhead rarely +matters for for large procedures. + +@deffn {Scheme Syntax} define-inlinable (name parameter ...) body ... +Define @var{name} as a procedure with parameters @var{parameter}s and +body @var{body}. +@end deffn @c Local Variables: @c TeX-master: "guile.texi" diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm index 33aa33382..327e3fa31 100644 --- a/module/ice-9/boot-9.scm +++ b/module/ice-9/boot-9.scm @@ -3496,6 +3496,42 @@ module '(ice-9 q) '(make-q q-length))}." (syntax-violation 'require-extension "Not a recognized extension type" x))))) + +;;; Defining transparently inlinable procedures +;;; + +(define-syntax define-inlinable + ;; Define a macro and a procedure such that direct calls are inlined, via + ;; the macro expansion, whereas references in non-call contexts refer to + ;; the procedure. Inspired by the `define-integrable' macro by Dybvig et al. + (lambda (x) + ;; Use a space in the prefix to avoid potential -Wunused-toplevel + ;; warning + (define prefix (string->symbol "% ")) + (define (make-procedure-name name) + (datum->syntax name + (symbol-append prefix (syntax->datum name) + '-procedure))) + + (syntax-case x () + ((_ (name formals ...) body ...) + (identifier? #'name) + (with-syntax ((proc-name (make-procedure-name #'name)) + ((args ...) (generate-temporaries #'(formals ...)))) + #`(begin + (define (proc-name formals ...) + body ...) + (define-syntax name + (lambda (x) + (syntax-case x () + ((_ args ...) + #'((lambda (formals ...) + body ...) + args ...)) + (_ + (identifier? x) + #'proc-name)))))))))) + (define using-readline? diff --git a/module/srfi/srfi-9.scm b/module/srfi/srfi-9.scm index f9449a66f..ad9e95de1 100644 --- a/module/srfi/srfi-9.scm +++ b/module/srfi/srfi-9.scm @@ -64,38 +64,6 @@ (cond-expand-provide (current-module) '(srfi-9)) -(define-syntax define-inlinable - ;; Define a macro and a procedure such that direct calls are inlined, via - ;; the macro expansion, whereas references in non-call contexts refer to - ;; the procedure. Inspired by the `define-integrable' macro by Dybvig et al. - (lambda (x) - ;; Use a space in the prefix to avoid potential -Wunused-toplevel - ;; warning - (define prefix (string->symbol "% ")) - (define (make-procedure-name name) - (datum->syntax name - (symbol-append prefix (syntax->datum name) - '-procedure))) - - (syntax-case x () - ((_ (name formals ...) body ...) - (identifier? #'name) - (with-syntax ((proc-name (make-procedure-name #'name)) - ((args ...) (generate-temporaries #'(formals ...)))) - #`(begin - (define (proc-name formals ...) - body ...) - (define-syntax name - (lambda (x) - (syntax-case x () - ((_ args ...) - #'((lambda (formals ...) - body ...) - args ...)) - (_ - (identifier? x) - #'proc-name)))))))))) - (define-syntax define-record-type (lambda (x) (define (field-identifiers field-specs) -- cgit v1.2.3