Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-12 Thread David Storrs
If you're willing to accept a low tech solution, might I suggest this:

$ perl -i.bak -lpe 's/\(foo/\(make-foo/g' *.rkt


Also, I'll self-plug and point you towards this:

#lang racket
(require struct-plus-plus )

(struct++ foo ([a real?]) (#:omit-reflection) #:prefab)

(define checked (foo++ #:a 7)) ; contract is checked

(define not-checked (foo 7)) ; contract is not checked

(writeln checked)
(writeln not-checked)

This defines the contracts using define/contract.  It's not clear to me if
that meets your needs, but hopefully it does.

On Mon, May 10, 2021 at 10:03 AM Sage Gerard  wrote:

> I hope so! That's what I understood option B to mean.
>
> I could adjust the define-message macro according to the info in Ryan and
> Phillip's attachments, but I'm not well-educated on trapping struct
> operations. Phillip: Your example and email gives me the impression that
> when you add a chaperone, you can proxy all struct operations, including
> the gap left by the chaperone for the constructor. Is that true?
>
> The macro I'd want has to preserve *all* characteristics of *all*
> generated struct bindings, which makes things tricky since the options for
> `struct` normally operate on a strict subset. e.g.
> #:[extra-]constructor-name seems to operate on the constructor alone, and
> the #:extra- variant does not preserve the match-expander/super-id
> characteristics. #:constructor-name is closer, but the original constructor
> id is no longer directly callable by the declaring module.
> On 5/10/21 7:05 AM, Hendrik Boom wrote:
>
> On Sun, May 09, 2021 at 10:23:34PM +, Sage Gerard wrote:
>
> I have a project with 57 prefab structure types. I need to construct 
> instances using a local contract (module level contracts do not fit my needs 
> here). Since I cannot define guards, the solution is easy enough.
>
> (struct foo (num) #:prefab)
> (define/contract make-foo (-> real? foo?) foo)
>
> Problem: I already have a few hundred constructor calls without
> contracts. I could either A) rewrite them all to use contracted
> constructors, or B) attach local contracts in a sweet spot so that I
> don't have to rewrite anything else.
>
> Is there any chance you could do the "rewriting" in a macro so you
> wouldn't actually have to change the few hundred constructor calls
> when you use option A)?
>
> -- hendrik
>
>
> I prefer option B, but it doesn't look like I can attach a local contract to 
> a constructor with `struct` alone, or even with an impersonator. When I hack 
> around to rebind or hide the constructor's identifier, I break compatibility 
> with `match` and `defstruct*`.
>
> If you were in my position, what would you do?
>
> --
>
> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com.
>
> --
> 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/20210510110509.cpg6jnil6th7xbsi%40topoi.pooq.com.
>
> --
> ~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/94e81fc9-e8a1-e677-bf0e-b49e597313b9%40sagegerard.com
> 
> .
>

-- 
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/CAE8gKofQDbSrOS1n-i7B-T0h78x%2Bz0NRdUkZx6-1T9FyxBspBQ%40mail.gmail.com.


Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-10 Thread Sage Gerard
I hope so! That's what I understood option B to mean.

I could adjust the define-message macro according to the info in Ryan and 
Phillip's attachments, but I'm not well-educated on trapping struct operations. 
Phillip: Your example and email gives me the impression that when you add a 
chaperone, you can proxy all struct operations, including the gap left by the 
chaperone for the constructor. Is that true?

The macro I'd want has to preserve all characteristics of all generated struct 
bindings, which makes things tricky since the options for `struct` normally 
operate on a strict subset. e.g. #:[extra-]constructor-name seems to operate on 
the constructor alone, and the #:extra- variant does not preserve the 
match-expander/super-id characteristics. #:constructor-name is closer, but the 
original constructor id is no longer directly callable by the declaring module.

On 5/10/21 7:05 AM, Hendrik Boom wrote:

> On Sun, May 09, 2021 at 10:23:34PM +, Sage Gerard wrote:
>
>> I have a project with 57 prefab structure types. I need to construct 
>> instances using a local contract (module level contracts do not fit my needs 
>> here). Since I cannot define guards, the solution is easy enough.
>>
>> (struct foo (num) #:prefab)
>> (define/contract make-foo (-> real? foo?) foo)
>>
>> Problem: I already have a few hundred constructor calls without
>> contracts. I could either A) rewrite them all to use contracted
>> constructors, or B) attach local contracts in a sweet spot so that I
>> don't have to rewrite anything else.
>
> Is there any chance you could do the "rewriting" in a macro so you
> wouldn't actually have to change the few hundred constructor calls
> when you use option A)?
>
> -- hendrik
>
>> I prefer option B, but it doesn't look like I can attach a local contract to 
>> a constructor with `struct` alone, or even with an impersonator. When I hack 
>> around to rebind or hide the constructor's identifier, I break compatibility 
>> with `match` and `defstruct*`.
>>
>> If you were in my position, what would you do?
>>
>> --
>>
>> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com
>> .
>
> --
> 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/20210510110509.cpg6jnil6th7xbsi%40topoi.pooq.com
> .

