Sam Mason wrote:
> On Mon, Jun 04, 2007 at 09:51:55AM -0400, Jonathan S. Shapiro wrote:
>> On Mon, 2007-06-04 at 11:23 +0100, Sam Mason wrote:
>>> On Sun, Jun 03, 2007 at 10:16:47PM -0400, Jonathan S. Shapiro wrote:
>>>> 2. Captured by-reference arguments are legal in *escaping* closures,
>>>> but a *copy* of the by-reference value is made at the time of
>>>> closure construction.
>>>>
>>>> This yields sensible behavior and preserves type safety, but it
>>>> introduces behavioral subtlety that will confuse programmers.
>>> I think this would confuse the semantics a lot, apparently simple
>>> changes to an expression could change its behaviour considerably.
>> No more so (or less so) than any procedure call that is passed a
>> reference.
>
> OK, I think I completely missed what you meant when you said copying
> the "by-reference value".
Even I thought the closed variable is copied by value. This is exactly
similar to the r-value getting copied as a result of being passed
by-value to closure-construction operator.
> I've just noticed a problem with these by-references values though.
> That of calling a "by-reference" method with the reference to an element
> of a union and changing the tag of the union invalidating the type of
> the element inside the "by-reference" function. I can only think of
> very contrived bits of code that would trigger it, but it would break
> type safety.
I did not understand this problem, can you please explain. In BitC, the
de-constructed value of a tagged union (resulting from a switch -- see
`x' below) is not a first class entity. It can only appear on the LHS of
a selection (.) operator, and it is a *copy* of the original union value
on which we are performing a switch.
For example:
(defunion (list 'a) nil (cons car:'a cdr:(list 'a)))
(define (f z:(by-ref bool) y)
(set! y nil)
(set! x #f))
(let ((y:(mutable (list (mutable bool))) (cons #t nil)))
(switch y x
(nil ())
(cons (f x.car y)))
In the above example, both assignments in the function f are legal and
safe. The only legal way to mutate a union value is to set! the entire
union value, not individual fields in one constructor. Of course, if the
constructors contain a value of reference type, it is legal to mutate
the contents of the cell named by that reference.
Even if there is a problem with unions, it might be easy to fix by
restricting the usage of de-constructed variables. In fact, not all
values / expressions can be used in a pass-by reference position (ex:
the literal 1 cannot be passed by reference).
>> The reason I want this is that there is an idiom for writing constructor
>> and re-initializer procedures that requires it. The problem at present
>> is that there is no clean way to re-initialize a data structure that is
>> unboxed, nor any way to characterize field get/set as a procedure call
>> within the language.
>
> yes, which is why (I believe) references got added to C++. I've never
> seen a way to do this safely without some heavy type-level stuff, like
> alias types. This is a big step from what you've got at the moment
> though.
This proposal does not introduce the generic & operator. We can only
have a down-flow of stack addresses passed by reference as far as I can
see. This can be thought of as a degenerate case of region-analysis. I
am missing the safety problem you are referring to, that would require a
stronger static analysis.
Swaroop.
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev