Jonathan S. Shapiro wrote:
> Here is another possible way to handle this (I am simply thinking out
> loud here):
> 
> 1. Adopt the view that the tags are arity-0 enumeration constructors, as
> I described above.
> 
> 2. Assign field names to the tags, so my example above would now change
> to:
> 
> (defrepr dr
>    (swizzled: (tag yes no)
>     d:double
>     direction: (tag left right)
>     (case ((swizzled yes) (i:int32 j:int32))
>           ((swizzled no)(b:bool)))
>     (case ((or (swizzled yes)
>                (direction left)) (k:int32)))))

If the cases do not completely cover the tag values, I guess it will 
result in a structure containing only the invariant positions.

For example:
  (defrepr dr
     (swizzled: (tag yes no)
      d:double
      direction: (tag left right)
      (case ((and (swizzled yes)
                  (direction left)) (k:int32))))

However, we need to check for overlap for the same tags within the same 
case, because at a time, only one leg of the case must be active.

For example:
  (defrepr dr
     (swizzled: (tag yes no)
      d:double
      direction: (tag left right)
      (case ((and (swizzled yes)
                  (direction left)) (k:int32))
           ((or (swizzled yes)
                  (direction left)) (p:int64))))

This is especially true if we move to the design where we allow things like:
  (defrepr dr
     (swizzled: (tag bool)
      d:double
      swizzled2: (tag int32)
      ... )

Also, in this case, we may need an otherwise clause.

> 3. Take your strategy, but drop the wrapping defunion. Instead, convert
> them into:
> 
>     (defstruct __con_dr-swizzled-right
>         swizzled:__tag_dr_swizzled
>         d:double
>         direction:__tag_dr_direction
>         i:int32 j:int32))
> 
> 4. Now introduce a special rule into the type checker stating that if
> "dr" is a DEFREPR type and "__con_dr_xxxxx" is a structure type, then
> 
>     dr <- __con_dr_xxxxx
> 
> is a legal assignment/binding (but not the other way).

This can be done, I don't see any problem at this time.

>>So,
>>(reprcase e ((id swizzled right  id.d))
>>              (otherwise 0.0))
>>
>>||
>>V
>>
>>(reprcase e ((id:__dr-swizzled-right swizzled right  id.d))
>>              (otherwise 0.0))
>>
>>As you have noted in the spec, we may do this for all unions as well.
> 
> Not quite, but I figured out this morning how to deal with the last
> complication, and it becomes very easy if the tag slots have names.

Are you saying that there is a problem for repcase, or for unions?


> Not quite, but I figured out this morning how to deal with the last
> complication, and it becomes very easy if the tag slots have names.
> Given a DEFREPR of the form: 
>   (defrepr something
>          ...
>          tagname : (tag id1 id2)
>          (case ((tagname id1) ...)
>                ...)
>          ...)
> 
> we can add a declaration of some sort indicating that the tag can be
> Cardelified. Perhaps:
> 
>   (defrepr something
>          ...
>          tagname : (tag id1 id2)
>          (declare (cardelli tagname))
>          (case ((tagname id1) ...)
>                ...)
>          ...)
> 
> This applies only to the CASE form that positionally follows the tag.

Doesn't this also require that no other case forms use the tag values?
Unless there is a compelling example, I actually liked the fact that 
defreprs will not be Cardellified. Or, are you are thinking about a way 
to move towards defreprs and remove defstructs and defunions?


> I also thought that this could be made to work, but it has strange
> consequences. Consider:
> 
>   (let ((yes 1))
>     (dr yes 2.0 left 5 6))
> 
> where the intention is that this will turn into:
> 
>   (__con_dr-swizzled-right __tag_dr-swizzled-yes 2.0
>         __tag-dr-direction-left 5 6)
> 
> but it is not clear why the original "yes" tag is not hidden here. I
> believe that this is essentially the same ambiguity that arises for
> constructors in applicative position elsewhere in the type checker.
> 
> Can you articulate a clear-cut story for this, or if not, should we
> consider making the initializer labels bound in the defining scope.

Actually, lifting them to the defining scope does not help. That will 
prevent a top-level definition from overriding that name, but a 
let/letrec definition is able to override value constructors or other 
bindings.

However, if the tags are treated as value matching,

  (defrepr dr
     (swizzled: (tag bool)
      d:double
      swizzled2: (tag int32)
      ... )

(dr #t 2.0 .. )

(let ((yes #t))
   (dr yes 2.0 ... )

then there is nothing to bind, and this issue goes away.

>>Is the rule:
>>
>>>A case form may make reference to any tagid that is mentioned in any 
>>>lexically preceding tag form within the same defrepr
>>
>>necessary? Conceptually, the compiler can process all tag forms first, 
>>so that all legs can make use all tags. I think, in the case of GDT 
>>entries, some fields come before the tag.
> 
> 
> Hmm. Now that is an *excellent* question, and I need to think about
> that. It follows from the ability to flatten to structures that you hvae
> identified, and that I had completely failed to see. Even if we decide
> to do named fields for tags, we can adopt the rule that they "hoist to
> the left in preorder" for purpose of forming constructor arguments.
> 
> However, I think that we must impose the requirement that a CASE form
> can only reference a tag that appears in a lexically containing BODY
> form. Otherwise it will not be possible to do case-dispatch reliably in
> REPRCASE.

I agree.


Swaroop.
_______________________________________________
bitc-dev mailing list
bitc-dev@coyotos.org
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to