--
~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/94e81fc9-e8a1-e677-bf0e-b49e597313b9%40sagegerard.com.


Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-10 Thread Hendrik Boom
On Sun, May 09, 2021 at 10:23:34PM +, Sage Gerard wrote:
> I have a project with 57 prefab structure types. I need to construct 
> instances using a local contract (module level contracts do not fit my needs 
> here). Since I cannot define guards, the solution is easy enough.
> 
> (struct foo (num) #:prefab)
> (define/contract make-foo (-> real? foo?) foo)
> 
> Problem: I already have a few hundred constructor calls without 
> contracts. I could either A) rewrite them all to use contracted 
> constructors, or B) attach local contracts in a sweet spot so that I 
> don't have to rewrite anything else.

Is there any chance you could do the "rewriting" in a macro so you 
wouldn't actually have to change the few hundred constructor calls
when you use option A)?

-- hendrik

> 
> I prefer option B, but it doesn't look like I can attach a local contract to 
> a constructor with `struct` alone, or even with an impersonator. When I hack 
> around to rebind or hide the constructor's identifier, I break compatibility 
> with `match` and `defstruct*`.
> 
> If you were in my position, what would you do?
> 
> --
> 
> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com.

-- 
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/20210510110509.cpg6jnil6th7xbsi%40topoi.pooq.com.


Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-09 Thread Sage Gerard
Almost forgot, just in case someone asks: I want to avoid checking for 
invariant violations when I print. That would entail checking a bunch of values 
in accumulated program output, where it would be awkward to do something 
non-printing related, let alone raise an error. When I am printing logs, all 
invariant violations come down to what went a constructor, because all program 
output is encoded as prefab structures. That's why I want to raise any errors 
on instantiation.

On 5/9/21 8:55 PM, Sage Gerard wrote:

> Of course, if you're okay with a longer email. Before that, thank you both 
> for volunteering your time to code something out. I enjoyed running into a 
> `define-module-boundary-contract` in the wild for the first time.
>
> I sometimes print output in a (read)able form because I like analyzing my 
> logs. The data I print includes prefab structures, with type ids matching the 
> topic they cover or the statements they make. You can see that I declare 
> prefab structure (sub)types cutely labeled "messages" here. [1]
>
> The idea is that I can either print (for example) a $package:output:built 
> instance as a localized string, or just toss the instance itself into 
> writeln. When I read instances back from a port, the struct accessors will 
> help me filter and match. Hopefully all this shows where my head is.
>
> Now for the problem. Look at [2], but don't worry about what it means. I just 
> wanted you to see the constructor call in the exception handler. If I made a 
> mistake and wrote that line such the exception was placed directly in the 
> instance, then I wouldn't be able to (read) that instance back later! I 
> cannot allow #<...> forms in my output, or some symbol soup that happens to 
> be readable, but doesn't constitute the value it used to be.
>
> TL;DR I want to protect the invariant `(equal? V (read (open-input-string (~s 
> V` for each V I print to an output port.
>
> Finally, as to why I didn't want the module boundary contract. The module 
> that declares prefab structure types is also primarily responsible for 
> creating all instances of those types. I rarely cross module boundaries when 
> applying the constructors.
>
> [1]: https://github.com/zyrolasting/xiden/blob/master/package.rkt#L49
> [2]: https://github.com/zyrolasting/xiden/blob/master/security.rkt#L100
>
> On 5/9/21 8:02 PM, Philip McGrath wrote:
>
>> Here's another minimally-tested sample implementation. A more robust 
>> solution might try to chaperone the struct type, as well, to protect 
>> reflective access to the constructor—but I wonder if that really makes sense 
>> when you are working with prefab structs. If you can explain more about your 
>> requirements, it might be possible to suggest better approaches.
>>
>> On Sun, May 9, 2021 at 7:57 PM Ryan Culpepper  wrote:
>>
>>> I'm not clear on what constraints you're working under with respect to 
>>> modules, but hopefully you can adapt this to your needs.
>>>
>>> One option is to use a combination of `define-module-boundary-contract` (or 
>>> `define/contract`) and `define-match-expander` to bind a name that can be 
>>> used as a contracted constructor and as a match pattern. (If you want to 
>>> extend the struct type, though, you still need to use the real one.)
>>>
>>> Another option would be to "forge" a new compile-time struct-info based on 
>>> the original struct-info but replacing the constructor.
>>>
>>> Minimally tested sample implementations attached.
>>>
>>> Ryan
>>>
>>> On Mon, May 10, 2021 at 12:23 AM Sage Gerard  wrote:
>>>
 I have a project with 57 prefab structure types. I need to construct 
 instances using a local contract (module level contracts do not fit my 
 needs here). Since I cannot define guards, the solution is easy enough.

 (struct foo (num) #:prefab)
 (define/contract make-foo (-> real? foo?) foo)

 Problem: I already have a few hundred constructor calls without contracts. 
 I could either A) rewrite them all to use contracted constructors, or B) 
 attach local contracts in a sweet spot so that I don't have to rewrite 
 anything else.

 I prefer option B, but it doesn't look like I can attach a local contract 
 to a constructor with `struct` alone, or even with an impersonator. When I 
 hack around to rebind or hide the constructor's identifier, I break 
 compatibility with `match` and `defstruct*`.

 If you were in my position, what would you do?

 --

 ~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 
 

Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-09 Thread Sage Gerard
Of course, if you're okay with a longer email. Before that, thank you both for 
volunteering your time to code something out. I enjoyed running into a 
`define-module-boundary-contract` in the wild for the first time.

