Alright, thank you for sticking with this. I'm refactoring now. ~slg
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Friday, January 1, 2021 11:56 AM, Jay McCarthy <[email protected]> wrote: > I’d imagine that you would only provide program and the modifiers. Everything > well work out :) > > Jay > > On Fri, Jan 1, 2021 at 11:44 AM Sage Gerard <[email protected]> wrote: > >> Ah, I see. Thank you for that! >> >> As for rephrasing my original question: If program were provided as >> #%module-begin, I expect that syntax-protect would prevent a programmer from >> using out the phase-0 bindings. But in my version of the program Racket >> would keep complaining about unbound identifiers unless I provided >> everything. >> >> The thing is, I don't want the user to be able to write things like >> set-field* in their program just because I'm forced to provide it. >> That's why I'm trying to figure out a way to say "Ok, this module language >> happens to include set-field*, but set-field* must only appear >> in module context, or not at all." >> >> ~slg >> >> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ >> On Thursday, December 31, 2020 1:40 PM, Jay McCarthy >> <[email protected]> wrote: >> >>> 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/nV9CQYlVP_TDoZiSKSx9xKAATgrOhrG2z9Q5erXF04cza6pfHq3kUIPiTEUZX3HNOJeFVDrcbG-f6qHOYTT79yS6JPYKDM5KbtAdCbWoMdM%3D%40sagegerard.com](https://groups.google.com/d/msgid/racket-users/nV9CQYlVP_TDoZiSKSx9xKAATgrOhrG2z9Q5erXF04cza6pfHq3kUIPiTEUZX3HNOJeFVDrcbG-f6qHOYTT79yS6JPYKDM5KbtAdCbWoMdM%3D%40sagegerard.com?utm_medium=email&utm_source=footer). > > -- > > -- > Jay McCarthy > Associate Professor @ CS @ UMass Lowell > http://jeapostrophe.github.io > Vincit qui se vincit. -- 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/xhOV-HJg6LAeonQMsnR0YYbbZjGOE8R6e5comR-j0RFDcc0liOMYs3-evzakJI7pOlFFNVzqPy0bguWls1pZHVkhas8NtexR2M2aLn0ujVc%3D%40sagegerard.com.

