| Java
Layers Home
JL Download
Installation Notes
Release Notes
Quick
Reference
Code Generation
|
|
JL
0.37
The limitations and restrictions described for Release .21b still
apply for this release, but the following enhancements and changes were
made:
- Fixed constructor propagation bug.
- Made -JavaCompAll the default compiler option. Added
-JavaCompRoot compiler option for support of old default behavior,
which passes only the root generated source file to javac.
JL 0.35
The limitations and restrictions described for Release .21b still
apply for this release, but the following enhancements and changes were
made:
- Race condition between jlc and javac processes eliminated.
- Improper scoping of exception variable in catch clauses fixed.
- Better error handling for duplicate field declarations.
JL 0.33
The limitations and restrictions described for Release .21b still
apply for this release, but the following enhancements and changes were
made:
- Support for This usage in inheritance clauses of nested
types. For example, the following declaration defines Inner1
to be the subclass of the most refined subclass of Outer1 defined in
an instantiation. The implicit This type parameter refers to
the This-binding of Outer1, which can be Outer1 or a subclass of
Outer1.
class Outer1<>
{
static class Inner1 extends This {}
}
Using This, a nested class can be defined to inherit from the most
refined subclass of a sibling nested class. In the example
below, InnerB does not inherit from its sibling InnerA.
Instead, the specification of This.InnerA means that InnerB inherits
from the InnerA of the most refined subclass Outer2 generated by an
instantiation.
class Outer2<>
{
static class InnerA {}
static class InnerB extends This.InnerA {}
}
- Fixed a number of bugs, including one that broke method
overloading.
JL
0.30
The limitations and restrictions described for Release .21b still
apply for this release, but the following enhancements and changes were
made:
- Support for the Sibling pattern. The Sibling pattern
describes an inheritance relationship between sibling types nested
in the same type. The relationship allows one sibling to
inherit from a subtype of the other sibling.
For example, the following code implements the Sibling
pattern. First, Parent.Inner1 and Parent.Inner2 are
siblings. Second, Parent.Inner2 extends Child.Inner1, a
subclass of Parent.Inner1, completing the Sibling pattern.
public class Parent
{
public static class Inner1 {}
public static class Inner2
extends Child.Inner1 {}
}
public class Child
{
public static class Inner1
extends Parent.Inner1 {}
public static class Inner2
extends Parent.Inner2 {}
}
In JL, mixins can be used with the Sibling pattern to
create flexible inheritance hierarchies among sibling types.
- Added the -JavaCompAll compiler option, which instructs jlc
to invoke javac and explicitly list all source files in the
invocation string. This option can be used with code that
implements the Sibling pattern described above so that the standard
javac compiler will successfully execute.
- jlc no longer deletes .class files during compilation. Name
mangling, nested types and the possibility that programmers use the
dollar sign in type names makes the explicit deletion of class files
non-trivial. Programmers can always delete class files before
invoking jlc. jlc continues to delete X.java when compiling
X.jl, and class files are overwritten when the javac compiler is
invoked.
- CLASSPATH and SOURCEPATH values are only included in the javac
invocation string if they were explicitly specified on the jlc
command line.
- Other minor changes.
JL
0.21b
The .21b release
of JL represents the first release that contains a reasonable
implementation of all planned features. The Limitations list enumerates
significant limitations of the current implementation. The
Restrictions list enumerates less important support issues.
Limitations
-
Expression types are not resolved.
This implementation limitation means that instantiations of
parametric types cannot be used in all places that non-parametric
type names can be used.
In JL, type names that appear in JL source code are resolved when
their fully-qualified class or interface names are known. Once
type names are fully-qualified, some representation of the type can
be loaded or generated by the compiler.
JL currently resolves all names that appear in statements that
require types, such as inheritance clauses of class or interface
declarations, field declarations, formal parameter declarations,
etc. In each of these cases, the source code name appears in a
statement, not an expression. To resolve these name, JL does
not have to resolve references to fields, local variables or
methods.
For our current experiments with JL this is sufficient, so JL
doesn't attempt to resolve names in expressions. This means
that instantiations of parametric types that appear in expressions
are not currently processed. Below are examples of statements
that contain expressions that JL does not process.
fld.m().Inner<int>.m2();
fld.m().Inner<int>.x = 7;
if (fld.Inner2<String>.bool) {}
The instantiation of parametric types in each of the above
expressions will be disallowed by JL, assuming "fld"
represents some field reference.
-
Partial support for non-static nested parametric classes.
Limitation 1 described above effects JL's ability to fully support
non-static nested parametric classes, which are often called inner
classes in Java. JL compiles inner classes correctly, but it
cannot compile allocation statements of inner class objects because
these statements use the qualified form of new. Qualified new
calls require field references to be resolved, something JL doesn't
do yet.
The following code, which assumes parametric type Outer<T> has
an inner class named Inner<U>, illustrates the limitation in
the current version of JL:
Outer<int> outer = new
Outer<int>();
Outer<int>.Inner<String> in = outer.new
Inner<String>();
JL compilation will fail on the second line of code because Inner
can't be resolved given that "outer.new" is not used in
resolution process. There is, however, a work-around for this problem, which is described in detail for those
that need to use parametric inner classes.
-
The JL Semantic Checking language feature is not implemented.
The requires and provides are, however, reserved
keywords.
-
JL doesn't write extended attributes to class files.
JL-specific data known at compile time is not saved to the bytecode
files that are ultimately generated. This often means that
unless the JL source code is recompiled, some important information
is lost. For example, class files contain no information about
which constructors are propagatable.
Here's a list of some of the JL information that should be added to
class files as extended attributes for use by jlc and other JL
utilities:
- Unmangled instantiation name.
- Constructor propagation information.
- Nested class propagation information.
- Semantic checking information.
Restrictions
-
JL source files cannot contain more than one top-level type declaration.
-
Local classes cannot be parameterized.
Allow parameterized local classes seems like overkill and more complication than any programmer really
needs. There are also technical challenges involving naming if this
were to be allowed.
-
Other restrictions on local classes.
Anonymous classes observe restrictions that apply to all local classes.
The restrictions are that local classes:
- Cannot be parameterized (as mentioned above).
- Cannot use unqualified This or propagate in their bodies.
- Cannot use provides or requires.
On the other hand, local classes:
- Can use deeply (but not anonymous classes).
- Can use type parameters defined in enclosing types.
- Can instantiate parametric types.
- Can inherit from instantiated parametric types.
- Can use qualified This.
Thus, anonymous classes can inherit from an instantiated parametric type.
-
Propagated constructors cannot call this(..).
The implementation difficulty here is that the type of an arbitrary expression may need to be resolved to select the correct
constructor to call.
Another complication is that possible target constructors for a this(..) invocation
must also be guaranteed to be propagated. The target of this(..)
must also be a propagated constructor because a specific superclass constructor eventually
must be called with its propagated arguments.
Last Modified: 11/05/2001 02:51 PM
|