Loose type checking in E

Mark S. Miller markm@erights.org
Sat, 17 Oct 1998 12:16:42 -0700

At 01:05 AM 10/17/98 -0400, Tyler Close wrote:
>The Actor theory depends on partial orderings of events in order to perform
>real calculations. I can see how your Promise objects will enforce the
>activation ordering; however, I see no mechanism for enforcing the arrival

I'm glad your getting into Actor Semantics, but whatever correspondence
you're seeing between E and Actors is not the correspondence I intend.  The
E programmer is not supposed to be enforcing the ordering laws, rather, all
E programs should have no choice but to obey the ordering laws.  (true for
the locality laws as well, but not relevant to this discussion.)  Promises
are icing that don't help wrt the fundamental properties.  Perhaps you mean
that E's implementation or semantics has mechanisms which enforce these
laws, but in fact, E simply contains no mechanism (and is guaranteed not
to) that would enable these laws to be violated.

So rather than speculate on what mechanisms need to be added to E to get to
Actors, I present below a subset of Kernel E, "Act-E", that I claim is a
pure Actor language.  To then demonstrate that "E is an Actor language", we
then need only answer four questions: 

	1) Is Act-E in fact an Actor language?
	2) Do any of the additional features of Kernel-E beyond Act-E 
	   threaten any of the Actor properties?
	3) Is E merely a set of syntactic extensions added to Kernel E, and 
	   defined only by expansion to Kernel E?  
	4) Are these four the only questions we needed to ask?

Step #3 is trivially seen to be true by examining the implementation of E
in terms of Kernel E.

Step #2 would be very tedious to prove in its entirety, and isn't even true
in some justified ways, but all this needs to subject of other email.

Here we present Act-E with some starting arguments about Step #1.

As a refresher, here are the syntactic constructs of Kernel E (whose
semantics are given in http://erights.org/doc/elang/elangmanual.pdf ):

verb:               Identifier
method:             to verb ( pattern*, ) {
matcher:            "match" pattern "{"

pattern:            param | suchThat | tuple
param:              definer | ignore
definer:            Identifier ":" expr
ignore:             "_"
suchThat:           pattern "?" expr
tuple:              "[" pattern*, "]" "+" pattern

expr:               /*any of the following:*/

literal:              BigIntegerLiteral | DoubleLiteral
                    | StringLiteral | CharLiteral
noun:                Identifier
slot:                "&" noun
assign:              noun ":=" expr
sequence:            expr ";" expr
call:                expr verb "(" expr*, ")"
send:                expr "<-" verb "(" expr*, ")"
matchBind:           expr "=~" pattern
init:                "define" pattern ":=" expr
methodical:          "define" param "{"
plumbing:            "define" param matcher
scope:               "scope"
throw:               "throw" expr
escape:              "escape" param "{" expr "}"
compound:            "{" expr "}"
loop:                "loop" "{" expr "}"
if:                  "if" "(" expr ")" "{" 
                     "}" "else" "{"
try:                 "try" "{"
                     "}" ("catch" pattern "{"
                     "}")? ("finally" "{"

Here's Act-E:

verb:               Identifier
method:             to verb ( param*, ) {
matcher:            "match" pattern "{"

pattern:            param | tuple
param:              definer
definer:              Identifier ":" "final"
                    | Identifier ":" "settable"
tuple:              "[" param*, "]" "+" param

expr:               /*any of the following:*/

literal:              BigIntegerLiteral | DoubleLiteral
                    | StringLiteral | CharLiteral
noun:                Identifier
assign:              noun ":=" expr
sequence:            expr ";" expr
send:                expr "<-" verb "(" expr*, ")"
methodical:          "define" "_" "{"
plumbing:            "define" "_" matcher

Notice that Act-E doesn't contain the synchronous "call", or any flow
control at all beyond "sequence", message dispatch, and asynchronous
"send".  Act-E's "send" is further restricted to always return "null".
(Consider "send" to be a void returning function, as one would normally
expect of a one-way asynchronous message sending construct.)

The partial-ordering guarantees of Kernel E are waived for Act-E.  Since I
haven't yet explained these guarantees on this list, I probably don't yet
need to explain what it means to drop them.  (For old E folks, Act-E is in
the pre-poE E tradition.)

The definer is restricted to specifying either "final" or "settable" as its
SlotMaker expression, accordingly, in Act-E these are keywords rather than
expressions.  Act-E does not provide for implicit sharing of side effects,
so only a final variables may be used within an object (a "methodical" or
"plumbing") expression to refer to a definition outside the object
expression.  Only a settable variable may appear on the left side of an

This language could probably be further simplified while remaining a
universal actor language -- we probably don't need both "method" and
"matcher", and we probably don't need both "methodical" and "plumbing".
But let's start with this and see if we've got an Actor language with all
the Actor properties, with Promises removed and nothing new added.  Once
(if?) we're satisfied with that, then we'll return to Kernel E.  Please
fire away.

	Avoid needless semantics,