From: Vijay S. <vi...@sa...> - 2009-07-04 16:07:04
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> </head> <body bgcolor="#ffffff" text="#000000"> The internal wiki page for this note is <a class="moz-txt-link-freetext" href="http://xj.watson.ibm.com/twiki/bin/view/Main/XtenTwoOhInlinedImmutableClasses">http://xj.watson.ibm.com/twiki/bin/view/Main/XtenTwoOhInlinedImmutableClasses</a><br> <br> Comments please! <br> <br> In particular I would like to hear your thoughts on whether the extra complexity of the XtenTwoOhInlined design is worth the extra power (it can handle final classes with mutable state whereas XtenTwoOhInlined cannot).<br> <br> Best,<br> Vijay<br> ==========================<br> <ul> <li> Created on July 4, 2009 </li> <li> Last update: July 4, 2009 </li> <li> Base link: <a href="http://xj.watson.ibm.com/twiki/bin/view/Main/XtenTwoOhDesign" class="twikiLink">XtenTwoOhDesign</a> </li> </ul> <p></p> <h1><a name="inlined_as_a_type_constructor"></a><a name="_inlined_as_a_type_constructor"></a> <code>inlined</code> as a type constructor </h1> <p> <em>Here is an attempt to work out Nate's idea that <code>inlined</code> should be a type constructor. The only way I can make it work without introducing significant complications is to have it apply only to <code>final</code> classes with no mutable state.</em> </p> <p></p> <h1><a name="Basic_design"></a> Basic design </h1> <p> <code>inlined</code> is a type constructor. For any <code>final</code> class <code>C</code> with no mutable state, <code>inlined C</code> is a type. (<code>C</code> is permitted to implement interfaces.) </p> <p>The type <code>inlined T</code> may be used in most places that a class type is used: </p> <ul> <li> As the type of a local variable or loop variable or catch variable. </li> <li> As the type of a method or closure parameter. </li> <li> As the return type of a method, closure or constructor. </li> <li> In a classcast. </li> <li> In an <code>instanceof</code>. </li> <li> In the RHS of <code>typedef</code>. </li> <li> As the type of a field. </li> <li> In the invocation of a generic method or a constructor. </li> <li> As an actual type parameter for a generic class. </li> </ul> <p>It cannot be used </p> <ul> <li> As the superclass in a <code>class</code> definition </li> </ul> <p>Values of this type are implemened by inlining their state in the enclosing container. For local variables, the container is the stack frame, for fields, the container is the object, for method parameters, the container is the parameter list (part of the stack frame). Values of type <code>inlined T</code> may also be returned from methods -- in this case the method may return multiple words on the stack. </p> <p>A non-null value <code>v</code> of type <code>T</code> may be assigned into a variable of type <code>inlined T</code>. A value of type <code>inlined T</code> may be assigned into a variable of type <code>inlined T</code>. In both cases the state of the RHS is copied into the state of the LHS. </p> <p>A value of type <code>inlined T</code> is created by calling any constructor for type <code>T</code> as a static method (i.e. not prefixing the call with <code>new</code>). </p> <p>Values of type <code>inlined T</code> may be compared via <code>==</code> with other values of type <code>inlined T</code>. This operation performs a component-wise <code>==</code> comparison. One is free to define comparison of a <code>T</code> value with an <code>inlined T</code> value as well in the same way. </p> <p> </p> <ul> <li> Note that this implies the time taken by <code>==</code> on values of type <code>inlined T</code> is proportional to the size of <code>T</code>. </li> </ul> <p>If <code>v</code> is a value of type <code>inlined T</code>, <code>new v</code> is a value of type <code>T</code> that is <code>==</code>. This may be a newly created object or a previously interned object. </p> <ul> <li> This is a bit odd in that <code>new</code> may not necessarily construct a new object but nothing breaks with this semantics. </li> </ul> <p>A value <code>v</code> of type <code>inlined T</code> can be assigned to a variable <code>x</code> of type <code>T</code>; this is taken as shorthand for assigning <code>new v</code> to <code>x</code>. </p> <p>Since there is no mutable state in an <code>inlined T</code> value, there is no reason to support a <code>ref T</code>. </p> <p>Since there is no mutable state in an <code>inlined T</code> value, there is no reason to introduce a <code>closed</code> qualifier on methods or "=scoped=" types. Within the body of a <code>final</code> class <code>T</code> (with immutable fields) the type of <code>this</code> may be taken as <code>inlined T</code>. Therefore, any method on <code>T</code> can be called on an <code>inlined T</code>. Every field of <code>T</code> is available for a value <code>v</code> of type <code>inlined T</code>. </p> <p> </p> <ul> <li> As described above, a value of type <code>inlined T</code> can be coerced to <code>T</code> when needed (auto-boxing). </li> </ul> <p></p> <h3><a name="Primitive_types"></a> Primitive types </h3> <p> The class <code>Integer</code> is defined as a user-defined class with primitively implemented state. The state of the class is a single field, <code>data</code> whose type is <code>Data32</code>. This is a private class defined in <code>x10.lang</code> and implemented primitively. The file <code>int.x10</code> contains: </p> <p></p> <pre>package x10.lang; public typedef int = inlined Integer; </pre> <p> Similarly for all the N built-in classes. </p> <ul> <li> Note this is subtly different from the class <code>Integer</code> in Java, which has a field of type <code>int</code>. </li> </ul> <p></p> <h3><a name="Type_system"></a> Type system </h3> <p> The type system looks as follows. The top of the hierarchy is <code>Object</code>. Every defined class inherits from <code>Object</code>. Each type <code>inlined C</code> inherits from <code>Object</code> and is incomparable with any other type. </p> <ul> <li> A value <code>v</code> of type <code>inlined T</code> can be cast to <code>Object</code>. This is implemented by boxing, i.e. creating a value of type <code>T</code> that is <code>==</code> <code>v</code>. </li> <li> A downcast from a value <code>v</code> of type <code>Object</code> to <code>inlined T</code> succeeds if the runtime type of <code>v</code> is <code>T</code>. </li> </ul> <p></p> <h3><a name="Generics"></a> Generics </h3> There are no complications with generics. <p></p> <p></p> <pre>final class Pair[S,T] { val first: S; val second: T; def this(f: S, s: T) { this.first=f; this.second=s; } def first(): S=first; def second(): T=second; def hashCode() = first.hashCode() + second.hashCode(); def toString() = "<" + first.toString() + "." + second.toString() +">"; def equals(o:Object) { if (o instanceof Pair[S,T]) { val o1 = o to Pair[S,T]; return first.equals(o1.first) && second.equals(o2.second); } return false; } } </pre> <p> The user may declare types <code>Pair[Complex,Complex]</code>, <code>Pair[complex,String]</code>, <code>inlined Pair[complex, complex]</code> etc. They behave as expected. </p> <p></p> <h1><a name="Pros"></a> Pros </h1> Simple. This is very good! <p>The three use cases I had proposed earlier work with this proposal: </p> <ul> <li> It should be possible to inline <code>Complex</code> in a <code>Rail</code> or <code>ValRail</code>. </li> <li> It should be possible to inline the <code>ValRail[char]</code> field in <code>String</code>. </li> <li> It should be possible to <code>inline <span class="twikiNewLink">ValRail<a rel="nofollow" href="http://xj.watson.ibm.com/twiki/bin/edit/Main/ValRail?topicparent=Main.XtenTwoOhInlinedImmutableClasses" title="Create this topic"><sup>?</sup></a></span>[int]</code> in <code>Point</code>. </li> </ul> <p>The user-defined primitive classes I had proposed can be implemented as normal classes <code>C</code>, and then <code>inlined C</code> can be used in place of the primitive type. </p> <p><strong>Example</strong> </p> <pre>// in complex.x10 public typedef complex = inlined Complex; // in Complex.x10 public final class Complex { val r:double; val i:double; Complex(r:double, i:double) { this.r=r; this.i=i; } public def neg() = Complex(-r,-i); public def add(c:complex) = Complex(r+d.r,i+c.i); public def mul(c:complex) = Complex(r*c.r - i*c.i, r*c.i+i*c.r); ... } </pre> <em>EndOfExample.</em> <p>There is no need for special treatment of built-in primitives. This means that <code>Any</code> is not needed either. </p> <p>There is no need for the <code>closed</code> or <code>ref</code> qualifier. </p> <p></p> <h1><a name="Cons"></a> Cons </h1> <ul> <li> Classes with mutable state cannot be inlined. </li> <li> User has to be aware of auto-boxing. </li> </ul> <p></p> -- <a href="http://xj.watson.ibm.com/twiki/bin/view/Main/VijaySaraswat" class="twikiLink">VijaySaraswat</a> - 04 Jul 2009 </body> </html> |