I sometimes print output in a (read)able form because I like analyzing my logs. 
The data I print includes prefab structures, with type ids matching the topic 
they cover or the statements they make. You can see that I declare prefab 
structure (sub)types cutely labeled "messages" here. [1]

The idea is that I can either print (for example) a $package:output:built 
instance as a localized string, or just toss the instance itself into writeln. 
When I read instances back from a port, the struct accessors will help me 
filter and match. Hopefully all this shows where my head is.

Now for the problem. Look at [2], but don't worry about what it means. I just 
wanted you to see the constructor call in the exception handler. If I made a 
mistake and wrote that line such the exception was placed directly in the 
instance, then I wouldn't be able to (read) that instance back later! I cannot 
allow #<...> forms in my output, or some symbol soup that happens to be 
readable, but doesn't constitute the value it used to be.

TL;DR I want to protect the invariant `(equal? V (read (open-input-string (~s 
V` for each V I print to an output port.

Finally, as to why I didn't want the module boundary contract. The module that 
declares prefab structure types is also primarily responsible for creating all 
instances of those types. I rarely cross module boundaries when applying the 
constructors.

[1]: https://github.com/zyrolasting/xiden/blob/master/package.rkt#L49
[2]: https://github.com/zyrolasting/xiden/blob/master/security.rkt#L100

On 5/9/21 8:02 PM, Philip McGrath wrote:

