Am Do., 15. Nov. 2018 um 17:55 Uhr schrieb Marc Nieper-Wißkirchen <
marc.nie...@gmail.com>:

> I would like to alias an identifier in Guile. By this, I mean the
> following: Given a bound identifier `x', I want to lexically introduce
> another identifier `y' with the same binding as `x' so that `x' and `y'
> become `free-identifier=?'.
>
> The following is one use case: I have written a macro `custom-quasiquote`,
> which has a similar syntax and does similar things as `quasiquote' does.
> Because I would like to use the special reader syntax for `quasiquote', I
> would do:
>
> (letrec-syntax ((quasiquote <custom-quasiquote-transformer>))
>   <body>)
>
> In the <body>, whenever I write ``<template>', my
> <custom-quasiquote-transformer> is being applied to <template>.
>
> There may be parts in the <body> where I would like to use Scheme's
> quasiquotation. One try is to surround these parts with:
>
> (let-syntax ((quasiquote (identifier-syntax scheme-quasiquote)))
>   <expression>)
>
> Here, `scheme-quasiquote' is bound to `quasiquote' as exported by
> `(guile)'. However, this solution is not correct as the `quasiquote' local
> to <expression> is not `free-identifier=?' to `scheme-quasiquote'. Thus
> quasiquotations containing quasiquotes (that should become auxiliary
> syntax) won't work right.
>
> What I really need is to make the inner `quasiquote' a true alias of
> `scheme-quasiquote' (or rather to restore the binding of `quasiquote' in
> <expression> to what the binding outside the outer `letrec-syntax' was).
>
> Chez Scheme has `alias' for this purpose:
> https://cisco.github.io/ChezScheme/csug9.5/syntax.html#./syntax:h10.
>
> What can I do in Scheme? If this is currently impossible, please consider
> this post as a feature request for `alias' or a similar binding construct.
> :-)
>

Typo. "What can I in GUILE?" was the question I intended to ask. :-)

I gave it a try to implement `define-alias' in Guile. My first
approximation to a solution was to add a clause like

((define-alias-form)
  (let ((id (wrap value w mod))
        (label (id-var-name e w mod)))
    (extend-ribcage! ribcage id label)
    (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))

to `expand-body' in `psyntax.scm'. (A similar clause is added to
`expand-top-sequence' and `syntax-type' is extended to recognize
`define-alias' and return `define-alias-form' for the type.)

With identifiers lexically bound in the same module, my change does what it
is supposed to do. The following test passes:

(pass-if "alias is free-identifier=?"
  (let ((x #t))
    (define-syntax foo
      (syntax-rules (x)
        ((foo x) #t)
        ((foo _) #f)))
    (let ()
      (define-alias y x)
      (foo y))))

My code, however, doesn't work when the aliased identifier is global and/or
comes from another module: The following test fails:

(pass-if-equal "alias is free-identifier=? with globals"
    '(1 5)
  (let ()
    (define-alias comma unquote)
    `(1 (comma (+ 2 3)))))

I see that my attempt to bind the identifier `y' to `x's label (if given
`(define-alias y x)') is too naive. I have taken a look at `free-id=?' and
`resolve-identifier' in `psyntax.scm', but the way modules are handled in
`psyntax.scm' is still new to me. Thus I'm glad about any hints.

-- Marc

Reply via email to