(More brain dump.)

"Context" is implemented as type coercion calls, implicitly inserted
by the compiler.

There are five types used in these calls.  The "..." below denote
the positions where these contexts typically occur, using common
Perl 5 operations as examples:

    Void              # ...; 1;
    Single[::of]      # chdir ...;
    Plural[::of]      # reverse ...;
    RW[Single[::of]]  # chop ...;
    RW[Plural[::of]]  # shift ...;

The compiler is responsible to translate sigils, "is rw" and "is context"
notations into the types above.  In the object model, the five types are
represented as roles.

Denotationally, the signature for = and := are as below:

    proto infix:<=> (RW[::a]: ::a) --> RW[::a]
    proto infix:<:=> (Plural[RW[::a]]: Plural[RW[::b]]) --> Plural[RW[::a]]

Note that both forms only have one invocant; dispatch is decided by the
left-hand side's type.

Each builtin type "does" exactly one of the five types above.

    Int         does Single[Int];        # 3
    Rule        does Single[Rule];       # rx{123}
    Args        does Plural[Any];        # \(1,2,3)
    Sigs        does Plural[Any];        # :(1,2,3)
    Seq[::a]    does RW[Plural[::a]];    # (1,2,3)
    Range[::a]  does Plural[::a];        # (1..3)
    Scalar[::a] does RW[Single[::a]];    # $IN
    Array[::a]  does RW[Plural[::a]];    # @ARGS
    Hash[::a]   does RW[Plural[::a]];    # %ENV
    List[::a]   does RW[Plural[::a]];    # ($IN,@ARGS,%ENV)

Note that the list-associative infix:<,> has two variants: If all its arguments
does RW, it returns a List; otherwise it returns a Seq.  This matches the Perl5
behaviour:

    perl -e '($_, $_) = 3'; # okay
    perl -e '($_, 7) = 3';  # error

For user-defined concrete classes without any "does" clauses, we automatically
derive a "does Single[::t]" for it.

During compile time, the local type inferencer looks up coerce:<as> calls for
each expression that does not match its expected type:

    proto coerce:<as> (::from, ::to) --> ::to

The availability of these coercion forms are checked at compile time, not
runtime, hence it's subject to constant folding.  If the programmer wants
to make "3 = 4" work, a corresponding form must be declared at compile time:

    multi coerce:<as> (Int, RW[Single[Int]]) {...}

otherwise it raises a compile time error.

Reply via email to