1 // Node vs browser behavior
3 if (typeof module
=== 'undefined') {
9 function _obj_type(obj
) {
10 if (_symbol_Q(obj
)) { return 'symbol'; }
11 else if (_list_Q(obj
)) { return 'list'; }
12 else if (_vector_Q(obj
)) { return 'vector'; }
13 else if (_hash_map_Q(obj
)) { return 'hash-map'; }
14 else if (_nil_Q(obj
)) { return 'nil'; }
15 else if (_true_Q(obj
)) { return 'true'; }
16 else if (_false_Q(obj
)) { return 'false'; }
17 else if (_atom_Q(obj
)) { return 'atom'; }
19 switch (typeof(obj
)) {
20 case 'number': return 'number';
21 case 'function': return 'function';
22 case 'string': return 'string';
23 default: throw new Error("Unknown type '" + typeof(obj
) + "'");
28 function _sequential_Q(lst
) { return _list_Q(lst
) || _vector_Q(lst
); }
31 function _equal_Q (a
, b
) {
32 var ota
= _obj_type(a
), otb
= _obj_type(b
);
33 if (!(ota
=== otb
|| (_sequential_Q(a
) && _sequential_Q(b
)))) {
37 case 'symbol': return a
.value
=== b
.value
;
40 if (a
.length
!== b
.length
) { return false; }
41 for (var i
=0; i
<a
.length
; i
++) {
42 if (! _equal_Q(a
[i
], b
[i
])) { return false; }
46 var akeys
= Object
.keys(a
).sort(),
47 bkeys
= Object
.keys(b
).sort();
48 if (akeys
.length
!== bkeys
.length
) { return false; }
49 for (var i
=0; i
<akeys
.length
; i
++) {
50 if (akeys
[i
] !== bkeys
[i
]) { return false; }
51 if (! equal_Q(a
[akeys
[i
]], b
[bkeys
[i
]])) { return false; }
60 function _clone (obj
) {
62 switch (_obj_type(obj
)) {
64 new_obj
= obj
.slice(0);
67 new_obj
= obj
.slice(0);
68 new_obj
.__isvector__
= true;
73 if (obj
.hasOwnProperty(k
)) { new_obj
[k
] = obj
[k
]; }
77 new_obj
= obj
.clone();
80 throw new Error("clone of non-collection: " + _obj_type(obj
));
87 function _nil_Q(a
) { return a
=== null ? true : false; }
88 function _true_Q(a
) { return a
=== true ? true : false; }
89 function _false_Q(a
) { return a
=== false ? true : false; }
93 function Symbol(name
) {
97 Symbol
.prototype.toString = function() { return this.value
; }
98 function _symbol(name
) { return new Symbol(name
); }
99 function _symbol_Q(obj
) { return obj
instanceof Symbol
; }
103 function _function(Eval
, Env
, ast
, env
, params
) {
104 var fn = function() {
105 return Eval(ast
, new Env(env
, params
, arguments
));
109 fn
.__gen_env__ = function(args
) { return new Env(env
, params
, args
); };
110 fn
._ismacro_
= false;
113 function _function_Q(obj
) { return typeof obj
== "function"; }
114 Function
.prototype.clone = function() {
116 var temp = function () { return that
.apply(this, arguments
); };
118 temp
[key
] = this[key
];
125 function _list() { return Array
.prototype.slice
.call(arguments
, 0); }
126 function _list_Q(obj
) { return Array
.isArray(obj
) && !obj
.__isvector__
; }
131 var v
= Array
.prototype.slice
.call(arguments
, 0);
132 v
.__isvector__
= true;
135 function _vector_Q(obj
) { return Array
.isArray(obj
) && !!obj
.__isvector__
; }
140 function _hash_map() {
141 if (arguments
.length
% 2 === 1) {
142 throw new Error("Odd number of hash map arguments");
144 var args
= [{}].concat(Array
.prototype.slice
.call(arguments
, 0));
145 return _assoc_BANG
.apply(null, args
);
147 function _hash_map_Q(hm
) {
148 return typeof hm
=== "object" &&
149 !Array
.isArray(hm
) &&
151 !(hm
instanceof Atom
);
153 function _assoc_BANG(hm
) {
154 if (arguments
.length
% 2 !== 1) {
155 throw new Error("Odd number of assoc arguments");
157 for (var i
=1; i
<arguments
.length
; i
+=2) {
158 var ktoken
= arguments
[i
],
159 vtoken
= arguments
[i
+1];
160 // TODO: support more than string keys
161 //if (list_Q(ktoken) && hash_map_Q(ktoken)) {
162 // throw new Error("expected hash-map key atom, got collection");
164 if (typeof ktoken
!== "string") {
165 throw new Error("expected hash-map key string, got: " + (typeof ktoken
));
171 function _dissoc_BANG(hm
) {
172 for (var i
=1; i
<arguments
.length
; i
++) {
173 var ktoken
= arguments
[i
];
181 function Atom(val
) { this.val
= val
; }
182 function _atom(val
) { return new Atom(val
); }
183 function _atom_Q(atm
) { return atm
instanceof Atom
; }
187 exports
._obj_type
= types
._obj_type
= _obj_type
;
188 exports
._sequential_Q
= types
._sequential_Q
= _sequential_Q
;
189 exports
._equal_Q
= types
._equal_Q
= _equal_Q
;
190 exports
._clone
= types
._clone
= _clone
;
191 exports
._nil_Q
= types
._nil_Q
= _nil_Q
;
192 exports
._true_Q
= types
._true_Q
= _true_Q
;
193 exports
._false_Q
= types
._false_Q
= _false_Q
;
194 exports
._symbol
= types
._symbol
= _symbol
;
195 exports
._symbol_Q
= types
._symbol_Q
= _symbol_Q
;
196 exports
._function
= types
._function
= _function
;
197 exports
._function_Q
= types
._function_Q
= _function_Q
;
198 exports
._list
= types
._list
= _list
;
199 exports
._list_Q
= types
._list_Q
= _list_Q
;
200 exports
._vector
= types
._vector
= _vector
;
201 exports
._vector_Q
= types
._vector_Q
= _vector_Q
;
202 exports
._hash_map
= types
._hash_map
= _hash_map
;
203 exports
._hash_map_Q
= types
._hash_map_Q
= _hash_map_Q
;
204 exports
._assoc_BANG
= types
._assoc_BANG
= _assoc_BANG
;
205 exports
._dissoc_BANG
= types
._dissoc_BANG
= _dissoc_BANG
;
206 exports
._atom
= types
._atom
= _atom
;
207 exports
._atom_Q
= types
._atom_Q
= _atom_Q
;