[e-cvs] cvs commit: e/src/jsrc/org/erights/e/elib/util IdentityFunc.java OneArgFunc.java TwineException.java

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Fri, 17 Aug 2001 16:59:27 -0400


markm       01/08/17 16:59:26

  Modified:    src/jsrc/net/captp/jcomm Sturdifier.java
               src/jsrc/org/erights/e/develop/exception ThrowableSugar.java
               src/jsrc/org/erights/e/elang/interp Interp.java
               src/jsrc/org/erights/e/elang/syntax ELexer.java
                        SyntaxException.java
               src/jsrc/org/erights/e/elib/prim E.java
               src/jsrc/org/erights/e/elib/serial PassByConstruction.java
                        Serializer.java Unserializer.java
               src/jsrc/org/erights/e/elib/tables CompositeTwine.java
                        LocatedTwine.java LoopyTwine.java SimpleTwine.java
                        Twine.java
               src/jsrc/org/erights/e/elib/util OneArgFunc.java
                        TwineException.java
  Added:       src/jsrc/org/erights/e/elib/util IdentityFunc.java
  Log:
  exceptions just print as their report.  Preparing for identity-persistence

Revision  Changes    Path
1.8       +90 -8     e/src/jsrc/net/captp/jcomm/Sturdifier.java

Index: Sturdifier.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/captp/jcomm/Sturdifier.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Sturdifier.java	2001/07/31 13:09:14	1.7
+++ Sturdifier.java	2001/08/17 20:59:25	1.8
@@ -41,7 +41,7 @@
     /**
      *
      */
