Alright, thank you for sticking with this. I'm refactoring now.

~slg

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, January 1, 2021 11:56 AM, Jay McCarthy <jay.mccar...@gmail.com> 
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 <s...@sagegerard.com> 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 
>> <jay.mccar...@gmail.com> 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 <s...@sagegerard.com> 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 
>>>> <jay.mccar...@gmail.com> 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 <s...@sagegerard.com> 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 racket-users+unsubscr...@googlegroups.com.
>>>>>> 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 racket-users+unsubscr...@googlegroups.com.
>>>> 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 racket-users+unsubscr...@googlegroups.com.
>> 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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/xhOV-HJg6LAeonQMsnR0YYbbZjGOE8R6e5comR-j0RFDcc0liOMYs3-evzakJI7pOlFFNVzqPy0bguWls1pZHVkhas8NtexR2M2aLn0ujVc%3D%40sagegerard.com.

Reply via email to