Alright, I think I see how I confused myself.

I load modules in my language dynamically. I use sandboxed evaluators instead 
of dynamic-require. I used replace-context on the entire module body to make 
the evaluators see values that I defined and provided during expansion. The 
problem was that in doing so, I coupled what a single module provided with the 
module language itself. I could not see a way to create a syntax-binding-set 
from an existing syntax object. Going off [1], I could only start with a blank 
set and add individual bindings. I used my blunt instrument and moved on 
because I was trying to design the language around how module evaluators 
worked, not the other way around.

Thank you again, Jay. Your examples helped me see what I was doing.

[1]: 
https://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-binding-set%29%29

~slg

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, January 1, 2021 12:51 PM, Sage Gerard <[email protected]> wrote:

> 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](https://groups.google.com/d/msgid/racket-users/xhOV-HJg6LAeonQMsnR0YYbbZjGOE8R6e5comR-j0RFDcc0liOMYs3-evzakJI7pOlFFNVzqPy0bguWls1pZHVkhas8NtexR2M2aLn0ujVc%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/UEc8PUyir7lY_62bnHCS8vOkIQGiHoq5BEsxL2EhLpPevCDCURLjj4myIaYZtSbXJ25wl-CCMWFRJXzg2zDdVSvhPGSi_IKAFuGuQn44Pws%3D%40sagegerard.com.

Reply via email to