I meant like this:

```
#lang racket/base
(require (for-syntax racket/base
                     syntax/parse)
         syntax/parse/define)

;; Run-time
(struct state (a b c d) #:transparent)
(define mt (state #f #f #f #f))
(define-simple-macro (set-field st:expr f:id v:expr)
  (struct-copy state st [f v]))
(define-simple-macro (set-field* f:id v:expr)
  (λ (st) (set-field st f v)))

;; Compile-time
(begin-for-syntax
  (define-struct modifier (f)))

(define-simple-macro (define-modifier (m . args) body)
  (begin
    (define-syntax m-f
      (syntax-parser [(_ args) #'body]))
  (define-syntax m (modifier #'m-f))))

(define-modifier (the-a-says x:string)
  (set-field* a x))
(define-modifier (the-b-says 'x:id)
  (set-field* b 'x))
(define-modifier (the-c-is x:string)
  (set-field* c x))
(define-modifier (the-d-looks-like x:nat)
  (set-field* d x))

(define-syntax-parser term
  [(_ ((~var m (static modifier? "state modifier")) . args))
   #:with f (modifier-f (attribute m.value))
   #'(f args)])

(define-syntax-parser program
  [(_) #'mt]
  [(_ x . more) #'((term x) (program . more))])

;; Example
(program
 (the-a-says "Aaah")
 (the-b-says 'Baah)
 (the-c-is "Caaah")
 (the-d-looks-like 42))
```

--
Jay McCarthy
Associate Professor @ CS @ UMass Lowell
http://jeapostrophe.github.io
Vincit qui se vincit.


On Thu, Dec 31, 2020 at 12:07 PM Sage Gerard <[email protected]> wrote:

> I didn't see an answer to my original question, but I still want to make
> sure I understood you before I rephrase. Thank you for the insights!
>
> By your three step suggestion, is something like this what you meant? I'm
> not sure I  understood Step 3. It seems like I still have to add new
> structure types and macros to define new terms, which is about as laborious
> as what I was doing with #:datum-literals and struct-copy.
>
> (module id racket/base
>   (require racket/format
>            (for-syntax racket/base syntax/parse))
>
>   (begin-for-syntax (struct item (name num)))
>
>   (define (record-item name num)
>     (~a num ". " name))
>
>   (define-syntax (term stx)
>     (syntax-parse stx
>       #:literals ([stmt item #:phase 1])
>       [(_ (stmt name:id num:exact-positive-integer))
>        #'(define name (record-item 'name num))]))
>
>   (define-syntax-rule (program x ...)
>     (begin (term x) ...)))
>
>
> *~slg*
>
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Thursday, December 31, 2020 9:45 AM, Jay McCarthy <
> [email protected]> wrote:
>
> Are you trying to take a macro argument and ensure that it is an
> expression? If so, then you can expand into `#%expression`
>
> https://docs.racket-lang.org/reference/__expression.html
>
> On the other hand, if you are trying to take a macro argument and ensure
> that it is NOT an expression... then that means that you know what it is
> allowed to be, so I don't think there's any better way than to just
> enumerate what it CAN be. I think I would use a syntax class that specifies
> the allowable patterns and then use that. For example, in my little
> teachlog language, I have the `term` syntax class for this purpose
>
> https://github.com/jeapostrophe/teachlog/blob/master/main.rkt#L119
>
> Looking at your code, I think what I would do is:
> 1) Define a phase-1 structure that represents one of these fields and an
> associated phase-0 function that records its values
> 2) Define `define-syntax` bindings for each particular field as an
> instance of these fields
> 3) Write `update` as a short `syntax-parse` that expects a list where the
> head is a static instance of the phase-1 structure and expands into an
> application of the associate phase-0 function on the arguments
>
> This would allow you to better abstract things so you don't have tie the
> `update` function to the particular fields.
>
> Jay
>
> --
> Jay McCarthy
> Associate Professor @ CS @ UMass Lowell
> http://jeapostrophe.github.io
> Vincit qui se vincit.
>
>
> On Wed, Dec 30, 2020 at 10:20 PM Sage Gerard <[email protected]> wrote:
>
>> I'm trying to learn how to restrict where expressions appear. Those
>> expressions might be procedure applications, *or* macros before
>> expansion.
>>
>> [1] shows a library I use to help me implement a collection pass for a
>> module language. To save you some reading, it uses syntax-parse with a
>> lengthy #:datum-literals. That's the only way I know how to restrict what
>> expressions appear in module context.
>>
>> One element of the #:datum-literals happens to share an identifier with a
>> bound procedure, so I expand the calls as-is in a module-level expression
>> [2][3]. I want that procedure to be applied ONLY in the module context, but
>> nothing in the language enforces that.
>>
>> I don't know what I don't know. Could I please get a link to a part of
>> the documentation that teaches me what I need to understand? I'm tied
>> between querying syntax properties for a fully expanded module, and writing
>> a second set of macros that somehow know where they should be. Not sure
>> which is best.
>>
>> [1]: https://github.com/zyrolasting/xiden/blob/master/pkgdef/expand.rkt
>> [2]:
>> https://github.com/zyrolasting/xiden/blob/master/pkgdef/expand.rkt#L111
>> [3]:
>> https://github.com/zyrolasting/xiden/blob/master/pkgdef/expand.rkt#L156
>>
>> *~slg*
>>
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Racket Users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/racket-users/bVbaZ_0mwFcWTIaeuwqMUr7TVY6Rhr5dusG9LkbT0gqW7gWIYAb8IOEUYnKQPIVR2ZrDGm9QMGnW-2YvYqw81oUJVCSCuwhuX_Wx2OGVG-w%3D%40sagegerard.com
>> <https://groups.google.com/d/msgid/racket-users/bVbaZ_0mwFcWTIaeuwqMUr7TVY6Rhr5dusG9LkbT0gqW7gWIYAb8IOEUYnKQPIVR2ZrDGm9QMGnW-2YvYqw81oUJVCSCuwhuX_Wx2OGVG-w%3D%40sagegerard.com?utm_medium=email&utm_source=footer>
>> .
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/AqmR-7s3hD8k0bf_kMXDsZzwswfEDWXltrNMX4L8EmghOzqZdXHsptRiSANiepcq-m_JBjriooGpx8PbJmu9Bppci68ViREo6un9Fv0uXM0%3D%40sagegerard.com
> <https://groups.google.com/d/msgid/racket-users/AqmR-7s3hD8k0bf_kMXDsZzwswfEDWXltrNMX4L8EmghOzqZdXHsptRiSANiepcq-m_JBjriooGpx8PbJmu9Bppci68ViREo6un9Fv0uXM0%3D%40sagegerard.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAJYbDakqC_Ymn9N5-FJ5KENG3zkfKno8go1%3DftPKoPctpbaYNg%40mail.gmail.com.

Reply via email to