aboutsummaryrefslogtreecommitdiff
path: root/clojurescript/PersistentVector-proto.js
diff options
context:
space:
mode:
authorChouser <chouser@n01se.net>2008-09-12 04:08:22 +0000
committerChouser <chouser@n01se.net>2008-09-12 04:08:22 +0000
commit5d0db072443c34f3dbd45ae077260e270f53a65a (patch)
tree12b0bb13e6195aca0939f5add197555217c14ed0 /clojurescript/PersistentVector-proto.js
parent0b0f94bc8258a31490092928b547614dcf25f722 (diff)
Initial preliminary checkin of ClojureScript -- very incomplete.
Diffstat (limited to 'clojurescript/PersistentVector-proto.js')
-rw-r--r--clojurescript/PersistentVector-proto.js189
1 files changed, 189 insertions, 0 deletions
diff --git a/clojurescript/PersistentVector-proto.js b/clojurescript/PersistentVector-proto.js
new file mode 100644
index 00000000..cbfdbee4
--- /dev/null
+++ b/clojurescript/PersistentVector-proto.js
@@ -0,0 +1,189 @@
+RT = { EMPTY_ARRAY: [] };
+
+function APersistentVector( _meta ) {
+ this._meta = _meta;
+}
+
+APersistentVector.prototype.meta = function() {
+ return this._meta;
+};
+
+APersistentVector.prototype.peek = function() {
+ if( this.count() > 0 ) {
+ return this.nth( this.count() - 1 );
+ }
+ return null;
+};
+
+function PersistentVector( _meta, cnt, shift, root, tail ) {
+ APersistentVector.call( this, _meta );
+ this._meta = _meta;
+ this.cnt = cnt;
+ this.shift = shift;
+ this.root = root;
+ this.tail = tail;
+}
+
+PersistentVector.prototype = new APersistentVector( null );
+PersistentVector.contraction = PersistentVector;
+
+PersistentVector.prototype.tailoff = function() {
+ return this.cnt - this.tail.length;
+};
+
+PersistentVector.prototype.nth = function( i ) {
+ if( i >= 0 && i < this.cnt ) {
+ if( i >= this.tailoff() ) {
+ return this.tail[ i & 0x01f ];
+ }
+ var arr = this.root;
+ for( var level = this.shift; level > 0; level -= 5 ) {
+ arr = arr[ (i >>> level) & 0x01f ];
+ }
+ return arr[ i & 0x01f ];
+ }
+ throw "IndexOutOfBoundsException";
+};
+
+PersistentVector.prototype.assocN = function( i, val ) {
+ if( i >= 0 && i < this.cnt ) {
+ if( i >= this.tailoff() ) {
+ var newTail = this.tail.slice( 0 );
+ newTail[ i & 0x01f ] = val;
+ return new PersistentVector(
+ this.meta(), this.cnt, this.shift, this.root, newTail );
+ }
+ return new PersistentVector(
+ this.meta(), this.cnt, this.shift,
+ this.doAssoc( this.shift, this.root, i, val), this.tail );
+ }
+ if( i == this.cnt ) {
+ return this.cons( val );
+ }
+ throw "IndexOutOfBoundsException";
+};
+
+PersistentVector.prototype.doAssoc = function( level, arr, i, val ) {
+ var ret = arr.slice( 0 );
+ if( level == 0 ) {
+ ret[ i & 0x01f ] = val;
+ }
+ else {
+ var subidx = (i >>> level) & 0x01f;
+ ret[ subidx ] = this.doAssoc( level - 5, arr[ subidx ], i, val );
+ }
+ return ret;
+};
+
+PersistentVector.prototype.count = function() {
+ return this.cnt;
+};
+
+PersistentVector.prototype.withMeta = function( _meta ) {
+ return new PersistentVector(
+ _meta, this.cnt, this.shift, this.root, this.tail );
+};
+
+PersistentVector.prototype.cons = function( val ) {
+ if( this.tail.length < 32 ) {
+ var newTail = this.tail.concat( [val] );
+ return new PersistentVector(
+ this.meta(), this.cnt + 1, this.shift, this.root, newTail );
+ }
+ var expansion = [null];
+ var newroot = this.pushTail( this.shift - 5, this.root, this.tail, expansion);
+ var newshift = this.shift;
+ if( expansion[0] != null ) {
+ newroot = [newroot, expansion[0]];
+ newshift += 5;
+ }
+ return new PersistentVector(
+ this.meta(), this.cnt+1, newshift, newroot, [val] );
+};
+
+PersistentVector.prototype.empty = function() {
+ return PersistentVector.EMPTY.withMeta( this.meta() );
+};
+
+PersistentVector.prototype.pushTail = function( level, arr, tailNode, expansion)
+{
+ var newchild;
+ if( level == 0 ) {
+ newchild = tailNode;
+ }
+ else {
+ newchild = this.pushTail(
+ level - 5, arr[arr.length - 1], tailNode, expansion);
+ if( expansion[0] == null ) {
+ var ret = arr.slice( 0 );
+ ret[ arr.length - 1 ] = newchild;
+ return ret;
+ }
+ else {
+ newchild = expansion[0];
+ }
+ }
+ //expansion
+ if( arr.length == 32 ) {
+ expansion[0] = [newchild];
+ return arr;
+ }
+ expansion[0] = null;
+ return arr.concat([newchild]);
+};
+
+PersistentVector.prototype.pop = function() {
+ if( this.cnt == 0 ) {
+ throw "IllegalStateException: Can't pop empty vector";
+ }
+ if( this.cnt == 1 ) {
+ return PersistentVector.EMPTY.withMeta( this.meta() );
+ }
+ if( this.tail.length > 1 ) {
+ var newTail = this.tail.slice( 0, this.tail.length - 1 );
+ return new PersistentVector(
+ this.meta(), this.cnt - 1, this.shift, this.root, newTail );
+ }
+ var ptail = [null];
+ var newroot = this.popTail( this.shift - 5, this.root, ptail );
+ var newshift = this.shift;
+ if( newroot == null ) {
+ newroot = RT.EMPTY_ARRAY;
+ }
+ if( this.shift > 5 && newroot.length == 1 ) {
+ newroot = newroot[0];
+ newshift -= 5;
+ }
+ return new PersistentVector(
+ this.meta(), this.cnt - 1, newshift, newroot, ptail[0] );
+};
+
+PersistentVector.prototype.popTail = function( shift, arr, ptail ) {
+ if( shift > 0 ) {
+ var newchild = this.popTail( shift - 5, arr[ arr.length - 1 ], ptail );
+ if( newchild != null ) {
+ var ret = arr.slice( 0 );
+ ret[ arr.length - 1 ] = newchild;
+ return ret;
+ }
+ }
+ if( shift == 0 ) {
+ ptail[0] = arr[ arr.length - 1 ];
+ }
+ //contraction
+ if( arr.length == 1 ) {
+ return null;
+ }
+ return arr.slice( 0, arr.length - 1 );
+};
+
+PersistentVector.EMPTY = new PersistentVector(
+ {}, 0, 5, RT.EMPTY_ARRAY, RT.EMPTY_ARRAY );
+
+PersistentVector.create = function( items ) {
+ var ret = PersistentVector.EMPTY;
+ for( var i = 0; i < items.length; ++i ) {
+ ret = ret.cons( items[ i ] );
+ }
+ return ret;
+}