Revision: 3630
          http://vexi.svn.sourceforge.net/vexi/?rev=3630&view=rev
Author:   clrg
Date:     2009-08-28 10:06:12 +0000 (Fri, 28 Aug 2009)

Log Message:
-----------
Better Cloning/Trap documentation

Modified Paths:
--------------
    trunk/core/org.ibex.js/src/org/ibex/js/JS.jpp
    trunk/core/org.ibex.js/src/org/ibex/js/JSArray.jpp

Modified: trunk/core/org.ibex.js/src/org/ibex/js/JS.jpp
===================================================================
--- trunk/core/org.ibex.js/src/org/ibex/js/JS.jpp       2009-08-28 09:47:06 UTC 
(rev 3629)
+++ trunk/core/org.ibex.js/src/org/ibex/js/JS.jpp       2009-08-28 10:06:12 UTC 
(rev 3630)
@@ -41,19 +41,22 @@
  * <code>cascade</code> keyword.  <em>Note that reading the property directly 
will re-invoke the
  * read trap.</em></p>
  * 
- * <pre> var obj = { a:5 };
+ * <pre>
+ * var obj = { a:5, b:4 };
  * 
  * // anonymous read trap
- * obj.aSquared ++= function() { var a = cascade; return a*a; };
- * obj.aSquared == 25; // true
+ * obj.a ++= function() { var a = cascade; return a*a; };
+ * obj.a == 25; // true
  * 
  * // referenced read trap
  * var readCubed = function() { var a = cascade; return a*a*a; };
- * obj.aCubed ++= readCubed;
- * obj.aCubed == 125; // true
- * obj.aCubed --= readCubed;
- * obj.aCubed == null; // true</pre>
+ * obj.b ++= readCubed;
+ * obj.b == 64; // true
+ * obj.b --= readCubed;
+ * obj.b == 4; // true</pre>
  * 
+ * <p>You can not write to the <code>cascade</code> keyword in a read trap.</p>
+ * 
  * <h3>Write Traps</h3>
  * 
  * <p>A write trap is a js function with a single argument, which is the value 
being assigned to
@@ -66,15 +69,38 @@
  * 
  * <p>To block a put - that is, cause the put to be ignored - simply 
return.</p>
  * 
+ * <pre>
+ * &lt;box id="a" enabled="true" focused="false" />
+ * &lt;box id="b" enabled="false" focused="false" />
+ * 
+ * var focusedWrite = function(v) {
+ *     if (trapee.enabled) casade = v;
+ *     else cascade = false;
+ * };
+ * 
+ * $a.focused ++= focusedWrite;
+ * $b.focused ++= focusedWrite;
+ * 
+ * // $a accepts focus because it is enabled
+ * $a.focused = true;
+ * $a.focused == true;
+ * 
+ * // $b declines focus because it is not enabled
+ * $b.focused = true;
+ * $b.focused == false;</pre>
+ * 
+ * <p>You can not read from the <code>cascade</code> keyword in a write 
trap.</p>
+ * 
  * <h3>Trap Chains</h3>
  * 
- * <p>Assigning multiple read or write traps to the same property on the same 
object are stacked
- * in order of assignment to create a trap chain.</p>
+ * <p>When assigning multiple read or write traps to the same property on the 
same object, the
+ * traps are stacked in order of assignment to create a trap chain.</p>
  * 
  * <p>There are two paths of execution in a trap chain, known as 
<em>pre-cascade</em> and
  * <em>post-cascade</em>.  When a write or read occurs, the trap at the top of 
the stack enters its
- * <em>pre-cascade</em> execution.  When it cascades, it passes the execution 
to the next trap,
- * and so on, until either a trap returns or the put/get reaches the object.  
Then the execution
+ * <em>pre-cascade</em> execution.  When it <em>cascades</em> - either writing 
to cascade (write
+ * trap) or reading from cascade (read trap) - it passes the execution to the 
next trap, and so on,
+ * until either a trap returns or the put/get reaches the object.  Then the 
execution
  * enters the <em>post-cascade</em> of the next trap up in the stack fro the 
