[plt-dev] macro error messages
On 03/29/2010 09:45 PM, Jon Rafkind wrote:
> On 03/29/2010 03:19 PM, Matthew Flatt wrote:
>> At Mon, 29 Mar 2010 15:06:00 -0600, Jon Rafkind wrote:
>>> Can these error messages be reviewed as well?
>>>
>>> On 03/26/2010 03:55 PM, Jon Rafkind wrote:
>>>> Can this error message
>>>>
>>>> illegal use of syntax
>>>>
>>>> be changed to
>>>>
>>>> illegal application of a transformer. transformers must be
>>>> functions
>>>> that accept one argument.
>>>>
>>>> To reproduce this error use this code:
>>>>
>>>> (define-syntax (foo a b c) #'1)
>>>> (foo)
>>>>
>>>> There is only one change to be made in eval.c line ~6284
>> Like the suggested `syntax-case' change, I think this one assumes the
>> perspective of a macro implementor with a particular goal.
>>
>> In general, an identifier bound with `define-syntax' doesn't have to be
>> bound to a transformer procedure. A non-transformer binding may be
>> intentional and useful, such as when a pattern variable is bound by
>> `syntax-case'.
>>
>> In such cases, it's a good idea to make the binding also include a
>> transformer procedure (perhaps through `prop:procedure') and refine the
>> "illegal use of syntax" error message --- just like it's a good idea to
>> cover more cases in `syntax-case' or `syntax-parse' and give good error
>> messages. But if a programmer doesn't do that, then "bad syntax" or
>> "illegal use of syntax" is about all that can be said automatically.
>>
>>
>
> I don't follow you. The C code has a check to see if the thing being
> applied is a procedure with an arity of 1. If it is anything else, the
> error "illegal use of syntax" will be raised. So my suggestion is for
> the error message to mirror the check being done.
Here is some simple code that throws a nicer error for macros when they
are used incorrectly. Probably not useful enough for planet, so I'll
just post it here in case anyone is interested. This works correctly
with `syntax-local-value'.
macro-data.ss:
#lang scheme
(provide (all-defined-out))
(define-struct macro (name function) #:property prop:procedure
(lambda (self . args)
(let ([function (macro-function self)])
(if (not (procedure-arity-includes? function (length
args)))
(raise-syntax-error (macro-name self) "wrong
number of arguments supplied" args)
(apply function args)))))
define-syntax.ss:
#lang scheme
(require (for-syntax scheme/base
"macro-data.ss"))
(require (prefix-in original: (only-in scheme/base define-syntax)))
(define-syntax (define-syntax stx)
(syntax-case stx ()
[(_ (id args ...) expr0 expr ...)
#'(original:define-syntax id (make-macro 'id (lambda (args ...)
expr0 expr ...)))]
[(_ (id args ... . rest-args) expr0 expr ...)
#'(original:define-syntax id (make-macro 'id (lambda (args ... .
rest) expr0 expr ...)))]
[(_ rest ...)
#'(original:define-syntax rest ...)]))
Then just (require "define-syntax.ss") and away you go.