diff options
Diffstat (limited to 'clojurescript/clj.js')
-rw-r--r-- | clojurescript/clj.js | 143 |
1 files changed, 97 insertions, 46 deletions
diff --git a/clojurescript/clj.js b/clojurescript/clj.js index 1dcc067c..7e889db6 100644 --- a/clojurescript/clj.js +++ b/clojurescript/clj.js @@ -1,3 +1,13 @@ +// 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, @@ -6,13 +16,20 @@ clojure = { t[ i ] = s[ i ]; } return t; - } + }, + Class: {} }, lang: { Namespace: function( m ) { clojure.JS.merge( this, m || {} ); } } }; +if( ! clojure.JS.global["java"] ) { + java = { lang: { String: {}, Character: {}, Class: {} }, + math: { BigDecimal: {} }, + util: { regex: { Pattern: {} } } }; +} + clojure = new clojure.lang.Namespace({ in_ns: function(s) { var nsparts = s.substring(1).split('.'); @@ -30,9 +47,9 @@ clojure = new clojure.lang.Namespace({ else if( coll.seq ) return coll.seq(); //else if( coll.constructor === String ) // return clojure.lang.StringSeq.create(coll); - else if( typeof coll.length == typeof 0 ) + else if( typeof coll.length == clojure.JS.numberType ) return clojure.lang.ArraySeq.create(coll); - else if( typeof coll === typeof {} ) + 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); @@ -94,10 +111,14 @@ clojure = new clojure.lang.Namespace({ 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( clojure.JS.instanceq( java.util.Map, coll ) ) { + else if( coll.containsKey ) { if( coll.containsKey( key ) ) return new clojure.lang.MapEntry( key, coll.get( key ) ); return null; @@ -105,23 +126,35 @@ clojure = new clojure.lang.Namespace({ return coll.entryAt( key ); }, get: function(coll, key, notFound ) { + var usenull = notFound === undefined; if( coll === null ) - return null; + return usenull ? null : notFound; if( coll.valAt ) return coll.valAt( key, notFound ); - if( coll.containsKey ) { - if( notFound === undefined || coll.containsKey( key ) ) - return coll.get( key ); - return notFound; - } - if( coll.contains ) { - if( notFound === undefined || coll.contains( key ) ) - return coll.get( key ); + 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; + 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( var seq = coll.seq(), i = 0; i <= n && seq; seq = seq.rest() ) { + if( i == n ) + return seq.first(); + } + if( usenull ) + throw "IndexOutOfBoundsException"; return notFound; } - if( notFound === undefined || key in coll ) - return coll[ key ]; - return notFound; + return usenull || n < coll.length ? coll[n] : notFound; }, contains_QMARK_: function(coll, key) { if( coll === null ) @@ -157,6 +190,8 @@ clojure = new clojure.lang.Namespace({ class_: function(o) { if( o === null ) return null; + if( typeof o === clojure.JS.functionType && ! ("constructor" in o) ) + return "" + o; // a Java class? return o.constructor || typeof o; }, import_: function() { @@ -174,6 +209,11 @@ clojure = new clojure.lang.Namespace({ 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; @@ -202,11 +242,11 @@ clojure = new clojure.lang.Namespace({ }, implement: function( cls, name, extend, implement ) { cls.classname = name; + cls.extend = extend; + cls.implement = implement; cls.classset = {}; - cls.hashCode = function() { return clojure.lang.Util.hash( name ); }; - cls.getSuperclass = function() { return extend || null; }; - cls.getInterfaces = function() { return implement || null; }; cls.classset[ name ] = true; + clojure.JS.merge( cls, clojure.JS.classmethods ); if( implement ) { for( var i = 0; i < implement.length; ++i ) { if( ! implement[ i ] ) @@ -233,8 +273,10 @@ clojure = new clojure.lang.Namespace({ return cls; }, instanceq: function( c, o ){ - if( o === null || o.getClass === null ) + 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 ) @@ -248,6 +290,13 @@ clojure = new clojure.lang.Namespace({ } return rtn; }, + classmethods: { + constructor: 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; } + }, ObjSeq: { create: function( obj ) { var pairs = []; @@ -272,25 +321,33 @@ clojure = new clojure.lang.Namespace({ hash: function(o){ if( o === null ) return 0; - if( typeof o == typeof "" ) { - var ret = 0; + if( typeof o == clojure.JS.stringType ) { + var ret = 0; // lousy hand-made string hash for( var i = 0; i < o.length; ++i ) { ret ^= o.charCodeAt(i) << ((i % 4) * 8); } return ret; } - if( o == String ) - return clojure.lang.Util.hash("stringtype"); - if( o == Number ) - return clojure.lang.Util.hash("numbertype"); - if( o == RegExp ) - return clojure.lang.Util.hash("regexptype"); - if( o == Object ) - return clojure.lang.Util.hash("objecttype"); + if( typeof o == clojure.JS.numberType ) { + return o & 0xffffffff; + } + switch( o ) { + case String: return 0x7A837A70; + case Number: return 0x7A837A71; + case RegExp: return 0x7A837A72; + case Object: return 0x7A837A73; + case Function: return 0x7A837A74; + case java.lang.String: + case java.lang.Character: + case java.lang.Class: + case java.math.BigDecimal: + case java.util.regex.Pattern: + return 0x7A830001; + } return o.hashCode(); }, equal: function(x,y) { return x == y; }, - isInteger: function(x) { return typeof x == typeof 0; } + isInteger: function(x) { return typeof x == clojure.JS.numberType; } }, RT: { EMPTY_ARRAY: [], @@ -318,15 +375,9 @@ clojure = new clojure.lang.Namespace({ } }); -java = { util: { regex: {} }, lang: {}, math: {} }; -clojure.JS.definterface( java.util, "Map" ); -clojure.JS.definterface( java.util, "Collection" ); -clojure.JS.definterface( java.util.regex, "Pattern" ); -clojure.JS.definterface( java.lang, "Character" ); -clojure.JS.definterface( java.lang, "Class" ); -clojure.JS.definterface( java.math, "BigDecimal", [Number] ); -clojure.JS.definterface( java.math, "BigInteger", [Number] ); -clojure.JS.defclass( java.lang, "StringBuilder", { +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; }, @@ -334,7 +385,7 @@ clojure.JS.defclass( java.lang, "StringBuilder", { } }); -clojure.JS.defclass( java.lang, "String", { +clojure.JS.defclass( clojure.JS, "String", { init: function(s) { this.s = s; this.length = s.length; @@ -609,7 +660,7 @@ clojure.JS.definterface( clojure.lang, "IPersistentList", clojure.JS.defclass( clojure.lang, "EmptyList", { extend: clojure.lang.Obj, - implement: [clojure.lang.IPersistentList, java.util.Collection], + implement: [clojure.lang.IPersistentList, clojure.JS.Collection], init: function( _meta ) { this._meta = _meta; }, methods: { cons: function(o) { @@ -652,7 +703,7 @@ clojure.JS.defclass( clojure.lang, "AMapEntry", { hashCode: function(){ throw "not implemented yet"; }, toString: function(){ return this.key() + " " + this.val(); - var sw = new java.io.StringWriter(); + var sw = new clojure.JS.StringWriter(); clojure.lang.RT.print( this, sw ); return sw.toString(); }, @@ -1078,7 +1129,7 @@ clojure.JS.definterface( clojure.lang, "IPersistentMap", clojure.JS.defclass( clojure.lang, "APersistentMap", { extend: clojure.lang.AFn, - implement: [clojure.lang.IPersistentMap, java.util.Collection], + implement: [clojure.lang.IPersistentMap, clojure.JS.Collection], init: function(_meta) { this._meta = _meta; this._hash = -1; @@ -1152,7 +1203,7 @@ clojure.JS.defclass( clojure.lang.APersistentMap, "KeySeq", { create: function(seq){ if(seq === null) return null; - return new clojure.lang.APersistentMap.KeySeq(seq); + return new clojure.lang.APersistentMap.KeySeq(null,seq); } }, methods: { @@ -1726,7 +1777,7 @@ clojure.print_method = new clojure.lang.MultiFn( clojure.keyword("","default")); clojure.print_method.addMethod( String, function(s,w) { - return clojure.print_method.apply( null, [new java.lang.String(s), w] ); + return clojure.print_method.apply( null, [new clojure.JS.String(s), w] ); }); clojure.JS.def(clojure,"_STAR_print_readably_STAR_",true); |