aboutsummaryrefslogtreecommitdiff
path: root/clojurescript/rt.js
diff options
context:
space:
mode:
Diffstat (limited to 'clojurescript/rt.js')
-rw-r--r--clojurescript/rt.js2053
1 files changed, 2053 insertions, 0 deletions
diff --git a/clojurescript/rt.js b/clojurescript/rt.js
new file mode 100644
index 00000000..5eac7c36
--- /dev/null
+++ b/clojurescript/rt.js
@@ -0,0 +1,2053 @@
+// Copyright (c) Chris Houser, Sep 2008. All rights reserved.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license.
+// You must not remove this notice, or any other, from this software.
+
+// Runtime support for code generated by tojs.clj
+
+clojure = {
+ JS: {
+ global: this,
+ merge: function( t, s ) {
+ for( var i in s ) {
+ t[ i ] = s[ i ];
+ }
+ return t;
+ },
+ Class: {
+ classname: "clojure.JS.Class",
+ hashCode: function() { return clojure.lang.Util.hash( this.classname ); },
+ isAssignableFrom: function(base) { return base.classset[this.classname];},
+ getSuperclass: function() { return this.extend || null; },
+ getInterfaces: function() { return this.implement || null; }
+ }
+ },
+ lang: {
+ Namespace: function( n, m ) {
+ this.name = n; // FIXME: this pollutes the namespace
+ clojure.JS.merge( this, m || {} );
+ }
+ }
+};
+
+clojure.JS.Class.constructor = clojure.JS.Class;
+clojure.JS.Class.classset = { Class: true };
+
+if( ! clojure.JS.global["java"] ) {
+ java = { lang: { String: {}, Character: {}, Class: {}, Number: {},
+ Boolean: {} },
+ math: { BigDecimal: {} },
+ util: { Collection: {}, Map: {}, Set: {}, regex: { Pattern: {} } } };
+}
+
+clojure = {
+ JS: {
+ merge: clojure.JS.merge,
+ global: clojure.JS.global,
+ Class: clojure.JS.Class,
+ objectType: typeof {},
+ functionType: typeof function(){},
+ stringType: typeof "",
+ numberType: typeof 0,
+ variadic: function( arity, f ) {
+ f.arity = arity;
+ f.isVariadic = true;
+ return f;
+ },
+ resolveVar: function( sym, ctxns ) {
+ return ctxns[ sym ] || clojure[ sym ] || clojure.JS.global[ sym ];
+ },
+ def: function( ns, name, init ) {
+ var v = new clojure.lang.Var( ns, name );
+ ns["_var_" + name] = v;
+ v.push( init );
+ return v;
+ },
+ variadic_sentinel: {},
+ rest_args: function( varflag, args, i ) {
+ if( varflag === clojure.JS.variadic_sentinel )
+ return args[ args.length - 1 ];
+ return new clojure.lang.ArraySeq( null, args, i );
+ },
+ invoke: function( obj, methodname, args ) {
+ return obj[ methodname ].apply( obj, args );
+ },
+ getOrRun: function( obj, prop ) {
+ var val = obj[ prop ];
+ if( typeof val === clojure.JS.functionType
+ || (typeof val === clojure.JS.objectType && "apply" in val) )
+ {
+ return val.apply( obj, [] );
+ }
+ return val;
+ },
+ lit_list: function( a ) {
+ if( a.length > 0 )
+ return new clojure.lang.ArraySeq( null, a, 0 );
+ return clojure.lang.PersistentList.EMPTY;
+ },
+ lit_vector: function( a ) {
+ return clojure.lang.LazilyPersistentVector.createOwning( a );
+ },
+ implement: function( cls, name, extend, implement ) {
+ clojure.JS.merge( cls, clojure.JS.Class );
+ cls.classname = name;
+ cls.extend = extend;
+ cls.implement = implement;
+ cls.classset = {};
+ cls.classset[ name ] = true;
+ if( implement ) {
+ for( var i = 0; i < implement.length; ++i ) {
+ if( ! implement[ i ] )
+ throw "Can't implement null: " + name;
+ clojure.JS.merge( cls.classset, implement[ i ].classset );
+ }
+ }
+ },
+ definterface: function( pkg, name, implement ) {
+ var cls = pkg[ name ] = {};
+ clojure.JS.implement( cls, name, null, implement );
+ return cls;
+ },
+ defclass: function( pkg, name, opts ) {
+ var cls = pkg[ name ] = opts.init || function() {};
+ clojure.JS.implement( cls, name, opts.extend, opts.implement );
+ if( 'extend' in opts ) {
+ cls.prototype = new opts.extend;
+ cls.prototype.constructor = cls;
+ clojure.JS.merge( cls.classset, opts.extend.classset );
+ }
+ if( opts.statics ) { clojure.JS.merge( cls, opts.statics ); }
+ if( opts.methods ) { clojure.JS.merge( cls.prototype, opts.methods ); }
+ return cls;
+ },
+ instanceq: function( c, o ){
+ if( o === null )
+ return false;
+ if( typeof o === clojure.JS.functionType && ! ("constructor" in o) )
+ return false; // a Java class?
+ if( o.constructor === c )
+ return true;
+ if( ! o.constructor.classset )
+ return false; // builtin class that doesn't match?
+ return o.constructor.classset[ c.classname ];
+ },
+ relayPrintMethod: function( jsclass, javaclass, ctor ) {
+ var m = clojure.core.print_method;
+ m.addMethod( jsclass, function(o,w) {
+ return (clojure.core.get( m.methodTable, javaclass )
+ .apply(null, [ctor ? ctor(o) : o, w]));
+ });
+ },
+ bitcount: function(n){
+ var rtn = 0;
+ for( ; n; n >>= 1) {
+ rtn += n & 1;
+ }
+ return rtn;
+ },
+ ObjSeq: {
+ create: function( obj ) {
+ var i, pairs = [];
+ for( i in obj ) {
+ pairs.push( [i, obj[i]] );
+ }
+ return clojure.lang.ArraySeq.create( pairs );
+ }
+ }
+ },
+ lang: {
+ Namespace: clojure.lang.Namespace,
+ Numbers: {
+ isZero: function(x) { return x === 0; },
+ isPos: function(x) { return x > 0; },
+ isNeg: function(x) { return x < 0; },
+ minus: function(x,y) { return y === undefined ? -x : x - y; },
+ inc: function(x) { return x + 1; },
+ dec: function(x) { return x - 1; },
+ add: function(x,y) { return x + y; },
+ multiply: function(x,y) { return x * y; },
+ divide: function(x,y) { return x / y; },
+ quotient: function(x,y) { return parseInt(x / y); },
+ remainder: function(x,y) { return x % y; },
+ equiv: function(x,y) { return x == y; },
+ lt: function(x,y) { return x < y; },
+ lte: function(x,y) { return x <= y; },
+ gt: function(x,y) { return x > y; },
+ gte: function(x,y) { return x >= y; },
+ compare: function(x,y) { return (x<y) ? -1 :( (y<x) ? 1 : 0 ); },
+ unchecked_inc: function(x) { return x + 1; }
+ },
+ Util: {
+ hash: function(o){
+ switch( o ) {
+ case null: return 0;
+ case Array: return 0x7A837A71;
+ case Boolean: return 0x7A837A72;
+ case Function: return 0x7A837A73;
+ case Number: return 0x7A837A74;
+ case Object: return 0x7A837A75;
+ case RegExp: return 0x7A837A76;
+ case String: return 0x7A837A77;
+ case java.lang.Boolean:
+ case java.lang.Character:
+ case java.lang.Class:
+ case java.lang.Double:
+ case java.lang.Integer:
+ case java.lang.Number:
+ case java.lang.String:
+ case java.math.BigDecimal:
+ case java.util.Collection:
+ case java.util.Map:
+ case java.util.Set:
+ case java.util.regex.Pattern:
+ return 0x7A830001;
+ }
+ var i = 0, ret = o.length;
+ switch( typeof o ) {
+ case clojure.JS.stringType:
+ // lousy hand-made string hash
+ for( ; i < o.length; ++i ) {
+ ret ^= o.charCodeAt(i) << ((i % 4) * 8);
+ }
+ return ret;
+ case clojure.JS.numberType:
+ return o & 0xffffffff;
+ }
+ switch( o.constructor ) {
+ case Array:
+ for( ; i < o.length; ++i ) {
+ ret = clojure.lang.Util.hashCombine(
+ ret, clojure.lang.Util.hash( o[i] ) );
+ }
+ return ret;
+ }
+ if( o.hashCode )
+ return o.hashCode();
+ return 0x11111111;
+ },
+ hashCombine: function(seed, hash){
+ return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+ },
+ equal: function(x,y) { return x == y; },
+ isInteger: function(x) { return typeof x == clojure.JS.numberType; }
+ },
+ RT: {
+ EMPTY_ARRAY: [],
+ conj: function( coll, x ) {
+ if( coll === null )
+ return new clojure.lang.PersistentList( null, x );
+ return coll.cons( x );
+ },
+ seqToArray: function(s) {
+ var i = 0, ret = new Array( clojure.count( s ) );
+ for( ; s !== null; ++i, s = s.rest() )
+ ret[ i ] = s.first();
+ return ret;
+ },
+ intCast: function(i) {
+ return parseInt(i);
+ },
+ makeStringBuilder: function(s) {
+ return new clojure.JS.StringBuilder( s===undefined ? "" : s );
+ },
+ className: function(c) {
+ if( "classname" in c )
+ return c.classname;
+ if( "name" in c )
+ return c.name;
+ var s = "" + c,
+ m = /^\[JavaClass (.*)]$/.exec(s);
+ if( m )
+ return m[1];
+ return s;
+ },
+ simpleClassName: function(c) {
+ // FIXME: should generate simple name
+ return clojure.lang.RT.className(c);
+ }
+ }
+ }
+};
+
+clojure.core = new clojure.lang.Namespace("clojure.core",{
+ in_ns: function(s) {
+ var i, nsparts = s.getName().split('.'),
+ base = clojure.JS.global;
+ for( i = 0; i < nsparts.length; ++i ) {
+ if( ! base[nsparts[i]] ) {
+ base[nsparts[i]] = new clojure.lang.Namespace(nsparts[i]);
+ }
+ base = base[nsparts[i]];
+ }
+ },
+ refer: function(s) {},
+ load: function(s) {},
+ seq: function(coll){
+ if( coll === null ) return null;
+ else if( coll.seq ) return coll.seq();
+ //else if( coll.constructor === String )
+ // return clojure.lang.StringSeq.create(coll);
+ else if( typeof coll.length == clojure.JS.numberType )
+ return clojure.lang.ArraySeq.create(coll);
+ else if( typeof coll === clojure.JS.objectType )
+ return clojure.JS.ObjSeq.create(coll);
+ throw ("Don't know how to create ISeq from: " +
+ (typeof coll) + " " + coll.constructor.name);
+ },
+ apply: function( f ) {
+ var i, newargs = [], s, eagercount,
+ oldargs = arguments, arglen = oldargs.length;
+ if( f.isVariadic ) {
+ // lazy
+ eagercount = Math.min( f.arity, arglen - 2 );
+ for( i = 0; i < eagercount; ++i ) {
+ newargs.push( oldargs[ i + 1 ] );
+ }
+ if( eagercount == f.arity ) {
+ if( arglen - eagercount < 3 ) {
+ newargs.push( clojure.core.seq( oldargs[ arglen - 1 ] ) );
+ }
+ else {
+ newargs.push( clojure.core.concat(
+ new clojure.lang.ArraySeq(
+ null, oldargs, eagercount + 1, arglen - 1 ),
+ oldargs[ arglen - 1 ] ) );
+ }
+ }
+ else {
+ s = clojure.core.seq( oldargs[ arglen - 1 ] );
+ for( ; s && newargs.length < f.arity; s = s.rest() ) {
+ newargs.push( s.first() );
+ }
+ if( s )
+ newargs.push( s );
+ }
+ return f.apply( clojure.JS.variadic_sentinel, newargs );
+ }
+ else {
+ // non-lazy
+ for( i = 1; i < arglen - 1; ++i ) {
+ newargs.push( oldargs[ i ] );
+ }
+ for( s = oldargs[ arglen - 1]; s; s = s.rest()) {
+ newargs.push( s.first() );
+ }
+ return f.apply( null, newargs );
+ }
+ },
+ first: function(x) {
+ if( x === null ) return null;
+ if( x.first ) return x.first();
+ var seq = clojure.core.seq( x );
+ if( seq === null ) return null;
+ return seq.first();
+ },
+ rest: function(x) {
+ if( x === null ) return null;
+ if( x.rest ) return x.rest();
+ var seq = clojure.core.seq( x );
+ if( seq === null ) return null;
+ return seq.rest();
+ },
+ second: function(x) { return clojure.first(clojure.rest(x)); },
+ cons: function( x, coll ) {
+ var y = clojure.core.seq( coll );
+ if( y === null )
+ return new clojure.lang.PersistentList( null, x );
+ return y.cons( x );
+ },
+ instance_QMARK_: function( c, o ) {
+ return clojure.JS.instanceq( c, o );
+ },
+ class_QMARK_: function(o) { return clojure.JS.instanceq(clojure.JS.Class,o);},
+ number_QMARK_: function(o) { return clojure.JS.instanceq( Number, o ); },
+ string_QMARK_: function(o) { return clojure.JS.instanceq( String, o ); },
+ integer_QMARK_: function(o) { return parseInt( o ) === o; },
+ find: function(coll, key) {
+ if( coll == null )
+ return null;
+ else if( coll.containsKey ) {
+ if( coll.containsKey( key ) )
+ return new clojure.lang.MapEntry( key, coll.get( key ) );
+ return null;
+ }
+ return coll.entryAt( key );
+ },
+ get: function(coll, key, notFound ) {
+ var usenull = notFound === undefined;
+ if( coll === null )
+ return usenull ? null : notFound;
+ if( coll.valAt )
+ return coll.valAt( key, notFound );
+ if( coll.containsKey )
+ return (usenull || coll.containsKey( key )) ? coll.get( key ) : notFound;
+ if( coll.contains )
+ return (usenull || coll.contains( key )) ? coll.get( key ) : notFound;
+ return (usenull || key in coll) ? coll[ key ] : notFound;
+ },
+ nth: function(coll, n, notFound) {
+ var usenull = (notFound === undefined), seq, i;
+ if( coll === null )
+ return usenull ? null : notFound;
+ if( coll.nth )
+ return usenull || n < coll.count() ? coll.nth(n) : notFound;
+ if( coll.get )
+ return usenull || n < coll.size() ? coll.get(n) : notFound;
+ if( coll.seq ) {
+ for( seq = coll.seq(), i = 0; i <= n && seq; seq = seq.rest() ) {
+ if( i == n )
+ return seq.first();
+ }
+ if( usenull )
+ throw "IndexOutOfBoundsException";
+ return notFound;
+ }
+ return usenull || n < coll.length ? coll[n] : notFound;
+ },
+ contains_QMARK_: function(coll, key) {
+ if( coll === null )
+ return false;
+ if( coll.containsKey )
+ return coll.containsKey( key ) ? true : false;
+ if( coll.contains )
+ return coll.contains( key ) ? true : false;
+ return key in coll;
+ },
+ hash_map: function() {
+ return clojure.lang.PersistentHashMap.create( arguments );
+ },
+ hash_set: function() {
+ return clojure.lang.PersistentHashSet.create( arguments );
+ },
+ to_array: function(coll){
+ if( coll === null )
+ return clojure.lang.RT.EMPTY_ARRAY;
+ if( coll.toArray )
+ return coll.toArray();
+ if( typeof coll === clojure.JS.stringType ) {
+ var i = 0, rtn = new Array( coll.length );
+ for( ; i < coll.length; ++i ) {
+ rtn[i] = coll[i];
+ }
+ return rtn;
+ }
+ if( coll.constructor === Array ) {
+ return coll.slice(0);
+ }
+ throw "Unable to convert: " + coll.constructor.classname + " to Array";
+ },
+ keyword: function(a,b) {
+ if( b === undefined )
+ return clojure.lang.Keyword.intern( null, a );
+ return clojure.lang.Keyword.intern( a, b );
+ },
+ symbol: function(a,b) {
+ if( b === undefined )
+ return clojure.lang.Symbol.intern( null, a );
+ return clojure.lang.Symbol.intern( a, b );
+ },
+ assoc: function( coll, key, val ) {
+ if( coll === null )
+ return new clojure.lang.PersistentArrayMap([key, val]);
+ return coll.assoc( key, val );
+ },
+ count: function(x) {
+ if( x === null ) return 0;
+ if( x.count ) return x.count();
+ if( x.length != undefined ) return x.length;
+ throw ("count not supported on: " + (typeof x) + " " + x.constructor);
+ },
+ class_: function(o) {
+ if( o === null || o === undefined )
+ return null;
+ if( typeof o === clojure.JS.functionType && ! ("constructor" in o) )
+ return java.lang.Class;
+ return o.constructor || typeof o;
+ },
+ import_: function() {
+ // do nothing
+ },
+ identical_QMARK_: function( a, b ) {
+ return a === b;
+ },
+ keys: function(coll) {
+ return clojure.lang.APersistentMap.KeySeq.create(clojure.core.seq(coll));
+ },
+ vals: function(coll) {
+ return clojure.lang.APersistentMap.ValSeq.create(clojure.core.seq(coll));
+ }
+});
+
+clojure.JS.definterface( clojure.JS, "Collection" );
+
+clojure.JS.defclass( clojure.JS, "StringBuilder", {
+ init: function( x ) { this.a = [ x ]; },
+ methods: {
+ append: function( x ) { this.a.push( x ); return this; },
+ toString: function() { return this.a.join(''); }
+ }
+});
+
+clojure.JS.defclass( clojure.JS, "String", {
+ init: function(s) {
+ this.s = s;
+ this.length = s.length;
+ },
+ methods: {
+ charAt: function(x) { return this.s.charAt(x); },
+ toString: function() { return this.s; }
+ }
+});
+
+clojure.JS.definterface( clojure.lang, "IObj" );
+
+clojure.JS.defclass( clojure.lang, "Obj", {
+ implement: [ clojure.lang.IObj ],
+ init: function(_meta) { this._meta = _meta; },
+ methods: {
+ meta: function() { return this._meta; }
+ }
+});
+
+clojure.JS.definterface( clojure.lang, "IReduce" );
+
+clojure.JS.definterface( clojure.lang, "IPersistentCollection" );
+
+clojure.JS.definterface( clojure.lang, "ISeq",
+ [clojure.lang.IPersistentCollection] );
+
+clojure.JS.definterface( clojure.lang, "IndexedSeq",
+ [clojure.lang.ISeq] );
+
+clojure.JS.defclass( clojure.lang, "ASeq", {
+ implement: [clojure.lang.ISeq],
+ methods: {
+ equals: function( obj ) {
+ var s = this.seq(), ms = obj.seq();
+ for( ; s !== null; s = s.rest(), ms = ms.rest() ) {
+ if( ms === null || !clojure.lang.Util.equal( s.first(), ms.first() ))
+ return false;
+ }
+ if( ms !== null )
+ return false;
+ return true;
+ },
+ hashCode: function() { throw "not yet implemented"; },
+ count: function() {
+ var i = 1, s = this.rest();
+ for( ; s; s = s.rest() )
+ i += 1;
+ return i;
+ },
+ seq: function(){ return this; },
+ cons: function(o){ return new clojure.lang.Cons( null, o, this ); },
+ toArray: function(){ return clojure.lang.RT.seqToArray( this.seq() ); },
+ containsAll: function(c){ throw "not yet implemented"; },
+ size: function(){ return this.count(); },
+ isEmpty: function(){ return this.count() == 0; },
+ contains: function(c){ throw "not yet implemented"; }
+ }
+});
+
+clojure.JS.defclass( clojure.lang, "Cons", {
+ extend: clojure.lang.ASeq,
+ init: function( _meta, _first, _rest ) {
+ this._meta = _meta;
+ this._first = _first;
+ this._rest = _rest;
+ },
+ methods: {
+ first: function(){ return this._first; },
+ rest: function(){ return this._rest; },
+ count: function(){ return 1 + clojure.count( this._rest ); },
+ seq: function(){ return this; },
+ withMeta: function(_meta){
+ return new clojure.lang.Cons( _meta, this._first, this._rest );
+ }
+ }
+});
+
+clojure.JS.defclass( clojure.lang, "ArraySeq", {
+ extend: clojure.lang.ASeq,
+ implement: [clojure.lang.IndexedSeq, clojure.lang.IReduce],
+ init: function( _meta, a, i, len ) {
+ this._meta = _meta;
+ this.a = a;
+ this.i = i;
+ this.len = (len === undefined) ? a.length : len;
+ },
+ statics: {
+ create: function( a ) {
+ if( a && a.length )
+ return new clojure.lang.ArraySeq( null, a, 0 );
+ return null;
+ }
+ },
+ methods: {
+ first: function() { return this.a[this.i]; },
+ rest: function() {
+ if( this.i + 1 < this.len )
+ return new clojure.lang.ArraySeq(
+ this._meta, this.a, this.i + 1, this.len);
+ return null;
+ },
+ count: function() { return this.len - this.i; },
+ index: function() { return this.i; },
+ withMeta: function( _meta ) {
+ return new clojure.lang.ArraySeq( _meta, this.array, this.i, this.len );
+ },
+ reduce: function( fn, start ) {
+ var ret = (start===undefined) ? this.a[this.i] : fn(start,this.a[this.i]),
+ x = this.i + 1;
+ for( ; x < this.len; ++x ) {
+ ret = fn( ret, this.a[x] );
+ }
+ return ret;
+ },
+ seq: function() { return this; }
+ }
+});
+
+
+clojure.JS.defclass( clojure.lang, "LazyCons", {
+ extend: clojure.lang.ASeq,
+ init: function(f,_first,_rest) {
+ this.f = f;
+ this._first = _first === undefined ? clojure.lang.LazyCons.sentinel :_first;
+ this._rest = _rest === undefined ? clojure.lang.LazyCons.sentinel :_rest;
+ },
+ statics: {
+ sentinel: {}
+ },
+ methods: {
+ first: function() {
+ if( this._first === clojure.lang.LazyCons.sentinel )
+ this._first = this.f();
+ return this._first;
+ },
+ rest: function() {
+ if( this._rest === clojure.lang.LazyCons.sentinel ) {
+ if( this._first === clojure.lang.LazyCons.sentinel ) {
+ this.first();
+ }
+ this._rest = clojure.core.seq( this.f(null) );
+ this.f = null;
+ }
+ return this._rest;
+ },
+ withMeta: function(_meta) {
+ if( _meta == this.meta() )
+ return this;
+ //force before copying
+ this.rest();
+ return new clojure.lang.LazyCons( _meta, this._first, this._rest );
+ },
+ seq: function() { return this; }
+ }
+});
+
+
+clojure.JS.defclass( clojure.lang, "Var", {
+ init: function( ns, name ) {
+ this.ns = ns;
+ this.name = name;
+ this.stack = [];
+ },
+ statics: {
+ stack: [],
+ pushThreadBindings: function( m ) {
+ var vars=[], bs = m.seq(), e;
+ for( ; bs; bs = bs.rest()) {
+ e = bs.first();
+ vars.push( e.key() );
+ e.key().push( e.val() );
+ }
+ clojure.lang.Var.stack.push( vars );
+ },
+ popThreadBindings: function() {
+ var i = 0, vars = clojure.lang.Var.stack.pop();
+ for( ; i < vars.length; ++i ) {
+ vars[i].pop();
+ }
+ }
+ },
+ methods: {
+ push: function( val ) {
+ this.stack.push( val );
+ this.ns[ this.name ] = val;
+ },
+ pop: function() {
+ this.stack.pop();
+ this.ns[ this.name ] = this.stack[ this.stack.length - 1 ];
+ },
+ set: function( val ) {
+ this.stack.pop();
+ this.push( val );
+ },
+ get: function() {
+ return this.ns[ this.name ];
+ },
+ hasRoot: function() { return this.stack.length > 0; },
+ toString: function() {
+ if( this.ns !== null )
+ return "#=(var " + this.ns.name + "/" + this.name + ")";
+ return "#<Var: " + (this.name !== null ? this.name : "--unnamed--") + ">";
+ },
+ hashCode: function() {
+ return clojure.lang.Util.hash( this.ns + "/" + this.name );
+ }
+ }
+});
+
+clojure.JS.definterface( clojure.lang, "IFn" );
+
+clojure.JS.defclass( clojure.lang, "AFn", {
+ extend: clojure.lang.Obj,
+ implement: [clojure.lang.IFn],
+ methods: {
+ apply: function( obj, args ){
+ return this.invoke.apply( this, args );
+ }
+ }
+});
+
+clojure.JS.definterface( clojure.lang, "IPersistentStack",
+ [clojure.lang.IPersistentCollection] );
+
+clojure.JS.definterface( clojure.lang, "Sequential" );
+
+clojure.JS.definterface( clojure.lang, "Reversible" );
+
+clojure.JS.definterface( clojure.lang, "Named" );
+
+clojure.JS.defclass( clojure.lang, "Keyword", {
+ extend: clojure.lang.AFn,
+ implement: [clojure.lang.Named],
+ init: function( ns, name ) {
+ this._ns = ns;
+ this._name = name;
+ },
+ statics: {
+ table: {},
+ intern: function( ns, name ) {
+ var key = (ns || "") + "/" + name,
+ obj = clojure.lang.Keyword.table[ key ];
+ if( obj )
+ return obj;
+ return clojure.lang.Keyword.table[ key ] =
+ new clojure.lang.Keyword( ns, name );
+ }
+ },
+ methods: {
+ toString: function() {
+ return ":" + (this.ns ? this.ns+"/" : "") + this._name;
+ },
+ compareTo: function(o) {
+ if( this == o )
+ return 0;
+ if( this._ns === null && o._ns !== null )
+ return -1;
+ if( this._ns !== null ) {
+ if( o._ns === null )
+ return 1;
+ var nsc = clojure.JS.compare(this._ns, o._ns);
+ if( nsc !== 0 )
+ return nsc;
+ }
+ return clojure.JS.compare(this._name, o._name);
+ },
+ getNamespace: function() { return this._ns; },
+ getName: function() { return this._name; },
+ hashCode: function() {
+ return clojure.lang.Util.hash( this._ns + "/" + this._name );
+ },
+ invoke: function(coll, notFound) { return clojure.core.get( coll,this,notFound);}
+ }
+});
+
+clojure.JS.defclass( clojure.lang, "Ratio", {} );
+
+clojure.JS.defclass( clojure.lang, "Symbol", {
+ extend: clojure.lang.AFn,
+ implement: [clojure.lang.Named],
+ init: function( ns, name ) {
+ this._ns = ns;
+ this._name = name;
+ },
+ statics: {
+ table: {},
+ intern: function( ns, name ) {
+ var key = (ns || "") + "/" + name,
+ obj = clojure.lang.Symbol.table[ key ];
+ if( obj )
+ return obj;
+ return clojure.lang.Symbol.table[ key ] =
+ new clojure.lang.Symbol( ns, name );
+ }
+ },
+ methods: {
+ toString: function() {
+ return (this.ns ? this.ns+"/" : "") + this._name;
+ },
+ compareTo: function(o) {
+ if( this == o )
+ return 0;
+ if( this._ns === null && o._ns !== null )
+ return -1;
+ if( this._ns !== null ) {
+ if( o._ns === null )
+ return 1;
+ var nsc = clojure.JS.compare(this._ns, o._ns);
+ if( nsc !== 0 )
+ return nsc;
+ }
+ return clojure.JS.compare(this._name, o._name);
+ },
+ getNamespace: function() { return this._ns; },
+ getName: function() { return this._name; },
+ hashCode: function() {
+ return clojure.lang.Util.hash( this._ns + "/" + this._name );
+ },
+ invoke: function(coll, notFound) {
+ return clojure.core.get( coll,this,notFound);
+ }
+ }
+});
+
+
+clojure.JS.definterface( clojure.lang, "IPersistentList",
+ [clojure.lang.Sequential, clojure.lang.IPersistentStack] );
+
+clojure.JS.defclass( clojure.lang, "EmptyList", {
+ extend: clojure.lang.Obj,
+ implement: [clojure.lang.IPersistentList, clojure.JS.Collection],
+ init: function( _meta ) { this._meta = _meta; },
+ methods: {
+ cons: function(o) {
+ return new clojure.lang.PersistentList( this.meta(), o );
+ },
+ empty: function() { return this; },
+ withMeta: function(m) {
+ if( m != this.meta() )
+ return new clojure.lang.EmptyList( m );
+ return this;
+ },
+ peek: function() { return null; },
+ pop: function() { throw "Can't pop empty list"; },
+ count: function() { return 0; },
+ seq: function() { return null; },
+ size: function() { return 0; },
+ isEmpty: function() { return true; },
+ contains: function() { return false; },
+ toArray: function() { return clojure.lang.RT.EMPTY_ARRAY; },
+ containsAll: function( coll ) { return coll.isEmpty(); }
+ }
+});
+
+clojure.JS.definterface( clojure.lang, "IMapEntry" );
+
+clojure.JS.definterface( clojure.lang, "Associative",
+ [ clojure.lang.IPersistentCollection ] );
+
+clojure.JS.definterface( clojure.lang, "IPersistentVector",
+ [ clojure.lang.Associative, clojure.lang.Sequential,
+ clojure.lang.IPersistentStack, clojure.lang.Reversible ]);
+
+clojure.JS.defclass( clojure.lang, "AMapEntry", {
+ implement: [ clojure.lang.IMapEntry, clojure.lang.IPersistentVector ],
+ methods: {
+ empty: function(){ return null; },
+ equals: function(o){
+ return clojure.lang.APersistentVector.doEquals(this,o);
+ },
+ hashCode: function(){ throw "not implemented yet"; },
+ toString: function(){
+ return this.key() + " " + this.val();
+ var sw = new clojure.JS.StringWriter();
+ clojure.lang.RT.print( this, sw );
+ return sw.toString();
+ },
+ length: function(){ return 2; },
+ nth: function(i){
+ switch(i){
+ case 0: return this.key();
+ case 1: return this.val();
+ default: throw "Index out of bounds";
+ }
+ },
+ asVector: function(){
+ return clojure.lang.LazilyPersistentVector.createOwning(
+ this.key(), this.val() );
+ },
+ assocN: function(i,v){ return this.asVector().assocN(i,v); },
+ count: function(){ return 2; },
+ seq: function(){ return this.asVector().seq(); },
+ cons: function(o){ return this.asVector().cons(o); },
+ containsKey: function(k){ return this.asVector().containsKey(k); },
+ entryAt: function(k){ return this.asVector().entryAt(k); },
+ assoc: function(k,v){ return this.asVector().assoc(k,v); },
+ valAt: function(k,notFound){ return this.asVector().valAt(k,notFound); },
+ peek: function(){ return this.val(); },
+ pop: function(){
+ return clojure.lang.LazilyPersistentVector.createOwning( this.key() );
+ },
+ rseq: function(){ return this.asVector().rseq(); }
+ }
+});
+
+clojure.JS.defclass( clojure.lang, "MapEntry", {
+ extend: clojure.lang.AMapEntry,
+ init: function(k,v){
+ this._key = k;
+ this._val = v;
+ },
+ methods: {
+ key: function(){ return this._key; },
+ val: function(){ return this._val; },
+ getKey: function(){ return this._key; },
+ getValue: function(){ return this._val; }
+ }
+});
+
+clojure.JS.defclass( clojure.lang, "PersistentList", {
+ extend: clojure.lang.ASeq,
+ implement: [clojure.lang.IPersistentList, clojure.lang.IReduce],
+ init: function( _meta, _first, _rest, _count ) {
+ this._meta = _meta || null;
+ this._first = _first;
+ this._rest = _rest || null;
+ this._count = _count || 1;
+ },
+ statics: {
+ creator: clojure.JS.variadic(0,function(){
+ var args = clojure.JS.rest_args(this,arguments,0),
+ ret, i;
+ if( clojure.JS.instanceq( clojure.lang.ArraySeq, args ) ) {
+ ret = clojure.lang.PersistentList.EMPTY;
+ for( i = args.a.length - 1; i >= 0; --i ) {
+ ret = ret.cons( args.a[ i ] );
+ }
+ return ret;
+ }
+ throw "Not yet implemented: clojure.lang.PersistentList.creator with non-ArraySeq";
+ }),
+ EMPTY: new clojure.lang.EmptyList(null)
+ },
+ methods: {
+ first: function(){ return this._first; },
+ rest: function(){
+ if( this._count == 1 )
+ return null;
+ return this._rest;
+ },
+ peek: function(){ return this.first; },
+ pop: function(){
+ if( this._rest === null )
+ return this.empty();
+ return this._rest;
+ },
+ count: function(){ return this._count; },
+ cons: function(o){
+ return new clojure.lang.PersistentList(
+ this._meta, o, this, this._count + 1 );
+ },
+ empty: function(){
+ return clojure.lang.PersistentList.EMPTY.withMeta( this._meta );
+ },
+ withMeta: function( _meta ){
+ if( _meta != this._meta )
+ return new clojure.lang.PersistentList(
+ this._meta, this._first, this._rest, this._count );
+ return this;
+ },
+ reduce: function( f, start ){
+ var ret = (start === undefined) ? this.first() : f( start, this.first() ),
+ s = this.rest();
+ for( ; s !== null; s = s.rest() )
+ ret = f( ret, s.first() );
+ return ret;
+ }
+ }
+});
+
+clojure.JS.defclass( clojure.lang, "APersistentVector", {
+ extend: clojure.lang.AFn,
+ implement: [clojure.lang.IPersistentVector],
+ init: function( _meta ) { this._meta = _meta; },
+ methods: {
+ meta: function() { return this._meta; },
+ peek: function() {
+ if( this.count() > 0 )
+ return this.nth( this.count() - 1 );
+ return null;
+ },
+ seq: function() {
+ if( this.count() > 0 )
+ return new clojure.lang.APersistentVector.Seq( null, this, 0 );
+ return null;
+ },
+ rseq: function() {
+ if( this.count() > 0 )
+ return new clojure.lang.APersistentVector.RSeq( null, this, this.count() - 1);
+ return null;
+ },
+ equals: function() { throw "not implemented yet"; },
+ hashCode: function() { throw "not implemented yet"; },
+ get: function(i) { return this.nth(i); },
+ indexOf: function( o ){
+ var i = 0, len = this.count();
+ for( ; i < len; ++i )
+ if( clojure.lang.Util.equal( this.nth( i ), o ) )
+ return i;
+ return -1;
+ },
+ lastIndexOf: function( o ){
+ for( var i = this.count() - 1; i >= 0; --i )
+ if( clojure.lang.Util.equal( this.nth( i ), o ) )
+ return i;
+ return -1;
+ },
+ subList: function( fromi, toi ) {
+ return clojure.lang.RT.subvec( this, fromi, toi );
+ },
+ invoke: function( i ) {
+ if( clojure.lang.Util.isInteger(i) )
+ return this.nth( parseInt( i ) );
+ throw "Key must be integer";
+ },
+ peek: function() {
+ if( this.count() > 0 )
+ return this.nth( this.count() - 1 );
+ return null
+ },
+ constainsKey: function(k){
+ if( ! clojure.lang.Util.isInteger( k ) )
+ return false;
+ var i = parseInt(k);
+ return i >= 0 && i < this.count();
+ },
+ entryAt: function(k){
+ if( clojure.lang.Util.isInteger( k ) ) {
+ var i = parseInt(k);
+ if( i >= 0 && i < this.count() )
+ return new clojure.lang.MapEntry( k, this.nth(i) );
+ }
+ return null;
+ },
+ assoc: function(k,v){
+ if( clojure.lang.Util.isInteger( k ) ) {
+ var i = parseInt(k);
+ return this.assocN(i,v);
+ }
+ throw "Key must be integer";
+ },
+ valAt: function(k, notFound){
+ if( clojure.lang.Util.isInteger( k ) ) {
+ var i = parseInt(k);
+ if( i >= 0 && i < this.count() )
+ return this.nth(i);
+ }
+ if( notFound === undefined )
+ return null;
+ return notFound;
+ },
+ toArray: function(){ return clojure.lang.RT.seqToArray( this.seq() ); },
+ containsAll: function(){ throw "not implemented yet"; },
+ size: function(){ return this.count(); },
+ isEmpty: function(){ return this.count() === 0; },
+ contains: function(o){
+ for( var s = this.seq(); s !== null; s = s.rest() ) {
+ if( clojure.lang.Util.equal( s.first(), o ) )
+ return true;
+ }
+ return false;
+ },
+ length: function(){ return this.count(); },
+ compareTo: function(v){
+ var i, c, len = this.count();
+ if( len < v.count() )
+ return -1;
+ else if( len > v.count() )
+ return 1;
+ for( i = 0; i < len; ++i ) {
+ c = this.nth(i).compareTo( v.nth(i) );
+ if( c != 0 )
+ return c;
+ }
+ return 0;
+ }
+ }
+});
+
+clojure.JS.defclass( clojure.lang.APersistentVector, "Seq", {
+ extend: clojure.lang.ASeq,
+ implement: [clojure.lang.IndexedSeq, clojure.lang.IReduce],
+ init: function( _meta, v, i){
+ this._meta = _meta;
+ this.v = v;
+ this.i = i;
+ },
+ methods: {
+ seq: function(){ return this; },
+ first: function(){ return this.v.nth(this.i); },
+ rest: function(){
+ if( this.i + 1 < this.v.count() )
+ return new clojure.lang.APersistentVector.Seq(
+ this._meta, this.v, this