Revision: 3616
http://vexi.svn.sourceforge.net/vexi/?rev=3616&view=rev
Author: clrg
Date: 2009-08-20 22:34:31 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Documentation for concepts Cloning/Traps
Modified Paths:
--------------
trunk/core/org.ibex.js/src/org/ibex/js/Interpreter.jpp
trunk/core/org.ibex.js/src/org/ibex/js/JS.jpp
trunk/tools/vexitools.jsdoc/src_dev/vexi/jsdoc/RunOnVexi.java
Modified: trunk/core/org.ibex.js/src/org/ibex/js/Interpreter.jpp
===================================================================
--- trunk/core/org.ibex.js/src/org/ibex/js/Interpreter.jpp 2009-08-20
15:20:42 UTC (rev 3615)
+++ trunk/core/org.ibex.js/src/org/ibex/js/Interpreter.jpp 2009-08-20
22:34:31 UTC (rev 3616)
@@ -7,6 +7,20 @@
/*...@page(concept=Special Variables)
*
+ * <h3>General Variables</h3>
+ * <p>The following special variables are accessible in general template
script.</p>
+ * <dl>
+ * <dt><code>thisbox</code></dt>
+ * <dd><p>A reference to the Box defined by the XML node containing it. It
can also be thought
+ * of as a Box property.</p></dd>
+ * <dt><code>thisobj</code></dt>
+ * <dd><p>A reference to the Object/Array/etc defined by the XML node
containing it.</p></dd>
+ * <dt><code>static</code></dt>
+ * <dd><p>The static context of the template in which it is called.</p></dd>
+ * <dt><code>vexi</code></dt>
+ * <dd><p>The immutable global vexi object.</p></dd>
+ * </dl>
+ *
* <h3>Function Variables</h3>
* <p>The following special variables are accessible in the body of a
function.</p>
* <dl>
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-20 15:20:42 UTC
(rev 3615)
+++ trunk/core/org.ibex.js/src/org/ibex/js/JS.jpp 2009-08-20 22:34:31 UTC
(rev 3616)
@@ -7,6 +7,163 @@
import java.util.*;
import org.vexi.util.BasicTree;
+/*...@page(concept=Traps)
+ *
+ * <p>Traps are functions that can be assigned as listeners when properties on
vexiscript objects
+ * are accessed.</p>
+ *
+ * <p>There are two types of traps:</p>
+ *
+ * <ul>
+ * <li><b>Read traps</b> : fired by a property read/get on an object/box
property</li>
+ * <li><b>Write traps</b> : fired by a property get/write on an object/box
property</li>
+ * </ul>
+ *
+ * <p>Traps are assigned using the <code>++=</code> operator and unassigned
using the
+ * <code>--=</code> operator.</p>
+ *
+ * <p>A trap function can only ever be assigned once to the same property on
the same object at any
+ * given time. Repeated assignments of the same function to the same property
on the same object,
+ * without matching unassignments, are ignored. Respectively, repeat
unassignments, without
+ * matching assignments, are also ignored.</p>
+ *
+ * <p>To unassign a trap, you must either use a reference or the
<code>callee</code> keyword from
+ * within an anonymous trap.</p>
+ *
+ * <p>A full list of trap function properties is listed in Special
Variables.</p>
+ *
+ * <h3>Read Traps</h3>
+ *
+ * <p>A read trap is a function with no arguments. It must contain a return
statement. Assigning
+ * a read trap without a return statement will produce an exception.</p>
+ *
+ * <p>To get the value of the property the trap is placed upon from within a
read trap, use the
+ * <code>cascade</code> keyword. <em>Note that reading the property directly
will re-invoke the
+ * read trap.</em></p>
+ *
+ * <pre> var obj = { a:5 };
+ *
+ * // anonymous read trap
+ * obj.aSquared ++= function() { var a = cascade; return a*a; };
+ * obj.aSquared == 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>
+ *
+ * <h3>Write Traps</h3>
+ *
+ * <p>A write trap is a js function with a single argument, which is the value
being assigned to
+ * the property. It should contain either a return or put to the
<code>cascade</code> keyword and
+ * will produce a warning if neither is present.</p>
+ *
+ * <p>To put a value to the property at any point in the function, put to the
<code>cascade</code>
+ * keyword. This may only be done once per execution of a write trap.
<em>Note that putting to
+ * the property directly will re-invoke the write trap.</em></p>
+ *
+ * <p>To block a put - that is, cause the put to be ignored - simply
return.</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>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
+ * 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>
+ *
+ * <p>We refer to this execution path as <em>cascading</em> through the trap
chain.</p>
+ *
+ * <p>Consider:</p>
+ *
+ * <pre> var obj = {};
+ * var block_at_B = false;
+ *
+ * var trap_A = function(v) {
+ * vexi.log.info("A: pre-cascade");
+ * cascade = v;
+ * vexi.log.info("A: post-cascade");
+ * };
+ * var trap_B = function(v) {
+ * vexi.log.info("B: pre-cascade");
+ * if (block_at_B) return;
+ * cascade = v;
+ * vexi.log.info("B: post-cascade");
+ * };
+ * var trap_C = function(v) {
+ * vexi.log.info("B: pre-cascade");
+ * cascade = v;
+ * vexi.log.info("B: post-cascade");
+ * };
+ *
+ * obj.a ++= trap_A;
+ * obj.a ++= trap_B;
+ * obj.a ++= trap_C;
+ *
+ * obj.a = true;
+ * // outputs:
+ * // C: pre-cascade
+ * // B: pre-cascade
+ * // A: pre-cascade
+ * // A: post-cascade
+ * // B: post-cascade
+ * // C: post-cascade
+ *
+ * block_at_B = true;
+ * obj.a = true;
+ * // outputs:
+ * // C: pre-cascade
+ * // B: pre-cascade
+ * // C: post-cascade</pre>
+ */
+
+/*...@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>Clones can be created using the <code>vexi.js.clone()</code>
function:</p>
+ *
+ * <pre> var clonee = {};
+ * var clone = vexi.js.clone(clonee);
+ * var tmp;
+ *
+ * // these puts are equivalent
+ * clone.foo = 1;
+ * clonee.foo = 1;
+ *
+ * // these reads are equivalent
+ * tmp = clone.foo;
+ * tmp = clonee.foo;
+ *
+ * clone.bar ++= function(v) { return; }
+ * clone.bar ++= function() { return null; }
+ *
+ * // these puts are not equivalent
+ * clone.bar = 2;
+ * clonee.bar = 2;
+ *
+ * // these reads are not equivalent
+ * tmp = clone.bar; // tmp==null
+ * tmp = clonee.bar; // tmp==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>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>
+ */
+
/** The minimum set of functionality required for objects which are
manipulated by JavaScript */
public interface JS extends Constants {
@@ -19,7 +176,7 @@
* and not treat as a function and attempt to call the method object
directly */
public static final JS METHOD = new JS.Method();
public static final class Method extends Immutable {
- private Method(){} // Private so that there can be only one.
+ private Method() {} // Private so that there can be only one.
}
/** Returns a 'keys object'. */
@@ -35,8 +192,10 @@
* An exception is thrown if there is no such method or the
* arguments are invalid. */
public JS callMethod(JS this_, JS method, JS[] args) throws JSExn;
+
/** Apply. Will throw an exception unless object can be treated as a
function */
public JS apply(JS this_, JS[] args) throws JSExn;
+
/** Apply. Will throw an exception unless object can be treated as a
constructor/template */
public JS new_(JS[] args) throws JSExn;
@@ -51,12 +210,9 @@
* a js object, unless you understand otherwise, you usually want to
return CALLTYPE_METHOD. */
public int callType();
-
-
public void addTrap(JS key, JS function) throws JSExn;
public void delTrap(JS key, JS function) throws JSExn;
public Trap getTrap(JS key);
-
/** Value returned from typeof */
public JS type();
@@ -82,7 +238,7 @@
public JS new_(JS[] args) throws JSExn { throw new JSExn(type() +" is
not a constructor"); }
public JS apply(JS this_, JS[] args) throws JSExn { throw new
JSExn(type() +" cannot be called"); }
public JS callMethod(JS this_, JS method, JS[] args) throws JSExn {
- throw new JSExn("Tried to call '"+JSU.toString(method)+"' with
"+args.length+" args on "+type());
+ throw new JSExn("Tried to call '"+JSU.toString(method)+"' with
"+args.length+" args on "+type());
}
public String[] getFormalArgs() { return EMPTY_STRING_ARRAY; }
@@ -95,8 +251,11 @@
throw new JSExn("'" + JSU.toString(key) + "' trap is read only on
"+type());
}
public Trap getTrap(JS key) { return null; }
+
public boolean instanceOf(JS constructor){ return false; }
- public void addConstructor(JS constructor) throws JSExn {throw new
JSExn("Attemted to add constructor to immutable"); }
+ public void addConstructor(JS constructor) throws JSExn {
+ throw new JSExn("Attemted to add constructor to immutable");
+ }
}
public interface Cloneable extends JS {
@@ -108,15 +267,15 @@
// REMARK - semantically certain methods (read vexi.bless)
// need to act on the clone not the clonee. Thus the
// requirement to pass in the target.
- public JS deepcopy() throws JSExn;
+ public JS deepcopy() throws JSExn;
}
public class Constructor extends JS.Immutable {
- final String 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");
- }
+ final String 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");
+ }
}
/** A JS.Clone of a JS is identical to the object it has cloned, the
clonee,
@@ -128,14 +287,16 @@
throw new JSExn(clonee.getClass().getName() + " does not
implement cloneable");
this.clonee = (Cloneable)clonee;
}
- // Non-Trap methods forward to the clonee
+ // Non-Trap methods forward to the clonee
public JS unclone() { return clonee.unclone(); }
public Keys keys() throws JSExn { return clonee.keys(); }
+ public JS callMethod(JS this_, JS method, JS[] args) throws JSExn {
+ return clonee.callMethod(this_, method, args);
+ }
public JS get(JS k) throws JSExn { return clonee.get(k); }
public void put(JS k, JS v) throws JSExn { clonee.put(k, v); }
- public JS callMethod(JS this_, JS method, JS[] args) throws JSExn {
return clonee.callMethod(this_, method, args); }
public String[] getFormalArgs() { return clonee.getFormalArgs(); }
- public int callType(){ return clonee.callType(); }
+ public int callType() { return clonee.callType(); }
public String coerceToString() { return clonee.coerceToString(); }
public JS type() { return clonee.type(); }
@@ -146,33 +307,33 @@
}
}
- static public class ConstructorList{
- public ConstructorList(JS value, ConstructorList next){
- this.value = value; this.next = next;
- }
- JS value;
- ConstructorList next;
- }
+ static public class ConstructorList {
+ public ConstructorList(JS value, ConstructorList next) {
+ this.value = value; this.next = next;
+ }
+ JS value;
+ ConstructorList next;
+ }
/** Standard JS object implementation that can store arbitrarily named
properties
* and can have traps dynamically placed upon properties. */
public static class Obj implements Cloneable, Copyable {
- static public JS.Constructor Constructor = new JS.Constructor("Object"){
- public JS new_(JS[] args) throws JSExn {
- return new JS.Obj();
- }
- };
- static public ConstructorList base = new
ConstructorList(Constructor,null);
-
-
- protected ConstructorList constructors = null;
+ static public JS.Constructor Constructor = new
JS.Constructor("Object") {
+ public JS new_(JS[] args) throws JSExn {
+ return new JS.Obj();
+ }
+ };
+ static public ConstructorList base = new
ConstructorList(Constructor,null);
+
+
+ protected ConstructorList constructors = null;
// a map of values against properties stored on this object
private Map props = null;
// a map of traps against properties stored on this object
private Map traps = null;
public Obj() {
- this(base);
+ this(base);
}
public Obj(ConstructorList constructor) {
@@ -186,43 +347,55 @@
// HACK - neat, but still a hack. At least until the semantics are
clear
// should we mirror, or should it just be a straight copy?
-// protected Obj mirror(){
-// if (props==null) props = new HashMap(4);
-// if (traps==null) traps = new HashMap(4);
-// Obj r = new Obj();
-// r.traps = traps;
-// r.props = props;
-// return r;
-// }
+ //protected Obj mirror() {
+ // if (props==null) props = new HashMap(4);
+ // if (traps==null) traps = new HashMap(4);
+ // Obj r = new Obj();
+ // r.traps = traps;
+ // r.props = props;
+ // return r;
+ //}
public JS deepcopy() throws JSExn {
- if(getClass()!=Obj.class) throw new JSExn("deepcopy not
supported for: "+getClass().getName());
- if(traps!=null && traps.size()>0) throw new JSExn("cannot
deepcopy object with traps");
- JS.Obj r = new JS.Obj();
- Enumeration E = keys().iterator();
- while(E.hasNext()){
- JS key = E.next();
- JS val = get(key);
- r.put(key,JSU.deepcopy(val));
- }
- return r;
+ if (getClass()!=Obj.class) {
+ throw new JSExn("deepcopy not supported for:
"+getClass().getName());
+ }
+ if (traps!=null && traps.size()>0) {
+ throw new JSExn("cannot deepcopy object with traps");
+ }
+ JS.Obj r = new JS.Obj();
+ Enumeration E = keys().iterator();
+ while (E.hasNext()) {
+ JS key = E.next();
+ JS val = get(key);
+ r.put(key,JSU.deepcopy(val));
+ }
+ return r;
}
public JS unclone() { return this; }
public String[] getFormalArgs() { return EMPTY_STRING_ARRAY; }
public int callType(){ return CALLTYPE_METHOD; }
- public JS new_(JS[] args) throws JSExn { throw new JSExn(type() +" is
not a constructor"); }
- public JS apply(JS target, JS[] args) throws JSExn { throw new
JSExn("Cannot call a " + type()); }
- public JS callMethod(JS this_, JS method, JS[] args) throws JSExn {
throw new Error("Method not found: " + JSU.toString(method)); }
+ public JS new_(JS[] args) throws JSExn {
+ throw new JSExn(type() +" is not a constructor");
+ }
+ public JS apply(JS target, JS[] args) throws JSExn {
+ throw new JSExn("Cannot call a " + type());
+ }
+ public JS callMethod(JS this_, JS method, JS[] args) throws JSExn {
+ throw new Error("Method not found: " + JSU.toString(method));
+ }
- public boolean instanceOf(JS constructor){
- for(ConstructorList cl=constructors; cl!=null; cl=cl.next){
- if(cl.value==constructor) return true;
- }
- return false;
+ public boolean instanceOf(JS constructor) {
+ for (ConstructorList cl=constructors; cl!=null; cl=cl.next) {
+ if (cl.value==constructor) {
+ return true;
+ }
+ }
+ return false;
}
- public void addConstructor(JS c){
- constructors = new ConstructorList(c,constructors);
+ public void addConstructor(JS c) {
+ constructors = new ConstructorList(c,constructors);
}
public Keys keys() throws JSExn {
@@ -233,7 +406,9 @@
private Object[] keys =
props==null?EMPTY_STRING_ARRAY:props.keySet().toArray();
public boolean _hasNext() { return cur < keys.length; }
public JS _next() throws JSExn {
- if (cur >= keys.length) throw new
NoSuchElementException();
+ if (cur >= keys.length) {
+ throw new NoSuchElementException();
+ }
return (JS)keys[cur++];
}
};
@@ -249,9 +424,9 @@
public JS type() { return SC_object; }
/** Fetches any value stored against the given key. */
- public JS get(JS key) throws JSExn {
- //#noswitch - leave, needed for jsdoc
- /*...@page(varname=Object,humanname=JS Object)
+ public JS get(JS key) throws JSExn {
+ //#noswitch - leave, needed for jsdoc
+ /*...@page(varname=Object,humanname=JS Object)
*
* <p>The standard js object.</p>
*
@@ -262,26 +437,30 @@
* completely free keyspace). </p>
*
* */
- //#end
- return getSafe(key);
+ //#end
+ return getSafe(key);
}
- final public JS getSafe(JS key) { // workaround, avoid JSExn in
signature
- if (props==null) return null;
+ final public JS getSafe(JS key) { // workaround, avoid JSExn in
signature
+ if (props==null) {
+ return null;
+ }
return (JS)props.get(key);
}
/** Store a value against a key on the object. */
public void put(JS key, JS value) throws JSExn { putSafe(key,value); }
- public void putSafe(JS key, JS value) { // workaround, avoid JSExn in
signature
- // MEMORY OPTIMIZE?
- //if (props==null) props = new SmallMap();
- //else if(props.size()>4) props = new HashMap(props);
- if (props==null) props = new HashMap(4);
+ public void putSafe(JS key, JS value) { // workaround, avoid JSExn in
signature
+ // FEATURE: MEMORY OPTIMIZE?
+ // if (props==null) props = new SmallMap();
+ // else if(props.size()>4) props = new HashMap(props);
+ if (props==null) {
+ props = new HashMap(4);
+ }
props.put(key, value);
}
/** Removes a key and any value associated with it. */
- private void remove(JS key){
+ private void remove(JS key) {
if (props==null) return;
props.remove(key);
}
@@ -290,16 +469,18 @@
/** Gets a trap for the given key */
public Trap getTrap(JS key) {
- if (traps==null) return null;
+ if (traps==null) {
+ return null;
+ }
return (Trap)traps.get(key);
}
/** Places a trap on the given key. */
public void putTrap(JS key, Trap t) {
- // MEMORY OPTIMIZE?
- // if (traps==null) traps = new SmallMap();
- // else if(traps.size()>4) traps = new HashMap(traps);
- if (traps==null) traps = new HashMap(4);
+ // FEATURE: MEMORY OPTIMIZE?
+ // if (traps==null) traps = new SmallMap();
+ // else if(traps.size()>4) traps = new HashMap(traps);
+ if (traps==null) traps = new HashMap(4);
traps.put(key, t);
}
@@ -312,8 +493,9 @@
// REMARK: we are only interested in this JS object
// although other JS implementations may cause trap
// chains to be active across different JS objects
- if (t.function().equals(f) && t.target().equals(this))
+ if (t.function().equals(f) && t.target().equals(this)) {
return;
+ }
}
putTrap(key, new TrapHolder(this, key, f, t0));
}
@@ -322,14 +504,18 @@
* If there is no trap represented by the function for the key, it
does nothing */
public void delTrap(JS key, JS f) throws JSExn {
Trap t = traps==null?null:(Trap)traps.get(key);
- if (t==null) return;
+ if (t==null) {
+ return;
+ }
// function f was first trap in the chain
if (t.function().equals(f)) {
t = t.next();
// no traps left on this object
- if (t==null || !t.target().equals(this))
+ if (t==null || !t.target().equals(this)) {
traps.remove(key);
- else putTrap(key, t);
+ } else {
+ putTrap(key, t);
+ }
return;
}
// traverse the trap chain and remove the unwanted trap
@@ -337,8 +523,9 @@
if (n.function().equals(f)) {
// REMARK: target.equals(this) check is to ensure we are
// not interfering with traps from another object
- if (n.target().equals(this))
+ if (n.target().equals(this)) {
((TrapHolder)t).next = n.next();
+ }
return;
}
}
@@ -352,29 +539,29 @@
public String coerceToString() { return "obj$" +
Integer.toHexString(hashCode()); }
-
public Map getPropsMap() { return traps; }
public Map getTrapsMap() { return props; }
}
/** An implementation of JS that supports a meta trap on all properties */
public static class Proxy extends Obj {
- static public JS Constructor = new JS.Constructor("Proxy"){
- public JS new_(JS[] args) throws JSExn {
- return new JS.Proxy();
- }
- };
-
+ static public JS Constructor = new JS.Constructor("Proxy"){
+ public JS new_(JS[] args) throws JSExn {
+ return new JS.Proxy();
+ }
+ };
+
Trap propertiesTrap = null;
- public JS get(JS key) throws JSExn {
- //#noswitch - leave, needed for jsdoc
- /*...@page(varname=Proxy,humanname=Proxy Object)
+ public JS get(JS key) throws JSExn {
+ //#noswitch - leave, needed for jsdoc
+ /*...@page(varname=Proxy,humanname=Proxy Object)
*
* <p>The proxy object is an alternative map object to the
standard js object, which
* supports a 'range trap' <code>Properties</code> to trap on the
- * accessingadding/removing of properties.</p>
+ * accessing/adding/removing of properties.</p>
*
* */
+
/* <p>The <code>Properties</code> property is a
<em>meta-property</em>
* representing a gateway for accessing the properties of the
proxy object.</p>
*
@@ -382,16 +569,15 @@
* proxy object</p>
*
* <pre>
- * proxy.Properties ++= function(){} // a (range) read trap
- * proxy.Properties ++= function(v){} // a (range) write trap
- * </pre>
+ * proxy.Properties ++= function(){} // a (range) read trap
+ * proxy.Properties ++= function(v){} // a (range) write trap</pre>
*
* @initial_value(N/A,code=false)
* @type(<i>N/A</i>)
* */
//also "Properties":
- //#end
-
+ //#end
+
Trap rangeTrap =
propertiesTrap==null?null:propertiesTrap.findRead();
JSExn rangeTrapException = null;
JS value = null;
@@ -400,7 +586,9 @@
value = Scheduler.findCurrent().runBeforeGet(rangeTrap,
key);
key = Scheduler.findCurrent().cascadedTo;
// if null value returned, avoiding innermost cascade
- if (key == null) return value;
+ if (key == null) {
+ return value;
+ }
}
value = super.get(key);
} catch (JSExn e) {
@@ -424,7 +612,9 @@
value = Scheduler.findCurrent().runBeforePut(rangeTrap,
value, key);
key = Scheduler.findCurrent().cascadedTo;
// returned from trap without cascading (cleaned up in
finally clause)
- if (key==null) return;
+ if (key==null) {
+ return;
+ }
}
super.put(key, value);
} catch (JSExn e) {
@@ -449,8 +639,9 @@
// REMARK: we are only interested in this JS object
// although other JS implementations may cause trap
// chains to be active across different JS objects
- if (t.function().equals(f) && t.target().equals(this))
+ if (t.function().equals(f) && t.target().equals(this)) {
return;
+ }
}
propertiesTrap = new TrapHolder(this, key, f, propertiesTrap);
}
@@ -474,8 +665,9 @@
if (n.function().equals(f)) {
// REMARK: target.equals(this) check is to ensure we are
// not interfering with traps from another object
- if (n.target().equals(this))
+ if (n.target().equals(this)) {
((TrapHolder)t).next = n.next();
+ }
return;
}
}
@@ -483,19 +675,18 @@
}
public class ProxyList extends JS.Immutable implements JSArrayLike {
- static public JS Constructor = new JS.Constructor("ProxyList"){
- public JS new_(JS[] args) throws JSExn {
- return new JS.ProxyList();
- }
- };
-
- final BasicTree bt = new BasicTree();
+ static public JS Constructor = new JS.Constructor("ProxyList"){
+ public JS new_(JS[] args) throws JSExn {
+ return new JS.ProxyList();
+ }
+ };
+
+ final BasicTree bt = new BasicTree();
Trap elementsTrap = null;
public JS get(JS key) throws JSExn {
- if (key == null || !JSU.isInt(key)) {
-
- //#switch(JSU.toString(key))
+ if (key == null || !JSU.isInt(key)) {
+ //#switch(JSU.toString(key))
/*...@page(varname=ProxyList,humanname=ProxyList Object)
*
* <p>The proxy list object is an alternative list object to
the
@@ -509,17 +700,20 @@
* at the index. </p>
*
* */
- /* The length of the ProxyList @type(Number) */
- case "length": return JSU.N(bt.treeSize());
- /* <p>The index of an element in the proxylist, or null if the
element
- * was not found.</p>
- *
- * <p><i>TODO specify behaviour when a modifying readtrap
exists</i></p
- *
- * @param(element)
- * @return(Number)
- * */
- case "indexOf": return METHOD;
+
+ /* The length of the ProxyList @type(Number) */
+ case "length": return JSU.N(bt.treeSize());
+
+ /* <p>The index of an element in the proxylist, or null if the
element
+ * was not found.</p>
+ *
+ * <p><i>TODO specify behaviour when a modifying readtrap
exists</i></p
+ *
+ * @param(element)
+ * @return(Number)
+ * */
+ case "indexOf": return METHOD;
+
/* <p>The <code>Elements</code> property is a
<em>meta-property</em>
* representing a gateway for accessing the properties of the
proxylist object.</p>
*
@@ -535,12 +729,12 @@
* @type(<i>N/A</i>)
* */
//also "Elements":
- //#end
- throw new JSExn("Attempt to get unrecognized string key
'"+key+"' from a ProxyList");
- }
+ //#end
+ throw new JSExn("Attempt to get unrecognized string key
'"+key+"' from a ProxyList");
+ }
try {
- Trap rangeTrap =
elementsTrap==null?null:elementsTrap.findRead();
+ Trap rangeTrap =
elementsTrap==null?null:elementsTrap.findRead();
JSExn rangeTrapException = null;
JS value = null;
@@ -549,10 +743,14 @@
value =
Scheduler.findCurrent().runBeforeGet(rangeTrap, key);
key = Scheduler.findCurrent().cascadedTo;
// if null value returned, avoiding innermost cascade
- if (key == null) return value;
+ if (key == null) {
+ return value;
+ }
}
- int i = JSU.toInt(key);
- if (i < 0) throw new JSExn("Attempt to get negative key
'"+i+"' from a ProxyList");
+ int i = JSU.toInt(key);
+ if (i < 0) {
+ throw new JSExn("Attempt to get negative key '"+i+"'
from a ProxyList");
+ }
value = (JS) bt.getNode(i);
} catch (JSExn e) {
rangeTrapException = e;
@@ -576,15 +774,23 @@
value = Scheduler.findCurrent().runBeforePut(rangeTrap,
value, key);
key = Scheduler.findCurrent().cascadedTo;
// returned from trap without cascading (cleaned up in
finally clause)
- if (key==null) return;
+ if (key==null) {
+ return;
+ }
}
- if (key == null || !(JSU.isInt(key)))
+ if (key == null || !(JSU.isInt(key))) {
throw new JSExn("ProxyLists 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 a ProxyList");
+ if (i < 0) {
+ throw new JSExn("Attempt to put to negative key '"+i+" on
a ProxyList");
+ }
- if(value!=null) bt.insertNode(i, value);
- else bt.deleteNode(i);
+ if (value!=null) {
+ bt.insertNode(i, value);
+ } else {
+ bt.deleteNode(i);
+ }
} catch (JSExn e) {
rangeTrapException = e;
@@ -598,14 +804,16 @@
final private int[] INDEXOF_ARGS = new int[]{JSU.ANY};
public JS callMethod(JS this_, JS method, JS[] args) throws JSExn {
- String methodStr = JSU.toString(method);
- if("indexOf".equals(methodStr)){
- JSU.checkArgs(args, INDEXOF_ARGS);
- int r = bt.indexNode(args[0]);
- if(r==-1) return null;
- return JSU.N(r);
- }
- return super.callMethod(this_, method, args);
+ String methodStr = JSU.toString(method);
+ if ("indexOf".equals(methodStr)) {
+ JSU.checkArgs(args, INDEXOF_ARGS);
+ int r = bt.indexNode(args[0]);
+ if (r==-1) {
+ return null;
+ }
+ return JSU.N(r);
+ }
+ return super.callMethod(this_, method, args);
}
/** Places the given function as a trap on the given key, first
validating the function. */
@@ -620,8 +828,9 @@
// REMARK: we are only interested in this JS object
// although other JS implementations may cause trap
// chains to be active across different JS objects
- if (t.function().equals(f) && t.target().equals(this))
+ if (t.function().equals(f) && t.target().equals(this)) {
return;
+ }
}
elementsTrap = new TrapHolder(this, key, f, elementsTrap);
}
@@ -633,7 +842,9 @@
super.delTrap(key, f);
return;
}
- if (elementsTrap==null) return;
+ if (elementsTrap==null) {
+ return;
+ }
// function f was first trap in the chain
if (elementsTrap.function().equals(f)) {
elementsTrap = elementsTrap.next();
@@ -645,21 +856,22 @@
if (n.function().equals(f)) {
// REMARK: target.equals(this) check is to ensure we are
// not interfering with traps from another object
- if (n.target().equals(this))
+ if (n.target().equals(this)) {
((TrapHolder)t).next = n.next();
+ }
return;
}
}
}
public JS getElement(int i) throws JSExn { return get(JSU.N(i)); }
- public int length() throws JSExn { return bt.treeSize(); }
+ public int length() throws JSExn { return bt.treeSize(); }
- public JS[] toArray() throws JSExn { throw new JSExn("Cannot convert
proxylist to an array"); }
- public JS.Keys keys() throws JSExn { return new JSArrayLike.Keys(this);
}
+ public JS[] toArray() throws JSExn { throw new JSExn("Cannot convert
proxylist to an array"); }
+ public JS.Keys keys() throws JSExn { return new
JSArrayLike.Keys(this); }
}
-
-
+
+
public interface Trap {
public JS key();
public JS target();
@@ -696,8 +908,9 @@
((JSFunction)f).validTrap = true;
Scheduler.findCurrent().logger.warn(JS.class,"Trap function
has no explicit cascade/return, defined at " + ((JSFunction)f).definedAt());
}
- if (f.getFormalArgs().length > 1 )
+ if (f.getFormalArgs().length > 1 ) {
throw new JSExn("Traps must take either one argument (write)
or no arguments (read)");
+ }
}
}
@@ -713,14 +926,14 @@
public int size() throws JSExn { throw new JSExn("Cannot call size on
keysof " + name()); }
private JS name() throws JSExn { throw new JSExn(type()+ " [" +
keysof.getClass().getName() +"]"); }
protected JSArray toArray() throws JSExn {
- JSArray r = new JSArray(size());
- Enumeration E = iterator();
- while(E.hasNext()) r.add(E.next());
- return r;
+ JSArray r = new JSArray(size());
+ Enumeration E = iterator();
+ while (E.hasNext()) {
+ r.add(E.next());
+ }
+ return r;
}
-
-
public JS get(JS key) throws JSExn {
//#switch(JSU.toString(key))
case "contains": return METHOD;
@@ -754,10 +967,16 @@
protected abstract boolean _hasNext() throws JSExn;
protected abstract JS _next() throws JSExn;
- public final boolean hasNext() throws JSExn { return _hasNext() ||
(parent != null ? parent.hasNext() : false); }
+ public final boolean hasNext() throws JSExn {
+ return _hasNext() || (parent != null ? parent.hasNext() : false);
+ }
public final JS next() throws JSExn {
- if (_hasNext()) return _next();
- if (parent == null) throw new NoSuchElementException("Reached end
of set");
+ if (_hasNext()) {
+ return _next();
+ }
+ if (parent == null) {
+ throw new NoSuchElementException("Reached end of set");
+ }
return parent.next();
}
@@ -792,7 +1011,11 @@
public static final class RandomAccessList extends Enumeration {
private final List l;
private int pos = 0, size;
- public RandomAccessList(Enumeration parent, List list) {
super(parent); l = list; size = l.size(); }
+ public RandomAccessList(Enumeration parent, List list) {
+ super(parent);
+ l = list;
+ size = l.size();
+ }
protected boolean _hasNext() { return pos < size; }
protected JS _next() { return (JS)l.get(pos++); }
}
Modified: trunk/tools/vexitools.jsdoc/src_dev/vexi/jsdoc/RunOnVexi.java
===================================================================
--- trunk/tools/vexitools.jsdoc/src_dev/vexi/jsdoc/RunOnVexi.java
2009-08-20 15:20:42 UTC (rev 3615)
+++ trunk/tools/vexitools.jsdoc/src_dev/vexi/jsdoc/RunOnVexi.java
2009-08-20 22:34:31 UTC (rev 3616)
@@ -23,13 +23,13 @@
jsdoc.addConcept("Overview", "org.vexi.core.Vexi");
jsdoc.addConcept("Biscuits", "org.vexi.core.Vexi");
jsdoc.addConcept("Box Model", "org.vexi.core.Box");
- jsdoc.addConcept("Cloning", null);
+ jsdoc.addConcept("Cloning", "org.ibex.js.JS");
jsdoc.addConcept("Special Variables",
"org.ibex.js.Interpreter");
jsdoc.addConcept("Streams", "org.vexi.core.Vexi");
jsdoc.addConcept("Surfaces", "org.vexi.core.Surface");
jsdoc.addConcept("Templates", "org.vexi.core.Vexi");
jsdoc.addConcept("Threading", "org.vexi.core.Vexi");
- jsdoc.addConcept("Traps", null);
+ jsdoc.addConcept("Traps", "org.ibex.js.JS");
jsdoc.version = "3.0";
jsdoc.build = "3600";
jsdoc.doIt();
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/vexi-svn