=head1 NAME

Context and Coersion - The interplay of the method call and the call chain

=head1 DESCRIPTION

We've flip-flopped back and forth on whether type and context are
equivalent.  In this proposal, they are not, but every context is also a
type.  It is also a runtime concept, except when we can optimize it away
(like in the case of a known signature for a method).  Context is a
argument that is passed in along with a call.  For now, until we get to
coersion, the return type of that call must be covariantly compatible
(i.e. a subtype of) the context.   This will allow us to overload
multimethods based on return type, but it will sidestep the paradoxes
that are often associated with that.

So how do we compute the context to pass to a call?  It comes from one
of the "signature functions" of the routine.  These operate on invocant
lists.  For the routine:

    proto foo(A $a, B $b: C $c: D $d E $e) {...}

The invocant lists are C<()> (empty), C<($a,$b)>, C<($c)>  (and not
C<($d, $e)>).  The first one is always empty. Every routine has a
C<context> method that returns an object that contains the contexts for
the first invocant set and another method for the second set.  For
example, in the call:

    foo($a, $b, $c, $d, $e);

To find the context of C<$d>, you would write something like:

    &foo.context().context($a,$b).context($c)[0];

(Of course these wouldn't be real method calls when used by the runtime,
because they would have to do context chaining too, and to find those
you'd have to do method calls, etc. etc. etc.)

For methods whose signatures are not known at all at compile time, the
context object would have to tell you how big the next set of invocants
is also.

Let's look at a standard paradox in multimethods that dispatch on return
types:

    multi doit(--> Int) { 42 }
    multi doit(--> Str) { "hello world" }
    
    multi tryit(Int $x) { say "Got an int" }
    multi tryit(Str $x) { say "Got a str" }

    tryit(doit());

Which variant of C<tryit()> gets called?  Well, execute C<doit()> to
find out.  But in order to know in which context C<doit()> is executed,
we have to know which variant of C<tryit()> we're going to call.  Both
variants of C<tryit()> are perfectly consistent, so we can't pick one to
call.

In order to solve this paradox, we just use the system outlined above.
C<tryit()> has no proto, so it defaults to:

    proto tryit(Any $x) {...}

So C<&tryit.context[0]> is C<Any>.  This is passed as an argument to
C<doit()>, resulting in an ambiguous multimethod call, and the program
dies.

This is all simple and expected, which is a good thing.  One of the
interesting results of this system is that C<is lazy> parameters can
only be non-invocants, because if they were invocants, they would be
evaluated immediately upon the call to C<&foo.context>.

=head2 Singular and Plural

Perl has a concept of "list context", in which multiple lists get
flattened together and passed as a single argument.  How does that work
in this system?

The context hierarchy is rooted with a tagged union: 

    union Context (Singular {}, Plural {})   # made-up syntax

That is, every context is either C<Singular> or C<Plural>, and I<they
have no common supercontext>!.  It is of course illegal to return
something C<Singular> when your context is C<Plural> and vice-versa.  If
you have a function whose signature looks like:

    proto foo(*@a) {...}

Then the call C<&foo.context[$n]> for any nonnegative integer C<$n> will
return some subtype of C<Plural>.  When the C<foo()> routine gets its
arguments, it will concatenate all of them into the C<@a> array.

The alert reader may notice a violation of the principle of
orthogonality here.  The context system allows, say, the third argument
to a routine to be in C<Singular> context and all the rest to be
C<Plural>.  However, the language (or at least the standard declaration
system) does not.  According to the language, once one parameter is
C<Plural>, all following parameters are C<Plural>.

=head2 References

We can at long last understand references.  We know that C<Scalar> and
C<Array> are containers.  The thing that has perplexed us is the idea
that:

    (\@array).push(42);

Works.  The reference doesn't have a C<push> method, so it must be
delegating.  But in fact this is not the case.

Every time you mention a variable in an rvalue context[1], you are
calling the container's C<fetch()> method.  This method is polymorphic
on context.  That is, in C<Singular> context, C<Scalar>s fetch the value
they contain, and in C<Plural> context they fetch a singleton C<List> of
they value contained.  In C<Singular> context, C<Array>s fetch
I<themselves> and in C<Plural> context they fetch a C<List> of the
values in the array  (that is, they don't fetch themselves in C<Plural>
context, because C<Array> objects are singular).

Finally, the C<\> operator simply puts the variable in lvalue context,
so that C<fetch()> is not called.  This still leaves the one remaining
hole:

    my $x = \\1;

That should not return "1 itself", but rather a reference to a scalar to
a reference to a scalar containing 1.  How come?  Well, the fundamental
thing to realize is that the C<\> operator works differently on
variables and on non-variables.  For non-variables, it puts the value in
C<Singular> context, creates an anonymous scalar and returns it.

Also note that:

    @array.push(42)

Still works, because method calls impose a C<Singular> context on their
invocant.

=head2 Assignment

What about assignment?  That is an example of a method whose
non-invocant types change based on the type of the invocant, which we
know is okay from the system described in the first part of this
proposal.  For the container interface:

    role Container {
        method infix:<=> (None $value) {...}  # [2]
    }

And then for the C<Scalar> and C<Array> container interfaces:

    role Scalar {
        does Container;
        method infix:<=> ($value) {...}
    }
    role Array {
        does Container;
        method infix:<=> (*@value) {...}
    }

Which gives the context-propagation that epitomizes C<=>.

[1] This document is supposed to explain context, so I can't just
handwave over that.  Have a nice day.   (XXX)

[2] Multis require that if a variant A is more specific than a variant
B, then all non-invocant parameters of A must in fact be I<more general>
than the corresponding parameters of B.  That allows us to give the
C<$value> parameter the type C<None> (not allowing assignment at all
into a general container), and if anything is known about the container,
the compiler can assume a more general type.

=head2 What's in a Context?

At the beginning of the proposal, I said that type and context are not
the same thing.  But exactly how are they different?  Every context is a
type, and they share the same subtype relations.  However, the context
tree has a constraint:  No multiple inheritance[3].  We need this so we
can do well-defined multi dispatch on contexts[4].

Recall that we also required that there be no common supercontext of
C<Singular> and C<Plural> (and there are no contexts that are not
subtypes of one of these two).  This means that operators need only
decide what to do in those two contexts and the dispatch is completely
well-defined.  Subs by default do the same thing in both contexts and
propagate the decision to their return value, which will eventually
propagate to something that will make the decision. 

In order to define a type to be a context, declare it with C<is context>
and derive from some other context (both of these things are necessary):

    class Foo does Int is context {...}
    class Bar does Plural is context {...}

When you introduce a new context, you must be sure that you don't derive
from two other contexts (if you do, the compiler will reject your
program).  Perhaps there is a way to set the "primary context" of a type
derived from two contexts, so that the subtype relation will ignore the
other when doing context calculations:

    class IntStr does Int does Str is context(Str) {...}

The reason that explicit marking of C<is context> is required is so that
we don't kill multiple inheritance altogether.  You're allowed to
multiply inherit, as long as all contexts you inherit from form a chain
of subtypes (A <: B <: C <: ...).  Basically, you can't be an C<Int> and
a C<Str> at once; you can't be a C<Ref> and a C<Plural> at once, etc.
Classes and roles by default are C<Singular>.  It is unclear how to
create a C<Plural> type, but there should be a way (C<Plural> might
have some mandatory interface).

[3] Formally, if A <: B and A <: C then B <: C or C <: B.

[4] In order to do well-defined multi dispatch, you must be sure that
the variant you pick is more specific than any other matching variant,
or the context was too general to decide.  The thing we want to avoid is
having a context that is I<too specific> to decide; equivalently, that
it is possible to define a completely unambiguous dispatch.  In the
language of logic:

Given a variant's context type C and its return value r <: C, another
variant's context type D and its return value s <: D, and the current
context cxt. Show that if both variants match, then one must be more
specific than the other; i.e. that if r <: cxt and s <: cxt then C <: D,
D <: C, or C <: cxt and D <: cxt (the context was too general).

Proof:  By the "no multiple inheritance" constraint in [3], r <: cxt and
r <: C implies cxt <: C or C <: cxt.  Similarly, cxt <: D or D <: cxt.
By cases:

    if cxt <: C and cxt <: D then (by [3]) C <: D or D <: C.
    if cxt <: C and D <: cxt then D <: C
    if C <: cxt and cxt <: D then C <: D
    C <: cxt and D <: cxt was a goal

=head2 Coersion

We defined what scalars and arrays do in the two base contexts
C<Singular> and C<Plural>.  But what happens when the context is more
specific, and the value that the scalar holds does not match?  This
violates the guarantee that the return has to be a subtype of the
context.  Perl could just fail (and does in general), but there is one
out:  C<< &*COERCE >>[5].  This gets called whenever a value is not a
subtype of the context it is in.  Just define it as a regular
return-value-polymorphic function:

    multi *COERCE (MyString $s --> Str) {
        $s.string_val;
    }

Incidentally, this single-invocant multi also allows you to define
C<COERCE> as a method.

[5] Note that it isn't C<< coerce:<as> >>, as it's not really a
syntactic category at all; it's just infix.  Better to have a callback
sub and let the syntax transform into it.

=head2 What needs to be done

How is lvalue and rvalue encoded in context?  How is a hash different
from an array?
