ERights Home enative 
Back to: ENative: Compiling Objects x On to: ENative: Compiling Patterns

Compiling Expressions


E is an expression language, but, unfortunately, C++ is not. To deal with this mismatch, we compile E using one of two functions:

  • FOR_VALUE(EExpr) => resultVarName; outputs C++ statements
  • FOR_EFFECT(EExpr); outputs C++ statements

 

DefineExpr

Special Case: Pattern defines only a single variable
e`def @var :@slotMakerExpr := @expr`
C++
FOR_EFFECT
def resultName := FOR_VALUE(expr)
MUST_MATCH(patt, resultName)
FOR_VALUE
//same
Example
def a := c + d
Ref result := c.call(&DoAdd, d);
Ref a = result;

 

General Case
e`def @patt := @expr`
C++
FOR_EFFECT
def resultName := FOR_VALUE(expr)
DECLARE_TEMPS(patt)
MUST_MATCH(patt, resultName)
ACTUALS_FROM_TEMPS(patt)
FOR_VALUE
//same
Example
def [a, b] := c + d
Ref result := c.call(&DoAdd, d);
Ref aTemp;
Ref bTemp;
ListMustMatch(&aTemp, &bTemp, result);
Ref a = aTemp;
Ref b = bTemp;

 

"def" patt ":=" rValue.

Match patt against the value of rValue.  Neither patt nor rValue may
use any variables defined by the other.  This allows their scopes to
be order independent.
 

//If patt is a FinalPattern, then it works according to the "def"
//rules above.  Otherwise match against temporary variables.  If match
//succeeds, initialize the actual local variables to the temporaries.
//Anywhere it fails, throw the (XXX to-be-specified) suitable
//exception.  Since the actual variable would then never come into
//scope, they need not be defined and initialized.
 
 

CallExpr

General Case
e`@recip.@verb(@arg0,...)`
C++
FOR_EFFECT
def recipName := FOR_VALUE(recip)
def arg0Name := FOR_VALUE(arg0)
...
cpp`$recipName.call(&$DoVerb, $arg0Name, ...);`
FOR_VALUE
def recipName := FOR_VALUE(recip)
def arg0Name := FOR_VALUE(arg0)
...
def resultName := newTemp()
cpp`Ref $resultName := $recipName.call(&$DoVerb, $arg0Name, ...);`
Example
a + b
Ref result = a.call(&DoAdd, b);

Eval left to right, then synchronously call the verb method of the value of recip with the values of the args.

SendExpr

General Case
e`@recip <- @verb(@arg0,...)`
C++
FOR_EFFECT
def recipName := FOR_VALUE(recip)
def arg0Name := FOR_VALUE(arg0)
...
cpp`$recipName.sendOnly(&$DoVerb, $arg0Name, ...);`
FOR_VALUE
def recipName := FOR_VALUE(recip)
def arg0Name := FOR_VALUE(arg0)
...
def resultName := newTemp()
cpp`Ref $resultName := $recipName.send(&$DoVerb, $arg0Name, ...);`
Example
a <- add(b)
Ref result = a.send(&DoAdd, b);

Like call, but asks that recip do the operation <i>eventually</i>, in its own turn.  

EscapeExpr

General Case
e`escape @hatch { @body }`
C++
FOR_EFFECT
 
FOR_VALUE
 
Example
def result := escape break {
    loop {
        if (foo()) {
            break(x)
        }
    }
}
Ref result;
Ejector * ejector = new Ejector();
Ref break = ejector.ref();
try {
    while(true) {
        if (test(foo.call(&DoRun))) {
            break.call(&DoRun, x);
        }
    }
} catch (Ejection *ej) {
    result = ejector->result(ej);
} finally {
    ejector->disable();
}

Bind hatch to an escape hatch.  If the escape hatch's run/1 is called during the execution of body, the escape expression will be exited early, and the run argument will be the value.  If run/0 is called, it's as if run(null) were called.

HideExpr

e`{ @ body }`

Evaluate body, but hide all variable names it defines from the surrounding scope.  

Only has an effect on the compiler's scope calculation.  Generates no code.

IfExpr

