gexp: Compilers can now provide an "expander".
* guix/gexp.scm (<gexp-compiler>)[expand]: New field. (default-expander, lookup-expander): New procedures. (define-gexp-compiler): Add second pattern to allow for the definition of both a compiler and an expander. (gexp->sexp)[reference->sexp]: Call 'lookup-expander' and use its result.
This commit is contained in:
parent
b5fed903c4
commit
ebdfd776f4
|
@ -126,27 +126,46 @@
|
||||||
|
|
||||||
;; Compiler for a type of objects that may be introduced in a gexp.
|
;; Compiler for a type of objects that may be introduced in a gexp.
|
||||||
(define-record-type <gexp-compiler>
|
(define-record-type <gexp-compiler>
|
||||||
(gexp-compiler predicate lower)
|
(gexp-compiler predicate lower expand)
|
||||||
gexp-compiler?
|
gexp-compiler?
|
||||||
(predicate gexp-compiler-predicate)
|
(predicate gexp-compiler-predicate)
|
||||||
(lower gexp-compiler-lower))
|
(lower gexp-compiler-lower)
|
||||||
|
(expand gexp-compiler-expand)) ;#f | DRV -> M sexp
|
||||||
|
|
||||||
(define %gexp-compilers
|
(define %gexp-compilers
|
||||||
;; List of <gexp-compiler>.
|
;; List of <gexp-compiler>.
|
||||||
'())
|
'())
|
||||||
|
|
||||||
|
(define (default-expander thing obj output)
|
||||||
|
"This is the default expander for \"things\" that appear in gexps. It
|
||||||
|
returns its output file name of OBJ's OUTPUT."
|
||||||
|
(match obj
|
||||||
|
((? derivation? drv)
|
||||||
|
(derivation->output-path drv output))
|
||||||
|
((? string? file)
|
||||||
|
file)))
|
||||||
|
|
||||||
(define (register-compiler! compiler)
|
(define (register-compiler! compiler)
|
||||||
"Register COMPILER as a gexp compiler."
|
"Register COMPILER as a gexp compiler."
|
||||||
(set! %gexp-compilers (cons compiler %gexp-compilers)))
|
(set! %gexp-compilers (cons compiler %gexp-compilers)))
|
||||||
|
|
||||||
(define (lookup-compiler object)
|
(define (lookup-compiler object)
|
||||||
"Search a compiler for OBJECT. Upon success, return the three argument
|
"Search for a compiler for OBJECT. Upon success, return the three argument
|
||||||
procedure to lower it; otherwise return #f."
|
procedure to lower it; otherwise return #f."
|
||||||
(any (match-lambda
|
(any (match-lambda
|
||||||
(($ <gexp-compiler> predicate lower)
|
(($ <gexp-compiler> predicate lower)
|
||||||
(and (predicate object) lower)))
|
(and (predicate object) lower)))
|
||||||
%gexp-compilers))
|
%gexp-compilers))
|
||||||
|
|
||||||
|
(define (lookup-expander object)
|
||||||
|
"Search for an expander for OBJECT. Upon success, return the three argument
|
||||||
|
procedure to expand it; otherwise return #f."
|
||||||
|
(or (any (match-lambda
|
||||||
|
(($ <gexp-compiler> predicate _ expand)
|
||||||
|
(and (predicate object) expand)))
|
||||||
|
%gexp-compilers)
|
||||||
|
default-expander))
|
||||||
|
|
||||||
(define* (lower-object obj
|
(define* (lower-object obj
|
||||||
#:optional (system (%current-system))
|
#:optional (system (%current-system))
|
||||||
#:key target)
|
#:key target)
|
||||||
|
@ -157,19 +176,33 @@ OBJ must be an object that has an associated gexp compiler, such as a
|
||||||
(let ((lower (lookup-compiler obj)))
|
(let ((lower (lookup-compiler obj)))
|
||||||
(lower obj system target)))
|
(lower obj system target)))
|
||||||
|
|
||||||
(define-syntax-rule (define-gexp-compiler (name (param predicate)
|
(define-syntax define-gexp-compiler
|
||||||
system target)
|
(syntax-rules (=> compiler expander)
|
||||||
body ...)
|
"Define NAME as a compiler for objects matching PREDICATE encountered in
|
||||||
"Define NAME as a compiler for objects matching PREDICATE encountered in
|
gexps.
|
||||||
gexps. BODY must return a derivation for PARAM, an object that matches
|
|
||||||
PREDICATE, for SYSTEM and TARGET (the latter of which is #f except when
|
In the simplest form of the macro, BODY must return a derivation for PARAM, an
|
||||||
cross-compiling.)"
|
object that matches PREDICATE, for SYSTEM and TARGET (the latter of which is
|
||||||
(begin
|
#f except when cross-compiling.)
|
||||||
(define name
|
|
||||||
(gexp-compiler predicate
|
The more elaborate form allows you to specify an expander:
|
||||||
(lambda (param system target)
|
|
||||||
body ...)))
|
(define-gexp-compiler something something?
|
||||||
(register-compiler! name)))
|
compiler => (lambda (param system target) ...)
|
||||||
|
expander => (lambda (param drv output) ...))
|
||||||
|
|
||||||
|
The expander specifies how an object is converted to its sexp representation."
|
||||||
|
((_ (name (param predicate) system target) body ...)
|
||||||
|
(define-gexp-compiler name predicate
|
||||||
|
compiler => (lambda (param system target) body ...)
|
||||||
|
expander => default-expander))
|
||||||
|
((_ name predicate
|
||||||
|
compiler => compile
|
||||||
|
expander => expand)
|
||||||
|
(begin
|
||||||
|
(define name
|
||||||
|
(gexp-compiler predicate compile expand))
|
||||||
|
(register-compiler! name)))))
|
||||||
|
|
||||||
(define-gexp-compiler (derivation-compiler (drv derivation?) system target)
|
(define-gexp-compiler (derivation-compiler (drv derivation?) system target)
|
||||||
;; Derivations are the lowest-level representation, so this is the identity
|
;; Derivations are the lowest-level representation, so this is the identity
|
||||||
|
@ -704,15 +737,12 @@ and in the current monad setting (system type, etc.)"
|
||||||
(or n? native?)))
|
(or n? native?)))
|
||||||
refs)))
|
refs)))
|
||||||
(($ <gexp-input> (? struct? thing) output n?)
|
(($ <gexp-input> (? struct? thing) output n?)
|
||||||
(let ((target (if (or n? native?) #f target)))
|
(let ((target (if (or n? native?) #f target))
|
||||||
|
(expand (lookup-expander thing)))
|
||||||
(mlet %store-monad ((obj (lower-object thing system
|
(mlet %store-monad ((obj (lower-object thing system
|
||||||
#:target target)))
|
#:target target)))
|
||||||
;; OBJ must be either a derivation or a store file name.
|
;; OBJ must be either a derivation or a store file name.
|
||||||
(return (match obj
|
(return (expand thing obj output)))))
|
||||||
((? derivation? drv)
|
|
||||||
(derivation->output-path drv output))
|
|
||||||
((? string? file)
|
|
||||||
file))))))
|
|
||||||
(($ <gexp-input> x)
|
(($ <gexp-input> x)
|
||||||
(return x))
|
(return x))
|
||||||
(x
|
(x
|
||||||
|
|
Loading…
Reference in New Issue