> Here's another minimally-tested sample implementation. A more robust solution 
> might try to chaperone the struct type, as well, to protect reflective access 
> to the constructor—but I wonder if that really makes sense when you are 
> working with prefab structs. If you can explain more about your requirements, 
> it might be possible to suggest better approaches.
>
> On Sun, May 9, 2021 at 7:57 PM Ryan Culpepper  wrote:
>
>> I'm not clear on what constraints you're working under with respect to 
>> modules, but hopefully you can adapt this to your needs.
>>
>> One option is to use a combination of `define-module-boundary-contract` (or 
>> `define/contract`) and `define-match-expander` to bind a name that can be 
>> used as a contracted constructor and as a match pattern. (If you want to 
>> extend the struct type, though, you still need to use the real one.)
>>
>> Another option would be to "forge" a new compile-time struct-info based on 
>> the original struct-info but replacing the constructor.
>>
>> Minimally tested sample implementations attached.
>>
>> Ryan
>>
>> On Mon, May 10, 2021 at 12:23 AM Sage Gerard  wrote:
>>
>>> I have a project with 57 prefab structure types. I need to construct 
>>> instances using a local contract (module level contracts do not fit my 
>>> needs here). Since I cannot define guards, the solution is easy enough.
>>>
>>> (struct foo (num) #:prefab)
>>> (define/contract make-foo (-> real? foo?) foo)
>>>
>>> Problem: I already have a few hundred constructor calls without contracts. 
>>> I could either A) rewrite them all to use contracted constructors, or B) 
>>> attach local contracts in a sweet spot so that I don't have to rewrite 
>>> anything else.
>>>
>>> I prefer option B, but it doesn't look like I can attach a local contract 
>>> to a constructor with `struct` alone, or even with an impersonator. When I 
>>> hack around to rebind or hide the constructor's identifier, I break 
>>> compatibility with `match` and `defstruct*`.
>>>
>>> If you were in my position, what would you do?
>>>
>>> --
>>>
>>> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com](https://groups.google.com/d/msgid/racket-users/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com?utm_medium=email_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/CANy33qmngGoVoAok6%2BR885jkh8MroMqYHpOd6XtjCSH7iiESQA%40mail.gmail.com](https://groups.google.com/d/msgid/racket-users/CANy33qmngGoVoAok6%2BR885jkh8MroMqYHpOd6XtjCSH7iiESQA%40mail.gmail.com?utm_medium=email_source=footer).

--

Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-09 Thread Philip McGrath
Here's another minimally-tested sample implementation. A more robust
solution might try to chaperone the struct type, as well, to protect
reflective access to the constructor—but I wonder if that really makes
sense when you are working with prefab structs. If you can explain more
about your requirements, it might be possible to suggest better approaches.


On Sun, May 9, 2021 at 7:57 PM Ryan Culpepper 
wrote:

> I'm not clear on what constraints you're working under with respect to
> modules, but hopefully you can adapt this to your needs.
>
> One option is to use a combination of `define-module-boundary-contract`
> (or `define/contract`) and `define-match-expander` to bind a name that can
> be used as a contracted constructor and as a match pattern. (If you want to
> extend the struct type, though, you still need to use the real one.)
>
> Another option would be to "forge" a new compile-time struct-info based on
> the original struct-info but replacing the constructor.
>
> Minimally tested sample implementations attached.
>
> Ryan
>
>
> On Mon, May 10, 2021 at 12:23 AM Sage Gerard  wrote:
>
>> I have a project with 57 prefab structure types. I need to construct
>> instances using a *local* contract (module level contracts do not fit my
>> needs here). Since I cannot define guards, the solution is easy enough.
>> (struct foo (num) #:prefab)
>> (define/contract make-foo (-> real? foo?) foo)
>>
>> Problem: I already have a few hundred constructor calls without
>> contracts. I could either A) rewrite them all to use contracted
>> constructors, or B) attach local contracts in a sweet spot so that I don't
>> have to rewrite anything else.
>>
>> I prefer option B, but it doesn't look like I can attach a local contract
>> to a constructor with `struct` alone, or even with an impersonator. When I
>> hack around to rebind or hide the constructor's identifier, I break
>> compatibility with `match` and `defstruct*`.
>>
>> If you were in my position, what would you do?
>> --
>>
>> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com
>> 
>> .
>>
> --
> 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/CANy33qmngGoVoAok6%2BR885jkh8MroMqYHpOd6XtjCSH7iiESQA%40mail.gmail.com
> 
> .
>

-- 
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/01000179539521f3-7e3fc7cf-409e-4574-8917-5d2ef798fa1c-00%40email.amazonses.com.


prefab-transformer.rkt
Description: Binary data


Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-09 Thread Ryan Culpepper
I'm not clear on what constraints you're working under with respect to
modules, but hopefully you can adapt this to your needs.

One option is to use a combination of `define-module-boundary-contract` (or
`define/contract`) and `define-match-expander` to bind a name that can be
used as a contracted constructor and as a match pattern. (If you want to
extend the struct type, though, you still need to use the real one.)

Another option would be to "forge" a new compile-time struct-info based on
the original struct-info but replacing the constructor.

Minimally tested sample implementations attached.

Ryan


On Mon, May 10, 2021 at 12:23 AM Sage Gerard  wrote:

> I have a project with 57 prefab structure types. I need to construct
> instances using a *local* contract (module level contracts do not fit my
> needs here). Since I cannot define guards, the solution is easy enough.
> (struct foo (num) #:prefab)
> (define/contract make-foo (-> real? foo?) foo)
>
> Problem: I already have a few hundred constructor calls without contracts.
> I could either A) rewrite them all to use contracted constructors, or B)
> attach local contracts in a sweet spot so that I don't have to rewrite
> anything else.
>
> I prefer option B, but it doesn't look like I can attach a local contract
> to a constructor with `struct` alone, or even with an impersonator. When I
> hack around to rebind or hide the constructor's identifier, I break
> compatibility with `match` and `defstruct*`.
>
> If you were in my position, what would you do?
> --
>
> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%40sagegerard.com
> 
> .
>

-- 
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/CANy33qmngGoVoAok6%2BR885jkh8MroMqYHpOd6XtjCSH7iiESQA%40mail.gmail.com.


prefab-contract.rkt
Description: Binary data