return point, and
  * when a trap finishes, it passes the execution back up again in the 
stack.</p>
  * 
@@ -82,86 +108,106 @@
  * 
  * <p>Consider:</p>
  * 
- * <pre> var obj = {};
- * var block_at_B = false;
+ * <pre>
+ * var obj = { a:true };
  * 
- * var trap_A = function(v) {
- *     vexi.log.info("A: pre-cascade");
+ * var trap_1 = function(v) {
+ *     vexi.log.info("1: pre-cascade");
  *     cascade = v;
- *     vexi.log.info("A: post-cascade");
+ *     vexi.log.info("1: post-cascade");
  * };
- * var trap_B = function(v) {
- *     vexi.log.info("B: pre-cascade");
- *     if (block_at_B) return;
+ * var trap_2 = function(v) {
+ *     vexi.log.info("2: pre-cascade");
+ *     if (v==false) return;
  *     cascade = v;
- *     vexi.log.info("B: post-cascade");
+ *     vexi.log.info("2: post-cascade");
  * };
- * var trap_C = function(v) {
- *     vexi.log.info("B: pre-cascade");
+ * var trap_3 = function(v) {
+ *     vexi.log.info("3: pre-cascade");
  *     cascade = v;
- *     vexi.log.info("B: post-cascade");
+ *     vexi.log.info("3: post-cascade");
  * };
  * 
- * obj.a ++= trap_A;
- * obj.a ++= trap_B;
- * obj.a ++= trap_C;
+ * obj.a ++= trap_1;
+ * obj.a ++= trap_2;
+ * obj.a ++= trap_3;
  * 
  * obj.a = true;
  * // outputs:
- * // C: pre-cascade
- * // B: pre-cascade
- * // A: pre-cascade
- * // A: post-cascade
- * // B: post-cascade
- * // C: post-cascade
+ * // 3: pre-cascade
+ * // 2: pre-cascade
+ * // 1: pre-cascade
+ * // 1: post-cascade
+ * // 2: post-cascade
+ * // 3: post-cascade
  * 
- * block_at_B = true;
- * obj.a = true;
+ * obj.a = false;
  * // outputs:
- * // C: pre-cascade
- * // B: pre-cascade
- * // C: post-cascade</pre>
+ * // 3: pre-cascade
+ * // 2: pre-cascade
+ * // 3: post-cascade</pre>
+ * 
+ * <p>For encapsulation reasons, traps are always stacked in order of 
assignment, and this order
+ * can not be altered except by removing, by reference, any traps in the 
chain.</p>
  */
 
 /*...@page(concept=Cloning)
  * 
- * <p>A clone of an object is identical to the object it has cloned, the 
clonee, except that
- * traps placed on it are not placed on the clonee. That is, puts and reads 
will act upon the
- * clonee unless otherwise intercepted by traps on the clone.</p>
+ * <p>A clone is an object that shares the properties of the object from which 
it was cloned, but
+ * can be modified using traps that do not impact upon the original object.</p>
  * 
- * <p>Clones can be created using the <code>vexi.js.clone()</code> 
function:</p>
+ * <p>Clones can be created using the <code>vexi.js.clone()</code> 
function.</p>
  * 
- * <pre> var clonee = {};
+ * <p>You may get the original object using <code>vexi.js.unclone()</code> 
function.  It will
+ * always get the original object and never return a clone.</p>
+ * 
+ * <h3>Clone Behaviour</h3>
+ * 
+ * <p>A clone of an object is initially identical to the object it has cloned, 
the clonee, and puts
+ * and reads on the clone will act upon the clonee, but they are not the same 
object.  Traps placed
+ * on the clone are not placed on the clonee.  That is, puts and reads on the 
clone will act upon
+ * the clonee unless otherwise intercepted by non-cascading traps on the 
clone.</p>
+ * 
+ * <p>Consider:</p>
+ * 
+ * <pre> var clonee = { a:3, b:5 };
  * var clone = vexi.js.clone(clonee);
- * var tmp;
+ * var z;
  * 
- * // these puts are equivalent
- * clone.foo = 1;
- * clonee.foo = 1;
+ * // true
+ * 3 == clonee.a == clone.a;
  * 
+ * // still true after put to clone
+ * clone.a = 2;
+ * 2 == clonee.a == clone.a;
+ * 
+ * // still true after put to clonee
+ * clonee.a = 1;
+ * 1 == clonee.a == clone.a;
+ * 
  * // these reads are equivalent
- * tmp = clone.foo;
- * tmp = clonee.foo;
+ * z = clone.a;
+ * z = clonee.a;
  * 
- * clone.bar ++= function(v) { return; }
- * clone.bar ++= function() { return null; }
+ * // non-cascading traps
+ * clone.b ++= function(v) { return; }
+ * clone.b ++= function() { return 0; }
  * 
  * // these puts are not equivalent
- * clone.bar = 2;
- * clonee.bar = 2;
+ * clone.b = 2;  // clone.b == 0, clonee.b == 5
+ * clonee.b = 2; // clone.b == 0, clonee.b == 2
  * 
  * // these reads are not equivalent
- * tmp = clone.bar;  // tmp==null
- * tmp = clonee.bar; // tmp==2</pre>
+ * z = clone.b;  // z==0
+ * z = clonee.b; // z==2</pre>
  * 
- * <p>You may created multiple clones of an object.  You may clones of clones. 
 Clones can be
- * created and discarded without affecting the original object directly.</p>
+ * <p>You may created multiple clones of an object.  You may create clones of 
clones.  Clones can
+ * be created and discarded without affecting the original object directly.</p>
  * 
  * <p>A clone is a different object to its clonee, so the following is always 
true:</p>
  * 
- * <pre> vexi.js.clone(clonee) != clonee</pre>
- * 
- * <p>You may get the original object using <code>vexi.js.unclone()</code> 
function.</p>
+ * <pre>
+ * vexi.js.clone(clonee) != clonee</pre>
  */
 
 /** The minimum set of functionality required for objects which are 
manipulated by JavaScript */
@@ -230,7 +276,28 @@
         public JS unclone() { return this; }
         public JS type() { return SC_immutable; }
         public Keys keys() throws JSExn { throw new JSExn(type()+" has no key 
set"); }
-        public JS get(JS key) throws JSExn { return null; }
+        public JS get(JS key) throws JSExn {
+            //#noswitch - leave, needed for jsdoc
+            /*...@page(varname=Immutable,humanname=Immutable JS Object)
+             * 
+             * <p>An immutable js object.</p>
+             * 
+             * <p>Immutable objects may not have any properties or traps 
placed upon them.</p>
+             * 
+             * <p>They may be useful in conjuction with Cloning to create 
objects with a strict
+             * set of static or scoped properties.</p>
+             * 
+             * <pre>
+             * var immutable = new vexi.js.Immutable();
+             * var type = vexi.js.clone(immutable);
+             * var scopedprop = "foo";
+             * type.prop ++= function() { return scopedprop; };
+             * type.prop ++= function(v) { scopedprop = v; };</pre>
+             *  
+             * */
+            //#end
+            throw new JSExn("'"+key+"' is not a valid property on "+type());
+        }
         public void put(JS key, JS val) throws JSExn {
             throw new JSExn("'" + key + "' is read only on " + type());
         }
@@ -272,7 +339,7 @@
     
     public class Constructor extends JS.Immutable {
         final String name;
-        public Constructor(String name){ this.name = name; }
+        public Constructor(String name) { this.name = name; }
         public JS apply(JS this_, JS[] args) throws JSExn {
             throw new JSExn("Basic type constructor '"+ name + "' can only 
used with new");
         }
@@ -283,8 +350,9 @@
     public static class Clone extends JS.Obj {
         protected final Cloneable clonee;
         public Clone(JS clonee) throws JSExn {
-            if (!(clonee instanceof Cloneable))
+            if (!(clonee instanceof Cloneable)) {
                 throw new JSExn(clonee.getClass().getName() + " does not 
implement cloneable");
+            }
             this.clonee = (Cloneable)clonee;
         }
         // Non-Trap methods forward to the clonee 
@@ -337,12 +405,16 @@
         }
         
         public Obj(ConstructorList constructor) { 
-            if (Instr.memory!=null) Instr.memory.register(this);
+            if (Instr.memory!=null) {
+                Instr.memory.register(this);
+            }
             constructors = constructor;
         }
         
         protected void finalize() throws Throwable {
-            if (Instr.memory!=null) Instr.memory.unregister(this);
+            if (Instr.memory!=null) {
+                Instr.memory.unregister(this);
+            }
         }
         
         // HACK - neat, but still a hack. At least until the semantics are 
clear
@@ -430,11 +502,13 @@
              * 
              * <p>The standard js object.</p>
              * 
-             * <p>Objects can be created as literals in javascript using 
<code>{}</code></p>
+             * <p>Objects can be created as literals in vexiscript using 
<code>{}</code>.</p>
              * 
-             * <p>Unlike in browser javascript, in vexiscript (Vexi javascript)
-             * Objects do not have any standard properties (and so have a
-             * completely free keyspace). </p>
+             * <p>Objects can be initialized with content using <code>{ 
key1:val1, key2:val2,...
+             * keyn:valn }.</code></p>
+             * 
+             * <p>Unlike in browser javascript, in vexiscript Objects do not 
have any standard
+             * properties, and so have a completely free keyspace.</p>
              *  
              * */
             //#end
@@ -568,9 +642,10 @@
              * <p>Placing a trap on this allows the interception of all read 
and writes to this
              * proxy object</p>
              * 
-             * <pre>
-             * proxy.Properties ++= function(){} // a (range) read trap 
-             * proxy.Properties ++= function(v){} // a (range) write trap</pre>
+             * <pre> // a (range) read trap
+             * proxy.Properties ++= function() { };
+             * // a (range) write trap
+             * proxy.Properties ++= function(v) { };</pre>
              * 
              * @initial_value(N/A,code=false)
              * @type(<i>N/A</i>)
@@ -689,19 +764,18 @@
                 //#switch(JSU.toString(key))
                 /*...@page(varname=ProxyList,humanname=ProxyList Object)
                  * 
-                 * <p>The proxy list object is an alternative list object to 
the
-                 * standard js array, which supports a 'range trap' 'Elements' 
to
-                 * trap on the accessingadding/removing of elements</p> 
+                 * <p>The proxy list object is an alternative list object to 
the standard js array,
+                 * which supports a 'range trap' 'Elements' to trap on the
+                 * accessing/adding/removing of elements</p> 
                  * 
                  * <p>Whereas the Proxy is very similar to the standard Object 
the ProxyList is not
                  * similar to an array and so cannot be used as a drop in 
replacement. Notably
                  * it does not support most of the methods that arrays have, 
and it is not sparse
                  * and cannot contain nulls. Putting null to a proxy list will 
remove the object
-                 * at the index. </p>
-                 *  
+                 * at the index.</p>
                  * */
                 
-                /* The length of the ProxyList @type(Number) */
+                /* The length of the ProxyList @type(Number) 
@initial_value(varies,code=false) */
                 case "length": return JSU.N(bt.treeSize());
                 
                 /* <p>The index of an element in the proxylist, or null if the 
element
@@ -720,10 +794,10 @@
                  * <p>Placing a trap on this allows the interception of all 
read and writes to this
                  * proxylist object</p>
                  * 
-                 * <pre>
-                 *   proxylist.Elements ++= function(){} // a (range) read 
trap 
-                 *   proxylist.Elements ++= function(v){} // a (range) write 
trap
-                 * </pre>
+                 * <pre> // a (range) read trap
+                 * proxylist.Elements ++= function() { };
+                 * // a (range) write trap
+                 * proxylist.Elements ++= function(v) { };</pre>
                  * 
                  * @initial_value(N/A,code=false)
                  * @type(<i>N/A</i>)

Modified: trunk/core/org.ibex.js/src/org/ibex/js/JSArray.jpp
===================================================================
--- trunk/core/org.ibex.js/src/org/ibex/js/JSArray.jpp  2009-08-28 09:47:06 UTC 
(rev 3629)
+++ trunk/core/org.ibex.js/src/org/ibex/js/JSArray.jpp  2009-08-28 10:06:12 UTC 
(rev 3630)
@@ -32,41 +32,49 @@
              * 
              * <p>The standard js array.</p>
              * 
-             * <p>Arrays can be created as literals in javascript using 
<code>[]</code></p>
+             * <p>Arrays can be created as literals in vexiscript using 
<code>[]</code> which
+             * creates a new empty array.</p>
+             * 
+             * <p>Arrays can be initialized with contents in vexiscript using 
<code>[i1, i2,... in]</code>. 
              * */
-               /* Returns a new array containing the elements from the array
-                * object followed by the elements from each of the arguments.
+            
+               /* Returns a new array containing the elements from the array 
object followed by the
+                * elements from each of the arguments.
                 * 
                 * @param(name=a,varargs=true) 
                 * @return(Array)
                 * */
                case "concat": return METHOD;
+               
                /* Returns a shallow copy of the array.
                 * 
                 * @return(Array)
                 * */
                case "copy": return METHOD;
-               /* <p>Returns the array's values concatenated into a single 
string,
-                * with each value separated by the separator string.</p>
+               
+               /* <p>Returns the array's values concatenated into a single 
string, with each value
+                * separated by the separator string.</p>
                 * 
-                * <p>If separator is omitted, then it defaults to "," as the 
-                * separator string.<p> 
+                * <p>If separator is omitted, then it defaults to "," as the 
separator string.</p>
                 * 
                 * @param(name=separator,optional=true) 
                 * @return(String)
                 * */
                case "join": return METHOD;
-               /* The length of an array. -
+               
+               /* The length of an array.
                 * 
                 * @type(Number) 
                 * */
                case "length": return JSU.N(size());
+               
             /* Removes the last element of the array and returns it. 
              * If the array is currently empty, then it returns null.
              * 
              * @return(<i>varies</i>)
              * */
                case "pop": return METHOD;
+               
                /* Adds the specified values to the end of the current array
                 * and returns the new size of the array.
                 * 
@@ -74,17 +82,20 @@
                 * @return(Number) 
                 * */
                case "push": return METHOD;
+               
                /* Reverses the order of the elements in the current array and 
returns the array.
                 * 
                 * @return(Array)
                 * */
             case "reverse": return METHOD;
+            
             /* Removes the first element of the array and returns it. If the 
array is currently
              * empty, then it returns null.
              * 
              * @return(<i>varies</i>)
              * */
             case "shift": return METHOD;
+            
             /* <p>Returns a new array which contains a copy of the section of 
the current array
              * between start and end - 1, inclusive.</p>
              * 
@@ -98,6 +109,7 @@
              * @return(Array)
              * */
             case "slice": return METHOD;
+            
             /* <p>Sorts the contents of the current array and returns it.</p>
              * 
              * <p>If compareFunction is specified, then the given comparison 
function (which must
@@ -108,6 +120,7 @@
              * @return(Array)
              * */
             case "sort": return METHOD;
+            
             /* <p>Removes the array elements from start to start + deleteCount 
from the array,
              * and replaces them with the specified values. Returns a new 
array containing the
              * deleted values.<p>
@@ -123,11 +136,13 @@
                 * @return(Number) 
              */
             case "splice": return METHOD;
+            
             /* Returns array.join().
              * 
              * @return(String)
              * */
             case "toString": return METHOD;
+            
             /* Inserts the specified values at the beginning of the array. 
Returns the new size
              * of the array.
              * 
@@ -135,26 +150,39 @@
              * @return(Number)
              * */      
             case "unshift": return METHOD;
+            
             //#end
             // MAYbe better to return null 
             // return null;
             throw new JSExn("Attempt to get unrecognized string key 
'"+JSU.toString(key)+"' from an array");
         }
         int i = JSU.toInt(key);
-        if (i < 0) throw new JSExn("Attempt to get negative key '"+i+"' from 
an array");
+        if (i < 0) {
+            throw new JSExn("Attempt to get negative key '"+i+"' from an 
array");
+        }
         try {
             return (JS)get(i);
-        } catch (IndexOutOfBoundsException e) { return null; }
+        } catch (IndexOutOfBoundsException e) {
+            return null;
+        }
     }
     public void put(JS key, JS val) throws JSExn {
         // special array property put for length
-        if (JSU.isString(key) && JSU.toString(key).equals("length")) { 
size(JSU.toInt(val)); return; }
+        if (JSU.isString(key) && JSU.toString(key).equals("length")) {
+            size(JSU.toInt(val));
+            return;
+        }
         // normal array[i] put
-        if (key == null || !(JSU.isInt(key)))
+        if (key == null || !(JSU.isInt(key))) {
             throw new JSExn("Arrays only support positive integer keys, can 
not use: "+JSU.toString(key));
+        }
         int i = JSU.toInt(key);
-        if (i < 0) throw new JSExn("Attempt to put to negative key '"+i+" on 
an array");
-        if (size() < i+1) size(i + 1);
+        if (i < 0) {
+            throw new JSExn("Attempt to put to negative key '"+i+" on an 
array");
+        }
+        if (size() < i+1) {
+            size(i + 1);
+        }
         set(i, val);
     }
 
@@ -182,7 +210,9 @@
         case "splice": return splice(args);
         case "toString": return join(",");
         case "unshift":
-            for (int i=0; i < args.length; i++) add(i, args[i]);
+            for (int i=0; i < args.length; i++) {
+                add(i, args[i]);
+            }
             return JSU.N(size());
         //#end
         throw new JSExn("Arrays have no function: "+JSU.toString(method));
@@ -204,7 +234,7 @@
     }
 
     private void concat_fill(JSArrayLike arr) throws JSExn {           
-               for(int i=0; i<arr.length(); i++) {
+               for (int i=0; i<arr.length(); i++) {
                        add(arr.getElement(i));
                }
     }
@@ -229,14 +259,16 @@
     private JS concat(JS[] args) throws JSExn {
        int l = size();
        // size & check
-       for(int i=0; i<args.length; i++) {
-               if(!(args[i] instanceof JSArrayLike)) throw new JSExn("Arg 
"+i+" not an []");
+       for (int i=0; i<args.length; i++) {
+               if (!(args[i] instanceof JSArrayLike)) {
+                   throw new JSExn("Arg "+i+" not an []");
+               }
                JSArrayLike a = ((JSArrayLike)args[i]);
                l += a.length();
        }
        JSArray r = new JSArray(l);
        r.concat_fill(this);
-       for(int i=0; i<args.length; i++) {
+       for (int i=0; i<args.length; i++) {
                r.concat_fill((JSArrayLike)args[i]);
        }
        return r;
@@ -304,8 +336,12 @@
         try {
             sortargs[0] = (JS)a; sortargs[1] = (JS)b;
             return JSU.toInt(sort.apply(null, sortargs));
-        } catch (JSExn e) { throw new JSExn.Wrapper(e);
-        } finally { sortargs[0] = null; sortargs[1] = null; }
+        } catch (JSExn e) {
+            throw new JSExn.Wrapper(e);
+        } finally {
+            sortargs[0] = null;
+            sortargs[1] = null;
+        }
     }
     
     private JSArray copy() {
@@ -319,8 +355,9 @@
        JSArray r = new JSArray(0);
        r.size = size;
         r.o = new Object[size];
-       for(int i=0; i<size(); i++)
+       for (int i=0; i<size(); i++) {
                r.o[i] = JSU.deepcopy((JS)o[i]);
+       }
         return r;
     }
     
@@ -328,8 +365,9 @@
     public int length() { return size(); }
     public JS[] toArray() {
        JS[] r = new JS[size()];
-       for(int i=0; i<size(); i++)
+       for (int i=0; i<size(); i++) {
                r[i] = (JS)o[i];
+       }
        return r;
     }
 }
\ No newline at end of file


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Vexi-svn mailing list
Vexi-svn@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vexi-svn

Reply via email to