Created
December 17, 2012 00:21
-
-
Save skopp/4314544 to your computer and use it in GitHub Desktop.
Brython-20121216-222009
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// brython.js www.brython.info | |
// version 1.0.20121216-222009 | |
// version compiled from commented, indented source files at http://code.google.com/p/brython/ | |
function abs(obj){ | |
if(isinstance(obj,int)){return int(Math.abs(obj))} | |
else if(isinstance(obj,float)){return int(Math.abs(obj.value))} | |
else{$raise('TypeError',"Bad operand type for abs(): '"+str(obj.__class__)+"'")} | |
} | |
function $alert(src){alert(str(src))} | |
function all(iterable){ | |
while(true){ | |
try{ | |
var elt=next(iterable) | |
if(!bool(elt)){return False} | |
}catch(err){return True} | |
} | |
} | |
function any(iterable){ | |
while(true){ | |
try{ | |
var elt=next(iterable) | |
if(bool(elt)){return True} | |
}catch(err){return False} | |
} | |
} | |
function bool(obj){ | |
if(isinstance(obj,dict)){return obj.keys.length>0} | |
else if(isinstance(obj,tuple)){return obj.items.length>0} | |
else if(typeof obj==="boolean"){return obj} | |
else if(typeof obj==="number" || typeof obj==="string"){ | |
if(obj){return true}else{return false} | |
}else if('__bool__' in obj){return obj.__bool__()} | |
else if('__len__' in obj){return obj.__len__()>0} | |
return true | |
} | |
function $confirm(src){return confirm(src)} | |
function $DictClass($keys,$values){ | |
var x=null | |
var i=null | |
this.iter=null | |
this.__class__=dict | |
this.$keys=$keys | |
this.$values=$values | |
} | |
$DictClass.prototype.toString=function(){ | |
if(this.$keys.length==0){return '{}'} | |
var res="{",key=null,value=null,i=null | |
for(i=0;i<this.$keys.length;i++){ | |
if(typeof this.$keys[i]==="string"){key="'"+this.$keys[i]+"'"} | |
else{key=str(this.$keys[i])} | |
if(typeof this.$values[i]==="string"){value="'"+this.$values[i]+"'"} | |
else{value=str(this.$values[i])} | |
res +=key+':'+value+',' | |
} | |
return res.substr(0,res.length-1)+'}' | |
} | |
$DictClass.prototype.__add__=function(other){ | |
var msg="unsupported operand types for +:'dict' and " | |
$raise('TypeError',msg+"'"+(str(other.__class__)|| typeof other)+"'") | |
} | |
$DictClass.prototype.__contains__=function(item){ | |
return this.$keys.__contains__(item) | |
} | |
$DictClass.prototype.__delitem__=function(arg){ | |
for(var i=0;i<this.$keys.length;i++){ | |
if(arg.__eq__(this.$keys[i])){ | |
this.$keys.splice(i,1) | |
this.$values.splice(i,1) | |
return | |
} | |
} | |
$raise('KeyError',str(arg)) | |
} | |
$DictClass.prototype.__eq__=function(other){ | |
if(!isinstance(other,dict)){return False} | |
if(!other.$keys.length==this.$keys.length){return False} | |
for(var i=0;i<this.$keys.length;i++){ | |
test=false | |
var key=this.$keys[i] | |
for(j=0;j<other.$keys.length;j++){ | |
try{ | |
if(other.$keys[j].__eq__(key)){ | |
if(other.$values[j].__eq__($values[i])){ | |
test=true;break | |
} | |
} | |
}catch(err){void(0)} | |
} | |
if(!test){return False} | |
} | |
return True | |
} | |
$DictClass.prototype.__getattr__=function(attr){ | |
return getattr(this,attr) | |
} | |
$DictClass.prototype.__getitem__=function(arg){ | |
for(var i=0;i<this.$keys.length;i++){ | |
if(arg.__eq__(this.$keys[i])){return this.$values[i]} | |
} | |
$raise('KeyError',str(arg)) | |
} | |
$DictClass.prototype.__in__=function(item){return item.__contains__(this)} | |
$DictClass.prototype.__item__=function(i){return this.$keys[i]} | |
$DictClass.prototype.__len__=function(){return this.$keys.length} | |
$DictClass.prototype.__ne__=function(other){return !this.__eq__(other)} | |
$DictClass.prototype.__next__=function(){ | |
if(this.iter==null){this.iter==0} | |
if(this.iter<this.$keys.length){ | |
this.iter++ | |
return this.$keys[this.iter-1] | |
}else{ | |
this.iter=null | |
$raise('StopIteration') | |
} | |
} | |
$DictClass.prototype.__not_in__=function(item){return !(item.__contains__(this))} | |
$DictClass.prototype.__setitem__=function(key,value){ | |
for(var i=0;i<this.$keys.length;i++){ | |
try{ | |
if(key.__eq__(this.$keys[i])){ | |
this.$values[i]=value | |
return | |
} | |
}catch(err){ | |
void(0) | |
} | |
} | |
this.$keys.push(key) | |
this.$values.push(value) | |
} | |
$DictClass.prototype.items=function(){ | |
var res=[] | |
for(var i=0;i<this.$keys.length;i++){ | |
res.push([this.$keys[i],this.$values[i]]) | |
} | |
return res | |
} | |
$DictClass.prototype.keys=function(){return this.$keys} | |
$DictClass.prototype.values=function(){return this.$values} | |
function dict(){ | |
if(arguments.length==0){return new $DictClass([],[])} | |
var iterable=arguments[0] | |
var keys=[],values=[] | |
for(var i=0;i<iterable.__len__();i++){ | |
var elt=iterable.__item__(i) | |
keys.push(elt.__item__(0)) | |
values.push(elt.__item__(1)) | |
} | |
return new $DictClass(keys,values) | |
} | |
function enumerate(iterator){ | |
var res=[] | |
for(var i=0;i<iterator.__len__();i++){ | |
res.push([i,iterator.__item__(i)]) | |
} | |
return res | |
} | |
function filter(){ | |
if(arguments.length!=2){$raise('TypeError', | |
"filter expected 2 arguments, got "+arguments.length)} | |
var func=arguments[0],iterable=arguments[1] | |
var res=[] | |
for(var i=0;i<iterable.__len__();i++){ | |
if(func(iterable.__item__(i))){ | |
res.push(iterable.__item__(i)) | |
} | |
} | |
return res | |
} | |
function $FloatClass(value){ | |
this.value=value | |
this.__class__=float | |
} | |
$FloatClass.prototype.toString=function(){ | |
var res=this.value+'' | |
if(res.indexOf('.')==-1){res+='.0'} | |
return str(res) | |
} | |
$FloatClass.prototype.__bool__=function(){return bool(this.value)} | |
$FloatClass.prototype.__floordiv__=function(other){ | |
if(isinstance(other,int)){return float(Math.floor(this.value/other))} | |
else if(isinstance(other,float)){return float(Math.floor(this.value/other.value))} | |
else{$raise('TypeError', | |
"unsupported operand type(s) for //: 'int' and '"+other.__class__+"'") | |
} | |
} | |
$FloatClass.prototype.__in__=function(item){return item.__contains__(this)} | |
$FloatClass.prototype.__not_in__=function(item){return !(item.__contains__(this))} | |
var $op_func=function(other){ | |
if(isinstance(other,int)){return float(this.value-other)} | |
else if(isinstance(other,float)){return float(this.value-other.value)} | |
else{$raise('TypeError', | |
"unsupported operand type(s) for -: "+this.value+" (float) and '"+other.__class__+"'") | |
} | |
} | |
$op_func +='' | |
var $ops={'+':'add','-':'sub','*':'mul','/':'truediv','%':'mod'} | |
for($op in $ops){ | |
eval('$FloatClass.prototype.__'+$ops[$op]+'__ = '+$op_func.replace(/-/gm,$op)) | |
} | |
var $comp_func=function(other){ | |
if(isinstance(other,int)){return this.value > other.valueOf()} | |
else if(isinstance(other,float)){return this.value > other.value} | |
else{$raise('TypeError', | |
"unorderable types: "+this.__class__+'() > '+other.__class__+"()") | |
} | |
} | |
$comp_func +='' | |
var $comps={'>':'gt','>=':'ge','<':'lt','<=':'le','==':'eq','!=':'ne'} | |
for($op in $comps){ | |
eval("$FloatClass.prototype.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op)) | |
} | |
var $notimplemented=function(other){ | |
$raise('TypeError', | |
"unsupported operand types for OPERATOR: '"+this.__class__+"' and '"+other.__class__+"'") | |
} | |
$notimplemented +='' | |
for($op in $operators){ | |
var $opfunc='__'+$operators[$op]+'__' | |
if(!($opfunc in $FloatClass.prototype)){ | |
eval('$FloatClass.prototype.'+$opfunc+"="+$notimplemented.replace(/OPERATOR/gm,$op)) | |
} | |
} | |
function float(value){ | |
if(typeof value=="number" ||( | |
typeof value=="string" && parseFloat(value)!=NaN)){ | |
return new $FloatClass(parseFloat(value)) | |
}else if(isinstance(value,float)){return value} | |
else{$raise('ValueError',"Could not convert to float(): '"+str(value)+"'")} | |
} | |
function $bind(func, thisValue){ | |
return function(){return func.apply(thisValue, arguments)} | |
} | |
function getattr(obj,attr,_default){ | |
if(attr in obj){ | |
var res=obj[attr] | |
if(typeof res==="function"){ | |
res=$bind(res, obj) | |
} | |
return $JS2Py(res) | |
} | |
else if(_default !==undefined){return _default} | |
else{$raise('AttributeError', | |
"'"+str(obj.__class__)+"' object has no attribute '"+attr+"'")} | |
} | |
function hasattr(obj,attr){ | |
try{getattr(obj,attr);return True} | |
catch(err){return False} | |
} | |
function $import(){ | |
var js_modules=$List2Dict('time','datetime','math','random','sys') | |
var calling={'line':document.line_num,'context':document.$context} | |
for(var i=0;i<arguments.length;i++){ | |
module=arguments[i] | |
if(!isinstance(module,str)){$raise('SyntaxError',"invalid syntax")} | |
var res='' | |
var is_js=module in js_modules | |
if(window.XMLHttpRequest){ | |
var $xmlhttp=new XMLHttpRequest() | |
}else{ | |
var $xmlhttp=new ActiveXObject("Microsoft.XMLHTTP") | |
} | |
$xmlhttp.onreadystatechange=function(){ | |
if($xmlhttp.readyState==4){ | |
window.clearTimeout(timer) | |
if($xmlhttp.status==200){res=$xmlhttp.responseText} | |
else{ | |
document.$context=calling.context | |
document.line_num=calling.line | |
$raise('ImportError',"No module named '"+module+"'") | |
} | |
} | |
} | |
var fake_qs='?foo='+Math.random().toString(36).substr(2,8) | |
if(is_js){$xmlhttp.open('GET','/'+module+'.js'+fake_qs,false)} | |
else{$xmlhttp.open('GET',module+'.py'+fake_qs,false)} | |
var timer=setTimeout(function(){ | |
$xmlhttp.abort() | |
document.$context=calling.context | |
document.line_num=calling.line | |
$raise('ImportError',"No module named '"+module+"'")}, 5000) | |
$xmlhttp.send() | |
if(is_js){ | |
try{eval(res)}catch(err){$raise('ImportError',err.message)} | |
}else{ | |
var stack=$py2js(res,module) | |
stack.list.splice(0,0,['code',module+'= new object()'],['newline','\n']) | |
var $pos=0 | |
while(true){ | |
var $mlname_pos=stack.find_next_at_same_level($pos,"keyword","function") | |
if($mlname_pos===null){break} | |
var $func_name=stack.list[$mlname_pos+1][1] | |
stack.list.splice($mlname_pos,2,['code',module+'.'+$func_name+"=function"]) | |
var $fend=stack.find_next_at_same_level($mlname_pos,"func_end") | |
var $fend_code=stack.list[$fend][1] | |
$fend_code=module+'.'+$fend_code.substr(1) | |
$pv_pos=$fend_code.search(';') | |
$fend_code=";"+$fend_code.substr(0,$pv_pos) | |
stack.list[$fend][1]=$fend_code | |
$pos=$mlname_pos+1 | |
} | |
var $pos=0 | |
while(true){ | |
var $mlname_pos=stack.find_next_at_same_level($pos,"assign_id") | |
if($mlname_pos===null){break} | |
stack.list[$mlname_pos][1]=module+'.'+stack.list[$mlname_pos][1] | |
$pos=$mlname_pos+1 | |
} | |
eval(stack.to_js()) | |
} | |
} | |
} | |
function $getNumClass(obj){ | |
return "int" | |
} | |
Number.prototype.__class__=$getNumClass(this) | |
Number.prototype.__floordiv__=function(other){ | |
if(isinstance(other,int)){return Math.floor(this/other)} | |
else if(isinstance(other,float)){return float(Math.floor(this/other.value))} | |
else{$UnsupportedOpType("//","int",other.__class__)} | |
} | |
Number.prototype.__getattr__=function(attr){$raise('AttributeError', | |
"'int' object has no attribute '"+attr+"'")} | |
Number.prototype.__in__=function(item){return item.__contains__(this)} | |
Number.prototype.__int__=function(){return this} | |
Number.prototype.__mul__=function(other){ | |
var val=this.valueOf() | |
if(isinstance(other,int)){return this*other} | |
else if(isinstance(other,float)){return float(this*other.value)} | |
else if(typeof other==="string"){ | |
var res='' | |
for(var i=0;i<val;i++){res+=other} | |
return res | |
}else if(isinstance(other,list)){ | |
var res=[] | |
var $temp=other.slice(0,other.length) | |
for(var i=0;i<val-1;i++){res=res.concat($temp)} | |
return res | |
}else{$UnsupportedOpType("*",int,other)} | |
} | |
Number.prototype.__not_in__=function(item){ | |
res=item.__contains__(this) | |
return !res | |
} | |
Number.prototype.__pow__=function(other){ | |
if(typeof other==="number"){return int(Math.pow(this.valueOf(),other.valueOf()))} | |
else{$UnsupportedOpType("//",int,other.__class__)} | |
} | |
Number.prototype.__setattr__=function(attr,value){$raise('AttributeError', | |
"'int' object has no attribute "+attr+"'")} | |
Number.prototype.__str__=function(){return this.toString()} | |
var $op_func=function(other){ | |
if(isinstance(other,int)){ | |
var res=this.valueOf()-other.valueOf() | |
if(isinstance(res,int)){return res} | |
else{return float(res)} | |
} | |
else if(isinstance(other,float)){return float(this.valueOf()-other.value)} | |
else{$raise('TypeError', | |
"unsupported operand type(s) for -: "+this.value+" (float) and '"+str(other.__class__)+"'") | |
} | |
} | |
$op_func +='' | |
var $ops={'+':'add','-':'sub','/':'truediv','%':'mod'} | |
for($op in $ops){ | |
eval('Number.prototype.__'+$ops[$op]+'__ = '+$op_func.replace(/-/gm,$op)) | |
} | |
var $comp_func=function(other){ | |
if(isinstance(other,int)){return this.valueOf()> other.valueOf()} | |
else if(isinstance(other,float)){return this.valueOf()> other.value} | |
else{$raise('TypeError', | |
"unorderable types: "+str(this.__class__)+'() > '+str(other.__class__)+"()")} | |
} | |
$comp_func +='' | |
var $comps={'>':'gt','>=':'ge','<':'lt','<=':'le','==':'eq','!=':'ne'} | |
for($op in $comps){ | |
eval("Number.prototype.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op)) | |
} | |
var $notimplemented=function(other){ | |
$raise('TypeError', | |
"unsupported operand types for OPERATOR: '"+str(this.__class__)+"' and '"+str(other.__class__)+"'") | |
} | |
$notimplemented +='' | |
for($op in $operators){ | |
var $opfunc='__'+$operators[$op]+'__' | |
if(!($opfunc in Number.prototype)){ | |
eval('Number.prototype.'+$opfunc+"="+$notimplemented.replace(/OPERATOR/gm,$op)) | |
} | |
} | |
function int(value){ | |
if(typeof value=="number" || | |
(typeof value=="string" && parseInt(value)!=NaN)){ | |
return parseInt(value) | |
}else if(isinstance(value,float)){ | |
return parseInt(value.value) | |
}else{$raise('ValueError', | |
"Invalid literal for int() with base 10: '"+str(value)+"'") | |
} | |
} | |
function isinstance(obj,arg){ | |
if(arg.constructor===Array){ | |
for(var i=0;i<arg.length;i++){ | |
if(isinstance(obj,arg[i])){return true} | |
} | |
return false | |
}else{ | |
if(arg===int){ | |
return(typeof obj=="number"||obj.constructor===Number)&&(obj.valueOf()%1===0) | |
} | |
if(arg===float){ | |
return((typeof obj=="number")&&(obj.valueOf()%1!==0))|| | |
(obj.__class__===float)} | |
if(arg===str){return(typeof obj=="string")} | |
if(arg===list){return(obj.constructor===Array)} | |
if(obj.__class__!==undefined){return obj.__class__===arg} | |
return obj.constructor===arg | |
} | |
} | |
function iter(obj){ | |
if('__item__' in obj){ | |
obj.__counter__=0 | |
return obj | |
} | |
$raise('TypeError',"'"+str(obj.__class__)+"' object is not iterable") | |
} | |
function len(obj){ | |
try{return obj.__len__()} | |
catch(err){$raise('TypeError',"object of type "+str(obj.__class__)+" has no len()")} | |
} | |
function log(){ | |
$ns=$MakeArgs(arguments,[],{},'args') | |
if(!('end' in $ns)){$ns['end']='\n'} | |
for(var i=0;i<$ns['args'].length;i++){ | |
console.log(str($ns['args'][i])+str($ns['end'])) | |
} | |
} | |
function map(){ | |
var func=arguments[0],res=[],rank=0 | |
while(true){ | |
var args=[],flag=true | |
for(var i=1;i<arguments.length;i++){ | |
var x=arguments[i].__item__(rank) | |
if(x===undefined){flag=false;break} | |
args.push(x) | |
} | |
if(!flag){break} | |
res.push(func.apply(null,args)) | |
rank++ | |
} | |
return res | |
} | |
function $extreme(args,op){ | |
if(op==='__gt__'){var $op_name="max"} | |
else{var $op_name="min"} | |
if(args.length==0){$raise('TypeError',$op_name+" expected 1 argument, got 0")} | |
var last_arg=args[args.length-1] | |
var last_i=args.length-1 | |
var has_key=false | |
if(isinstance(last_arg,$Kw)){ | |
if(last_arg.name==='key'){ | |
var func=last_arg.value | |
has_key=true | |
last_i-- | |
}else{$raise('TypeError',$op_name+"() got an unexpected keyword argument")} | |
}else{var func=function(x){return x}} | |
if((has_key && args.length==2)||(!has_key && args.length==1)){ | |
var arg=args[0] | |
var $iter=iter(arg) | |
var res=null | |
while(true){ | |
try{ | |
var x=next($iter) | |
if(res===null || bool(func(x)[op](func(res)))){res=x} | |
}catch(err){ | |
if(err.name=="StopIteration"){return res} | |
throw err | |
} | |
} | |
}else{ | |
var res=null | |
for(var i=0;i<=last_i;i++){ | |
var x=args[i] | |
if(res===null || bool(func(x)[op](func(res)))){res=x} | |
} | |
return res | |
} | |
} | |
function max(){ | |
var args=[] | |
for(var i=0;i<arguments.length;i++){args.push(arguments[i])} | |
return $extreme(args,'__gt__') | |
} | |
function min(){ | |
var args=[] | |
for(var i=0;i<arguments.length;i++){args.push(arguments[i])} | |
return $extreme(args,'__lt__') | |
} | |
function next(obj){ | |
if('__item__' in obj){ | |
if(obj.__counter__===undefined){obj.__counter__=0} | |
var res=obj.__item__(obj.__counter__) | |
if(res!==undefined){obj.__counter__++;return res} | |
$raise('StopIteration') | |
} | |
$raise('TypeError',"'"+str(obj.__class__)+"' object is not iterable") | |
} | |
function $not(obj){return !bool(obj)} | |
function $ObjectClass(){ | |
} | |
$ObjectClass.prototype.__getattr__=function(attr){ | |
if(attr in this){return this[attr]} | |
else{$raise('AttributeError',"object has no attribute '"+attr+"'")} | |
} | |
$ObjectClass.prototype.__delattr__=function(attr){delete this[attr]} | |
$ObjectClass.prototype.__setattr__=function(attr,value){this[attr]=value} | |
function object(){ | |
return new $ObjectClass() | |
} | |
function $prompt(src){return str(prompt(src))} | |
function range(){ | |
if(arguments.length>3){$raise('TypeError', | |
"range expected at most 3 arguments, got "+arguments.length) | |
} | |
var start=0 | |
var stop=0 | |
var step=1 | |
if(arguments.length==1){ | |
stop=arguments[0] | |
}else if(arguments.length>=2){ | |
start=arguments[0] | |
stop=arguments[1] | |
} | |
if(arguments.length>=3){ | |
step=arguments[2] | |
} | |
if(step==0){$raise('ValueError',"range() arg 3 must not be zero")} | |
var res=[] | |
if(step>0){ | |
for(var i=start;i<stop;i+=step){res.push(i)} | |
}else if(step<0){ | |
for(var i=start;i>stop;i+=step){res.push(i)} | |
} | |
return res | |
} | |
function reversed(seq){ | |
if(isinstance(seq,list)){seq.reverse();return seq} | |
else if(isinstance(seq,str)){ | |
var res='' | |
for(var i=seq.length-1;i>=0;i--){res+=seq.charAt(i)} | |
return res | |
}else{$raise('TypeError', | |
"argument to reversed() must be a sequence")} | |
} | |
function round(arg,n){ | |
if(!isinstance(arg,[int,float])){ | |
$raise('TypeError',"type "+str(arg.__class__)+" doesn't define __round__ method") | |
} | |
if(n===undefined){n=0} | |
if(!isinstance(n,int)){$raise('TypeError', | |
"'"+n.__class__+"' object cannot be interpreted as an integer")} | |
var mult=Math.pow(10,n) | |
return Number(Math.round(arg*mult)).__truediv__(mult) | |
} | |
function $SetClass(){ | |
var x=null | |
var i=null | |
this.iter=null | |
this.__class__=set | |
this.items=[] | |
} | |
$SetClass.prototype.toString=function(){ | |
var res="[" | |
for(var i=0;i<this.items.length;i++){ | |
var x=this.items[i] | |
if(isinstance(x,str)){res +="'"+x+"'"} | |
else{res +=x.toString()} | |
if(i<this.items.length-1){res +=','} | |
} | |
return res+']' | |
} | |
$SetClass.prototype.__add__=function(other){ | |
return set(this.items.concat(other.items)) | |
} | |
$SetClass.prototype.__contains__=function(item){ | |
for(var i=0;i<this.items.length;i++){ | |
try{if(this.items[i].__eq__(item)){return True} | |
}catch(err){void(0)} | |
} | |
return False | |
} | |
$SetClass.prototype.__eq__=function(other){ | |
if(isinstance(other,set)){ | |
if(other.items.length==this.items.length){ | |
for(var i=0;i<this.items.length;i++){ | |
if(this.__contains__(other.items[i])===False){ | |
return False | |
} | |
} | |
return True | |
} | |
} | |
return False | |
} | |
$SetClass.prototype.__in__=function(item){return item.__contains__(this)} | |
$SetClass.prototype.__len__=function(){return int(this.items.length)} | |
$SetClass.prototype.__ne__=function(other){return !(this.__eq__(other))} | |
$SetClass.prototype.__item__=function(i){return this.items[i]} | |
$SetClass.prototype.__not_in__=function(item){return !(item.__contains__(this))} | |
$SetClass.prototype.add=function(item){ | |
var i=0 | |
for(i=0;i<this.items.length;i++){ | |
try{if(item.__eq__(this.items[i])){return}} | |
catch(err){void(0)} | |
} | |
this.items.push(item) | |
} | |
function set(){ | |
var i=0 | |
if(arguments.length==0){return new $SetClass()} | |
else if(arguments.length==1){ | |
var arg=arguments[0] | |
if(isinstance(arg,set)){return arg} | |
var obj=new $SetClass() | |
try{ | |
for(var i=0;i<arg.__len__();i++){ | |
obj.items.push(arg.__getitem__(i)) | |
} | |
return obj | |
}catch(err){ | |
$raise('TypeError',"'"+str(args[0].__class__)+"' object is not iterable") | |
} | |
}else{ | |
$raise('TypeError',"set expected at most 1 argument, got "+arguments.length) | |
} | |
} | |
function setattr(obj,attr,value){ | |
if(!isinstance(attr,str)){$raise('TypeError',"setattr(): attribute name must be string")} | |
obj[attr]=value | |
} | |
function sum(iterable,start){ | |
if(start===undefined){start=0} | |
var res=0 | |
for(var i=start;i<iterable.__len__();i++){ | |
res +=iterable.__item__(i) | |
} | |
return res | |
} | |
function $tuple(arg){return arg} | |
function tuple(){ | |
var args=new Array(),i=0 | |
for(i=0;i<arguments.length;i++){args.push(arguments[i])} | |
var obj=list(args) | |
obj.__class__=tuple | |
return obj | |
} | |
function zip(){ | |
var rank=0,res=[] | |
while(true){ | |
var line=[],flag=true | |
for(var i=0;i<arguments.length;i++){ | |
var x=arguments[i].__item__(rank) | |
if(x===undefined){flag=false;break} | |
line.push(x) | |
} | |
if(!flag){return res} | |
res.push(line) | |
rank++ | |
} | |
} | |
True=true | |
False=false | |
Boolean.prototype.toString=function(){ | |
if(this.valueOf()){return "True"}else{return "False"} | |
} | |
function $NoneClass(){ | |
this.__class__="None" | |
this.value=null | |
this.__bool__=function(){return False} | |
this.__eq__=function(other){return other.__class__=="None"} | |
this.__str__=function(){return str('None')} | |
} | |
None=new $NoneClass() | |
function $SliceClass(start,stop,step){ | |
this.__class__=slice | |
this.start=start | |
this.stop=stop | |
this.step=step | |
} | |
function slice(){ | |
var start=arguments[0]|| null | |
var stop=arguments[1] | |
if(typeof stop!=="number"){stop=null} | |
var step=arguments[2]|| null | |
var indices=[start,stop,step] | |
for(var i=0;i<indices.length;i++){ | |
if(indices[i]===null){continue} | |
if(!isinstance(indices[i],int)){$raise('TypeError', | |
"slice indices must be integers or None or have an __index__ method")} | |
} | |
if(step!==null){ | |
if(step===0){$raise('ValueError','slice step cannot be zero')} | |
} | |
return new $SliceClass(start,stop,step) | |
} | |
function $KwClass(name,value){ | |
this.__class__=$Kw | |
this.name=name | |
this.value=value | |
} | |
function $Kw(name,value){ | |
return new $KwClass(name,value) | |
} | |
function $ListClass(items){ | |
var x=null,i=null | |
this.iter=null | |
this.__class__=list | |
this.items=items | |
} | |
Array.prototype.__add__=function(other){ | |
return this.valueOf().concat(other.valueOf()) | |
} | |
Array.prototype.__contains__=function(item){ | |
for(var i=0;i<this.length;i++){ | |
try{if(this[i].__eq__(item)){return true} | |
}catch(err){void(0)} | |
} | |
return false | |
} | |
Array.prototype.__delitem__=function(arg){ | |
if(isinstance(arg,int)){ | |
var pos=arg | |
if(arg<0){pos=this.length+pos} | |
if(pos>=0 && pos<this.length){ | |
this.splice(pos,1) | |
return | |
} | |
else{$raise('IndexError','list index out of range')} | |
}else if(isinstance(arg,slice)){ | |
var start=arg.start || 0 | |
var stop=arg.stop || this.length | |
var step=arg.step || 1 | |
if(start<0){start=this.length+start} | |
if(stop<0){stop=this.length+stop} | |
var res=[],i=null | |
if(step>0){ | |
if(stop>start){ | |
for(i=start;i<stop;i+=step){ | |
if(this[i]!==undefined){res.push(i)} | |
} | |
} | |
}else{ | |
if(stop<start){ | |
for(i=start;i>stop;i+=step.value){ | |
if(this[i]!==undefined){res.push(i)} | |
} | |
res.reverse() | |
} | |
} | |
for(var i=res.length-1;i>=0;i--){ | |
this.splice(res[i],1) | |
} | |
return | |
}else{ | |
$raise('TypeError','list indices must be integer, not '+str(arg.__class__)) | |
} | |
} | |
Array.prototype.__eq__=function(other){ | |
if(isinstance(other,list)){ | |
if(other.length==this.length){ | |
for(var i=0;i<this.length;i++){ | |
if(!this[i].__eq__(other[i])){return False} | |
} | |
return True | |
} | |
} | |
return False | |
} | |
Array.prototype.__getattr__=function(attr){ | |
obj=this | |
switch(attr){ | |
case 'append': | |
return function(other){obj.push(other)} | |
case 'count': | |
return $list_count(obj) | |
case 'extend': | |
return $list_extend(obj) | |
case 'index': | |
return $list_index(obj) | |
case 'reverse': | |
return function(){$list_reverse(obj)} | |
case 'sort': | |
return function(arg){$list_sort(obj,arg)} | |
default: | |
return this[attr] | |
} | |
} | |
Array.prototype.__getitem__=function(arg){ | |
if(isinstance(arg,int)){ | |
var items=this.valueOf() | |
var pos=arg | |
if(arg<0){pos=items.length+pos} | |
if(pos>=0 && pos<items.length){return items[pos]} | |
else{$raise('IndexError','list index out of range')} | |
}else if(isinstance(arg,slice)){ | |
var start=arg.start || 0 | |
var stop=arg.stop || this.length | |
var step=arg.step || 1 | |
if(start<0){start=int(this.length+start)} | |
if(stop<0){stop=this.length+stop} | |
var res=[],i=null,items=this.valueOf() | |
if(step>0){ | |
if(stop<=start){return res} | |
else{ | |
for(i=start;i<stop;i+=step){ | |
if(items[i]!==undefined){res.push(items[i])} | |
} | |
return res | |
} | |
}else{ | |
if(stop>=start){return res} | |
else{ | |
for(i=start;i>stop;i+=step){ | |
if(items[i]!==undefined){res.push(items[i])} | |
} | |
return res | |
} | |
} | |
}else{ | |
$raise('TypeError','list indices must be integer, not '+str(arg.__class__)) | |
} | |
} | |
Array.prototype.__item__=function(i){return this[i]} | |
Array.prototype.__in__=function(item){return item.__contains__(this)} | |
Array.prototype.__len__=function(){return this.length} | |
Array.prototype.__ne__=function(other){return !this.__eq__(other)} | |
Array.prototype.__next__=function(){ | |
if(this.iter===null){this.iter=0} | |
if(this.iter<this.valueOf().length){ | |
this.iter++ | |
return this.valueOf()[this.iter-1] | |
}else{ | |
this.iter=null | |
$raise('StopIteration') | |
} | |
} | |
Array.prototype.__not_in__=function(item){return !item.__contains__(this)} | |
Array.prototype.__setitem__=function(arg,value){ | |
if(isinstance(arg,int)){ | |
var pos=arg | |
if(arg<0){pos=this.length+pos} | |
if(pos>=0 && pos<this.length){this[pos]=value} | |
else{$raise('IndexError','list index out of range')} | |
}else if(isinstance(arg,slice)){ | |
var start=arg.start || 0 | |
if(arg.stop===null){stop=this.__len__()}else{stop=arg.stop} | |
var step=arg.step || 1 | |
if(start<0){start=this.length+start} | |
if(stop<0){stop=this.length+stop} | |
this.splice(start,stop-start) | |
var $temp=value.slice(0,value.length) | |
for(var i=value.length-1;i>=0;i--){ | |
this.splice(start,0,$temp[i]) | |
} | |
}else{ | |
$raise('TypeError','list indices must be integer, not '+str(arg.__class__)) | |
} | |
} | |
Array.prototype.toString=function(){ | |
var res="[",i=null,items=this.valueOf() | |
for(i=0;i<items.length;i++){ | |
var x=items[i] | |
if(isinstance(x,str)){res +="'"+x+"'"} | |
else{res +=x.toString()} | |
if(i<items.length-1){res +=','} | |
} | |
return res+']' | |
} | |
function $list_count(obj){ | |
return function(elt){ | |
var res=0 | |
for(var i=0;i<obj.length;i++){ | |
if(obj[i].__eq__(elt)){res++} | |
} | |
return res | |
} | |
} | |
function $list_extend(obj){ | |
return function(other){ | |
if(arguments.length!=1){$raise('TypeError', | |
"extend() takes exactly one argument ("+arguments.length+" given)")} | |
try{ | |
for(var i=0;i<other.__len__();i++){ | |
obj.push(other.__item__(i)) | |
} | |
}catch(err){ | |
$raise('TypeError',"object is not iterable") | |
} | |
} | |
} | |
function $list_index(obj){ | |
return function(elt){ | |
for(var i=0;i<obj.length;i++){ | |
if(obj[i].__eq__(elt)){return i} | |
} | |
$raise('ValueError',str(elt)+" is not in list") | |
} | |
} | |
function $list_reverse(obj){ | |
for(var i=0;i<parseInt(obj.length/2);i++){ | |
buf=obj[i] | |
obj[i]=obj[obj.length-i-1] | |
obj[obj.length-i-1]=buf | |
} | |
} | |
function $partition(arg,array,begin,end,pivot) | |
{ | |
var piv=array[pivot] | |
array.swap(pivot, end-1) | |
var store=begin | |
var ix | |
for(ix=begin;ix<end-1;++ix){ | |
if(arg(array[ix]).__le__(arg(piv))){ | |
array.swap(store, ix) | |
++store | |
} | |
} | |
array.swap(end-1, store) | |
return store | |
} | |
Array.prototype.swap=function(a, b) | |
{ | |
var tmp=this[a] | |
this[a]=this[b] | |
this[b]=tmp | |
} | |
function $qsort(arg,array, begin, end) | |
{ | |
if(end-1>begin){ | |
var pivot=begin+Math.floor(Math.random()*(end-begin)) | |
pivot=$partition(arg,array, begin, end, pivot) | |
$qsort(arg,array, begin, pivot) | |
$qsort(arg,array, pivot+1, end) | |
} | |
} | |
function $list_sort(obj,arg){ | |
if(!arg){arg=function(x){return x}} | |
else if(typeof arg==="string"){arg=function(x){return x.__getitem__(arg)}} | |
if(obj.length==0){return} | |
$qsort(arg,obj,0,obj.length) | |
} | |
function $list(){ | |
var args=new Array(),i=0 | |
for(i=0;i<arguments.length;i++){args.push(arguments[i])} | |
return new $ListClass(args) | |
} | |
function list(){ | |
if(arguments.length==1){ | |
if(isinstance(arguments[0],list)){return arguments[0]} | |
var res=[] | |
try{ | |
for(var i=0;i<arguments[0].__len__();i++){ | |
res.push(arguments[0].__getitem__(i)) | |
} | |
return res | |
}catch(err){ | |
$raise('TypeError',"'"+str(args[0].__class__)+"' object is not iterable") | |
} | |
}else{ | |
$raise('TypeError',"list() takes at most 1 argument ("+args.length+" given)") | |
} | |
} | |
String.prototype.__add__=function(other){ | |
if(!(typeof other==="string")){ | |
try{return other.__radd__(this)} | |
catch(err){$raise('TypeError', | |
"Can't convert "+other.__class__+" to str implicitely")} | |
}else{ | |
return this+other | |
} | |
} | |
String.prototype.__contains__=function(item){ | |
if(!(typeof item==="string")){$raise('TypeError', | |
"'in <string>' requires string as left operand, not "+item.__class__)} | |
var nbcar=item.length | |
for(var i=0;i<this.length;i++){ | |
if(this.substr(i,nbcar)==item){return True} | |
} | |
return False | |
} | |
String.prototype.__getattr__=function(attr){ | |
obj=this | |
switch(attr){ | |
case 'capitalize': | |
return $string_capitalize(obj) | |
case 'center': | |
return $string_center(obj) | |
case 'count': | |
return $string_count(obj) | |
case 'endswith': | |
return $string_endswith(obj) | |
case 'find': | |
return $string_find(obj) | |
case 'index': | |
return $string_index(obj) | |
case 'join': | |
return $string_join(obj) | |
case 'lower': | |
return $string_lower(obj) | |
case 'lstrip': | |
return $string_lstrip(obj) | |
case 'replace': | |
return $string_replace(obj) | |
case 'rfind': | |
return $string_rfind(obj) | |
case 'rindex': | |
return $string_rindex(obj) | |
case 'rstrip': | |
return $string_rstrip(obj) | |
case 'split': | |
return $string_split(obj) | |
case 'startswith': | |
return $string_startswith(obj) | |
case 'strip': | |
return $string_strip(obj) | |
case 'upper': | |
return $string_upper(obj) | |
default: | |
return this[attr] | |
} | |
} | |
String.prototype.__getitem__=function(arg){ | |
if(isinstance(arg,int)){ | |
var pos=arg | |
if(arg<0){pos=this.length+pos} | |
if(pos>=0 && pos<this.length){return this.charAt(pos)} | |
else{$raise('IndexError','string index out of range')} | |
}else if(isinstance(arg,slice)){ | |
var start=arg.start || 0 | |
if(arg.stop===null){stop=this.__len__()}else{stop=arg.stop} | |
var step=arg.step || 1 | |
if(start<0){start=this.length+start} | |
if(stop<0){stop=this.length+stop} | |
var res='',i=null | |
if(step>0){ | |
if(stop<=start){return ''} | |
else{ | |
for(i=start;i<stop;i+=step){ | |
res +=this.charAt(i) | |
} | |
} | |
}else{ | |
if(stop>=start){return ''} | |
else{ | |
for(i=start;i>stop;i+=step){ | |
res +=this.charAt(i) | |
} | |
} | |
} | |
return res | |
} | |
} | |
String.prototype.__in__=function(item){return item.__contains__(this.valueOf())} | |
String.prototype.__item__=function(i){return this.charAt(i)} | |
String.prototype.__len__=function(){return this.length} | |
String.prototype.__mod__=function(args){ | |
var flags=$List2Dict('#','0','-',' ','+') | |
var ph=[] | |
function format(s){ | |
var conv_flags='([#\\+\\- 0])*' | |
var conv_types='[diouxXeEfFgGcrsa%]' | |
var re=new RegExp('\\%(\\(.+\\))*'+conv_flags+'(\\*|\\d*)(\\.\\*|\\.\\d*)*(h|l|L)*('+conv_types+'){1}') | |
var res=re.exec(s) | |
this.is_format=true | |
if(res===undefined){this.is_format=false;return} | |
this.src=res[0] | |
if(res[1]){this.mapping_key=str(res[1].substr(1,res[1].length-2))} | |
else{this.mapping_key=null} | |
this.flag=res[2] | |
this.min_width=res[3] | |
this.precision=res[4] | |
this.length_modifier=res[5] | |
this.type=res[6] | |
this.toString=function(){ | |
var res='type '+this.type+' key '+this.mapping_key+' min width '+this.min_width | |
res +=' precision '+this.precision | |
return res | |
} | |
this.format=function(src){ | |
if(this.mapping_key!==null){ | |
if(!isinstance(src,dict)){$raise('TypeError',"format requires a mapping")} | |
src=src.__getitem__(this.mapping_key) | |
} | |
if(this.type=="s"){return str(src)} | |
else if(this.type=="i" || this.type=="d"){ | |
if(!isinstance(src,[int,float])){$raise('TypeError', | |
"%"+this.type+" format : a number is required, not "+str(src.__class__))} | |
return str(int(src)) | |
}else if(this.type=="f" || this.type=="F"){ | |
if(!isinstance(src,[int,float])){$raise('TypeError', | |
"%"+this.type+" format : a number is required, not "+str(src.__class__))} | |
return str(float(src)) | |
} | |
} | |
} | |
var elts=[] | |
var pos=0, start=0, nb_repl=0 | |
var val=this.valueOf() | |
while(pos<val.length){ | |
if(val.charAt(pos)=='%'){ | |
var f=new format(val.substr(pos)) | |
if(f.is_format){ | |
elts.push(val.substring(start,pos)) | |
elts.push(f) | |
start=pos+f.src.length | |
pos=start | |
nb_repl++ | |
}else{pos++} | |
}else{pos++} | |
} | |
elts.push(val.substr(start)) | |
if(!isinstance(args,tuple)){ | |
if(nb_repl>1){$raise('TypeError','not enough arguments for format string')} | |
else{elts[1]=elts[1].format(args)} | |
}else{ | |
if(nb_repl==args.length){ | |
for(var i=0;i<args.length;i++){ | |
var fmt=elts[1+2*i] | |
elts[1+2*i]=fmt.format(args[i]) | |
} | |
}else if(nb_repl<args.length){$raise('TypeError', | |
"not all arguments converted during string formatting") | |
}else{$raise('TypeError','not enough arguments for format string')} | |
} | |
var res='' | |
for(var i=0;i<elts.length;i++){res+=elts[i]} | |
return str(res) | |
} | |
String.prototype.__mul__=function(other){ | |
if(!isinstance(other,int)){$raise('TypeError', | |
"Can't multiply sequence by non-int of type '"+str(other.__class__)+"'")} | |
$res='' | |
for(var i=0;i<other;i++){$res+=this.valueOf()} | |
return $res | |
} | |
String.prototype.__next__=function(){ | |
if(this.iter==null){this.iter==0} | |
if(this.iter<this.value.length){ | |
this.iter++ | |
return str(this.value.charAt(this.iter-1)) | |
}else{ | |
this.iter=null | |
$raise('StopIteration') | |
} | |
} | |
String.prototype.__not_in__=function(item){return !item.__contains__(this)} | |
String.prototype.__setattr__=function(attr,value){setattr(this,attr,value)} | |
String.prototype.__setitem__=function(attr,value){ | |
$raise('TypeError',"'str' object does not support item assignment") | |
} | |
var $comp_func=function(other){ | |
if(typeof other !=="string"){$raise('TypeError', | |
"unorderable types: 'str' > "+other.__class__+"()")} | |
return this > other | |
} | |
$comp_func +='' | |
var $comps={'>':'gt','>=':'ge','<':'lt','<=':'le','==':'eq','!=':'ne'} | |
for($op in $comps){ | |
eval("String.prototype.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op)) | |
} | |
var $notimplemented=function(other){ | |
$raise('TypeError', | |
"unsupported operand types for OPERATOR: '"+str(this.__class__)+"' and '"+str(other.__class__)+"'") | |
} | |
$notimplemented +='' | |
for($op in $operators){ | |
var $opfunc='__'+$operators[$op]+'__' | |
if(!($opfunc in String.prototype)){ | |
eval('String.prototype.'+$opfunc+"="+$notimplemented.replace(/OPERATOR/gm,$op)) | |
} | |
} | |
function $string_capitalize(obj){ | |
if(obj.length==0){return ''} | |
return obj.charAt(0).toUpperCase()+obj.substr(1).toLowerCase() | |
} | |
function $string_center(obj){ | |
return function(width,fillchar){ | |
if(fillchar===undefined){fillchar=' '}else{fillchar=fillchar} | |
if(width<=obj.length){return obj} | |
else{ | |
var pad=parseInt((width-obj.length)/2) | |
res='' | |
for(var i=0;i<pad;i++){res+=fillchar} | |
res +=obj | |
for(var i=0;i<pad;i++){res+=fillchar} | |
if(res.length<width){res +=fillchar} | |
return res | |
} | |
} | |
} | |
function $string_count(obj){ | |
return function(elt){ | |
if(!(typeof elt==="string")){$raise('TypeError', | |
"Can't convert '"+str(elt.__class__)+"' object to str implicitly")} | |
var res=0 | |
for(var i=0;i<obj.length-elt.length+1;i++){ | |
if(obj.substr(i,elt.length)===elt){res++} | |
} | |
return res | |
} | |
} | |
function $string_endswith(obj){ | |
return function(){ | |
var $ns=$MakeArgs(arguments,['suffix'], | |
{'start':null,'end':null},null,null) | |
var suffixes=$ns['suffix'] | |
if(!isinstance(suffixes,tuple)){suffixes=[suffixes]} | |
var start=$ns['start']|| 0 | |
var end=$ns['end']|| obj.length-1 | |
var s=obj.substr(start,end+1) | |
for(var i=0;i<suffixes.length;i++){ | |
suffix=suffixes[i] | |
if(suffix.length<=s.length && | |
s.substr(s.length-suffix.length)==suffix){return True} | |
} | |
return False | |
} | |
} | |
function $string_find(obj){ | |
return function(){ | |
var $ns=$MakeArgs(arguments,['sub'], | |
{'start':0,'end':obj.length},null,null) | |
var sub=$ns['sub'],start=$ns['start'],end=$ns['end'] | |
if(!isinstance(sub,str)){$raise('TypeError', | |
"Can't convert '"+str(sub.__class__)+"' object to str implicitly")} | |
if(!isinstance(start,int)||!isinstance(end,int)){$raise('TypeError', | |
"slice indices must be integers or None or have an __index__ method")} | |
var s=obj.substring(start,end) | |
var res=s.search(sub) | |
if(res==-1){return -1} | |
else{return start+res} | |
} | |
} | |
function $string_index(obj){ | |
return function(){ | |
var args=[] | |
for(var i=0;i<arguments.length;i++){args.push(arguments[i])} | |
var res=$string_find(obj).apply(obj,args) | |
if(res===-1){$raise('ValueError',"substring not found")} | |
else{return res} | |
} | |
} | |
function $string_join(obj){ | |
return function(iterable){ | |
if(!'__next__' in iterable){$raise('TypeError', | |
"'"+str(iterable.__class__)+"' object is not iterable")} | |
var res='',count=0 | |
while(true){ | |
try{ | |
var obj2=next(iterable) | |
if(!isinstance(obj2,str)){$raise('TypeError', | |
"sequence item "+count+": expected str instance, "+str(obj2.__class__)+"found")} | |
res +=obj2+obj | |
count++ | |
}catch(err){ | |
if(err.name=='StopIteration'){break} | |
throw err | |
} | |
} | |
if(count==0){return str('')} | |
res=res.substr(0,res.length-obj.length) | |
return res | |
} | |
} | |
function $string_lower(obj){ | |
return function(){return obj.toLowerCase()} | |
} | |
function $string_lstrip(obj){ | |
return function(x){ | |
var pattern=null | |
if(x==undefined){pattern="\\s*"} | |
else{pattern="["+x+"]*"} | |
var sp=new RegExp("^"+pattern) | |
return obj.replace(sp,"") | |
} | |
} | |
function $string_replace(obj){ | |
return function(old,_new,count){ | |
if(count!==undefined){ | |
if(!isinstance(count,[int,float])){$raise('TypeError', | |
"'"+str(count.__class__)+"' object cannot be interpreted as an integer")} | |
var re=new RegExp(old) | |
var res=obj.valueOf() | |
while(count>0){ | |
if(obj.search(re)==-1){return res} | |
res=res.replace(re,_new) | |
count-- | |
} | |
return res | |
}else{ | |
var re=new RegExp(old,"g") | |
return obj.replace(re,_new) | |
} | |
} | |
} | |
function $string_rfind(obj){ | |
return function(){ | |
var $ns=$MakeArgs(arguments,['sub'], | |
{'start':0,'end':obj.length},null,null) | |
var sub=$ns['sub'],start=$ns['start'],end=$ns['end'] | |
if(!isinstance(sub,str)){$raise('TypeError', | |
"Can't convert '"+str(sub.__class__)+"' object to str implicitly")} | |
if(!isinstance(start,int)||!isinstance(end,int)){$raise('TypeError', | |
"slice indices must be integers or None or have an __index__ method")} | |
var s=obj.substring(start,end) | |
var reversed='' | |
for(var i=s.length-1;i>=0;i--){reversed +=s.charAt(i)} | |
var res=reversed.search(sub) | |
if(res==-1){return -1} | |
else{return start+s.length-1-res} | |
} | |
} | |
function $string_rindex(obj){ | |
return function(){ | |
var args=[] | |
for(var i=0;i<arguments.length;i++){args.push(arguments[i])} | |
var res=$string_rfind(obj).apply(obj,args) | |
if(res==-1){$raise('ValueError',"substring not found")} | |
else{return res} | |
} | |
} | |
function $string_rstrip(x){ | |
if(x==undefined){pattern="\\s*"} | |
else{pattern="["+x.value+"]*"} | |
sp=new RegExp(pattern+'$') | |
return str(this.value.replace(sp,"")) | |
} | |
function $string_split(obj){ | |
return function(){ | |
var $ns=$MakeArgs(arguments,['sep'], | |
{'maxsplit':-1},null,null) | |
var sep=$ns['sep'],maxsplit=$ns['maxsplit'] | |
var res=[],pos=0,spos=0 | |
if(isinstance(sep,str)){ | |
while(true){ | |
spos=obj.substr(pos).search(sep) | |
if(spos==-1){break} | |
res.push(obj.substr(pos,spos)) | |
pos +=spos+sep.length | |
if(maxsplit !=-1 && res.length==maxsplit){break} | |
} | |
res.push(obj.substr(pos)) | |
return res | |
} | |
} | |
} | |
function $string_startswith(obj){ | |
return function(){ | |
$ns=$MakeArgs(arguments,['prefix'], | |
{'start':null,'end':null},null,null) | |
var prefixes=$ns['prefix'] | |
if(!isinstance(prefixes,tuple)){prefixes=[prefixes]} | |
console.log(prefixes) | |
var start=$ns['start']|| 0 | |
var end=$ns['end']|| obj.length-1 | |
var s=obj.substr(start,end+1) | |
for(var i=0;i<prefixes.length;i++){ | |
prefix=prefixes[i] | |
if(prefix.length<=s.length && | |
s.substr(0,prefix.length)==prefix){return True} | |
} | |
return False | |
} | |
} | |
function $string_strip(obj){ | |
return function(x){ | |
if(x==undefined){x="\\s"} | |
pattern="["+x+"]" | |
sp=new RegExp("^"+pattern+"+|"+pattern+"+$","g") | |
return obj.replace(sp,"") | |
} | |
} | |
function $string_upper(obj){return function(){return obj.toUpperCase()}} | |
function str(arg){return arg.toString()} | |
function $MakeArgs($args,$required,$defaults,$other_args,$other_kw){ | |
var i=null | |
var $PyVars={} | |
var $def_names=[] | |
var $ns={} | |
for(k in $defaults){$def_names.push(k);$ns[k]=$defaults[k]} | |
if($other_args !=null){$ns[$other_args]=[]} | |
if($other_kw !=null){$dict_items=[]} | |
for(i=0;i<$args.length;i++){ | |
$arg=$args[i] | |
$PyVar=$JS2Py($arg) | |
if(!isinstance($arg,$Kw)){ | |
if(i<$required.length){ | |
eval($required[i]+"=$PyVar") | |
$ns[$required[i]]=$PyVar | |
}else if(i<$required.length+$def_names.length){ | |
$ns[$def_names[i-$required.length]]=$PyVar | |
}else if($other_args!=null){ | |
eval('$ns["'+$other_args+'"].push($PyVar)') | |
}else{ | |
msg=$fname+"() takes "+$required.length+' positional arguments ' | |
msg +='but more were given' | |
throw TypeError(msg) | |
} | |
}else{ | |
$PyVar=$arg.value | |
if($arg.name in $PyVars){ | |
throw new TypeError($fname+"() got multiple values for argument '"+$arg.name+"'") | |
}else if($required.indexOf($arg.name)>-1){ | |
var ix=$required.indexOf($arg.name) | |
eval($required[ix]+"=$PyVar") | |
$ns[$required[ix]]=$PyVar | |
}else if($arg.name in $defaults){ | |
$ns[$arg.name]=$arg | |
}else if($other_kw!=null){ | |
$dict_items.push([$arg.name,$PyVar]) | |
}else{ | |
throw new TypeError($fname+"() got an unexpected keyword argument '"+$arg.name+"'") | |
} | |
if($arg.name in $defaults){delete $defaults[$arg.name]} | |
} | |
} | |
if($other_kw!=null){$ns[$other_kw]=dict($dict_items)} | |
return $ns | |
} | |
function $multiple_assign(indent,targets,right_expr,assign_pos){ | |
var i=0,target=null | |
for(var i=0;i<targets.list;i++){ | |
var left=targets[i] | |
if(left.list[0][3]==="local"){left.list[0][1]="var "+left.list[0][1]} | |
} | |
var rlist=right_expr.list() | |
if(rlist[0][0]=="bracket"){rlist=rlist.slice(1,rlist.length-1)} | |
var rs=new Stack(rlist) | |
var rs_items=rs.split(',') | |
if(rs_items.length>1){ | |
if(rs_items.length>targets.length){ | |
$raise("ValueError","Too many values to unpack (expected "+targets.length+")") | |
}else if(rs_items.length<targets.length){ | |
$raise("ValueError","Need more than "+rs_items.length+" values to unpack") | |
}else{ | |
var seq=[['code','var $temp=[]'],['newline','\n']] | |
for(i=0;i<targets.length;i++){ | |
seq.push(['indent',indent],['code','$temp.push'],['bracket','(']) | |
seq=seq.concat(rs_items[i].list) | |
seq.push(['bracket',')'],['newline','\n',assign_pos]) | |
} | |
for(i=0;i<targets.length;i++){ | |
seq.push(['indent',indent]) | |
seq=seq.concat(targets[i].list) | |
seq.push(['assign','=',assign_pos], | |
['code','$temp['+i+']'],['newline','\n',assign_pos]) | |
} | |
} | |
}else{ | |
var seq=[['code',"var $var",assign_pos], | |
['assign','=']] | |
seq=seq.concat(right_expr.list()) | |
seq.push(['newline','\n',assign_pos]) | |
for(var i=0;i<targets.length;i++){ | |
target=targets[i] | |
seq.push(['indent',indent]) | |
seq=seq.concat(target.list) | |
seq.push(['assign','='],['code','$var.__item__('+i+')'], | |
['newline','\n']) | |
} | |
} | |
return seq | |
} | |
$OpeningBrackets=$List2Dict('(','[','{') | |
function $py2js(src,context,debug){ | |
document.$debug=debug | |
var i=0 | |
src=src.replace(/\r\n/gm,'\n') | |
while(src.length>0 &&(src.charAt(0)=="\n" || src.charAt(0)=="\r")){ | |
src=src.substr(1) | |
} | |
if(src.charAt(src.length-1)!="\n"){src+='\n'} | |
if(!context){context='__main__';document.$py_src={'__main__':src}} | |
else{document.$py_src[context]=src} | |
document.$context=context | |
var pos2line={} | |
var lnum=1 | |
for(i=0;i<src.length;i++){ | |
pos2line[i]=lnum | |
if(src.charAt(i)=='\n'){lnum+=1} | |
} | |
var dobj=new Date() | |
var t0=dobj.getTime() | |
var times={} | |
tokens=$tokenize(src) | |
stack=new Stack(tokens) | |
var $err_num=0 | |
if(debug){ | |
var pos=0 | |
var s_nl=0 | |
while(true){ | |
var nl=stack.find_next(pos,'newline') | |
if(nl==null){break} | |
var indent_pos=stack.find_previous(nl,'indent') | |
if(!stack.list[indent_pos+1].match(['keyword','else'])&& | |
!stack.list[indent_pos+1].match(['keyword','elif'])&& | |
!stack.list[indent_pos+1].match(['keyword','except'])){ | |
stack.list.splice(s_nl,0,stack.list[indent_pos], | |
['code','document.line_num='+stack.list[nl][1],stack.list[nl][2]], | |
['newline','\n']) | |
s_nl=nl+4 | |
pos=nl+5 | |
}else{ | |
s_nl=nl+1 | |
pos=nl+2 | |
} | |
} | |
} | |
var dobj=new Date() | |
times['add line nums']=dobj.getTime()-t0 | |
var repl=[['not','in'],['is','not']] | |
for(i=0;i<repl.length;i++){ | |
var seq=repl[i] | |
var pos=stack.list.length-1 | |
while(pos>0){ | |
var op_pos=stack.find_previous(pos,"operator",seq[1]) | |
if(op_pos==null){break} | |
if(op_pos>1 && stack.list[op_pos-1].match(["operator",seq[0]])){ | |
stack.list.splice(op_pos-1,2,['operator',seq[0]+'_'+seq[1],stack.list[op_pos][2]]) | |
} | |
pos=op_pos-2 | |
} | |
} | |
var not_a_display={ | |
'[':[["id"],["assign_id"],['str'],['int'],['float'],["qualifier"],["bracket",$List2Dict("]",")")]], | |
'(':[["id"],["assign_id"],["qualifier"],["bracket",$List2Dict("]",")")]], | |
'{':[[]] | |
} | |
var PyType={'(':'tuple','[':'$list','{':'dict'} | |
var br_list=['[','(','{'] | |
for(var ibr=0;ibr<br_list.length;ibr++){ | |
var bracket=br_list[ibr] | |
var pos=stack.list.length-1 | |
while(true){ | |
var br_elt=stack.find_previous(pos,"bracket",bracket) | |
if(br_elt==null){break} | |
if(br_elt>0){ | |
var previous=stack.list[br_elt-1] | |
var is_display=true | |
for(var inad=0;inad<not_a_display[bracket].length;inad++){ | |
var args=not_a_display[bracket][inad] | |
if(args[0]==previous[0]){ | |
if(args.length!=2 ||(previous[1]in args[1])){ | |
is_display=false | |
} | |
} | |
} | |
if(!is_display){pos=br_elt-1;continue} | |
var pyType=PyType[bracket] | |
var br_pos=stack.list[br_elt][2] | |
var sequence=[['id',pyType,br_elt[2]],['bracket','(',br_pos]] | |
var end=stack.find_next_matching(br_elt) | |
if(pyType=='dict'){ | |
var args=new Stack(stack.list.slice(br_elt+1,end)) | |
if(args.list.length>0){ | |
sequence=[['id','dict'],['bracket','('], | |
['id','$list'],['bracket','(']] | |
var kvs=args.split(',') | |
for(var ikv=0;ikv<kvs.length;ikv++){ | |
var kv=kvs[ikv] | |
var elts=kv.split(':') | |
if(elts.length!=2){ | |
document.line_num=pos2line[br_pos] | |
$raise("SyntaxError","invalid syntax") | |
} | |
var key=elts[0] | |
var value=elts[1] | |
var key_start=kv.start+key.start | |
var key_end=kv.start+key.end | |
sequence.push(['id','$list']) | |
sequence.push(['bracket','(']) | |
sequence=sequence.concat(args.list.slice(key_start,key_end+1)) | |
sequence.push(['delimiter',',',br_pos]) | |
var value_start=kv.start+value.start | |
var value_end=kv.start+value.end | |
sequence=sequence.concat(args.list.slice(value_start,value_end+1)) | |
sequence.push(['bracket',')']) | |
sequence.push(['delimiter',',',br_pos]) | |
} | |
sequence.pop() | |
sequence.push(['bracket',')']) | |
} | |
sequence.push(['bracket',')',stack.list[end][2]]) | |
}else if(pyType=='tuple'){ | |
var args=new Stack(stack.list.slice(br_elt+1,end)) | |
var kvs=args.split(',') | |
if(kvs.length==1){sequence[0][1]='$tuple'} | |
if(kvs[kvs.length-1].list.length==0){ | |
if(kvs.length==2){sequence[0][1]='$tuple'} | |
stack.list[end-1]=['code',''] | |
} | |
sequence=sequence.concat(stack.list.slice(br_elt+1,end)) | |
sequence.push(['bracket',')',stack.list[end][2]]) | |
}else{ | |
var args=new Stack(stack.list.slice(br_elt+1,end)) | |
if(end > br_elt+1){ | |
sequence=sequence.concat(stack.list.slice(br_elt+1,end)) | |
sequence.push(['bracket',')',stack.list[end][2]]) | |
}else{sequence.push(['bracket',')',stack.list[end][2]])} | |
} | |
tail=stack.list.slice(end+1,stack.list.length) | |
stack.list=stack.list.slice(0,br_elt) | |
stack.list=stack.list.concat(sequence) | |
stack.list=stack.list.concat(tail) | |
} | |
pos=br_elt - 1 | |
} | |
} | |
var dobj=new Date() | |
times['displays']=dobj.getTime()-t0 | |
var pos=stack.list.length-1 | |
while(true){ | |
var def_pos=stack.find_previous(pos,"keyword","def") | |
if(def_pos==null){break} | |
var func_token=stack.list[def_pos+1] | |
var arg_start=stack.list[def_pos+2] | |
var indent_pos=stack.find_next(def_pos,'indent') | |
var indent=stack.list[indent_pos][1] | |
var f_indent='\n' | |
while(indent>0){f_indent+=' ';indent--} | |
document.line_num=pos2line[func_token[2]] | |
if(!func_token[0]=='id'){$raise("SyntaxError","wrong type after def")} | |
if(arg_start[0]!='bracket' || arg_start[1]!='('){$raise("SyntaxError","missing ( after function name")} | |
if(func_token[0]=='id' && arg_start[0]=='bracket' | |
&& arg_start[1]=='(' && | |
!(stack.list[def_pos+3].match(["bracket",")"]))){ | |
arg_end=stack.find_next_matching(def_pos+2) | |
for(var i=def_pos+2;i<arg_end;i++){ | |
if(stack.list[i][0]=='id'){stack.list[i][0]='arg_id'} | |
} | |
var s=new Stack(stack.list.slice(def_pos+3,arg_end)) | |
var args=s.split(',') | |
var required=[] | |
var defaults=[] | |
var has_defaults=false | |
var other_args=null | |
var other_kw=null | |
for(var i=args.length-1;i>=0;i--){ | |
arg=args[i] | |
var op=null | |
if(arg.list[0][0]=="operator" && arg.list[1][0]=="arg_id"){ | |
if(arg.list[0][1]=="*"){op='*';other_args=arg.list[1][1]} | |
else if(arg.list[0][1]=='**'){op='**';other_kw=arg.list[1][1]} | |
if(op!=null){ | |
if(i==0){ | |
stack.list.splice(def_pos+2+arg.start+1,arg.end-arg.start+1) | |
}else{ | |
stack.list.splice(def_pos+2+arg.start,arg.end-arg.start+2) | |
} | |
} | |
} | |
if(op==null){ | |
var elts=arg.split("=") | |
if(elts.length>1){ | |
defaults.push([elts[0].list[0][1],elts[1].to_js()]) | |
has_defaults=true | |
}else{ | |
required.push(arg.list[0][1]) | |
} | |
if(i==0){ | |
stack.list.splice(def_pos+3+arg.start,arg.end-arg.start+1) | |
}else{ | |
stack.list.splice(def_pos+2+arg.start,arg.end-arg.start+2) | |
} | |
} | |
} | |
var end_def=stack.find_next_at_same_level(def_pos,"delimiter",":") | |
if(end_def==null){ | |
$raise("SyntaxError","Unable to find definition end "+end_def) | |
} | |
var arg_code='arguments,' | |
if(required.length==0){arg_code+='[],'} | |
else{ | |
arg_code +='[' | |
required.reverse() | |
for(ireq=0;ireq<required.length;ireq++){ | |
arg_code+="'"+required[ireq]+"'," | |
} | |
arg_code=arg_code.substr(0,arg_code.length-1)+"]," | |
} | |
var def_code='{' | |
if(has_defaults){ | |
for($idef=0;$idef<defaults.length;$idef++){ | |
def_code +='"'+defaults[$idef][0]+'":'+defaults[$idef][1]+',' | |
} | |
def_code=def_code.substr(0,def_code.length-1) | |
} | |
def_code +='}' | |
arg_code +=def_code+',' | |
if(other_args==null){arg_code+="null,"} | |
else{arg_code +='"'+other_args+'",'} | |
if(other_kw==null){arg_code+="null"} | |
else{arg_code +='"'+other_kw+'"'} | |
var fcode=f_indent+'for($var in $ns){eval("var "+$var+"=$ns[$var]")}' | |
stack.list.splice(end_def+1,0, | |
['code',f_indent+"$ns=$MakeArgs("+arg_code+")"+fcode,stack.list[end_def][2]]) | |
} | |
pos=def_pos-1 | |
} | |
var dobj=new Date() | |
times['function defs']=dobj.getTime()-t0 | |
pos=stack.list.length-1 | |
while(true){ | |
var br_pos=stack.find_previous(pos,"bracket","(") | |
if(br_pos==null){break} | |
if((stack.list[br_pos-1][0]=='id' || stack.list[br_pos-1][0]=="qualifier") | |
&& br_pos>1 && | |
!(stack.list[br_pos-2].match(["keyword",'def']))){ | |
var end_call=stack.find_next_matching(br_pos) | |
var s=new Stack(stack.list.slice(br_pos+1,end_call)) | |
var args=s.split(',') | |
for(i=args.length-1;i>=0;i--){ | |
var arg=args[i] | |
var elts=arg.split('=') | |
if(elts.length==2){ | |
var src_pos=elts[0].list[0][2] | |
var seq=[['code','$Kw("'+elts[0].list[0][1]+'",',src_pos]] | |
seq=seq.concat(elts[1].list) | |
seq.push(['code',')',src_pos]) | |
var code='$Kw("'+elts[0].list[0][1]+'",' | |
code +=elts[1].to_js()+')' | |
stack.list.splice(br_pos+1+arg.start,arg.end-arg.start+1) | |
tail=stack.list.slice(br_pos+1+arg.start,stack.list.length) | |
stack.list=stack.list.slice(0,br_pos+1+arg.start).concat(seq).concat(tail) | |
} | |
} | |
} | |
pos=br_pos-1 | |
} | |
var dobj=new Date() | |
times['function calls']=dobj.getTime()-t0 | |
pos=0 | |
var sign2mult={'+':1,'-':-1} | |
while(true){ | |
var sign=stack.find_next(pos,"operator","+","-") | |
if(sign==null){break} | |
var op=stack.list[sign] | |
var mult=sign2mult[op[1]] | |
while(sign<stack.list.length-1){ | |
var next=stack.list[sign+1] | |
if(next[0]=="operator" && next[1]in sign2mult){ | |
mult *=sign2mult[next[1]] | |
stack.list.splice(sign+1,1) | |
}else{break } | |
} | |
if(mult !=sign2mult[op[1]]){ | |
if(op[1]=='+'){stack.list[sign][1]='-'} | |
else{stack.list[sign][1]='+'} | |
} | |
pos=sign+1 | |
} | |
pos=0 | |
while(true){ | |
var sign=stack.find_next(pos,"operator","+","-") | |
if(sign==null){break} | |
var op=stack.list[sign] | |
if(sign>0 && | |
(stack.list[sign-1][0]in $List2Dict("delimiter","newline","indent","assign","operator")|| | |
(stack.list[sign-1][0]=="bracket" &&("({[".indexOf(stack.list[sign-1][1])>-1)))){ | |
if(sign<stack.list.length-1){ | |
var next=stack.list[sign+1] | |
if(next[0]=="int" || next[0]=="float"){ | |
var value=next[1] | |
if(op[1]=='-'){ | |
stack.list[sign+1][1]=-1*stack.list[sign+1][1] | |
} | |
stack.list.splice(sign,1) | |
}else if(next[0]=="id"){ | |
var mult=1 | |
if(op[1]=="-"){mult=-1} | |
stack.list.splice(sign,1,["int",mult,op[2]], | |
['operator','*',op[2]]) | |
} | |
} | |
} | |
pos=sign+1 | |
} | |
pos=0 | |
while(pos<stack.list.length){ | |
var imp_pos=stack.find_next(pos,"keyword","import") | |
if(imp_pos==null){break} | |
var imported=stack.atom_at(imp_pos+1,true) | |
if(imported.type !='id' && imported.type !='tuple'){ | |
document.line_num=pos2line[stack.list[imp_pos][2]] | |
$raise("SyntaxError","invalid syntax") | |
} | |
for(var i=0;i<imported.list().length;i++){ | |
if(stack.list[imported.start+i][0]=="id"){ | |
stack.list[imported.start+i][0]='str' | |
stack.list[imported.start+i][1]='"'+stack.list[imported.start+i][1]+'"' | |
} | |
} | |
var src_pos=stack.list[imp_pos][2] | |
stack.list.splice(imported.end+1,0,['bracket',')']) | |
stack.list.splice(imp_pos,1, | |
['code','$import',src_pos],['bracket','(',src_pos]) | |
pos=imp_pos+1 | |
} | |
var dobj=new Date() | |
times['misc']=dobj.getTime()-t0 | |
var pos=0 | |
while(true){ | |
var try_pos=stack.find_next(pos,"keyword","try") | |
if(try_pos===null){break} | |
var try_indent=0 | |
if(try_pos==0){try_indent=0} | |
else if(stack.list[try_pos-1][0]=='indent'){try_indent=stack.list[try_pos-1][1]} | |
var block=stack.find_block(try_pos) | |
var nxt=block[1] | |
var exc_pos=try_pos | |
var clauses=[] | |
while(true){ | |
exc_pos=stack.next_at_same_indent(exc_pos) | |
if(exc_pos===null){break} | |
if(stack.list[exc_pos][0]!=="keyword" && | |
["except","finally","else"].indexOf(stack.list[exc_pos][1])==-1){ | |
break | |
} | |
clauses.push(exc_pos) | |
} | |
if(clauses.length==0){$raise('SyntaxError','invalid syntax')} | |
var last_block=stack.find_block(clauses[clauses.length-1]) | |
for(var i=clauses[0]-1;i<last_block[1];i++){ | |
if(stack.list[i][0]=="indent"){ | |
stack.list[i][1]=stack.list[i][1]+4 | |
} | |
} | |
for(var i=clauses.length-1;i>=0;i--){ | |
var clause=stack.list[clauses[i]] | |
if(clause[1]=='except'){ | |
stack.list[clauses[i]][1]='else' | |
if(!stack.list[clauses[i]+1].match(['delimiter',':'])){ | |
var excs=stack.atom_at(clauses[i]+1,true) | |
if(excs.type=="id"){ | |
var exc=stack.list[clauses[i]+1] | |
stack.list[clauses[i]+1]=['code','if($err'+$err_num+'.name=="'+exc[1]+'")'] | |
}else if(excs.type=="function_call"){ | |
var exc_str=[],exc_list=excs.list() | |
for(var j=2;j<exc_list.length;j++){ | |
if(exc_list[j][0]=="id"){exc_str.push('"'+exc_list[j][1]+'"')} | |
} | |
stack.list.splice(clauses[i]+1,exc_list.length, | |
['code','if(['+exc_str.join(',')+'].indexOf($err'+$err_num+'.name)>-1)']) | |
}else{$raise('SyntaxError','invalid syntax')} | |
} | |
} | |
} | |
stack.list.splice(nxt+1,0,['indent',try_indent],['keyword','catch'], | |
['id','$err'+$err_num],['delimiter',':'],['newline','\n']) | |
stack.list.splice(nxt+6,0,['indent',try_indent+4],['code','if(false){void(0)}'], | |
['newline','\n']) | |
pos=try_pos+1 | |
$err_num++ | |
} | |
var pos=stack.list.length-1 | |
while(true){ | |
var assert_pos=stack.find_previous(pos,"keyword","assert") | |
if(assert_pos===null){break} | |
var assert_indent=stack.indent(assert_pos) | |
var end=stack.line_end(assert_pos) | |
var cond_block=stack.list.slice(assert_pos+1,end) | |
stack.list[assert_pos][1]="if" | |
stack.list.splice(end,0,['delimiter',':'],['newline','\n'], | |
['indent',assert_indent+4],['keyword','pass'],['newline','\n'], | |
['indent',assert_indent],['keyword','else'],['delimiter',':'],['newline','\n'], | |
['indent',assert_indent+4],['code','$raise("AssertionError")']) | |
pos=assert_pos-1 | |
} | |
var kws={'if':'if','else':'else','elif':'else if', | |
'def':'function','for':'for','while':'while', | |
'try':'try','catch':'catch','finally':'finally'} | |
var has_parenth=$List2Dict('if','elif','while','for','catch') | |
var $funcs=[] | |
var module_level_functions=[] | |
var loop_id=0 | |
for(kw in kws){ | |
pos=0 | |
while(pos<stack.list.length){ | |
var kw_pos=stack.find_next(pos,"keyword",kw) | |
if(kw_pos==null){break} | |
var kw_indent=stack.indent(kw_pos) | |
var src_pos=stack.list[kw_pos][2] | |
var block=stack.find_block(kw_pos) | |
if(block===null){ | |
document.line_num=pos2line[stack.list[kw_pos][2]] | |
$raise('SyntaxError') | |
} | |
s=new Stack(stack.list.slice(block[0],block[1]+1)) | |
if(block==null){console.log('anomalie '+kw);pos=kw_pos-1;continue} | |
var multiline=(s.find_next(0,'newline')!=null) | |
stack.list[kw_pos][1]=kws[kw] | |
stack.list[block[0]]=['bracket','{'] | |
var end_pos=stack.list[block[1]][2] | |
tail=stack.list.slice(block[1],stack.list.length) | |
if(kw in has_parenth){ | |
if(kw=="for"){ | |
loop_id++ | |
var block_indent=stack.indent(block[0]+1) | |
var arg_list=stack.atom_at(kw_pos+1,true) | |
var _in=stack.atom_at(arg_list.end+1) | |
var _in_list=stack.list.slice(_in.start,_in.end+1) | |
if(_in_list.length !=1 || | |
_in_list[0][0]!="operator" || _in_list[0][1]!="in"){ | |
$raise("SyntaxError","missing 'in' after 'for'",src,src_pos) | |
} | |
var iterable=stack.atom_at(_in.end+1,true) | |
seq=[['indent',kw_indent], | |
['code','var $iter'+loop_id],['assign','=']] | |
seq=seq.concat(iterable.list()) | |
seq.push(['newline','\n'],['indent',kw_indent],['code','for']) | |
var $loop='(var $i'+loop_id+'=0;$i'+loop_id+'<' | |
$loop +='$iter'+loop_id+'.__len__();$i'+loop_id+'++){' | |
seq=seq.concat([['code',$loop],['newline','\n'], | |
['indent',block_indent]]) | |
seq=seq.concat(arg_list.list()) | |
seq.push(['assign','='],['id','$iter'+loop_id]) | |
seq.push(['point','.'],['qualifier','__item__'], | |
['bracket','('],['id','$i'+loop_id],['bracket',')']) | |
seq=seq.concat(stack.list.slice(block[0]+1,block[1])) | |
stack.list=stack.list.slice(0,kw_pos-1) | |
stack.list=stack.list.concat(seq) | |
$err_num++ | |
}else if(kw=='if' || kw=='elif' || kw=='while'){ | |
var seq=[['bracket','(',src_pos]] | |
seq=seq.concat(stack.list.slice(kw_pos+1,block[0])) | |
seq.push(['bracket',')',src_pos]) | |
seq.push(stack.list[block[0]]) | |
seq=seq.concat(stack.list.slice(block[0]+1,block[1])) | |
stack.list=stack.list.slice(0,kw_pos+1) | |
stack.list=stack.list.concat(seq) | |
}else{ | |
var seq=[['bracket','(',src_pos]] | |
seq=seq.concat(stack.list.slice(kw_pos+1,block[0])) | |
seq.push(['bracket',')',src_pos]) | |
seq.push(stack.list[block[0]]) | |
seq=seq.concat(stack.list.slice(block[0]+1,block[1])) | |
stack.list=stack.list.slice(0,kw_pos+1) | |
stack.list=stack.list.concat(seq) | |
} | |
}else if(kws[kw]=="function"){ | |
var func_name=stack.list[kw_pos+1] | |
var i=0,parent=false | |
for(i=$funcs.length-1;i>=0;i--){ | |
if(kw_pos>$funcs[i][1]&& kw_pos<$funcs[i][2]){parent=true;break} | |
} | |
$funcs.push([func_name[1],block[0],block[1],parent]) | |
stack.list[kw_pos+1][0]="function_id" | |
seq=stack.list.slice(kw_pos+1,block[0]+1) | |
var fbody=stack.list.slice(block[0]+1,block[1]) | |
var globals={} | |
var fstack=new Stack(fbody) | |
var global_pos=fstack.find_next(0,'keyword','global') | |
if(global_pos!==null){ | |
var globs=fstack.atom_at(global_pos+1,true) | |
if(globs.type=="id" || globs.type=="tuple" || | |
globs.type=="function_call"){ | |
var glob_list=globs.list() | |
for(var i=0;i<glob_list.length;i++){ | |
if(glob_list[i][0]=='id'){globals[glob_list[i][1]]=0} | |
} | |
} | |
fbody.splice(global_pos,glob_list.length+1) | |
} | |
seq=seq.concat(fbody) | |
for(var i=0;i<seq.length;i++){ | |
if(seq[i][0]=="id"){ | |
if(!(seq[i][1]in globals)){seq[i].push('local')} | |
} | |
} | |
stack.list=stack.list.slice(0,kw_pos+1) | |
stack.list=stack.list.concat(seq) | |
var fname=stack.list[kw_pos+1][1] | |
var indent=stack.indent(kw_pos) | |
var f_indent='' | |
while(indent>0){f_indent+=' ';indent--} | |
if(!parent){ | |
var code='\n'+f_indent+'window.'+fname+'='+fname | |
module_level_functions.push(fname) | |
tail.splice(0,0,['func_end',code]) | |
} | |
}else{ | |
stack.list=stack.list.slice(0,block[1]) | |
} | |
stack.list.push(['newline','\n',end_pos]) | |
if(block[2]>0){ | |
stack.list.push(['indent',block[2],end_pos]) | |
} | |
stack.list.push(['bracket','}',end_pos]) | |
stack.list=stack.list.concat(tail) | |
pos=kw_pos+1 | |
} | |
} | |
var dobj=new Date() | |
times['if def class for']=dobj.getTime()-t0 | |
pos=stack.list.length-1 | |
while(true){ | |
var op=stack.find_previous(pos,"operator","not") | |
if(op==null){break} | |
ro=stack.atom_at(op+1) | |
seq=[['bracket','(']] | |
seq=seq.concat(ro.list()) | |
seq.push(['bracket',')']) | |
stack.list[op]=["id","$not",stack.list[op][2]] | |
var tail=stack.list.slice(ro.end+1,stack.list.length) | |
stack.list=stack.list.slice(0,op+1).concat(seq).concat(tail) | |
pos=op-1 | |
} | |
pos=stack.list.length-1 | |
while(true){ | |
var assign=stack.find_previous(pos,"assign") | |
if(assign===null){break} | |
if(stack.list[assign][1]in $augmented_assigns){ | |
var left=stack.atom_before(assign) | |
if(left.type=="id"){left.list()[0][3]="global"} | |
var op=stack.list[assign][1] | |
var simple_op=op.substr(0,op.length-1) | |
stack.list[assign][1]="=" | |
stack.list.splice(assign+1,0,['operator',simple_op]) | |
for(var i=left.list().length-1;i>=0;i--){ | |
stack.list.splice(assign+1,0,left.list()[i]) | |
} | |
} | |
pos=assign-1 | |
} | |
var ops_order=["**","*","/","//","%","-","+", | |
"<","<=",">",">=","!=","==", | |
"+=","-=","*=","/=","//=","%=","**=", | |
"not_in","in","is_not"] | |
var ops=[], op=null | |
var lo1=$List2Dict(["id","bracket"]) | |
var lo2=$List2Dict(["id","bracket","delimiter","operator"]) | |
for(var i=0;i<ops_order.length;i++){ | |
op=ops_order[i] | |
if(op=="+" || op=="-"){ | |
ops.push([op,lo2]) | |
}else{ | |
ops.push([op,lo1]) | |
} | |
} | |
var $lo_ok=$List2Dict('id','str','int','float','tuple') | |
for(var i=0;i<ops.length;i++){ | |
operator=ops[i] | |
var op_sign=operator[0] | |
var auth_lo_types=operator[1] | |
var py_op='__'+$operators[op_sign]+'__' | |
pos=0 | |
while(true){ | |
var op=stack.find_next(pos,"operator",op_sign) | |
if(op==null){break} | |
var lo=stack.atom_before(op,false) | |
if(!lo.type in $lo_ok){ | |
document.line_num=pos2line[stack.list[op][2]] | |
$raise("SyntaxError","Bad left operand type "+lo.type+" for "+op_sign) | |
} | |
var par_before_lo=false | |
if(lo.type!="tuple"){ | |
var before_lo=stack.list[lo.start-1] | |
if(before_lo!=null){ | |
if(before_lo[0]=="operator"){ | |
par_before_lo=true | |
} | |
} | |
} | |
if(op==stack.list.length-1){ | |
$raise("SyntaxError","Bad right operand ",src,stack.list[op][2]) | |
} | |
var ro=stack.atom_at(op+1,false) | |
if(op_sign in $List2Dict("+=","-=","*=","/=","//=","%=","**=")){ | |
ro.end=stack.find_next(op,'newline')-1 | |
} | |
var ro_startswith_par=false | |
if(ro!=null && ro.type=="tuple"){ro_startswith_par=true} | |
var sequence=new Array() | |
if(par_before_lo){sequence.push(["bracket","(",op[2]])} | |
sequence=sequence.concat(stack.list.slice(lo.start,lo.end+1)) | |
sequence.push(["point",".",op[2]]) | |
sequence.push(["qualifier",py_op,op[2]]) | |
if(!ro_startswith_par){sequence.push(["bracket","(",op[2]])} | |
sequence=sequence.concat(stack.list.slice(ro.start,ro.end+1)) | |
if(!ro_startswith_par){sequence.push(["bracket",")",op[2]])} | |
if(par_before_lo){sequence.push(["bracket",")",op[2]])} | |
tail=stack.list.slice(ro.end+1,stack.list.length) | |
stack.list.splice(lo.start,ro.end-lo.start+1) | |
stack.list=stack.list.slice(0,lo.start).concat(sequence).concat(tail) | |
pos=op+1 | |
} | |
} | |
var ops={"and":"&&","or":"||"} | |
for(var op in ops){ | |
var pos=0 | |
while(true){ | |
var op_pos=stack.find_next(pos,'operator',op) | |
if(op_pos===null){break} | |
stack.list[op_pos][1]=ops[op] | |
var left=stack.atom_before(op_pos,false) | |
var right=stack.atom_at(op_pos+1,false) | |
var head=stack.list.slice(0,left.start) | |
var tail=stack.list.slice(right.end+1,stack.list.length) | |
var nb=0 | |
if(left.list()[0].match(['bracket','('])){ | |
left=[['id','$test_item']].concat(left.list()) | |
nb++ | |
}else if(!left.list()[0].match(['id','$test_item'])){ | |
left=[['id','$test_item'],['bracket','(']].concat(left.list()).concat([['bracket',')']]) | |
nb +=3 | |
}else{ | |
left=left.list() | |
} | |
if(right.list()[0].match(['bracket','('])){ | |
right=[['id','$test_item']].concat(right.list()) | |
nb++ | |
}else{ | |
right=[['id','$test_item'],['bracket','(']].concat(right.list()).concat([['bracket',')']]) | |
nb+=3 | |
} | |
stack.list=head | |
stack.list=stack.list.concat(left).concat([['operator',ops[op]]]).concat(right) | |
stack.list=stack.list.concat(tail) | |
pos+=nb | |
} | |
} | |
var pos=0 | |
while(true){ | |
var test_pos=stack.find_next(pos,'id','$test_item') | |
if(test_pos===null){break} | |
var test_end=stack.find_next_matching(test_pos+1) | |
while(test_end<stack.list.length-1 && stack.list[test_end+1][0]=='operator' | |
&&(stack.list[test_end+1][1]=='&&' || stack.list[test_end+1][1]=='||')){ | |
test_end=stack.find_next_matching(test_end+3) | |
} | |
stack.list.splice(test_end,0,['bracket',')']) | |
stack.list.splice(test_pos,0,['code','$test_expr'],['bracket','(']) | |
pos=test_end | |
} | |
var dobj=new Date() | |
times['operators']=dobj.getTime()-t0 | |
var js2py={'pass':'void(0)'} | |
for(key in js2py){ | |
pos=0 | |
while(true){ | |
var func_pos=stack.find_next(pos,'keyword',key) | |
if(func_pos==null){break} | |
stack.list[func_pos][1]=js2py[key] | |
pos=func_pos+1 | |
} | |
} | |
var js2py={'alert':'$alert','prompt':'$prompt','confirm':'$confirm'} | |
for(key in js2py){ | |
pos=0 | |
while(true){ | |
var func_pos=stack.find_next(pos,'id',key) | |
if(func_pos==null){break} | |
stack.list[func_pos][0]='code' | |
stack.list[func_pos][1]=js2py[key] | |
pos=func_pos+1 | |
} | |
} | |
var pos=stack.list.length-1 | |
while(true){ | |
var assign=stack.find_previous(pos,"assign","=") | |
if(assign===null){break} | |
var line_start=stack.line_start(assign) | |
var line_end=stack.line_end(assign) | |
var line_stack=new Stack(stack.list.slice(line_start,line_end)) | |
var line_pos=line_stack.list.length-1 | |
var assigns=[] | |
var nb_assigns=0 | |
while(true){ | |
var assign_pos=line_stack.find_previous(line_pos,'assign','=') | |
if(assign_pos===null){break} | |
nb_assigns++ | |
var left=line_stack.atom_before(assign_pos,true) | |
var right=line_stack.atom_at(assign_pos+1,true) | |
assigns.push(stack.list[line_start]) | |
assigns=assigns.concat(left.list()) | |
assigns.push(["assign","="]) | |
assigns=assigns.concat(right.list()) | |
assigns.push(['newline','\n']) | |
line_pos=assign_pos-1 | |
} | |
if(nb_assigns>1){ | |
var assign_stack=new Stack(assigns) | |
var tail=stack.list.slice(line_end,stack.list.length) | |
stack.list=stack.list.slice(0,line_start).concat(assigns).concat(tail) | |
} | |
pos=line_start | |
} | |
pos=stack.list.length-1 | |
while(true){ | |
var assign=stack.find_previous(pos,"assign","=") | |
if(assign==null){break} | |
var left=stack.atom_before(assign,true) | |
var right=stack.atom_at(assign+1,true) | |
if(left.type=="tuple" || | |
(left.type=="function_call" && left.list()[0][1]=="tuple")){ | |
var list=left.list() | |
if(list[0].match(["id","tuple"])){ | |
list=list.slice(2,list.length-1) | |
} | |
var t_stack=new Stack(list) | |
var targets=t_stack.split(',') | |
document.line_num=pos2line[stack.list[assign][2]] | |
var indent=stack.indent(assign) | |
var seq=$multiple_assign(indent,targets,right,stack.list[assign][2]) | |
var tail=stack.list.slice(right.end+1,stack.list.length) | |
stack.list=stack.list.slice(0,left.start).concat(seq).concat(tail) | |
pos=left.start+seq.length-1 | |
}else if(left.type=='str' || left.type=='int' || left.type=='float'){ | |
pos=left.list()[0][2] | |
document.line_num=pos2line[pos] | |
$raise("SyntaxError","can't assign to literal") | |
}else if(left.type=='qualified_id' || left.type=='slicing' || left.type=="function_call"){ | |
pos=assign-1 | |
}else{ | |
if(left.list()[0][3]==="local"){left.list()[0][1]="var "+left.list()[0][1]} | |
pos=assign-1 | |
} | |
} | |
var dobj=new Date() | |
times['assignments']=dobj.getTime()-t0 | |
pos=stack.list.length-1 | |
while(true){ | |
br_pos=stack.find_previous(pos,'bracket','[') | |
if(br_pos==null){break} | |
if(br_pos==0){break} | |
var previous=stack.list[br_pos-1] | |
if(['id','qualifier','keyword'].indexOf(previous[0])==-1){pos=br_pos-1;continue} | |
src_pos=stack.list[br_pos][2] | |
var end=stack.find_next_matching(br_pos) | |
var args=stack.list.slice(br_pos+1,end) | |
if(args.length==0){$raise('SyntaxError','invalid syntax')} | |
var args1=new Stack(args) | |
var items=args1.split(":") | |
var new_args=[] | |
if(items.length==1){ | |
new_args=items[0].list | |
}else{ | |
new_args=[['id','slice',src_pos]] | |
new_args.push(['bracket','(',src_pos]) | |
for(var i=0;i<items.length;i++){ | |
var item=items[i] | |
if(item.list.length==0){ | |
new_args.push(['keyword','null',src_pos]) | |
}else{ | |
new_args=new_args.concat(item.list) | |
} | |
if(i<items.length-1){ | |
new_args.push(["delimiter",",",src_pos]) | |
} | |
} | |
new_args.push(['bracket',')',stack.list[end][2]]) | |
} | |
if(end<stack.list.length-1 && stack.list[end+1][0]=="assign"){ | |
var sequence=[['point','.',src_pos],['qualifier','__setitem__',src_pos], | |
['bracket','(',src_pos]] | |
left=stack.atom_before(end+1) | |
right=stack.atom_at(end+2) | |
sequence=sequence.concat(new_args) | |
sequence.push(['delimiter',',',stack.list[end+1][2]]) | |
sequence=sequence.concat(right.list()) | |
sequence.push(['bracket',')',stack.list[end][2]]) | |
tail=stack.list.slice(right.end+1,stack.list.length) | |
stack.list=stack.list.slice(0,br_pos) | |
stack.list=stack.list.concat(sequence).concat(tail) | |
}else{ | |
var func='__getitem__' | |
var x=stack.atom_before(br_pos) | |
if(x.start>0){ | |
var before=stack.list[x.start-1] | |
if(before[0]=='keyword' && before[1]=='del'){ | |
var func='__delitem__' | |
} | |
} | |
var sequence=[['point','.',src_pos],['qualifier',func,src_pos], | |
['bracket','(',src_pos]] | |
sequence=sequence.concat(new_args) | |
sequence.push(['bracket',')',stack.list[end][2]]) | |
tail=stack.list.slice(end+1,stack.list.length) | |
stack.list=stack.list.slice(0,br_pos) | |
stack.list=stack.list.concat(sequence).concat(tail) | |
if(func=='__delitem__'){ | |
stack.list.splice(x.start-1,1) | |
} | |
} | |
pos=br_pos-1 | |
} | |
var dobj=new Date() | |
times['slicings']=dobj.getTime()-t0 | |
pos=stack.list.length-1 | |
while(true){ | |
q_pos=stack.find_previous(pos,'qualifier') | |
if(q_pos==null){break} | |
src_pos=stack.list[q_pos][2] | |
if(q_pos<stack.list.length-1 && stack.list[q_pos+1][0]=="assign"){ | |
var ro=stack.atom_at(q_pos+2) | |
var q_name=stack.list[q_pos][1] | |
if(q_name.substr(0,2)=='__'){pos=q_pos-1;continue} | |
tail=stack.list.slice(ro.end+1,stack.list.length) | |
var seq=[['id','__setattr__'],['bracket','('], | |
['code',"'"+q_name+"'"],['delimiter',',']] | |
seq=seq.concat(ro.list()).concat([['bracket',')']]) | |
stack.list=stack.list.slice(0,q_pos).concat(seq).concat(tail) | |
}else{ | |
var func='__getattr__' | |
var x=stack.atom_before(q_pos) | |
if(x.start>0){ | |
var before=stack.list[x.start-1] | |
if(before[0]=='keyword' && before[1]=='del'){ | |
var func='__delattr__' | |
} | |
} | |
var q_name=stack.list[q_pos][1] | |
if(q_name.substr(0,2)=='__'){pos=q_pos-1;continue} | |
stack.list.splice(q_pos,1,['id',func],['bracket','('], | |
['code',"'"+q_name+"'"],['bracket',')']) | |
if(func=='__delattr__'){ | |
stack.list.splice(x.start-1,1) | |
} | |
} | |
pos=q_pos-1 | |
} | |
var pos=0 | |
while(true){ | |
var $list_pos=stack.find_next(pos,'id','$list') | |
if($list_pos===null){break} | |
stack.list.splice($list_pos,1) | |
var end=stack.find_next_matching($list_pos) | |
stack.list[$list_pos][1]='[' | |
stack.list[end][1]=']' | |
pos=$list_pos | |
} | |
var pos=0 | |
while(true){ | |
var func_pos=stack.find_next(pos,'keyword','function') | |
if(func_pos===null){break} | |
var br_pos=stack.find_next_at_same_level(func_pos,'bracket','{') | |
var end_pos=stack.find_next_matching(br_pos) | |
var block=new Stack(stack.list.slice(br_pos+1,end_pos)) | |
pos=func_pos+1 | |
} | |
var dobj=new Date() | |
times['total']=dobj.getTime()-t0 | |
return stack | |
} | |
function $run(js){ | |
eval(js) | |
} | |
function brython(debug){ | |
var elts=document.getElementsByTagName("script") | |
for($i=0;$i<elts.length;$i++){ | |
var elt=elts[$i] | |
if(elt.type=="text/python"){ | |
var src=(elt.innerHTML || elt.textContent) | |
js=$py2js(src,null,debug).to_js() | |
if(debug==2){document.write('<textarea cols=120 rows=30>'+js+'</textarea>')} | |
try{ | |
$run(js) | |
}catch(err){$raise('ExecutionError',err.message) | |
if(err.py_error===undefined){$raise('ExecutionError',err.message)} | |
else{throw err} | |
} | |
} | |
} | |
}var $operators={ | |
"//=":"ifloordiv",">>=":"irshift","<<=":"ilshift", | |
"**=":"ipow","**":"pow","//":"floordiv","<<":"lshift",">>":"rshift", | |
"+=":"iadd","-=":"isub","*=":"imul","/=":"itruediv", | |
"%=":"imod","&=":"iand","|=":"ior", | |
"^=":"ipow","+":"add","-":"sub","*":"mul", | |
"/":"truediv","%":"mod","&":"and","|":"or", | |
"^":"pow","<":"lt",">":"gt", | |
"<=":"le",">=":"ge","==":"eq","!=":"ne", | |
"or":"or","and":"and","in":"in","not":"not", | |
"not_in":"not_in","is_not":"is_not" | |
} | |
var $augmented_assigns={ | |
"//=":"ifloordiv",">>=":"irshift","<<=":"ilshift", | |
"**=":"ipow","+=":"iadd","-=":"isub","*=":"imul","/=":"itruediv", | |
"%=":"imod","^=":"ipow" | |
} | |
var $first_op_letter={} | |
for(op in $operators){$first_op_letter[op.charAt(0)]=0} | |
function $tokenize(src){ | |
var delimiters=[["#","\n","comment"],['"""','"""',"triple_string"], | |
["'","'","string"],['"','"',"string"], | |
["r'","'","raw_string"],['r"','"',"raw_string"]] | |
var br_open={"(":0,"[":0,"{":0} | |
var br_close={")":"(","]":"[","}":"{"} | |
var br_stack="" | |
var br_pos=new Array() | |
var kwdict=["False","class","finally","is","return", | |
"None","continue","for","lambda","try","True","def","from", | |
"nonlocal","while","del","global","with", | |
"as","elif","if","yield","assert","else","import","pass", | |
"break","except","raise"] | |
var unsupported=["class","is","from","nonlocal","with", | |
"as","yield"] | |
var forbidden=['item','var', | |
'closed','defaultStatus','document','frames', | |
'history','innerHeight','innerWidth','length', | |
'location','name','navigator','opener', | |
'outerHeight','outerWidth','pageXOffset','pageYOffset', | |
'parent','screen','screenLeft','screenTop', | |
'screenX','screenY','self','status', | |
'top'] | |
var punctuation={',':0,':':0} | |
var int_pattern=new RegExp("^\\d+") | |
var float_pattern=new RegExp("^\\d+\\.\\d*(e-?\\d+)?") | |
var id_pattern=new RegExp("[\\$_a-zA-Z]\\w*") | |
var stack=new Array() | |
var name="" | |
var _type=null | |
var pos=0 | |
var indent_stack=[0] | |
var pos2line={} | |
var lnum=1 | |
for(i=0;i<src.length;i++){ | |
pos2line[i]=lnum | |
if(src.charAt(i)=='\n'){lnum+=1} | |
} | |
lnum=0 | |
while(pos<src.length){ | |
document.line_num=pos2line[pos] | |
var flag=false | |
var car=src.charAt(pos) | |
if(stack.length==0 || $last(stack)[0]=='newline'){ | |
var indent=0 | |
while(pos<src.length && src.charAt(pos)==" "){ | |
indent++;pos++ | |
} | |
if(src.charAt(pos)=='\n'){pos++;lnum++;continue} | |
if(stack.length>1){ | |
if(indent>$last(indent_stack)){ | |
if(stack[stack.length-2][0]!="delimiter" && | |
stack[stack.length-2][1]!=":"){ | |
$raise("IndentationError","unexpected indent") | |
}else{ | |
indent_stack.push(indent) | |
} | |
}else if(indent==$last(indent_stack)){ | |
if(stack[stack.length-2][0]=="delimiter" && | |
stack[stack.length-2][1]==":"){ | |
$raise("IndentationError","expected an indented block") | |
} | |
}else if(indent<$last(indent_stack)){ | |
indent_stack.pop() | |
while(true){ | |
if(indent_stack.length==0){ | |
$raise('IndentationError','unexpected indent') | |
} | |
if(indent>$last(indent_stack)){ | |
$raise('IndentationError','unexpected indent') | |
}else if(indent==$last(indent_stack)){break} | |
else{indent_stack.pop()} | |
} | |
} | |
}else if(indent>0){ | |
$raise("IndentationError","unexpected indent") | |
} | |
stack.push(["indent",indent,pos-indent]) | |
continue | |
} | |
if(car=="#"){ | |
var end=src.substr(pos+1).search('\n') | |
if(end==-1){end=src.length-1} | |
stack.push(["newline",lnum,pos+1+end]) | |
lnum +=1 | |
pos +=end+2;continue | |
} | |
if(car=='"' || car=="'"){ | |
var raw=false | |
var end=null | |
if(name.length>0 && name.toLowerCase()=="r"){ | |
raw=true;name="" | |
} | |
if(src.substr(pos,3)==car+car+car){_type="triple_string";end=pos+3} | |
else{_type="string";end=pos+1} | |
var escaped=false | |
var zone=car | |
var found=false | |
while(end<src.length){ | |
if(escaped){zone+=src.charAt(end);escaped=false;end+=1} | |
else if(src.charAt(end)=="\\"){ | |
if(raw){ | |
zone +='\\\\' | |
end++ | |
}else{ | |
if(src.charAt(end+1)=='\n'){ | |
end +=2 | |
lnum++ | |
}else{ | |
zone+=src.charAt(end);escaped=true;end+=1 | |
} | |
} | |
}else if(src.charAt(end)==car){ | |
if(_type=="triple_string" && src.substr(end,3)!=car+car+car){ | |
end++ | |
}else{ | |
found=true | |
if(stack.length>0 && $last(stack)[0]=="str"){ | |
stack.push(['operator','+',end]) | |
} | |
stack.push(["str",zone+car,pos]) | |
pos=end+1 | |
if(_type=="triple_string"){pos=end+3} | |
break | |
} | |
}else{ | |
zone +=src.charAt(end) | |
if(src.charAt(end)=='\n'){lnum++} | |
end++ | |
} | |
} | |
if(!found){ | |
document.line_num=pos2line[pos] | |
$raise('SyntaxError',"String end not found ") | |
} | |
continue | |
} | |
if(name==""){ | |
if(car.search(/[a-zA-Z_]/)!=-1){ | |
name=car | |
pos++;continue | |
} | |
}else{ | |
if(car.search(/\w/)!=-1){ | |
name+=car | |
pos++;continue | |
}else{ | |
if(kwdict.indexOf(name)>-1){ | |
if(unsupported.indexOf(name)>-1){ | |
document.line_num=pos2line[pos] | |
$raise('SyntaxError',"Unsupported Python keyword '"+name+"'") | |
} | |
stack.push(["keyword",name,pos-name.length]) | |
}else if(name in $operators){ | |
stack.push(["operator",name,pos-name.length]) | |
}else if(stack.length>1 && $last(stack)[0]=="point" | |
&&(['id','str','int','float','qualifier','bracket'].indexOf(stack[stack.length-2][0])>-1)){ | |
stack.push(["qualifier",name,pos-name.length]) | |
}else if(forbidden.indexOf(name)>-1){ | |
document.line_num=pos2line[pos] | |
$raise('SyntaxError',"Forbidden name '"+name+"' : might conflict with Javascript variables") | |
}else{ | |
stack.push(["id",name,pos-name.length]) | |
} | |
name="" | |
continue | |
} | |
} | |
if(car=="."){ | |
stack.push(["point",".",pos]) | |
pos++;continue | |
} | |
if(car.search(/\d/)>-1){ | |
var res=float_pattern.exec(src.substr(pos)) | |
if(res){ | |
if(res[0].search('e')>-1){stack.push(["float",res[0],pos])} | |
else{stack.push(["float",eval(res[0]),pos])} | |
}else{ | |
res=int_pattern.exec(src.substr(pos)) | |
stack.push(["int",eval(res[0]),pos]) | |
} | |
pos +=res[0].length | |
continue | |
} | |
if(car=="\n"){ | |
lnum++ | |
if(br_stack.length>0){ | |
pos++;continue | |
}else{ | |
if(stack[stack.length-1][0]!="newline"){ | |
stack.push(["newline",lnum,pos]) | |
}else{ | |
stack[stack.length-1][1]=lnum | |
} | |
pos++;continue | |
} | |
} | |
if(car in br_open){ | |
br_stack +=car | |
br_pos[br_stack.length-1]=pos | |
stack.push(["bracket",car,pos]) | |
pos++;continue | |
} | |
if(car in br_close){ | |
if(br_stack==""){ | |
document.line_num=pos2line[pos] | |
$raise('SyntaxError',"Unexpected closing bracket") | |
}else if(br_close[car]!=$last(br_stack)){ | |
document.line_num=pos2line[pos] | |
$raise('SyntaxError',"Unbalanced bracket ") | |
}else{ | |
br_stack=br_stack.substr(0,br_stack.length-1) | |
stack.push(["bracket",car,pos]) | |
pos++;continue | |
} | |
} | |
if(car=="="){ | |
if(src.charAt(pos+1)!="="){ | |
if(br_stack.length==0){ | |
stack.push(["assign","=",pos]) | |
}else{ | |
stack.push(["delimiter","=",pos]) | |
} | |
pos++;continue | |
}else{ | |
stack.push(["operator","==",pos]) | |
pos+=2;continue | |
} | |
} | |
if(car in punctuation){ | |
stack.push(["delimiter",car,pos]) | |
pos++;continue | |
} | |
if(car in $first_op_letter){ | |
var op_match="" | |
for(op_sign in $operators){ | |
if(op_sign==src.substr(pos,op_sign.length) | |
&& op_sign.length>op_match.length){ | |
op_match=op_sign | |
} | |
} | |
if(op_match.length>0){ | |
if(op_match in $augmented_assigns){ | |
stack.push(["assign",op_match,pos]) | |
}else{ | |
stack.push(["operator",op_match,pos]) | |
} | |
pos +=op_match.length | |
continue | |
} | |
} | |
if(car=='\\' && src.charAt(pos+1)=='\n'){ | |
lnum++;pos+=2;continue | |
} | |
if(car!=' '){$raise('SyntaxError','unknown token ['+car+']')} | |
pos +=1 | |
} | |
if(br_stack.length!=0){ | |
pos=br_pos.pop() | |
document.line_num=pos2line[pos] | |
$raise('SyntaxError',"Unbalanced bracket "+br_stack.charAt(br_stack.length-1)) | |
} | |
return stack | |
} | |
function $JS2Py(src){ | |
if(isinstance(src,[str,int,float,list,dict,set])){return src} | |
if(src===null){return None} | |
if(src===false){return False} | |
if(src===true){return True} | |
htmlelt_pattern=new RegExp(/\[object HTML(.*)Element\]/) | |
if(["string","number"].indexOf(typeof src)>-1){ | |
return src | |
}else if(typeof src=="object"){ | |
if(src.constructor===Array){return src} | |
else if(src.tagName!==undefined && src.nodeName!==undefined){return $DomElement(src)} | |
else{ | |
try{if(src.constructor==DragEvent){return new $MouseEvent(src)}} | |
catch(err){void(0)} | |
try{if(src.constructor==MouseEvent){return new $MouseEvent(src)}} | |
catch(err){void(0)} | |
try{if(src.constructor==KeyboardEvent){return new $DomWrapper(src)}} | |
catch(err){void(0)} | |
if(src.__class__!==undefined){return src} | |
return new $DomObject(src) | |
} | |
}else{return src} | |
} | |
function $raise(name,msg){ | |
if(document.$debug==0){return} | |
if(msg===undefined){msg=''} | |
var lines=document.$py_src[document.$context].split('\n') | |
msg +='\nLine '+document.line_num+'\n'+lines[document.line_num-1] | |
err=new Error(name+": "+msg) | |
err.name=name | |
err.message=name+": "+msg | |
err.py_error=true | |
throw err | |
} | |
function $UnsupportedOpType(op,class1,class2){ | |
$raise('TypeError', | |
"unsupported operand type(s) for "+op+": '"+class1+"' and '"+class2+"'") | |
} | |
function $test_item(expr){ | |
document.$test_result=expr | |
return bool(expr) | |
} | |
function $test_expr(){ | |
return document.$test_result | |
} | |
Function.prototype.__eq__=function(other){ | |
if(typeof other !=='function'){return False} | |
return other+''===this+'' | |
} | |
Function.prototype.__class__=Function | |
Function.prototype.get_name=function(){ | |
var src=this.toString() | |
pattern=new RegExp("function (.*?)\\(") | |
var res=pattern.exec(src) | |
value='<function '+res[1]+'>' | |
} | |
Array.prototype.match=function(other){ | |
var $i=0 | |
while($i<this.length && $i<other.length){ | |
if(this[$i]!==other[$i]){return false} | |
$i++ | |
} | |
return true | |
} | |
if(!Array.indexOf){ | |
Array.prototype.indexOf=function(obj){ | |
for(var i=0;i<this.length;i++){ | |
if(this[i]==obj){ | |
return i | |
} | |
} | |
return -1 | |
} | |
} | |
try{console} | |
catch(err){ | |
console={'log':function(data){alert(data)}} | |
} | |
function $List2Dict(){ | |
var res={} | |
var i=0 | |
if(arguments.length==1 && arguments[0].constructor==Array){ | |
for(i=0;i<arguments[0].length;i++){ | |
res[arguments[0][i]]=0 | |
} | |
}else{ | |
for(i=0;i<arguments.length;i++){ | |
res[arguments[i]]=0 | |
} | |
} | |
return res | |
} | |
function $last(item){ | |
if(typeof item=="string"){return item.charAt(item.length-1)} | |
else if(typeof item=="object"){return item[item.length-1]} | |
} | |
function Atom(stack){ | |
this.parent=stack | |
this.type=null | |
this.stack=function(){ | |
return new Stack(this.parent.list.slice(this.start,this.end+1)) | |
} | |
this.list=function(){ | |
return this.parent.list.slice(this.start,this.end+1) | |
} | |
this.to_js=function(){return this.stack().to_js()} | |
} | |
function Stack(stack_list){ | |
this.list=stack_list | |
} | |
Stack.prototype.find_next=function(){ | |
var pos=arguments[0] | |
var _type=arguments[1] | |
var values=null | |
if(arguments.length>2){ | |
values={} | |
for(i=2;i<arguments.length;i++){values[arguments[i]]=0} | |
} | |
for(i=pos;i<this.list.length;i++){ | |
if(this.list[i][0]===_type){ | |
if(values===null){ | |
return i | |
}else if(this.list[i][1]in values){ | |
return i | |
} | |
} | |
} | |
return null | |
} | |
Stack.prototype.find_next_at_same_level=function(){ | |
var pos=arguments[0] | |
var _type=arguments[1] | |
var values=null | |
if(arguments.length>2){ | |
values={} | |
for(i=2;i<arguments.length;i++){values[arguments[i]]=0} | |
} | |
while(true){ | |
if(this.list[pos][0]==_type){ | |
if(values==null){return pos} | |
else if(this.list[pos][1]in values){return pos} | |
}else if(this.list[pos][0]=="bracket" | |
&& this.list[pos][1]in $OpeningBrackets){ | |
pos=this.find_next_matching(pos) | |
} | |
pos++ | |
if(pos>this.list.length-1){return null} | |
} | |
} | |
Stack.prototype.find_previous=function(){ | |
var pos=arguments[0] | |
var _type=arguments[1] | |
var values=null | |
if(arguments.length>2){ | |
values={} | |
for(i=2;i<arguments.length;i++){values[arguments[i]]=0} | |
} | |
for(i=pos;i>=0;i--){ | |
if(this.list[i][0]==_type){ | |
if(values==null){ | |
return i | |
}else if(this.list[i][1]in values){ | |
return i | |
} | |
} | |
} | |
return null | |
} | |
Stack.prototype.find_next_matching=function(pos){ | |
var brackets={"(":")","[":"]","{":"}"} | |
var _item=this.list[pos] | |
if(_item[0]=="bracket"){ | |
opening=_item[1] | |
count=0 | |
for(i=pos;i<this.list.length;i++){ | |
if(this.list[i][0]=="bracket"){ | |
var value=this.list[i][1] | |
if(value==opening){count +=1} | |
else if(value==brackets[opening]){ | |
count -=1 | |
if(count==0){return i} | |
} | |
} | |
} | |
} | |
return null | |
} | |
Stack.prototype.find_previous_matching=function(pos){ | |
var brackets={")":"(","]":"[","}":"{"} | |
var item=this.list[pos] | |
var i=0 | |
if(item[0]=="bracket"){ | |
closing=item[1] | |
count=0 | |
for(i=pos;i>=0;i--){ | |
if(this.list[i][0]=="bracket"){ | |
var value=this.list[i][1] | |
if(value==closing){count +=1;} | |
else if(value==brackets[closing]){ | |
count -=1 | |
if(count==0){return i} | |
} | |
} | |
} | |
} | |
return null | |
} | |
Stack.prototype.get_atoms=function(){ | |
var pos=0 | |
var nb=0 | |
var atoms=[] | |
while(pos<this.list.length){ | |
atom=this.atom_at(pos,true) | |
atoms.push(atom) | |
pos +=atom.end-atom.start | |
} | |
return atoms | |
} | |
Stack.prototype.raw_atom_at=function(pos){ | |
atom=new Atom(this) | |
atom.valid_type=true | |
atom.start=pos | |
if(pos>this.list.length-1){ | |
atom.valid_type=false | |
atom.end=pos | |
return atom | |
} | |
var dict1=$List2Dict('id','assign_id','str','int','float') | |
var $valid_kws=$List2Dict("True","False","None") | |
if(this.list[pos][0]in dict1 || | |
(this.list[pos][0]=="keyword" && this.list[pos][1]in $valid_kws)|| | |
(this.list[pos][0]=="bracket" && | |
(this.list[pos][1]=="(" || this.list[pos][1]=='['))){ | |
atom.type=this.list[pos][0] | |
end=pos | |
if(this.list[pos][0]=='bracket'){ | |
atom.type="tuple" | |
end=this.find_next_matching(pos) | |
} | |
while(end<this.list.length-1){ | |
var item=this.list[end+1] | |
if(item[0]in dict1 && atom.type=="qualified_id"){ | |
end +=1 | |
}else if(item[0]=="point"||item[0]=="qualifier"){ | |
atom.type="qualified_id" | |
end +=1 | |
}else if(item[0]=="bracket" && item[1]=='('){ | |
atom.type="function_call" | |
end=this.find_next_matching(end+1) | |
}else if(item[0]=="bracket" && item[1]=='['){ | |
atom.type="slicing" | |
end=this.find_next_matching(end+1) | |
}else{ | |
break | |
} | |
} | |
atom.end=end | |
return atom | |
}else if(this.list[pos][0]=="bracket" && | |
(this.list[pos][1]=="(" || this.list[pos][1]=='[')){ | |
atom.type="tuple" | |
atom.end=this.find_next_matching(pos) | |
return atom | |
}else{ | |
atom.type=this.list[pos][0] | |
atom.valid_type=false | |
atom.end=pos | |
return atom | |
} | |
} | |
Stack.prototype.tuple_at=function(pos){ | |
var first=this.raw_atom_at(pos) | |
var items=[first] | |
while(true){ | |
var last=items[items.length-1] | |
if(last.end+1>=this.list.length){break} | |
var delim=this.list[last.end+1] | |
if(delim[0]=='delimiter' && delim[1]==','){ | |
var next=this.raw_atom_at(last.end+2) | |
if(next !==null && next.valid_type){items.push(next)} | |
else{break} | |
}else{break} | |
} | |
return items | |
} | |
Stack.prototype.atom_at=function(pos,implicit_tuple){ | |
if(!implicit_tuple){return this.raw_atom_at(pos)} | |
else{ | |
var items=this.tuple_at(pos) | |
atom=new Atom(this) | |
if(items.length==1){return items[0]} | |
else{ | |
atom.type="tuple" | |
atom.start=items[0].start | |
atom.end=items[items.length-1].end | |
return atom | |
} | |
} | |
} | |
Stack.prototype.atom_before=function(pos,implicit_tuple){ | |
atom=new Atom(this) | |
if(pos==0){return null} | |
atom.end=pos-1 | |
atom.start=pos-1 | |
var atom_parts=$List2Dict("id","assign_id","str",'int','float',"point","qualifier") | |
var $valid_kws=$List2Dict("True","False","None") | |
var closing=$List2Dict(')',']') | |
while(true){ | |
if(atom.start==-1){break} | |
var item=this.list[atom.start] | |
if(item[0]in atom_parts){atom.start--;continue} | |
else if(item[0]=="keyword" && item[1]in $valid_kws){ | |
atom.start--;continue | |
} | |
else if(item[0]=="bracket" && item[1]in closing){ | |
atom.start=this.find_previous_matching(atom.start)-1 | |
continue | |
} | |
else if(implicit_tuple && item[0]=="delimiter" | |
&& item[1]==","){atom.start--;continue} | |
break | |
} | |
atom.start++ | |
return this.atom_at(atom.start,implicit_tuple) | |
} | |
Stack.prototype.indent=function(pos){ | |
var nl=this.find_previous(pos,"newline") | |
if(nl==null){nl=0} | |
if(nl<this.list.length-1 && this.list[nl+1][0]=="indent"){ | |
return this.list[nl+1][1] | |
}else{return 0} | |
} | |
Stack.prototype.line_end=function(pos){ | |
var nl=this.find_next(pos,"newline") | |
if(nl==null){nl=this.list.length} | |
return nl | |
} | |
Stack.prototype.line_start=function(pos){ | |
var nl=this.find_previous(pos,"newline") | |
if(nl==null){return 0} | |
return nl+1 | |
} | |
Stack.prototype.next_at_same_indent=function(pos){ | |
var indent=this.indent(pos) | |
var nxt_pos=this.find_next(pos,"newline") | |
while(true){ | |
if(nxt_pos===null){return null} | |
if(nxt_pos>=this.list.length-1){return null} | |
else if(this.list[nxt_pos+1][0]=="indent"){ | |
var nxt_indent=this.list[nxt_pos+1][1] | |
nxt_pos++ | |
}else{var nxt_indent=0} | |
if(nxt_indent==indent){return nxt_pos+1} | |
else if(nxt_indent<indent){return null} | |
nxt_pos=this.find_next(nxt_pos+1,"newline") | |
} | |
} | |
Stack.prototype.split=function(delimiter){ | |
var items=new Array(), count=0,pos=0,start=0 | |
while(pos<this.list.length){ | |
pos=this.find_next_at_same_level(pos,'delimiter',delimiter) | |
if(pos==null){pos=this.list.length;break} | |
var s=new Stack(this.list.slice(start,pos)) | |
s.start=start | |
s.end=pos-1 | |
items.push(s) | |
start=pos+1 | |
pos++ | |
} | |
var s=new Stack(this.list.slice(start,pos)) | |
s.start=start | |
s.end=pos-1 | |
if(s.end<start){s.end=start} | |
items.push(s) | |
return items | |
} | |
Stack.prototype.find_block=function(pos){ | |
var item=this.list[pos] | |
var closing_pos=this.find_next_at_same_level(pos+1,'delimiter',':') | |
if(closing_pos!=null){ | |
var kw_indent=0 | |
var line_start=this.find_previous(pos,"newline") | |
if(line_start==null){kw_indent=0} | |
else if(this.list[line_start+1][0]=="indent"){ | |
kw_indent=this.list[line_start+1][1] | |
} | |
var stop=closing_pos | |
while(true){ | |
nl=this.find_next(stop,"newline") | |
if(nl==null){stop=this.list.length-1;break} | |
if(nl<this.list.length-1){ | |
if(this.list[nl+1][0]=="indent"){ | |
if(this.list[nl+1][1]<=kw_indent){ | |
stop=nl | |
break | |
} | |
}else{ | |
stop=nl | |
break | |
} | |
}else{ | |
stop=this.list.length-1 | |
break | |
} | |
stop=nl+1 | |
} | |
return[closing_pos,stop,kw_indent] | |
}else{return null} | |
} | |
Stack.prototype.to_js=function(){ | |
var i=0,j=0,x=null | |
var js="",scope_stack=[] | |
var t2=$List2Dict('id','assign_id','str','int','float','keyword','code') | |
for(i=0;i<this.list.length;i++){ | |
x=this.list[i] | |
if(x[0]=="indent"){ | |
for(j=0;j<x[1];j++){js +=" "} | |
}else if(x[0]in t2){ | |
if(x[0]=='int'){js +='Number('+x[1]+')'} | |
else if(x[0]==='float'){js +='float('+x[1]+')'} | |
else if(x[0]==='str'){js+=x[1].replace(/\n/gm,'\\n')} | |
else{js +=x[1]} | |
if(i<this.list.length-1 && this.list[i+1][0]!="bracket" | |
&& this.list[i+1][0]!="point" && this.list[i+1][0]!="delimiter"){ | |
js +=" " | |
} | |
}else{ | |
if(x[0]=="newline"){js +='\r\n'} | |
else{js +=x[1]} | |
} | |
} | |
return js | |
} | |
Stack.prototype.dump=function(){ | |
ch='' | |
for(var i=0;i<this.list.length;i++){ | |
_item=this.list[i] | |
ch +=i+' '+_item[0]+' '+_item[1]+'\n' | |
} | |
alert(ch) | |
} | |
function $XmlHttpClass(obj){ | |
this.__class__='XMLHttpRequest' | |
this.__getattr__=function(attr){ | |
if('get_'+attr in this){return this['get_'+attr]()} | |
else{return getattr(obj,attr)} | |
} | |
this.get_text=function(){return str(obj.responseText)} | |
this.get_xml=function(){alert(obj.responseXML);return $DomElement(obj.responseXML)} | |
} | |
function $AjaxClass(){ | |
if(window.XMLHttpRequest){ | |
var $xmlhttp=new XMLHttpRequest() | |
}else{ | |
var $xmlhttp=new ActiveXObject("Microsoft.XMLHTTP") | |
} | |
$xmlhttp.$ajax=this | |
$xmlhttp.$requestTimer=null | |
$xmlhttp.onreadystatechange=function(){ | |
var state=this.readyState | |
var req=this.$ajax | |
var timer=this.$requestTimer | |
var obj=new $XmlHttpClass($xmlhttp) | |
if(state===0 && 'on_uninitialized' in req){req.on_uninitialized(obj)} | |
else if(state===1 && 'on_loading' in req){req.on_loading(obj)} | |
else if(state===2 && 'on_loaded' in req){req.on_loaded(obj)} | |
else if(state===3 && 'on_interactive' in req){req.on_interactive(obj)} | |
else if(state===4 && 'on_complete' in req){ | |
if(timer !==null){window.clearTimeout(timer)} | |
req.on_complete(obj) | |
} | |
} | |
this.__getattr__=function(attr){return getattr(this,attr)} | |
this.__setattr__=function(attr,value){setattr(this,attr,value)} | |
this.open=function(method,url,async){ | |
$xmlhttp.open(method,url,async) | |
} | |
this.set_header=function(key,value){ | |
$xmlhttp.setRequestHeader(key,value) | |
} | |
this.send=function(params){ | |
if(!params || params.$keys.length==0){$xmlhttp.send();return} | |
if(!isinstance(params,dict)){$raise('TypeError', | |
"send() argument must be dictonary, not '"+str(params.__class__)+"'")} | |
var res='' | |
for(i=0;i<params.$keys.length;i++){ | |
res +=str(params.$keys[i])+'='+str(params.$values[i])+'&' | |
} | |
res=res.substr(0,res.length-1) | |
$xmlhttp.send(res) | |
} | |
this.set_timeout=function(seconds,func){ | |
$xmlhttp.$requestTimer=setTimeout( | |
function(){$xmlhttp.abort();func()}, | |
seconds*1000) | |
} | |
} | |
function ajax(){ | |
return new $AjaxClass() | |
} | |
function $getMouseOffset(target, ev){ | |
ev=ev || window.event | |
var docPos=$getPosition(target) | |
var mousePos=$mouseCoords(ev) | |
return{x:mousePos.x - docPos.x, y:mousePos.y - docPos.y} | |
} | |
function $getPosition(e){ | |
var left=0 | |
var top=0 | |
var width=e.offsetWidth | |
var height=e.offsetHeight | |
while(e.offsetParent){ | |
left +=e.offsetLeft | |
top +=e.offsetTop | |
e=e.offsetParent | |
} | |
left +=e.offsetLeft | |
top +=e.offsetTop | |
return{left:left, top:top, width:width, height:height} | |
} | |
function $mouseCoords(ev){ | |
var posx=0 | |
var posy=0 | |
if(!ev)var ev=window.event | |
if(ev.pageX || ev.pageY){ | |
posx=ev.pageX | |
posy=ev.pageY | |
}else if(ev.clientX || ev.clientY){ | |
posx=ev.clientX + document.body.scrollLeft | |
+ document.documentElement.scrollLeft | |
posy=ev.clientY + document.body.scrollTop | |
+ document.documentElement.scrollTop | |
} | |
var res=object() | |
res.x=int(posx) | |
res.y=int(posy) | |
res.__getattr__=function(attr){return this[attr]} | |
res.__class__="MouseCoords" | |
return res | |
} | |
function $MouseEvent(ev){ | |
this.event=ev | |
this.__class__="MouseEvent" | |
} | |
$MouseEvent.prototype.__getattr__=function(attr){ | |
if(attr=="x"){return $mouseCoords(this.event).x} | |
if(attr=="y"){return $mouseCoords(this.event).y} | |
if(attr=="data"){return new $Clipboard(this.event.dataTransfer)} | |
return getattr(this.event,attr) | |
} | |
function $DomWrapper(js_dom){ | |
this.value=js_dom | |
this.__class__="$DomWrapper" | |
} | |
$DomWrapper.prototype.__getattr__=function(attr){ | |
if(attr in this.value){ | |
var obj=this.value,obj_attr=this.value[attr] | |
if(typeof this.value[attr]=='function'){ | |
return function(){ | |
var args=[] | |
for(var i=0;i<arguments.length;i++){args.push(arguments[i])} | |
var res=obj_attr.apply(obj,args) | |
if(typeof res=='object'){return new $DomWrapper(res)} | |
else if(res===undefined){return None} | |
else{return $JS2Py(res)} | |
} | |
}else{ | |
return $JS2Py(this.value[attr]) | |
} | |
}else{ | |
$raise('AttributeError','object has no attribute '+attr) | |
} | |
} | |
$DomWrapper.prototype.__setattr__=function(attr,value){ | |
if(isinstance(value,"$DomWrapper")){ | |
this.value[attr]=value.value | |
}else{ | |
this.value[attr]=value | |
} | |
} | |
function $Clipboard(data){ | |
this.data=data | |
} | |
$Clipboard.prototype.__getitem__=function(name){ | |
return $JS2Py(this.data.getData(name)) | |
} | |
$Clipboard.prototype.__setitem__=function(name,value){ | |
this.data.setData(name,value) | |
} | |
$Clipboard.prototype.__setattr__=function(attr,value){ | |
eval("this.data."+attr+"=value") | |
} | |
function $DomObject(obj){ | |
this.obj=obj | |
this.type=obj.constructor.toString() | |
} | |
$DomObject.prototype.__getattr__=function(attr){ | |
return getattr(this.obj,attr) | |
} | |
function $OptionsClass(parent){ | |
this.parent=parent | |
this.__getattr__=function(attr){ | |
if('get_'+attr in this){return eval('this.get_'+attr)} | |
if(attr in this.parent.elt.options){ | |
var obj=eval('this.parent.elt.options.'+attr) | |
if((typeof obj)=='function'){ | |
$raise('AttributeError',"'options' object has no attribute '"+attr+'"') | |
} | |
return $JS2Py(obj) | |
} | |
} | |
this.__class__='options' | |
this.__getitem__=function(arg){ | |
return $DomElement(parent.elt.options[arg]) | |
} | |
this.__delitem__=function(arg){ | |
parent.elt.options.remove(arg) | |
} | |
this.__len__=function(){return parent.elt.options.length} | |
this.__setattr__=function(attr,value){ | |
eval('parent.elt.options.'+attr+'= str(value)') | |
} | |
this.__setitem__=function(attr,value){ | |
parent.elt.options[attr]=$JS2Py(value) | |
} | |
this.get_append=function(element){ | |
parent.elt.options.add(element.elt) | |
} | |
this.get_insert=function(index,element){ | |
if(index===undefined){parent.elt.options.add(element.elt)} | |
else{parent.elt.options.add(element.elt,index)} | |
} | |
this.get_item=function(index){ | |
return $DomElement(parent.elt.options.item(index)) | |
} | |
this.get_namedItem=function(name){ | |
return $DomElement(parent.elt.options.namedItem(name)) | |
} | |
this.get_remove=function(arg){parent.elt.options.remove(arg)} | |
} | |
function $Document(){ | |
this.elt=document | |
this.mouse=null | |
this.__delitem__=function(key){ | |
if(typeof key==="string"){ | |
var res=document.getElementById(key) | |
if(res){res.parentNode.removeChild(res)} | |
else{$raise("KeyError",key)} | |
}else{ | |
try{ | |
var elts=document.getElementsByTagName(key),res=list() | |
for(var $i=0;$i<elts.length;$i++){res.append($DomElement(elts[$i]))} | |
return res | |
}catch(err){ | |
$raise("KeyError",key) | |
} | |
} | |
} | |
this.__getattr__=function(attr){return getattr(this.elt,attr)} | |
this.__getitem__=function(key){ | |
if(typeof key==="string"){ | |
var res=document.getElementById(key) | |
if(res){return $DomElement(res)} | |
else{$raise("KeyError",key)} | |
}else{ | |
try{ | |
var elts=document.getElementsByTagName(key.name),res=[] | |
for(var $i=0;$i<elts.length;$i++){res.push($DomElement(elts[$i]))} | |
return res | |
}catch(err){ | |
$raise("KeyError",str(key)) | |
} | |
} | |
} | |
this.__le__=function(other){ | |
if(isinstance(other,$AbstractTag)){ | |
var $i=0 | |
for($i=0;$i<other.children.length;$i++){ | |
document.body.appendChild(other.children[$i]) | |
} | |
}else if(isinstance(other,[str,int,float,list,dict,set,tuple])){ | |
txt=document.createTextNode(str(other)) | |
document.body.appendChild(txt) | |
}else{document.body.appendChild(other.elt)} | |
} | |
this.__setattr__=function(attr,value){ | |
if(attr in $events){document.addEventListener(attr.substr(2),value)} | |
else{document[attr]=value} | |
} | |
this.insert_before=function(other,ref_elt){ | |
document.insertBefore(other.elt,ref_elt.elt) | |
} | |
} | |
doc=new $Document() | |
win={ | |
__getattr__ : function(attr){return getattr(window,attr)}, | |
location:{__getattr__:function(attr){return getattr(window.location,attr)}} | |
} | |
function $DomElement(elt){ | |
var i=null | |
var elt_name=elt.tagName | |
if(elt_name===undefined && elt.nodeName=="#text"){ | |
return str(elt.data) | |
} | |
var obj=new $TagClass() | |
if(elt_name===undefined && elt.nodeName=="#document"){ | |
obj.__class__=$Document | |
}else if($tags.indexOf(elt_name.toUpperCase())>-1){ | |
obj.__class__=eval(elt_name.toUpperCase()) | |
}else if($svg_tags.indexOf(elt_name)>-1){ | |
obj.__class__=eval('SVG.'+elt_name) | |
} | |
obj.elt=elt | |
return obj | |
} | |
function $AbstractTagClass(){ | |
this.__class__=$AbstractTag | |
this._class_name='abstract' | |
this.children=[] | |
} | |
$AbstractTagClass.prototype.appendChild=function(child){ | |
this.children.push(child) | |
} | |
$AbstractTagClass.prototype.__add__=function(other){ | |
if(isinstance(other,$AbstractTag)){ | |
this.children=this.children.concat(other.children) | |
}else{this.children.push(other.elt)} | |
return this | |
} | |
$AbstractTagClass.prototype.__iadd__=function(other){ | |
if(isinstance(other,$AbstractTag)){ | |
this.children=this.children.concat(other.children) | |
}else{this.children.push(other.elt)} | |
} | |
$AbstractTagClass.prototype.clone=function(){ | |
var res=$AbstractTag(), $i=0 | |
for($i=0;$i<this.children.length;$i++){ | |
res.children.push(this.children[$i].cloneNode(true)) | |
} | |
return res | |
} | |
function $AbstractTag(){ | |
return new $AbstractTagClass() | |
} | |
$events=$List2Dict('onabort','onactivate','onafterprint','onafterupdate', | |
'onbeforeactivate','onbeforecopy','onbeforecut','onbeforedeactivate', | |
'onbeforeeditfocus','onbeforepaste','onbeforeprint','onbeforeunload', | |
'onbeforeupdate','onblur','onbounce','oncellchange','onchange','onclick', | |
'oncontextmenu','oncontrolselect','oncopy','oncut','ondataavailable', | |
'ondatasetchanged','ondatasetcomplete','ondblclick','ondeactivate','ondrag', | |
'ondragend','ondragenter','ondragleave','ondragover','ondragstart','ondrop', | |
'onerror','onerrorupdate','onfilterchange','onfinish','onfocus','onfocusin', | |
'onfocusout','onhashchange','onhelp','oninput','onkeydown','onkeypress', | |
'onkeyup','onload','onlosecapture','onmessage','onmousedown','onmouseenter', | |
'onmouseleave','onmousemove','onmouseout','onmouseover','onmouseup', | |
'onmousewheel','onmove','onmoveend','onmovestart','onoffline','ononline', | |
'onpaste','onpropertychange','onreadystatechange','onreset','onresize', | |
'onresizeend','onresizestart','onrowenter','onrowexit','onrowsdelete', | |
'onrowsinserted','onscroll','onsearch','onselect','onselectionchange', | |
'onselectstart','onstart','onstop','onsubmit','onunload', | |
'ontouchstart','ontouchmove','ontouchend' | |
) | |
function $TagClass(class_name,args){ | |
var $i=null | |
var $obj=this | |
if(class_name!==undefined){ | |
this.name=class_name | |
eval("this.__class__ ="+class_name) | |
this.elt=document.createElement(this.name) | |
this.elt.parent=this | |
} | |
if(args!=undefined && args.length>0){ | |
$start=0 | |
$first=args[0] | |
if(!isinstance($first,$Kw)){ | |
$start=1 | |
if(isinstance($first,[str,int,float])){ | |
txt=document.createTextNode($first.toString()) | |
this.elt.appendChild(txt) | |
}else if(isinstance($first,$AbstractTag)){ | |
for($i=0;$i<$first.children.length;$i++){ | |
this.elt.appendChild($first.children[$i]) | |
} | |
}else{ | |
try{this.elt.appendChild($first.elt)} | |
catch(err){$raise('ValueError','wrong element '+$first.elt)} | |
} | |
} | |
for($i=$start;$i<args.length;$i++){ | |
$arg=args[$i] | |
if(isinstance($arg,$Kw)){ | |
if($arg.name.toLowerCase()in $events){ | |
eval('this.elt.'+$arg.name.toLowerCase()+'=function(){'+$arg.value+'}') | |
}else if($arg.name.toLowerCase()=="style"){ | |
this.set_style($arg.value) | |
}else{ | |
if($arg.value!==false){ | |
this.elt.setAttribute($arg.name.toLowerCase(),$arg.value) | |
} | |
} | |
} | |
} | |
} | |
if('elt' in this && !this.elt.getAttribute('id')){ | |
this.elt.setAttribute('id',Math.random().toString(36).substr(2, 8)) | |
} | |
} | |
$TagClass.prototype.__add__=function(other){ | |
var res=$AbstractTag() | |
res.children=[this.elt] | |
if(isinstance(other,$AbstractTag)){ | |
for(var $i=0;$i<other.children.length;$i++){res.children.push(other.children[$i])} | |
}else if(isinstance(other,[str,int,float,list,dict,set,tuple])){ | |
res.children.push(document.createTextNode(str(other))) | |
}else{res.children.push(other.elt)} | |
return res | |
} | |
$TagClass.prototype.__eq__=function(other){ | |
if(!('getAttribute' in other.elt)){return False} | |
return this.elt.getAttribute('id')==other.elt.getAttribute('id') | |
} | |
$TagClass.prototype.__getattr__=function(attr){ | |
if('get_'+attr in this){return this['get_'+attr]()} | |
return getattr(this.elt,attr) | |
} | |
$TagClass.prototype.__getitem__=function(key){ | |
return $DomElement(this.elt.childNodes[key.value]) | |
} | |
$TagClass.prototype.__iadd__=function(other){ | |
this.__class__=$AbstractTag | |
if(!('children' in this)){this.children=[this.elt]} | |
if(isinstance(other,$AbstractTag)){ | |
for(var $i=0;$i<other.children.length;$i++){ | |
this.children.push(other.children[$i]) | |
} | |
}else{this.children.push(other.elt)} | |
} | |
$TagClass.prototype.__le__=function(other){ | |
if(isinstance(other,$AbstractTag)){ | |
var $i=0 | |
for($i=0;$i<other.children.length;$i++){ | |
this.elt.appendChild(other.children[$i]) | |
} | |
}else if(typeof other==="string" || typeof other==="number"){ | |
var $txt=document.createTextNode(other.toString()) | |
this.elt.appendChild($txt) | |
}else{ | |
this.elt.appendChild(other.elt) | |
} | |
} | |
$TagClass.prototype.__ne__=function(other){return $not(this.__eq__(other))} | |
$TagClass.prototype.__radd__=function(other){ | |
var res=$AbstractTag() | |
var txt=document.createTextNode(other) | |
res.children=[txt,this.elt] | |
return res | |
} | |
$TagClass.prototype.__setattr__=function(attr,value){ | |
if(attr in $events){this.elt.addEventListener(attr.substr(2),value)} | |
else if('set_'+attr in this){return this['set_'+attr](value)} | |
else if(attr in this.elt){this.elt[attr]=value.value} | |
else{$setattr(this,attr,value)} | |
} | |
$TagClass.prototype.__setitem__=function(key,value){ | |
this.elt.childNodes[key.value]=value | |
} | |
$TagClass.prototype.get_clone=function(){ | |
res=new $TagClass(this.name) | |
res.elt=this.elt.cloneNode(true) | |
for(var evt in $events){ | |
if(this.elt[evt]){res.elt[evt]=this.elt[evt]} | |
} | |
var func=function(){return res} | |
return func | |
} | |
$TagClass.prototype.get_getContext=function(){ | |
if(!('getContext' in this.elt)){$raise('AttributeError', | |
"object has no attribute 'getContext'")} | |
var obj=this.elt | |
return function(ctx){return new $DomWrapper(obj.getContext(ctx))} | |
} | |
$TagClass.prototype.get_parent=function(){ | |
if(this.elt.parentElement){return $DomElement(this.elt.parentElement)} | |
else{return None} | |
} | |
$TagClass.prototype.get_options=function(){ | |
return new $OptionsClass(this) | |
} | |
$TagClass.prototype.get_left=function(){ | |
return int($getPosition(this.elt)["left"]) | |
} | |
$TagClass.prototype.get_top=function(){ | |
return int($getPosition(this.elt)["top"]) | |
} | |
$TagClass.prototype.get_children=function(){ | |
var res=[] | |
for(var i=0;i<this.elt.childNodes.length;i++){ | |
res.push($DomElement(this.elt.childNodes[i])) | |
} | |
return res | |
} | |
$TagClass.prototype.get_reset=function(){ | |
var $obj=this.elt | |
return function(){$obj.reset()} | |
} | |
$TagClass.prototype.get_style=function(){ | |
return new $DomWrapper(this.elt.style) | |
} | |
$TagClass.prototype.set_style=function(style){ | |
for(var i=0;i<style.$keys.length;i++){ | |
this.elt.style[str(style.$keys[i])]=style.$values[i] | |
} | |
} | |
$TagClass.prototype.get_submit=function(){ | |
var $obj=this.elt | |
return function(){$obj.submit()} | |
} | |
$TagClass.prototype.get_text=function(){ | |
return str(this.elt.innerText || this.elt.textContent) | |
} | |
$TagClass.prototype.get_html=function(){return this.elt.innerHTML} | |
$TagClass.prototype.get_value=function(value){return this.elt.value} | |
$TagClass.prototype.make_draggable=function(target){ | |
if(target===undefined){ | |
if(this.elt.parentElement){target=new $DomElement(this.elt.parentElement)} | |
else{target=doc} | |
} | |
this.elt.draggable=true | |
this.elt.onmouseover=function(ev){this.style.cursor="move"} | |
this.elt.ondragstart=function(ev){ | |
ev.dataTransfer.setData("Text",ev.target.id) | |
document.$drag_id=ev.target.id | |
doc.mouse=$mouseCoords(ev) | |
if('ondragstart' in ev.target.$parent){ | |
ev.target.$parent['ondragstart'](ev.target.$parent) | |
} | |
} | |
if(!('$accepted' in target.elt)){target.elt.$accepted={}} | |
target.elt.$accepted[this.elt.id]=0 | |
target.elt.ondragover=function(ev){ | |
var elt_id=document.$drag_id | |
ev.preventDefault() | |
if(!(elt_id in this.$accepted)){ | |
ev.dataTransfer.dropEffect='none' | |
}else if('on_drag_over' in ev.target.$parent){ | |
var dropped=document.getElementById(elt_id) | |
doc.mouse=$mouseCoords(ev) | |
ev.target.$parent['on_drag_over'](ev.target.$parent,dropped.$parent) | |
} | |
} | |
target.elt.ondrop=function(ev){ | |
ev.preventDefault() | |
var elt_id=document.$drag_id | |
if(elt_id in this.$accepted){ | |
var dropped=document.getElementById(elt_id) | |
if(dropped !==ev.target && dropped.parentElement!==ev.target && dropped.parentElement!==ev.target.parentElement){ | |
} | |
doc.mouse=$mouseCoords(ev) | |
if('on_drop' in ev.target.$parent){ | |
ev.target.$parent['on_drop'](ev.target.$parent,dropped.$parent) | |
} | |
} | |
} | |
} | |
$TagClass.prototype.set_html=function(value){this.elt.innerHTML=str(value)} | |
$TagClass.prototype.set_text=function(value){ | |
this.elt.innerText=str(value) | |
this.elt.textContent=str(value) | |
} | |
$TagClass.prototype.set_value=function(value){this.elt.value=value.toString()} | |
function A(){return new $TagClass('A',arguments)} | |
var $src=A+'' | |
$tags=['A', 'ABBR', 'ACRONYM', 'ADDRESS', 'APPLET', | |
'B', 'BDO', 'BIG', 'BLOCKQUOTE', 'BUTTON', | |
'CAPTION', 'CENTER', 'CITE', 'CODE', | |
'DEL', 'DFN', 'DIR', 'DIV', 'DL', | |
'EM', 'FIELDSET', 'FONT', 'FORM', 'FRAMESET', | |
'H1', 'H2', 'H3', 'H4', 'H5', 'H6', | |
'I', 'IFRAME', 'INS', 'KBD', 'LABEL', 'LEGEND', | |
'MAP', 'MENU', 'NOFRAMES', 'NOSCRIPT', 'OBJECT', | |
'OL', 'OPTGROUP', 'PRE', 'Q', 'S', 'SAMP', | |
'SCRIPT', 'SELECT', 'SMALL', 'SPAN', 'STRIKE', | |
'STRONG', 'STYLE', 'SUB', 'SUP', 'TABLE', | |
'TEXTAREA', 'TITLE', 'TT', 'U', 'UL', | |
'VAR', 'BODY', 'COLGROUP', 'DD', 'DT', 'HEAD', | |
'HTML', 'LI', 'P', 'TBODY','OPTION', | |
'TD', 'TFOOT', 'TH', 'THEAD', 'TR', | |
'AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME', | |
'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', | |
'META', 'PARAM'] | |
$tags=$tags.concat(['ARTICLE','ASIDE','FIGURE','FOOTER','HEADER','NAV', | |
'SECTION','AUDIO','VIDEO','CANVAS','COMMAND','DATALIST', | |
'DETAILS','OUTPUT','PROGRESS','HGROUP','MARK','METER','TIME', | |
'RP','RT','RUBY']) | |
for($i=0;$i<$tags.length;$i++){ | |
$code=$src.replace(/A/gm,$tags[$i]) | |
eval($code) | |
} | |
SVG={ | |
__getattr__:function(attr){return this[attr]} | |
} | |
$svgNS="http://www.w3.org/2000/svg" | |
$xlinkNS="http://www.w3.org/1999/xlink" | |
function $SVGTagClass(tag_name,args){ | |
var $i=null | |
var $obj=this | |
if(tag_name!==undefined){ | |
this.name=tag_name | |
this.__class__=SVG | |
this.elt=document.createElementNS($svgNS,this.name) | |
this.elt.parent=this | |
} | |
if(args!=undefined && args.length>0){ | |
$start=0 | |
$first=args[0] | |
if(!isinstance($first,$Kw)){ | |
$start=1 | |
if(isinstance($first,str)){ | |
txt=document.createTextNode($first.value) | |
this.elt.appendChild(txt) | |
}else if(isinstance($first,int)|| isinstance($first,float)){ | |
txt=document.createTextNode($first.value.toString()) | |
this.elt.appendChild(txt) | |
}else if(isinstance($first,$AbstractTag)){ | |
for($i=0;$i<$first.children.length;$i++){ | |
this.elt.appendChild($first.children[$i]) | |
} | |
}else{ | |
try{this.elt.appendChild($first.elt)} | |
catch(err){$raise('ValueError','wrong element '+$first.elt)} | |
} | |
} | |
for($i=$start;$i<args.length;$i++){ | |
$arg=args[$i] | |
if(isinstance($arg,$Kw)){ | |
if($arg.name.toLowerCase()in $events){ | |
eval('this.elt.'+$arg.name.toLowerCase()+'=function(){'+$arg.value.value+'}') | |
}else if($arg.name.toLowerCase()=="style"){ | |
this.set_style($arg.value) | |
}else{ | |
if($arg.value.value!==false){ | |
this.elt.setAttributeNS(null,$arg.name.replace('_','-'),$arg.value.value) | |
} | |
} | |
} | |
} | |
} | |
if('elt' in this && !this.elt.getAttribute('id')){ | |
this.elt.setAttribute('id',Math.random().toString(36).substr(2, 8)) | |
} | |
} | |
$SVGTagClass.prototype.__add__=$TagClass.prototype.__add__ | |
$SVGTagClass.prototype.__eq__=$TagClass.prototype.__eq__ | |
$SVGTagClass.prototype.__getattr__=$TagClass.prototype.__getattr__ | |
$SVGTagClass.prototype.__getitem__=$TagClass.prototype.__getitem__ | |
$SVGTagClass.prototype.__iadd__=$TagClass.prototype.__iadd__ | |
$SVGTagClass.prototype.__le__=$TagClass.prototype.__le__ | |
$SVGTagClass.prototype.__ne__=$TagClass.prototype.__ne__ | |
$SVGTagClass.prototype.__radd__=$TagClass.prototype.__radd__ | |
$SVGTagClass.prototype.__setattr__=function(key,value){ | |
if(key=="href"){ | |
this.elt.setAttributeNS($xlinkNS,key.replace('_','-'),value.value) | |
}else{ | |
this.elt.setAttributeNS(null,key.replace('_','-'),value.value) | |
} | |
} | |
$SVGTagClass.prototype.__setitem__=$TagClass.prototype.__setitem__ | |
var $svg_tags=['a', | |
'altGlyph', | |
'altGlyphDef', | |
'altGlyphItem', | |
'animate', | |
'animateColor', | |
'animateMotion', | |
'animateTransform', | |
'circle', | |
'clipPath', | |
'color_profile', | |
'cursor', | |
'defs', | |
'desc', | |
'ellipse', | |
'feBlend', | |
'g', | |
'image', | |
'line', | |
'linearGradient', | |
'marker', | |
'mask', | |
'path', | |
'pattern', | |
'polygon', | |
'polyline', | |
'radialGradient', | |
'rect', | |
'stop', | |
'svg', | |
'text', | |
'tref', | |
'tspan', | |
'use'] | |
$svg=function(){return new $SVGTagClass('X',arguments)} | |
$svg +='' | |
for(var i=0;i<$svg_tags.length;i++){ | |
var tag=$svg_tags[i] | |
eval('SVG.'+tag+'='+$svg.replace('X',tag)) | |
} | |
function $LocalStorageClass(){ | |
this.__class__='localStorage' | |
this.supported=typeof(Storage)!=="undefined" | |
this.__delitem__=function(key){ | |
if(this.supported){localStorage.removeItem(key)} | |
else{$raise('NameError',"local storage is not supported by this browser")} | |
} | |
this.__getitem__=function(key){ | |
if(this.supported){ | |
res=localStorage[key] | |
if(res===undefined){return None} | |
else{return $JS2Py(res)} | |
} | |
else{$raise('NameError',"local storage is not supported by this browser")} | |
} | |
this.__setitem__=function(key,value){ | |
if(this.supported){localStorage[key]=value} | |
else{$raise('NameError',"local storage is not supported by this browser")} | |
} | |
} | |
local_storage=new $LocalStorageClass() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment