//
// $log() - takes any number of arguments of any type and writes them to the console
//
function $log(){
var iterated = new Array();
var newline = (Browser.Engine.trident) ? '    \r' : '\r\n'; // because IE is using firebug lite
var tab = (Browser.Engine.trident) ? '    ' : '\t'; // because IE is using firebug lite
function _prepLog(data, level){
if(!$defined(data)) return;
level = $pick(level, 0);
if(level > 4) return '...'; // who needs to go deeper than this?
var type = $type(data);
var out = '{'+type+'} ';
if( $chk(data.length) ) out+= '('+data.length+') ';
if( ['string','number','boolean','regexp'].contains(type) ) out+= data;
if( type == 'textnode' ) out+= data.data;
if( type == 'whitespace' ) out+= data.data.replace(/ /g,'\\s').replace(/\t/g,tab).replace(/\r?\n/g,newline);
if( type == 'function' ) out+= /^[^{]*/.exec(data).toString().trim();
if( type == 'element' ) {
if(!$defined(data.tagName)) return out; // surely this is the prototype
out+= '<'+data.get('tag')+'>';
data = data.getProperties('id','class','src','href','type','name','value');
type = $type(data);
}
if( ['event','object','array','collection', 'arguments', 'class'].contains(type) && !iterated.contains(data) ) {
iterated.push(data);
if( type == 'arguments' ) data = $A(data);
var indent = tab;
for(i = 0; i < level; i++) indent+=tab;
level++;
for(d in data) if($chk(data[d])) out+= newline+indent+"["+d+'] '+_prepLog(data[d], level);
}
return out;
}

var out = '';
$A(arguments).each(function(a,i) { out+=_prepLog(a,0); if(i < arguments.length) out+=newline+"------"+newline; });
out+=newline;
try{ 
if(Browser.Engine.presto) opera.postError(out); 
else if(Browser.Engine.trident) out.split(newline).each(function(line) { console.log(line); })
else console.log(out); 
}catch(e){  /* no console because IE is dumb */ } 
if(Browser.Engine.trident) try{ console.show() }catch(e) { /* no fauxconsole */ }
return out;
}