allow prop:template-metafunction value to be a function

This commit is contained in:
AlexKnauth 2019-02-16 11:53:15 -05:00 committed by Suzanne Soy
parent b25cf850fa
commit ad97ade071
3 changed files with 48 additions and 17 deletions

View File

@ -351,11 +351,17 @@ invalid binding list.
((defthing prop:template-metafunction struct-type-property?)
(defthing template-metafunction? (-> any/c boolean?)))]{
A structure type property, and the associated predicate. The
property value is either an identifier, or the index of a field containing an
identifier. The identifier should be bound to the run-time metafunction. The
run-time metafunction should accept a syntax object representing its use, and
produce a new syntax object as a result.
A structure type property, and the associated predicate. The property value is
one of:
@itemlist[
@item{an identifier bound to a run-time metafunction}
@item{the index of a field containing such an an identifier}
@item{a procedure that takes an instance of the structure and produces
such an identifier}]
The identifier's run-time metafunction should accept a syntax object
representing its use, and produce a new syntax object as a result.
When an identifier is bound as syntax to a structure instance with this
property, it is treated as a template metafunction as if the identifier had

View File

@ -128,4 +128,17 @@
(define-syntax mf5 (my-template-metafunction5))
(check-equal? (syntax->datum (template (x (mf5 3) z)))
'(x 6 z)))
'(x 6 z)))
(begin-for-syntax
(struct my-template-metafunction6 (proc-id)
#:property prop:template-metafunction
(lambda (self) (my-template-metafunction6-proc-id self))))
(test-case "use custom prop:template-metafunction with a function"
(define (myproc6 stx)
(syntax-case stx ()
[(_ n) #`#,(* 2 (syntax-e #'n))]))
(define-syntax mf6 (my-template-metafunction6 (quote-syntax myproc6)))
(check-equal? (syntax->datum (template (x (mf6 3) z)))
'(x 6 z)))

View File

@ -4,13 +4,20 @@
(rename prop:template-metafunction? template-metafunction?)
template-metafunction-accessor))
;; The prop:template-metafunction structure type property can contain an
;; identifier bound to the run-time metafunction procedure, or the index of a
;; field containing such an identifier.
;; The prop:template-metafunction structure type property can contain one of:
;; - an identifier bound to the run-time metafunction procedure
;; - the index of a field containing such an identifier
;; - a function that takes the structure instance and produces such an
;; identifier
;; At run-time, when processing the template, the syntax object whose first
;; element is a metafunction identifiers is passed to this metafunction
;; procedure.
;; Internally, the value inside the property will be stored as a function
;; that takes the structure instance and produces the identifier,
;; so the first two cases of that `one-of` will be "normalized" to the
;; function case by `prop:template-metafunction-guard`.
(define-values (prop:template-metafunction-guard)
(lambda (val struct-type-info-list)
(if (exact-nonnegative-integer? val)
@ -36,13 +43,18 @@
(if (if (syntax? val) (symbol? (syntax-e val)) #f)
;; Identifier bound to the run-time metafunction procedure.
(λ (_instance) val)
;; Otherwise, raise an error.
(raise-argument-error
'prop:template-metafunction-guard
(string-append "an identifier, or an exact non-negative integer designating"
" a field index within the structure that should contain an"
" identifier.")
val)))))
;; Otherwise, expect a function of one argument
(if
(if (procedure? val) (procedure-arity-includes? val 1) #f)
val
;; Otherwise, raise an error.
(raise-argument-error
'prop:template-metafunction-guard
(string-append "an identifier, or an exact non-negative integer designating"
" a field index within the structure that should contain an"
" identifier, or a procedure of one argument that produces"
" an identifier")
val))))))
(define-values (prop:template-metafunction
prop:template-metafunction?