[e-lang] Joe-E

Steven R. Brandt sbrandt at cct.lsu.edu
Thu Apr 29 06:42:55 PDT 2010


After a little thought, I believe I have an acceptable solution for the 
problem. In case it is of use, here's what I did to implement a 
powerless list class:

public class PowerlessList<T> {
     private final Holder data;
     public final PowerlessList<T> tail;
     public final int size;

     @SuppressWarnings(value = "unchecked")
     public T getHead() { return (T)data.get(); }

     public PowerlessList() {
         tail = null;
         data = null;
         size = 0;
     }
     public PowerlessList(T data,PowerlessList<T> tail) {
         this.data = Holder.create(data);
         this.tail = tail;
         this.size = tail.size+1;
     }

     public PowerlessList<T> push(T data) {
         return new PowerlessList<T>(data,this);
     }

     public T get(int n) {
         PowerlessList<T> p = this;
         while(n > 0) {
             p = p.tail;
             n--;
         }
         return p.getHead();
     }
}

The key is the holder class. It is able to hold a String, Integer, etc. 
Essentially, it turns the check from a compile-time to a run-time check, 
and allows me to use either String or Powerless. Of course, the whole 
thing might die with a bad type error, so it's a trade-off.

import org.joe_e.Powerless;

public abstract class Holder implements Powerless {
     public abstract Object get();
     public static Holder create(final Object o) {
         if(o instanceof String) {
             final String s = (String)o;
             return new Holder() {
                 public Object get() {
                     return s;
                 }
             };
         } else if(o instanceof Powerless) {
             final Powerless p = (Powerless)o;
             return new Holder() {
                 public Object get() {
                     return p;
                 }
             };
         } else if(o instanceof Number) {
             final Number n = (Number)o;
             return new Holder() {
                 public Object get() {
                     return n;
                 }
             };
         } else if(o instanceof Boolean) {
             final Boolean b = (Boolean)o;
             return new Holder() {
                 public Object get() {
                     return b;
                 }
             };
         } else if(o instanceof Character) {
             final Character c = (Character)o;
             return new Holder() {
                 public Object get() {
                     return c;
                 }
             };
         }
         throw new Error("bad type");
     }
}

The basic problem, I think, is that Powerless is a marker interface. If 
it were an attribute instead, then I think things would be nicer. We 
could have a compile-time check, and we could eliminate the ugliness and 
inefficiency of the Holder solution I have used above.

@Powerless
public class Foo<T> {
     T t;
     Foo(T t) { this.t = t; }
     public static void main(String[] args) {
        Foo<String> foo = ...;
        Foo<NonPowerlessType> bar = ...; // Joe-E could flag this as an 
error
     }
}

Maybe you could consider this for a future version?

Cheers,
Steve

On 04/29/2010 02:52 AM, David Wagner wrote:
> Steven R. Brandt wrote:
>    
>> I'm trying to build a powerless container, PowerlessMap. I have gotten
>> to the point where I follow all the rules and everything compiles.
>>
>> However, Joe-E says that I have to declare the key and value of the map
>> to be powerless, i.e.
>>
>> public class PowerlessMap<K extends Powerless, V extends Powerless>  { ... }
>>
>> This means that I can't make a PowerlessMap<String,String>  as String
>> does not extends Powerless. I can make a holder for String that
>> extends Powerless, and I can use that--but that's very clunky. What
>> should I be doing?
>>      
> Thanks for trying out Joe-E, and sorry about the frustration!
>
> You don't include the full source of your PowerlessMap, but I can guess
> what the issue is.  I'm guessing your PowerlessMap class is declared to
> implement Powerless [1], and has a field whose declared type is K or V.
> The Joe-E static verifier insists that all fields of any class declared
> Powerless must themselves be Powerless as well (see the documentation
> for org.joe_e.Powerless), which is why you need to declare in the type
> signature that K and V extend Powerless.  That indeed leads to the
> consequence that you describe.
>
> I know of no good solution for this.  (Maybe Adrian or Tyler know
> something I've overlooking.)  What I mean is, I know of no good way
> to build a PowerlessMap that does what you want, in Joe-E code.
>
> We ran into the same issue when building array classes (ConstArray,
> ImmutableArray, PowerlessArray, etc.).  What we did there was to write
> trusted code, in Java, and add it to the Joe-E library.  The Joe-E library
> contains some trusted Java code we have written, which would not pass
> the Joe-E static verifier, but which was written and reviewed by us very
> carefully to ensure that it nonetheless is safe, opens no security holes,
> and complies with capability rules.  The Joe-E library is exempt from
> static verification.
>
> I suspect the best solution is going to be to do the same thing we
> did for ImmutableArray and PowerlessArray: write a trusted library in
> Java, review it very carefully, and include it in the Joe-E library.
> You'll have to spend some time poring over that code, as it's pretty
> tricky code.  (You'll notice that it uses reflection to dynamically
> check that all elements are of the expected type, rather than using
> the static type system; this is how a PowerlessArray can be used to
> store both user classes that are declared Powerless as well as
> library classes that are honorarily Powerless, like String.)
>
> Ideally, the goal is that Joe-E would provide a rich enough set of
> libraries that you never have to run into this problem in application
> code.  In practice, Joe-E is a research project and does not have as
> rich a set of libraries as we would like, so you may need to extend
> our libraries.  If you do, you might consider submitting your code for
> inclusion in the Joe-E system.
>
>
> Alternatively, if you're willing to use a mutable map, you could consider
> LinkedHashMap.
>
>
> P.S. One concern I can imagine you might have: I can imagine you might
> be concerned that if you can't express something simple like this
> in Joe-E, what good is it?  Is Joe-E too restrictive?  Well, I think
> that's a fair concern, though I think it may not be as bad as it seems
> at first.  I think collection classes are probably a special case:
> it's non-trivial to write collection classes that are genericized,
> enable code to take advantage of Joe-E's Immutable/Powerless/...
> marker interfaces to the maximum extent possible, and also handle
> honorarily Immutable/Powerless/... legacy classes (like String) well.
> However I'm not sure this issue will come up much in application code,
> once you have a good collection library.  At present, Joe-E's collection
> library is almost certainly overly minimalistic and insufficiently
> expressive; this seems like something that should be fixable with some
> engineering effort (but without fundamental changes to the language).
>
>
>
> Footnote 1: Did you mean the following type signature?
>
> public class PowerlessMap<K extends Powerless, V extends Powerless>  implements Powerless { ... }
> _______________________________________________
> e-lang mailing list
> e-lang at mail.eros-os.org
> http://www.eros-os.org/mailman/listinfo/e-lang
>    



More information about the e-lang mailing list