-    public Sturdifier(Introducer introducer, Timer persistentTimer) {
+    /*package*/ Sturdifier(Introducer introducer, Timer persistentTimer) {
         myIntroducer = introducer;
         myPersistentTimer = persistentTimer;
     }
@@ -57,27 +57,32 @@
     public SturdyRef run(Object obj) {
         return run(obj, Long.MAX_VALUE);
     }
-
+    
     /**
-     * Produce a SturdyRef for an object.
+     * Given an obj-swissNum association, arrange for the object to last 
+     * until an expiration time (so that the weak association will last till 
+     * then as well) and make a SturdyRef that uses this arrangement to 
+     * designate the object across time and space.
      *
      * @param obj The object for which a SturdyRef is desired
+     * @param swissNum The swissNum already associated with this object 
+     *                 (presumably because of an action taken by our caller).
      * @param optExpirationDate The date after which the SturdyRef will not
      *                          longer be guaranteed to be valid.  If 
      *                          Long.MAX_VALUE, then it's always valid.
      * @return A new SturdyRef for the indicated object
      */
-    public SturdyRef run(Object obj, long optExpirationDate) {
-        SwissTable swissTable = myIntroducer.getSwissTable();
-        BigInteger swissNum = swissTable.getNewSwiss(obj);
-        
+    private SturdyRef makeSturdy(Object obj,
+                                 BigInteger swissNum,
+                                 long optExpirationDate)
+    {
         /*
          * We don't bother checking for Long.MAX_VALUE == optExpirationDate, 
          * which is technically a XXX bug: these registrations will expire 
          * before the year 300,000,000.  Assuming no processes stay live that 
          * long, I think it's safe to assume that a future upgrade of E will 
          * rescue such persistent state before then.  Let's call this the 
-         * "Year Three Hundred M problem".
+         * "Y Three Hundred M problem".
          *
          * We don't bother capturing the Timeout returned by whenAlarm 
          * below, as this API provides no mean for cancelling these 
@@ -93,6 +98,83 @@
                              swissNum,
                              optExpirationDate);
     }
+    
+    /**
+     * Produce a SturdyRef for an object.
+     * <p>
+     * The SturdyRef will designate the object across time and space, at 
+     * least until the expiration time, so long as the hosting vat (this vat) 
+     * is accessible.
+     *
+     * @param obj The object for which a SturdyRef is desired
+     * @param optExpirationDate The date after which the SturdyRef will not
+     *                          longer be guaranteed to be valid.  If 
+     *                          Long.MAX_VALUE, then it's always valid.
+     * @return A new SturdyRef for the indicated object
+     */
+    public SturdyRef run(Object obj, long optExpirationDate) {
+        SwissTable swissTable = myIntroducer.getSwissTable();
+        BigInteger swissNum = swissTable.getNewSwiss(obj);
+        return makeSturdy(obj, swissNum, optExpirationDate);
+    }
+
+    /**
+     * Produce a SturdyRef, and a swissBase so in a later incarnation of this 
+     * vat a newly created object can be made to be the reincarnation of this 
+     * one (from the perspective of those holding the SturdyRef). 
+     * <p>
+     * An object is that which object references to it designate.  From one 
+     * vat incarnation to another, the only intervat references which survive 
+     * are SturdyRefs.  When doing identity-persistence (as opposed to object 
+     * persistence), the application creates the first SturdyRef to a 
+     * persistent object using incarnate(..), and makes sure to store the 
+     * swissBase somewhere for use during this vat's next incarnation.  
+     * (In identity-persistence, where this precious information is stored is 
+     * up to the app.)
+     * <p>
+     * On the next incarnation of the vat, the app creates a fresh object to 
+     * serve as the reincarnation of the original object, and calls 
+     * reincarnate(..) so the old SturdyRef will now designate the new 
+     * object. 
+     *
+     * @param obj The object for which a SturdyRef is desired
+     * @param optExpirationDate The date after which the SturdyRef will not
+     *                          longer be guaranteed to be valid.  If 
+     *                          Long.MAX_VALUE, then it's always valid.
+     * @return A pair of a new SturdyRef for 'obj', and a swissBase for 
+     *         reincarnating the identity assigned to 'obj'.
+     */
+    public Object[] incarnate(Object obj, long optExpirationDate) {
+        SwissTable swissTable = myIntroducer.getSwissTable();
+        BigInteger swissBase = swissTable.nextSwiss();
+        BigInteger swissNum = swissTable.registerNewSwiss(obj, swissBase);
+        
+        SturdyRef sr = makeSturdy(obj, swissNum, optExpirationDate);
+        Object[] result = { sr, swissBase };
+        return result;
+    }
+    
+    /**
+     * Cause 'obj' to be the object designated by 'swissHash cryptoHash()' in 
+     * this vat.
+     * <p>
+     * Used by an identity-persistent app (as opposed to an object-persistent 
+     * app) to cause old SturdyRefs that were given out by a previous 
+     * incarnation of this vat to continue to function.  It's polite for an 
+     * identity-peristent app to use an expiration date that's at least as 
+     * big as the ones used in previous incarnations.  To do otherwise is to 
+     * not honor the previously implied obligation.
+     *
+     */
+    public SturdyRef reincarnate(Object obj, 
+                                 BigInteger swissBase,
+                                 long optExpirationDate)
+    {
+        SwissTable swissTable = myIntroducer.getSwissTable();
+        BigInteger swissNum = swissTable.registerNewSwiss(obj, swissBase);
+        return makeSturdy(obj, swissNum, optExpirationDate);
+    }
+        
 
     /**
      *



1.8       +37 -6     e/src/jsrc/org/erights/e/develop/exception/ThrowableSugar.java

Index: ThrowableSugar.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/develop/exception/ThrowableSugar.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ThrowableSugar.java	2001/04/01 08:13:40	1.7
+++ ThrowableSugar.java	2001/08/17 20:59:26	1.8
@@ -33,25 +33,56 @@
  * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
  */
 public class ThrowableSugar {
+    
+    /** the standard "problem: " prefix */
+    static public final String ProblemPrefix = "problem: ";
+    
+    /** Same number of spaces as in the ProblemPrefix */
+    static public final String ProblemIndent = 
+        StringHelper.multiply(" ", ProblemPrefix.length());
 
     /** prevents instantiation */
     private ThrowableSugar() {}
     
     /**
+     * In general, a Throwable prints as 'problem: <type: msg>'.
+     * <p>
+     * If the msg is null, then prints as just 'problem: <type>'.  If msg 
+     * contains multiple lines, the remaining lines are indented to line up 
+     * with the "<type:...".
+     * <p>
+     * If self is an instance of RuntimeException, but not of any subclass of 
+     * RuntimeException, then it prints as 'problem: msg' (since the type 
+     * RuntimeException isn't interesting).  This behavior really should be 
+     * in a separate RuntimeExceptionSugar class, but is placed here to avoid 
+     * creating that sugar class for this only this purpose.
+     * <p>
      * This really should be 'printOn', but because of layering issues, we 
      * rename it and make a special case in the MirandaMethods.printOn().
      */
     static public void printThrowableOn(Throwable self, Writer out)
     throws IOException {
         PrintWriter pw = new PrintWriter(out);
+        pw.print(ProblemPrefix);
+        
         self = leaf(self);
-        String name = self.getClass().getName();
-        pw.print("<" + name.substring(name.lastIndexOf('.') +1));
-        String msg = self.getMessage();
-        if (null != msg) {
-            pw.print(": " + msg);
+        Class type = self.getClass();
+        String optMsg = self.getMessage();
+        if (null != optMsg) {
+            optMsg = StringHelper.replaceAll(optMsg,
+                                             "\n",
+                                             "\n" + ProblemIndent);
+        }
+        if (RuntimeException.class == type && null != optMsg) {
+            pw.print(optMsg);
+        } else {
+            String name = type.getName();
+            pw.print("<" + name.substring(name.lastIndexOf('.') +1));
+            if (null != optMsg) {
+                pw.print(": " + optMsg);
+            }
+            pw.print(">");
         }
-        pw.print(">");
     }
     
     /**



1.63      +2 -16     e/src/jsrc/org/erights/e/elang/interp/Interp.java

Index: Interp.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/interp/Interp.java,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -r1.62 -r1.63
--- Interp.java	2001/08/17 05:48:57	1.62
+++ Interp.java	2001/08/17 20:59:26	1.63
@@ -363,22 +363,8 @@
         try {
             Throwable leaf = ThrowableSugar.leaf(t);
 
-            TextWriter indented;
-            if (leaf instanceof SyntaxException) {
-                SyntaxException sex = (SyntaxException)leaf;
-                indented = sex.report(errs);
-            } else {
-                indented = commentBlock(errs, "problem");
-
-                if (leaf instanceof TwineException ||
-                    leaf.getClass() == RuntimeException.class)
-                {
-                    //only show the message
-                    indented.println(leaf.getMessage());
-                } else {
-                    indented.println(leaf);
-                }
-            }
+            errs.indent("# ").print("# ", leaf);
+            errs.lnPrint("#");
             if (verboseFlag) {
                 errs.indent("#   ").lnPrint(ThrowableSugar.javaStack(leaf));
             }



1.43      +2 -1      e/src/jsrc/org/erights/e/elang/syntax/ELexer.java

Index: ELexer.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/syntax/ELexer.java,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- ELexer.java	2001/07/29 02:16:50	1.42
+++ ELexer.java	2001/08/17 20:59:26	1.43
@@ -1014,7 +1014,8 @@
                 } while (t.tokenType() != EParser.EOF);
                 return;
             } catch (SyntaxException sex) {
-                sex.report(new TextWriter(PrintStreamWriter.err()));
+                TextWriter err = new TextWriter(PrintStreamWriter.err());
+                err.indent("# ").print("# ", sex);
             }
         }
     }



1.15      +16 -24    e/src/jsrc/org/erights/e/elang/syntax/SyntaxException.java

Index: SyntaxException.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/syntax/SyntaxException.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- SyntaxException.java	2001/04/01 08:13:41	1.14
+++ SyntaxException.java	2001/08/17 20:59:26	1.15
@@ -77,44 +77,36 @@
             return (Twine)myOptLine.run(myStart, myBound);
         }
     }
+    
+    static private final String ErrPrefix = "syntax error: ";
+    /** Same number of spaces as in the ErrPrefix */
+    static private final String ErrIndent = 
+        StringHelper.multiply(" ", ErrPrefix.length());
 
     /**
-     *
+     * Prints as "syntax error: " followed by an optional message, and then 
+     * an optional indication of the location of the error.
      */
-    public TextWriter report(TextWriter errs) throws IOException {
-        TextWriter result = errs.indent("#   ");
-        result.print("# syntax error: ");
+    public void printOn(TextWriter out) throws IOException {
+        out.print(ErrPrefix);
         String msg = getMessage();
         if (! msg.equals("syntax error")) {
-            result.print(msg);
+            out.indent(ErrIndent).print(msg);
         }
         if (null != myOptLine) {
-            result.lnPrint(myOptLine.replaceAll("\t", " "));
+            out = out.indent("  ");
+            out.lnPrint(myOptLine.replaceAll("\t", " "));
             if (! myOptLine.endsWith("\n")) {
-                result.println();
+                out.println();
             }
-            result.print(StringHelper.multiply(" ", myStart));
-            result.print(StringHelper.multiply("^", myBound - myStart));
+            out.print(StringHelper.multiply(" ", myStart));
+            out.print(StringHelper.multiply("^", myBound - myStart));
             Twine section = (Twine)myOptLine.run(myStart, myBound);
             SourceSpan optSpan = section.optSourceSpan();
             if (null != optSpan) {
-                result.lnPrint(optSpan);
+                out.lnPrint(optSpan);
             }
         }
-        return result;
-    }
-    
-    /**
-     * With no arguments, returns a string containing the report.
-     */
-    public String report() throws IOException {
-        StringWriter strWriter = new StringWriter();
-        try {
-            report(new TextWriter(strWriter));
-        } catch (Throwable th) {
-            throw ExceptionMgr.asSafe(th);
-        }
-        return strWriter.getBuffer().toString();
     }
 }
 



1.55      +1 -1      e/src/jsrc/org/erights/e/elib/prim/E.java

Index: E.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/prim/E.java,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -r1.54 -r1.55
--- E.java	2001/07/18 20:54:34	1.54
+++ E.java	2001/08/17 20:59:26	1.55
@@ -479,7 +479,7 @@
         if (problem instanceof Throwable) {
             return (Throwable)problem;
         } else {
-            return new TwineException(toTwine(problem));
+            return TwineException.make(toTwine(problem));
         }
     }
 



1.9       +8 -0      e/src/jsrc/org/erights/e/elib/serial/PassByConstruction.java

Index: PassByConstruction.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/serial/PassByConstruction.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- PassByConstruction.java	2001/08/17 03:11:33	1.8
+++ PassByConstruction.java	2001/08/17 20:59:26	1.9
@@ -59,6 +59,14 @@
         //of the stack trace, and we currently have no way to enforce the 
         //transitive adherence to any rules by Throwable subclasses.
         "java.lang.Throwable",
+        
+        //We'd like these to be (at least honorarily) Selfless, and therefore 
+        //PassByCopy, but they don't implement their own equals() and 
+        //hashCode(), and there doesn't seem to be any generic way to get 
+        //their contents and restore them from their contents.  However, 
+        //KeySpec looks like a hopeful solution someday.
+        "java.security.Key",
+        "java.security.KeyPair",
     };
 
     /**



1.5       +18 -5     e/src/jsrc/org/erights/e/elib/serial/Serializer.java

Index: Serializer.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/serial/Serializer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Serializer.java	2001/08/17 03:11:33	1.4
+++ Serializer.java	2001/08/17 20:59:26	1.5
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.io.OutputStream;
+import org.erights.e.elib.ref.Ref;
+import org.erights.e.elib.util.IdentityFunc;
 import org.erights.e.elib.util.OneArgFunc;
 
 /**
@@ -52,8 +54,7 @@
      * overriding of replaceObject().  See the Java Serialization spec for 
      * the detailed implications of this.
      */
-    public Serializer(OutputStream out,
-                      OneArgFunc replacer)
+    public Serializer(OutputStream out, OneArgFunc replacer)
     throws IOException {
         super(out);
         enableReplaceObject(true);
@@ -62,12 +63,18 @@
     }
     
     /**
+     * replacer defaults to identity function
+     */
+    public Serializer(OutputStream out) throws IOException {
+        this(out, IdentityFunc.TheOne);
+    }
+    
+    /**
      * Using a Serializer parameterized by this replacer, record the 
      * seriaized form of the specimen and return the resulting byte array.  
      * Such recordings can be play()ed by Unserializer.
      */
-    static public byte[] record(Object specimen,
-                                OneArgFunc replacer) 
+    static public byte[] record(Object specimen, OneArgFunc replacer) 
     throws IOException {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         Serializer ser = new Serializer(out, replacer);
@@ -80,6 +87,12 @@
      * Just applies the replacer I was constructed with.
      */
     protected Object replaceObject(Object obj) throws IOException {
-        return myReplacer.run(obj);
+        obj = Ref.resolution(obj);
+        obj = myReplacer.run(obj);
+        obj = Ref.resolution(obj);
+        if (! Ref.isPBC(obj)) {
+            throw new RuntimeException("not pbc: " + obj);
+        }
+        return obj;
     }
 }



1.5       +18 -5     e/src/jsrc/org/erights/e/elib/serial/Unserializer.java

Index: Unserializer.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/serial/Unserializer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Unserializer.java	2001/08/17 03:11:33	1.4
+++ Unserializer.java	2001/08/17 20:59:26	1.5
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.InputStream;
+import org.erights.e.elib.ref.Ref;
+import org.erights.e.elib.util.IdentityFunc;
 import org.erights.e.elib.util.OneArgFunc;
 
 /**
@@ -51,8 +53,7 @@
      * overriding of resolveObject().  See the Java Serialization spec for 
      * the detailed implications of this.
      */
-    public Unserializer(InputStream inp,
-                        OneArgFunc resolver)
+    public Unserializer(InputStream inp, OneArgFunc resolver)
     throws IOException {
         super(inp);
         enableResolveObject(true);
@@ -61,10 +62,16 @@
     }
     
     /**
+     * resolver defaults to identity function
+     */
+    public Unserializer(InputStream inp) throws IOException {
+        this(inp, IdentityFunc.TheOne);
+    }
+    
+    /**
      *
      */
-    static public Object play(byte[] recording,
-                              OneArgFunc resolver)
+    static public Object play(byte[] recording, OneArgFunc resolver)
     throws IOException, ClassNotFoundException {
         ByteArrayInputStream inp = new ByteArrayInputStream(recording);
         Unserializer uns = new Unserializer(inp, resolver);
@@ -78,6 +85,12 @@
      * Just applies the resolver I was constructed with.
      */
     protected Object resolveObject(Object obj) throws IOException {
-        return myResolver.run(obj);
+        obj = Ref.resolution(obj);
+        if (! Ref.isPBC(obj)) {
+            throw new RuntimeException("not pbc: " + obj);
+        }
+        obj = myResolver.run(obj);
+        obj = Ref.resolution(obj);
+        return obj;
     }    
 }



1.6       +7 -0      e/src/jsrc/org/erights/e/elib/tables/CompositeTwine.java

Index: CompositeTwine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/CompositeTwine.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- CompositeTwine.java	2001/02/09 19:35:25	1.5
+++ CompositeTwine.java	2001/08/17 20:59:26	1.6
@@ -126,6 +126,13 @@
     }
 
     /**
+     * 
+     */
+    public boolean isBare() {
+        return false;
+    }
+
+    /**
      *
      */
     public ConstList getParts() {



1.4       +7 -0      e/src/jsrc/org/erights/e/elib/tables/LocatedTwine.java

Index: LocatedTwine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/LocatedTwine.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- LocatedTwine.java	2001/02/03 18:32:06	1.3
+++ LocatedTwine.java	2001/08/17 20:59:26	1.4
@@ -58,6 +58,13 @@
     }
     
     /**
+     * 
+     */
+    public boolean isBare() {
+        return false;
+    }
+
+    /**
      * Returns a Twine which is either empty or is a LocatedTwine describing 
      * where the extracted run cam from.
      */



1.4       +7 -0      e/src/jsrc/org/erights/e/elib/tables/LoopyTwine.java

Index: LoopyTwine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/LoopyTwine.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- LoopyTwine.java	2001/02/03 18:32:06	1.3
+++ LoopyTwine.java	2001/08/17 20:59:26	1.4
@@ -65,6 +65,13 @@
     }
     
     /**
+     * 
+     */
+    public boolean isBare() {
+        return false;
+    }
+
+    /**
      * Loose the loopiness
      */
     public ConstList run(int start, int bound) {



1.5       +8 -0      e/src/jsrc/org/erights/e/elib/tables/SimpleTwine.java

Index: SimpleTwine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/SimpleTwine.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SimpleTwine.java	2001/02/09 19:35:25	1.4
+++ SimpleTwine.java	2001/08/17 20:59:26	1.5
@@ -50,7 +50,15 @@
         Object[] result = { TwineMaker, "fromString", myStr };
         return result;
     }
+
+    /**
+     * 
+     */
+    public boolean isBare() {
+        return true;
+    }
     
+
     /**
      *
      */



1.14      +5 -0      e/src/jsrc/org/erights/e/elib/tables/Twine.java

Index: Twine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/Twine.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Twine.java	2001/07/29 02:16:50	1.13
+++ Twine.java	2001/08/17 20:59:26	1.14
@@ -195,6 +195,11 @@
     public abstract String bare();
     
     /**
+     * Is the bare string all the info there is?
+     */
+    public abstract boolean isBare();
+    
+    /**
      * Gets the sourceSpan part of the twine, if it's there. <p>
      *
      * If this is an AtomicTwine, then, if the SourceSpan is there, it's as 



1.6       +1 -0      e/src/jsrc/org/erights/e/elib/util/OneArgFunc.java

Index: OneArgFunc.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/util/OneArgFunc.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- OneArgFunc.java	2000/11/21 09:24:34	1.5
+++ OneArgFunc.java	2001/08/17 20:59:26	1.6
@@ -18,6 +18,7 @@
 
 Contributor(s): ______________________________________.
 */
+
 /**
  * An interface for anonymous inner classes to implement so they can act as a 
  * one-argument inline closure. <p>



1.2       +30 -4     e/src/jsrc/org/erights/e/elib/util/TwineException.java

Index: TwineException.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/util/TwineException.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TwineException.java	2001/04/01 08:13:42	1.1
+++ TwineException.java	2001/08/17 20:59:26	1.2
@@ -19,11 +19,15 @@
 Contributor(s): ______________________________________.
 */
 
+import java.io.IOException;
+import org.erights.e.develop.exception.ThrowableSugar;
+import org.erights.e.elib.base.TextWriter;
 import org.erights.e.elib.tables.Twine;
 
 /**
- * If an E program throws a non-Exception object, a TwineException
- * is actually thrown using E.toTwine(problem) to convert it to a Twine.
+ * If an E program throws a non-Exception object, a TwineException or 
+ * RuntimeException is actually thrown using E.toTwine(problem) to convert 
+ * the object into the exception's message.
  *
  * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
  */
@@ -34,8 +38,30 @@
     /**
      *
      */
-    public TwineException(Twine msg) {
-        super(msg.bare());
+    private TwineException(String bareMsg, Twine msg) {
+        super(bareMsg);
         myTwineMsg = msg;
+    }
+
+    /**
+     * If the message is a simple String, then just use a RuntimeException. 
+     * Otherwise, use a TwineException in order to keep track of source 
+     * position information. 
+     */
+    static public RuntimeException make(Twine msg) {
+        String bareMsg = msg.bare();
+        if (msg.isBare()) {
+            return new RuntimeException(bareMsg);
+        } else {
+            return new TwineException(bareMsg, msg);
+        }
+    }
+
+    /**
+     * A TwineException just prints as 'problem: <bare message>'
+     */
+    public void printOn(TextWriter out) throws IOException {
+        out.indent(ThrowableSugar.ProblemIndent)
+           .print(ThrowableSugar.ProblemPrefix, getMessage());
     }
 }



1.1                  e/src/jsrc/org/erights/e/elib/util/IdentityFunc.java

Index: IdentityFunc.java
===================================================================
package org.erights.e.elib.util;

/*
The contents of this file are subject to the Improvements to the
Distributed E Language Implementation License Version 1.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.erights.org/mmlicense.html

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.

The Original Code is the Improvements to the Distributed E Language
Implementation, released May 27, 1999.

The Initial Developer of the Original Code is Mark S. Miller.
Copyright (C) 1999 Mark S. Miller. All Rights Reserved.

Contributor(s): ______________________________________.
*/

/**
 * Just returns its argument
 *
 * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
 */
public class IdentityFunc implements OneArgFunc {
    
    /** The canonical instance */
    static public final IdentityFunc TheOne = new IdentityFunc();
    
    /**
     * 
     */
    private IdentityFunc() {}
    
    /**
     * Returns arg
     */
    public Object run(Object arg) {
        return arg;
    }
}