ERights Home download / 0-8-24 
No Previous Sibling On to: SWT Support

Highlights of 0.8.24j


Changes to Kernel-E

Variable Definition Patterns
Experimental Extended "escape" Expression
Internal Changes to Scope Handling

Performance Improvements

Call-site Caching
Integers Are Typically Small
Most Objects Aren't a kind of Proxy
Expanding "extends" into Faster Code

Preparing for the Proposed "easy-return" Style

New "e.enable.easy-return" Property
Unary Prefix "^" for Returning Values

Non-Upwards Compatible Changes

Parsing Integers

Rune improvements

--help
--src

Bugs Closed

E implementation must use StrictMath, not Math
FlexSet is untamed
line numbers not reported for some problems
Stack Traces show many stack frames multiple times


Changes to Kernel-E

Variable Definition Patterns

The concept of a SlotGuard has disappeared. Instead, the guard after a ":" is now always a ValueGuard. The boundary between E and Kernel-E has moved:

  • In Kernel-E, the guard is now optional as well. (It used to default to ":any". If left out, it still acts like ":any", but is visibly distinct.)
  • Besides the old <name> and "var" <name> patterns, the "&" name pattern is now also part of Kernel-E.
def x := y
x is a final variable whose permanent value is the current value of y.
def x :int := y

x is final variable whose permanent value is the result, if any, of coercing the current value of y through the int guard. This definition has the same effect as

    (def x := int.coerce(y, null); y)
except that the original will be taken by many meta-level tools (like auditors) to declare approximately the "type" of x, whereas the expanded version leaves x "untyped".
var x := y

x is an assignable variable whose initial value is the current value of y.

  • &x obtains the implicitly-created SimpleSlot used to hold x's current value.
  • (x := z) is equivalent to ((&x).setValue(z); z), which always succeeds.
  • The expression x is equivalent to (&x).getValue(), which has no side effects and always succeeds.
var x :int := y
x is an assignable variable that may only hold the result, if any, of coercing values through the int guard. It's initial value is the result of coercing the current value of y.
  • &x obtains the implicitly-created SettableSlot used to hold x's current value.
  • (x := z) is equivalent to ((&x).setValue(z); z), which stores the coercion, if any, of z through int. On coercion failure, the value of x is unaffected.
  • The expression x is equivalent to (&x).getValue(), which has no side effects and always succeeds.
def &x := y
x is an indirect variable whose slot is the current value of y.
  • &x obtains this slot.
  • (x := z) is equivalent to ((&x).setValue(z); z), whatever that means according to that slot.
  • The expression x is equivalent to (&x).getValue(), whatever that means according to that slot.
def &x :sg := y
x is an indirect variable whose slot is the result, if any, of coercing the current value of y though the sg guard. This definition has the same effect as
    (def &x := sg.coerce(y, null); y)
except that the original will be taken by many meta-level tools (like auditors) to declare approximately the "type" of &x, whereas the expanded version leaves &x "untyped".

See the email thread rooted here for more.

Experimental Extended "escape" Expression

The new e.enable.escape-handler property can be turned on to experiment with the proposed extended escape expression.

It allows the escape expression, and the loop expressions which build on it -- "while", "for" -- to be optionally followed by an escape-handler. As of the 0.8.24j release, the optional escape-handler is written with the same syntax as the catch-clause of a try-catch block:

    "catch" pattern "{" expression "}"
An escape expression with an escape-handler is therefore written as
    escape ejector-pattern {
        body-expression
    } catch handler-pattern {
        handler-expression
    }
If such an escape expression, if the ejector is invoked during the execution of body-expression, body-expression is terminated, the handler-pattern is matched against the argument to the ejector, and the handler-expression is evaluated in the resulting scope.

In a while-loop or for-loop with a escape-handler, if the break ejector is called, the loop is exited and the argument to break is passed to the handler.

See the email thread rooted here for more.

Internal Changes to Scope Handling

We have changed the internal representation of Scopes in Kernel-E in order to close out bug "safeScope Mutability breaks confinement", and to implement auditors, but neither of these have yet happened.

Performance Improvements

We have now implemented most of the performance imrovements discussed in recent email. For reasons we don't yet understand, we are running about twice as fast as before. While this is nothing to sneeze at, the measurements our measurements had led us to expect a larger improvement.

Thanks to Chris Hibbert for providing a benchmark for evaluating the speedup. Unfortunately, this benchmark probably isn't representative. The speedup may be smaller on more typical code.