General Case
e`if (@query) { @then } else {@els }`
C++
FOR_EFFECT
def queryName := FOR_VALUE(query)
cpp`if (test($queryName)) {
    ${FOR_EFFECT(then)}
} else {
    ${FOR_EFFECT(els)}
}
FOR_VALUE
def queryName := FOR_VALUE(query)

def resultName := newTemp()
cpp`Ref $resultName;
if (test($queryName)) {
    ${def name0 := FOR_VALUE(then)}
    cpp`$resultName = $name0;
} else {
    ${def name1 := FOR_VALUE(els)}

    cpp`$resultName = $name1;
}
Example
 
 

Evaluate test to a boolean.  If true, the value is the evaluation of then.  Else the value is the evaluation of els.

Not yet dealt with: then evaluates in the scope of query, els does not.

LiteralExpr

This value is the value of the expression.
 

  E C++
Unicode Character Literal
'c'
Ref('c')
String
"foo"
Ref("foo")
boolean
true
Ref(true)
false
Ref(false)
-2**30 <= Integer < 2 ** 30
1234
Ref(1234)
BigInteger
1000000000000
BigInteger.call(&DoFromString,
                Ref("1000000000000"))
float64
3.14159
Ref(3.14159)

LoopExpr

General Case
e`loop { @body }`
C++
FOR_EFFECT
cpp`while (true) {
    ${FOR_EFFECT(body)}
}
FOR_VALUE

//same

Example
 
 

Execute body repeatedly forever (or until stopped by other means).

Not yet formatted, edited, or made readable

But does contain useful content. Proceed past this point at your own risk.

MatchBindExpr

specimen "=~" patt

Match patt against the value of specimen.  Say whether it matches.
 

Ref specimen = TRANSLATE(specimen);
boolean result = true;
Ref local1;
...
do {
    //match specimen against patt, binding to temporary variables as
    //we go.  Anywhere we fail, we do:
        result = false;
 break;
    //After all matching steps are completed, we fall through to
    //binding the actual variables:
    local1 = temp1;
    ...
} while(false);
if (!result) {
    local1 = local2 = ... = //appropriate broken ref
}
//result is value of MatchBindExpr
 
 

ScopeExpr

"meta" "scope"

Reifies the current runtime scope as a runtime scope object.

Object visitScopeExpr();
 
 

SeqExpr

first "\n" second

Do first, then evaluate to the result of second.
 

TRANSLATE(first);
TRANSLATE(second);
 
 

MetaExpr

"meta" "(" varName ")"

varName must be the paramName of an enclosing object-expression or
plumbing-expression.  This returns the EMeta giving meta-level
access to that object.

Object visitMetaExpr(NounExpr noun);
 
 

CatchExpr

"try" "{" attempt "}" "catch" patt "{" catcher "}"

Evaluate attempt.  If it completes successfully, then its value is the
value of the catch-expression.  If it throws an exception, match it
against patt.  If it succeeds, evaluate to the evaluation of catcher.
Otherwise rethrow the exception.
 

Ref result;
try {
    result = TRANSLATE(attempt);
} catch (Ref &problem) {
    if (TRANSLATE(`$problem =~ $patt`)) {
 result = TRANSLATE(catcher);
    } else {
 throw problem;
    }
}
//result is value of Catch expression
 

 

FinallyExpr

"try" "{" attempt "}" "finally" "{" unwinder "}"

Evaluate attempt.  On the way out, whether by successful completion or
abrupt termination (throw or escape), in all cases evaluate the
unwinder before leaving.  If attempt succeeds, then the value of the
finally-expression is the value of attempt.
 

Ref result;
try {
    result = TRANSLATE(attempt);
} finally {
    TRANSLATE(unwinder);
}
//result is value of Finally expression
 
 
 
 

 

 
Unless stated otherwise, all text on this page which is either unattributed or by Mark S. Miller is hereby placed in the public domain.
ERights Home enative 
Back to: ENative: Compiling Objects x On to: ENative: Compiling Patterns
Download    FAQ    API    Mail Archive    Donate

report bug (including invalid html)

Golden Key Campaign Blue Ribbon Campaign