Thanks to Dean Tribble, Tyler Close, and Bill Frantz for various measurements and suggestions.

Call-site Caching

Familiar from Smalltalk implementations. Each "call site", i.e., static occurrence of a call-expression in E source code, now has a call-site-cache, remembering the last method looked up by that call. When this expression is next evaluated, it first does a quick check to see if the cached method is applicable to the new receiver. If so, it branches to the method with no hash table lookups.

Integers Are Typically Small

Prior to 0.8.24, the E implementation preferred to keep integers in BigInteger form. Now, if it will fit into an Integer, the E implementation prefers to keep it in Integer form. If not, then it still uses a BigInteger.

In addition, the integers in the range -128..127 are preallocated. If E needs to produce an integer in that range, it reuses a preallocated one rather than allocating a new one. Thanks to Greg Nelson for reminding us of this technique (used in some old Lisp implementations). It allows most of the same benefits as tagged pointers, but without needing to fight against the JVM's type system.

Most Objects Aren't a kind of Proxy

This refers to java.lang.reflect.Proxy, which is the magic Java class used to dynamically implement Java interfaces. Measurement had seemed to indicate that E's tables were bottlenecked on Ref.resolution/1, which was in turn bottlenecked on Proxy.isProxyClass.

Expanding "extends" into Faster Code

See the email thread rooted here for an explanation.

This "improvement" only resulted in a 1% speedup.

Preparing for the Proposed "easy-return" Style

The easy-return style was privately suggested by Dean. Dean, could I get you to explain it to the list? (I'll link to it from here.) Thanks.

New "e.enable.easy-return" Property

The new e.enable.easy-return property has two related effects:

It makes a left out method result guard default to the equivalent of :any, and it changes the expansion of "to" methods into primitive methods so that an explicit return is required to return a non-null value. Whereas

    to foo() { ... }
normally expands to
    method foo() :void { escape __return { ... } }
after a pragma.enable("easy-return"), it instead expands to
    method foo() { escape __return { ...; null } }

As with left-out variable guards, a left-out result guard is now represented as a distinct case in Kernel-E ((internally represented with a null).

Until this proposal is accepted, the printed form of Kernel-E is misleading. As seen above, when interpreted as an E program by current rules, the missing result guard will be taken to be equivalent to :void rather than :any, which is incorrect.

This proposal, if accepted, would be non-upwards compatible. Assuming we make this change, the transition plan is to go through a phase where only a more restrictive form of E is accepted by default -- one that means the same thing under either syntax. In this more restrictive form of E, result guards are always required, and if non-:void, a value must always be returned from a function or to-method by an explicit return. Until the matter is settled, and possibly even afterwards, published papers should stay within this more restrictive style. (See Paradigm Regained and the online version of The Ode.)

Unary Prefix "^" for Returning Values

The proposed style requires much more frequent use of the "return" keyword -- even more frequent than C or Java, since E uses lambda evaluation for instantiation. To avoid having this be an noisy syntactic burden, we introduce the unary prefix "^" operator as a synonym for "return".

Non-Upwards Compatible Changes

Parsing Integers

Code that used to say "<import:java.lang.Integer>.parseInt(string)" should now say "__makeInt(string)". The new form is not precision limited.

Rune improvements

--help

The "rune" command has a somewhat improved help system. Start with

    $ rune --help

--src

The previously reserved "--src" option to rune is now implemented. If you ask the new help system,

    $ rune --help --src

it says

Help on "--src":

    $ rune --src.<ext> <src> <arg>*    Interprets <src> as if from a file
                                       ending in ".<ext>".
    $ rune --src       <src> <arg>*    Equivalent to "--src.e <src> <arg>*".

For example, in a bash shell:

    $ rune --src 'println(interp.getArgs())' foo bar
    ["foo", "bar"]

    $ rune --src 'println(help)'       For E command line help.

For help on an individual extension, use "$ rune --help.<ext>"
For general Rune help, use "$ rune --help"

Bugs Closed

E implementation must use StrictMath, not Math
FlexSet is untamed
line numbers not reported for some problems
Stack Traces show many stack frames multiple times
 
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 download / 0-8-24 
No Previous Sibling On to: SWT Support
Download    FAQ    API    Mail Archive    Donate

report bug (including invalid html)

Golden Key Campaign Blue Ribbon Campaign